bump product version to 4.1.6.2
[LibreOffice.git] / sc / source / filter / excel / xltools.cxx
blob3538ddec7125af9d195dec5d0547beba0c88b97a
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 .
21 #include <algorithm>
22 #include <math.h>
23 #include <sal/mathconf.h>
24 #include <unotools/fontcvt.hxx>
25 #include <sfx2/objsh.hxx>
26 #include <sal/macros.h>
27 #include <editeng/editstat.hxx>
28 #include <filter/msfilter/msvbahelper.hxx>
29 #include "xestream.hxx"
30 #include "document.hxx"
31 #include "docuno.hxx"
32 #include "editutil.hxx"
33 #include "formula/errorcodes.hxx"
34 #include "globstr.hrc"
35 #include "xlstyle.hxx"
36 #include "xlname.hxx"
37 #include "xistream.hxx"
38 #include "xiroot.hxx"
39 #include "xltools.hxx"
42 // GUID import/export =========================================================
44 XclGuid::XclGuid()
46 ::std::fill( mpnData, STATIC_ARRAY_END( mpnData ), 0 );
49 XclGuid::XclGuid(
50 sal_uInt32 nData1, sal_uInt16 nData2, sal_uInt16 nData3,
51 sal_uInt8 nData41, sal_uInt8 nData42, sal_uInt8 nData43, sal_uInt8 nData44,
52 sal_uInt8 nData45, sal_uInt8 nData46, sal_uInt8 nData47, sal_uInt8 nData48 )
54 // convert to little endian -> makes streaming easy
55 UInt32ToSVBT32( nData1, mpnData );
56 ShortToSVBT16( nData2, mpnData + 4 );
57 ShortToSVBT16( nData3, mpnData + 6 );
58 mpnData[ 8 ] = nData41;
59 mpnData[ 9 ] = nData42;
60 mpnData[ 10 ] = nData43;
61 mpnData[ 11 ] = nData44;
62 mpnData[ 12 ] = nData45;
63 mpnData[ 13 ] = nData46;
64 mpnData[ 14 ] = nData47;
65 mpnData[ 15 ] = nData48;
68 bool operator==( const XclGuid& rCmp1, const XclGuid& rCmp2 )
70 return ::std::equal( rCmp1.mpnData, STATIC_ARRAY_END( rCmp1.mpnData ), rCmp2.mpnData );
73 bool operator<( const XclGuid& rCmp1, const XclGuid& rCmp2 )
75 return ::std::lexicographical_compare(
76 rCmp1.mpnData, STATIC_ARRAY_END( rCmp1.mpnData ),
77 rCmp2.mpnData, STATIC_ARRAY_END( rCmp2.mpnData ) );
80 XclImpStream& operator>>( XclImpStream& rStrm, XclGuid& rGuid )
82 rStrm.Read( rGuid.mpnData, 16 ); // mpnData always in little endian
83 return rStrm;
86 XclExpStream& operator<<( XclExpStream& rStrm, const XclGuid& rGuid )
88 rStrm.Write( rGuid.mpnData, 16 ); // mpnData already in little endian
89 return rStrm;
92 // Excel Tools ================================================================
94 // GUID's ---------------------------------------------------------------------
96 const XclGuid XclTools::maGuidStdLink(
97 0x79EAC9D0, 0xBAF9, 0x11CE, 0x8C, 0x82, 0x00, 0xAA, 0x00, 0x4B, 0xA9, 0x0B );
99 const XclGuid XclTools::maGuidUrlMoniker(
100 0x79EAC9E0, 0xBAF9, 0x11CE, 0x8C, 0x82, 0x00, 0xAA, 0x00, 0x4B, 0xA9, 0x0B );
102 const XclGuid XclTools::maGuidFileMoniker(
103 0x00000303, 0x0000, 0x0000, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46 );
105 // numeric conversion ---------------------------------------------------------
107 double XclTools::GetDoubleFromRK( sal_Int32 nRKValue )
109 union
111 double fVal;
112 sal_math_Double smD;
114 fVal = 0.0;
116 if( ::get_flag( nRKValue, EXC_RK_INTFLAG ) )
118 sal_Int32 nTemp = nRKValue >> 2;
119 ::set_flag< sal_Int32 >( nTemp, 0xE0000000, nRKValue < 0 );
120 fVal = nTemp;
122 else
124 smD.w32_parts.msw = nRKValue & EXC_RK_VALUEMASK;
127 if( ::get_flag( nRKValue, EXC_RK_100FLAG ) )
128 fVal /= 100.0;
130 return fVal;
133 bool XclTools::GetRKFromDouble( sal_Int32& rnRKValue, double fValue )
135 double fFrac, fInt;
137 // integer
138 fFrac = modf( fValue, &fInt );
139 if( (fFrac == 0.0) && (fInt >= -536870912.0) && (fInt <= 536870911.0) ) // 2^29
141 rnRKValue = static_cast< sal_Int32 >( fInt );
142 rnRKValue <<= 2;
143 rnRKValue |= EXC_RK_INT;
144 return true;
147 // integer/100
148 fFrac = modf( fValue * 100.0, &fInt );
149 if( (fFrac == 0.0) && (fInt >= -536870912.0) && (fInt <= 536870911.0) )
151 rnRKValue = static_cast< sal_Int32 >( fInt );
152 rnRKValue <<= 2;
153 rnRKValue |= EXC_RK_INT100;
154 return true;
157 // double
158 return false;
161 sal_Int32 XclTools::GetScRotation( sal_uInt16 nXclRot, sal_Int32 nRotForStacked )
163 if( nXclRot == EXC_ROT_STACKED )
164 return nRotForStacked;
165 OSL_ENSURE( nXclRot <= 180, "XclTools::GetScRotation - illegal rotation angle" );
166 return static_cast< sal_Int32 >( (nXclRot <= 180) ? (100 * ((nXclRot > 90) ? (450 - nXclRot) : nXclRot)) : 0 );
169 sal_uInt8 XclTools::GetXclRotation( sal_Int32 nScRot )
171 sal_Int32 nXclRot = nScRot / 100;
172 if( (0 <= nXclRot) && (nXclRot <= 90) )
173 return static_cast< sal_uInt8 >( nXclRot );
174 if( nXclRot < 180 )
175 return static_cast< sal_uInt8 >( 270 - nXclRot );
176 if( nXclRot < 270 )
177 return static_cast< sal_uInt8 >( nXclRot - 180 );
178 if( nXclRot < 360 )
179 return static_cast< sal_uInt8 >( 450 - nXclRot );
180 return 0;
183 sal_uInt8 XclTools::GetXclRotFromOrient( sal_uInt8 nXclOrient )
185 switch( nXclOrient )
187 case EXC_ORIENT_NONE: return EXC_ROT_NONE;
188 case EXC_ORIENT_STACKED: return EXC_ROT_STACKED;
189 case EXC_ORIENT_90CCW: return EXC_ROT_90CCW;
190 case EXC_ORIENT_90CW: return EXC_ROT_90CW;
191 default: OSL_FAIL( "XclTools::GetXclRotFromOrient - unknown text orientation" );
193 return EXC_ROT_NONE;
196 sal_uInt8 XclTools::GetXclOrientFromRot( sal_uInt16 nXclRot )
198 if( nXclRot == EXC_ROT_STACKED )
199 return EXC_ORIENT_STACKED;
200 OSL_ENSURE( nXclRot <= 180, "XclTools::GetXclOrientFromRot - unknown text rotation" );
201 if( (45 < nXclRot) && (nXclRot <= 90) )
202 return EXC_ORIENT_90CCW;
203 if( (135 < nXclRot) && (nXclRot <= 180) )
204 return EXC_ORIENT_90CW;
205 return EXC_ORIENT_NONE;
208 sal_uInt8 XclTools::GetXclErrorCode( sal_uInt16 nScError )
210 using namespace ScErrorCodes;
211 switch( nScError )
213 case errIllegalArgument: return EXC_ERR_VALUE;
214 case errIllegalFPOperation: return EXC_ERR_NUM; // maybe DIV/0 or NUM...
215 case errDivisionByZero: return EXC_ERR_DIV0;
216 case errIllegalParameter: return EXC_ERR_VALUE;
217 case errPairExpected: return EXC_ERR_VALUE;
218 case errOperatorExpected: return EXC_ERR_VALUE;
219 case errVariableExpected: return EXC_ERR_VALUE;
220 case errParameterExpected: return EXC_ERR_VALUE;
221 case errNoValue: return EXC_ERR_VALUE;
222 case errCircularReference: return EXC_ERR_VALUE;
223 case errNoCode: return EXC_ERR_NULL;
224 case errNoRef: return EXC_ERR_REF;
225 case errNoName: return EXC_ERR_NAME;
226 case errNoAddin: return EXC_ERR_NAME;
227 case errNoMacro: return EXC_ERR_NAME;
228 case NOTAVAILABLE: return EXC_ERR_NA;
230 return EXC_ERR_NA;
233 sal_uInt16 XclTools::GetScErrorCode( sal_uInt8 nXclError )
235 using namespace ScErrorCodes;
236 switch( nXclError )
238 case EXC_ERR_NULL: return errNoCode;
239 case EXC_ERR_DIV0: return errDivisionByZero;
240 case EXC_ERR_VALUE: return errNoValue;
241 case EXC_ERR_REF: return errNoRef;
242 case EXC_ERR_NAME: return errNoName;
243 case EXC_ERR_NUM: return errIllegalFPOperation;
244 case EXC_ERR_NA: return NOTAVAILABLE;
245 default: OSL_FAIL( "XclTools::GetScErrorCode - unknown error code" );
247 return NOTAVAILABLE;
250 double XclTools::ErrorToDouble( sal_uInt8 nXclError )
252 union
254 double fVal;
255 sal_math_Double smD;
257 ::rtl::math::setNan( &fVal );
258 smD.nan_parts.fraction_lo = GetScErrorCode( nXclError );
259 return fVal;
262 XclBoolError XclTools::ErrorToEnum( double& rfDblValue, sal_uInt8 bErrOrBool, sal_uInt8 nValue )
264 XclBoolError eType;
265 if( bErrOrBool )
267 // error value
268 switch( nValue )
270 case EXC_ERR_NULL: eType = xlErrNull; break;
271 case EXC_ERR_DIV0: eType = xlErrDiv0; break;
272 case EXC_ERR_VALUE: eType = xlErrValue; break;
273 case EXC_ERR_REF: eType = xlErrRef; break;
274 case EXC_ERR_NAME: eType = xlErrName; break;
275 case EXC_ERR_NUM: eType = xlErrNum; break;
276 case EXC_ERR_NA: eType = xlErrNA; break;
277 default: eType = xlErrUnknown;
279 rfDblValue = 0.0;
281 else
283 // Boolean value
284 eType = nValue ? xlErrTrue : xlErrFalse;
285 rfDblValue = nValue ? 1.0 : 0.0;
287 return eType;
290 sal_uInt16 XclTools::GetTwipsFromInch( double fInches )
292 return static_cast< sal_uInt16 >(
293 ::std::min( ::std::max( (fInches * EXC_TWIPS_PER_INCH + 0.5), 0.0 ), 65535.0 ) );
296 sal_uInt16 XclTools::GetTwipsFromHmm( sal_Int32 nHmm )
298 return GetTwipsFromInch( static_cast< double >( nHmm ) / 1000.0 / CM_PER_INCH );
301 double XclTools::GetInchFromTwips( sal_Int32 nTwips )
303 return static_cast< double >( nTwips ) / EXC_TWIPS_PER_INCH;
306 double XclTools::GetInchFromHmm( sal_Int32 nHmm )
308 return GetInchFromTwips( GetTwipsFromHmm( nHmm ) );
311 sal_Int32 XclTools::GetHmmFromInch( double fInches )
313 return static_cast< sal_Int32 >( fInches * CM_PER_INCH * 1000 );
316 sal_Int32 XclTools::GetHmmFromTwips( sal_Int32 nTwips )
318 return GetHmmFromInch( GetInchFromTwips( nTwips ) );
321 sal_uInt16 XclTools::GetScColumnWidth( sal_uInt16 nXclWidth, long nScCharWidth )
323 double fScWidth = static_cast< double >( nXclWidth ) / 256.0 * nScCharWidth + 0.5;
324 return limit_cast< sal_uInt16 >( fScWidth );
327 sal_uInt16 XclTools::GetXclColumnWidth( sal_uInt16 nScWidth, long nScCharWidth )
329 double fXclWidth = static_cast< double >( nScWidth ) * 256.0 / nScCharWidth + 0.5;
330 return limit_cast< sal_uInt16 >( fXclWidth );
333 double XclTools::GetXclDefColWidthCorrection( long nXclDefFontHeight )
335 return 40960.0 / ::std::max( nXclDefFontHeight - 15L, 60L ) + 50.0;
338 // formatting -----------------------------------------------------------------
340 Color XclTools::GetPatternColor( const Color& rPattColor, const Color& rBackColor, sal_uInt16 nXclPattern )
342 // 0x00 == 0% transparence (full rPattColor)
343 // 0x80 == 100% transparence (full rBackColor)
344 static const sal_uInt8 pnRatioTable[] =
346 0x80, 0x00, 0x40, 0x20, 0x60, 0x40, 0x40, 0x40, // 00 - 07
347 0x40, 0x40, 0x20, 0x60, 0x60, 0x60, 0x60, 0x48, // 08 - 15
348 0x50, 0x70, 0x78 // 16 - 18
350 return (nXclPattern < SAL_N_ELEMENTS( pnRatioTable )) ?
351 ScfTools::GetMixedColor( rPattColor, rBackColor, pnRatioTable[ nXclPattern ] ) : rPattColor;
354 // text encoding --------------------------------------------------------------
356 namespace {
358 const struct XclCodePageEntry
360 sal_uInt16 mnCodePage;
361 rtl_TextEncoding meTextEnc;
363 pCodePageTable[] =
365 { 437, RTL_TEXTENCODING_IBM_437 }, // OEM US
366 // { 720, RTL_TEXTENCODING_IBM_720 }, // OEM Arabic
367 { 737, RTL_TEXTENCODING_IBM_737 }, // OEM Greek
368 { 775, RTL_TEXTENCODING_IBM_775 }, // OEM Baltic
369 { 850, RTL_TEXTENCODING_IBM_850 }, // OEM Latin I
370 { 852, RTL_TEXTENCODING_IBM_852 }, // OEM Latin II (Central European)
371 { 855, RTL_TEXTENCODING_IBM_855 }, // OEM Cyrillic
372 { 857, RTL_TEXTENCODING_IBM_857 }, // OEM Turkish
373 // { 858, RTL_TEXTENCODING_IBM_858 }, // OEM Multilingual Latin I with Euro
374 { 860, RTL_TEXTENCODING_IBM_860 }, // OEM Portugese
375 { 861, RTL_TEXTENCODING_IBM_861 }, // OEM Icelandic
376 { 862, RTL_TEXTENCODING_IBM_862 }, // OEM Hebrew
377 { 863, RTL_TEXTENCODING_IBM_863 }, // OEM Canadian (French)
378 { 864, RTL_TEXTENCODING_IBM_864 }, // OEM Arabic
379 { 865, RTL_TEXTENCODING_IBM_865 }, // OEM Nordic
380 { 866, RTL_TEXTENCODING_IBM_866 }, // OEM Cyrillic (Russian)
381 { 869, RTL_TEXTENCODING_IBM_869 }, // OEM Greek (Modern)
382 { 874, RTL_TEXTENCODING_MS_874 }, // MS Windows Thai
383 { 932, RTL_TEXTENCODING_MS_932 }, // MS Windows Japanese Shift-JIS
384 { 936, RTL_TEXTENCODING_MS_936 }, // MS Windows Chinese Simplified GBK
385 { 949, RTL_TEXTENCODING_MS_949 }, // MS Windows Korean (Wansung)
386 { 950, RTL_TEXTENCODING_MS_950 }, // MS Windows Chinese Traditional BIG5
387 { 1200, RTL_TEXTENCODING_DONTKNOW }, // Unicode (BIFF8) - return *_DONTKNOW to preserve old code page
388 { 1250, RTL_TEXTENCODING_MS_1250 }, // MS Windows Latin II (Central European)
389 { 1251, RTL_TEXTENCODING_MS_1251 }, // MS Windows Cyrillic
390 { 1252, RTL_TEXTENCODING_MS_1252 }, // MS Windows Latin I (BIFF4-BIFF8)
391 { 1253, RTL_TEXTENCODING_MS_1253 }, // MS Windows Greek
392 { 1254, RTL_TEXTENCODING_MS_1254 }, // MS Windows Turkish
393 { 1255, RTL_TEXTENCODING_MS_1255 }, // MS Windows Hebrew
394 { 1256, RTL_TEXTENCODING_MS_1256 }, // MS Windows Arabic
395 { 1257, RTL_TEXTENCODING_MS_1257 }, // MS Windows Baltic
396 { 1258, RTL_TEXTENCODING_MS_1258 }, // MS Windows Vietnamese
397 { 1361, RTL_TEXTENCODING_MS_1361 }, // MS Windows Korean (Johab)
398 { 10000, RTL_TEXTENCODING_APPLE_ROMAN }, // Apple Roman
399 { 32768, RTL_TEXTENCODING_APPLE_ROMAN }, // Apple Roman
400 { 32769, RTL_TEXTENCODING_MS_1252 } // MS Windows Latin I (BIFF2-BIFF3)
402 const XclCodePageEntry* const pCodePageTableEnd = STATIC_ARRAY_END( pCodePageTable );
404 struct XclCodePageEntry_CPPred
406 inline explicit XclCodePageEntry_CPPred( sal_uInt16 nCodePage ) : mnCodePage( nCodePage ) {}
407 inline bool operator()( const XclCodePageEntry& rEntry ) const { return rEntry.mnCodePage == mnCodePage; }
408 sal_uInt16 mnCodePage;
411 struct XclCodePageEntry_TEPred
413 inline explicit XclCodePageEntry_TEPred( rtl_TextEncoding eTextEnc ) : meTextEnc( eTextEnc ) {}
414 inline bool operator()( const XclCodePageEntry& rEntry ) const { return rEntry.meTextEnc == meTextEnc; }
415 rtl_TextEncoding meTextEnc;
418 } // namespace
420 rtl_TextEncoding XclTools::GetTextEncoding( sal_uInt16 nCodePage )
422 const XclCodePageEntry* pEntry = ::std::find_if( pCodePageTable, pCodePageTableEnd, XclCodePageEntry_CPPred( nCodePage ) );
423 if( pEntry == pCodePageTableEnd )
425 OSL_TRACE( "XclTools::GetTextEncoding - unknown code page: 0x%04hX (%d)", nCodePage, nCodePage );
426 return RTL_TEXTENCODING_DONTKNOW;
428 return pEntry->meTextEnc;
431 sal_uInt16 XclTools::GetXclCodePage( rtl_TextEncoding eTextEnc )
433 if( eTextEnc == RTL_TEXTENCODING_UNICODE )
434 return 1200; // for BIFF8
436 const XclCodePageEntry* pEntry = ::std::find_if( pCodePageTable, pCodePageTableEnd, XclCodePageEntry_TEPred( eTextEnc ) );
437 if( pEntry == pCodePageTableEnd )
439 OSL_TRACE( "XclTools::GetXclCodePage - unsupported text encoding: %d", eTextEnc );
440 return 1252;
442 return pEntry->mnCodePage;
445 // font names -----------------------------------------------------------------
447 OUString XclTools::GetXclFontName( const OUString& rFontName )
449 // substitute with MS fonts
450 OUString aNewName = GetSubsFontName(rFontName, SUBSFONT_ONLYONE | SUBSFONT_MS);
451 return aNewName.isEmpty() ? rFontName : aNewName;
454 // built-in defined names -----------------------------------------------------
456 const OUString XclTools::maDefNamePrefix( "Excel_BuiltIn_" );
458 const OUString XclTools::maDefNamePrefixXml ( "_xlnm." );
460 static const sal_Char* const ppcDefNames[] =
462 "Consolidate_Area",
463 "Auto_Open",
464 "Auto_Close",
465 "Extract",
466 "Database",
467 "Criteria",
468 "Print_Area",
469 "Print_Titles",
470 "Recorder",
471 "Data_Form",
472 "Auto_Activate",
473 "Auto_Deactivate",
474 "Sheet_Title",
475 "_FilterDatabase"
478 OUString XclTools::GetXclBuiltInDefName( sal_Unicode cBuiltIn )
480 OSL_ENSURE( SAL_N_ELEMENTS( ppcDefNames ) == EXC_BUILTIN_UNKNOWN,
481 "XclTools::GetXclBuiltInDefName - built-in defined name list modified" );
483 if( cBuiltIn < SAL_N_ELEMENTS( ppcDefNames ) )
484 return OUString::createFromAscii(ppcDefNames[cBuiltIn]);
485 else
486 return OUString::number(cBuiltIn);
489 OUString XclTools::GetBuiltInDefName( sal_Unicode cBuiltIn )
491 OUStringBuffer aBuf(maDefNamePrefix);
492 aBuf.append(GetXclBuiltInDefName(cBuiltIn));
493 return aBuf.makeStringAndClear();
496 OUString XclTools::GetBuiltInDefNameXml( sal_Unicode cBuiltIn )
498 OUStringBuffer aBuf(maDefNamePrefixXml);
499 aBuf.append(GetXclBuiltInDefName(cBuiltIn));
500 return aBuf.makeStringAndClear();
503 sal_Unicode XclTools::GetBuiltInDefNameIndex( const OUString& rDefName )
505 sal_Int32 nPrefixLen = maDefNamePrefix.getLength();
506 if( String(rDefName).EqualsIgnoreCaseAscii( maDefNamePrefix, 0, nPrefixLen ) )
508 for( sal_Unicode cBuiltIn = 0; cBuiltIn < EXC_BUILTIN_UNKNOWN; ++cBuiltIn )
510 OUString aBuiltInName(GetXclBuiltInDefName(cBuiltIn));
511 sal_Int32 nBuiltInLen = aBuiltInName.getLength();
512 if( String(rDefName).EqualsIgnoreCaseAscii( aBuiltInName, nPrefixLen, nBuiltInLen ) )
514 // name can be followed by underline or space character
515 xub_StrLen nNextCharPos = nPrefixLen + nBuiltInLen;
516 sal_Unicode cNextChar = (rDefName.getLength() > nNextCharPos) ? rDefName.getStr()[nNextCharPos] : '\0';
517 if( (cNextChar == '\0') || (cNextChar == ' ') || (cNextChar == '_') )
518 return cBuiltIn;
522 return EXC_BUILTIN_UNKNOWN;
525 // built-in style names -------------------------------------------------------
527 const OUString XclTools::maStyleNamePrefix1( "Excel_BuiltIn_" );
528 const OUString XclTools::maStyleNamePrefix2( "Excel Built-in " );
530 static const sal_Char* const ppcStyleNames[] =
532 "", // "Normal" not used directly, but localized "Default"
533 "RowLevel_", // outline level will be appended
534 "ColumnLevel_", // outline level will be appended
535 "Comma",
536 "Currency",
537 "Percent",
538 "Comma_0",
539 "Currency_0",
540 "Hyperlink",
541 "Followed_Hyperlink"
544 OUString XclTools::GetBuiltInStyleName( sal_uInt8 nStyleId, const OUString& rName, sal_uInt8 nLevel )
546 OUString aStyleName;
548 if( nStyleId == EXC_STYLE_NORMAL ) // "Normal" becomes "Default" style
550 aStyleName = ScGlobal::GetRscString( STR_STYLENAME_STANDARD );
552 else
554 OUStringBuffer aBuf(maStyleNamePrefix1);
555 if( nStyleId < SAL_N_ELEMENTS( ppcStyleNames ) )
556 aBuf.appendAscii(ppcStyleNames[nStyleId]);
557 else if (!rName.isEmpty())
558 aBuf.append(rName);
559 else
560 aBuf.append(static_cast<sal_Int32>(nStyleId));
562 if( (nStyleId == EXC_STYLE_ROWLEVEL) || (nStyleId == EXC_STYLE_COLLEVEL) )
563 aBuf.append(static_cast<sal_Int32>(nLevel+1));
565 aStyleName = aBuf.makeStringAndClear();
568 return aStyleName;
571 bool XclTools::IsBuiltInStyleName( const OUString& rStyleName, sal_uInt8* pnStyleId, sal_Int32* pnNextChar )
573 // "Default" becomes "Normal"
574 if (rStyleName.equals(ScGlobal::GetRscString(STR_STYLENAME_STANDARD)))
576 if( pnStyleId ) *pnStyleId = EXC_STYLE_NORMAL;
577 if( pnNextChar ) *pnNextChar = rStyleName.getLength();
578 return true;
581 // try the other built-in styles
582 sal_uInt8 nFoundId = 0;
583 sal_Int32 nNextChar = 0;
585 sal_Int32 nPrefixLen = 0;
586 if( String(rStyleName).EqualsIgnoreCaseAscii( maStyleNamePrefix1, 0, maStyleNamePrefix1.getLength() ) )
587 nPrefixLen = maStyleNamePrefix1.getLength();
588 else if( String(rStyleName).EqualsIgnoreCaseAscii( maStyleNamePrefix2, 0, maStyleNamePrefix2.getLength() ) )
589 nPrefixLen = maStyleNamePrefix2.getLength();
590 if( nPrefixLen > 0 )
592 for( sal_uInt8 nId = 0; nId < SAL_N_ELEMENTS( ppcStyleNames ); ++nId )
594 if( nId != EXC_STYLE_NORMAL )
596 OUString aShortName = OUString::createFromAscii(ppcStyleNames[nId]);
597 if( String(rStyleName).EqualsIgnoreCaseAscii( aShortName, nPrefixLen, aShortName.getLength() ) &&
598 (nNextChar < nPrefixLen + aShortName.getLength()))
600 nFoundId = nId;
601 nNextChar = nPrefixLen + aShortName.getLength();
607 if( nNextChar > 0 )
609 if( pnStyleId ) *pnStyleId = nFoundId;
610 if( pnNextChar ) *pnNextChar = nNextChar;
611 return true;
614 if( pnStyleId ) *pnStyleId = EXC_STYLE_USERDEF;
615 if( pnNextChar ) *pnNextChar = 0;
616 return nPrefixLen > 0; // also return true for unknown built-in styles
619 bool XclTools::GetBuiltInStyleId( sal_uInt8& rnStyleId, sal_uInt8& rnLevel, const OUString& rStyleName )
621 sal_uInt8 nStyleId;
622 sal_Int32 nNextChar;
623 if( IsBuiltInStyleName( rStyleName, &nStyleId, &nNextChar ) && (nStyleId != EXC_STYLE_USERDEF) )
625 if( (nStyleId == EXC_STYLE_ROWLEVEL) || (nStyleId == EXC_STYLE_COLLEVEL) )
627 OUString aLevel = rStyleName.copy(nNextChar);
628 sal_Int32 nLevel = aLevel.toInt32();
629 if (OUString::valueOf(nLevel) == aLevel && nLevel > 0 && nLevel <= EXC_STYLE_LEVELCOUNT)
631 rnStyleId = nStyleId;
632 rnLevel = static_cast< sal_uInt8 >( nLevel - 1 );
633 return true;
636 else if( rStyleName.getLength() == nNextChar )
638 rnStyleId = nStyleId;
639 rnLevel = EXC_STYLE_NOLEVEL;
640 return true;
643 rnStyleId = EXC_STYLE_USERDEF;
644 rnLevel = EXC_STYLE_NOLEVEL;
645 return false;
648 // conditional formatting style names -----------------------------------------
650 const OUString XclTools::maCFStyleNamePrefix1( "Excel_CondFormat_" );
651 const OUString XclTools::maCFStyleNamePrefix2( "ConditionalStyle_" );
653 OUString XclTools::GetCondFormatStyleName( SCTAB nScTab, sal_Int32 nFormat, sal_uInt16 nCondition )
655 OUStringBuffer aBuf(maCFStyleNamePrefix1);
656 aBuf.append(static_cast<sal_Int32>(nScTab+1));
657 aBuf.append(sal_Unicode('_'));
658 aBuf.append(static_cast<sal_Int32>(nFormat+1));
659 aBuf.append(sal_Unicode('_'));
660 aBuf.append(static_cast<sal_Int32>(nCondition+1));
661 return aBuf.makeStringAndClear();
664 bool XclTools::IsCondFormatStyleName( const OUString& rStyleName )
666 if( String(rStyleName).EqualsIgnoreCaseAscii( maCFStyleNamePrefix1, 0, maCFStyleNamePrefix1.getLength() ) )
667 return true;
669 if( String(rStyleName).EqualsIgnoreCaseAscii( maCFStyleNamePrefix2, 0, maCFStyleNamePrefix2.getLength() ) )
670 return true;
672 return false;
675 // stream handling ------------------------------------------------------------
677 void XclTools::SkipSubStream( XclImpStream& rStrm )
679 bool bLoop = true;
680 while( bLoop && rStrm.StartNextRecord() )
682 sal_uInt16 nRecId = rStrm.GetRecId();
683 bLoop = nRecId != EXC_ID_EOF;
684 if( (nRecId == EXC_ID2_BOF) || (nRecId == EXC_ID3_BOF) || (nRecId == EXC_ID4_BOF) || (nRecId == EXC_ID5_BOF) )
685 SkipSubStream( rStrm );
689 // Basic macro names ----------------------------------------------------------
691 const OUString XclTools::maSbMacroPrefix( "vnd.sun.star.script:" );
692 const OUString XclTools::maSbMacroSuffix( "?language=Basic&location=document" );
694 OUString XclTools::GetSbMacroUrl( const OUString& rMacroName, SfxObjectShell* pDocShell )
696 OSL_ENSURE( !rMacroName.isEmpty(), "XclTools::GetSbMacroUrl - macro name is empty" );
697 ::ooo::vba::MacroResolvedInfo aMacroInfo = ::ooo::vba::resolveVBAMacro( pDocShell, rMacroName, false );
698 if( aMacroInfo.mbFound )
699 return ::ooo::vba::makeMacroURL( aMacroInfo.msResolvedMacro );
700 return OUString();
703 OUString XclTools::GetXclMacroName( const OUString& rSbMacroUrl )
705 sal_Int32 nSbMacroUrlLen = rSbMacroUrl.getLength();
706 sal_Int32 nMacroNameLen = nSbMacroUrlLen - maSbMacroPrefix.getLength() - maSbMacroSuffix.getLength();
707 if( (nMacroNameLen > 0) && rSbMacroUrl.matchIgnoreAsciiCase( maSbMacroPrefix, 0 ) &&
708 rSbMacroUrl.matchIgnoreAsciiCase( maSbMacroSuffix, nSbMacroUrlLen - maSbMacroSuffix.getLength() ) )
710 sal_Int32 nPrjDot = rSbMacroUrl.indexOf( '.', maSbMacroPrefix.getLength() ) + 1;
711 return rSbMacroUrl.copy( nPrjDot, nSbMacroUrlLen - nPrjDot - maSbMacroSuffix.getLength() );
713 return OUString();
716 // read/write colors ----------------------------------------------------------
718 XclImpStream& operator>>( XclImpStream& rStrm, Color& rColor )
720 sal_uInt8 nR, nG, nB, nD;
721 rStrm >> nR >> nG >> nB >> nD;
722 rColor.SetColor( RGB_COLORDATA( nR, nG, nB ) );
723 return rStrm;
726 XclExpStream& operator<<( XclExpStream& rStrm, const Color& rColor )
728 return rStrm << rColor.GetRed() << rColor.GetGreen() << rColor.GetBlue() << sal_uInt8( 0 );
731 // ============================================================================
733 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */