1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 24 // MARKER(update_precomp.py): autogen include statement, do not remove 25 #include "precompiled_sc.hxx" 26 27 28 29 #include "global.hxx" 30 #include "scresid.hxx" 31 #include "impex.hxx" 32 #include "asciiopt.hxx" 33 #include "asciiopt.hrc" 34 #include <tools/debug.hxx> 35 #include <rtl/tencinfo.h> 36 #include <unotools/transliterationwrapper.hxx> 37 // ause 38 #include "editutil.hxx" 39 40 // ============================================================================ 41 42 static const sal_Char __FAR_DATA pStrFix[] = "FIX"; 43 static const sal_Char __FAR_DATA pStrMrg[] = "MRG"; 44 45 46 // ============================================================================ 47 48 ScAsciiOptions::ScAsciiOptions() : 49 bFixedLen ( sal_False ), 50 aFieldSeps ( ';' ), 51 bMergeFieldSeps ( sal_False ), 52 bQuotedFieldAsText(false), 53 bDetectSpecialNumber(false), 54 cTextSep ( cDefaultTextSep ), 55 eCharSet ( gsl_getSystemTextEncoding() ), 56 eLang ( LANGUAGE_SYSTEM ), 57 bCharSetSystem ( sal_False ), 58 nStartRow ( 1 ), 59 nInfoCount ( 0 ), 60 pColStart ( NULL ), 61 pColFormat ( NULL ) 62 { 63 } 64 65 66 ScAsciiOptions::ScAsciiOptions(const ScAsciiOptions& rOpt) : 67 bFixedLen ( rOpt.bFixedLen ), 68 aFieldSeps ( rOpt.aFieldSeps ), 69 bMergeFieldSeps ( rOpt.bMergeFieldSeps ), 70 bQuotedFieldAsText(rOpt.bQuotedFieldAsText), 71 bDetectSpecialNumber(rOpt.bDetectSpecialNumber), 72 cTextSep ( rOpt.cTextSep ), 73 eCharSet ( rOpt.eCharSet ), 74 eLang ( rOpt.eLang ), 75 bCharSetSystem ( rOpt.bCharSetSystem ), 76 nStartRow ( rOpt.nStartRow ), 77 nInfoCount ( rOpt.nInfoCount ) 78 { 79 if (nInfoCount) 80 { 81 pColStart = new xub_StrLen[nInfoCount]; 82 pColFormat = new sal_uInt8[nInfoCount]; 83 for (sal_uInt16 i=0; i<nInfoCount; i++) 84 { 85 pColStart[i] = rOpt.pColStart[i]; 86 pColFormat[i] = rOpt.pColFormat[i]; 87 } 88 } 89 else 90 { 91 pColStart = NULL; 92 pColFormat = NULL; 93 } 94 } 95 96 97 ScAsciiOptions::~ScAsciiOptions() 98 { 99 delete[] pColStart; 100 delete[] pColFormat; 101 } 102 103 104 void ScAsciiOptions::SetColInfo( sal_uInt16 nCount, const xub_StrLen* pStart, const sal_uInt8* pFormat ) 105 { 106 delete[] pColStart; 107 delete[] pColFormat; 108 109 nInfoCount = nCount; 110 111 if (nInfoCount) 112 { 113 pColStart = new xub_StrLen[nInfoCount]; 114 pColFormat = new sal_uInt8[nInfoCount]; 115 for (sal_uInt16 i=0; i<nInfoCount; i++) 116 { 117 pColStart[i] = pStart[i]; 118 pColFormat[i] = pFormat[i]; 119 } 120 } 121 else 122 { 123 pColStart = NULL; 124 pColFormat = NULL; 125 } 126 } 127 128 129 void ScAsciiOptions::SetColumnInfo( const ScCsvExpDataVec& rDataVec ) 130 { 131 delete[] pColStart; 132 pColStart = NULL; 133 delete[] pColFormat; 134 pColFormat = NULL; 135 136 nInfoCount = static_cast< sal_uInt16 >( rDataVec.size() ); 137 if( nInfoCount ) 138 { 139 pColStart = new xub_StrLen[ nInfoCount ]; 140 pColFormat = new sal_uInt8[ nInfoCount ]; 141 for( sal_uInt16 nIx = 0; nIx < nInfoCount; ++nIx ) 142 { 143 pColStart[ nIx ] = rDataVec[ nIx ].mnIndex; 144 pColFormat[ nIx ] = rDataVec[ nIx ].mnType; 145 } 146 } 147 } 148 149 150 ScAsciiOptions& ScAsciiOptions::operator=( const ScAsciiOptions& rCpy ) 151 { 152 SetColInfo( rCpy.nInfoCount, rCpy.pColStart, rCpy.pColFormat ); 153 154 bFixedLen = rCpy.bFixedLen; 155 aFieldSeps = rCpy.aFieldSeps; 156 bMergeFieldSeps = rCpy.bMergeFieldSeps; 157 bQuotedFieldAsText = rCpy.bQuotedFieldAsText; 158 cTextSep = rCpy.cTextSep; 159 eCharSet = rCpy.eCharSet; 160 bCharSetSystem = rCpy.bCharSetSystem; 161 nStartRow = rCpy.nStartRow; 162 163 return *this; 164 } 165 166 167 sal_Bool ScAsciiOptions::operator==( const ScAsciiOptions& rCmp ) const 168 { 169 if ( bFixedLen == rCmp.bFixedLen && 170 aFieldSeps == rCmp.aFieldSeps && 171 bMergeFieldSeps == rCmp.bMergeFieldSeps && 172 bQuotedFieldAsText == rCmp.bQuotedFieldAsText && 173 cTextSep == rCmp.cTextSep && 174 eCharSet == rCmp.eCharSet && 175 bCharSetSystem == rCmp.bCharSetSystem && 176 nStartRow == rCmp.nStartRow && 177 nInfoCount == rCmp.nInfoCount ) 178 { 179 DBG_ASSERT( !nInfoCount || (pColStart && pColFormat && rCmp.pColStart && rCmp.pColFormat), 180 "0-Zeiger in ScAsciiOptions" ); 181 for (sal_uInt16 i=0; i<nInfoCount; i++) 182 if ( pColStart[i] != rCmp.pColStart[i] || 183 pColFormat[i] != rCmp.pColFormat[i] ) 184 return sal_False; 185 186 return sal_True; 187 } 188 return sal_False; 189 } 190 191 // 192 // Der Options-String darf kein Semikolon mehr enthalten (wegen Pickliste) 193 // darum ab Version 336 Komma stattdessen 194 // 195 196 197 void ScAsciiOptions::ReadFromString( const String& rString ) 198 { 199 xub_StrLen nCount = rString.GetTokenCount(','); 200 String aToken; 201 xub_StrLen nSub; 202 xub_StrLen i; 203 204 // 205 // Feld-Trenner 206 // 207 208 if ( nCount >= 1 ) 209 { 210 bFixedLen = bMergeFieldSeps = sal_False; 211 aFieldSeps.Erase(); 212 213 aToken = rString.GetToken(0,','); 214 if ( aToken.EqualsAscii(pStrFix) ) 215 bFixedLen = sal_True; 216 nSub = aToken.GetTokenCount('/'); 217 for ( i=0; i<nSub; i++ ) 218 { 219 String aCode = aToken.GetToken( i, '/' ); 220 if ( aCode.EqualsAscii(pStrMrg) ) 221 bMergeFieldSeps = sal_True; 222 else 223 { 224 sal_Int32 nVal = aCode.ToInt32(); 225 if ( nVal ) 226 aFieldSeps += (sal_Unicode) nVal; 227 } 228 } 229 } 230 231 // 232 // Text-Trenner 233 // 234 235 if ( nCount >= 2 ) 236 { 237 aToken = rString.GetToken(1,','); 238 sal_Int32 nVal = aToken.ToInt32(); 239 cTextSep = (sal_Unicode) nVal; 240 } 241 242 // 243 // Zeichensatz 244 // 245 246 if ( nCount >= 3 ) 247 { 248 aToken = rString.GetToken(2,','); 249 eCharSet = ScGlobal::GetCharsetValue( aToken ); 250 } 251 252 // 253 // Startzeile 254 // 255 256 if ( nCount >= 4 ) 257 { 258 aToken = rString.GetToken(3,','); 259 nStartRow = aToken.ToInt32(); 260 } 261 262 // 263 // Spalten-Infos 264 // 265 266 if ( nCount >= 5 ) 267 { 268 delete[] pColStart; 269 delete[] pColFormat; 270 271 aToken = rString.GetToken(4,','); 272 nSub = aToken.GetTokenCount('/'); 273 nInfoCount = nSub / 2; 274 if (nInfoCount) 275 { 276 pColStart = new xub_StrLen[nInfoCount]; 277 pColFormat = new sal_uInt8[nInfoCount]; 278 for (sal_uInt16 nInfo=0; nInfo<nInfoCount; nInfo++) 279 { 280 pColStart[nInfo] = (xub_StrLen) aToken.GetToken( 2*nInfo, '/' ).ToInt32(); 281 pColFormat[nInfo] = (sal_uInt8) aToken.GetToken( 2*nInfo+1, '/' ).ToInt32(); 282 } 283 } 284 else 285 { 286 pColStart = NULL; 287 pColFormat = NULL; 288 } 289 } 290 291 // Language 292 if (nCount >= 6) 293 { 294 aToken = rString.GetToken(5, ','); 295 eLang = static_cast<LanguageType>(aToken.ToInt32()); 296 } 297 298 // Import quoted field as text. 299 if (nCount >= 7) 300 { 301 aToken = rString.GetToken(6, ','); 302 bQuotedFieldAsText = aToken.EqualsAscii("true") ? true : false; 303 } 304 305 // Detect special nubmers. 306 if (nCount >= 8) 307 { 308 aToken = rString.GetToken(7, ','); 309 bDetectSpecialNumber = aToken.EqualsAscii("true") ? true : false; 310 } 311 else 312 bDetectSpecialNumber = sal_True; // default of versions that didn't add the parameter 313 314 // 9th token is used for "Save as shown" in export options 315 } 316 317 318 String ScAsciiOptions::WriteToString() const 319 { 320 String aOutStr; 321 322 // 323 // Feld-Trenner 324 // 325 326 if ( bFixedLen ) 327 aOutStr.AppendAscii(pStrFix); 328 else if ( !aFieldSeps.Len() ) 329 aOutStr += '0'; 330 else 331 { 332 xub_StrLen nLen = aFieldSeps.Len(); 333 for (xub_StrLen i=0; i<nLen; i++) 334 { 335 if (i) 336 aOutStr += '/'; 337 aOutStr += String::CreateFromInt32(aFieldSeps.GetChar(i)); 338 } 339 if ( bMergeFieldSeps ) 340 { 341 aOutStr += '/'; 342 aOutStr.AppendAscii(pStrMrg); 343 } 344 } 345 346 aOutStr += ','; // Token-Ende 347 348 // 349 // Text-Trenner 350 // 351 352 aOutStr += String::CreateFromInt32(cTextSep); 353 aOutStr += ','; // Token-Ende 354 355 // 356 // Zeichensatz 357 // 358 359 if ( bCharSetSystem ) // force "SYSTEM" 360 aOutStr += ScGlobal::GetCharsetString( RTL_TEXTENCODING_DONTKNOW ); 361 else 362 aOutStr += ScGlobal::GetCharsetString( eCharSet ); 363 aOutStr += ','; // Token-Ende 364 365 // 366 // Startzeile 367 // 368 369 aOutStr += String::CreateFromInt32(nStartRow); 370 aOutStr += ','; // Token-Ende 371 372 // 373 // Spalten-Infos 374 // 375 376 DBG_ASSERT( !nInfoCount || (pColStart && pColFormat), "0-Zeiger in ScAsciiOptions" ); 377 for (sal_uInt16 nInfo=0; nInfo<nInfoCount; nInfo++) 378 { 379 if (nInfo) 380 aOutStr += '/'; 381 aOutStr += String::CreateFromInt32(pColStart[nInfo]); 382 aOutStr += '/'; 383 aOutStr += String::CreateFromInt32(pColFormat[nInfo]); 384 } 385 386 // #i112025# the options string is used in macros and linked sheets, 387 // so new options must be added at the end, to remain compatible 388 389 aOutStr += ','; 390 391 // Language 392 aOutStr += String::CreateFromInt32(eLang); 393 aOutStr += ','; 394 395 // Import quoted field as text. 396 aOutStr += String::CreateFromAscii(bQuotedFieldAsText ? "true" : "false"); 397 aOutStr += ','; 398 399 // Detect special nubmers. 400 aOutStr += String::CreateFromAscii(bDetectSpecialNumber ? "true" : "false"); 401 402 // 9th token is used for "Save as shown" in export options 403 404 return aOutStr; 405 } 406 407 #if 0 408 // Code, um die Spalten-Liste aus einem Excel-kompatiblen String zu erzeugen: 409 // (im Moment nicht benutzt) 410 411 void ScAsciiOptions::InterpretColumnList( const String& rString ) 412 { 413 // Eingabe ist 1-basiert, pColStart fuer FixedLen ist 0-basiert 414 415 // Kommas durch Semikolon ersetzen 416 417 String aSemiStr = rString; 418 sal_uInt16 nPos = 0; 419 do 420 nPos = aSemiStr.SearchAndReplace( ',', ';', nPos ); 421 while ( nPos != STRING_NOTFOUND ); 422 423 // Eintraege sortieren 424 425 sal_uInt16 nCount = aSemiStr.GetTokenCount(); 426 sal_uInt16* pTemp = new sal_uInt16[nCount+1]; 427 pTemp[0] = 1; // erste Spalte faengt immer bei 1 an 428 sal_uInt16 nFound = 1; 429 sal_uInt16 i,j; 430 for (i=0; i<nCount; i++) 431 { 432 sal_uInt16 nVal = (sal_uInt16) aSemiStr.GetToken(i); 433 if (nVal) 434 { 435 sal_Bool bThere = sal_False; 436 nPos = 0; 437 for (j=0; j<nFound; j++) 438 { 439 if ( pTemp[j] == nVal ) 440 bThere = sal_True; 441 else if ( pTemp[j] < nVal ) 442 nPos = j+1; 443 } 444 if ( !bThere ) 445 { 446 if ( nPos < nFound ) 447 memmove( &pTemp[nPos+1], &pTemp[nPos], (nFound-nPos)*sizeof(sal_uInt16) ); 448 pTemp[nPos] = nVal; 449 ++nFound; 450 } 451 } 452 } 453 454 // Eintraege uebernehmen 455 456 delete[] pColStart; 457 delete[] pColFormat; 458 nInfoCount = nFound; 459 if (nInfoCount) 460 { 461 pColStart = new sal_uInt16[nInfoCount]; 462 pColFormat = new sal_uInt8[nInfoCount]; 463 for (i=0; i<nInfoCount; i++) 464 { 465 pColStart[i] = pTemp[i] - 1; 466 pColFormat[i] = SC_COL_STANDARD; 467 } 468 } 469 else 470 { 471 pColStart = NULL; 472 pColFormat = NULL; 473 } 474 475 bFixedLen = sal_True; // sonst macht's keinen Sinn 476 477 // aufraeumen 478 479 delete[] pTemp; 480 } 481 #endif 482 483