1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include <asciiopt.hxx>
22 #include <comphelper/string.hxx>
23 #include <osl/thread.h>
24 #include <o3tl/string_view.hxx>
25 #include <sfx2/objsh.hxx>
27 constexpr std::u16string_view pStrFix
= u
"FIX";
28 constexpr std::u16string_view pStrMrg
= u
"MRG";
29 constexpr std::u16string_view pStrDet
= u
"DETECT";
31 ScAsciiOptions::ScAsciiOptions() :
33 aFieldSeps ( OUString(';') ),
34 bMergeFieldSeps ( false ),
35 bRemoveSpace ( false ),
36 bQuotedFieldAsText(false),
37 bDetectSpecialNumber(false),
38 bDetectScientificNumber(true),
39 bEvaluateFormulas(true),
40 bSkipEmptyCells(false),
44 cTextSep ( cDefaultTextSep
),
45 eCharSet ( osl_getThreadTextEncoding() ),
46 eLang ( LANGUAGE_SYSTEM
),
47 bCharSetSystem ( false ),
52 void ScAsciiOptions::SetColumnInfo( const ScCsvExpDataVec
& rDataVec
)
54 sal_uInt16 nInfoCount
= static_cast< sal_uInt16
>( rDataVec
.size() );
55 mvColStart
.resize(nInfoCount
);
56 mvColFormat
.resize(nInfoCount
);
57 for( sal_uInt16 nIx
= 0; nIx
< nInfoCount
; ++nIx
)
59 mvColStart
[ nIx
] = rDataVec
[ nIx
].mnIndex
;
60 mvColFormat
[ nIx
] = rDataVec
[ nIx
].mnType
;
64 static OUString
lcl_decodeSepString( std::u16string_view rSepNums
, bool & o_bMergeFieldSeps
)
66 if ( rSepNums
.empty() )
69 OUStringBuffer aFieldSeps
;
73 const std::u16string_view aCode
= o3tl::getToken(rSepNums
, 0, '/', nPos
);
74 if ( aCode
== pStrMrg
)
75 o_bMergeFieldSeps
= true;
78 sal_Int32 nVal
= o3tl::toInt32(aCode
);
80 aFieldSeps
.append(sal_Unicode(nVal
));
85 return aFieldSeps
.makeStringAndClear();
88 // The options string must not contain semicolons (because of the pick list),
89 // use comma as separator.
91 void ScAsciiOptions::ReadFromString( std::u16string_view rString
, SvStream
* pStream4Detect
)
93 sal_Int32 nPos
= rString
.empty() ? -1 : 0;
94 bool bDetectSep
= false;
96 // Token 0: Field separator.
99 bFixedLen
= bMergeFieldSeps
= false;
101 const std::u16string_view aToken
= o3tl::getToken(rString
, 0, ',', nPos
);
102 if ( aToken
== pStrDet
)
106 if ( aToken
== pStrFix
)
108 aFieldSeps
= lcl_decodeSepString( aToken
, bMergeFieldSeps
);
112 // Token 1: Text separator.
115 const sal_Int32 nVal
= o3tl::toInt32(o3tl::getToken(rString
, 0, ',', nPos
));
116 cTextSep
= static_cast<sal_Unicode
>(nVal
);
119 // Token 2: Text encoding.
122 const std::u16string_view aToken
= o3tl::getToken(rString
, 0, ',', nPos
);
123 SvStreamEndian endian
;
124 bool bDetectCharSet
= aToken
== pStrDet
;
125 if ( bDetectCharSet
&& pStream4Detect
)
127 SfxObjectShell::DetectCharSet(*pStream4Detect
, eCharSet
, endian
);
128 if (eCharSet
== RTL_TEXTENCODING_UNICODE
)
129 pStream4Detect
->SetEndian(endian
);
131 else if (!bDetectCharSet
)
132 eCharSet
= ScGlobal::GetCharsetValue( aToken
);
135 if (bDetectSep
&& pStream4Detect
)
136 SfxObjectShell::DetectCsvSeparators(*pStream4Detect
, eCharSet
, aFieldSeps
, cTextSep
);
138 // Token 3: Number of start row.
141 nStartRow
= o3tl::toInt32(o3tl::getToken(rString
, 0, ',', nPos
));
144 // Token 4: Column info.
147 const std::u16string_view aToken
= o3tl::getToken(rString
, 0, ',', nPos
);
148 const sal_Int32 nInfoCount
= comphelper::string::getTokenCount(aToken
, '/')/2;
149 mvColStart
.resize(nInfoCount
);
150 mvColFormat
.resize(nInfoCount
);
152 for (sal_Int32 nInfo
=0; nInfo
<nInfoCount
; ++nInfo
)
154 mvColStart
[nInfo
] = o3tl::toInt32(o3tl::getToken(aToken
, 0, '/', nP
));
155 mvColFormat
[nInfo
] = static_cast<sal_uInt8
>(o3tl::toInt32(o3tl::getToken(aToken
, 0, '/', nP
)));
159 // Token 5: Language.
162 eLang
= static_cast<LanguageType
>(o3tl::toInt32(o3tl::getToken(rString
, 0, ',', nPos
)));
165 // Token 6: Import quoted field as text.
168 bQuotedFieldAsText
= o3tl::getToken(rString
, 0, ',', nPos
) == u
"true";
171 // Token 7: Detect special numbers.
174 bDetectSpecialNumber
= o3tl::getToken(rString
, 0, ',', nPos
) == u
"true";
177 bDetectSpecialNumber
= true; // default of versions that didn't add the parameter
179 // Token 8: used for "Save as shown" in export options
182 bSaveAsShown
= o3tl::getToken(rString
, 0, ',', nPos
) == u
"true";
185 bSaveAsShown
= true; // default value
187 // Token 9: used for "Save cell formulas" in export options
190 bSaveFormulas
= o3tl::getToken(rString
, 0, ',', nPos
) == u
"true";
193 bSaveFormulas
= false;
195 // Token 10: Boolean for Trim spaces.
198 bRemoveSpace
= o3tl::getToken(rString
, 0, ',', nPos
) == u
"true";
201 bRemoveSpace
= false;
203 // Token 11: sheet to export for --convert-to csv
204 // Does not need to be evaluated here but may be present.
207 o3tl::getToken(rString
, 0, ',', nPos
);
210 // Token 12: evaluate formulas.
213 // If present, defaults to "false".
214 bEvaluateFormulas
= o3tl::getToken(rString
, 0, ',', nPos
) == u
"true";
217 bEvaluateFormulas
= true; // default of versions that didn't add the parameter
219 // Token 13: include BOM.
220 bIncludeBOM
= nPos
>= 0 && o3tl::getToken(rString
, 0, ',', nPos
) == u
"true";
222 // Token 14: Detect scientific numbers.
225 bDetectScientificNumber
= o3tl::getToken(rString
, 0, ',', nPos
) == u
"true";
228 bDetectScientificNumber
= true; // default of versions that didn't add the parameter
232 OUString
ScAsciiOptions::WriteToString() const
234 OUStringBuffer aOutStr
;
236 // Token 0: Field separator.
238 aOutStr
.append(pStrFix
);
239 else if ( aFieldSeps
.isEmpty() )
243 sal_Int32 nLen
= aFieldSeps
.getLength();
244 for (sal_Int32 i
=0; i
<nLen
; i
++)
248 aOutStr
.append(OUString::number(aFieldSeps
[i
]));
250 if ( bMergeFieldSeps
)
252 aOutStr
.append(OUString::Concat("/") + pStrMrg
);
256 // Token 1: Text Quote character.
257 aOutStr
.append("," + OUString::number(cTextSep
) + ",");
259 //Token 2: Text encoding.
260 if ( bCharSetSystem
) // force "SYSTEM"
261 aOutStr
.append(ScGlobal::GetCharsetString( RTL_TEXTENCODING_DONTKNOW
));
263 aOutStr
.append(ScGlobal::GetCharsetString( eCharSet
));
265 //Token 3: Number of start row.
266 aOutStr
.append("," + OUString::number(nStartRow
) + ",");
268 //Token 4: Column info.
269 for (size_t nInfo
=0; nInfo
<mvColStart
.size(); nInfo
++)
273 aOutStr
.append(OUString::number(mvColStart
[nInfo
]) +
275 OUString::number(mvColFormat
[nInfo
]));
278 // #i112025# the options string is used in macros and linked sheets,
279 // so new options must be added at the end, to remain compatible
280 // Always keep in sync with ScImportOptions.
284 OUString::number(static_cast<sal_uInt16
>(eLang
)) + "," +
285 // Token 6: Import quoted field as text.
286 OUString::boolean( bQuotedFieldAsText
) + "," +
287 // Token 7: Detect special numbers.
288 OUString::boolean( bDetectSpecialNumber
) + "," +
289 // Token 8: used for "Save as shown" in export options
290 OUString::boolean( bSaveAsShown
) +"," +
291 // Token 9: used for "Save cell formulas" in export options
292 OUString::boolean( bSaveFormulas
) + "," +
293 // Token 10: Trim Space
294 OUString::boolean( bRemoveSpace
) +
295 // Token 11: sheet to export, always 0 for current sheet
297 // Token 12: evaluate formulas in import
298 OUString::boolean( bEvaluateFormulas
) + "," +
299 // Token 13: include BOM
300 OUString::boolean(bIncludeBOM
) + "," +
301 // Token 14: Detect scientific numbers.
302 OUString::boolean( bDetectScientificNumber
)
304 return aOutStr
.makeStringAndClear();
308 sal_Unicode
ScAsciiOptions::GetWeightedFieldSep( const OUString
& rFieldSeps
, bool bDecodeNumbers
)
310 bool bMergeFieldSeps
= false;
311 OUString
aFieldSeps( bDecodeNumbers
? lcl_decodeSepString( rFieldSeps
, bMergeFieldSeps
) : rFieldSeps
);
312 if (aFieldSeps
.isEmpty())
316 else if (aFieldSeps
.getLength() == 1)
317 return aFieldSeps
[0];
320 // There can be only one separator for output. See also fdo#53449
321 if (aFieldSeps
.indexOf(',') != -1)
323 else if (aFieldSeps
.indexOf('\t') != -1)
325 else if (aFieldSeps
.indexOf(';') != -1)
327 else if (aFieldSeps
.indexOf(' ') != -1)
330 return aFieldSeps
[0];
334 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */