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,
79 CSVIO_PasteSkipEmptyCells
98 "DetectSpecialNumbers",
102constexpr OUStringLiteral
aSep_Path =
u"Office.Calc/Dialogs/CSVImport";
109 return eCall ==
SC_TEXTTOCOLUMNS ? CSVIO_Text2ColSkipEmptyCells : CSVIO_PasteSkipEmptyCells;
132 aStr = OUString(cSelect);
142 if ( !
aStr.isEmpty() && !rList.empty() )
150 sal_Int32 nTmpIdx {nIdx};
160 if( (
aStr.getLength() == 1) || (cFirst <
'0') || (cFirst >
'9') )
190 OUString* pNames = rNames.getArray();
207 const sal_Int32 nSkipEmptyCells = getSkipEmptyCellsIndex(eCall);
208 assert( nSkipEmptyCells < rNames.getLength());
214 bool& rMergeDelimiters,
bool& rQuotedAsText,
bool& rDetectSpecialNum,
215 bool& rFixedWidth, sal_Int32& rFromRow, sal_Int32& rCharSet,
216 sal_Int32& rLanguage,
bool& rSkipEmptyCells,
bool& rRemoveSpace,
220 const Any *pProperties;
226 pProperties = aValues.getConstArray();
228 if( pProperties[ CSVIO_MergeDelimiters ].hasValue() )
231 if( pProperties[ CSVIO_RemoveSpace ].hasValue() )
234 if( pProperties[ CSVIO_Separators ].hasValue() )
235 pProperties[ CSVIO_Separators ] >>= rFieldSeparators;
237 if( pProperties[ CSVIO_TextSeparators ].hasValue() )
238 pProperties[ CSVIO_TextSeparators ] >>= rTextSeparators;
240 if( pProperties[ CSVIO_FixedWidth ].hasValue() )
243 if( pProperties[ CSVIO_EvaluateFormulas ].hasValue() )
248 if( pProperties[ CSVIO_FromRow ].hasValue() )
249 pProperties[ CSVIO_FromRow ] >>= rFromRow;
251 if( pProperties[ CSVIO_CharSet ].hasValue() )
252 pProperties[ CSVIO_CharSet ] >>= rCharSet;
254 if ( pProperties[ CSVIO_QuotedAsText ].hasValue() )
255 pProperties[ CSVIO_QuotedAsText ] >>= rQuotedAsText;
257 if ( pProperties[ CSVIO_DetectSpecialNum ].hasValue() )
258 pProperties[ CSVIO_DetectSpecialNum ] >>= rDetectSpecialNum;
260 if ( pProperties[ CSVIO_Language ].hasValue() )
261 pProperties[ CSVIO_Language ] >>= rLanguage;
265 const sal_Int32 nSkipEmptyCells = getSkipEmptyCellsIndex(eCall);
266 assert( nSkipEmptyCells < aValues.getLength());
267 if ( pProperties[nSkipEmptyCells].hasValue() )
273 const OUString& sFieldSeparators,
const OUString& sTextSeparators,
bool bMergeDelimiters,
bool bQuotedAsText,
274 bool bDetectSpecialNum,
bool bFixedWidth, sal_Int32 nFromRow,
275 sal_Int32 nCharSet, sal_Int32 nLanguage,
bool bSkipEmptyCells,
bool bRemoveSpace,
bool bEvaluateFormulas,
285 pProperties = aValues.getArray();
287 pProperties[ CSVIO_MergeDelimiters ] <<= bMergeDelimiters;
288 pProperties[ CSVIO_RemoveSpace ] <<= bRemoveSpace;
289 pProperties[ CSVIO_Separators ] <<= sFieldSeparators;
290 pProperties[ CSVIO_TextSeparators ] <<= sTextSeparators;
291 pProperties[ CSVIO_FixedWidth ] <<= bFixedWidth;
292 pProperties[ CSVIO_EvaluateFormulas ] <<= bEvaluateFormulas;
295 pProperties[ CSVIO_FromRow ] <<= nFromRow;
296 pProperties[ CSVIO_CharSet ] <<= nCharSet;
297 pProperties[ CSVIO_QuotedAsText ] <<= bQuotedAsText;
298 pProperties[ CSVIO_DetectSpecialNum ] <<= bDetectSpecialNum;
299 pProperties[ CSVIO_Language ] <<= nLanguage;
303 const sal_Int32 nSkipEmptyCells = getSkipEmptyCellsIndex(eCall);
304 assert( nSkipEmptyCells < aValues.getLength());
305 pProperties[ nSkipEmptyCells ] <<= bSkipEmptyCells;
313 : GenericDialogController(pParent,
"modules/scalc/ui/textimportcsv.ui",
"TextImportCsvDialog")
314 , mpDatStream(pInStream)
315 , mnStreamPos(pInStream ? pInStream->Tell() : 0)
320 , mxFtCharSet(m_xBuilder->weld_label(
"textcharset"))
322 , mxFtCustomLang(m_xBuilder->weld_label(
"textlanguage"))
323 , mxLbCustomLang(new
SvxLanguageBox(m_xBuilder->weld_combo_box(
"language")))
324 , mxFtRow(m_xBuilder->weld_label(
"textfromrow"))
325 , mxNfRow(m_xBuilder->weld_spin_button(
"fromrow"))
326 , mxRbFixed(m_xBuilder->weld_radio_button(
"tofixedwidth"))
327 , mxRbSeparated(m_xBuilder->weld_radio_button(
"toseparatedby"))
328 , mxCkbTab(m_xBuilder->weld_check_button(
"tab"))
329 , mxCkbSemicolon(m_xBuilder->weld_check_button(
"semicolon"))
330 , mxCkbComma(m_xBuilder->weld_check_button(
"comma"))
331 , mxCkbRemoveSpace(m_xBuilder->weld_check_button(
"removespace"))
332 , mxCkbSpace(m_xBuilder->weld_check_button(
"space"))
333 , mxCkbOther(m_xBuilder->weld_check_button(
"other"))
334 , mxEdOther(m_xBuilder->weld_entry(
"inputother"))
335 , mxCkbAsOnce(m_xBuilder->weld_check_button(
"mergedelimiters"))
336 , mxFtTextSep(m_xBuilder->weld_label(
"texttextdelimiter"))
337 , mxCbTextSep(m_xBuilder->weld_combo_box(
"textdelimiter"))
338 , mxCkbQuotedAsText(m_xBuilder->weld_check_button(
"quotedfieldastext"))
339 , mxCkbDetectNumber(m_xBuilder->weld_check_button(
"detectspecialnumbers"))
340 , mxCkbEvaluateFormulas(m_xBuilder->weld_check_button(
"evaluateformulas"))
341 , mxCkbSkipEmptyCells(m_xBuilder->weld_check_button(
"skipemptycells"))
342 , mxFtType(m_xBuilder->weld_label(
"textcolumntype"))
343 , mxLbType(m_xBuilder->weld_combo_box(
"columntype"))
344 , mxAltTitle(m_xBuilder->weld_label(
"textalttitle"))
356 aName +=
" - [" + aDatName +
"]";
365 bool bIsTSV = (aDatName.endsWithIgnoreAsciiCase(
".tsv") || aDatName.endsWithIgnoreAsciiCase(
".tab"));
368 OUString sFieldSeparators(
",;\t");
370 bool bMergeDelimiters =
false;
371 bool bFixedWidth =
false;
372 bool bQuotedFieldAsText =
false;
373 bool bDetectSpecialNum =
true;
375 bool bSkipEmptyCells =
true;
376 bool bRemoveSpace =
false;
377 sal_Int32 nFromRow = 1;
378 sal_Int32 nCharSet = -1;
379 sal_Int32 nLanguage = 0;
381 bQuotedFieldAsText, bDetectSpecialNum, bFixedWidth, nFromRow,
382 nCharSet, nLanguage, bSkipEmptyCells, bRemoveSpace, bEvaluateFormulas,
meCall);
386 if( bMergeDelimiters && !bIsTSV )
388 if (bQuotedFieldAsText)
392 if (bDetectSpecialNum)
394 if (bEvaluateFormulas)
398 if (bFixedWidth && !bIsTSV)
405 RTL_TEXTENCODING_DONTKNOW : RTL_TEXTENCODING_UNICODE);
407 if( ePreselectUnicode == RTL_TEXTENCODING_DONTKNOW &&
mpDatStream )
410 constexpr size_t buffsize = 4096;
417 UErrorCode uerr = U_ZERO_ERROR;
418 UCharsetDetector* ucd = ucsdet_open( &uerr );
419 ucsdet_setText( ucd,
reinterpret_cast<const char*
>(
bytes), nRead, &uerr );
421 if (
const UCharsetMatch*
match = ucsdet_detect(ucd, &uerr) )
423 const char* pEncodingName = ucsdet_getName(
match, &uerr );
425 if ( U_SUCCESS(uerr) && !strcmp(
"UTF-8", pEncodingName) )
427 ePreselectUnicode = RTL_TEXTENCODING_UTF8;
430 else if ( U_SUCCESS(uerr) && !strcmp(
"UTF-16LE", pEncodingName) )
432 ePreselectUnicode = RTL_TEXTENCODING_UNICODE;
436 else if ( U_SUCCESS(uerr) && !strcmp(
"UTF-16BE", pEncodingName) )
438 ePreselectUnicode = RTL_TEXTENCODING_UNICODE;
471 if (aLine.getLength() == 8)
473 else if (aLine.getLength() == 5 && aLine.startsWithIgnoreAsciiCase(
"sep="))
475 else if (aLine.getLength() == 7 && aLine[6] ==
'"' && aLine.startsWithIgnoreAsciiCase(
"\"sep="))
496 mxCkbTab->connect_toggled( aSeparatorClickHdl );
498 mxCkbComma->connect_toggled( aSeparatorClickHdl );
499 mxCkbAsOnce->connect_toggled( aSeparatorClickHdl );
504 mxCkbSpace->connect_toggled( aSeparatorClickHdl );
506 mxCkbOther->connect_toggled( aSeparatorClickHdl );
514 mxLbCharSet->InsertTextEncoding( RTL_TEXTENCODING_DONTKNOW,
ScResId( SCSTR_CHARSET_USER ) );
515 if ( ePreselectUnicode == RTL_TEXTENCODING_DONTKNOW )
517 rtl_TextEncoding eSystemEncoding = osl_getThreadTextEncoding();
520 if ( ( eSystemEncoding == RTL_TEXTENCODING_UNICODE ) &&
mpDatStream )
521 eSystemEncoding = RTL_TEXTENCODING_UTF8;
522 mxLbCharSet->SelectTextEncoding( eSystemEncoding );
526 mxLbCharSet->SelectTextEncoding( ePreselectUnicode );
529 if (nCharSet >= 0 && ePreselectUnicode == RTL_TEXTENCODING_DONTKNOW)
536 SvxLanguageListFlags::ALL | SvxLanguageListFlags::ONLY_KNOWN,
false,
false);
541 OUString aColumnUser(
ScResId( SCSTR_COLUMN_USER ) );
542 for (sal_Int32 nIdx {0}; nIdx>=0; )
544 mxLbType->append_text(aColumnUser.getToken(0,
';', nIdx));
707 constexpr sal_Unicode aSeps[] = {
'\t',
';',
',',
' ' };
710 const bool bSet = (c == cSep);
713 case '\t':
mxCkbTab->set_active(bSet);
break;
715 case ',':
mxCkbComma->set_active(bSet);
break;
716 case ' ':
mxCkbSpace->set_active(bSet);
break;
733 case '\t':
mxCkbTab->set_active(
true);
break;
735 case ',':
mxCkbComma->set_active(
true);
break;
736 case ' ':
mxCkbSpace->set_active(
true);
break;
803 if (!rButton.get_active())
810 SeparatorHdl(&rCtrl);
815 SeparatorHdl(&rCtrl);
820 SeparatorHdl(&rEdit);
825 OSL_ENSURE( pCtrl,
"ScImportAsciiDlg::SeparatorHdl - missing sender" );
826 OSL_ENSURE( !
mxRbFixed->get_active(),
"ScImportAsciiDlg::SeparatorHdl - not allowed in fixed width" );
849 if (mxLbCharSet->get_active() != -1)
852 rtl_TextEncoding eOldCharSet = meCharSet;
853 SetSelectedCharSet();
855 if (eOldCharSet != meCharSet)
869 if (&rListBox == mxLbType.get())
879 mbDetectSep = (mbDetectSep && !mxRbFixed->get_active()
880 && (!mxCkbTab->get_active() || !mxCkbSemicolon->get_active()
881 || !mxCkbComma->get_active() || !mxCkbSpace->get_active()));
882 sal_Unicode cDetectSep = (mbDetectSep ? 0 : 0xffff);
884 sal_Int32 nBaseLine = mxTableBox->GetGrid().GetFirstVisLine();
885 sal_Int32 nRead = mxTableBox->GetGrid().GetVisLineCount();
894 for (
i = 0;
i < nRead;
i++)
896 if (!GetLine( nBaseLine +
i, maPreviewLine[
i], cDetectSep))
900 maPreviewLine[
i].clear();
909 assert(maFieldSeparators.endsWith(OUStringChar(cDetectSep)));
913 case '\t': mxCkbTab->set_active(
true);
break;
914 case ';': mxCkbSemicolon->set_active(
true);
break;
915 case ',': mxCkbComma->set_active(
true);
break;
916 case ' ': mxCkbSpace->set_active(
true);
break;
922 bool bMergeSep = mxCkbAsOnce->get_active();
923 bool bRemoveSpace = mxCkbRemoveSpace->get_active();
924 mxTableBox->SetUniStrings( maPreviewLine, maFieldSeparators, mcTextSep, bMergeSep, bRemoveSpace );
929 sal_Int32
nType = rTableBox.GetSelColumnType();
930 sal_Int32 nTypeCount = mxLbType->get_count();
932 bool bEnable = ((0 <=
nType) && (
nType < nTypeCount)) || bEmpty;
934 mxFtType->set_sensitive( bEnable );
935 mxLbType->set_sensitive( bEnable );
938 mxLbType->set_active(-1);
940 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 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
ScImportAsciiDlg(weld::Window *pParent, const OUString &aDatName, SvStream *pInStream, ScImportAsciiCall eCall)
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::Label > mxFtType
OUString GetSeparators() const
Returns all separator characters in a string.
std::unique_ptr< weld::CheckButton > mxCkbSemicolon
std::unique_ptr< sal_uLong[]> mpRowPosArray
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)
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.
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
static void lcl_LoadSeparators(OUString &rFieldSeparators, OUString &rTextSeparators, bool &rMergeDelimiters, bool &rQuotedAsText, bool &rDetectSpecialNum, bool &rFixedWidth, sal_Int32 &rFromRow, sal_Int32 &rCharSet, sal_Int32 &rLanguage, bool &rSkipEmptyCells, bool &rRemoveSpace, bool &rEvaluateFormulas, ScImportAsciiCall eCall)
constexpr sal_uInt32 kMaxEmbeddedLinefeeds
constexpr OUStringLiteral aSep_Path
static void lcl_SaveSeparators(const OUString &sFieldSeparators, const OUString &sTextSeparators, bool bMergeDelimiters, bool bQuotedAsText, bool bDetectSpecialNum, bool bFixedWidth, sal_Int32 nFromRow, sal_Int32 nCharSet, sal_Int32 nLanguage, bool bSkipEmptyCells, bool bRemoveSpace, bool bEvaluateFormulas, 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()