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 .
22 #include <string_view>
24 #include <o3tl/unit_conversion.hxx>
25 #include <sal/mathconf.h>
26 #include <sal/macros.h>
27 #include <sal/log.hxx>
28 #include <tools/solar.h>
29 #include <o3tl/string_view.hxx>
30 #include <unotools/fontdefs.hxx>
31 #include <filter/msfilter/msvbahelper.hxx>
32 #include <xestream.hxx>
33 #include <formula/errorcodes.hxx>
34 #include <globstr.hrc>
35 #include <scresid.hxx>
36 #include <xlstyle.hxx>
38 #include <xistream.hxx>
39 #include <xltools.hxx>
49 sal_uInt32 nData1
, sal_uInt16 nData2
, sal_uInt16 nData3
,
50 sal_uInt8 nData41
, sal_uInt8 nData42
, sal_uInt8 nData43
, sal_uInt8 nData44
,
51 sal_uInt8 nData45
, sal_uInt8 nData46
, sal_uInt8 nData47
, sal_uInt8 nData48
)
53 // convert to little endian -> makes streaming easy
54 UInt32ToSVBT32( nData1
, mpnData
);
55 ShortToSVBT16( nData2
, mpnData
+ 4 );
56 ShortToSVBT16( nData3
, mpnData
+ 6 );
57 mpnData
[ 8 ] = nData41
;
58 mpnData
[ 9 ] = nData42
;
59 mpnData
[ 10 ] = nData43
;
60 mpnData
[ 11 ] = nData44
;
61 mpnData
[ 12 ] = nData45
;
62 mpnData
[ 13 ] = nData46
;
63 mpnData
[ 14 ] = nData47
;
64 mpnData
[ 15 ] = nData48
;
67 bool operator==( const XclGuid
& rCmp1
, const XclGuid
& rCmp2
)
69 return ::std::equal( rCmp1
.mpnData
, std::end( rCmp1
.mpnData
), rCmp2
.mpnData
);
72 XclImpStream
& operator>>( XclImpStream
& rStrm
, XclGuid
& rGuid
)
74 rStrm
.Read( rGuid
.mpnData
, 16 ); // mpnData always in little endian
78 XclExpStream
& operator<<( XclExpStream
& rStrm
, const XclGuid
& rGuid
)
80 rStrm
.Write( rGuid
.mpnData
, 16 ); // mpnData already in little endian
87 const XclGuid
XclTools::maGuidStdLink(
88 0x79EAC9D0, 0xBAF9, 0x11CE, 0x8C, 0x82, 0x00, 0xAA, 0x00, 0x4B, 0xA9, 0x0B );
90 const XclGuid
XclTools::maGuidUrlMoniker(
91 0x79EAC9E0, 0xBAF9, 0x11CE, 0x8C, 0x82, 0x00, 0xAA, 0x00, 0x4B, 0xA9, 0x0B );
93 const XclGuid
XclTools::maGuidFileMoniker(
94 0x00000303, 0x0000, 0x0000, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46 );
98 double XclTools::GetDoubleFromRK( sal_Int32 nRKValue
)
100 sal_math_Double smD
{};
102 if( ::get_flag( nRKValue
, EXC_RK_INTFLAG
) )
104 sal_Int32 nTemp
= nRKValue
>> 2;
105 ::set_flag
< sal_Int32
>( nTemp
, 0xE0000000, nRKValue
< 0 );
110 smD
.w32_parts
.msw
= nRKValue
& EXC_RK_VALUEMASK
;
113 if( ::get_flag( nRKValue
, EXC_RK_100FLAG
) )
119 bool XclTools::GetRKFromDouble( sal_Int32
& rnRKValue
, double fValue
)
124 fFrac
= modf( fValue
, &fInt
);
125 if( (fFrac
== 0.0) && (fInt
>= -536870912.0) && (fInt
<= 536870911.0) ) // 2^29
128 = static_cast<sal_Int32
>(
129 static_cast<sal_uInt32
>(static_cast<sal_Int32
>(fInt
)) << 2)
135 fFrac
= modf( fValue
* 100.0, &fInt
);
136 if( (fFrac
== 0.0) && (fInt
>= -536870912.0) && (fInt
<= 536870911.0) )
139 = static_cast<sal_Int32
>(
140 static_cast<sal_uInt32
>(static_cast<sal_Int32
>(fInt
)) << 2)
149 Degree100
XclTools::GetScRotation( sal_uInt16 nXclRot
, Degree100 nRotForStacked
)
151 if( nXclRot
== EXC_ROT_STACKED
)
152 return nRotForStacked
;
153 OSL_ENSURE( nXclRot
<= 180, "XclTools::GetScRotation - illegal rotation angle" );
154 return Degree100(static_cast< sal_Int32
>( (nXclRot
<= 180) ? (100 * ((nXclRot
> 90) ? (450 - nXclRot
) : nXclRot
)) : 0 ));
157 sal_uInt8
XclTools::GetXclRotation( Degree100 nScRot
)
159 sal_Int32 nXclRot
= nScRot
.get() / 100;
160 if( (0 <= nXclRot
) && (nXclRot
<= 90) )
161 return static_cast< sal_uInt8
>( nXclRot
);
163 return static_cast< sal_uInt8
>( 270 - nXclRot
);
165 return static_cast< sal_uInt8
>( nXclRot
- 180 );
167 return static_cast< sal_uInt8
>( 450 - nXclRot
);
171 sal_uInt8
XclTools::GetXclRotFromOrient( sal_uInt8 nXclOrient
)
175 case EXC_ORIENT_NONE
: return EXC_ROT_NONE
;
176 case EXC_ORIENT_STACKED
: return EXC_ROT_STACKED
;
177 case EXC_ORIENT_90CCW
: return EXC_ROT_90CCW
;
178 case EXC_ORIENT_90CW
: return EXC_ROT_90CW
;
179 default: OSL_FAIL( "XclTools::GetXclRotFromOrient - unknown text orientation" );
184 sal_uInt8
XclTools::GetXclOrientFromRot( sal_uInt16 nXclRot
)
186 if( nXclRot
== EXC_ROT_STACKED
)
187 return EXC_ORIENT_STACKED
;
188 OSL_ENSURE( nXclRot
<= 180, "XclTools::GetXclOrientFromRot - unknown text rotation" );
189 if( (45 < nXclRot
) && (nXclRot
<= 90) )
190 return EXC_ORIENT_90CCW
;
191 if( (135 < nXclRot
) && (nXclRot
<= 180) )
192 return EXC_ORIENT_90CW
;
193 return EXC_ORIENT_NONE
;
196 sal_uInt8
XclTools::GetXclErrorCode( FormulaError nScError
)
200 case FormulaError::IllegalArgument
: return EXC_ERR_VALUE
;
201 case FormulaError::IllegalFPOperation
: return EXC_ERR_NUM
; // maybe DIV/0 or NUM...
202 case FormulaError::DivisionByZero
: return EXC_ERR_DIV0
;
203 case FormulaError::IllegalParameter
: return EXC_ERR_VALUE
;
204 case FormulaError::PairExpected
: return EXC_ERR_VALUE
;
205 case FormulaError::OperatorExpected
: return EXC_ERR_VALUE
;
206 case FormulaError::VariableExpected
: return EXC_ERR_VALUE
;
207 case FormulaError::ParameterExpected
: return EXC_ERR_VALUE
;
208 case FormulaError::NoValue
: return EXC_ERR_VALUE
;
209 case FormulaError::CircularReference
: return EXC_ERR_VALUE
;
210 case FormulaError::NoCode
: return EXC_ERR_NULL
;
211 case FormulaError::NoRef
: return EXC_ERR_REF
;
212 case FormulaError::NoName
: return EXC_ERR_NAME
;
213 case FormulaError::NoAddin
: return EXC_ERR_NAME
;
214 case FormulaError::NoMacro
: return EXC_ERR_NAME
;
215 case FormulaError::NotAvailable
: return EXC_ERR_NA
;
221 FormulaError
XclTools::GetScErrorCode( sal_uInt8 nXclError
)
225 case EXC_ERR_NULL
: return FormulaError::NoCode
;
226 case EXC_ERR_DIV0
: return FormulaError::DivisionByZero
;
227 case EXC_ERR_VALUE
: return FormulaError::NoValue
;
228 case EXC_ERR_REF
: return FormulaError::NoRef
;
229 case EXC_ERR_NAME
: return FormulaError::NoName
;
230 case EXC_ERR_NUM
: return FormulaError::IllegalFPOperation
;
231 case EXC_ERR_NA
: return FormulaError::NotAvailable
;
232 default: OSL_FAIL( "XclTools::GetScErrorCode - unknown error code" );
234 return FormulaError::NotAvailable
;
237 double XclTools::ErrorToDouble( sal_uInt8 nXclError
)
239 return CreateDoubleError(GetScErrorCode( nXclError
));
242 XclBoolError
XclTools::ErrorToEnum( double& rfDblValue
, bool bErrOrBool
, sal_uInt8 nValue
)
250 case EXC_ERR_NULL
: eType
= xlErrNull
; break;
251 case EXC_ERR_DIV0
: eType
= xlErrDiv0
; break;
252 case EXC_ERR_VALUE
: eType
= xlErrValue
; break;
253 case EXC_ERR_REF
: eType
= xlErrRef
; break;
254 case EXC_ERR_NAME
: eType
= xlErrName
; break;
255 case EXC_ERR_NUM
: eType
= xlErrNum
; break;
256 case EXC_ERR_NA
: eType
= xlErrNA
; break;
257 default: eType
= xlErrUnknown
;
264 eType
= nValue
? xlErrTrue
: xlErrFalse
;
265 rfDblValue
= nValue
? 1.0 : 0.0;
270 template <typename N
> static N
to(double f
) { return limit_cast
<N
>(f
+ 0.5); }
272 sal_uInt16
XclTools::GetTwipsFromInch( double fInches
)
274 return to
<sal_uInt16
>(o3tl::convert(fInches
, o3tl::Length::in
, o3tl::Length::twip
));
277 sal_uInt16
XclTools::GetTwipsFromHmm( sal_Int32 nHmm
)
279 return limit_cast
<sal_uInt16
>(o3tl::convert(nHmm
, o3tl::Length::mm100
, o3tl::Length::twip
));
282 double XclTools::GetInchFromTwips( sal_Int32 nTwips
)
284 return o3tl::convert
<double>(nTwips
, o3tl::Length::twip
, o3tl::Length::in
);
287 double XclTools::GetInchFromHmm( sal_Int32 nHmm
)
289 return o3tl::convert
<double>(nHmm
, o3tl::Length::mm100
, o3tl::Length::in
);
292 sal_Int32
XclTools::GetHmmFromInch( double fInches
)
294 return to
<sal_Int32
>(o3tl::convert(fInches
, o3tl::Length::in
, o3tl::Length::mm100
));
297 sal_Int32
XclTools::GetHmmFromTwips( sal_Int32 nTwips
)
299 return limit_cast
<sal_Int32
>(o3tl::convert(nTwips
, o3tl::Length::twip
, o3tl::Length::mm100
));
302 sal_uInt16
XclTools::GetScColumnWidth( sal_uInt16 nXclWidth
, tools::Long nScCharWidth
)
304 double fScWidth
= static_cast< double >( nXclWidth
) / 256.0 * nScCharWidth
- 0.5;
305 return limit_cast
< sal_uInt16
>( fScWidth
);
308 sal_uInt16
XclTools::GetXclColumnWidth( sal_uInt16 nScWidth
, tools::Long nScCharWidth
)
310 double fXclWidth
= ( static_cast< double >( nScWidth
) + 0.5 ) * 256.0 / nScCharWidth
;
311 return limit_cast
< sal_uInt16
>( fXclWidth
);
314 // takes font height in twips (1/20 pt = 1/1440 in)
315 // returns correction value in 1/256th of *digit width* of default font
316 double XclTools::GetXclDefColWidthCorrection( tools::Long nXclDefFontHeight
)
318 // Excel uses *max digit width of default font* (W) as cell width unit. Also it has 5-pixel
319 // "correction" to cell widths (ECMA-376-1:2016 18.3.1.81): each cell has 1-pixel padding, then
320 // 3 pixels for the border (which may be 1-pixel - hairline - then it will have 2 additional
321 // 1-pixel spacings from each side; or e.g. 2 hairlines with 1-pixel spacing in the middle; or
322 // thick 3-pixel). Obviously, correction size entirely depends on pixel size (and it is actually
323 // different in Excel on monitors with different resolution). Thus actual (displayed/printed)
324 // cell widths consist of X*W+5px; stored in file is the X (or X*256 if 1/256th of digit width
325 // units are used) value.
326 // This formula apparently converts this 5-pixel correction to 1/256th of digit width units.
327 // Looks like it is created from
329 // 5 * 256 * 1440 * 2.1333 / (96 * max(N-15, 60)) + 50.0
331 // where 5 - pixel correction; 256 - used to produce 1/256th of digit width; 1440 - used to
332 // convert font height N (in twips) to inches; 2.1333 - an (empirical?) quotient to convert
333 // font *height* into digit *width*; 96 - "standard" monitor resolution (DPI).
334 // Additionally the formula uses 15 (of unknown origin), 60 (minimal font height 3 pt), and
335 // 50.0 (also of unknown origin).
337 // TODO: convert this to take font digit width directly (and possibly DPI?), to avoid guessing
338 // the digit width and pixel size. Or DPI might stay 96, to not follow Excel dependency on DPI
339 // in addition to used font, and have absolute size of the correction fixed 5/96 in.
340 return 40960.0 / ::std::max( nXclDefFontHeight
- 15, tools::Long(60) ) + 50.0;
345 Color
XclTools::GetPatternColor( const Color
& rPattColor
, const Color
& rBackColor
, sal_uInt16 nXclPattern
)
347 // 0x00 == 0% transparence (full rPattColor)
348 // 0x80 == 100% transparence (full rBackColor)
349 static const sal_uInt8 pnRatioTable
[] =
351 0x80, 0x00, 0x40, 0x20, 0x60, 0x40, 0x40, 0x40, // 00 - 07
352 0x40, 0x40, 0x20, 0x60, 0x60, 0x60, 0x60, 0x48, // 08 - 15
353 0x50, 0x70, 0x78 // 16 - 18
355 return (nXclPattern
< std::size( pnRatioTable
)) ?
356 ScfTools::GetMixedColor( rPattColor
, rBackColor
, pnRatioTable
[ nXclPattern
] ) : rPattColor
;
363 const struct XclCodePageEntry
365 sal_uInt16 mnCodePage
;
366 rtl_TextEncoding meTextEnc
;
370 { 437, RTL_TEXTENCODING_IBM_437
}, // OEM US
371 // { 720, RTL_TEXTENCODING_IBM_720 }, // OEM Arabic
372 { 737, RTL_TEXTENCODING_IBM_737
}, // OEM Greek
373 { 775, RTL_TEXTENCODING_IBM_775
}, // OEM Baltic
374 { 850, RTL_TEXTENCODING_IBM_850
}, // OEM Latin I
375 { 852, RTL_TEXTENCODING_IBM_852
}, // OEM Latin II (Central European)
376 { 855, RTL_TEXTENCODING_IBM_855
}, // OEM Cyrillic
377 { 857, RTL_TEXTENCODING_IBM_857
}, // OEM Turkish
378 // { 858, RTL_TEXTENCODING_IBM_858 }, // OEM Multilingual Latin I with Euro
379 { 860, RTL_TEXTENCODING_IBM_860
}, // OEM Portuguese
380 { 861, RTL_TEXTENCODING_IBM_861
}, // OEM Icelandic
381 { 862, RTL_TEXTENCODING_IBM_862
}, // OEM Hebrew
382 { 863, RTL_TEXTENCODING_IBM_863
}, // OEM Canadian (French)
383 { 864, RTL_TEXTENCODING_IBM_864
}, // OEM Arabic
384 { 865, RTL_TEXTENCODING_IBM_865
}, // OEM Nordic
385 { 866, RTL_TEXTENCODING_IBM_866
}, // OEM Cyrillic (Russian)
386 { 869, RTL_TEXTENCODING_IBM_869
}, // OEM Greek (Modern)
387 { 874, RTL_TEXTENCODING_MS_874
}, // MS Windows Thai
388 { 932, RTL_TEXTENCODING_MS_932
}, // MS Windows Japanese Shift-JIS
389 { 936, RTL_TEXTENCODING_MS_936
}, // MS Windows Chinese Simplified GBK
390 { 949, RTL_TEXTENCODING_MS_949
}, // MS Windows Korean (Wansung)
391 { 950, RTL_TEXTENCODING_MS_950
}, // MS Windows Chinese Traditional BIG5
392 { 1200, RTL_TEXTENCODING_DONTKNOW
}, // Unicode (BIFF8) - return *_DONTKNOW to preserve old code page
393 { 1250, RTL_TEXTENCODING_MS_1250
}, // MS Windows Latin II (Central European)
394 { 1251, RTL_TEXTENCODING_MS_1251
}, // MS Windows Cyrillic
395 { 1252, RTL_TEXTENCODING_MS_1252
}, // MS Windows Latin I (BIFF4-BIFF8)
396 { 1253, RTL_TEXTENCODING_MS_1253
}, // MS Windows Greek
397 { 1254, RTL_TEXTENCODING_MS_1254
}, // MS Windows Turkish
398 { 1255, RTL_TEXTENCODING_MS_1255
}, // MS Windows Hebrew
399 { 1256, RTL_TEXTENCODING_MS_1256
}, // MS Windows Arabic
400 { 1257, RTL_TEXTENCODING_MS_1257
}, // MS Windows Baltic
401 { 1258, RTL_TEXTENCODING_MS_1258
}, // MS Windows Vietnamese
402 { 1361, RTL_TEXTENCODING_MS_1361
}, // MS Windows Korean (Johab)
403 { 10000, RTL_TEXTENCODING_APPLE_ROMAN
}, // Apple Roman
404 { 32768, RTL_TEXTENCODING_APPLE_ROMAN
}, // Apple Roman
405 { 32769, RTL_TEXTENCODING_MS_1252
} // MS Windows Latin I (BIFF2-BIFF3)
407 const XclCodePageEntry
* const pCodePageTableEnd
= std::end(pCodePageTable
);
409 struct XclCodePageEntry_CPPred
411 explicit XclCodePageEntry_CPPred( sal_uInt16 nCodePage
) : mnCodePage( nCodePage
) {}
412 bool operator()( const XclCodePageEntry
& rEntry
) const { return rEntry
.mnCodePage
== mnCodePage
; }
413 sal_uInt16 mnCodePage
;
416 struct XclCodePageEntry_TEPred
418 explicit XclCodePageEntry_TEPred( rtl_TextEncoding eTextEnc
) : meTextEnc( eTextEnc
) {}
419 bool operator()( const XclCodePageEntry
& rEntry
) const { return rEntry
.meTextEnc
== meTextEnc
; }
420 rtl_TextEncoding meTextEnc
;
425 rtl_TextEncoding
XclTools::GetTextEncoding( sal_uInt16 nCodePage
)
427 const XclCodePageEntry
* pEntry
= ::std::find_if( pCodePageTable
, pCodePageTableEnd
, XclCodePageEntry_CPPred( nCodePage
) );
428 if( pEntry
== pCodePageTableEnd
)
430 SAL_WARN("sc", "XclTools::GetTextEncoding - unknown code page: 0x" << std::hex
<< nCodePage
);
431 return RTL_TEXTENCODING_DONTKNOW
;
433 return pEntry
->meTextEnc
;
436 sal_uInt16
XclTools::GetXclCodePage( rtl_TextEncoding eTextEnc
)
438 if( eTextEnc
== RTL_TEXTENCODING_UNICODE
)
439 return 1200; // for BIFF8
441 const XclCodePageEntry
* pEntry
= ::std::find_if( pCodePageTable
, pCodePageTableEnd
, XclCodePageEntry_TEPred( eTextEnc
) );
442 if( pEntry
== pCodePageTableEnd
)
444 SAL_WARN("sc", "XclTools::GetXclCodePage - unsupported text encoding: 0x" << std::hex
<< eTextEnc
);
447 return pEntry
->mnCodePage
;
450 OUString
XclTools::GetXclFontName( const OUString
& rFontName
)
452 // substitute with MS fonts
453 OUString aNewName
= GetSubsFontName(rFontName
, SubsFontFlags::ONLYONE
| SubsFontFlags::MS
);
454 return aNewName
.isEmpty() ? rFontName
: aNewName
;
457 // built-in defined names
458 const char maDefNamePrefix
[] = "Excel_BuiltIn_"; /// Prefix for built-in defined names.
459 const char maDefNamePrefixXml
[] = "_xlnm."; /// Prefix for built-in defined names for OOX
461 const char* const ppcDefNames
[] =
479 OUString
XclTools::GetXclBuiltInDefName( sal_Unicode cBuiltIn
)
481 OSL_ENSURE( std::size( ppcDefNames
) == EXC_BUILTIN_UNKNOWN
,
482 "XclTools::GetXclBuiltInDefName - built-in defined name list modified" );
484 if( cBuiltIn
< std::size( ppcDefNames
) )
485 return OUString::createFromAscii(ppcDefNames
[cBuiltIn
]);
487 return OUString::number(cBuiltIn
);
490 OUString
XclTools::GetBuiltInDefName( sal_Unicode cBuiltIn
)
492 return maDefNamePrefix
+ GetXclBuiltInDefName(cBuiltIn
);
495 OUString
XclTools::GetBuiltInDefNameXml( sal_Unicode cBuiltIn
)
497 return maDefNamePrefixXml
+ GetXclBuiltInDefName(cBuiltIn
);
500 sal_Unicode
XclTools::GetBuiltInDefNameIndex( const OUString
& rDefName
)
502 sal_Int32 nPrefixLen
= 0;
503 if( rDefName
.startsWithIgnoreAsciiCase( maDefNamePrefix
) )
504 nPrefixLen
= strlen(maDefNamePrefix
);
505 else if( rDefName
.startsWithIgnoreAsciiCase( maDefNamePrefixXml
) )
506 nPrefixLen
= strlen(maDefNamePrefixXml
);
509 for( sal_Unicode cBuiltIn
= 0; cBuiltIn
< EXC_BUILTIN_UNKNOWN
; ++cBuiltIn
)
511 OUString
aBuiltInName(GetXclBuiltInDefName(cBuiltIn
));
512 sal_Int32 nBuiltInLen
= aBuiltInName
.getLength();
513 if( rDefName
.matchIgnoreAsciiCase( aBuiltInName
, nPrefixLen
) )
515 // name can be followed by underline or space character
516 sal_Int32 nNextCharPos
= nPrefixLen
+ nBuiltInLen
;
517 sal_Unicode cNextChar
= (rDefName
.getLength() > nNextCharPos
) ? rDefName
[nNextCharPos
] : '\0';
518 if( (cNextChar
== '\0') || (cNextChar
== ' ') || (cNextChar
== '_') )
523 return EXC_BUILTIN_UNKNOWN
;
526 // built-in style names
528 const char maStyleNamePrefix1
[] = "Excel_BuiltIn_"; /// Prefix for built-in cell style names.
529 const char maStyleNamePrefix2
[] = "Excel Built-in "; /// Prefix for built-in cell style names from OOX filter.
531 const char* const ppcStyleNames
[] =
533 "", // "Normal" not used directly, but localized "Default"
534 "RowLevel_", // outline level will be appended
535 "ColumnLevel_", // outline level will be appended
545 OUString
XclTools::GetBuiltInStyleName( sal_uInt8 nStyleId
, std::u16string_view rName
, sal_uInt8 nLevel
)
549 if( nStyleId
== EXC_STYLE_NORMAL
) // "Normal" becomes "Default" style
551 aStyleName
= ScResId( STR_STYLENAME_STANDARD
);
555 OUStringBuffer
aBuf(maStyleNamePrefix1
);
556 if( nStyleId
< std::size( ppcStyleNames
) )
557 aBuf
.appendAscii(ppcStyleNames
[nStyleId
]);
558 else if (!rName
.empty())
561 aBuf
.append(static_cast<sal_Int32
>(nStyleId
));
563 if( (nStyleId
== EXC_STYLE_ROWLEVEL
) || (nStyleId
== EXC_STYLE_COLLEVEL
) )
564 aBuf
.append(static_cast<sal_Int32
>(nLevel
+1));
566 aStyleName
= aBuf
.makeStringAndClear();
572 bool XclTools::IsBuiltInStyleName( const OUString
& rStyleName
, sal_uInt8
* pnStyleId
, sal_Int32
* pnNextChar
)
574 // "Default" becomes "Normal"
575 if (rStyleName
== ScResId(STR_STYLENAME_STANDARD
))
577 if( pnStyleId
) *pnStyleId
= EXC_STYLE_NORMAL
;
578 if( pnNextChar
) *pnNextChar
= rStyleName
.getLength();
582 // try the other built-in styles
583 sal_uInt8 nFoundId
= 0;
584 sal_Int32 nNextChar
= 0;
586 sal_Int32 nPrefixLen
= 0;
587 if( rStyleName
.startsWithIgnoreAsciiCase( maStyleNamePrefix1
) )
588 nPrefixLen
= strlen(maStyleNamePrefix1
);
589 else if( rStyleName
.startsWithIgnoreAsciiCase( maStyleNamePrefix2
) )
590 nPrefixLen
= strlen(maStyleNamePrefix2
);
593 for( sal_uInt8 nId
= 0; nId
< std::size( ppcStyleNames
); ++nId
)
595 if( nId
!= EXC_STYLE_NORMAL
)
597 OUString aShortName
= OUString::createFromAscii(ppcStyleNames
[nId
]);
598 if( rStyleName
.matchIgnoreAsciiCase( aShortName
, nPrefixLen
) &&
599 (nNextChar
< nPrefixLen
+ aShortName
.getLength()))
602 nNextChar
= nPrefixLen
+ aShortName
.getLength();
610 if( pnStyleId
) *pnStyleId
= nFoundId
;
611 if( pnNextChar
) *pnNextChar
= nNextChar
;
615 if( pnStyleId
) *pnStyleId
= EXC_STYLE_USERDEF
;
616 if( pnNextChar
) *pnNextChar
= 0;
617 return nPrefixLen
> 0; // also return true for unknown built-in styles
620 bool XclTools::GetBuiltInStyleId( sal_uInt8
& rnStyleId
, sal_uInt8
& rnLevel
, const OUString
& rStyleName
)
624 if( IsBuiltInStyleName( rStyleName
, &nStyleId
, &nNextChar
) && (nStyleId
!= EXC_STYLE_USERDEF
) )
626 if( (nStyleId
== EXC_STYLE_ROWLEVEL
) || (nStyleId
== EXC_STYLE_COLLEVEL
) )
628 std::u16string_view aLevel
= rStyleName
.subView(nNextChar
);
629 sal_Int32 nLevel
= o3tl::toInt32(aLevel
);
630 if (std::u16string_view(OUString::number(nLevel
)) == aLevel
631 && nLevel
> 0 && nLevel
<= EXC_STYLE_LEVELCOUNT
)
633 rnStyleId
= nStyleId
;
634 rnLevel
= static_cast< sal_uInt8
>( nLevel
- 1 );
638 else if( rStyleName
.getLength() == nNextChar
)
640 rnStyleId
= nStyleId
;
641 rnLevel
= EXC_STYLE_NOLEVEL
;
646 rnStyleId
= EXC_STYLE_USERDEF
;
647 rnLevel
= EXC_STYLE_NOLEVEL
;
651 // conditional formatting style names
653 const char maCFStyleNamePrefix1
[] = "Excel_CondFormat_"; /// Prefix for cond. formatting style names.
654 const char maCFStyleNamePrefix2
[] = "ConditionalStyle_"; /// Prefix for cond. formatting style names from OOX filter.
655 const char maCFStyleNamePrefix3
[] = "ExtConditionalStyle_";
657 OUString
XclTools::GetCondFormatStyleName( SCTAB nScTab
, sal_Int32 nFormat
, sal_uInt16 nCondition
)
659 return maCFStyleNamePrefix1
+
660 OUString::number(static_cast<sal_Int32
>(nScTab
+1)) +
662 OUString::number(static_cast<sal_Int32
>(nFormat
+1)) +
664 OUString::number(static_cast<sal_Int32
>(nCondition
+1));
667 bool XclTools::IsCondFormatStyleName( const OUString
& rStyleName
)
669 if( rStyleName
.startsWithIgnoreAsciiCase( maCFStyleNamePrefix1
) )
672 if( rStyleName
.startsWithIgnoreAsciiCase( maCFStyleNamePrefix2
) )
675 if (rStyleName
.startsWithIgnoreAsciiCase(maCFStyleNamePrefix3
))
683 void XclTools::SkipSubStream( XclImpStream
& rStrm
)
686 while( bLoop
&& rStrm
.StartNextRecord() )
688 sal_uInt16 nRecId
= rStrm
.GetRecId();
689 bLoop
= nRecId
!= EXC_ID_EOF
;
690 if( (nRecId
== EXC_ID2_BOF
) || (nRecId
== EXC_ID3_BOF
) || (nRecId
== EXC_ID4_BOF
) || (nRecId
== EXC_ID5_BOF
) )
691 SkipSubStream( rStrm
);
697 const char maSbMacroPrefix
[] = "vnd.sun.star.script:"; /// Prefix for StarBasic macros.
698 const char maSbMacroSuffix
[] = "?language=Basic&location=document"; /// Suffix for StarBasic macros.
700 OUString
XclTools::GetSbMacroUrl( const OUString
& rMacroName
, SfxObjectShell
* pDocShell
)
702 OSL_ENSURE( !rMacroName
.isEmpty(), "XclTools::GetSbMacroUrl - macro name is empty" );
703 ::ooo::vba::MacroResolvedInfo aMacroInfo
= ::ooo::vba::resolveVBAMacro( pDocShell
, rMacroName
);
704 if( aMacroInfo
.mbFound
)
705 return ::ooo::vba::makeMacroURL( aMacroInfo
.msResolvedMacro
);
709 OUString
XclTools::GetXclMacroName( const OUString
& rSbMacroUrl
)
711 sal_Int32 nSbMacroUrlLen
= rSbMacroUrl
.getLength();
712 sal_Int32 nMacroNameLen
= nSbMacroUrlLen
- strlen(maSbMacroPrefix
) - strlen(maSbMacroSuffix
);
713 if( (nMacroNameLen
> 0) && rSbMacroUrl
.startsWithIgnoreAsciiCase( maSbMacroPrefix
) &&
714 rSbMacroUrl
.endsWithIgnoreAsciiCase( maSbMacroSuffix
) )
716 sal_Int32 nPrjDot
= rSbMacroUrl
.indexOf( '.', strlen(maSbMacroPrefix
) ) + 1;
717 return rSbMacroUrl
.copy( nPrjDot
, nSbMacroUrlLen
- nPrjDot
- strlen(maSbMacroSuffix
) );
724 XclImpStream
& operator>>( XclImpStream
& rStrm
, Color
& rColor
)
726 sal_uInt8 nR
= rStrm
.ReaduInt8();
727 sal_uInt8 nG
= rStrm
.ReaduInt8();
728 sal_uInt8 nB
= rStrm
.ReaduInt8();
729 rStrm
.Ignore( 1 );//nD
730 rColor
= Color( nR
, nG
, nB
);
734 XclExpStream
& operator<<( XclExpStream
& rStrm
, const Color
& rColor
)
736 return rStrm
<< rColor
.GetRed() << rColor
.GetGreen() << rColor
.GetBlue() << sal_uInt8( 0 );
739 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */