LibreOffice Module sc (master) 1
xltools.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
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 .
18 */
19
20#include <algorithm>
21#include <math.h>
22#include <string_view>
23
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>
32#include <xestream.hxx>
34#include <globstr.hrc>
35#include <scresid.hxx>
36#include <xlstyle.hxx>
37#include <xlname.hxx>
38#include <xistream.hxx>
39#include <xltools.hxx>
40
41// GUID import/export
42
44 : mpnData{}
45{
46}
47
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 )
52{
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;
65}
66
67bool operator==( const XclGuid& rCmp1, const XclGuid& rCmp2 )
68{
69 return ::std::equal( rCmp1.mpnData, std::end( rCmp1.mpnData ), rCmp2.mpnData );
70}
71
73{
74 rStrm.Read( rGuid.mpnData, 16 ); // mpnData always in little endian
75 return rStrm;
76}
77
79{
80 rStrm.Write( rGuid.mpnData, 16 ); // mpnData already in little endian
81 return rStrm;
82}
83
84// Excel Tools
85
86// GUID's
88 0x79EAC9D0, 0xBAF9, 0x11CE, 0x8C, 0x82, 0x00, 0xAA, 0x00, 0x4B, 0xA9, 0x0B );
89
91 0x79EAC9E0, 0xBAF9, 0x11CE, 0x8C, 0x82, 0x00, 0xAA, 0x00, 0x4B, 0xA9, 0x0B );
92
94 0x00000303, 0x0000, 0x0000, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46 );
95
96// numeric conversion
97
98double XclTools::GetDoubleFromRK( sal_Int32 nRKValue )
99{
100 union
101 {
102 double fVal;
103 sal_math_Double smD;
104 };
105 fVal = 0.0;
106
107 if( ::get_flag( nRKValue, EXC_RK_INTFLAG ) )
108 {
109 sal_Int32 nTemp = nRKValue >> 2;
110 ::set_flag< sal_Int32 >( nTemp, 0xE0000000, nRKValue < 0 );
111 fVal = nTemp;
112 }
113 else
114 {
115 smD.w32_parts.msw = nRKValue & EXC_RK_VALUEMASK;
116 }
117
118 if( ::get_flag( nRKValue, EXC_RK_100FLAG ) )
119 fVal /= 100.0;
120
121 return fVal;
122}
123
124bool XclTools::GetRKFromDouble( sal_Int32& rnRKValue, double fValue )
125{
126 double fFrac, fInt;
127
128 // integer
129 fFrac = modf( fValue, &fInt );
130 if( (fFrac == 0.0) && (fInt >= -536870912.0) && (fInt <= 536870911.0) ) // 2^29
131 {
132 rnRKValue
133 = static_cast<sal_Int32>(
134 static_cast<sal_uInt32>(static_cast<sal_Int32>(fInt)) << 2)
135 | EXC_RK_INT;
136 return true;
137 }
138
139 // integer/100
140 fFrac = modf( fValue * 100.0, &fInt );
141 if( (fFrac == 0.0) && (fInt >= -536870912.0) && (fInt <= 536870911.0) )
142 {
143 rnRKValue
144 = static_cast<sal_Int32>(
145 static_cast<sal_uInt32>(static_cast<sal_Int32>(fInt)) << 2)
147 return true;
148 }
149
150 // double
151 return false;
152}
153
154Degree100 XclTools::GetScRotation( sal_uInt16 nXclRot, Degree100 nRotForStacked )
155{
156 if( nXclRot == EXC_ROT_STACKED )
157 return nRotForStacked;
158 OSL_ENSURE( nXclRot <= 180, "XclTools::GetScRotation - illegal rotation angle" );
159 return Degree100(static_cast< sal_Int32 >( (nXclRot <= 180) ? (100 * ((nXclRot > 90) ? (450 - nXclRot) : nXclRot)) : 0 ));
160}
161
163{
164 sal_Int32 nXclRot = nScRot.get() / 100;
165 if( (0 <= nXclRot) && (nXclRot <= 90) )
166 return static_cast< sal_uInt8 >( nXclRot );
167 if( nXclRot < 180 )
168 return static_cast< sal_uInt8 >( 270 - nXclRot );
169 if( nXclRot < 270 )
170 return static_cast< sal_uInt8 >( nXclRot - 180 );
171 if( nXclRot < 360 )
172 return static_cast< sal_uInt8 >( 450 - nXclRot );
173 return 0;
174}
175
177{
178 switch( nXclOrient )
179 {
180 case EXC_ORIENT_NONE: return EXC_ROT_NONE;
182 case EXC_ORIENT_90CCW: return EXC_ROT_90CCW;
183 case EXC_ORIENT_90CW: return EXC_ROT_90CW;
184 default: OSL_FAIL( "XclTools::GetXclRotFromOrient - unknown text orientation" );
185 }
186 return EXC_ROT_NONE;
187}
188
190{
191 if( nXclRot == EXC_ROT_STACKED )
192 return EXC_ORIENT_STACKED;
193 OSL_ENSURE( nXclRot <= 180, "XclTools::GetXclOrientFromRot - unknown text rotation" );
194 if( (45 < nXclRot) && (nXclRot <= 90) )
195 return EXC_ORIENT_90CCW;
196 if( (135 < nXclRot) && (nXclRot <= 180) )
197 return EXC_ORIENT_90CW;
198 return EXC_ORIENT_NONE;
199}
200
202{
203 switch( nScError )
204 {
205 case FormulaError::IllegalArgument: return EXC_ERR_VALUE;
206 case FormulaError::IllegalFPOperation: return EXC_ERR_NUM; // maybe DIV/0 or NUM...
207 case FormulaError::DivisionByZero: return EXC_ERR_DIV0;
208 case FormulaError::IllegalParameter: return EXC_ERR_VALUE;
209 case FormulaError::PairExpected: return EXC_ERR_VALUE;
210 case FormulaError::OperatorExpected: return EXC_ERR_VALUE;
211 case FormulaError::VariableExpected: return EXC_ERR_VALUE;
212 case FormulaError::ParameterExpected: return EXC_ERR_VALUE;
213 case FormulaError::NoValue: return EXC_ERR_VALUE;
214 case FormulaError::CircularReference: return EXC_ERR_VALUE;
215 case FormulaError::NoCode: return EXC_ERR_NULL;
216 case FormulaError::NoRef: return EXC_ERR_REF;
217 case FormulaError::NoName: return EXC_ERR_NAME;
218 case FormulaError::NoAddin: return EXC_ERR_NAME;
219 case FormulaError::NoMacro: return EXC_ERR_NAME;
220 case FormulaError::NotAvailable: return EXC_ERR_NA;
221 default: break;
222 }
223 return EXC_ERR_NA;
224}
225
227{
228 switch( nXclError )
229 {
230 case EXC_ERR_NULL: return FormulaError::NoCode;
231 case EXC_ERR_DIV0: return FormulaError::DivisionByZero;
232 case EXC_ERR_VALUE: return FormulaError::NoValue;
233 case EXC_ERR_REF: return FormulaError::NoRef;
234 case EXC_ERR_NAME: return FormulaError::NoName;
235 case EXC_ERR_NUM: return FormulaError::IllegalFPOperation;
236 case EXC_ERR_NA: return FormulaError::NotAvailable;
237 default: OSL_FAIL( "XclTools::GetScErrorCode - unknown error code" );
238 }
239 return FormulaError::NotAvailable;
240}
241
243{
244 return CreateDoubleError(GetScErrorCode( nXclError ));
245}
246
247XclBoolError XclTools::ErrorToEnum( double& rfDblValue, bool bErrOrBool, sal_uInt8 nValue )
248{
250 if( bErrOrBool )
251 {
252 // error value
253 switch( nValue )
254 {
255 case EXC_ERR_NULL: eType = xlErrNull; break;
256 case EXC_ERR_DIV0: eType = xlErrDiv0; break;
257 case EXC_ERR_VALUE: eType = xlErrValue; break;
258 case EXC_ERR_REF: eType = xlErrRef; break;
259 case EXC_ERR_NAME: eType = xlErrName; break;
260 case EXC_ERR_NUM: eType = xlErrNum; break;
261 case EXC_ERR_NA: eType = xlErrNA; break;
262 default: eType = xlErrUnknown;
263 }
264 rfDblValue = 0.0;
265 }
266 else
267 {
268 // Boolean value
270 rfDblValue = nValue ? 1.0 : 0.0;
271 }
272 return eType;
273}
274
275template <typename N> static N to(double f) { return limit_cast<N>(f + 0.5); }
276
277sal_uInt16 XclTools::GetTwipsFromInch( double fInches )
278{
279 return to<sal_uInt16>(o3tl::convert(fInches, o3tl::Length::in, o3tl::Length::twip));
280}
281
282sal_uInt16 XclTools::GetTwipsFromHmm( sal_Int32 nHmm )
283{
284 return limit_cast<sal_uInt16>(o3tl::convert(nHmm, o3tl::Length::mm100, o3tl::Length::twip));
285}
286
287double XclTools::GetInchFromTwips( sal_Int32 nTwips )
288{
289 return o3tl::convert<double>(nTwips, o3tl::Length::twip, o3tl::Length::in);
290}
291
292double XclTools::GetInchFromHmm( sal_Int32 nHmm )
293{
294 return o3tl::convert<double>(nHmm, o3tl::Length::mm100, o3tl::Length::in);
295}
296
297sal_Int32 XclTools::GetHmmFromInch( double fInches )
298{
299 return to<sal_Int32>(o3tl::convert(fInches, o3tl::Length::in, o3tl::Length::mm100));
300}
301
302sal_Int32 XclTools::GetHmmFromTwips( sal_Int32 nTwips )
303{
304 return limit_cast<sal_Int32>(o3tl::convert(nTwips, o3tl::Length::twip, o3tl::Length::mm100));
305}
306
307sal_uInt16 XclTools::GetScColumnWidth( sal_uInt16 nXclWidth, tools::Long nScCharWidth )
308{
309 double fScWidth = static_cast< double >( nXclWidth ) / 256.0 * nScCharWidth - 0.5;
310 return limit_cast< sal_uInt16 >( fScWidth );
311}
312
313sal_uInt16 XclTools::GetXclColumnWidth( sal_uInt16 nScWidth, tools::Long nScCharWidth )
314{
315 double fXclWidth = ( static_cast< double >( nScWidth ) + 0.5 ) * 256.0 / nScCharWidth;
316 return limit_cast< sal_uInt16 >( fXclWidth );
317}
318
319// takes font height in twips (1/20 pt = 1/1440 in)
320// returns correction value in 1/256th of *digit width* of default font
322{
323 // Excel uses *max digit width of default font* (W) as cell width unit. Also it has 5-pixel
324 // "correction" to cell widths (ECMA-376-1:2016 18.3.1.81): each cell has 1-pixel padding, then
325 // 3 pixels for the border (which may be 1-pixel - hairline - then it will have 2 additional
326 // 1-pixel spacings from each side; or e.g. 2 hairlines with 1-pixel spacing in the middle; or
327 // thick 3-pixel). Obviously, correction size entirely depends on pixel size (and it is actually
328 // different in Excel on monitors with different resolution). Thus actual (displayed/printed)
329 // cell widths consist of X*W+5px; stored in file is the X (or X*256 if 1/256th of digit width
330 // units are used) value.
331 // This formula apparently converts this 5-pixel correction to 1/256th of digit width units.
332 // Looks like it is created from
333 //
334 // 5 * 256 * 1440 * 2.1333 / (96 * max(N-15, 60)) + 50.0
335 //
336 // where 5 - pixel correction; 256 - used to produce 1/256th of digit width; 1440 - used to
337 // convert font height N (in twips) to inches; 2.1333 - an (empirical?) quotient to convert
338 // font *height* into digit *width*; 96 - "standard" monitor resolution (DPI).
339 // Additionally the formula uses 15 (of unknown origin), 60 (minimal font height 3 pt), and
340 // 50.0 (also of unknown origin).
341 //
342 // TODO: convert this to take font digit width directly (and possibly DPI?), to avoid guessing
343 // the digit width and pixel size. Or DPI might stay 96, to not follow Excel dependency on DPI
344 // in addition to used font, and have absolute size of the correction fixed 5/96 in.
345 return 40960.0 / ::std::max( nXclDefFontHeight - 15, tools::Long(60) ) + 50.0;
346}
347
348// formatting
349
350Color XclTools::GetPatternColor( const Color& rPattColor, const Color& rBackColor, sal_uInt16 nXclPattern )
351{
352 // 0x00 == 0% transparence (full rPattColor)
353 // 0x80 == 100% transparence (full rBackColor)
354 static const sal_uInt8 pnRatioTable[] =
355 {
356 0x80, 0x00, 0x40, 0x20, 0x60, 0x40, 0x40, 0x40, // 00 - 07
357 0x40, 0x40, 0x20, 0x60, 0x60, 0x60, 0x60, 0x48, // 08 - 15
358 0x50, 0x70, 0x78 // 16 - 18
359 };
360 return (nXclPattern < SAL_N_ELEMENTS( pnRatioTable )) ?
361 ScfTools::GetMixedColor( rPattColor, rBackColor, pnRatioTable[ nXclPattern ] ) : rPattColor;
362}
363
364// text encoding
365
366namespace {
367
368const struct XclCodePageEntry
369{
370 sal_uInt16 mnCodePage;
371 rtl_TextEncoding meTextEnc;
372}
373pCodePageTable[] =
374{
375 { 437, RTL_TEXTENCODING_IBM_437 }, // OEM US
376// { 720, RTL_TEXTENCODING_IBM_720 }, // OEM Arabic
377 { 737, RTL_TEXTENCODING_IBM_737 }, // OEM Greek
378 { 775, RTL_TEXTENCODING_IBM_775 }, // OEM Baltic
379 { 850, RTL_TEXTENCODING_IBM_850 }, // OEM Latin I
380 { 852, RTL_TEXTENCODING_IBM_852 }, // OEM Latin II (Central European)
381 { 855, RTL_TEXTENCODING_IBM_855 }, // OEM Cyrillic
382 { 857, RTL_TEXTENCODING_IBM_857 }, // OEM Turkish
383// { 858, RTL_TEXTENCODING_IBM_858 }, // OEM Multilingual Latin I with Euro
384 { 860, RTL_TEXTENCODING_IBM_860 }, // OEM Portuguese
385 { 861, RTL_TEXTENCODING_IBM_861 }, // OEM Icelandic
386 { 862, RTL_TEXTENCODING_IBM_862 }, // OEM Hebrew
387 { 863, RTL_TEXTENCODING_IBM_863 }, // OEM Canadian (French)
388 { 864, RTL_TEXTENCODING_IBM_864 }, // OEM Arabic
389 { 865, RTL_TEXTENCODING_IBM_865 }, // OEM Nordic
390 { 866, RTL_TEXTENCODING_IBM_866 }, // OEM Cyrillic (Russian)
391 { 869, RTL_TEXTENCODING_IBM_869 }, // OEM Greek (Modern)
392 { 874, RTL_TEXTENCODING_MS_874 }, // MS Windows Thai
393 { 932, RTL_TEXTENCODING_MS_932 }, // MS Windows Japanese Shift-JIS
394 { 936, RTL_TEXTENCODING_MS_936 }, // MS Windows Chinese Simplified GBK
395 { 949, RTL_TEXTENCODING_MS_949 }, // MS Windows Korean (Wansung)
396 { 950, RTL_TEXTENCODING_MS_950 }, // MS Windows Chinese Traditional BIG5
397 { 1200, RTL_TEXTENCODING_DONTKNOW }, // Unicode (BIFF8) - return *_DONTKNOW to preserve old code page
398 { 1250, RTL_TEXTENCODING_MS_1250 }, // MS Windows Latin II (Central European)
399 { 1251, RTL_TEXTENCODING_MS_1251 }, // MS Windows Cyrillic
400 { 1252, RTL_TEXTENCODING_MS_1252 }, // MS Windows Latin I (BIFF4-BIFF8)
401 { 1253, RTL_TEXTENCODING_MS_1253 }, // MS Windows Greek
402 { 1254, RTL_TEXTENCODING_MS_1254 }, // MS Windows Turkish
403 { 1255, RTL_TEXTENCODING_MS_1255 }, // MS Windows Hebrew
404 { 1256, RTL_TEXTENCODING_MS_1256 }, // MS Windows Arabic
405 { 1257, RTL_TEXTENCODING_MS_1257 }, // MS Windows Baltic
406 { 1258, RTL_TEXTENCODING_MS_1258 }, // MS Windows Vietnamese
407 { 1361, RTL_TEXTENCODING_MS_1361 }, // MS Windows Korean (Johab)
408 { 10000, RTL_TEXTENCODING_APPLE_ROMAN }, // Apple Roman
409 { 32768, RTL_TEXTENCODING_APPLE_ROMAN }, // Apple Roman
410 { 32769, RTL_TEXTENCODING_MS_1252 } // MS Windows Latin I (BIFF2-BIFF3)
411};
412const XclCodePageEntry* const pCodePageTableEnd = std::end(pCodePageTable);
413
414struct XclCodePageEntry_CPPred
415{
416 explicit XclCodePageEntry_CPPred( sal_uInt16 nCodePage ) : mnCodePage( nCodePage ) {}
417 bool operator()( const XclCodePageEntry& rEntry ) const { return rEntry.mnCodePage == mnCodePage; }
418 sal_uInt16 mnCodePage;
419};
420
421struct XclCodePageEntry_TEPred
422{
423 explicit XclCodePageEntry_TEPred( rtl_TextEncoding eTextEnc ) : meTextEnc( eTextEnc ) {}
424 bool operator()( const XclCodePageEntry& rEntry ) const { return rEntry.meTextEnc == meTextEnc; }
425 rtl_TextEncoding meTextEnc;
426};
427
428} // namespace
429
430rtl_TextEncoding XclTools::GetTextEncoding( sal_uInt16 nCodePage )
431{
432 const XclCodePageEntry* pEntry = ::std::find_if( pCodePageTable, pCodePageTableEnd, XclCodePageEntry_CPPred( nCodePage ) );
433 if( pEntry == pCodePageTableEnd )
434 {
435 SAL_WARN("sc", "XclTools::GetTextEncoding - unknown code page: 0x" << std::hex << nCodePage );
436 return RTL_TEXTENCODING_DONTKNOW;
437 }
438 return pEntry->meTextEnc;
439}
440
441sal_uInt16 XclTools::GetXclCodePage( rtl_TextEncoding eTextEnc )
442{
443 if( eTextEnc == RTL_TEXTENCODING_UNICODE )
444 return 1200; // for BIFF8
445
446 const XclCodePageEntry* pEntry = ::std::find_if( pCodePageTable, pCodePageTableEnd, XclCodePageEntry_TEPred( eTextEnc ) );
447 if( pEntry == pCodePageTableEnd )
448 {
449 SAL_WARN("sc", "XclTools::GetXclCodePage - unsupported text encoding: 0x" << std::hex << eTextEnc );
450 return 1252;
451 }
452 return pEntry->mnCodePage;
453}
454
455OUString XclTools::GetXclFontName( const OUString& rFontName )
456{
457 // substitute with MS fonts
458 OUString aNewName = GetSubsFontName(rFontName, SubsFontFlags::ONLYONE | SubsFontFlags::MS);
459 return aNewName.isEmpty() ? rFontName : aNewName;
460}
461
462// built-in defined names
463const char maDefNamePrefix[] = "Excel_BuiltIn_";
464const char maDefNamePrefixXml[] = "_xlnm.";
465
466const char* const ppcDefNames[] =
467{
468 "Consolidate_Area",
469 "Auto_Open",
470 "Auto_Close",
471 "Extract",
472 "Database",
473 "Criteria",
474 "Print_Area",
475 "Print_Titles",
476 "Recorder",
477 "Data_Form",
478 "Auto_Activate",
479 "Auto_Deactivate",
480 "Sheet_Title",
481 "_FilterDatabase"
482};
483
485{
487 "XclTools::GetXclBuiltInDefName - built-in defined name list modified" );
488
489 if( cBuiltIn < SAL_N_ELEMENTS( ppcDefNames ) )
490 return OUString::createFromAscii(ppcDefNames[cBuiltIn]);
491 else
492 return OUString::number(cBuiltIn);
493}
494
496{
497 return maDefNamePrefix + GetXclBuiltInDefName(cBuiltIn);
498}
499
501{
502 return maDefNamePrefixXml + GetXclBuiltInDefName(cBuiltIn);
503}
504
506{
507 sal_Int32 nPrefixLen = 0;
508 if( rDefName.startsWithIgnoreAsciiCase( maDefNamePrefix ) )
509 nPrefixLen = strlen(maDefNamePrefix);
510 else if( rDefName.startsWithIgnoreAsciiCase( maDefNamePrefixXml ) )
511 nPrefixLen = strlen(maDefNamePrefixXml);
512 if( nPrefixLen > 0 )
513 {
514 for( sal_Unicode cBuiltIn = 0; cBuiltIn < EXC_BUILTIN_UNKNOWN; ++cBuiltIn )
515 {
516 OUString aBuiltInName(GetXclBuiltInDefName(cBuiltIn));
517 sal_Int32 nBuiltInLen = aBuiltInName.getLength();
518 if( rDefName.matchIgnoreAsciiCase( aBuiltInName, nPrefixLen ) )
519 {
520 // name can be followed by underline or space character
521 sal_Int32 nNextCharPos = nPrefixLen + nBuiltInLen;
522 sal_Unicode cNextChar = (rDefName.getLength() > nNextCharPos) ? rDefName[nNextCharPos] : '\0';
523 if( (cNextChar == '\0') || (cNextChar == ' ') || (cNextChar == '_') )
524 return cBuiltIn;
525 }
526 }
527 }
528 return EXC_BUILTIN_UNKNOWN;
529}
530
531// built-in style names
532
533const char maStyleNamePrefix1[] = "Excel_BuiltIn_";
534const char maStyleNamePrefix2[] = "Excel Built-in ";
535
536const char* const ppcStyleNames[] =
537{
538 "", // "Normal" not used directly, but localized "Default"
539 "RowLevel_", // outline level will be appended
540 "ColumnLevel_", // outline level will be appended
541 "Comma",
542 "Currency",
543 "Percent",
544 "Comma_0",
545 "Currency_0",
546 "Hyperlink",
547 "Followed_Hyperlink"
548};
549
550OUString XclTools::GetBuiltInStyleName( sal_uInt8 nStyleId, std::u16string_view rName, sal_uInt8 nLevel )
551{
552 OUString aStyleName;
553
554 if( nStyleId == EXC_STYLE_NORMAL ) // "Normal" becomes "Default" style
555 {
556 aStyleName = ScResId( STR_STYLENAME_STANDARD );
557 }
558 else
559 {
560 OUStringBuffer aBuf(maStyleNamePrefix1);
561 if( nStyleId < SAL_N_ELEMENTS( ppcStyleNames ) )
562 aBuf.appendAscii(ppcStyleNames[nStyleId]);
563 else if (!rName.empty())
564 aBuf.append(rName);
565 else
566 aBuf.append(static_cast<sal_Int32>(nStyleId));
567
568 if( (nStyleId == EXC_STYLE_ROWLEVEL) || (nStyleId == EXC_STYLE_COLLEVEL) )
569 aBuf.append(static_cast<sal_Int32>(nLevel+1));
570
571 aStyleName = aBuf.makeStringAndClear();
572 }
573
574 return aStyleName;
575}
576
577bool XclTools::IsBuiltInStyleName( const OUString& rStyleName, sal_uInt8* pnStyleId, sal_Int32* pnNextChar )
578{
579 // "Default" becomes "Normal"
580 if (rStyleName == ScResId(STR_STYLENAME_STANDARD))
581 {
582 if( pnStyleId ) *pnStyleId = EXC_STYLE_NORMAL;
583 if( pnNextChar ) *pnNextChar = rStyleName.getLength();
584 return true;
585 }
586
587 // try the other built-in styles
588 sal_uInt8 nFoundId = 0;
589 sal_Int32 nNextChar = 0;
590
591 sal_Int32 nPrefixLen = 0;
592 if( rStyleName.startsWithIgnoreAsciiCase( maStyleNamePrefix1 ) )
593 nPrefixLen = strlen(maStyleNamePrefix1);
594 else if( rStyleName.startsWithIgnoreAsciiCase( maStyleNamePrefix2 ) )
595 nPrefixLen = strlen(maStyleNamePrefix2);
596 if( nPrefixLen > 0 )
597 {
598 for( sal_uInt8 nId = 0; nId < SAL_N_ELEMENTS( ppcStyleNames ); ++nId )
599 {
600 if( nId != EXC_STYLE_NORMAL )
601 {
602 OUString aShortName = OUString::createFromAscii(ppcStyleNames[nId]);
603 if( rStyleName.matchIgnoreAsciiCase( aShortName, nPrefixLen ) &&
604 (nNextChar < nPrefixLen + aShortName.getLength()))
605 {
606 nFoundId = nId;
607 nNextChar = nPrefixLen + aShortName.getLength();
608 }
609 }
610 }
611 }
612
613 if( nNextChar > 0 )
614 {
615 if( pnStyleId ) *pnStyleId = nFoundId;
616 if( pnNextChar ) *pnNextChar = nNextChar;
617 return true;
618 }
619
620 if( pnStyleId ) *pnStyleId = EXC_STYLE_USERDEF;
621 if( pnNextChar ) *pnNextChar = 0;
622 return nPrefixLen > 0; // also return true for unknown built-in styles
623}
624
625bool XclTools::GetBuiltInStyleId( sal_uInt8& rnStyleId, sal_uInt8& rnLevel, const OUString& rStyleName )
626{
627 sal_uInt8 nStyleId;
628 sal_Int32 nNextChar;
629 if( IsBuiltInStyleName( rStyleName, &nStyleId, &nNextChar ) && (nStyleId != EXC_STYLE_USERDEF) )
630 {
631 if( (nStyleId == EXC_STYLE_ROWLEVEL) || (nStyleId == EXC_STYLE_COLLEVEL) )
632 {
633 std::u16string_view aLevel = rStyleName.subView(nNextChar);
634 sal_Int32 nLevel = o3tl::toInt32(aLevel);
635 if (std::u16string_view(OUString::number(nLevel)) == aLevel
636 && nLevel > 0 && nLevel <= EXC_STYLE_LEVELCOUNT)
637 {
638 rnStyleId = nStyleId;
639 rnLevel = static_cast< sal_uInt8 >( nLevel - 1 );
640 return true;
641 }
642 }
643 else if( rStyleName.getLength() == nNextChar )
644 {
645 rnStyleId = nStyleId;
646 rnLevel = EXC_STYLE_NOLEVEL;
647 return true;
648 }
649 }
650
651 rnStyleId = EXC_STYLE_USERDEF;
652 rnLevel = EXC_STYLE_NOLEVEL;
653 return false;
654}
655
656// conditional formatting style names
657
658const char maCFStyleNamePrefix1[] = "Excel_CondFormat_";
659const char maCFStyleNamePrefix2[] = "ConditionalStyle_";
660const char maCFStyleNamePrefix3[] = "ExtConditionalStyle_";
661
662OUString XclTools::GetCondFormatStyleName( SCTAB nScTab, sal_Int32 nFormat, sal_uInt16 nCondition )
663{
664 return maCFStyleNamePrefix1 +
665 OUString::number(static_cast<sal_Int32>(nScTab+1)) +
666 "_" +
667 OUString::number(static_cast<sal_Int32>(nFormat+1)) +
668 "_" +
669 OUString::number(static_cast<sal_Int32>(nCondition+1));
670}
671
672bool XclTools::IsCondFormatStyleName( const OUString& rStyleName )
673{
674 if( rStyleName.startsWithIgnoreAsciiCase( maCFStyleNamePrefix1 ) )
675 return true;
676
677 if( rStyleName.startsWithIgnoreAsciiCase( maCFStyleNamePrefix2 ) )
678 return true;
679
680 if (rStyleName.startsWithIgnoreAsciiCase(maCFStyleNamePrefix3))
681 return true;
682
683 return false;
684}
685
686// stream handling
687
689{
690 bool bLoop = true;
691 while( bLoop && rStrm.StartNextRecord() )
692 {
693 sal_uInt16 nRecId = rStrm.GetRecId();
694 bLoop = nRecId != EXC_ID_EOF;
695 if( (nRecId == EXC_ID2_BOF) || (nRecId == EXC_ID3_BOF) || (nRecId == EXC_ID4_BOF) || (nRecId == EXC_ID5_BOF) )
697 }
698}
699
700// Basic macro names
701
702const char maSbMacroPrefix[] = "vnd.sun.star.script:";
703const char maSbMacroSuffix[] = "?language=Basic&location=document";
704
705OUString XclTools::GetSbMacroUrl( const OUString& rMacroName, SfxObjectShell* pDocShell )
706{
707 OSL_ENSURE( !rMacroName.isEmpty(), "XclTools::GetSbMacroUrl - macro name is empty" );
708 ::ooo::vba::MacroResolvedInfo aMacroInfo = ::ooo::vba::resolveVBAMacro( pDocShell, rMacroName );
709 if( aMacroInfo.mbFound )
710 return ::ooo::vba::makeMacroURL( aMacroInfo.msResolvedMacro );
711 return OUString();
712}
713
714OUString XclTools::GetXclMacroName( const OUString& rSbMacroUrl )
715{
716 sal_Int32 nSbMacroUrlLen = rSbMacroUrl.getLength();
717 sal_Int32 nMacroNameLen = nSbMacroUrlLen - strlen(maSbMacroPrefix) - strlen(maSbMacroSuffix);
718 if( (nMacroNameLen > 0) && rSbMacroUrl.startsWithIgnoreAsciiCase( maSbMacroPrefix ) &&
719 rSbMacroUrl.endsWithIgnoreAsciiCase( maSbMacroSuffix ) )
720 {
721 sal_Int32 nPrjDot = rSbMacroUrl.indexOf( '.', strlen(maSbMacroPrefix) ) + 1;
722 return rSbMacroUrl.copy( nPrjDot, nSbMacroUrlLen - nPrjDot - strlen(maSbMacroSuffix) );
723 }
724 return OUString();
725}
726
727// read/write colors
728
730{
731 sal_uInt8 nR = rStrm.ReaduInt8();
732 sal_uInt8 nG = rStrm.ReaduInt8();
733 sal_uInt8 nB = rStrm.ReaduInt8();
734 rStrm.Ignore( 1 );//nD
735 rColor = Color( nR, nG, nB );
736 return rStrm;
737}
738
739XclExpStream& operator<<( XclExpStream& rStrm, const Color& rColor )
740{
741 return rStrm << rColor.GetRed() << rColor.GetGreen() << rColor.GetBlue() << sal_uInt8( 0 );
742}
743
744/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
sal_uInt8 GetBlue() const
sal_uInt8 GetRed() const
sal_uInt8 GetGreen() const
static Color GetMixedColor(const Color &rFore, const Color &rBack, sal_uInt8 nTrans)
Mixes colors with given transparence.
Definition: ftools.cxx:137
This class is used to export Excel record streams.
Definition: xestream.hxx:73
This class is used to import record oriented streams.
Definition: xistream.hxx:278
static void SkipSubStream(XclImpStream &rStrm)
Skips a substream (BOF/EOF record block).
Definition: xltools.cxx:688
static Color GetPatternColor(const Color &rPattColor, const Color &rBackColor, sal_uInt16 nXclPattern)
Returns the best fitting color for an Excel pattern area format.
Definition: xltools.cxx:350
static const XclGuid maGuidStdLink
Definition: xltools.hxx:95
static double GetDoubleFromRK(sal_Int32 nRKValue)
GUID of file moniker (HLINK record).
Definition: xltools.cxx:98
static sal_uInt8 GetXclOrientFromRot(sal_uInt16 nXclRot)
Calculates BIFF2-BIFF5 text orientation from BIFF8 rotation angle.
Definition: xltools.cxx:189
static sal_uInt8 GetXclErrorCode(FormulaError nScError)
Converts a Calc error code to an Excel error code.
Definition: xltools.cxx:201
static OUString GetBuiltInDefNameXml(sal_Unicode cBuiltIn)
Returns the Excel built-in name with OOXML prefix @descr Adds the "_xlnm." prefix to the representati...
Definition: xltools.cxx:500
static sal_uInt8 GetXclRotFromOrient(sal_uInt8 nXclOrient)
Calculates BIFF8 rotation angle from BIFF2-BIFF5 text orientation.
Definition: xltools.cxx:176
static sal_uInt16 GetXclColumnWidth(sal_uInt16 nScWidth, tools::Long nScCharWidth)
Returns the Excel column width for the passed Calc width (twips).
Definition: xltools.cxx:313
static XclBoolError ErrorToEnum(double &rfDblValue, bool bErrOrBool, sal_uInt8 nValue)
Gets a translated error code or Boolean value from Excel error codes.
Definition: xltools.cxx:247
static double GetInchFromTwips(sal_Int32 nTwips)
Returns the length in inches calculated from a length in twips.
Definition: xltools.cxx:287
static FormulaError GetScErrorCode(sal_uInt8 nXclError)
Converts an Excel error code to a Calc error code.
Definition: xltools.cxx:226
static rtl_TextEncoding GetTextEncoding(sal_uInt16 nCodePage)
Returns a text encoding from an Excel code page.
Definition: xltools.cxx:430
static double ErrorToDouble(sal_uInt8 nXclError)
Converts the passed BIFF error to a double containing the respective Calc error code.
Definition: xltools.cxx:242
static OUString GetXclBuiltInDefName(sal_Unicode cBuiltIn)
Returns the raw English UI representation of a built-in defined name used in NAME records.
Definition: xltools.cxx:484
static double GetXclDefColWidthCorrection(tools::Long nXclDefFontHeight)
Returns a correction value to convert column widths from/to default column widths.
Definition: xltools.cxx:321
static sal_Int32 GetHmmFromTwips(sal_Int32 nTwips)
Returns the length in 1/100 mm calculated from a length in twips.
Definition: xltools.cxx:302
static Degree100 GetScRotation(sal_uInt16 nXclRot, Degree100 nRotForStacked)
Calculates an angle (in 1/100 of degrees) from an Excel angle value.
Definition: xltools.cxx:154
static sal_uInt16 GetTwipsFromInch(double fInches)
Returns the length in twips calculated from a length in inches.
Definition: xltools.cxx:277
static OUString GetCondFormatStyleName(SCTAB nScTab, sal_Int32 nFormat, sal_uInt16 nCondition)
Returns the style name for a single condition of a conditional formatting.
Definition: xltools.cxx:662
static sal_uInt16 GetScColumnWidth(sal_uInt16 nXclWidth, tools::Long nScCharWidth)
Returns the Calc column width (twips) for the passed Excel width.
Definition: xltools.cxx:307
static bool IsBuiltInStyleName(const OUString &rStyleName, sal_uInt8 *pnStyleId=nullptr, sal_Int32 *pnNextChar=nullptr)
Returns true, if the passed string is a name of an Excel built-in style.
Definition: xltools.cxx:577
static sal_uInt8 GetXclRotation(Degree100 nScRot)
Calculates the Excel angle value from an angle in 1/100 of degrees.
Definition: xltools.cxx:162
static OUString GetSbMacroUrl(const OUString &rMacroName, SfxObjectShell *pDocShell)
Returns the full StarBasic macro URL from an Excel macro name.
Definition: xltools.cxx:705
static double GetInchFromHmm(sal_Int32 nHmm)
Returns the length in inches calculated from a length in 1/100 mm.
Definition: xltools.cxx:292
static const XclGuid maGuidFileMoniker
GUID of URL moniker (HLINK record).
Definition: xltools.hxx:97
static bool GetBuiltInStyleId(sal_uInt8 &rnStyleId, sal_uInt8 &rnLevel, const OUString &rStyleName)
Returns the Excel built-in style identifier of a passed style name.
Definition: xltools.cxx:625
static const XclGuid maGuidUrlMoniker
GUID of StdLink (HLINK record).
Definition: xltools.hxx:96
static OUString GetBuiltInStyleName(sal_uInt8 nStyleId, std::u16string_view rName, sal_uInt8 nLevel)
Returns the specified built-in cell style name.
Definition: xltools.cxx:550
static sal_uInt16 GetTwipsFromHmm(sal_Int32 nHmm)
Returns the length in twips calculated from a length in 1/100 mm.
Definition: xltools.cxx:282
static sal_uInt16 GetXclCodePage(rtl_TextEncoding eTextEnc)
Returns an Excel code page from a text encoding.
Definition: xltools.cxx:441
static bool IsCondFormatStyleName(const OUString &rStyleName)
Returns true, if the passed string is a name of a conditional format style created by Excel import.
Definition: xltools.cxx:672
static OUString GetXclFontName(const OUString &rFontName)
Returns the matching Excel font name for a passed Calc font name.
Definition: xltools.cxx:455
static OUString GetBuiltInDefName(sal_Unicode cBuiltIn)
Returns the Calc UI representation of a built-in defined name used in NAME records.
Definition: xltools.cxx:495
static bool GetRKFromDouble(sal_Int32 &rnRKValue, double fValue)
Calculates an RK value (encoded integer or double) from a double value.
Definition: xltools.cxx:124
static sal_Unicode GetBuiltInDefNameIndex(const OUString &rDefName)
Returns the Excel built-in name index of the passed defined name from Calc.
Definition: xltools.cxx:505
static OUString GetXclMacroName(const OUString &rSbMacroUrl)
Returns the Excel macro name from a full StarBasic macro URL.
Definition: xltools.cxx:714
static sal_Int32 GetHmmFromInch(double fInches)
Returns the length in 1/100 mm calculated from a length in inches.
Definition: xltools.cxx:297
FormulaError
double CreateDoubleError(FormulaError nErr)
DocumentType eType
sal_Int16 nValue
UNOTOOLS_DLLPUBLIC OUString GetSubsFontName(std::u16string_view rName, SubsFontFlags nFlags)
bool get_flag(Type nBitField, Type nMask)
Returns true, if at least one of the bits set in nMask is set in nBitField.
Definition: ftools.hxx:75
#define SAL_WARN(area, stream)
#define SAL_N_ELEMENTS(arr)
aBuf
void SvStream & rStrm
sal_Int32 toInt32(std::u16string_view str, sal_Int16 radix=10)
constexpr Point convert(const Point &rPoint, o3tl::Length eFrom, o3tl::Length eTo)
long Long
sal_Int16 nId
#define N
OUString ScResId(TranslateId aId)
Definition: scdll.cxx:90
This struct stores a GUID (class ID) and supports reading, writing and comparison.
Definition: xltools.hxx:60
XclGuid()
Stores GUID always in little endian.
Definition: xltools.cxx:43
sal_uInt8 mpnData[16]
Definition: xltools.hxx:61
UNDERLYING_TYPE get() const
unsigned char sal_uInt8
sal_uInt16 sal_Unicode
sal_Int16 SCTAB
Definition: types.hxx:22
const sal_uInt8 EXC_ORIENT_90CW
Text orientation: 90 deg counterclockwise.
Definition: xlconst.hxx:136
const sal_Int32 EXC_RK_100FLAG
Definition: xlconst.hxx:122
const sal_Int32 EXC_RK_INTFLAG
Definition: xlconst.hxx:123
const sal_uInt8 EXC_ORIENT_NONE
Definition: xlconst.hxx:133
const sal_uInt16 EXC_ID2_BOF
Text rotation: vertically stacked.
Definition: xlconst.hxx:147
const sal_uInt8 EXC_ERR_NA
Definition: xlconst.hxx:110
const sal_uInt8 EXC_ERR_REF
Definition: xlconst.hxx:107
const sal_uInt8 EXC_ROT_NONE
Text orientation: 90 deg clockwise.
Definition: xlconst.hxx:138
const sal_uInt8 EXC_ROT_90CCW
Text rotation: not rotated.
Definition: xlconst.hxx:139
const sal_uInt8 EXC_ERR_NAME
Definition: xlconst.hxx:108
const sal_uInt8 EXC_ERR_NULL
DDE application-topic delimiter.
Definition: xlconst.hxx:104
const sal_uInt8 EXC_ERR_VALUE
Definition: xlconst.hxx:106
const sal_uInt8 EXC_ORIENT_90CCW
Text orientation: vertically stacked.
Definition: xlconst.hxx:135
const sal_uInt16 EXC_ID4_BOF
Definition: xlconst.hxx:149
const sal_Int32 EXC_RK_INT100
Definition: xlconst.hxx:129
const sal_uInt8 EXC_ORIENT_STACKED
Text orientation: not rotated.
Definition: xlconst.hxx:134
const sal_uInt8 EXC_ERR_DIV0
Definition: xlconst.hxx:105
const sal_Int32 EXC_RK_INT
Definition: xlconst.hxx:128
const sal_Int32 EXC_RK_VALUEMASK
Definition: xlconst.hxx:124
const sal_uInt16 EXC_ID5_BOF
Definition: xlconst.hxx:150
const sal_uInt16 EXC_ID3_BOF
Definition: xlconst.hxx:148
const sal_uInt8 EXC_ROT_90CW
Text rotation: 90 deg counterclockwise.
Definition: xlconst.hxx:140
const sal_uInt8 EXC_ROT_STACKED
Text rotation: 90 deg clockwise.
Definition: xlconst.hxx:141
const sal_uInt16 EXC_ID_EOF
Internal use only.
Definition: xlconst.hxx:167
const sal_uInt8 EXC_ERR_NUM
Definition: xlconst.hxx:109
const sal_Unicode EXC_BUILTIN_UNKNOWN
Definition: xlname.hxx:61
const sal_uInt8 EXC_STYLE_COLLEVEL
"RowLevel_*" styles.
Definition: xlstyle.hxx:226
const sal_uInt8 EXC_STYLE_LEVELCOUNT
No built-in style.
Definition: xlstyle.hxx:236
const sal_uInt8 EXC_STYLE_ROWLEVEL
"Normal" style.
Definition: xlstyle.hxx:225
const sal_uInt8 EXC_STYLE_NOLEVEL
Number of outline level styles.
Definition: xlstyle.hxx:237
const sal_uInt8 EXC_STYLE_NORMAL
Definition: xlstyle.hxx:224
const sal_uInt8 EXC_STYLE_USERDEF
"Followed_Hyperlink" style.
Definition: xlstyle.hxx:234
const char *const ppcStyleNames[]
Prefix for built-in cell style names from OOX filter.
Definition: xltools.cxx:536
const char maCFStyleNamePrefix1[]
Definition: xltools.cxx:658
const char maCFStyleNamePrefix3[]
Prefix for cond. formatting style names from OOX filter.
Definition: xltools.cxx:660
XclImpStream & operator>>(XclImpStream &rStrm, XclGuid &rGuid)
Definition: xltools.cxx:72
bool operator==(const XclGuid &rCmp1, const XclGuid &rCmp2)
Definition: xltools.cxx:67
const char *const ppcDefNames[]
Prefix for built-in defined names for OOX.
Definition: xltools.cxx:466
const char maDefNamePrefix[]
Definition: xltools.cxx:463
const char maStyleNamePrefix2[]
Prefix for built-in cell style names.
Definition: xltools.cxx:534
const char maCFStyleNamePrefix2[]
Prefix for cond. formatting style names.
Definition: xltools.cxx:659
const char maSbMacroPrefix[]
Definition: xltools.cxx:702
const char maStyleNamePrefix1[]
Definition: xltools.cxx:533
const char maSbMacroSuffix[]
Prefix for StarBasic macros.
Definition: xltools.cxx:703
const char maDefNamePrefixXml[]
Prefix for built-in defined names.
Definition: xltools.cxx:464
XclExpStream & operator<<(XclExpStream &rStrm, const XclGuid &rGuid)
Definition: xltools.cxx:78
static N to(double f)
Definition: xltools.cxx:275
XclBoolError
An enumeration for all Excel error codes and the values true and false.
Definition: xltools.hxx:40
@ xlErrDiv0
The error code NULL!
Definition: xltools.hxx:42
@ xlErrValue
The error code #DIV/0!
Definition: xltools.hxx:43
@ xlErrNA
The error code #NUM!
Definition: xltools.hxx:47
@ xlErrNull
Definition: xltools.hxx:41
@ xlErrUnknown
The Boolean value false.
Definition: xltools.hxx:50
@ xlErrName
The error code #REF!
Definition: xltools.hxx:45
@ xlErrNum
The error code #NAME?
Definition: xltools.hxx:46
@ xlErrFalse
The Boolean value true.
Definition: xltools.hxx:49
@ xlErrTrue
The error code N/A!
Definition: xltools.hxx:48
@ xlErrRef
The error code #VALUE!
Definition: xltools.hxx:44