diff options
Diffstat (limited to 'sc/source')
-rw-r--r-- | sc/source/ui/attrdlg/scdlgfact.cxx | 5 | ||||
-rw-r--r-- | sc/source/ui/attrdlg/scdlgfact.hxx | 3 | ||||
-rw-r--r-- | sc/source/ui/dbgui/asciiopt.cxx | 31 | ||||
-rw-r--r-- | sc/source/ui/dbgui/csvtablebox.cxx | 36 | ||||
-rw-r--r-- | sc/source/ui/dbgui/scuiasciiopt.cxx | 338 | ||||
-rw-r--r-- | sc/source/ui/docshell/docsh.cxx | 2 | ||||
-rw-r--r-- | sc/source/ui/inc/asciiopt.hxx | 2 | ||||
-rw-r--r-- | sc/source/ui/inc/csvtablebox.hxx | 2 | ||||
-rw-r--r-- | sc/source/ui/inc/scuiasciiopt.hxx | 14 | ||||
-rw-r--r-- | sc/source/ui/unoobj/filtuno.cxx | 12 | ||||
-rw-r--r-- | sc/source/ui/view/cellsh2.cxx | 1 |
11 files changed, 237 insertions, 209 deletions
diff --git a/sc/source/ui/attrdlg/scdlgfact.cxx b/sc/source/ui/attrdlg/scdlgfact.cxx index 47e81dc7c09f..af95b1e025fa 100644 --- a/sc/source/ui/attrdlg/scdlgfact.cxx +++ b/sc/source/ui/attrdlg/scdlgfact.cxx @@ -1073,10 +1073,9 @@ bool AbstractScSelEntryDlg_Impl::StartExecuteAsync(VclAbstractDialog::AsyncConte // =========================Factories for createdialog =================== VclPtr<AbstractScImportAsciiDlg> ScAbstractDialogFactory_Impl::CreateScImportAsciiDlg(weld::Window* pParent, const OUString& aDatName, - SvStream* pInStream, ScImportAsciiCall eCall, - ScAsciiOptions* aOptions) + SvStream* pInStream, ScImportAsciiCall eCall) { - return VclPtr<AbstractScImportAsciiDlg_Impl>::Create(std::make_shared<ScImportAsciiDlg>(pParent, aDatName,pInStream, eCall, aOptions)); + return VclPtr<AbstractScImportAsciiDlg_Impl>::Create(std::make_shared<ScImportAsciiDlg>(pParent, aDatName,pInStream, eCall)); } VclPtr<AbstractScTextImportOptionsDlg> ScAbstractDialogFactory_Impl::CreateScTextImportOptionsDlg(weld::Window* pParent) diff --git a/sc/source/ui/attrdlg/scdlgfact.hxx b/sc/source/ui/attrdlg/scdlgfact.hxx index 0f8077240a73..d7dab5e4c4b8 100644 --- a/sc/source/ui/attrdlg/scdlgfact.hxx +++ b/sc/source/ui/attrdlg/scdlgfact.hxx @@ -666,8 +666,7 @@ public: virtual VclPtr<AbstractScImportAsciiDlg> CreateScImportAsciiDlg(weld::Window* pParent, const OUString& aDatName, SvStream* pInStream, - ScImportAsciiCall eCall, - ScAsciiOptions* aOptions = nullptr) override; + ScImportAsciiCall eCall) override; virtual VclPtr<AbstractScTextImportOptionsDlg> CreateScTextImportOptionsDlg(weld::Window* pParent) override; diff --git a/sc/source/ui/dbgui/asciiopt.cxx b/sc/source/ui/dbgui/asciiopt.cxx index c9a4d881baed..4c470793f9ac 100644 --- a/sc/source/ui/dbgui/asciiopt.cxx +++ b/sc/source/ui/dbgui/asciiopt.cxx @@ -22,9 +22,11 @@ #include <comphelper/string.hxx> #include <osl/thread.h> #include <o3tl/string_view.hxx> +#include <sfx2/objsh.hxx> constexpr std::u16string_view pStrFix = u"FIX"; constexpr std::u16string_view pStrMrg = u"MRG"; +constexpr std::u16string_view pStrDet = u"DETECT"; ScAsciiOptions::ScAsciiOptions() : bFixedLen ( false ), @@ -86,9 +88,10 @@ static OUString lcl_decodeSepString( std::u16string_view rSepNums, bool & o_bMer // The options string must not contain semicolons (because of the pick list), // use comma as separator. -void ScAsciiOptions::ReadFromString( std::u16string_view rString ) +void ScAsciiOptions::ReadFromString( std::u16string_view rString, SvStream* pStream4Detect ) { sal_Int32 nPos = rString.empty() ? -1 : 0; + bool bDetectSep = false; // Token 0: Field separator. if ( nPos >= 0 ) @@ -96,9 +99,14 @@ void ScAsciiOptions::ReadFromString( std::u16string_view rString ) bFixedLen = bMergeFieldSeps = false; const std::u16string_view aToken = o3tl::getToken(rString, 0, ',', nPos); - if ( aToken == pStrFix ) - bFixedLen = true; - aFieldSeps = lcl_decodeSepString( aToken, bMergeFieldSeps); + if ( aToken == pStrDet) + bDetectSep = true; + else + { + if ( aToken == pStrFix ) + bFixedLen = true; + aFieldSeps = lcl_decodeSepString( aToken, bMergeFieldSeps); + } } // Token 1: Text separator. @@ -111,9 +119,22 @@ void ScAsciiOptions::ReadFromString( std::u16string_view rString ) // Token 2: Text encoding. if ( nPos >= 0 ) { - eCharSet = ScGlobal::GetCharsetValue( o3tl::getToken(rString, 0, ',', nPos) ); + const std::u16string_view aToken = o3tl::getToken(rString, 0, ',', nPos); + SvStreamEndian endian; + bool bDetectCharSet = aToken == pStrDet; + if ( bDetectCharSet && pStream4Detect ) + { + SfxObjectShell::DetectCharSet(*pStream4Detect, eCharSet, endian); + if (eCharSet == RTL_TEXTENCODING_UNICODE) + pStream4Detect->SetEndian(endian); + } + else if (!bDetectCharSet) + eCharSet = ScGlobal::GetCharsetValue( aToken ); } + if (bDetectSep && pStream4Detect) + SfxObjectShell::DetectCsvSeparators(*pStream4Detect, eCharSet, aFieldSeps, cTextSep); + // Token 3: Number of start row. if ( nPos >= 0 ) { diff --git a/sc/source/ui/dbgui/csvtablebox.cxx b/sc/source/ui/dbgui/csvtablebox.cxx index 2a3a16c0c550..ab8231013009 100644 --- a/sc/source/ui/dbgui/csvtablebox.cxx +++ b/sc/source/ui/dbgui/csvtablebox.cxx @@ -57,6 +57,26 @@ ScCsvTableBox::~ScCsvTableBox() // common table box handling -------------------------------------------------- +void ScCsvTableBox::Refresh() +{ + mxGrid->DisableRepaint(); + mxGrid->Execute( CSVCMD_SETLINEOFFSET, 0 ); + if (mbFixedMode) + { + mxGrid->Execute( CSVCMD_SETPOSCOUNT, mnFixedWidth ); + mxGrid->SetSplits( mxRuler->GetSplits() ); + mxGrid->SetColumnStates( std::vector(maFixColStates) ); + } + else + { + mxGrid->Execute( CSVCMD_SETPOSCOUNT, 1 ); + mxGrid->Execute( CSVCMD_NEWCELLTEXTS ); + mxGrid->SetColumnStates( std::vector(maSepColStates) ); + } + InitControls(); + mxGrid->EnableRepaint(); +} + void ScCsvTableBox::SetSeparatorsMode() { if( !mbFixedMode ) @@ -68,13 +88,7 @@ void ScCsvTableBox::SetSeparatorsMode() // switch to separators mode mbFixedMode = false; // reset and reinitialize controls - mxGrid->DisableRepaint(); - mxGrid->Execute( CSVCMD_SETLINEOFFSET, 0 ); - mxGrid->Execute( CSVCMD_SETPOSCOUNT, 1 ); - mxGrid->Execute( CSVCMD_NEWCELLTEXTS ); - mxGrid->SetColumnStates( std::vector(maSepColStates) ); - InitControls(); - mxGrid->EnableRepaint(); + Refresh(); } void ScCsvTableBox::SetFixedWidthMode() @@ -87,13 +101,7 @@ void ScCsvTableBox::SetFixedWidthMode() // switch to fixed width mode mbFixedMode = true; // reset and reinitialize controls - mxGrid->DisableRepaint(); - mxGrid->Execute( CSVCMD_SETLINEOFFSET, 0 ); - mxGrid->Execute( CSVCMD_SETPOSCOUNT, mnFixedWidth ); - mxGrid->SetSplits( mxRuler->GetSplits() ); - mxGrid->SetColumnStates( std::vector(maFixColStates) ); - InitControls(); - mxGrid->EnableRepaint(); + Refresh(); } void ScCsvTableBox::Init() diff --git a/sc/source/ui/dbgui/scuiasciiopt.cxx b/sc/source/ui/dbgui/scuiasciiopt.cxx index 304424806aa5..2789d33096c8 100644 --- a/sc/source/ui/dbgui/scuiasciiopt.cxx +++ b/sc/source/ui/dbgui/scuiasciiopt.cxx @@ -41,6 +41,8 @@ #include <o3tl/string_view.hxx> #include <unicode/ucsdet.h> +#include <sfx2/objsh.hxx> +#include <svx/txenctab.hxx> //! TODO make dynamic const SCSIZE ASCIIDLG_MAXROWS = MAXROWCOUNT; @@ -67,6 +69,7 @@ enum CSVImportOptionsIndex CSVIO_FixedWidth, CSVIO_RemoveSpace, CSVIO_EvaluateFormulas, + CSVIO_SeparatorType, // Settings for *all* dialog invocations above. // Settings not for SC_TEXTTOCOLUMNS below. CSVIO_FromRow, @@ -80,6 +83,13 @@ enum CSVImportOptionsIndex CSVIO_PasteSkipEmptyCells }; +enum SeparatorType +{ + FIXED, + SEPARATOR, + DETECT_SEPARATOR +}; + } // Config items for all three paths are defined in @@ -93,6 +103,7 @@ const ::std::vector<OUString> CSVImportOptionNames = u"FixedWidth"_ustr, u"RemoveSpace"_ustr, u"EvaluateFormulas"_ustr, + u"SeparatorType"_ustr, u"FromRow"_ustr, u"CharSet"_ustr, u"QuotedFieldAsText"_ustr, @@ -176,16 +187,16 @@ static void lcl_CreatePropertiesNames ( OUString& rSepPath, Sequence<OUString>& { case SC_IMPORTFILE: rSepPath = aSep_Path; - nProperties = 12; + nProperties = 13; break; case SC_PASTETEXT: rSepPath = aSep_Path_Clpbrd; - nProperties = 13; + nProperties = 14; break; case SC_TEXTTOCOLUMNS: default: rSepPath = aSep_Path_Text2Col; - nProperties = 7; + nProperties = 8; break; } rNames.realloc( nProperties ); @@ -196,6 +207,7 @@ static void lcl_CreatePropertiesNames ( OUString& rSepPath, Sequence<OUString>& pNames[ CSVIO_FixedWidth ] = CSVImportOptionNames[ CSVIO_FixedWidth ]; pNames[ CSVIO_RemoveSpace ] = CSVImportOptionNames[ CSVIO_RemoveSpace ]; pNames[ CSVIO_EvaluateFormulas ] = CSVImportOptionNames[ CSVIO_EvaluateFormulas ]; + pNames[ CSVIO_SeparatorType ] = CSVImportOptionNames[ CSVIO_SeparatorType ]; if (eCall != SC_TEXTTOCOLUMNS) { pNames[ CSVIO_FromRow ] = CSVImportOptionNames[ CSVIO_FromRow ]; @@ -215,9 +227,9 @@ static void lcl_CreatePropertiesNames ( OUString& rSepPath, Sequence<OUString>& static void lcl_LoadSeparators( OUString& rFieldSeparators, OUString& rTextSeparators, bool& rMergeDelimiters, bool& rQuotedAsText, bool& rDetectSpecialNum, bool& rDetectScientificNum, - bool& rFixedWidth, sal_Int32& rFromRow, sal_Int32& rCharSet, + SeparatorType& rSepType, sal_Int32& rFromRow, sal_Int32& rCharSet, sal_Int32& rLanguage, bool& rSkipEmptyCells, bool& rRemoveSpace, - bool& rEvaluateFormulas, ScImportAsciiCall eCall ) + bool& rEvaluateFormulas, ScImportAsciiCall eCall, bool& rBeforeDetection ) { Sequence<Any>aValues; const Any *pProperties; @@ -240,8 +252,14 @@ static void lcl_LoadSeparators( OUString& rFieldSeparators, OUString& rTextSepar if( pProperties[ CSVIO_TextSeparators ].hasValue() ) pProperties[ CSVIO_TextSeparators ] >>= rTextSeparators; - if( pProperties[ CSVIO_FixedWidth ].hasValue() ) - rFixedWidth = ScUnoHelpFunctions::GetBoolFromAny( pProperties[ CSVIO_FixedWidth ] ); + rBeforeDetection = true; + if( pProperties[ CSVIO_SeparatorType ].hasValue() ) + { + rBeforeDetection = false; + rSepType = static_cast<SeparatorType>(ScUnoHelpFunctions::GetInt16FromAny( pProperties[ CSVIO_SeparatorType ] )); + } + else if( pProperties[ CSVIO_FixedWidth ].hasValue() ) + rSepType = (ScUnoHelpFunctions::GetBoolFromAny( pProperties[ CSVIO_FixedWidth ] ) ? SeparatorType::FIXED : SeparatorType::DETECT_SEPARATOR); if( pProperties[ CSVIO_EvaluateFormulas ].hasValue() ) rEvaluateFormulas = ScUnoHelpFunctions::GetBoolFromAny( pProperties[ CSVIO_EvaluateFormulas ] ); @@ -277,7 +295,7 @@ static void lcl_LoadSeparators( OUString& rFieldSeparators, OUString& rTextSepar static void lcl_SaveSeparators( const OUString& sFieldSeparators, const OUString& sTextSeparators, bool bMergeDelimiters, bool bQuotedAsText, - bool bDetectSpecialNum, bool bDetectScientificNum, bool bFixedWidth, sal_Int32 nFromRow, + bool bDetectSpecialNum, bool bDetectScientificNum, SeparatorType rSepType, sal_Int32 nFromRow, sal_Int32 nCharSet, sal_Int32 nLanguage, bool bSkipEmptyCells, bool bRemoveSpace, bool bEvaluateFormulas, ScImportAsciiCall eCall ) { @@ -294,8 +312,8 @@ static void lcl_SaveSeparators( pProperties[ CSVIO_RemoveSpace ] <<= bRemoveSpace; pProperties[ CSVIO_Separators ] <<= sFieldSeparators; pProperties[ CSVIO_TextSeparators ] <<= sTextSeparators; - pProperties[ CSVIO_FixedWidth ] <<= bFixedWidth; pProperties[ CSVIO_EvaluateFormulas ] <<= bEvaluateFormulas; + pProperties[ CSVIO_SeparatorType ] <<= static_cast<sal_Int16>(rSepType); if (eCall != SC_TEXTTOCOLUMNS) { pProperties[ CSVIO_FromRow ] <<= nFromRow; @@ -316,21 +334,24 @@ static void lcl_SaveSeparators( } ScImportAsciiDlg::ScImportAsciiDlg(weld::Window* pParent, std::u16string_view aDatName, - SvStream* pInStream, ScImportAsciiCall eCall, - const ScAsciiOptions* aOptions) + SvStream* pInStream, ScImportAsciiCall eCall) : GenericDialogController(pParent, u"modules/scalc/ui/textimportcsv.ui"_ustr, u"TextImportCsvDialog"_ustr) , mpDatStream(pInStream) , mnStreamPos(pInStream ? pInStream->Tell() : 0) + , mnStreamInitPos(mnStreamPos) , mnRowPosCount(0) , mcTextSep(ScAsciiOptions::cDefaultTextSep) + , meDetectedCharSet(RTL_TEXTENCODING_DONTKNOW) + , mbCharSetDetect(true) , meCall(eCall) - , mbDetectSep(eCall != SC_TEXTTOCOLUMNS) , mxFtCharSet(m_xBuilder->weld_label(u"textcharset"_ustr)) , mxLbCharSet(new SvxTextEncodingBox(m_xBuilder->weld_combo_box(u"charset"_ustr))) + , mxFtDetectedCharSet(m_xBuilder->weld_label(u"textdetectedcharset"_ustr)) , mxFtCustomLang(m_xBuilder->weld_label(u"textlanguage"_ustr)) , mxLbCustomLang(new SvxLanguageBox(m_xBuilder->weld_combo_box(u"language"_ustr))) , mxFtRow(m_xBuilder->weld_label(u"textfromrow"_ustr)) , mxNfRow(m_xBuilder->weld_spin_button(u"fromrow"_ustr)) + , mxRbDetectSep(m_xBuilder->weld_radio_button(u"todetectseparator"_ustr)) , mxRbFixed(m_xBuilder->weld_radio_button(u"tofixedwidth"_ustr)) , mxRbSeparated(m_xBuilder->weld_radio_button(u"toseparatedby"_ustr)) , mxCkbTab(m_xBuilder->weld_check_button(u"tab"_ustr)) @@ -376,40 +397,23 @@ ScImportAsciiDlg::ScImportAsciiDlg(weld::Window* pParent, std::u16string_view aD OUString sFieldSeparators(u",;\t"_ustr); OUString sTextSeparators(mcTextSep); bool bMergeDelimiters = false; - bool bFixedWidth = false; + SeparatorType eSepType = DETECT_SEPARATOR; bool bQuotedFieldAsText = false; bool bDetectSpecialNum = true; bool bDetectScientificNum = true; bool bEvaluateFormulas = (meCall != SC_IMPORTFILE); bool bSkipEmptyCells = true; bool bRemoveSpace = false; + bool bBeforeDetection = false; sal_Int32 nFromRow = 1; sal_Int32 nCharSet = -1; sal_Int32 nLanguage = 0; - if (aOptions) - { - if (!aOptions->GetFieldSeps().isEmpty()) - sFieldSeparators = aOptions->GetFieldSeps(); - if (aOptions->GetTextSep()) - sTextSeparators = OUStringChar(aOptions->GetTextSep()); - bMergeDelimiters = aOptions->IsMergeSeps(); - bFixedWidth = aOptions->IsFixedLen(); - bQuotedFieldAsText = aOptions->IsQuotedAsText(); - bDetectSpecialNum = aOptions->IsDetectSpecialNumber(); - bDetectScientificNum = aOptions->IsDetectScientificNumber(); - bEvaluateFormulas = aOptions->IsEvaluateFormulas(); - bSkipEmptyCells = aOptions->IsSkipEmptyCells(); - bRemoveSpace = aOptions->IsRemoveSpace(); - nFromRow = aOptions->GetStartRow(); - nCharSet = aOptions->GetCharSet(); - nLanguage = static_cast<sal_uInt16>(aOptions->GetLanguage()); - } - else - lcl_LoadSeparators (sFieldSeparators, sTextSeparators, bMergeDelimiters, - bQuotedFieldAsText, bDetectSpecialNum, bDetectScientificNum, bFixedWidth, nFromRow, - nCharSet, nLanguage, bSkipEmptyCells, bRemoveSpace, bEvaluateFormulas, meCall); - // load from saved settings + lcl_LoadSeparators (sFieldSeparators, sTextSeparators, bMergeDelimiters, + bQuotedFieldAsText, bDetectSpecialNum, bDetectScientificNum, eSepType, nFromRow, + nCharSet, nLanguage, bSkipEmptyCells, bRemoveSpace, bEvaluateFormulas, meCall, + bBeforeDetection); + maFieldSeparators = sFieldSeparators; if( bMergeDelimiters && !bIsTSV ) @@ -430,95 +434,48 @@ ScImportAsciiDlg::ScImportAsciiDlg(weld::Window* pParent, std::u16string_view aD mxCkbEvaluateFormulas->set_active(true); if (bSkipEmptyCells) mxCkbSkipEmptyCells->set_active(true); - if (bFixedWidth && !bIsTSV) - mxRbFixed->set_active(true); - if (nFromRow != 1) - mxNfRow->set_value(nFromRow); - - // Clipboard is always Unicode, else detect. - rtl_TextEncoding ePreselectUnicode = (aOptions ? aOptions->GetCharSet() : (meCall == SC_IMPORTFILE ? - RTL_TEXTENCODING_DONTKNOW : RTL_TEXTENCODING_UNICODE)); - // Sniff for Unicode / not - if( ePreselectUnicode == RTL_TEXTENCODING_DONTKNOW && mpDatStream ) + if (eSepType == SeparatorType::FIXED) { - mpDatStream->Seek( 0 ); - constexpr size_t buffsize = 4096; - sal_Int8 bytes[buffsize] = { 0 }; - sal_Int32 nRead = mpDatStream->ReadBytes( bytes, buffsize ); - mpDatStream->Seek( 0 ); - - if ( nRead > 0 ) + if (bIsTSV) { - UErrorCode uerr = U_ZERO_ERROR; - UCharsetDetector* ucd = ucsdet_open( &uerr ); - ucsdet_setText( ucd, reinterpret_cast<const char*>(bytes), nRead, &uerr ); - - if ( const UCharsetMatch* match = ucsdet_detect(ucd, &uerr) ) - { - const char* pEncodingName = ucsdet_getName( match, &uerr ); - - if ( U_SUCCESS(uerr) && !strcmp("UTF-8", pEncodingName) ) - { - ePreselectUnicode = RTL_TEXTENCODING_UTF8; // UTF-8 - mpDatStream->StartReadingUnicodeText( RTL_TEXTENCODING_UTF8 ); - } - else if ( U_SUCCESS(uerr) && !strcmp("UTF-16LE", pEncodingName) ) - { - ePreselectUnicode = RTL_TEXTENCODING_UNICODE; // UTF-16LE - mpDatStream->SetEndian( SvStreamEndian::LITTLE ); - mpDatStream->StartReadingUnicodeText( RTL_TEXTENCODING_UNICODE ); - } - else if ( U_SUCCESS(uerr) && !strcmp("UTF-16BE", pEncodingName) ) - { - ePreselectUnicode = RTL_TEXTENCODING_UNICODE; // UTF-16BE - mpDatStream->SetEndian( SvStreamEndian::BIG ); - mpDatStream->StartReadingUnicodeText( RTL_TEXTENCODING_UNICODE ); - } - else // other - mpDatStream->StartReadingUnicodeText( RTL_TEXTENCODING_DONTKNOW ); - } - - ucsdet_close( ucd ); + eSepType = SeparatorType::SEPARATOR; + mxRbSeparated->set_active(true); } + else + mxRbFixed->set_active(true); + } + else if (eSepType == SeparatorType::SEPARATOR) + mxRbSeparated->set_active(true); + else + mxRbDetectSep->set_active(true); + if (nFromRow != 1) + mxNfRow->set_value(nFromRow); - mnStreamPos = mpDatStream->Tell(); + // Clipboard is always Unicode, else rely on default/config. + rtl_TextEncoding ePreselectUnicode = (meCall == SC_IMPORTFILE ? + RTL_TEXTENCODING_DONTKNOW : RTL_TEXTENCODING_UNICODE); + + // Detect character set only once and then use it for "Detect" option. + SvStreamEndian eEndian; + SfxObjectShell::DetectCharSet(*mpDatStream, meDetectedCharSet, eEndian); + if (meDetectedCharSet == RTL_TEXTENCODING_UNICODE) + mpDatStream->SetEndian(eEndian); + else if ( meDetectedCharSet == RTL_TEXTENCODING_DONTKNOW ) + { + meDetectedCharSet = osl_getThreadTextEncoding(); + // Prefer UTF-8, as UTF-16 would have already been detected from the stream. + // This gives a better chance that the file is going to be opened correctly. + if ( meDetectedCharSet == RTL_TEXTENCODING_UNICODE && mpDatStream ) + meDetectedCharSet = RTL_TEXTENCODING_UTF8; } - if (aOptions && !maFieldSeparators.isEmpty()) - SetSeparators(0); - else if (bIsTSV) + if (bIsTSV) SetSeparators('\t'); else - { - // Some MS-Excel convention is the first line containing the field - // separator as "sep=|" (without quotes and any field separator - // character). The second possibility seems to be it is present *with* - // quotes so it shows up as cell content *including* the separator and - // can be preserved during round trips. Check for an exact match of - // any such and set separator. - /* TODO: it is debatable whether the unquoted form should rather be - * treated special to actually include the separator in the field data. - * Currently it does not. */ - sal_Unicode cSep = 0; - OUString aLine; - // Try to read one more character, if more than 7 it can't be an exact - // match of any. - mpDatStream->ReadUniOrByteStringLine( aLine, mpDatStream->GetStreamCharSet(), 8); - mpDatStream->Seek(mnStreamPos); - if (aLine.getLength() == 8) - ; // nothing - else if (aLine.getLength() == 5 && aLine.startsWithIgnoreAsciiCase("sep=")) - cSep = aLine[4]; - else if (aLine.getLength() == 7 && aLine[6] == '"' && aLine.startsWithIgnoreAsciiCase("\"sep=")) - cSep = aLine[5]; - - // Set Separators in the dialog from maFieldSeparators (empty are not - // set) or an optionally defined by file content field separator. - SetSeparators(cSep); - } + SetSeparators(0); // Get Separators from the dialog (empty are set from default) - maFieldSeparators = GetSeparators(); + maFieldSeparators = GetActiveSeparators(); mxNfRow->connect_value_changed( LINK( this, ScImportAsciiDlg, FirstRowHdl ) ); @@ -551,22 +508,15 @@ ScImportAsciiDlg::ScImportAsciiDlg(weld::Window* pParent, std::u16string_view aD // Insert one "SYSTEM" entry for compatibility in AsciiOptions and system // independent document linkage. mxLbCharSet->InsertTextEncoding( RTL_TEXTENCODING_DONTKNOW, ScResId( SCSTR_CHARSET_USER ) ); - if ( ePreselectUnicode == RTL_TEXTENCODING_DONTKNOW ) - { - rtl_TextEncoding eSystemEncoding = osl_getThreadTextEncoding(); - // Prefer UTF-8, as UTF-16 would have already been detected from the stream. - // This gives a better chance that the file is going to be opened correctly. - if ( ( eSystemEncoding == RTL_TEXTENCODING_UNICODE ) && mpDatStream ) - eSystemEncoding = RTL_TEXTENCODING_UTF8; - mxLbCharSet->SelectTextEncoding( eSystemEncoding ); - } - else - { - mxLbCharSet->SelectTextEncoding( ePreselectUnicode ); - } + // Insert one for detecting charset. + mxLbCharSet->InsertTextEncoding( RTL_TEXTENCODING_USER_DETECTED, "- " + ScResId( SCSTR_AUTOMATIC ) + " -" ); - if (nCharSet >= 0 && ePreselectUnicode == RTL_TEXTENCODING_DONTKNOW) + if (ePreselectUnicode != RTL_TEXTENCODING_DONTKNOW) + mxLbCharSet->SelectTextEncoding( ePreselectUnicode ); + else if (nCharSet >= 0 && !bBeforeDetection) mxLbCharSet->set_active(nCharSet); + else + mxLbCharSet->SelectTextEncoding(RTL_TEXTENCODING_USER_DETECTED); SetSelectedCharSet(); mxLbCharSet->connect_changed( LINK( this, ScImportAsciiDlg, CharSetHdl ) ); @@ -592,10 +542,10 @@ ScImportAsciiDlg::ScImportAsciiDlg(weld::Window* pParent, std::u16string_view aD mxTableBox->InitTypes( *mxLbType ); mxTableBox->SetColTypeHdl( LINK( this, ScImportAsciiDlg, ColTypeHdl ) ); + mxRbDetectSep->connect_toggled( LINK( this, ScImportAsciiDlg, RbSepFixHdl ) ); mxRbSeparated->connect_toggled( LINK( this, ScImportAsciiDlg, RbSepFixHdl ) ); mxRbFixed->connect_toggled( LINK( this, ScImportAsciiDlg, RbSepFixHdl ) ); - SetupSeparatorCtrls(); RbSepFix(); UpdateVertical(); @@ -715,9 +665,9 @@ void ScImportAsciiDlg::GetOptions( ScAsciiOptions& rOpt ) rOpt.SetFixedLen( mxRbFixed->get_active() ); rOpt.SetStartRow( mxNfRow->get_value() ); mxTableBox->FillColumnData( rOpt ); - if( mxRbSeparated->get_active() ) + if( mxRbSeparated->get_active() || mxRbDetectSep->get_active()) { - rOpt.SetFieldSeps( GetSeparators() ); + rOpt.SetFieldSeps( GetActiveSeparators() ); rOpt.SetMergeSeps( mxCkbAsOnce->get_active() ); rOpt.SetRemoveSpace( mxCkbRemoveSpace->get_active() ); rOpt.SetTextSep( lcl_CharFromCombo( *mxCbTextSep, SCSTR_TEXTSEP ) ); @@ -732,9 +682,9 @@ void ScImportAsciiDlg::GetOptions( ScAsciiOptions& rOpt ) void ScImportAsciiDlg::SaveParameters() { - lcl_SaveSeparators( maFieldSeparators, mxCbTextSep->get_active_text(), mxCkbAsOnce->get_active(), + lcl_SaveSeparators( GetSeparators(), mxCbTextSep->get_active_text(), mxCkbAsOnce->get_active(), mxCkbQuotedAsText->get_active(), mxCkbDetectNumber->get_active(), mxCkbDetectScientificNumber->get_active(), - mxRbFixed->get_active(), + mxRbFixed->get_active() ? FIXED : (mxRbDetectSep->get_active() ? DETECT_SEPARATOR : SEPARATOR), mxNfRow->get_value(), mxLbCharSet->get_active(), static_cast<sal_uInt16>(mxLbCustomLang->get_active_id()), @@ -788,10 +738,27 @@ void ScImportAsciiDlg::SetSeparators( sal_Unicode cSep ) void ScImportAsciiDlg::SetSelectedCharSet() { + rtl_TextEncoding eOldCharSet = meCharSet; meCharSet = mxLbCharSet->GetSelectTextEncoding(); + mbCharSetDetect = (meCharSet == RTL_TEXTENCODING_USER_DETECTED); mbCharSetSystem = (meCharSet == RTL_TEXTENCODING_DONTKNOW); - if( mbCharSetSystem ) + if (mbCharSetDetect) + { + meCharSet = meDetectedCharSet; + mxFtDetectedCharSet->set_label(SvxTextEncodingTable::GetTextString(meCharSet)); + } + else if( mbCharSetSystem ) + { meCharSet = osl_getThreadTextEncoding(); + mxFtDetectedCharSet->set_label(SvxTextEncodingTable::GetTextString(meCharSet)); + } + else + mxFtDetectedCharSet->set_label(SvxTextEncodingTable::GetTextString(meCharSet)); + + if (eOldCharSet != meCharSet) + DetectCsvSeparators(); + + RbSepFix(); } OUString ScImportAsciiDlg::GetSeparators() const @@ -810,6 +777,17 @@ OUString ScImportAsciiDlg::GetSeparators() const return aSepChars; } +OUString ScImportAsciiDlg::GetActiveSeparators() const +{ + if (mxRbSeparated->get_active()) + return GetSeparators(); + + if (mxRbDetectSep->get_active()) + return maDetectedFieldSeps; + + return OUString(); +} + void ScImportAsciiDlg::SetupSeparatorCtrls() { bool bEnable = mxRbSeparated->get_active(); @@ -817,12 +795,41 @@ void ScImportAsciiDlg::SetupSeparatorCtrls() mxCkbSemicolon->set_sensitive( bEnable ); mxCkbComma->set_sensitive( bEnable ); mxCkbSpace->set_sensitive( bEnable ); - mxCkbRemoveSpace->set_sensitive( bEnable ); mxCkbOther->set_sensitive( bEnable ); mxEdOther->set_sensitive( bEnable ); + + bEnable = bEnable || mxRbDetectSep->get_active(); + mxCkbRemoveSpace->set_sensitive( bEnable ); mxCkbAsOnce->set_sensitive( bEnable ); mxFtTextSep->set_sensitive( bEnable ); mxCbTextSep->set_sensitive( bEnable ); + + OUString aSepName; + if (maDetectedFieldSeps.isEmpty()) + aSepName += ScResId(SCSTR_NONE); + else + { + for (int idx = 0; idx < maDetectedFieldSeps.getLength(); idx ++) + { + if (idx > 0) + aSepName += u" "; + + if (maDetectedFieldSeps[idx] == u' ') + aSepName += ScResId(SCSTR_FIELDSEP_SPACE); + else if (maDetectedFieldSeps[idx] == u'\t') + aSepName += ScResId(SCSTR_FIELDSEP_TAB); + else + aSepName += OUStringChar(maDetectedFieldSeps[idx]); + } + } + mxRbDetectSep->set_label(ScResId(SCSTR_DETECTED).replaceFirst( "%1", aSepName)); +} + +void ScImportAsciiDlg::DetectCsvSeparators() +{ + mpDatStream->Seek(mnStreamInitPos); + SfxObjectShell::DetectCsvSeparators(*mpDatStream, meCharSet, maDetectedFieldSeps, mcTextSep); + mpDatStream->Seek(mnStreamPos); } void ScImportAsciiDlg::UpdateVertical() @@ -835,10 +842,17 @@ void ScImportAsciiDlg::UpdateVertical() void ScImportAsciiDlg::RbSepFix() { weld::WaitObject aWaitObj(m_xDialog.get()); - if( mxRbFixed->get_active() ) - mxTableBox->SetFixedWidthMode(); + if (mxRbSeparated->get_active() || mxRbDetectSep->get_active()) + { + maFieldSeparators = GetActiveSeparators(); + if (mxTableBox->IsFixedWidthMode()) + mxTableBox->SetSeparatorsMode(); + else + mxTableBox->Refresh(); + } else - mxTableBox->SetSeparatorsMode(); + mxTableBox->SetFixedWidthMode(); + SetupSeparatorCtrls(); } @@ -892,13 +906,26 @@ void ScImportAsciiDlg::SeparatorHdl(const weld::Widget* pCtrl) mxCkbOther->set_active(!mxEdOther->get_text().isEmpty()); OUString aOldFldSeps( maFieldSeparators); - maFieldSeparators = GetSeparators(); sal_Unicode cOldSep = mcTextSep; mcTextSep = lcl_CharFromCombo( *mxCbTextSep, SCSTR_TEXTSEP ); // Any separator changed may result in completely different lines due to // embedded line breaks. - if (cOldSep != mcTextSep || aOldFldSeps != maFieldSeparators) - UpdateVertical(); + if (cOldSep != mcTextSep) + { + DetectCsvSeparators(); + + SetupSeparatorCtrls(); + + maFieldSeparators = GetActiveSeparators(); + if (aOldFldSeps != maFieldSeparators) + { + UpdateVertical(); + mxTableBox->Refresh(); + return; + } + } + else + maFieldSeparators = GetActiveSeparators(); mxTableBox->GetGrid().Execute( CSVCMD_NEWCELLTEXTS ); } @@ -931,14 +958,7 @@ IMPL_LINK(ScImportAsciiDlg, LbColTypeHdl, weld::ComboBox&, rListBox, void) IMPL_LINK_NOARG(ScImportAsciiDlg, UpdateTextHdl, ScCsvTableBox&, void) { - // Checking the separator can only be done once for the very first time - // when the dialog wasn't already presented to the user. - // As a side effect this has the benefit that the check is only done on the - // first set of visible lines. - mbDetectSep = (mbDetectSep && !mxRbFixed->get_active() - && (!mxCkbTab->get_active() || !mxCkbSemicolon->get_active() - || !mxCkbComma->get_active() || !mxCkbSpace->get_active())); - sal_Unicode cDetectSep = (mbDetectSep ? 0 : 0xffff); + sal_Unicode cDetectSep = 0xffff; sal_Int32 nBaseLine = mxTableBox->GetGrid().GetFirstVisLine(); sal_Int32 nRead = mxTableBox->GetGrid().GetVisLineCount(); @@ -958,24 +978,6 @@ IMPL_LINK_NOARG(ScImportAsciiDlg, UpdateTextHdl, ScCsvTableBox&, void) for (; i < CSV_PREVIEW_LINES; i++) maPreviewLine[i].clear(); - if (mbDetectSep) - { - mbDetectSep = false; - if (cDetectSep) - { - // Expect separator to be appended by now so all subsequent - // GetLine()/ReadCsvLine() actually used it. - assert(maFieldSeparators.endsWith(OUStringChar(cDetectSep))); - // Preselect separator in UI. - switch (cDetectSep) - { - case '\t': mxCkbTab->set_active(true); break; - case ';': mxCkbSemicolon->set_active(true); break; - case ',': mxCkbComma->set_active(true); break; - case ' ': mxCkbSpace->set_active(true); break; - } - } - } mxTableBox->GetGrid().Execute( CSVCMD_SETLINECOUNT, mnRowPosCount); bool bMergeSep = mxCkbAsOnce->get_active(); diff --git a/sc/source/ui/docshell/docsh.cxx b/sc/source/ui/docshell/docsh.cxx index 4b8e5f041c8d..7ef50cc7a8d3 100644 --- a/sc/source/ui/docshell/docsh.cxx +++ b/sc/source/ui/docshell/docsh.cxx @@ -1354,7 +1354,7 @@ bool ScDocShell::ConvertFrom( SfxMedium& rMedium ) if ( const SfxStringItem* pOptionsItem = rMedium.GetItemSet().GetItemIfSet( SID_FILE_FILTEROPTIONS ) ) { - aOptions.ReadFromString( pOptionsItem->GetValue() ); + aOptions.ReadFromString( pOptionsItem->GetValue(), rMedium.GetInStream() ); bOptInit = true; } diff --git a/sc/source/ui/inc/asciiopt.hxx b/sc/source/ui/inc/asciiopt.hxx index 6028b8825d94..af97d4b0f2ba 100644 --- a/sc/source/ui/inc/asciiopt.hxx +++ b/sc/source/ui/inc/asciiopt.hxx @@ -52,7 +52,7 @@ public: static const sal_Unicode cDefaultTextSep = '"'; - void ReadFromString( std::u16string_view rString ); + void ReadFromString( std::u16string_view rString, SvStream* pStream4Detect = nullptr ); OUString WriteToString() const; rtl_TextEncoding GetCharSet() const { return eCharSet; } diff --git a/sc/source/ui/inc/csvtablebox.hxx b/sc/source/ui/inc/csvtablebox.hxx index e2392a478f4c..9d626493fd54 100644 --- a/sc/source/ui/inc/csvtablebox.hxx +++ b/sc/source/ui/inc/csvtablebox.hxx @@ -72,10 +72,12 @@ public: // common table box handling ---------------------------------------------- public: + void Refresh(); /** Sets the control to separators mode. */ void SetSeparatorsMode(); /** Sets the control to fixed width mode. */ void SetFixedWidthMode(); + bool IsFixedWidthMode(){ return mbFixedMode; } ScCsvRuler& GetRuler() { return *mxRuler; } ScCsvGrid& GetGrid() { return *mxGrid; } diff --git a/sc/source/ui/inc/scuiasciiopt.hxx b/sc/source/ui/inc/scuiasciiopt.hxx index ee8ca78b221d..5b19b8c4d3ee 100644 --- a/sc/source/ui/inc/scuiasciiopt.hxx +++ b/sc/source/ui/inc/scuiasciiopt.hxx @@ -31,29 +31,34 @@ class SvxTextEncodingBox; class ScImportAsciiDlg : public weld::GenericDialogController { - SvStream* mpDatStream; + SvStream* mpDatStream; sal_uLong mnStreamPos; + sal_uLong mnStreamInitPos; std::unique_ptr<sal_uLong[]> mpRowPosArray; sal_uLong mnRowPosCount; OUString maPreviewLine[ CSV_PREVIEW_LINES ]; OUString maFieldSeparators; // selected field separators + OUString maDetectedFieldSeps; // detected field seps sal_Unicode mcTextSep; rtl_TextEncoding meCharSet; /// Selected char set. + rtl_TextEncoding meDetectedCharSet; /// This is computed only once at initialization, so store it. bool mbCharSetSystem; /// Is System char set selected? + bool mbCharSetDetect; /// Should we autodetect character set ? ScImportAsciiCall meCall; /// How the dialog is called (see asciiopt.hxx) - bool mbDetectSep; /// Whether to detect a possible separator. std::unique_ptr<weld::Label> mxFtCharSet; std::unique_ptr<SvxTextEncodingBox> mxLbCharSet; + std::unique_ptr<weld::Label> mxFtDetectedCharSet; std::unique_ptr<weld::Label> mxFtCustomLang; std::unique_ptr<SvxLanguageBox> mxLbCustomLang; std::unique_ptr<weld::Label> mxFtRow; std::unique_ptr<weld::SpinButton> mxNfRow; + std::unique_ptr<weld::RadioButton> mxRbDetectSep; std::unique_ptr<weld::RadioButton> mxRbFixed; std::unique_ptr<weld::RadioButton> mxRbSeparated; @@ -83,8 +88,7 @@ class ScImportAsciiDlg : public weld::GenericDialogController public: ScImportAsciiDlg( weld::Window* pParent, std::u16string_view aDatName, - SvStream* pInStream, ScImportAsciiCall eCall, - const ScAsciiOptions* aOptions = nullptr ); + SvStream* pInStream, ScImportAsciiCall eCall); virtual ~ScImportAsciiDlg() override; void GetOptions( ScAsciiOptions& rOpt ); @@ -98,6 +102,8 @@ private: void SetSeparators( sal_Unicode cSep ); /** Returns all separator characters in a string. */ OUString GetSeparators() const; + OUString GetActiveSeparators() const; + void DetectCsvSeparators(); /** Enables or disables all separator checkboxes and edit fields. */ void SetupSeparatorCtrls(); diff --git a/sc/source/ui/unoobj/filtuno.cxx b/sc/source/ui/unoobj/filtuno.cxx index e5ee8de17d29..575d66147b64 100644 --- a/sc/source/ui/unoobj/filtuno.cxx +++ b/sc/source/ui/unoobj/filtuno.cxx @@ -179,25 +179,15 @@ sal_Int16 SAL_CALL ScFilterOptionsObj::execute() { // ascii import is special... - ScAsciiOptions aInOptions, *pInOptions = nullptr; INetURLObject aURL( aFileName ); // tdf#132421 - don't URL encode filename for the import ASCII dialog title OUString aPrivDatName(aURL.GetLastName(INetURLObject::DecodeMechanism::Unambiguous)); std::unique_ptr<SvStream> pInStream; if ( xInputStream.is() ) - { pInStream = utl::UcbStreamHelper::CreateStream( xInputStream ); - if (aFilterOptions.isEmpty()) - aFilterOptions = "DETECT,34,DETECT,,,,,,,,,,,,"; - SfxObjectShell::DetectCsvFilterOptions(*pInStream, aFilterOptions); - - aInOptions.ReadFromString(aFilterOptions); - pInOptions = &aInOptions; - } - ScopedVclPtr<AbstractScImportAsciiDlg> pDlg(pFact->CreateScImportAsciiDlg(Application::GetFrameWeld(xDialogParent), aPrivDatName, - pInStream.get(), SC_IMPORTFILE, pInOptions)); + pInStream.get(), SC_IMPORTFILE)); if ( pDlg->Execute() == RET_OK ) { ScAsciiOptions aOptions; diff --git a/sc/source/ui/view/cellsh2.cxx b/sc/source/ui/view/cellsh2.cxx index 0323ca8c219f..bb7c4cf831b3 100644 --- a/sc/source/ui/view/cellsh2.cxx +++ b/sc/source/ui/view/cellsh2.cxx @@ -1040,6 +1040,7 @@ void ScCellShell::ExecuteDB( SfxRequest& rReq ) ScImportExport::SetNoEndianSwap( aStream ); aExport.ExportStream( aStream, OUString(), SotClipboardFormatId::STRING ); + aStream.Seek(0); ScAbstractDialogFactory* pFact = ScAbstractDialogFactory::Create(); ScopedVclPtr<AbstractScImportAsciiDlg> pDlg(pFact->CreateScImportAsciiDlg( pTabViewShell->GetFrameWeld(), OUString(), &aStream, SC_TEXTTOCOLUMNS)); |