Version 6.4.0.3, tag libreoffice-6.4.0.3
[LibreOffice.git] / sc / source / filter / excel / xltools.cxx
blob2a531a70da61a68fe694262485ec7b6ee6cc9089
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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 .
20 #include <algorithm>
21 #include <math.h>
22 #include <sal/mathconf.h>
23 #include <sal/macros.h>
24 #include <sal/log.hxx>
25 #include <tools/solar.h>
26 #include <unotools/fontdefs.hxx>
27 #include <filter/msfilter/msvbahelper.hxx>
28 #include <xestream.hxx>
29 #include <global.hxx>
30 #include <formula/errorcodes.hxx>
31 #include <globstr.hrc>
32 #include <scresid.hxx>
33 #include <xlstyle.hxx>
34 #include <xlname.hxx>
35 #include <xistream.hxx>
36 #include <xltools.hxx>
38 // GUID import/export
40 XclGuid::XclGuid()
41 : mpnData{}
45 XclGuid::XclGuid(
46 sal_uInt32 nData1, sal_uInt16 nData2, sal_uInt16 nData3,
47 sal_uInt8 nData41, sal_uInt8 nData42, sal_uInt8 nData43, sal_uInt8 nData44,
48 sal_uInt8 nData45, sal_uInt8 nData46, sal_uInt8 nData47, sal_uInt8 nData48 )
50 // convert to little endian -> makes streaming easy
51 UInt32ToSVBT32( nData1, mpnData );
52 ShortToSVBT16( nData2, mpnData + 4 );
53 ShortToSVBT16( nData3, mpnData + 6 );
54 mpnData[ 8 ] = nData41;
55 mpnData[ 9 ] = nData42;
56 mpnData[ 10 ] = nData43;
57 mpnData[ 11 ] = nData44;
58 mpnData[ 12 ] = nData45;
59 mpnData[ 13 ] = nData46;
60 mpnData[ 14 ] = nData47;
61 mpnData[ 15 ] = nData48;
64 bool operator==( const XclGuid& rCmp1, const XclGuid& rCmp2 )
66 return ::std::equal( rCmp1.mpnData, std::end( rCmp1.mpnData ), rCmp2.mpnData );
69 XclImpStream& operator>>( XclImpStream& rStrm, XclGuid& rGuid )
71 rStrm.Read( rGuid.mpnData, 16 ); // mpnData always in little endian
72 return rStrm;
75 XclExpStream& operator<<( XclExpStream& rStrm, const XclGuid& rGuid )
77 rStrm.Write( rGuid.mpnData, 16 ); // mpnData already in little endian
78 return rStrm;
81 // Excel Tools
83 // GUID's
84 const XclGuid XclTools::maGuidStdLink(
85 0x79EAC9D0, 0xBAF9, 0x11CE, 0x8C, 0x82, 0x00, 0xAA, 0x00, 0x4B, 0xA9, 0x0B );
87 const XclGuid XclTools::maGuidUrlMoniker(
88 0x79EAC9E0, 0xBAF9, 0x11CE, 0x8C, 0x82, 0x00, 0xAA, 0x00, 0x4B, 0xA9, 0x0B );
90 const XclGuid XclTools::maGuidFileMoniker(
91 0x00000303, 0x0000, 0x0000, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46 );
93 // numeric conversion
95 double XclTools::GetDoubleFromRK( sal_Int32 nRKValue )
97 union
99 double fVal;
100 sal_math_Double smD;
102 fVal = 0.0;
104 if( ::get_flag( nRKValue, EXC_RK_INTFLAG ) )
106 sal_Int32 nTemp = nRKValue >> 2;
107 ::set_flag< sal_Int32 >( nTemp, 0xE0000000, nRKValue < 0 );
108 fVal = nTemp;
110 else
112 smD.w32_parts.msw = nRKValue & EXC_RK_VALUEMASK;
115 if( ::get_flag( nRKValue, EXC_RK_100FLAG ) )
116 fVal /= 100.0;
118 return fVal;
121 bool XclTools::GetRKFromDouble( sal_Int32& rnRKValue, double fValue )
123 double fFrac, fInt;
125 // integer
126 fFrac = modf( fValue, &fInt );
127 if( (fFrac == 0.0) && (fInt >= -536870912.0) && (fInt <= 536870911.0) ) // 2^29
129 rnRKValue
130 = static_cast<sal_Int32>(
131 static_cast<sal_uInt32>(static_cast<sal_Int32>(fInt)) << 2)
132 | EXC_RK_INT;
133 return true;
136 // integer/100
137 fFrac = modf( fValue * 100.0, &fInt );
138 if( (fFrac == 0.0) && (fInt >= -536870912.0) && (fInt <= 536870911.0) )
140 rnRKValue
141 = static_cast<sal_Int32>(
142 static_cast<sal_uInt32>(static_cast<sal_Int32>(fInt)) << 2)
143 | EXC_RK_INT100;
144 return true;
147 // double
148 return false;
151 sal_Int32 XclTools::GetScRotation( sal_uInt16 nXclRot, sal_Int32 nRotForStacked )
153 if( nXclRot == EXC_ROT_STACKED )
154 return nRotForStacked;
155 OSL_ENSURE( nXclRot <= 180, "XclTools::GetScRotation - illegal rotation angle" );
156 return static_cast< sal_Int32 >( (nXclRot <= 180) ? (100 * ((nXclRot > 90) ? (450 - nXclRot) : nXclRot)) : 0 );
159 sal_uInt8 XclTools::GetXclRotation( sal_Int32 nScRot )
161 sal_Int32 nXclRot = nScRot / 100;
162 if( (0 <= nXclRot) && (nXclRot <= 90) )
163 return static_cast< sal_uInt8 >( nXclRot );
164 if( nXclRot < 180 )
165 return static_cast< sal_uInt8 >( 270 - nXclRot );
166 if( nXclRot < 270 )
167 return static_cast< sal_uInt8 >( nXclRot - 180 );
168 if( nXclRot < 360 )
169 return static_cast< sal_uInt8 >( 450 - nXclRot );
170 return 0;
173 sal_uInt8 XclTools::GetXclRotFromOrient( sal_uInt8 nXclOrient )
175 switch( nXclOrient )
177 case EXC_ORIENT_NONE: return EXC_ROT_NONE;
178 case EXC_ORIENT_STACKED: return EXC_ROT_STACKED;
179 case EXC_ORIENT_90CCW: return EXC_ROT_90CCW;
180 case EXC_ORIENT_90CW: return EXC_ROT_90CW;
181 default: OSL_FAIL( "XclTools::GetXclRotFromOrient - unknown text orientation" );
183 return EXC_ROT_NONE;
186 sal_uInt8 XclTools::GetXclOrientFromRot( sal_uInt16 nXclRot )
188 if( nXclRot == EXC_ROT_STACKED )
189 return EXC_ORIENT_STACKED;
190 OSL_ENSURE( nXclRot <= 180, "XclTools::GetXclOrientFromRot - unknown text rotation" );
191 if( (45 < nXclRot) && (nXclRot <= 90) )
192 return EXC_ORIENT_90CCW;
193 if( (135 < nXclRot) && (nXclRot <= 180) )
194 return EXC_ORIENT_90CW;
195 return EXC_ORIENT_NONE;
198 sal_uInt8 XclTools::GetXclErrorCode( FormulaError nScError )
200 switch( nScError )
202 case FormulaError::IllegalArgument: return EXC_ERR_VALUE;
203 case FormulaError::IllegalFPOperation: return EXC_ERR_NUM; // maybe DIV/0 or NUM...
204 case FormulaError::DivisionByZero: return EXC_ERR_DIV0;
205 case FormulaError::IllegalParameter: return EXC_ERR_VALUE;
206 case FormulaError::PairExpected: return EXC_ERR_VALUE;
207 case FormulaError::OperatorExpected: return EXC_ERR_VALUE;
208 case FormulaError::VariableExpected: return EXC_ERR_VALUE;
209 case FormulaError::ParameterExpected: return EXC_ERR_VALUE;
210 case FormulaError::NoValue: return EXC_ERR_VALUE;
211 case FormulaError::CircularReference: return EXC_ERR_VALUE;
212 case FormulaError::NoCode: return EXC_ERR_NULL;
213 case FormulaError::NoRef: return EXC_ERR_REF;
214 case FormulaError::NoName: return EXC_ERR_NAME;
215 case FormulaError::NoAddin: return EXC_ERR_NAME;
216 case FormulaError::NoMacro: return EXC_ERR_NAME;
217 case FormulaError::NotAvailable: return EXC_ERR_NA;
218 default: break;
220 return EXC_ERR_NA;
223 FormulaError XclTools::GetScErrorCode( sal_uInt8 nXclError )
225 switch( nXclError )
227 case EXC_ERR_NULL: return FormulaError::NoCode;
228 case EXC_ERR_DIV0: return FormulaError::DivisionByZero;
229 case EXC_ERR_VALUE: return FormulaError::NoValue;
230 case EXC_ERR_REF: return FormulaError::NoRef;
231 case EXC_ERR_NAME: return FormulaError::NoName;
232 case EXC_ERR_NUM: return FormulaError::IllegalFPOperation;
233 case EXC_ERR_NA: return FormulaError::NotAvailable;
234 default: OSL_FAIL( "XclTools::GetScErrorCode - unknown error code" );
236 return FormulaError::NotAvailable;
239 double XclTools::ErrorToDouble( sal_uInt8 nXclError )
241 return CreateDoubleError(GetScErrorCode( nXclError ));
244 XclBoolError XclTools::ErrorToEnum( double& rfDblValue, bool bErrOrBool, sal_uInt8 nValue )
246 XclBoolError eType;
247 if( bErrOrBool )
249 // error value
250 switch( nValue )
252 case EXC_ERR_NULL: eType = xlErrNull; break;
253 case EXC_ERR_DIV0: eType = xlErrDiv0; break;
254 case EXC_ERR_VALUE: eType = xlErrValue; break;
255 case EXC_ERR_REF: eType = xlErrRef; break;
256 case EXC_ERR_NAME: eType = xlErrName; break;
257 case EXC_ERR_NUM: eType = xlErrNum; break;
258 case EXC_ERR_NA: eType = xlErrNA; break;
259 default: eType = xlErrUnknown;
261 rfDblValue = 0.0;
263 else
265 // Boolean value
266 eType = nValue ? xlErrTrue : xlErrFalse;
267 rfDblValue = nValue ? 1.0 : 0.0;
269 return eType;
272 sal_uInt16 XclTools::GetTwipsFromInch( double fInches )
274 return static_cast< sal_uInt16 >(
275 ::std::min( ::std::max( (fInches * EXC_TWIPS_PER_INCH + 0.5), 0.0 ), 65535.0 ) );
278 sal_uInt16 XclTools::GetTwipsFromHmm( sal_Int32 nHmm )
280 return GetTwipsFromInch( static_cast< double >( nHmm ) / 1000.0 / CM_PER_INCH );
283 double XclTools::GetInchFromTwips( sal_Int32 nTwips )
285 return static_cast< double >( nTwips ) / EXC_TWIPS_PER_INCH;
288 double XclTools::GetInchFromHmm( sal_Int32 nHmm )
290 return GetInchFromTwips( GetTwipsFromHmm( nHmm ) );
293 sal_Int32 XclTools::GetHmmFromInch( double fInches )
295 return static_cast< sal_Int32 >( fInches * CM_PER_INCH * 1000 );
298 sal_Int32 XclTools::GetHmmFromTwips( sal_Int32 nTwips )
300 return GetHmmFromInch( GetInchFromTwips( nTwips ) );
303 sal_uInt16 XclTools::GetScColumnWidth( sal_uInt16 nXclWidth, long nScCharWidth )
305 double fScWidth = static_cast< double >( nXclWidth ) / 256.0 * nScCharWidth - 0.5;
306 return limit_cast< sal_uInt16 >( fScWidth );
309 sal_uInt16 XclTools::GetXclColumnWidth( sal_uInt16 nScWidth, long nScCharWidth )
311 double fXclWidth = ( static_cast< double >( nScWidth ) + 0.5 ) * 256.0 / nScCharWidth;
312 return limit_cast< sal_uInt16 >( fXclWidth );
315 double XclTools::GetXclDefColWidthCorrection( long nXclDefFontHeight )
317 return 40960.0 / ::std::max( nXclDefFontHeight - 15, 60L ) + 50.0;
320 // formatting
322 Color XclTools::GetPatternColor( const Color& rPattColor, const Color& rBackColor, sal_uInt16 nXclPattern )
324 // 0x00 == 0% transparence (full rPattColor)
325 // 0x80 == 100% transparence (full rBackColor)
326 static const sal_uInt8 pnRatioTable[] =
328 0x80, 0x00, 0x40, 0x20, 0x60, 0x40, 0x40, 0x40, // 00 - 07
329 0x40, 0x40, 0x20, 0x60, 0x60, 0x60, 0x60, 0x48, // 08 - 15
330 0x50, 0x70, 0x78 // 16 - 18
332 return (nXclPattern < SAL_N_ELEMENTS( pnRatioTable )) ?
333 ScfTools::GetMixedColor( rPattColor, rBackColor, pnRatioTable[ nXclPattern ] ) : rPattColor;
336 // text encoding
338 namespace {
340 const struct XclCodePageEntry
342 sal_uInt16 const mnCodePage;
343 rtl_TextEncoding const meTextEnc;
345 pCodePageTable[] =
347 { 437, RTL_TEXTENCODING_IBM_437 }, // OEM US
348 // { 720, RTL_TEXTENCODING_IBM_720 }, // OEM Arabic
349 { 737, RTL_TEXTENCODING_IBM_737 }, // OEM Greek
350 { 775, RTL_TEXTENCODING_IBM_775 }, // OEM Baltic
351 { 850, RTL_TEXTENCODING_IBM_850 }, // OEM Latin I
352 { 852, RTL_TEXTENCODING_IBM_852 }, // OEM Latin II (Central European)
353 { 855, RTL_TEXTENCODING_IBM_855 }, // OEM Cyrillic
354 { 857, RTL_TEXTENCODING_IBM_857 }, // OEM Turkish
355 // { 858, RTL_TEXTENCODING_IBM_858 }, // OEM Multilingual Latin I with Euro
356 { 860, RTL_TEXTENCODING_IBM_860 }, // OEM Portuguese
357 { 861, RTL_TEXTENCODING_IBM_861 }, // OEM Icelandic
358 { 862, RTL_TEXTENCODING_IBM_862 }, // OEM Hebrew
359 { 863, RTL_TEXTENCODING_IBM_863 }, // OEM Canadian (French)
360 { 864, RTL_TEXTENCODING_IBM_864 }, // OEM Arabic
361 { 865, RTL_TEXTENCODING_IBM_865 }, // OEM Nordic
362 { 866, RTL_TEXTENCODING_IBM_866 }, // OEM Cyrillic (Russian)
363 { 869, RTL_TEXTENCODING_IBM_869 }, // OEM Greek (Modern)
364 { 874, RTL_TEXTENCODING_MS_874 }, // MS Windows Thai
365 { 932, RTL_TEXTENCODING_MS_932 }, // MS Windows Japanese Shift-JIS
366 { 936, RTL_TEXTENCODING_MS_936 }, // MS Windows Chinese Simplified GBK
367 { 949, RTL_TEXTENCODING_MS_949 }, // MS Windows Korean (Wansung)
368 { 950, RTL_TEXTENCODING_MS_950 }, // MS Windows Chinese Traditional BIG5
369 { 1200, RTL_TEXTENCODING_DONTKNOW }, // Unicode (BIFF8) - return *_DONTKNOW to preserve old code page
370 { 1250, RTL_TEXTENCODING_MS_1250 }, // MS Windows Latin II (Central European)
371 { 1251, RTL_TEXTENCODING_MS_1251 }, // MS Windows Cyrillic
372 { 1252, RTL_TEXTENCODING_MS_1252 }, // MS Windows Latin I (BIFF4-BIFF8)
373 { 1253, RTL_TEXTENCODING_MS_1253 }, // MS Windows Greek
374 { 1254, RTL_TEXTENCODING_MS_1254 }, // MS Windows Turkish
375 { 1255, RTL_TEXTENCODING_MS_1255 }, // MS Windows Hebrew
376 { 1256, RTL_TEXTENCODING_MS_1256 }, // MS Windows Arabic
377 { 1257, RTL_TEXTENCODING_MS_1257 }, // MS Windows Baltic
378 { 1258, RTL_TEXTENCODING_MS_1258 }, // MS Windows Vietnamese
379 { 1361, RTL_TEXTENCODING_MS_1361 }, // MS Windows Korean (Johab)
380 { 10000, RTL_TEXTENCODING_APPLE_ROMAN }, // Apple Roman
381 { 32768, RTL_TEXTENCODING_APPLE_ROMAN }, // Apple Roman
382 { 32769, RTL_TEXTENCODING_MS_1252 } // MS Windows Latin I (BIFF2-BIFF3)
384 const XclCodePageEntry* const pCodePageTableEnd = std::end(pCodePageTable);
386 struct XclCodePageEntry_CPPred
388 explicit XclCodePageEntry_CPPred( sal_uInt16 nCodePage ) : mnCodePage( nCodePage ) {}
389 bool operator()( const XclCodePageEntry& rEntry ) const { return rEntry.mnCodePage == mnCodePage; }
390 sal_uInt16 const mnCodePage;
393 struct XclCodePageEntry_TEPred
395 explicit XclCodePageEntry_TEPred( rtl_TextEncoding eTextEnc ) : meTextEnc( eTextEnc ) {}
396 bool operator()( const XclCodePageEntry& rEntry ) const { return rEntry.meTextEnc == meTextEnc; }
397 rtl_TextEncoding const meTextEnc;
400 } // namespace
402 rtl_TextEncoding XclTools::GetTextEncoding( sal_uInt16 nCodePage )
404 const XclCodePageEntry* pEntry = ::std::find_if( pCodePageTable, pCodePageTableEnd, XclCodePageEntry_CPPred( nCodePage ) );
405 if( pEntry == pCodePageTableEnd )
407 SAL_WARN("sc", "XclTools::GetTextEncoding - unknown code page: 0x" << std::hex << nCodePage );
408 return RTL_TEXTENCODING_DONTKNOW;
410 return pEntry->meTextEnc;
413 sal_uInt16 XclTools::GetXclCodePage( rtl_TextEncoding eTextEnc )
415 if( eTextEnc == RTL_TEXTENCODING_UNICODE )
416 return 1200; // for BIFF8
418 const XclCodePageEntry* pEntry = ::std::find_if( pCodePageTable, pCodePageTableEnd, XclCodePageEntry_TEPred( eTextEnc ) );
419 if( pEntry == pCodePageTableEnd )
421 SAL_WARN("sc", "XclTools::GetXclCodePage - unsupported text encoding: 0x" << std::hex << eTextEnc );
422 return 1252;
424 return pEntry->mnCodePage;
427 OUString XclTools::GetXclFontName( const OUString& rFontName )
429 // substitute with MS fonts
430 OUString aNewName = GetSubsFontName(rFontName, SubsFontFlags::ONLYONE | SubsFontFlags::MS);
431 return aNewName.isEmpty() ? rFontName : aNewName;
434 // built-in defined names
435 static const char maDefNamePrefix[] = "Excel_BuiltIn_"; /// Prefix for built-in defined names.
436 static const char maDefNamePrefixXml[] = "_xlnm."; /// Prefix for built-in defined names for OOX
438 static const sal_Char* const ppcDefNames[] =
440 "Consolidate_Area",
441 "Auto_Open",
442 "Auto_Close",
443 "Extract",
444 "Database",
445 "Criteria",
446 "Print_Area",
447 "Print_Titles",
448 "Recorder",
449 "Data_Form",
450 "Auto_Activate",
451 "Auto_Deactivate",
452 "Sheet_Title",
453 "_FilterDatabase"
456 OUString XclTools::GetXclBuiltInDefName( sal_Unicode cBuiltIn )
458 OSL_ENSURE( SAL_N_ELEMENTS( ppcDefNames ) == EXC_BUILTIN_UNKNOWN,
459 "XclTools::GetXclBuiltInDefName - built-in defined name list modified" );
461 if( cBuiltIn < SAL_N_ELEMENTS( ppcDefNames ) )
462 return OUString::createFromAscii(ppcDefNames[cBuiltIn]);
463 else
464 return OUString::number(cBuiltIn);
467 OUString XclTools::GetBuiltInDefName( sal_Unicode cBuiltIn )
469 OUStringBuffer aBuf(maDefNamePrefix);
470 aBuf.append(GetXclBuiltInDefName(cBuiltIn));
471 return aBuf.makeStringAndClear();
474 OUString XclTools::GetBuiltInDefNameXml( sal_Unicode cBuiltIn )
476 OUStringBuffer aBuf(maDefNamePrefixXml);
477 aBuf.append(GetXclBuiltInDefName(cBuiltIn));
478 return aBuf.makeStringAndClear();
481 sal_Unicode XclTools::GetBuiltInDefNameIndex( const OUString& rDefName )
483 sal_Int32 nPrefixLen = 0;
484 if( rDefName.startsWithIgnoreAsciiCase( maDefNamePrefix ) )
485 nPrefixLen = strlen(maDefNamePrefix);
486 else if( rDefName.startsWithIgnoreAsciiCase( maDefNamePrefixXml ) )
487 nPrefixLen = strlen(maDefNamePrefixXml);
488 if( nPrefixLen > 0 )
490 for( sal_Unicode cBuiltIn = 0; cBuiltIn < EXC_BUILTIN_UNKNOWN; ++cBuiltIn )
492 OUString aBuiltInName(GetXclBuiltInDefName(cBuiltIn));
493 sal_Int32 nBuiltInLen = aBuiltInName.getLength();
494 if( rDefName.matchIgnoreAsciiCase( aBuiltInName, nPrefixLen ) )
496 // name can be followed by underline or space character
497 sal_Int32 nNextCharPos = nPrefixLen + nBuiltInLen;
498 sal_Unicode cNextChar = (rDefName.getLength() > nNextCharPos) ? rDefName[nNextCharPos] : '\0';
499 if( (cNextChar == '\0') || (cNextChar == ' ') || (cNextChar == '_') )
500 return cBuiltIn;
504 return EXC_BUILTIN_UNKNOWN;
507 // built-in style names
509 static const char maStyleNamePrefix1[] = "Excel_BuiltIn_"; /// Prefix for built-in cell style names.
510 static const char maStyleNamePrefix2[] = "Excel Built-in "; /// Prefix for built-in cell style names from OOX filter.
512 static const sal_Char* const ppcStyleNames[] =
514 "", // "Normal" not used directly, but localized "Default"
515 "RowLevel_", // outline level will be appended
516 "ColumnLevel_", // outline level will be appended
517 "Comma",
518 "Currency",
519 "Percent",
520 "Comma_0",
521 "Currency_0",
522 "Hyperlink",
523 "Followed_Hyperlink"
526 OUString XclTools::GetBuiltInStyleName( sal_uInt8 nStyleId, const OUString& rName, sal_uInt8 nLevel )
528 OUString aStyleName;
530 if( nStyleId == EXC_STYLE_NORMAL ) // "Normal" becomes "Default" style
532 aStyleName = ScResId( STR_STYLENAME_STANDARD );
534 else
536 OUStringBuffer aBuf(maStyleNamePrefix1);
537 if( nStyleId < SAL_N_ELEMENTS( ppcStyleNames ) )
538 aBuf.appendAscii(ppcStyleNames[nStyleId]);
539 else if (!rName.isEmpty())
540 aBuf.append(rName);
541 else
542 aBuf.append(static_cast<sal_Int32>(nStyleId));
544 if( (nStyleId == EXC_STYLE_ROWLEVEL) || (nStyleId == EXC_STYLE_COLLEVEL) )
545 aBuf.append(static_cast<sal_Int32>(nLevel+1));
547 aStyleName = aBuf.makeStringAndClear();
550 return aStyleName;
553 bool XclTools::IsBuiltInStyleName( const OUString& rStyleName, sal_uInt8* pnStyleId, sal_Int32* pnNextChar )
555 // "Default" becomes "Normal"
556 if (rStyleName == ScResId(STR_STYLENAME_STANDARD))
558 if( pnStyleId ) *pnStyleId = EXC_STYLE_NORMAL;
559 if( pnNextChar ) *pnNextChar = rStyleName.getLength();
560 return true;
563 // try the other built-in styles
564 sal_uInt8 nFoundId = 0;
565 sal_Int32 nNextChar = 0;
567 sal_Int32 nPrefixLen = 0;
568 if( rStyleName.startsWithIgnoreAsciiCase( maStyleNamePrefix1 ) )
569 nPrefixLen = strlen(maStyleNamePrefix1);
570 else if( rStyleName.startsWithIgnoreAsciiCase( maStyleNamePrefix2 ) )
571 nPrefixLen = strlen(maStyleNamePrefix2);
572 if( nPrefixLen > 0 )
574 for( sal_uInt8 nId = 0; nId < SAL_N_ELEMENTS( ppcStyleNames ); ++nId )
576 if( nId != EXC_STYLE_NORMAL )
578 OUString aShortName = OUString::createFromAscii(ppcStyleNames[nId]);
579 if( rStyleName.matchIgnoreAsciiCase( aShortName, nPrefixLen ) &&
580 (nNextChar < nPrefixLen + aShortName.getLength()))
582 nFoundId = nId;
583 nNextChar = nPrefixLen + aShortName.getLength();
589 if( nNextChar > 0 )
591 if( pnStyleId ) *pnStyleId = nFoundId;
592 if( pnNextChar ) *pnNextChar = nNextChar;
593 return true;
596 if( pnStyleId ) *pnStyleId = EXC_STYLE_USERDEF;
597 if( pnNextChar ) *pnNextChar = 0;
598 return nPrefixLen > 0; // also return true for unknown built-in styles
601 bool XclTools::GetBuiltInStyleId( sal_uInt8& rnStyleId, sal_uInt8& rnLevel, const OUString& rStyleName )
603 sal_uInt8 nStyleId;
604 sal_Int32 nNextChar;
605 if( IsBuiltInStyleName( rStyleName, &nStyleId, &nNextChar ) && (nStyleId != EXC_STYLE_USERDEF) )
607 if( (nStyleId == EXC_STYLE_ROWLEVEL) || (nStyleId == EXC_STYLE_COLLEVEL) )
609 OUString aLevel = rStyleName.copy(nNextChar);
610 sal_Int32 nLevel = aLevel.toInt32();
611 if (OUString::number(nLevel) == aLevel && nLevel > 0 && nLevel <= EXC_STYLE_LEVELCOUNT)
613 rnStyleId = nStyleId;
614 rnLevel = static_cast< sal_uInt8 >( nLevel - 1 );
615 return true;
618 else if( rStyleName.getLength() == nNextChar )
620 rnStyleId = nStyleId;
621 rnLevel = EXC_STYLE_NOLEVEL;
622 return true;
626 rnStyleId = EXC_STYLE_USERDEF;
627 rnLevel = EXC_STYLE_NOLEVEL;
628 return false;
631 // conditional formatting style names
633 static const char maCFStyleNamePrefix1[] = "Excel_CondFormat_"; /// Prefix for cond. formatting style names.
634 static const char maCFStyleNamePrefix2[] = "ConditionalStyle_"; /// Prefix for cond. formatting style names from OOX filter.
636 OUString XclTools::GetCondFormatStyleName( SCTAB nScTab, sal_Int32 nFormat, sal_uInt16 nCondition )
638 return maCFStyleNamePrefix1 +
639 OUString::number(static_cast<sal_Int32>(nScTab+1)) +
640 "_" +
641 OUString::number(static_cast<sal_Int32>(nFormat+1)) +
642 "_" +
643 OUString::number(static_cast<sal_Int32>(nCondition+1));
646 bool XclTools::IsCondFormatStyleName( const OUString& rStyleName )
648 if( rStyleName.startsWithIgnoreAsciiCase( maCFStyleNamePrefix1 ) )
649 return true;
651 if( rStyleName.startsWithIgnoreAsciiCase( maCFStyleNamePrefix2 ) )
652 return true;
654 return false;
657 // stream handling
659 void XclTools::SkipSubStream( XclImpStream& rStrm )
661 bool bLoop = true;
662 while( bLoop && rStrm.StartNextRecord() )
664 sal_uInt16 nRecId = rStrm.GetRecId();
665 bLoop = nRecId != EXC_ID_EOF;
666 if( (nRecId == EXC_ID2_BOF) || (nRecId == EXC_ID3_BOF) || (nRecId == EXC_ID4_BOF) || (nRecId == EXC_ID5_BOF) )
667 SkipSubStream( rStrm );
671 // Basic macro names
673 static const char maSbMacroPrefix[] = "vnd.sun.star.script:"; /// Prefix for StarBasic macros.
674 static const char maSbMacroSuffix[] = "?language=Basic&location=document"; /// Suffix for StarBasic macros.
676 OUString XclTools::GetSbMacroUrl( const OUString& rMacroName, SfxObjectShell* pDocShell )
678 OSL_ENSURE( !rMacroName.isEmpty(), "XclTools::GetSbMacroUrl - macro name is empty" );
679 ::ooo::vba::MacroResolvedInfo aMacroInfo = ::ooo::vba::resolveVBAMacro( pDocShell, rMacroName );
680 if( aMacroInfo.mbFound )
681 return ::ooo::vba::makeMacroURL( aMacroInfo.msResolvedMacro );
682 return OUString();
685 OUString XclTools::GetXclMacroName( const OUString& rSbMacroUrl )
687 sal_Int32 nSbMacroUrlLen = rSbMacroUrl.getLength();
688 sal_Int32 nMacroNameLen = nSbMacroUrlLen - strlen(maSbMacroPrefix) - strlen(maSbMacroSuffix);
689 if( (nMacroNameLen > 0) && rSbMacroUrl.startsWithIgnoreAsciiCase( maSbMacroPrefix ) &&
690 rSbMacroUrl.endsWithIgnoreAsciiCase( maSbMacroSuffix ) )
692 sal_Int32 nPrjDot = rSbMacroUrl.indexOf( '.', strlen(maSbMacroPrefix) ) + 1;
693 return rSbMacroUrl.copy( nPrjDot, nSbMacroUrlLen - nPrjDot - strlen(maSbMacroSuffix) );
695 return OUString();
698 // read/write colors
700 XclImpStream& operator>>( XclImpStream& rStrm, Color& rColor )
702 sal_uInt8 nR = rStrm.ReaduInt8();
703 sal_uInt8 nG = rStrm.ReaduInt8();
704 sal_uInt8 nB = rStrm.ReaduInt8();
705 rStrm.Ignore( 1 );//nD
706 rColor = Color( nR, nG, nB );
707 return rStrm;
710 XclExpStream& operator<<( XclExpStream& rStrm, const Color& rColor )
712 return rStrm << rColor.GetRed() << rColor.GetGreen() << rColor.GetBlue() << sal_uInt8( 0 );
715 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */