20#undef SC_DLLIMPLEMENTATION
31#include <osl/thread.h>
35#include <com/sun/star/uno/Any.hxx>
36#include <com/sun/star/uno/Sequence.hxx>
38#include <osl/diagnose.h>
43#include <unicode/ucsdet.h>
62enum CSVImportOptionsIndex
64 CSVIO_MergeDelimiters = 0,
69 CSVIO_EvaluateFormulas,
73 CSVIO_Text2ColSkipEmptyCells = CSVIO_FromRow,
76 CSVIO_DetectSpecialNum,
77 CSVIO_DetectScientificNum,
80 CSVIO_PasteSkipEmptyCells
99 "DetectSpecialNumbers",
100 "DetectScientificNumbers",
104constexpr OUStringLiteral
aSep_Path =
u"Office.Calc/Dialogs/CSVImport";
111 return eCall ==
SC_TEXTTOCOLUMNS ? CSVIO_Text2ColSkipEmptyCells : CSVIO_PasteSkipEmptyCells;
134 aStr = OUString(cSelect);
144 if ( !
aStr.isEmpty() && !rList.empty() )
152 sal_Int32 nTmpIdx {nIdx};
162 if( (
aStr.getLength() == 1) || (cFirst <
'0') || (cFirst >
'9') )
192 OUString* pNames = rNames.getArray();
210 const sal_Int32 nSkipEmptyCells = getSkipEmptyCellsIndex(eCall);
211 assert( nSkipEmptyCells < rNames.getLength());
217 bool& rMergeDelimiters,
bool& rQuotedAsText,
bool& rDetectSpecialNum,
bool& rDetectScientificNum,
218 bool& rFixedWidth, sal_Int32& rFromRow, sal_Int32& rCharSet,
219 sal_Int32& rLanguage,
bool& rSkipEmptyCells,
bool& rRemoveSpace,
223 const Any *pProperties;
229 pProperties = aValues.getConstArray();
231 if( pProperties[ CSVIO_MergeDelimiters ].hasValue() )
234 if( pProperties[ CSVIO_RemoveSpace ].hasValue() )
237 if( pProperties[ CSVIO_Separators ].hasValue() )
238 pProperties[ CSVIO_Separators ] >>= rFieldSeparators;
240 if( pProperties[ CSVIO_TextSeparators ].hasValue() )
241 pProperties[ CSVIO_TextSeparators ] >>= rTextSeparators;
243 if( pProperties[ CSVIO_FixedWidth ].hasValue() )
246 if( pProperties[ CSVIO_EvaluateFormulas ].hasValue() )
251 if( pProperties[ CSVIO_FromRow ].hasValue() )
252 pProperties[ CSVIO_FromRow ] >>= rFromRow;
254 if( pProperties[ CSVIO_CharSet ].hasValue() )
255 pProperties[ CSVIO_CharSet ] >>= rCharSet;
257 if ( pProperties[ CSVIO_QuotedAsText ].hasValue() )
258 pProperties[ CSVIO_QuotedAsText ] >>= rQuotedAsText;
260 if ( pProperties[ CSVIO_DetectSpecialNum ].hasValue() )
261 pProperties[ CSVIO_DetectSpecialNum ] >>= rDetectSpecialNum;
263 if ( pProperties[ CSVIO_DetectScientificNum ].hasValue() )
264 pProperties[ CSVIO_DetectScientificNum ] >>= rDetectScientificNum;
266 if ( pProperties[ CSVIO_Language ].hasValue() )
267 pProperties[ CSVIO_Language ] >>= rLanguage;
271 const sal_Int32 nSkipEmptyCells = getSkipEmptyCellsIndex(eCall);
272 assert( nSkipEmptyCells < aValues.getLength());
273 if ( pProperties[nSkipEmptyCells].hasValue() )
279 const OUString& sFieldSeparators,
const OUString& sTextSeparators,
bool bMergeDelimiters,
bool bQuotedAsText,
280 bool bDetectSpecialNum,
bool bDetectScientificNum,
bool bFixedWidth, sal_Int32 nFromRow,
281 sal_Int32 nCharSet, sal_Int32 nLanguage,
bool bSkipEmptyCells,
bool bRemoveSpace,
bool bEvaluateFormulas,
291 pProperties = aValues.getArray();
293 pProperties[ CSVIO_MergeDelimiters ] <<= bMergeDelimiters;
294 pProperties[ CSVIO_RemoveSpace ] <<= bRemoveSpace;
295 pProperties[ CSVIO_Separators ] <<= sFieldSeparators;
296 pProperties[ CSVIO_TextSeparators ] <<= sTextSeparators;
297 pProperties[ CSVIO_FixedWidth ] <<= bFixedWidth;
298 pProperties[ CSVIO_EvaluateFormulas ] <<= bEvaluateFormulas;
301 pProperties[ CSVIO_FromRow ] <<= nFromRow;
302 pProperties[ CSVIO_CharSet ] <<= nCharSet;
303 pProperties[ CSVIO_QuotedAsText ] <<= bQuotedAsText;
304 pProperties[ CSVIO_DetectSpecialNum ] <<= bDetectSpecialNum;
305 pProperties[ CSVIO_DetectScientificNum ] <<= bDetectScientificNum;
306 pProperties[ CSVIO_Language ] <<= nLanguage;
310 const sal_Int32 nSkipEmptyCells = getSkipEmptyCellsIndex(eCall);
311 assert( nSkipEmptyCells < aValues.getLength());
312 pProperties[ nSkipEmptyCells ] <<= bSkipEmptyCells;
320 : GenericDialogController(pParent,
"modules/scalc/ui/textimportcsv.ui",
"TextImportCsvDialog")
321 , mpDatStream(pInStream)
322 , mnStreamPos(pInStream ? pInStream->Tell() : 0)
327 , mxFtCharSet(m_xBuilder->weld_label(
"textcharset"))
329 , mxFtCustomLang(m_xBuilder->weld_label(
"textlanguage"))
330 , mxLbCustomLang(new
SvxLanguageBox(m_xBuilder->weld_combo_box(
"language")))
331 , mxFtRow(m_xBuilder->weld_label(
"textfromrow"))
332 , mxNfRow(m_xBuilder->weld_spin_button(
"fromrow"))
333 , mxRbFixed(m_xBuilder->weld_radio_button(
"tofixedwidth"))
334 , mxRbSeparated(m_xBuilder->weld_radio_button(
"toseparatedby"))
335 , mxCkbTab(m_xBuilder->weld_check_button(
"tab"))
336 , mxCkbSemicolon(m_xBuilder->weld_check_button(
"semicolon"))
337 , mxCkbComma(m_xBuilder->weld_check_button(
"comma"))
338 , mxCkbRemoveSpace(m_xBuilder->weld_check_button(
"removespace"))
339 , mxCkbSpace(m_xBuilder->weld_check_button(
"space"))
340 , mxCkbOther(m_xBuilder->weld_check_button(
"other"))
341 , mxEdOther(m_xBuilder->weld_entry(
"inputother"))
342 , mxCkbAsOnce(m_xBuilder->weld_check_button(
"mergedelimiters"))
343 , mxFtTextSep(m_xBuilder->weld_label(
"texttextdelimiter"))
344 , mxCbTextSep(m_xBuilder->weld_combo_box(
"textdelimiter"))
345 , mxCkbQuotedAsText(m_xBuilder->weld_check_button(
"quotedfieldastext"))
346 , mxCkbDetectNumber(m_xBuilder->weld_check_button(
"detectspecialnumbers"))
347 , mxCkbDetectScientificNumber(m_xBuilder->weld_check_button(
"detectscientificnumbers"))
348 , mxCkbEvaluateFormulas(m_xBuilder->weld_check_button(
"evaluateformulas"))
349 , mxCkbSkipEmptyCells(m_xBuilder->weld_check_button(
"skipemptycells"))
350 , mxLbType(m_xBuilder->weld_combo_box(
"columntype"))
351 , mxAltTitle(m_xBuilder->weld_label(
"textalttitle"))
363 aName += OUString::Concat(
" - [") + aDatName +
"]";
375 OUString sFieldSeparators(
",;\t");
377 bool bMergeDelimiters =
false;
378 bool bFixedWidth =
false;
379 bool bQuotedFieldAsText =
false;
380 bool bDetectSpecialNum =
true;
381 bool bDetectScientificNum =
true;
383 bool bSkipEmptyCells =
true;
384 bool bRemoveSpace =
false;
385 sal_Int32 nFromRow = 1;
386 sal_Int32 nCharSet = -1;
387 sal_Int32 nLanguage = 0;
389 bQuotedFieldAsText, bDetectSpecialNum, bDetectScientificNum, bFixedWidth, nFromRow,
390 nCharSet, nLanguage, bSkipEmptyCells, bRemoveSpace, bEvaluateFormulas,
meCall);
394 if( bMergeDelimiters && !bIsTSV )
396 if (bQuotedFieldAsText)
400 if (bDetectSpecialNum)
403 bDetectScientificNum =
true;
406 if (bDetectScientificNum)
408 if (bEvaluateFormulas)
412 if (bFixedWidth && !bIsTSV)
419 RTL_TEXTENCODING_DONTKNOW : RTL_TEXTENCODING_UNICODE);
421 if( ePreselectUnicode == RTL_TEXTENCODING_DONTKNOW &&
mpDatStream )
424 constexpr size_t buffsize = 4096;
431 UErrorCode uerr = U_ZERO_ERROR;
432 UCharsetDetector* ucd = ucsdet_open( &uerr );
433 ucsdet_setText( ucd,
reinterpret_cast<const char*
>(
bytes), nRead, &uerr );
435 if (
const UCharsetMatch*
match = ucsdet_detect(ucd, &uerr) )
437 const char* pEncodingName = ucsdet_getName(
match, &uerr );
439 if ( U_SUCCESS(uerr) && !strcmp(
"UTF-8", pEncodingName) )
441 ePreselectUnicode = RTL_TEXTENCODING_UTF8;
444 else if ( U_SUCCESS(uerr) && !strcmp(
"UTF-16LE", pEncodingName) )
446 ePreselectUnicode = RTL_TEXTENCODING_UNICODE;
450 else if ( U_SUCCESS(uerr) && !strcmp(
"UTF-16BE", pEncodingName) )
452 ePreselectUnicode = RTL_TEXTENCODING_UNICODE;
485 if (aLine.getLength() == 8)
487 else if (aLine.getLength() == 5 && aLine.startsWithIgnoreAsciiCase(
"sep="))
489 else if (aLine.getLength() == 7 && aLine[6] ==
'"' && aLine.startsWithIgnoreAsciiCase(
"\"sep="))
511 mxCkbTab->connect_toggled( aSeparatorClickHdl );
513 mxCkbComma->connect_toggled( aSeparatorClickHdl );
514 mxCkbAsOnce->connect_toggled( aSeparatorClickHdl );
515 mxCkbSpace->connect_toggled( aSeparatorClickHdl );
517 mxCkbOther->connect_toggled( aSeparatorClickHdl );
530 mxLbCharSet->InsertTextEncoding( RTL_TEXTENCODING_DONTKNOW,
ScResId( SCSTR_CHARSET_USER ) );
531 if ( ePreselectUnicode == RTL_TEXTENCODING_DONTKNOW )
533 rtl_TextEncoding eSystemEncoding = osl_getThreadTextEncoding();
536 if ( ( eSystemEncoding == RTL_TEXTENCODING_UNICODE ) &&
mpDatStream )
537 eSystemEncoding = RTL_TEXTENCODING_UTF8;
538 mxLbCharSet->SelectTextEncoding( eSystemEncoding );
542 mxLbCharSet->SelectTextEncoding( ePreselectUnicode );
545 if (nCharSet >= 0 && ePreselectUnicode == RTL_TEXTENCODING_DONTKNOW)
552 SvxLanguageListFlags::ALL | SvxLanguageListFlags::ONLY_KNOWN,
false,
false);
557 OUString aColumnUser(
ScResId( SCSTR_COLUMN_USER ) );
558 for (sal_Int32 nIdx {0}; nIdx>=0; )
560 mxLbType->append_text(aColumnUser.getToken(0,
';', nIdx));
725 constexpr sal_Unicode aSeps[] = {
'\t',
';',
',',
' ' };
728 const bool bSet = (c == cSep);
731 case '\t':
mxCkbTab->set_active(bSet);
break;
733 case ',':
mxCkbComma->set_active(bSet);
break;
734 case ' ':
mxCkbSpace->set_active(bSet);
break;
751 case '\t':
mxCkbTab->set_active(
true);
break;
753 case ',':
mxCkbComma->set_active(
true);
break;
754 case ' ':
mxCkbSpace->set_active(
true);
break;
821 if (!rButton.get_active())
828 SeparatorHdl(&rCtrl);
833 SeparatorHdl(&rCtrl);
838 SeparatorHdl(&rEdit);
843 if (&rCtrl == mxCkbDetectNumber.get())
845 if (mxCkbDetectNumber->get_active())
847 mxCkbDetectScientificNumber->set_active(
true);
848 mxCkbDetectScientificNumber->set_sensitive(
false);
851 mxCkbDetectScientificNumber->set_sensitive(
true);
858 OSL_ENSURE( pCtrl,
"ScImportAsciiDlg::SeparatorHdl - missing sender" );
859 OSL_ENSURE( !
mxRbFixed->get_active(),
"ScImportAsciiDlg::SeparatorHdl - not allowed in fixed width" );
882 if (mxLbCharSet->get_active() != -1)
885 rtl_TextEncoding eOldCharSet = meCharSet;
886 SetSelectedCharSet();
888 if (eOldCharSet != meCharSet)
902 if (&rListBox == mxLbType.get())
912 mbDetectSep = (mbDetectSep && !mxRbFixed->get_active()
913 && (!mxCkbTab->get_active() || !mxCkbSemicolon->get_active()
914 || !mxCkbComma->get_active() || !mxCkbSpace->get_active()));
915 sal_Unicode cDetectSep = (mbDetectSep ? 0 : 0xffff);
917 sal_Int32 nBaseLine = mxTableBox->GetGrid().GetFirstVisLine();
918 sal_Int32 nRead = mxTableBox->GetGrid().GetVisLineCount();
927 for (
i = 0;
i < nRead;
i++)
929 if (!GetLine( nBaseLine +
i, maPreviewLine[
i], cDetectSep))
933 maPreviewLine[
i].clear();
942 assert(maFieldSeparators.endsWith(OUStringChar(cDetectSep)));
946 case '\t': mxCkbTab->set_active(
true);
break;
947 case ';': mxCkbSemicolon->set_active(
true);
break;
948 case ',': mxCkbComma->set_active(
true);
break;
949 case ' ': mxCkbSpace->set_active(
true);
break;
955 bool bMergeSep = mxCkbAsOnce->get_active();
956 bool bRemoveSpace = mxCkbRemoveSpace->get_active();
957 mxTableBox->SetUniStrings( maPreviewLine, maFieldSeparators, mcTextSep, bMergeSep, bRemoveSpace );
962 sal_Int32
nType = rTableBox.GetSelColumnType();
963 sal_Int32 nTypeCount = mxLbType->get_count();
965 bool bEnable = ((0 <=
nType) && (
nType < nTypeCount)) || bEmpty;
967 mxLbType->set_sensitive( bEnable );
970 mxLbType->set_active(-1);
972 mxLbType->set_active(
nType);
size_t SCSIZE
size_t typedef to be able to find places where code was changed from USHORT to size_t and is used to ...
ScImportAsciiCall
How ScImportAsciiDlg is called.
Reference< XExecutableDialog > m_xDialog
void SetFieldSeps(const OUString &rStr)
void SetRemoveSpace(bool bSet)
void SetCharSet(rtl_TextEncoding eNew)
void SetLanguage(LanguageType e)
void SetFixedLen(bool bSet)
void SetTextSep(sal_Unicode c)
void SetQuotedAsText(bool bSet)
void SetDetectScientificNumber(bool bSet)
void SetMergeSeps(bool bSet)
void SetStartRow(sal_Int32 nRow)
void SetSkipEmptyCells(bool bSet)
void SetCharSetSystem(bool bSet)
void SetEvaluateFormulas(bool bSet)
void SetDetectSpecialNumber(bool bSet)
The control in the CSV import dialog that contains a ruler and a data grid to visualize and modify th...
static SC_DLLPUBLIC ::utl::TransliterationWrapper & GetTransliteration()
std::unique_ptr< weld::SpinButton > mxNfRow
std::unique_ptr< weld::CheckButton > mxCkbComma
std::unique_ptr< weld::CheckButton > mxCkbSkipEmptyCells
void SetupSeparatorCtrls()
Enables or disables all separator checkboxes and edit fields.
std::unique_ptr< weld::ComboBox > mxLbType
std::unique_ptr< weld::CheckButton > mxCkbDetectNumber
std::unique_ptr< weld::Label > mxFtRow
std::unique_ptr< weld::CheckButton > mxCkbQuotedAsText
OUString maFieldSeparators
std::unique_ptr< weld::RadioButton > mxRbFixed
void SetSelectedCharSet()
Sets the selected char set data to meCharSet and mbCharSetSystem.
bool GetLine(sal_uLong nLine, OUString &rText, sal_Unicode &rcDetectSep)
std::unique_ptr< weld::CheckButton > mxCkbDetectScientificNumber
OUString GetSeparators() const
Returns all separator characters in a string.
std::unique_ptr< weld::CheckButton > mxCkbSemicolon
std::unique_ptr< sal_uLong[]> mpRowPosArray
ScImportAsciiDlg(weld::Window *pParent, std::u16string_view aDatName, SvStream *pInStream, ScImportAsciiCall eCall)
std::unique_ptr< weld::CheckButton > mxCkbOther
void GetOptions(ScAsciiOptions &rOpt)
void SetSeparators(sal_Unicode cSep)
Set separators in ui from maFieldSeparators or an optionally defined separator.
std::unique_ptr< weld::Entry > mxEdOther
std::unique_ptr< weld::CheckButton > mxCkbAsOnce
std::unique_ptr< weld::CheckButton > mxCkbRemoveSpace
std::unique_ptr< weld::Label > mxFtTextSep
bool mbCharSetSystem
Selected char set.
ScImportAsciiCall meCall
Is System char set selected?
std::unique_ptr< weld::Label > mxFtCharSet
Whether to detect a possible separator.
std::unique_ptr< weld::CheckButton > mxCkbEvaluateFormulas
bool Seek(sal_uLong nPos)
std::unique_ptr< weld::Label > mxFtCustomLang
void SeparatorHdl(const weld::Widget *)
std::unique_ptr< weld::CheckButton > mxCkbSpace
std::unique_ptr< ScCsvTableBox > mxTableBox
std::unique_ptr< weld::ComboBox > mxCbTextSep
std::unique_ptr< weld::Label > mxAltTitle
std::unique_ptr< SvxTextEncodingBox > mxLbCharSet
rtl_TextEncoding meCharSet
std::unique_ptr< weld::RadioButton > mxRbSeparated
std::unique_ptr< weld::CheckButton > mxCkbTab
std::unique_ptr< SvxLanguageBox > mxLbCustomLang
virtual ~ScImportAsciiDlg() override
static void EmbeddedNullTreatment(OUString &rStr)
void PutProperties(const css::uno::Sequence< OUString > &rNames, const css::uno::Sequence< css::uno::Any > &rValues)
css::uno::Sequence< css::uno::Any > GetProperties(const css::uno::Sequence< OUString > &rNames)
static bool GetBoolFromAny(const css::uno::Any &aAny)
virtual void ResetError()
void StartReadingUnicodeText(rtl_TextEncoding eReadBomCharSet)
void SetEndian(SvStreamEndian SvStreamEndian)
bool ReadUniOrByteStringLine(OUString &rStr, rtl_TextEncoding eSrcCharSet, sal_Int32 nMaxCodepointsToRead=0xFFFE)
sal_uInt64 Seek(sal_uInt64 nPos)
void SetStreamCharSet(rtl_TextEncoding eCharSet)
std::size_t ReadBytes(void *pData, std::size_t nSize)
rtl_TextEncoding GetStreamCharSet() const
virtual OUString get_active_text() const=0
virtual void set_entry_text(const OUString &rStr)=0
void append_text(const OUString &rStr)
std::shared_ptr< weld::Dialog > m_xDialog
const sal_Int32 CSV_PREVIEW_LINES
TODO make string array dynamic.
const sal_Int32 CSV_TYPE_MULTI
Multi selection with different types.
@ CSVCMD_SETCOLUMNTYPE
Update cell texts with current split settings. [-].
@ CSVCMD_SETLINECOUNT
Change character pixel width. [width in pixel].
@ CSVCMD_SETFIRSTIMPORTLINE
Send selected column type to external controls. [-].
@ CSVCMD_NEWCELLTEXTS
Move to make passed position visible (for mouse tracking). [position].
#define ERRCODE_IO_CANTSEEK
OUString ReadCsvLine(SvStream &rStream, bool bEmbeddedLineBreak, OUString &rFieldSeparators, sal_Unicode cFieldQuote, sal_Unicode &rcDetectSep, sal_uInt32 nMaxSourceLines)
Read a CSV (comma separated values) data line using ReadUniOrByteStringLine().
#define LINK(Instance, Class, Member)
bool match(const sal_Unicode *pWild, const sal_Unicode *pStr, const sal_Unicode cEscape)
bool endsWithIgnoreAsciiCase(std::u16string_view s1, std::u16string_view s2, std::u16string_view *rest=nullptr)
sal_Int32 toInt32(std::u16string_view str, sal_Int16 radix=10)
std::basic_string_view< charT, traits > getToken(std::basic_string_view< charT, traits > sv, charT delimiter, std::size_t &position)
std::vector< sal_uInt8 > bytes
OUString ScResId(TranslateId aId)
const SCSIZE ASCIIDLG_MAXROWS
TODO make dynamic.
static void lcl_SaveSeparators(const OUString &sFieldSeparators, const OUString &sTextSeparators, bool bMergeDelimiters, bool bQuotedAsText, bool bDetectSpecialNum, bool bDetectScientificNum, bool bFixedWidth, sal_Int32 nFromRow, sal_Int32 nCharSet, sal_Int32 nLanguage, bool bSkipEmptyCells, bool bRemoveSpace, bool bEvaluateFormulas, ScImportAsciiCall eCall)
IMPL_STATIC_LINK_NOARG(ScImportAsciiDlg, InstallLOKNotifierHdl, void *, vcl::ILibreOfficeKitNotifier *)
static sal_Unicode lcl_CharFromCombo(const weld::ComboBox &rCombo, std::u16string_view rList)
IMPL_LINK_NOARG(ScImportAsciiDlg, CharSetHdl, weld::ComboBox &, void)
constexpr OUStringLiteral aSep_Path_Text2Col
constexpr sal_uInt32 kMaxEmbeddedLinefeeds
constexpr OUStringLiteral aSep_Path
static void lcl_LoadSeparators(OUString &rFieldSeparators, OUString &rTextSeparators, bool &rMergeDelimiters, bool &rQuotedAsText, bool &rDetectSpecialNum, bool &rDetectScientificNum, bool &rFixedWidth, sal_Int32 &rFromRow, sal_Int32 &rCharSet, sal_Int32 &rLanguage, bool &rSkipEmptyCells, bool &rRemoveSpace, bool &rEvaluateFormulas, ScImportAsciiCall eCall)
const ::std::vector< OUString > CSVImportOptionNames
static void lcl_CreatePropertiesNames(OUString &rSepPath, Sequence< OUString > &rNames, ScImportAsciiCall eCall)
static void lcl_FillCombo(weld::ComboBox &rCombo, std::u16string_view rList, sal_Unicode cSelect)
IMPL_LINK(ScImportAsciiDlg, RbSepFixHdl, weld::Toggleable &, rButton, void)
constexpr OUStringLiteral aSep_Path_Clpbrd
constexpr OUStringLiteral SCSTR_TEXTSEP
VCL_DLLPUBLIC Application * GetpApp()