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 <sal/mathconf.h>
23 #include <sal/macros.h>
24 #include <sal/log.hxx>
25 #include <tools/solar.h>
26 #include <unotools/fontdefs.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>
37 
38 // GUID import/export
39 
41  : mpnData{}
42 {
43 }
44 
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 )
49 {
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;
62 }
63 
64 bool operator==( const XclGuid& rCmp1, const XclGuid& rCmp2 )
65 {
66  return ::std::equal( rCmp1.mpnData, std::end( rCmp1.mpnData ), rCmp2.mpnData );
67 }
68 
70 {
71  rStrm.Read( rGuid.mpnData, 16 ); // mpnData always in little endian
72  return rStrm;
73 }
74 
75 XclExpStream& operator<<( XclExpStream& rStrm, const XclGuid& rGuid )
76 {
77  rStrm.Write( rGuid.mpnData, 16 ); // mpnData already in little endian
78  return rStrm;
79 }
80 
81 // Excel Tools
82 
83 // GUID's
85  0x79EAC9D0, 0xBAF9, 0x11CE, 0x8C, 0x82, 0x00, 0xAA, 0x00, 0x4B, 0xA9, 0x0B );
86 
88  0x79EAC9E0, 0xBAF9, 0x11CE, 0x8C, 0x82, 0x00, 0xAA, 0x00, 0x4B, 0xA9, 0x0B );
89 
91  0x00000303, 0x0000, 0x0000, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46 );
92 
93 // numeric conversion
94 
95 double XclTools::GetDoubleFromRK( sal_Int32 nRKValue )
96 {
97  union
98  {
99  double fVal;
100  sal_math_Double smD;
101  };
102  fVal = 0.0;
103 
104  if( ::get_flag( nRKValue, EXC_RK_INTFLAG ) )
105  {
106  sal_Int32 nTemp = nRKValue >> 2;
107  ::set_flag< sal_Int32 >( nTemp, 0xE0000000, nRKValue < 0 );
108  fVal = nTemp;
109  }
110  else
111  {
112  smD.w32_parts.msw = nRKValue & EXC_RK_VALUEMASK;
113  }
114 
115  if( ::get_flag( nRKValue, EXC_RK_100FLAG ) )
116  fVal /= 100.0;
117 
118  return fVal;
119 }
120 
121 bool XclTools::GetRKFromDouble( sal_Int32& rnRKValue, double fValue )
122 {
123  double fFrac, fInt;
124 
125  // integer
126  fFrac = modf( fValue, &fInt );
127  if( (fFrac == 0.0) && (fInt >= -536870912.0) && (fInt <= 536870911.0) ) // 2^29
128  {
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;
134  }
135 
136  // integer/100
137  fFrac = modf( fValue * 100.0, &fInt );
138  if( (fFrac == 0.0) && (fInt >= -536870912.0) && (fInt <= 536870911.0) )
139  {
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;
145  }
146 
147  // double
148  return false;
149 }
150 
151 sal_Int32 XclTools::GetScRotation( sal_uInt16 nXclRot, sal_Int32 nRotForStacked )
152 {
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 );
157 }
158 
160 {
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;
171 }
172 
174 {
175  switch( nXclOrient )
176  {
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" );
182  }
183  return EXC_ROT_NONE;
184 }
185 
187 {
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;
196 }
197 
199 {
200  switch( nScError )
201  {
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;
219  }
220  return EXC_ERR_NA;
221 }
222 
224 {
225  switch( nXclError )
226  {
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" );
235  }
236  return FormulaError::NotAvailable;
237 }
238 
240 {
241  return CreateDoubleError(GetScErrorCode( nXclError ));
242 }
243 
244 XclBoolError XclTools::ErrorToEnum( double& rfDblValue, bool bErrOrBool, sal_uInt8 nValue )
245 {
247  if( bErrOrBool )
248  {
249  // error value
250  switch( nValue )
251  {
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;
260  }
261  rfDblValue = 0.0;
262  }
263  else
264  {
265  // Boolean value
266  eType = nValue ? xlErrTrue : xlErrFalse;
267  rfDblValue = nValue ? 1.0 : 0.0;
268  }
269  return eType;
270 }
271 
272 sal_uInt16 XclTools::GetTwipsFromInch( double fInches )
273 {
274  return static_cast< sal_uInt16 >(
275  ::std::min( ::std::max( (fInches * EXC_TWIPS_PER_INCH + 0.5), 0.0 ), 65535.0 ) );
276 }
277 
278 sal_uInt16 XclTools::GetTwipsFromHmm( sal_Int32 nHmm )
279 {
280  return GetTwipsFromInch( static_cast< double >( nHmm ) / 1000.0 / CM_PER_INCH );
281 }
282 
283 double XclTools::GetInchFromTwips( sal_Int32 nTwips )
284 {
285  return static_cast< double >( nTwips ) / EXC_TWIPS_PER_INCH;
286 }
287 
288 double XclTools::GetInchFromHmm( sal_Int32 nHmm )
289 {
290  return GetInchFromTwips( GetTwipsFromHmm( nHmm ) );
291 }
292 
293 sal_Int32 XclTools::GetHmmFromInch( double fInches )
294 {
295  return static_cast< sal_Int32 >( fInches * CM_PER_INCH * 1000 );
296 }
297 
298 sal_Int32 XclTools::GetHmmFromTwips( sal_Int32 nTwips )
299 {
300  return GetHmmFromInch( GetInchFromTwips( nTwips ) );
301 }
302 
303 sal_uInt16 XclTools::GetScColumnWidth( sal_uInt16 nXclWidth, long nScCharWidth )
304 {
305  double fScWidth = static_cast< double >( nXclWidth ) / 256.0 * nScCharWidth - 0.5;
306  return limit_cast< sal_uInt16 >( fScWidth );
307 }
308 
309 sal_uInt16 XclTools::GetXclColumnWidth( sal_uInt16 nScWidth, long nScCharWidth )
310 {
311  double fXclWidth = ( static_cast< double >( nScWidth ) + 0.5 ) * 256.0 / nScCharWidth;
312  return limit_cast< sal_uInt16 >( fXclWidth );
313 }
314 
315 // takes font height in twips (1/20 pt = 1/1440 in)
316 // returns correction value in 1/256th of *digit width* of default font
317 double XclTools::GetXclDefColWidthCorrection( long nXclDefFontHeight )
318 {
319  // Excel uses *max digit width of default font* (W) as cell width unit. Also it has 5-pixel
320  // "correction" to cell widths (ECMA-376-1:2016 18.3.1.81): each cell has 1-pixel padding, then
321  // 3 pixels for the border (which may be 1-pixel - hairline - then it will have 2 additional
322  // 1-pixel spacings from each side; or e.g. 2 hairlines with 1-pixel spacing in the middle; or
323  // thick 3-pixel). Obviously, correction size entirely depends on pixel size (and it is actually
324  // different in Excel on monitors with different resolution). Thus actual (displayed/printed)
325  // cell widths consist of X*W+5px; stored in file is the X (or X*256 if 1/256th of digit width
326  // units are used) value.
327  // This formula apparently converts this 5-pixel correction to 1/256th of digit width units.
328  // Looks like it is created from
329  //
330  // 5 * 256 * 1440 * 2.1333 / (96 * max(N-15, 60)) + 50.0
331  //
332  // where 5 - pixel correction; 256 - used to produce 1/256th of digit width; 1440 - used to
333  // convert font height N (in twips) to inches; 2.1333 - an (empirical?) quotient to convert
334  // font *height* into digit *width*; 96 - "standard" monitor resolution (DPI).
335  // Additionally the formula uses 15 (of unknown origin), 60 (minimal font height 3 pt), and
336  // 50.0 (also of unknown origin).
337  //
338  // TODO: convert this to take font digit width directly (and possibly DPI?), to avoid guessing
339  // the digit width and pixel size. Or DPI might stay 96, to not follow Excel dependency on DPI
340  // in addition to used font, and have absolute size of the correction fixed 5/96 in.
341  return 40960.0 / ::std::max( nXclDefFontHeight - 15, 60L ) + 50.0;
342 }
343 
344 // formatting
345 
346 Color XclTools::GetPatternColor( const Color& rPattColor, const Color& rBackColor, sal_uInt16 nXclPattern )
347 {
348  // 0x00 == 0% transparence (full rPattColor)
349  // 0x80 == 100% transparence (full rBackColor)
350  static const sal_uInt8 pnRatioTable[] =
351  {
352  0x80, 0x00, 0x40, 0x20, 0x60, 0x40, 0x40, 0x40, // 00 - 07
353  0x40, 0x40, 0x20, 0x60, 0x60, 0x60, 0x60, 0x48, // 08 - 15
354  0x50, 0x70, 0x78 // 16 - 18
355  };
356  return (nXclPattern < SAL_N_ELEMENTS( pnRatioTable )) ?
357  ScfTools::GetMixedColor( rPattColor, rBackColor, pnRatioTable[ nXclPattern ] ) : rPattColor;
358 }
359 
360 // text encoding
361 
362 namespace {
363 
364 const struct XclCodePageEntry
365 {
366  sal_uInt16 mnCodePage;
367  rtl_TextEncoding meTextEnc;
368 }
369 pCodePageTable[] =
370 {
371  { 437, RTL_TEXTENCODING_IBM_437 }, // OEM US
372 // { 720, RTL_TEXTENCODING_IBM_720 }, // OEM Arabic
373  { 737, RTL_TEXTENCODING_IBM_737 }, // OEM Greek
374  { 775, RTL_TEXTENCODING_IBM_775 }, // OEM Baltic
375  { 850, RTL_TEXTENCODING_IBM_850 }, // OEM Latin I
376  { 852, RTL_TEXTENCODING_IBM_852 }, // OEM Latin II (Central European)
377  { 855, RTL_TEXTENCODING_IBM_855 }, // OEM Cyrillic
378  { 857, RTL_TEXTENCODING_IBM_857 }, // OEM Turkish
379 // { 858, RTL_TEXTENCODING_IBM_858 }, // OEM Multilingual Latin I with Euro
380  { 860, RTL_TEXTENCODING_IBM_860 }, // OEM Portuguese
381  { 861, RTL_TEXTENCODING_IBM_861 }, // OEM Icelandic
382  { 862, RTL_TEXTENCODING_IBM_862 }, // OEM Hebrew
383  { 863, RTL_TEXTENCODING_IBM_863 }, // OEM Canadian (French)
384  { 864, RTL_TEXTENCODING_IBM_864 }, // OEM Arabic
385  { 865, RTL_TEXTENCODING_IBM_865 }, // OEM Nordic
386  { 866, RTL_TEXTENCODING_IBM_866 }, // OEM Cyrillic (Russian)
387  { 869, RTL_TEXTENCODING_IBM_869 }, // OEM Greek (Modern)
388  { 874, RTL_TEXTENCODING_MS_874 }, // MS Windows Thai
389  { 932, RTL_TEXTENCODING_MS_932 }, // MS Windows Japanese Shift-JIS
390  { 936, RTL_TEXTENCODING_MS_936 }, // MS Windows Chinese Simplified GBK
391  { 949, RTL_TEXTENCODING_MS_949 }, // MS Windows Korean (Wansung)
392  { 950, RTL_TEXTENCODING_MS_950 }, // MS Windows Chinese Traditional BIG5
393  { 1200, RTL_TEXTENCODING_DONTKNOW }, // Unicode (BIFF8) - return *_DONTKNOW to preserve old code page
394  { 1250, RTL_TEXTENCODING_MS_1250 }, // MS Windows Latin II (Central European)
395  { 1251, RTL_TEXTENCODING_MS_1251 }, // MS Windows Cyrillic
396  { 1252, RTL_TEXTENCODING_MS_1252 }, // MS Windows Latin I (BIFF4-BIFF8)
397  { 1253, RTL_TEXTENCODING_MS_1253 }, // MS Windows Greek
398  { 1254, RTL_TEXTENCODING_MS_1254 }, // MS Windows Turkish
399  { 1255, RTL_TEXTENCODING_MS_1255 }, // MS Windows Hebrew
400  { 1256, RTL_TEXTENCODING_MS_1256 }, // MS Windows Arabic
401  { 1257, RTL_TEXTENCODING_MS_1257 }, // MS Windows Baltic
402  { 1258, RTL_TEXTENCODING_MS_1258 }, // MS Windows Vietnamese
403  { 1361, RTL_TEXTENCODING_MS_1361 }, // MS Windows Korean (Johab)
404  { 10000, RTL_TEXTENCODING_APPLE_ROMAN }, // Apple Roman
405  { 32768, RTL_TEXTENCODING_APPLE_ROMAN }, // Apple Roman
406  { 32769, RTL_TEXTENCODING_MS_1252 } // MS Windows Latin I (BIFF2-BIFF3)
407 };
408 const XclCodePageEntry* const pCodePageTableEnd = std::end(pCodePageTable);
409 
410 struct XclCodePageEntry_CPPred
411 {
412  explicit XclCodePageEntry_CPPred( sal_uInt16 nCodePage ) : mnCodePage( nCodePage ) {}
413  bool operator()( const XclCodePageEntry& rEntry ) const { return rEntry.mnCodePage == mnCodePage; }
414  sal_uInt16 mnCodePage;
415 };
416 
417 struct XclCodePageEntry_TEPred
418 {
419  explicit XclCodePageEntry_TEPred( rtl_TextEncoding eTextEnc ) : meTextEnc( eTextEnc ) {}
420  bool operator()( const XclCodePageEntry& rEntry ) const { return rEntry.meTextEnc == meTextEnc; }
421  rtl_TextEncoding meTextEnc;
422 };
423 
424 } // namespace
425 
426 rtl_TextEncoding XclTools::GetTextEncoding( sal_uInt16 nCodePage )
427 {
428  const XclCodePageEntry* pEntry = ::std::find_if( pCodePageTable, pCodePageTableEnd, XclCodePageEntry_CPPred( nCodePage ) );
429  if( pEntry == pCodePageTableEnd )
430  {
431  SAL_WARN("sc", "XclTools::GetTextEncoding - unknown code page: 0x" << std::hex << nCodePage );
432  return RTL_TEXTENCODING_DONTKNOW;
433  }
434  return pEntry->meTextEnc;
435 }
436 
437 sal_uInt16 XclTools::GetXclCodePage( rtl_TextEncoding eTextEnc )
438 {
439  if( eTextEnc == RTL_TEXTENCODING_UNICODE )
440  return 1200; // for BIFF8
441 
442  const XclCodePageEntry* pEntry = ::std::find_if( pCodePageTable, pCodePageTableEnd, XclCodePageEntry_TEPred( eTextEnc ) );
443  if( pEntry == pCodePageTableEnd )
444  {
445  SAL_WARN("sc", "XclTools::GetXclCodePage - unsupported text encoding: 0x" << std::hex << eTextEnc );
446  return 1252;
447  }
448  return pEntry->mnCodePage;
449 }
450 
451 OUString XclTools::GetXclFontName( const OUString& rFontName )
452 {
453  // substitute with MS fonts
454  OUString aNewName = GetSubsFontName(rFontName, SubsFontFlags::ONLYONE | SubsFontFlags::MS);
455  return aNewName.isEmpty() ? rFontName : aNewName;
456 }
457 
458 // built-in defined names
459 const char maDefNamePrefix[] = "Excel_BuiltIn_";
460 const char maDefNamePrefixXml[] = "_xlnm.";
461 
462 const char* const ppcDefNames[] =
463 {
464  "Consolidate_Area",
465  "Auto_Open",
466  "Auto_Close",
467  "Extract",
468  "Database",
469  "Criteria",
470  "Print_Area",
471  "Print_Titles",
472  "Recorder",
473  "Data_Form",
474  "Auto_Activate",
475  "Auto_Deactivate",
476  "Sheet_Title",
477  "_FilterDatabase"
478 };
479 
481 {
483  "XclTools::GetXclBuiltInDefName - built-in defined name list modified" );
484 
485  if( cBuiltIn < SAL_N_ELEMENTS( ppcDefNames ) )
486  return OUString::createFromAscii(ppcDefNames[cBuiltIn]);
487  else
488  return OUString::number(cBuiltIn);
489 }
490 
492 {
493  OUStringBuffer aBuf(maDefNamePrefix);
494  aBuf.append(GetXclBuiltInDefName(cBuiltIn));
495  return aBuf.makeStringAndClear();
496 }
497 
499 {
500  OUStringBuffer aBuf(maDefNamePrefixXml);
501  aBuf.append(GetXclBuiltInDefName(cBuiltIn));
502  return aBuf.makeStringAndClear();
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 
533 const char maStyleNamePrefix1[] = "Excel_BuiltIn_";
534 const char maStyleNamePrefix2[] = "Excel Built-in ";
535 
536 const 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 
550 OUString XclTools::GetBuiltInStyleName( sal_uInt8 nStyleId, const OUString& 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_CELL );
557  }
558  else
559  {
560  OUStringBuffer aBuf(maStyleNamePrefix1);
561  if( nStyleId < SAL_N_ELEMENTS( ppcStyleNames ) )
562  aBuf.appendAscii(ppcStyleNames[nStyleId]);
563  else if (!rName.isEmpty())
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 
577 bool XclTools::IsBuiltInStyleName( const OUString& rStyleName, sal_uInt8* pnStyleId, sal_Int32* pnNextChar )
578 {
579  // "Default" becomes "Normal"
580  if (rStyleName == ScResId(STR_STYLENAME_STANDARD_CELL))
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 
625 bool 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  OUString aLevel = rStyleName.copy(nNextChar);
634  sal_Int32 nLevel = aLevel.toInt32();
635  if (OUString::number(nLevel) == aLevel && nLevel > 0 && nLevel <= EXC_STYLE_LEVELCOUNT)
636  {
637  rnStyleId = nStyleId;
638  rnLevel = static_cast< sal_uInt8 >( nLevel - 1 );
639  return true;
640  }
641  }
642  else if( rStyleName.getLength() == nNextChar )
643  {
644  rnStyleId = nStyleId;
645  rnLevel = EXC_STYLE_NOLEVEL;
646  return true;
647  }
648  }
649 
650  rnStyleId = EXC_STYLE_USERDEF;
651  rnLevel = EXC_STYLE_NOLEVEL;
652  return false;
653 }
654 
655 // conditional formatting style names
656 
657 const char maCFStyleNamePrefix1[] = "Excel_CondFormat_";
658 const char maCFStyleNamePrefix2[] = "ConditionalStyle_";
659 
660 OUString XclTools::GetCondFormatStyleName( SCTAB nScTab, sal_Int32 nFormat, sal_uInt16 nCondition )
661 {
662  return maCFStyleNamePrefix1 +
663  OUString::number(static_cast<sal_Int32>(nScTab+1)) +
664  "_" +
665  OUString::number(static_cast<sal_Int32>(nFormat+1)) +
666  "_" +
667  OUString::number(static_cast<sal_Int32>(nCondition+1));
668 }
669 
670 bool XclTools::IsCondFormatStyleName( const OUString& rStyleName )
671 {
672  if( rStyleName.startsWithIgnoreAsciiCase( maCFStyleNamePrefix1 ) )
673  return true;
674 
675  if( rStyleName.startsWithIgnoreAsciiCase( maCFStyleNamePrefix2 ) )
676  return true;
677 
678  return false;
679 }
680 
681 // stream handling
682 
684 {
685  bool bLoop = true;
686  while( bLoop && rStrm.StartNextRecord() )
687  {
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 );
692  }
693 }
694 
695 // Basic macro names
696 
697 const char maSbMacroPrefix[] = "vnd.sun.star.script:";
698 const char maSbMacroSuffix[] = "?language=Basic&location=document";
699 
700 OUString XclTools::GetSbMacroUrl( const OUString& rMacroName, SfxObjectShell* pDocShell )
701 {
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 );
706  return OUString();
707 }
708 
709 OUString XclTools::GetXclMacroName( const OUString& rSbMacroUrl )
710 {
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 ) )
715  {
716  sal_Int32 nPrjDot = rSbMacroUrl.indexOf( '.', strlen(maSbMacroPrefix) ) + 1;
717  return rSbMacroUrl.copy( nPrjDot, nSbMacroUrlLen - nPrjDot - strlen(maSbMacroSuffix) );
718  }
719  return OUString();
720 }
721 
722 // read/write colors
723 
725 {
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 );
731  return rStrm;
732 }
733 
734 XclExpStream& operator<<( XclExpStream& rStrm, const Color& rColor )
735 {
736  return rStrm << rColor.GetRed() << rColor.GetGreen() << rColor.GetBlue() << sal_uInt8( 0 );
737 }
738 
739 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
static const XclGuid maGuidUrlMoniker
GUID of StdLink (HLINK record).
Definition: xltools.hxx:94
const sal_uInt8 EXC_ORIENT_NONE
Definition: xlconst.hxx:139
const sal_uInt8 EXC_ERR_NULL
DDE application-topic delimiter.
Definition: xlconst.hxx:105
std::size_t Write(const void *pData, std::size_t nBytes)
Writes nBytes bytes from memory.
Definition: xestream.cxx:215
const sal_uInt8 EXC_ERR_NA
Definition: xlconst.hxx:111
sal_uInt8 GetRed() const
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:244
const char maSbMacroPrefix[]
Definition: xltools.cxx:697
static sal_Int32 GetHmmFromInch(double fInches)
Returns the length in 1/100 mm calculated from a length in inches.
Definition: xltools.cxx:293
sal_uInt16 GetRecId() const
Returns the current record ID.
Definition: xistream.hxx:354
This class is used to export Excel record streams.
Definition: xestream.hxx:71
static const XclGuid maGuidFileMoniker
GUID of URL moniker (HLINK record).
Definition: xltools.hxx:95
static double GetXclDefColWidthCorrection(long nXclDefFontHeight)
Returns a correction value to convert column widths from/to default column widths.
Definition: xltools.cxx:317
XclGuid()
Stores GUID always in little endian.
Definition: xltools.cxx:40
const char maSbMacroSuffix[]
Prefix for StarBasic macros.
Definition: xltools.cxx:698
static sal_uInt8 GetXclOrientFromRot(sal_uInt16 nXclRot)
Calculates BIFF2-BIFF5 text orientation from BIFF8 rotation angle.
Definition: xltools.cxx:186
const sal_uInt8 EXC_ROT_STACKED
Text rotation: 90 deg clockwise.
Definition: xlconst.hxx:147
XclBoolError
An enumeration for all Excel error codes and the values true and false.
Definition: xltools.hxx:37
const char *const ppcDefNames[]
Prefix for built-in defined names for OOX.
Definition: xltools.cxx:462
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
std::size_t Read(void *pData, std::size_t nBytes)
Reads nBytes bytes to the existing(!) buffer pData.
Definition: xistream.cxx:720
static sal_uInt16 GetTwipsFromInch(double fInches)
Returns the length in twips calculated from a length in inches.
Definition: xltools.cxx:272
aBuf
sal_Int16 nId
const sal_Int32 EXC_RK_INTFLAG
Definition: xlconst.hxx:124
OUString GetSubsFontName(const OUString &rName, SubsFontFlags nFlags)
static sal_uInt8 GetXclRotFromOrient(sal_uInt8 nXclOrient)
Calculates BIFF8 rotation angle from BIFF2-BIFF5 text orientation.
Definition: xltools.cxx:173
ReturnType limit_cast(Type nValue, ReturnType nMin, ReturnType nMax)
Returns the value, if it is not less than nMin and not greater than nMax, otherwise one of the limits...
Definition: ftools.hxx:61
const sal_uInt16 EXC_ID5_BOF
Definition: xlconst.hxx:156
const sal_uInt8 EXC_STYLE_USERDEF
"Followed_Hyperlink" style.
Definition: xlstyle.hxx:235
The Boolean value false.
Definition: xltools.hxx:48
static double ErrorToDouble(sal_uInt8 nXclError)
Converts the passed BIFF error to a double containing the respective Calc error code.
Definition: xltools.cxx:239
static bool GetRKFromDouble(sal_Int32 &rnRKValue, double fValue)
Calculates an RK value (encoded integer or double) from a double value.
Definition: xltools.cxx:121
The error code #REF!
Definition: xltools.hxx:43
The Boolean value true.
Definition: xltools.hxx:47
const sal_uInt8 EXC_ORIENT_STACKED
Text orientation: not rotated.
Definition: xlconst.hxx:140
static OUString GetBuiltInDefNameXml(sal_Unicode cBuiltIn)
Returns the Excel built-in name with OOXML prefix Adds the "_xlnm." prefix to the representation ret...
Definition: xltools.cxx:498
XclImpStream & operator>>(XclImpStream &rStrm, XclGuid &rGuid)
Definition: xltools.cxx:69
sal_uInt16 sal_Unicode
The error code NULL!
Definition: xltools.hxx:40
static OUString GetXclFontName(const OUString &rFontName)
Returns the matching Excel font name for a passed Calc font name.
Definition: xltools.cxx:451
const sal_uInt8 EXC_ERR_NUM
Definition: xlconst.hxx:110
static const XclGuid maGuidStdLink
Definition: xltools.hxx:93
static OUString GetXclMacroName(const OUString &rSbMacroUrl)
Returns the Excel macro name from a full StarBasic macro URL.
Definition: xltools.cxx:709
static FormulaError GetScErrorCode(sal_uInt8 nXclError)
Converts an Excel error code to a Calc error code.
Definition: xltools.cxx:223
static OUString GetBuiltInDefName(sal_Unicode cBuiltIn)
Returns the Calc UI representation of a built-in defined name used in NAME records.
Definition: xltools.cxx:491
bool StartNextRecord()
Sets stream pointer to the start of the next record content.
Definition: xistream.cxx:455
const char maCFStyleNamePrefix1[]
Definition: xltools.cxx:657
XclExpStream & operator<<(XclExpStream &rStrm, const XclGuid &rGuid)
Definition: xltools.cxx:75
The error code #NUM!
Definition: xltools.hxx:45
const sal_Unicode EXC_BUILTIN_UNKNOWN
Definition: xlname.hxx:62
sal_uInt8 GetBlue() const
const sal_uInt8 EXC_STYLE_ROWLEVEL
"Normal" style.
Definition: xlstyle.hxx:226
const sal_uInt8 EXC_ERR_REF
Definition: xlconst.hxx:108
#define SAL_N_ELEMENTS(arr)
DocumentType eType
static sal_Int32 GetHmmFromTwips(sal_Int32 nTwips)
Returns the length in 1/100 mm calculated from a length in twips.
Definition: xltools.cxx:298
static Color GetMixedColor(const Color &rFore, const Color &rBack, sal_uInt8 nTrans)
Mixes colors with given transparence.
Definition: ftools.cxx:133
const char maDefNamePrefixXml[]
Prefix for built-in defined names.
Definition: xltools.cxx:460
const sal_Int32 EXC_TWIPS_PER_INCH
Definition: xlconst.hxx:135
const sal_Int32 EXC_RK_VALUEMASK
Definition: xlconst.hxx:125
static sal_uInt16 GetTwipsFromHmm(sal_Int32 nHmm)
Returns the length in twips calculated from a length in 1/100 mm.
Definition: xltools.cxx:278
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
const sal_Int32 EXC_RK_100FLAG
Definition: xlconst.hxx:123
const sal_uInt16 EXC_ID4_BOF
Definition: xlconst.hxx:155
static double GetDoubleFromRK(sal_Int32 nRKValue)
GUID of file moniker (HLINK record).
Definition: xltools.cxx:95
const sal_uInt8 EXC_ERR_VALUE
Definition: xlconst.hxx:107
static sal_uInt8 GetXclErrorCode(FormulaError nScError)
Converts a Calc error code to an Excel error code.
Definition: xltools.cxx:198
const sal_uInt8 EXC_STYLE_LEVELCOUNT
No built-in style.
Definition: xlstyle.hxx:237
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:670
static rtl_TextEncoding GetTextEncoding(sal_uInt16 nCodePage)
Returns a text encoding from an Excel code page.
Definition: xltools.cxx:426
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:346
sal_uInt8 mpnData[16]
Definition: xltools.hxx:59
OUString ScResId(const char *pId)
Definition: scdll.cxx:95
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
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:73
static double GetInchFromTwips(sal_Int32 nTwips)
Returns the length in inches calculated from a length in twips.
Definition: xltools.cxx:283
static sal_uInt16 GetXclColumnWidth(sal_uInt16 nScWidth, long nScCharWidth)
Returns the Excel column width for the passed Calc width (twips).
Definition: xltools.cxx:309
const char maDefNamePrefix[]
Definition: xltools.cxx:459
static OUString GetBuiltInStyleName(sal_uInt8 nStyleId, const OUString &rName, sal_uInt8 nLevel)
Returns the specified built-in cell style name.
Definition: xltools.cxx:550
const sal_uInt8 EXC_STYLE_NOLEVEL
Number of outline level styles.
Definition: xlstyle.hxx:238
static void SkipSubStream(XclImpStream &rStrm)
Skips a substream (BOF/EOF record block).
Definition: xltools.cxx:683
const sal_Int32 EXC_RK_INT100
Definition: xlconst.hxx:130
static sal_uInt16 GetXclCodePage(rtl_TextEncoding eTextEnc)
Returns an Excel code page from a text encoding.
Definition: xltools.cxx:437
static sal_uInt8 GetXclRotation(sal_Int32 nScRot)
Calculates the Excel angle value from an angle in 1/100 of degrees.
Definition: xltools.cxx:159
FormulaError
const sal_uInt8 EXC_STYLE_COLLEVEL
"RowLevel_*" styles.
Definition: xlstyle.hxx:227
The error code #VALUE!
Definition: xltools.hxx:42
const sal_uInt8 EXC_STYLE_NORMAL
Definition: xlstyle.hxx:225
bool operator==(const XclGuid &rCmp1, const XclGuid &rCmp2)
Definition: xltools.cxx:64
sal_uInt8 GetGreen() const
#define CM_PER_INCH
Definition: global.hxx:81
The error code #DIV/0!
Definition: xltools.hxx:41
static double GetInchFromHmm(sal_Int32 nHmm)
Returns the length in inches calculated from a length in 1/100 mm.
Definition: xltools.cxx:288
This struct stores a GUID (class ID) and supports reading, writing and comparison.
Definition: xltools.hxx:57
double CreateDoubleError(FormulaError nErr)
static OUString GetSbMacroUrl(const OUString &rMacroName, SfxObjectShell *pDocShell)
Returns the full StarBasic macro URL from an Excel macro name.
Definition: xltools.cxx:700
static sal_Int32 GetScRotation(sal_uInt16 nXclRot, sal_Int32 nRotForStacked)
Calculates an angle (in 1/100 of degrees) from an Excel angle value.
Definition: xltools.cxx:151
const char maCFStyleNamePrefix2[]
Prefix for cond. formatting style names.
Definition: xltools.cxx:658
static sal_uInt16 GetScColumnWidth(sal_uInt16 nXclWidth, long nScCharWidth)
Returns the Calc column width (twips) for the passed Excel width.
Definition: xltools.cxx:303
The error code N/A!
Definition: xltools.hxx:46
void Ignore(std::size_t nBytes)
Seeks forward inside the current record.
Definition: xistream.cxx:795
unsigned char sal_uInt8
const sal_uInt8 EXC_ERR_NAME
Definition: xlconst.hxx:109
sal_uInt8 ReaduInt8()
Definition: xistream.cxx:616
const sal_Int32 EXC_RK_INT
Definition: xlconst.hxx:129
const sal_uInt8 EXC_ERR_DIV0
Definition: xlconst.hxx:106
const sal_uInt8 EXC_ROT_90CW
Text rotation: 90 deg counterclockwise.
Definition: xlconst.hxx:146
const sal_uInt8 EXC_ROT_90CCW
Text rotation: not rotated.
Definition: xlconst.hxx:145
const sal_uInt8 EXC_ROT_NONE
Text orientation: 90 deg clockwise.
Definition: xlconst.hxx:144
#define SAL_WARN(area, stream)
const sal_uInt16 EXC_ID3_BOF
Definition: xlconst.hxx:154
const sal_uInt8 EXC_ORIENT_90CCW
Text orientation: vertically stacked.
Definition: xlconst.hxx:141
const char maStyleNamePrefix1[]
Definition: xltools.cxx:533
This class is used to import record oriented streams.
Definition: xistream.hxx:278
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:660
const sal_uInt16 EXC_ID2_BOF
Text rotation: vertically stacked.
Definition: xlconst.hxx:153
const char maStyleNamePrefix2[]
Prefix for built-in cell style names.
Definition: xltools.cxx:534
sal_Int16 SCTAB
Definition: types.hxx:23
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:480
const char *const ppcStyleNames[]
Prefix for built-in cell style names from OOX filter.
Definition: xltools.cxx:536
const sal_uInt8 EXC_ORIENT_90CW
Text orientation: 90 deg counterclockwise.
Definition: xlconst.hxx:142
The error code #NAME?
Definition: xltools.hxx:44
const sal_uInt16 EXC_ID_EOF
Internal use only.
Definition: xlconst.hxx:173