LibreOffice Module sc (master)  1
xetable.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 <xetable.hxx>
21 
22 #include <map>
23 #include <numeric>
24 #include <com/sun/star/i18n/ScriptType.hpp>
25 #include <scitems.hxx>
26 #include <svl/intitem.hxx>
27 #include <svl/stritem.hxx>
28 #include <tools/UnitConversion.hxx>
29 #include <editeng/flditem.hxx>
30 #include <document.hxx>
31 #include <dociter.hxx>
32 #include <olinetab.hxx>
33 #include <formulacell.hxx>
34 #include <patattr.hxx>
35 #include <attrib.hxx>
36 #include <xehelper.hxx>
37 #include <xecontent.hxx>
38 #include <xeescher.hxx>
39 #include <xeextlst.hxx>
40 #include <xeformula.hxx>
41 #include <xlcontent.hxx>
42 #include <xltools.hxx>
43 #include <tokenarray.hxx>
44 #include <formula/errorcodes.hxx>
46 #include <oox/token/tokens.hxx>
47 #include <oox/export/utils.hxx>
48 
49 using namespace ::oox;
50 
51 namespace ApiScriptType = ::com::sun::star::i18n::ScriptType;
52 
53 // Helper records for cell records
54 
55 XclExpStringRec::XclExpStringRec( const XclExpRoot& rRoot, const OUString& rResult ) :
57  mxResult( XclExpStringHelper::CreateString( rRoot, rResult ) )
58 {
59  OSL_ENSURE( (rRoot.GetBiff() <= EXC_BIFF5) || (mxResult->Len() > 0),
60  "XclExpStringRec::XclExpStringRec - empty result not allowed in BIFF8+" );
61  SetRecSize( mxResult->GetSize() );
62 }
63 
65 {
66  rStrm << *mxResult;
67 }
68 
69 // Additional records for special formula ranges ==============================
70 
72  sal_uInt16 nRecId, sal_uInt32 nRecSize, const ScAddress& rScPos ) :
73  XclExpRecord( nRecId, nRecSize ),
74  maXclRange( ScAddress::UNINITIALIZED ),
75  maBaseXclPos( ScAddress::UNINITIALIZED )
76 {
77  maBaseXclPos.Set( static_cast< sal_uInt16 >( rScPos.Col() ), static_cast< sal_uInt16 >( rScPos.Row() ) );
79 }
80 
82  sal_uInt16 nRecId, sal_uInt32 nRecSize, const ScRange& rScRange ) :
83  XclExpRecord( nRecId, nRecSize ),
84  maXclRange( ScAddress::UNINITIALIZED ),
85  maBaseXclPos( ScAddress::UNINITIALIZED )
86 {
88  static_cast< sal_uInt16 >( rScRange.aStart.Col() ),
89  static_cast< sal_uInt16 >( rScRange.aStart.Row() ),
90  static_cast< sal_uInt16 >( rScRange.aEnd.Col() ),
91  static_cast< sal_uInt16 >( rScRange.aEnd.Row() ) );
93 }
94 
95 bool XclExpRangeFmlaBase::IsBasePos( sal_uInt16 nXclCol, sal_uInt32 nXclRow ) const
96 {
97  return (maBaseXclPos.mnCol == nXclCol) && (maBaseXclPos.mnRow == nXclRow);
98 }
99 
101 {
102  sal_uInt16 nXclCol = static_cast< sal_uInt16 >( rScPos.Col() );
103  sal_uInt32 nXclRow = static_cast< sal_uInt32 >( rScPos.Row() );
104  maXclRange.maFirst.mnCol = ::std::min( maXclRange.maFirst.mnCol, nXclCol );
105  maXclRange.maFirst.mnRow = ::std::min( maXclRange.maFirst.mnRow, nXclRow );
106  maXclRange.maLast.mnCol = ::std::max( maXclRange.maLast.mnCol, nXclCol );
107  maXclRange.maLast.mnRow = ::std::max( maXclRange.maLast.mnRow, nXclRow );
108 }
109 
111 {
112  maXclRange.Write( rStrm, false );
113 }
114 
115 // Array formulas =============================================================
116 
117 XclExpArray::XclExpArray( const XclTokenArrayRef& xTokArr, const ScRange& rScRange ) :
118  XclExpRangeFmlaBase( EXC_ID3_ARRAY, 14 + xTokArr->GetSize(), rScRange ),
119  mxTokArr( xTokArr )
120 {
121 }
122 
124 {
126 }
127 
129 {
130  return mxTokArr->IsVolatile();
131 }
132 
134 {
135  WriteRangeAddress( rStrm );
136  sal_uInt16 nFlags = EXC_ARRAY_DEFAULTFLAGS;
138  rStrm << nFlags << sal_uInt32( 0 ) << *mxTokArr;
139 }
140 
142  XclExpRoot( rRoot )
143 {
144 }
145 
147 {
148  const ScAddress& rScPos = rScRange.aStart;
149  XclTokenArrayRef xTokArr = GetFormulaCompiler().CreateFormula( EXC_FMLATYPE_MATRIX, rScTokArr, &rScPos );
150 
151  OSL_ENSURE( maRecMap.find( rScPos ) == maRecMap.end(), "XclExpArrayBuffer::CreateArray - array exists already" );
152  XclExpArrayRef& rxRec = maRecMap[ rScPos ];
153  rxRec = new XclExpArray( xTokArr, rScRange );
154  return rxRec;
155 }
156 
157 XclExpArrayRef XclExpArrayBuffer::FindArray( const ScTokenArray& rScTokArr, const ScAddress& rBasePos ) const
158 {
159  XclExpArrayRef xRec;
160  // try to extract a matrix reference token
161  if (rScTokArr.GetLen() != 1)
162  // Must consist of a single reference token.
163  return xRec;
164 
165  const formula::FormulaToken* pToken = rScTokArr.GetArray()[0];
166  if (!pToken || pToken->GetOpCode() != ocMatRef)
167  // not a matrix reference token.
168  return xRec;
169 
170  const ScSingleRefData& rRef = *pToken->GetSingleRef();
171  ScAddress aAbsPos = rRef.toAbs(GetRoot().GetDoc(), rBasePos);
172  XclExpArrayMap::const_iterator it = maRecMap.find(aAbsPos);
173 
174  if (it != maRecMap.end())
175  xRec = it->second;
176  return xRec;
177 }
178 
179 // Shared formulas ============================================================
180 
181 XclExpShrfmla::XclExpShrfmla( const XclTokenArrayRef& xTokArr, const ScAddress& rScPos ) :
182  XclExpRangeFmlaBase( EXC_ID_SHRFMLA, 10 + xTokArr->GetSize(), rScPos ),
183  mxTokArr( xTokArr ),
184  mnUsedCount( 1 )
185 {
186 }
187 
189 {
190  Extend( rScPos );
191  ++mnUsedCount;
192 }
193 
195 {
197 }
198 
200 {
201  return mxTokArr->IsVolatile();
202 }
203 
205 {
206  WriteRangeAddress( rStrm );
207  rStrm << sal_uInt8( 0 ) << mnUsedCount << *mxTokArr;
208 }
209 
211  XclExpRoot( rRoot )
212 {
213 }
214 
216 {
217  using namespace formula;
218 
219  FormulaToken** pTokens = rArray.GetArray();
220  sal_uInt16 nLen = rArray.GetLen();
221  for (sal_uInt16 i = 0; i < nLen; ++i)
222  {
223  const FormulaToken* p = pTokens[i];
224  switch (p->GetType())
225  {
226  case svSingleRef:
227  {
228  const ScSingleRefData& rRefData = *p->GetSingleRef();
229  if (!GetFormulaCompiler().IsRef2D(rRefData))
230  // Excel's shared formula cannot include 3D reference.
231  return false;
232  }
233  break;
234  case svDoubleRef:
235  {
236  const ScComplexRefData& rRefData = *p->GetDoubleRef();
237  if (!GetFormulaCompiler().IsRef2D(rRefData))
238  // Excel's shared formula cannot include 3D reference.
239  return false;
240  }
241  break;
242  case svExternalSingleRef:
243  case svExternalDoubleRef:
244  case svExternalName:
245  // External references aren't allowed.
246  return false;
247  default:
248  ;
249  }
250  }
251  return true;
252 }
253 
255  const ScFormulaCell& rScCell, const ScAddress& rScPos )
256 {
257  XclExpShrfmlaRef xRec;
258  const ScTokenArray* pShrdScTokArr = rScCell.GetSharedCode();
259  if (!pShrdScTokArr)
260  // This formula cell is not shared formula cell.
261  return xRec;
262 
263  // Check to see if this shared formula contains any tokens that Excel's shared formula cannot handle.
264  if (maBadTokens.count(pShrdScTokArr) > 0)
265  // Already on the black list. Skip it.
266  return xRec;
267 
268  if (!IsValidTokenArray(*pShrdScTokArr))
269  {
270  // We can't export this as shared formula.
271  maBadTokens.insert(pShrdScTokArr);
272  return xRec;
273  }
274 
275  TokensType::iterator aIt = maRecMap.find(pShrdScTokArr);
276  if( aIt == maRecMap.end() )
277  {
278  // create a new record
279  XclTokenArrayRef xTokArr = GetFormulaCompiler().CreateFormula( EXC_FMLATYPE_SHARED, *pShrdScTokArr, &rScPos );
280  xRec = new XclExpShrfmla( xTokArr, rScPos );
281  maRecMap[ pShrdScTokArr ] = xRec;
282  }
283  else
284  {
285  // extend existing record
286  OSL_ENSURE( aIt->second, "XclExpShrfmlaBuffer::CreateOrExtendShrfmla - missing record" );
287  xRec = aIt->second;
288  xRec->ExtendRange( rScPos );
289  }
290 
291  return xRec;
292 }
293 
294 // Multiple operations ========================================================
295 
297  const XclMultipleOpRefs& rRefs, sal_uInt8 nScMode ) :
298  XclExpRangeFmlaBase( EXC_ID3_TABLEOP, 16, rScPos ),
299  mnLastAppXclCol( static_cast< sal_uInt16 >( rScPos.Col() ) ),
300  mnColInpXclCol( static_cast< sal_uInt16 >( rRefs.maColFirstScPos.Col() ) ),
301  mnColInpXclRow( static_cast< sal_uInt16 >( rRefs.maColFirstScPos.Row() ) ),
302  mnRowInpXclCol( static_cast< sal_uInt16 >( rRefs.maRowFirstScPos.Col() ) ),
303  mnRowInpXclRow( static_cast< sal_uInt16 >( rRefs.maRowFirstScPos.Row() ) ),
304  mnScMode( nScMode ),
305  mbValid( false )
306 {
307 }
308 
309 bool XclExpTableop::TryExtend( const ScAddress& rScPos, const XclMultipleOpRefs& rRefs )
310 {
311  sal_uInt16 nXclCol = static_cast< sal_uInt16 >( rScPos.Col() );
312  sal_uInt16 nXclRow = static_cast< sal_uInt16 >( rScPos.Row() );
313 
314  bool bOk = IsAppendable( nXclCol, nXclRow );
315  if( bOk )
316  {
317  SCCOL nFirstScCol = static_cast< SCCOL >( maXclRange.maFirst.mnCol );
318  SCROW nFirstScRow = static_cast< SCROW >( maXclRange.maFirst.mnRow );
319  SCCOL nColInpScCol = static_cast< SCCOL >( mnColInpXclCol );
320  SCROW nColInpScRow = static_cast< SCROW >( mnColInpXclRow );
321  SCCOL nRowInpScCol = static_cast< SCCOL >( mnRowInpXclCol );
322  SCROW nRowInpScRow = static_cast< SCROW >( mnRowInpXclRow );
323 
324  bOk = ((mnScMode == 2) == rRefs.mbDblRefMode) &&
325  (rScPos.Tab() == rRefs.maFmlaScPos.Tab()) &&
326  (nColInpScCol == rRefs.maColFirstScPos.Col()) &&
327  (nColInpScRow == rRefs.maColFirstScPos.Row()) &&
328  (rScPos.Tab() == rRefs.maColFirstScPos.Tab()) &&
329  (rScPos.Tab() == rRefs.maColRelScPos.Tab());
330 
331  if( bOk ) switch( mnScMode )
332  {
333  case 0:
334  bOk = (rScPos.Col() == rRefs.maFmlaScPos.Col()) &&
335  (nFirstScRow == rRefs.maFmlaScPos.Row() + 1) &&
336  (nFirstScCol == rRefs.maColRelScPos.Col() + 1) &&
337  (rScPos.Row() == rRefs.maColRelScPos.Row());
338  break;
339  case 1:
340  bOk = (nFirstScCol == rRefs.maFmlaScPos.Col() + 1) &&
341  (rScPos.Row() == rRefs.maFmlaScPos.Row()) &&
342  (rScPos.Col() == rRefs.maColRelScPos.Col()) &&
343  (nFirstScRow == rRefs.maColRelScPos.Row() + 1);
344  break;
345  case 2:
346  bOk = (nFirstScCol == rRefs.maFmlaScPos.Col() + 1) &&
347  (nFirstScRow == rRefs.maFmlaScPos.Row() + 1) &&
348  (nFirstScCol == rRefs.maColRelScPos.Col() + 1) &&
349  (rScPos.Row() == rRefs.maColRelScPos.Row()) &&
350  (nRowInpScCol == rRefs.maRowFirstScPos.Col()) &&
351  (nRowInpScRow == rRefs.maRowFirstScPos.Row()) &&
352  (rScPos.Tab() == rRefs.maRowFirstScPos.Tab()) &&
353  (rScPos.Col() == rRefs.maRowRelScPos.Col()) &&
354  (nFirstScRow == rRefs.maRowRelScPos.Row() + 1) &&
355  (rScPos.Tab() == rRefs.maRowRelScPos.Tab());
356  break;
357  default:
358  bOk = false;
359  }
360 
361  if( bOk )
362  {
363  // extend the cell range
364  OSL_ENSURE( IsAppendable( nXclCol, nXclRow ), "XclExpTableop::TryExtend - wrong cell address" );
365  Extend( rScPos );
366  mnLastAppXclCol = nXclCol;
367  }
368  }
369 
370  return bOk;
371 }
372 
374 {
375  // is the range complete? (last appended cell is in last column)
377  // if last row is incomplete, try to shorten the used range
379  {
381  mbValid = true;
382  }
383 
384  // check if referred cells are outside of own range
385  if( !mbValid )
386  return;
387 
388  switch( mnScMode )
389  {
390  case 0:
393  break;
394  case 1:
397  break;
398  case 2:
403  break;
404  }
405 }
406 
408 {
409  XclExpFormulaCompiler& rFmlaComp = rRoot.GetFormulaCompiler();
410  return mbValid ?
412  rFmlaComp.CreateErrorFormula( EXC_ERR_NA );
413 }
414 
416 {
417  return true;
418 }
419 
421 {
422  if( mbValid )
423  XclExpRangeFmlaBase::Save( rStrm );
424 }
425 
426 bool XclExpTableop::IsAppendable( sal_uInt16 nXclCol, sal_uInt16 nXclRow ) const
427 {
428  return ((nXclCol == mnLastAppXclCol + 1) && (nXclRow == maXclRange.maFirst.mnRow)) ||
429  ((nXclCol == mnLastAppXclCol + 1) && (nXclCol <= maXclRange.maLast.mnCol) && (nXclRow == maXclRange.maLast.mnRow)) ||
430  ((mnLastAppXclCol == maXclRange.maLast.mnCol) && (nXclCol == maXclRange.maFirst.mnCol) && (nXclRow == maXclRange.maLast.mnRow + 1));
431 }
432 
434 {
435  sal_uInt16 nFlags = EXC_TABLEOP_DEFAULTFLAGS;
437  switch( mnScMode )
438  {
439  case 1: ::set_flag( nFlags, EXC_TABLEOP_ROW ); break;
440  case 2: ::set_flag( nFlags, EXC_TABLEOP_BOTH ); break;
441  }
442 
443  WriteRangeAddress( rStrm );
444  rStrm << nFlags;
445  if( mnScMode == 2 )
447  else
448  rStrm << mnColInpXclRow << mnColInpXclCol << sal_uInt32( 0 );
449 }
450 
452  XclExpRoot( rRoot )
453 {
454 }
455 
457  const ScTokenArray& rScTokArr, const ScAddress& rScPos )
458 {
459  XclExpTableopRef xRec;
460 
461  // try to extract cell references of a multiple operations formula
462  XclMultipleOpRefs aRefs;
463  if (XclTokenArrayHelper::GetMultipleOpRefs(GetDoc(), aRefs, rScTokArr, rScPos))
464  {
465  // try to find an existing TABLEOP record for this cell position
466  for( size_t nPos = 0, nSize = maTableopList.GetSize(); !xRec && (nPos < nSize); ++nPos )
467  {
468  XclExpTableop* xTempRec = maTableopList.GetRecord( nPos );
469  if( xTempRec->TryExtend( rScPos, aRefs ) )
470  xRec = xTempRec;
471  }
472 
473  // no record found, or found record not extensible
474  if( !xRec )
475  xRec = TryCreate( rScPos, aRefs );
476  }
477 
478  return xRec;
479 }
480 
482 {
483  for( size_t nPos = 0, nSize = maTableopList.GetSize(); nPos < nSize; ++nPos )
485 }
486 
488 {
489  sal_uInt8 nScMode = 0;
490  bool bOk = (rScPos.Tab() == rRefs.maFmlaScPos.Tab()) &&
491  (rScPos.Tab() == rRefs.maColFirstScPos.Tab()) &&
492  (rScPos.Tab() == rRefs.maColRelScPos.Tab());
493 
494  if( bOk )
495  {
496  if( rRefs.mbDblRefMode )
497  {
498  nScMode = 2;
499  bOk = (rScPos.Col() == rRefs.maFmlaScPos.Col() + 1) &&
500  (rScPos.Row() == rRefs.maFmlaScPos.Row() + 1) &&
501  (rScPos.Col() == rRefs.maColRelScPos.Col() + 1) &&
502  (rScPos.Row() == rRefs.maColRelScPos.Row()) &&
503  (rScPos.Tab() == rRefs.maRowFirstScPos.Tab()) &&
504  (rScPos.Col() == rRefs.maRowRelScPos.Col()) &&
505  (rScPos.Row() == rRefs.maRowRelScPos.Row() + 1) &&
506  (rScPos.Tab() == rRefs.maRowRelScPos.Tab());
507  }
508  else if( (rScPos.Col() == rRefs.maFmlaScPos.Col()) &&
509  (rScPos.Row() == rRefs.maFmlaScPos.Row() + 1) &&
510  (rScPos.Col() == rRefs.maColRelScPos.Col() + 1) &&
511  (rScPos.Row() == rRefs.maColRelScPos.Row()) )
512  {
513  nScMode = 0;
514  }
515  else if( (rScPos.Col() == rRefs.maFmlaScPos.Col() + 1) &&
516  (rScPos.Row() == rRefs.maFmlaScPos.Row()) &&
517  (rScPos.Col() == rRefs.maColRelScPos.Col()) &&
518  (rScPos.Row() == rRefs.maColRelScPos.Row() + 1) )
519  {
520  nScMode = 1;
521  }
522  else
523  {
524  bOk = false;
525  }
526  }
527 
528  XclExpTableopRef xRec;
529  if( bOk )
530  {
531  xRec = new XclExpTableop( rScPos, rRefs, nScMode );
532  maTableopList.AppendRecord( xRec );
533  }
534 
535  return xRec;
536 }
537 
538 // Cell records
539 
541  sal_uInt16 nRecId, std::size_t nContSize, const XclAddress& rXclPos ) :
542  XclExpRecord( nRecId, nContSize + 4 ),
543  maXclPos( rXclPos )
544 {
545 }
546 
548 {
549  return false;
550 }
551 
552 bool XclExpCellBase::TryMerge( const XclExpCellBase& /*rCell*/ )
553 {
554  return false;
555 }
556 
557 void XclExpCellBase::GetBlankXFIndexes( ScfUInt16Vec& /*rXFIndexes*/ ) const
558 {
559  // default: do nothing
560 }
561 
563 {
564  // default: do nothing
565 }
566 
567 // Single cell records ========================================================
568 
570  sal_uInt16 nRecId, std::size_t nContSize, const XclAddress& rXclPos, sal_uInt32 nXFId ) :
571  XclExpCellBase( nRecId, 2, rXclPos ),
572  maXFId( nXFId ),
573  mnContSize( nContSize )
574 {
575 }
576 
578  sal_uInt16 nRecId, std::size_t nContSize, const XclAddress& rXclPos,
579  const ScPatternAttr* pPattern, sal_Int16 nScript, sal_uInt32 nForcedXFId ) :
580  XclExpCellBase( nRecId, 2, rXclPos ),
581  maXFId( nForcedXFId ),
582  mnContSize( nContSize )
583 {
584  if( GetXFId() == EXC_XFID_NOTFOUND )
585  SetXFId( rRoot.GetXFBuffer().Insert( pPattern, nScript ) );
586 }
587 
589 {
590  return GetXclCol();
591 }
592 
594 {
595  return GetXFId();
596 }
597 
599 {
600  return false;
601 }
602 
604 {
605  maXFId.ConvertXFIndex( rRoot );
606 }
607 
609 {
610  OSL_ENSURE_BIFF( rStrm.GetRoot().GetBiff() >= EXC_BIFF3 );
612  XclExpCellBase::Save( rStrm );
613 }
614 
616 {
617  rStrm << static_cast<sal_uInt16> (GetXclRow()) << GetXclCol() << maXFId.mnXFIndex;
618  WriteContents( rStrm );
619 }
620 
622  const XclExpRoot& rRoot, const XclAddress& rXclPos,
623  const ScPatternAttr* pPattern, sal_uInt32 nForcedXFId, double fValue ) :
624  // #i41210# always use latin script for number cells - may look wrong for special number formats...
625  XclExpSingleCellBase( rRoot, EXC_ID3_NUMBER, 8, rXclPos, pPattern, ApiScriptType::LATIN, nForcedXFId ),
626  mfValue( fValue )
627 {
628 }
629 
630 static OString lcl_GetStyleId( const XclExpXmlStream& rStrm, sal_uInt32 nXFIndex )
631 {
632  return OString::number( rStrm.GetRoot().GetXFBuffer()
633  .GetXmlCellIndex( nXFIndex ) );
634 }
635 
636 static OString lcl_GetStyleId( const XclExpXmlStream& rStrm, const XclExpCellBase& rCell )
637 {
638  sal_uInt32 nXFId = rCell.GetFirstXFId();
639  sal_uInt16 nXFIndex = rStrm.GetRoot().GetXFBuffer().GetXFIndex( nXFId );
640  return lcl_GetStyleId( rStrm, nXFIndex );
641 }
642 
644 {
645  sax_fastparser::FSHelperPtr& rWorksheet = rStrm.GetCurrentStream();
646  rWorksheet->startElement( XML_c,
647  XML_r, XclXmlUtils::ToOString(rStrm.GetRoot().GetStringBuf(), GetXclPos()).getStr(),
648  XML_s, lcl_GetStyleId(rStrm, *this),
649  XML_t, "n"
650  // OOXTODO: XML_cm, XML_vm, XML_ph
651  );
652  rWorksheet->startElement(XML_v);
653  rWorksheet->write( mfValue );
654  rWorksheet->endElement( XML_v );
655  rWorksheet->endElement( XML_c );
656 }
657 
659 {
660  rStrm << mfValue;
661 }
662 
664  const XclExpRoot& rRoot, const XclAddress& rXclPos,
665  const ScPatternAttr* pPattern, sal_uInt32 nForcedXFId, bool bValue ) :
666  // #i41210# always use latin script for boolean cells
667  XclExpSingleCellBase( rRoot, EXC_ID3_BOOLERR, 2, rXclPos, pPattern, ApiScriptType::LATIN, nForcedXFId ),
668  mbValue( bValue )
669 {
670 }
671 
673 {
674  sax_fastparser::FSHelperPtr& rWorksheet = rStrm.GetCurrentStream();
675  rWorksheet->startElement( XML_c,
676  XML_r, XclXmlUtils::ToOString(rStrm.GetRoot().GetStringBuf(), GetXclPos()).getStr(),
677  XML_s, lcl_GetStyleId(rStrm, *this),
678  XML_t, "b"
679  // OOXTODO: XML_cm, XML_vm, XML_ph
680  );
681  rWorksheet->startElement( XML_v );
682  rWorksheet->write( mbValue ? "1" : "0" );
683  rWorksheet->endElement( XML_v );
684  rWorksheet->endElement( XML_c );
685 }
686 
688 {
689  rStrm << sal_uInt16( mbValue ? 1 : 0 ) << EXC_BOOLERR_BOOL;
690 }
691 
693  const XclExpRoot& rRoot, const XclAddress& rXclPos,
694  const ScPatternAttr* pPattern, sal_uInt32 nForcedXFId, const OUString& rStr ) :
695  XclExpSingleCellBase( EXC_ID3_LABEL, 0, rXclPos, nForcedXFId )
696 {
697  sal_uInt16 nMaxLen = (rRoot.GetBiff() == EXC_BIFF8) ? EXC_STR_MAXLEN : EXC_LABEL_MAXLEN;
699  rRoot, rStr, pPattern, XclStrFlags::NONE, nMaxLen);
700  Init( rRoot, pPattern, xText );
701 }
702 
704  const XclExpRoot& rRoot, const XclAddress& rXclPos,
705  const ScPatternAttr* pPattern, sal_uInt32 nForcedXFId,
706  const EditTextObject* pEditText, XclExpHyperlinkHelper& rLinkHelper ) :
707  XclExpSingleCellBase( EXC_ID3_LABEL, 0, rXclPos, nForcedXFId )
708 {
709  sal_uInt16 nMaxLen = (rRoot.GetBiff() == EXC_BIFF8) ? EXC_STR_MAXLEN : EXC_LABEL_MAXLEN;
710 
711  XclExpStringRef xText;
712  if (pEditText)
714  rRoot, *pEditText, pPattern, rLinkHelper, XclStrFlags::NONE, nMaxLen);
715  else
717  rRoot, EMPTY_OUSTRING, pPattern, XclStrFlags::NONE, nMaxLen);
718 
719  Init( rRoot, pPattern, xText );
720 }
721 
723 {
724  return mbLineBreak || mxText->IsWrapped();
725 }
726 
728  const ScPatternAttr* pPattern, XclExpStringRef const & xText )
729 {
730  OSL_ENSURE( xText && xText->Len(), "XclExpLabelCell::XclExpLabelCell - empty string passed" );
731  mxText = xText;
732  mnSstIndex = 0;
733 
734  const XclFormatRunVec& rFormats = mxText->GetFormats();
735  // remove formatting of the leading run if the entire string
736  // is equally formatted
737  sal_uInt16 nXclFont = EXC_FONT_NOTFOUND;
738  if( rFormats.size() == 1 )
739  nXclFont = mxText->RemoveLeadingFont();
740  else
741  nXclFont = mxText->GetLeadingFont();
742 
743  // create cell format
744  if( GetXFId() == EXC_XFID_NOTFOUND )
745  {
746  OSL_ENSURE( nXclFont != EXC_FONT_NOTFOUND, "XclExpLabelCell::Init - leading font not found" );
747  bool bForceLineBreak = mxText->IsWrapped();
748  SetXFId( rRoot.GetXFBuffer().InsertWithFont( pPattern, ApiScriptType::WEAK, nXclFont, bForceLineBreak ) );
749  }
750 
751  // get auto-wrap attribute from cell format
752  const XclExpXF* pXF = rRoot.GetXFBuffer().GetXFById( GetXFId() );
753  mbLineBreak = pXF && pXF->GetAlignmentData().mbLineBreak;
754 
755  // initialize the record contents
756  switch( rRoot.GetBiff() )
757  {
758  case EXC_BIFF5:
759  // BIFF5-BIFF7: create a LABEL or RSTRING record
760  OSL_ENSURE( mxText->Len() <= EXC_LABEL_MAXLEN, "XclExpLabelCell::XclExpLabelCell - string too long" );
761  SetContSize( mxText->GetSize() );
762  // formatted string is exported in an RSTRING record
763  if( mxText->IsRich() )
764  {
765  OSL_ENSURE( mxText->GetFormatsCount() <= EXC_LABEL_MAXLEN, "XclExpLabelCell::WriteContents - too many formats" );
766  mxText->LimitFormatCount( EXC_LABEL_MAXLEN );
768  SetContSize( GetContSize() + 1 + 2 * mxText->GetFormatsCount() );
769  }
770  break;
771  case EXC_BIFF8:
772  // BIFF8+: create a LABELSST record
773  mnSstIndex = rRoot.GetSst().Insert( xText );
775  SetContSize( 4 );
776  break;
777  default: DBG_ERROR_BIFF();
778  }
779 }
780 
782 {
783  sax_fastparser::FSHelperPtr& rWorksheet = rStrm.GetCurrentStream();
784  rWorksheet->startElement( XML_c,
785  XML_r, XclXmlUtils::ToOString(rStrm.GetRoot().GetStringBuf(), GetXclPos()).getStr(),
786  XML_s, lcl_GetStyleId(rStrm, *this),
787  XML_t, "s"
788  // OOXTODO: XML_cm, XML_vm, XML_ph
789  );
790  rWorksheet->startElement( XML_v );
791  rWorksheet->write( static_cast<sal_Int32>(mnSstIndex) );
792  rWorksheet->endElement( XML_v );
793  rWorksheet->endElement( XML_c );
794 }
795 
797 {
798  switch( rStrm.GetRoot().GetBiff() )
799  {
800  case EXC_BIFF5:
801  rStrm << *mxText;
802  if( mxText->IsRich() )
803  {
804  rStrm << static_cast< sal_uInt8 >( mxText->GetFormatsCount() );
805  mxText->WriteFormats( rStrm );
806  }
807  break;
808  case EXC_BIFF8:
809  rStrm << mnSstIndex;
810  break;
811  default: DBG_ERROR_BIFF();
812  }
813 }
814 
816  const XclExpRoot& rRoot, const XclAddress& rXclPos,
817  const ScPatternAttr* pPattern, sal_uInt32 nForcedXFId,
818  const ScFormulaCell& rScFmlaCell,
819  XclExpArrayBuffer& rArrayBfr,
820  XclExpShrfmlaBuffer& rShrfmlaBfr,
821  XclExpTableopBuffer& rTableopBfr ) :
822  XclExpSingleCellBase( EXC_ID2_FORMULA, 0, rXclPos, nForcedXFId ),
823  mrScFmlaCell( const_cast< ScFormulaCell& >( rScFmlaCell ) )
824 {
825  // *** Find result number format overwriting cell number format *** -------
826 
827  if( GetXFId() == EXC_XFID_NOTFOUND )
828  {
829  SvNumberFormatter& rFormatter = rRoot.GetFormatter();
830  XclExpNumFmtBuffer& rNumFmtBfr = rRoot.GetNumFmtBuffer();
831 
832  // current cell number format
833  sal_uInt32 nScNumFmt = pPattern ?
834  pPattern->GetItemSet().Get( ATTR_VALUE_FORMAT ).GetValue() :
835  rNumFmtBfr.GetStandardFormat();
836 
837  // alternative number format passed to XF buffer
838  sal_uInt32 nAltScNumFmt = NUMBERFORMAT_ENTRY_NOT_FOUND;
839  /* Xcl doesn't know Boolean number formats, we write
840  "TRUE";"FALSE" (language dependent). Don't do it for automatic
841  formula formats, because Excel gets them right. */
842  /* #i8640# Don't set text format, if we have string results. */
844  if( ((nScNumFmt % SV_COUNTRY_LANGUAGE_OFFSET) == 0) &&
845  (nFormatType != SvNumFormatType::LOGICAL) &&
846  (nFormatType != SvNumFormatType::TEXT) )
847  nAltScNumFmt = nScNumFmt;
848  /* If cell number format is Boolean and automatic formula
849  format is Boolean don't write that ugly special format. */
850  else if( (nFormatType == SvNumFormatType::LOGICAL) &&
851  (rFormatter.GetType( nScNumFmt ) == SvNumFormatType::LOGICAL) )
852  nAltScNumFmt = rNumFmtBfr.GetStandardFormat();
853 
854  // #i41420# find script type according to result type (always latin for numeric results)
855  sal_Int16 nScript = ApiScriptType::LATIN;
856  bool bForceLineBreak = false;
857  if( nFormatType == SvNumFormatType::TEXT )
858  {
859  OUString aResult = mrScFmlaCell.GetString().getString();
860  bForceLineBreak = mrScFmlaCell.IsMultilineResult();
861  nScript = XclExpStringHelper::GetLeadingScriptType( rRoot, aResult );
862  }
863  SetXFId( rRoot.GetXFBuffer().InsertWithNumFmt( pPattern, nScript, nAltScNumFmt, bForceLineBreak ) );
864  }
865 
866  // *** Convert the formula token array *** --------------------------------
867 
868  ScAddress aScPos( static_cast< SCCOL >( rXclPos.mnCol ), static_cast< SCROW >( rXclPos.mnRow ), rRoot.GetCurrScTab() );
869  const ScTokenArray& rScTokArr = *mrScFmlaCell.GetCode();
870 
871  // first try to create multiple operations
872  mxAddRec = rTableopBfr.CreateOrExtendTableop( rScTokArr, aScPos );
873 
874  // no multiple operation found - try to create matrix formula
875  if( !mxAddRec )
876  switch( mrScFmlaCell.GetMatrixFlag() )
877  {
879  {
880  // origin of the matrix - find the used matrix range
881  SCCOL nMatWidth;
882  SCROW nMatHeight;
883  mrScFmlaCell.GetMatColsRows( nMatWidth, nMatHeight );
884  OSL_ENSURE( nMatWidth && nMatHeight, "XclExpFormulaCell::XclExpFormulaCell - empty matrix" );
885  ScRange aMatScRange( aScPos );
886  ScAddress& rMatEnd = aMatScRange.aEnd;
887  rMatEnd.IncCol( static_cast< SCCOL >( nMatWidth - 1 ) );
888  rMatEnd.IncRow( static_cast< SCROW >( nMatHeight - 1 ) );
889  // reduce to valid range (range keeps valid, because start position IS valid)
890  rRoot.GetAddressConverter().ValidateRange( aMatScRange, true );
891  // create the ARRAY record
892  mxAddRec = rArrayBfr.CreateArray( rScTokArr, aMatScRange );
893  }
894  break;
896  {
897  // other formula cell covered by a matrix - find the ARRAY record
898  mxAddRec = rArrayBfr.FindArray(rScTokArr, aScPos);
899  // should always be found, if Calc document is not broken
900  OSL_ENSURE( mxAddRec, "XclExpFormulaCell::XclExpFormulaCell - no matrix found" );
901  }
902  break;
903  default:;
904  }
905 
906  // no matrix found - try to create shared formula
907  if( !mxAddRec )
908  mxAddRec = rShrfmlaBfr.CreateOrExtendShrfmla(mrScFmlaCell, aScPos);
909 
910  // no shared formula found - create a simple cell formula
911  if( !mxAddRec )
912  mxTokArr = rRoot.GetFormulaCompiler().CreateFormula( EXC_FMLATYPE_CELL, rScTokArr, &aScPos );
913 }
914 
916 {
917  // create token array for FORMULA cells with additional record
918  if( mxAddRec )
919  mxTokArr = mxAddRec->CreateCellTokenArray( rStrm.GetRoot() );
920 
921  // FORMULA record itself
922  OSL_ENSURE( mxTokArr, "XclExpFormulaCell::Save - missing token array" );
923  if( !mxTokArr )
925  SetContSize( 16 + mxTokArr->GetSize() );
927 
928  // additional record (ARRAY, SHRFMLA, or TABLEOP), only for first FORMULA record
929  if( mxAddRec && mxAddRec->IsBasePos( GetXclCol(), GetXclRow() ) )
930  mxAddRec->Save( rStrm );
931 
932  // STRING record for string result
933  if( mxStringRec )
934  mxStringRec->Save( rStrm );
935 }
936 
938 {
939  const char* sType = nullptr;
940  OUString sValue;
942  sax_fastparser::FSHelperPtr& rWorksheet = rStrm.GetCurrentStream();
943  rWorksheet->startElement( XML_c,
944  XML_r, XclXmlUtils::ToOString(rStrm.GetRoot().GetStringBuf(), GetXclPos()).getStr(),
945  XML_s, lcl_GetStyleId(rStrm, *this),
946  XML_t, sType
947  // OOXTODO: XML_cm, XML_vm, XML_ph
948  );
949 
950  bool bWriteFormula = true;
951  bool bTagStarted = false;
952  ScAddress aScPos( static_cast< SCCOL >( GetXclPos().mnCol ),
953  static_cast< SCROW >( GetXclPos().mnRow ), rStrm.GetRoot().GetCurrScTab() );
954 
955  switch (mrScFmlaCell.GetMatrixFlag())
956  {
957  case ScMatrixMode::NONE:
958  break;
960  bWriteFormula = false;
961  break;
963  {
964  // origin of the matrix - find the used matrix range
965  SCCOL nMatWidth;
966  SCROW nMatHeight;
967  mrScFmlaCell.GetMatColsRows( nMatWidth, nMatHeight );
968  OSL_ENSURE( nMatWidth && nMatHeight, "XclExpFormulaCell::XclExpFormulaCell - empty matrix" );
969  ScRange aMatScRange( aScPos );
970  ScAddress& rMatEnd = aMatScRange.aEnd;
971  rMatEnd.IncCol( static_cast< SCCOL >( nMatWidth - 1 ) );
972  rMatEnd.IncRow( static_cast< SCROW >( nMatHeight - 1 ) );
973  // reduce to valid range (range keeps valid, because start position IS valid
974  rStrm.GetRoot().GetAddressConverter().ValidateRange( aMatScRange, true );
975 
976  OStringBuffer sFmlaCellRange;
977  if (rStrm.GetRoot().GetDoc().ValidRange(aMatScRange))
978  {
979  // calculate the cell range.
980  sFmlaCellRange.append( XclXmlUtils::ToOString(
981  rStrm.GetRoot().GetStringBuf(), aMatScRange.aStart ).getStr());
982  sFmlaCellRange.append(":");
983  sFmlaCellRange.append( XclXmlUtils::ToOString(
984  rStrm.GetRoot().GetStringBuf(), aMatScRange.aEnd ).getStr());
985  }
986 
987  if ( aMatScRange.aStart.Col() == GetXclPos().mnCol &&
988  aMatScRange.aStart.Row() == static_cast<SCROW>(GetXclPos().mnRow))
989  {
990  rWorksheet->startElement( XML_f,
991  XML_aca, ToPsz( (mxTokArr && mxTokArr->IsVolatile()) ||
992  (mxAddRec && mxAddRec->IsVolatile())),
993  XML_t, mxAddRec ? "array" : nullptr,
994  XML_ref, !sFmlaCellRange.isEmpty()? sFmlaCellRange.getStr() : nullptr
995  // OOXTODO: XML_dt2D, bool
996  // OOXTODO: XML_dtr, bool
997  // OOXTODO: XML_del1, bool
998  // OOXTODO: XML_del2, bool
999  // OOXTODO: XML_r1, ST_CellRef
1000  // OOXTODO: XML_r2, ST_CellRef
1001  // OOXTODO: XML_ca, bool
1002  // OOXTODO: XML_si, uint
1003  // OOXTODO: XML_bx bool
1004  );
1005  bTagStarted = true;
1006  }
1007  }
1008  break;
1009  }
1010 
1011  if (bWriteFormula)
1012  {
1013  if (!bTagStarted)
1014  {
1015  rWorksheet->startElement( XML_f,
1016  XML_aca, ToPsz( (mxTokArr && mxTokArr->IsVolatile()) ||
1017  (mxAddRec && mxAddRec->IsVolatile()) ) );
1018  }
1019  rWorksheet->writeEscaped( XclXmlUtils::ToOUString(
1022  rWorksheet->endElement( XML_f );
1023  }
1024 
1025  if( strcmp( sType, "inlineStr" ) == 0 )
1026  {
1027  rWorksheet->startElement(XML_is);
1028  rWorksheet->startElement(XML_t);
1029  rWorksheet->writeEscaped( sValue );
1030  rWorksheet->endElement( XML_t );
1031  rWorksheet->endElement( XML_is );
1032  }
1033  else
1034  {
1035  rWorksheet->startElement(XML_v);
1036  rWorksheet->writeEscaped( sValue );
1037  rWorksheet->endElement( XML_v );
1038  }
1039  rWorksheet->endElement( XML_c );
1040 }
1041 
1043 {
1044  FormulaError nScErrCode = mrScFmlaCell.GetErrCode();
1045  if( nScErrCode != FormulaError::NONE )
1046  {
1047  rStrm << EXC_FORMULA_RES_ERROR << sal_uInt8( 0 )
1048  << XclTools::GetXclErrorCode( nScErrCode )
1049  << sal_uInt8( 0 ) << sal_uInt16( 0 )
1050  << sal_uInt16( 0xFFFF );
1051  }
1052  else
1053  {
1054  // result of the formula
1055  switch( mrScFmlaCell.GetFormatType() )
1056  {
1057  case SvNumFormatType::NUMBER:
1058  {
1059  // either value or error code
1060  rStrm << mrScFmlaCell.GetValue();
1061  }
1062  break;
1063 
1064  case SvNumFormatType::TEXT:
1065  {
1066  OUString aResult = mrScFmlaCell.GetString().getString();
1067  if( !aResult.isEmpty() || (rStrm.GetRoot().GetBiff() <= EXC_BIFF5) )
1068  {
1069  rStrm << EXC_FORMULA_RES_STRING;
1070  mxStringRec = new XclExpStringRec( rStrm.GetRoot(), aResult );
1071  }
1072  else
1073  rStrm << EXC_FORMULA_RES_EMPTY; // BIFF8 only
1074  rStrm << sal_uInt8( 0 ) << sal_uInt32( 0 ) << sal_uInt16( 0xFFFF );
1075  }
1076  break;
1077 
1078  case SvNumFormatType::LOGICAL:
1079  {
1080  sal_uInt8 nXclValue = (mrScFmlaCell.GetValue() == 0.0) ? 0 : 1;
1081  rStrm << EXC_FORMULA_RES_BOOL << sal_uInt8( 0 )
1082  << nXclValue << sal_uInt8( 0 ) << sal_uInt16( 0 )
1083  << sal_uInt16( 0xFFFF );
1084  }
1085  break;
1086 
1087  default:
1088  rStrm << mrScFmlaCell.GetValue();
1089  }
1090  }
1091 
1092  // flags and formula token array
1093  sal_uInt16 nFlags = EXC_FORMULA_DEFAULTFLAGS;
1094  ::set_flag( nFlags, EXC_FORMULA_RECALC_ALWAYS, mxTokArr->IsVolatile() || (mxAddRec && mxAddRec->IsVolatile()) );
1095  ::set_flag( nFlags, EXC_FORMULA_SHARED, mxAddRec && (mxAddRec->GetRecId() == EXC_ID_SHRFMLA) );
1096  rStrm << nFlags << sal_uInt32( 0 ) << *mxTokArr;
1097 }
1098 
1099 // Multiple cell records ======================================================
1100 
1102  sal_uInt16 nRecId, sal_uInt16 nMulRecId, std::size_t nContSize, const XclAddress& rXclPos ) :
1103  XclExpCellBase( nRecId, 0, rXclPos ),
1104  mnMulRecId( nMulRecId ),
1105  mnContSize( nContSize )
1106 {
1107 }
1108 
1110 {
1111  return GetXclCol() + GetCellCount() - 1;
1112 }
1113 
1115 {
1116  return maXFIds.empty() ? XclExpXFBuffer::GetDefCellXFId() : maXFIds.front().mnXFId;
1117 }
1118 
1120 {
1121  return maXFIds.empty();
1122 }
1123 
1125 {
1126  for( auto& rXFId : maXFIds )
1127  rXFId.ConvertXFIndex( rRoot );
1128 }
1129 
1131 {
1132  OSL_ENSURE_BIFF( rStrm.GetRoot().GetBiff() >= EXC_BIFF3 );
1133 
1134  XclExpMultiXFIdDeq::const_iterator aEnd = maXFIds.end();
1135  XclExpMultiXFIdDeq::const_iterator aRangeBeg = maXFIds.begin();
1136  XclExpMultiXFIdDeq::const_iterator aRangeEnd = aRangeBeg;
1137  sal_uInt16 nBegXclCol = GetXclCol();
1138  sal_uInt16 nEndXclCol = nBegXclCol;
1139 
1140  while( aRangeEnd != aEnd )
1141  {
1142  // find begin of next used XF range
1143  aRangeBeg = aRangeEnd;
1144  nBegXclCol = nEndXclCol;
1145  while( (aRangeBeg != aEnd) && (aRangeBeg->mnXFIndex == EXC_XF_NOTFOUND) )
1146  {
1147  nBegXclCol = nBegXclCol + aRangeBeg->mnCount;
1148  ++aRangeBeg;
1149  }
1150  // find end of next used XF range
1151  aRangeEnd = aRangeBeg;
1152  nEndXclCol = nBegXclCol;
1153  while( (aRangeEnd != aEnd) && (aRangeEnd->mnXFIndex != EXC_XF_NOTFOUND) )
1154  {
1155  nEndXclCol = nEndXclCol + aRangeEnd->mnCount;
1156  ++aRangeEnd;
1157  }
1158 
1159  // export this range as a record
1160  if( aRangeBeg != aRangeEnd )
1161  {
1162  sal_uInt16 nCount = nEndXclCol - nBegXclCol;
1163  bool bIsMulti = nCount > 1;
1164  std::size_t nTotalSize = GetRecSize() + (2 + mnContSize) * nCount;
1165  if( bIsMulti ) nTotalSize += 2;
1166 
1167  rStrm.StartRecord( bIsMulti ? mnMulRecId : GetRecId(), nTotalSize );
1168  rStrm << static_cast<sal_uInt16> (GetXclRow()) << nBegXclCol;
1169 
1170  sal_uInt16 nRelCol = nBegXclCol - GetXclCol();
1171  for( XclExpMultiXFIdDeq::const_iterator aIt = aRangeBeg; aIt != aRangeEnd; ++aIt )
1172  {
1173  for( sal_uInt16 nIdx = 0; nIdx < aIt->mnCount; ++nIdx )
1174  {
1175  rStrm << aIt->mnXFIndex;
1176  WriteContents( rStrm, nRelCol );
1177  ++nRelCol;
1178  }
1179  }
1180  if( bIsMulti )
1181  rStrm << static_cast< sal_uInt16 >( nEndXclCol - 1 );
1182  rStrm.EndRecord();
1183  }
1184  }
1185 }
1186 
1188 {
1189  XclExpMultiXFIdDeq::const_iterator aEnd = maXFIds.end();
1190  XclExpMultiXFIdDeq::const_iterator aRangeBeg = maXFIds.begin();
1191  XclExpMultiXFIdDeq::const_iterator aRangeEnd = aRangeBeg;
1192  sal_uInt16 nBegXclCol = GetXclCol();
1193  sal_uInt16 nEndXclCol = nBegXclCol;
1194 
1195  while( aRangeEnd != aEnd )
1196  {
1197  // find begin of next used XF range
1198  aRangeBeg = aRangeEnd;
1199  nBegXclCol = nEndXclCol;
1200  while( (aRangeBeg != aEnd) && (aRangeBeg->mnXFIndex == EXC_XF_NOTFOUND) )
1201  {
1202  nBegXclCol = nBegXclCol + aRangeBeg->mnCount;
1203  ++aRangeBeg;
1204  }
1205  // find end of next used XF range
1206  aRangeEnd = aRangeBeg;
1207  nEndXclCol = nBegXclCol;
1208  while( (aRangeEnd != aEnd) && (aRangeEnd->mnXFIndex != EXC_XF_NOTFOUND) )
1209  {
1210  nEndXclCol = nEndXclCol + aRangeEnd->mnCount;
1211  ++aRangeEnd;
1212  }
1213 
1214  // export this range as a record
1215  if( aRangeBeg != aRangeEnd )
1216  {
1217  sal_uInt16 nRelColIdx = nBegXclCol - GetXclCol();
1218  sal_Int32 nRelCol = 0;
1219  for( XclExpMultiXFIdDeq::const_iterator aIt = aRangeBeg; aIt != aRangeEnd; ++aIt )
1220  {
1221  for( sal_uInt16 nIdx = 0; nIdx < aIt->mnCount; ++nIdx )
1222  {
1224  rStrm,
1225  XclAddress( static_cast<sal_uInt16>(nBegXclCol + nRelCol), GetXclRow() ),
1226  aIt->mnXFIndex,
1227  nRelColIdx );
1228  ++nRelCol;
1229  ++nRelColIdx;
1230  }
1231  }
1232  }
1233  }
1234 }
1235 
1237 {
1238  return std::accumulate(maXFIds.begin(), maXFIds.end(), sal_uInt16(0),
1239  [](const sal_uInt16& rSum, const XclExpMultiXFId& rXFId) { return rSum + rXFId.mnCount; });
1240 }
1241 
1243 {
1244  if( maXFIds.empty() || (maXFIds.back().mnXFId != rXFId.mnXFId) )
1245  maXFIds.push_back( rXFId );
1246  else
1247  maXFIds.back().mnCount = maXFIds.back().mnCount + rXFId.mnCount;
1248 }
1249 
1251  const ScPatternAttr* pPattern, sal_uInt16 nScript, sal_uInt32 nForcedXFId, sal_uInt16 nCount )
1252 {
1253  sal_uInt32 nXFId = (nForcedXFId == EXC_XFID_NOTFOUND) ?
1254  rRoot.GetXFBuffer().Insert( pPattern, nScript ) : nForcedXFId;
1255  AppendXFId( XclExpMultiXFId( nXFId, nCount ) );
1256 }
1257 
1259 {
1260  if( GetLastXclCol() + 1 == rCell.GetXclCol() )
1261  {
1262  maXFIds.insert( maXFIds.end(), rCell.maXFIds.begin(), rCell.maXFIds.end() );
1263  return true;
1264  }
1265  return false;
1266 }
1267 
1269 {
1270  OSL_ENSURE( GetLastXclCol() < rXFIndexes.size(), "XclExpMultiCellBase::GetXFIndexes - vector too small" );
1271  ScfUInt16Vec::iterator aDestIt = rXFIndexes.begin() + GetXclCol();
1272  for( const auto& rXFId : maXFIds )
1273  {
1274  ::std::fill( aDestIt, aDestIt + rXFId.mnCount, rXFId.mnXFIndex );
1275  aDestIt += rXFId.mnCount;
1276  }
1277 }
1278 
1280 {
1281  // save last column before calling maXFIds.clear()
1282  sal_uInt16 nLastXclCol = GetLastXclCol();
1283  OSL_ENSURE( nLastXclCol < rXFIndexes.size(), "XclExpMultiCellBase::RemoveUnusedXFIndexes - XF index vector too small" );
1284 
1285  // build new XF index vector, containing passed XF indexes
1286  maXFIds.clear();
1287  std::for_each(rXFIndexes.begin() + GetXclCol(), rXFIndexes.begin() + nLastXclCol + 1,
1288  [this](const sal_uInt16& rXFIndex) {
1289  XclExpMultiXFId aXFId( 0 );
1290  // AppendXFId() tests XclExpXFIndex::mnXFId, set it too
1291  aXFId.mnXFId = aXFId.mnXFIndex = rXFIndex;
1292  AppendXFId( aXFId );
1293  });
1294 
1295  // remove leading and trailing unused XF indexes
1296  if( !maXFIds.empty() && (maXFIds.front().mnXFIndex == EXC_XF_NOTFOUND) )
1297  {
1298  SetXclCol( GetXclCol() + maXFIds.front().mnCount );
1299  maXFIds.erase(maXFIds.begin(), maXFIds.begin() + 1);
1300  }
1301  if( !maXFIds.empty() && (maXFIds.back().mnXFIndex == EXC_XF_NOTFOUND) )
1302  maXFIds.pop_back();
1303 
1304  // The Save() function will skip all XF indexes equal to EXC_XF_NOTFOUND.
1305 }
1306 
1309 {
1310  OSL_ENSURE( rXFId.mnCount > 0, "XclExpBlankCell::XclExpBlankCell - invalid count" );
1311  AppendXFId( rXFId );
1312 }
1313 
1315  const XclExpRoot& rRoot, const XclAddress& rXclPos, sal_uInt16 nLastXclCol,
1316  const ScPatternAttr* pPattern, sal_uInt32 nForcedXFId ) :
1318 {
1319  OSL_ENSURE( rXclPos.mnCol <= nLastXclCol, "XclExpBlankCell::XclExpBlankCell - invalid column range" );
1320  // #i46627# use default script type instead of ApiScriptType::WEAK
1321  AppendXFId( rRoot, pPattern, rRoot.GetDefApiScript(), nForcedXFId, nLastXclCol - rXclPos.mnCol + 1 );
1322 }
1323 
1325 {
1326  const XclExpBlankCell* pBlankCell = dynamic_cast< const XclExpBlankCell* >( &rCell );
1327  return pBlankCell && TryMergeXFIds( *pBlankCell );
1328 }
1329 
1331 {
1332  GetXFIndexes( rXFIndexes );
1333 }
1334 
1336 {
1337  RemoveUnusedXFIndexes( rXFIndexes );
1338 }
1339 
1340 void XclExpBlankCell::WriteContents( XclExpStream& /*rStrm*/, sal_uInt16 /*nRelCol*/ )
1341 {
1342 }
1343 
1344 void XclExpBlankCell::WriteXmlContents( XclExpXmlStream& rStrm, const XclAddress& rAddress, sal_uInt32 nXFId, sal_uInt16 /* nRelCol */ )
1345 {
1346  sax_fastparser::FSHelperPtr& rWorksheet = rStrm.GetCurrentStream();
1347  rWorksheet->singleElement( XML_c,
1348  XML_r, XclXmlUtils::ToOString(rStrm.GetRoot().GetStringBuf(), rAddress).getStr(),
1349  XML_s, lcl_GetStyleId(rStrm, nXFId) );
1350 }
1351 
1353  const XclExpRoot& rRoot, const XclAddress& rXclPos,
1354  const ScPatternAttr* pPattern, sal_uInt32 nForcedXFId, sal_Int32 nRkValue ) :
1356 {
1357  // #i41210# always use latin script for number cells - may look wrong for special number formats...
1358  AppendXFId( rRoot, pPattern, ApiScriptType::LATIN, nForcedXFId );
1359  maRkValues.push_back( nRkValue );
1360 }
1361 
1363 {
1364  const XclExpRkCell* pRkCell = dynamic_cast< const XclExpRkCell* >( &rCell );
1365  if( pRkCell && TryMergeXFIds( *pRkCell ) )
1366  {
1367  maRkValues.insert( maRkValues.end(), pRkCell->maRkValues.begin(), pRkCell->maRkValues.end() );
1368  return true;
1369  }
1370  return false;
1371 }
1372 
1373 void XclExpRkCell::WriteXmlContents( XclExpXmlStream& rStrm, const XclAddress& rAddress, sal_uInt32 nXFId, sal_uInt16 nRelCol )
1374 {
1375  sax_fastparser::FSHelperPtr& rWorksheet = rStrm.GetCurrentStream();
1376  rWorksheet->startElement( XML_c,
1377  XML_r, XclXmlUtils::ToOString(rStrm.GetRoot().GetStringBuf(), rAddress).getStr(),
1378  XML_s, lcl_GetStyleId(rStrm, nXFId),
1379  XML_t, "n"
1380  // OOXTODO: XML_cm, XML_vm, XML_ph
1381  );
1382  rWorksheet->startElement( XML_v );
1383  rWorksheet->write( XclTools::GetDoubleFromRK( maRkValues[ nRelCol ] ) );
1384  rWorksheet->endElement( XML_v );
1385  rWorksheet->endElement( XML_c );
1386 }
1387 
1388 void XclExpRkCell::WriteContents( XclExpStream& rStrm, sal_uInt16 nRelCol )
1389 {
1390  OSL_ENSURE( nRelCol < maRkValues.size(), "XclExpRkCell::WriteContents - overflow error" );
1391  rStrm << maRkValues[ nRelCol ];
1392 }
1393 
1394 // Rows and Columns
1395 
1397  mpScOLArray( nullptr ),
1398  maLevelInfos( SC_OL_MAXDEPTH ),
1399  mnCurrLevel( 0 ),
1400  mbCurrCollapse( false )
1401 {
1402  if( const ScOutlineTable* pOutlineTable = rRoot.GetDoc().GetOutlineTable( rRoot.GetCurrScTab() ) )
1403  mpScOLArray = &(bRows ? pOutlineTable->GetRowArray() : pOutlineTable->GetColArray());
1404 
1405  if( mpScOLArray )
1406  for( size_t nLevel = 0; nLevel < SC_OL_MAXDEPTH; ++nLevel )
1407  if( const ScOutlineEntry* pEntry = mpScOLArray->GetEntryByPos( nLevel, 0 ) )
1408  maLevelInfos[ nLevel ].mnScEndPos = pEntry->GetEnd();
1409 }
1410 
1412 {
1413  if( !mpScOLArray )
1414  return;
1415 
1416  // find open level index for passed position
1417  size_t nNewOpenScLevel = 0; // new open level (0-based Calc index)
1418  sal_uInt8 nNewLevel = 0; // new open level (1-based Excel index)
1419 
1420  if( mpScOLArray->FindTouchedLevel( nScPos, nScPos, nNewOpenScLevel ) )
1421  nNewLevel = static_cast< sal_uInt8 >( nNewOpenScLevel + 1 );
1422  // else nNewLevel keeps 0 to show that there are no groups
1423 
1424  mbCurrCollapse = false;
1425  if( nNewLevel >= mnCurrLevel )
1426  {
1427  // new level(s) opened, or no level closed - update all level infos
1428  for( size_t nScLevel = 0; nScLevel <= nNewOpenScLevel; ++nScLevel )
1429  {
1430  /* In each level: check if a new group is started (there may be
1431  neighbored groups without gap - therefore check ALL levels). */
1432  if( maLevelInfos[ nScLevel ].mnScEndPos < nScPos )
1433  {
1434  if( const ScOutlineEntry* pEntry = mpScOLArray->GetEntryByPos( nScLevel, nScPos ) )
1435  {
1436  maLevelInfos[ nScLevel ].mnScEndPos = pEntry->GetEnd();
1437  maLevelInfos[ nScLevel ].mbHidden = pEntry->IsHidden();
1438  }
1439  }
1440  }
1441  }
1442  else
1443  {
1444  // level(s) closed - check if any of the closed levels are collapsed
1445  // Calc uses 0-based level indexes
1446  sal_uInt16 nOldOpenScLevel = mnCurrLevel - 1;
1447  for( sal_uInt16 nScLevel = nNewOpenScLevel + 1; !mbCurrCollapse && (nScLevel <= nOldOpenScLevel); ++nScLevel )
1448  mbCurrCollapse = maLevelInfos[ nScLevel ].mbHidden;
1449  }
1450 
1451  // cache new opened level
1452  mnCurrLevel = nNewLevel;
1453 }
1454 
1456  XclExpRecord( EXC_ID_GUTS, 8 ),
1457  mnColLevels( 0 ),
1458  mnColWidth( 0 ),
1459  mnRowLevels( 0 ),
1460  mnRowWidth( 0 )
1461 {
1462  const ScOutlineTable* pOutlineTable = rRoot.GetDoc().GetOutlineTable( rRoot.GetCurrScTab() );
1463  if(!pOutlineTable)
1464  return;
1465 
1466  // column outline groups
1467  const ScOutlineArray& rColArray = pOutlineTable->GetColArray();
1468  mnColLevels = ulimit_cast< sal_uInt16 >( rColArray.GetDepth(), EXC_OUTLINE_MAX );
1469  if( mnColLevels )
1470  {
1471  ++mnColLevels;
1472  mnColWidth = 12 * mnColLevels + 5;
1473  }
1474 
1475  // row outline groups
1476  const ScOutlineArray& rRowArray = pOutlineTable->GetRowArray();
1477  mnRowLevels = ulimit_cast< sal_uInt16 >( rRowArray.GetDepth(), EXC_OUTLINE_MAX );
1478  if( mnRowLevels )
1479  {
1480  ++mnRowLevels;
1481  mnRowWidth = 12 * mnRowLevels + 5;
1482  }
1483 }
1484 
1486 {
1487  rStrm << mnRowWidth << mnColWidth << mnRowLevels << mnColLevels;
1488 }
1489 
1491  mrRoot(rRoot),
1492  mnFirstUsedXclRow( 0 ),
1493  mnFirstFreeXclRow( 0 ),
1494  mnFirstUsedXclCol( 0 ),
1495  mnFirstFreeXclCol( 0 )
1496 {
1497  switch( rRoot.GetBiff() )
1498  {
1499  case EXC_BIFF2: SetRecHeader( EXC_ID2_DIMENSIONS, 8 ); break;
1500  case EXC_BIFF3:
1501  case EXC_BIFF4:
1502  case EXC_BIFF5: SetRecHeader( EXC_ID3_DIMENSIONS, 10 ); break;
1503  case EXC_BIFF8: SetRecHeader( EXC_ID3_DIMENSIONS, 14 ); break;
1504  default: DBG_ERROR_BIFF();
1505  }
1506 }
1507 
1509  sal_uInt16 nFirstUsedXclCol, sal_uInt32 nFirstUsedXclRow,
1510  sal_uInt16 nFirstFreeXclCol, sal_uInt32 nFirstFreeXclRow )
1511 {
1512  mnFirstUsedXclRow = nFirstUsedXclRow;
1513  mnFirstFreeXclRow = nFirstFreeXclRow;
1514  mnFirstUsedXclCol = nFirstUsedXclCol;
1515  mnFirstFreeXclCol = nFirstFreeXclCol;
1516 }
1517 
1519 {
1520  ScRange aRange;
1521  aRange.aStart.SetRow( static_cast<SCROW>(mnFirstUsedXclRow) );
1522  aRange.aStart.SetCol( static_cast<SCCOL>(mnFirstUsedXclCol) );
1523 
1525  {
1526  aRange.aEnd.SetRow( static_cast<SCROW>(mnFirstFreeXclRow-1) );
1527  aRange.aEnd.SetCol( static_cast<SCCOL>(mnFirstFreeXclCol-1) );
1528  }
1529 
1530  aRange.PutInOrder();
1531  rStrm.GetCurrentStream()->singleElement( XML_dimension,
1532  // To be compatible with MS Office 2007,
1533  // we need full address notation format
1534  // e.g. "A1:AMJ177" and not partial like: "1:177".
1535  XML_ref, XclXmlUtils::ToOString(mrRoot.GetDoc(), aRange, true) );
1536 }
1537 
1539 {
1540  XclBiff eBiff = rStrm.GetRoot().GetBiff();
1541  if( eBiff == EXC_BIFF8 )
1543  else
1544  rStrm << static_cast< sal_uInt16 >( mnFirstUsedXclRow ) << static_cast< sal_uInt16 >( mnFirstFreeXclRow );
1546  if( eBiff >= EXC_BIFF3 )
1547  rStrm << sal_uInt16( 0 );
1548 }
1549 
1550 namespace {
1551 
1552 double lclGetCChCorrection(const XclExpRoot& rRoot)
1553 {
1554  // Convert the correction from 1/256ths of a character size to count of chars
1555  // TODO: make to fit ECMA-376-1:2016 18.3.1.81 sheetFormatPr (Sheet Format Properties):
1556  // 5 pixels are added to the base width: 2 for margin padding on each side, plus 1 for gridline
1557  // So this should depend on rRoot.GetCharWidth(), not on font height
1558 
1559  tools::Long nFontHt = rRoot.GetFontBuffer().GetAppFontData().mnHeight;
1560  return XclTools::GetXclDefColWidthCorrection(nFontHt) / 256.0;
1561 }
1562 
1563 } // namespace
1564 
1566  XclExpDoubleRecord(EXC_ID_DEFCOLWIDTH, EXC_DEFCOLWIDTH_DEF + lclGetCChCorrection(rRoot)),
1567  XclExpRoot( rRoot )
1568 {
1569 }
1570 
1571 bool XclExpDefcolwidth::IsDefWidth( sal_uInt16 nXclColWidth ) const
1572 {
1573  // This formula is taking number of characters with GetValue()
1574  // and it is translating it into default column width.
1575  // https://msdn.microsoft.com/en-us/library/documentformat.openxml.spreadsheet.column.aspx
1576  double defaultColumnWidth = 256.0 * GetValue();
1577 
1578  // exactly matched, if difference is less than 1/16 of a character to the left or to the right
1579  return std::abs(defaultColumnWidth - nXclColWidth) < 256.0 * 1.0 / 16.0;
1580 }
1581 
1582 void XclExpDefcolwidth::SetDefWidth( sal_uInt16 nXclColWidth, bool bXLS )
1583 {
1584  double fCCh = nXclColWidth / 256.0;
1585  if (bXLS)
1586  {
1587  const double fCorrection = lclGetCChCorrection(GetRoot());
1588  const double fCorrectedCCh = fCCh - fCorrection;
1589  // Now get the value which would be stored in XLS DefColWidth struct
1590  double fCChRound = std::round(fCorrectedCCh);
1591  // If default width was set to a value that is not representable as integral CCh between 0
1592  // and 255, then just ignore that value, and use an arbitrary default. That way, the stored
1593  // default might not represent the most used column width (or any used column width), but
1594  // that's OK, and it just means that those columns will explicitly store their width in
1595  // 1/256ths of char, and have fUserSet in their ColInfo records.
1596  if (fCChRound < 0.0 || fCChRound > 255.0 || std::abs(fCChRound - fCorrectedCCh) > 1.0 / 512)
1597  fCChRound = 8.0;
1598  fCCh = fCChRound + fCorrection;
1599  }
1600 
1601  SetValue(fCCh);
1602 }
1603 
1605 {
1606  double fCorrectedCCh = GetValue() - lclGetCChCorrection(GetRoot());
1607  // Convert double to sal_uInt16
1608  XclExpUInt16Record aUInt16Rec(GetRecId(),
1609  static_cast<sal_uInt16>(std::round(fCorrectedCCh)));
1610  aUInt16Rec.Save(rStrm);
1611 }
1612 
1614  SCCOL nScCol, SCROW nLastScRow, XclExpColOutlineBuffer& rOutlineBfr ) :
1616  XclExpRoot( rRoot ),
1617  mbCustomWidth( false ),
1618  mnWidth( 0 ),
1619  mnScWidth( 0 ),
1620  mnFlags( 0 ),
1621  mnOutlineLevel( 0 ),
1622  mnFirstXclCol( static_cast< sal_uInt16 >( nScCol ) ),
1623  mnLastXclCol( static_cast< sal_uInt16 >( nScCol ) )
1624 {
1625  ScDocument& rDoc = GetDoc();
1626  SCTAB nScTab = GetCurrScTab();
1627 
1628  // column default format
1630  rDoc.GetMostUsedPattern( nScCol, 0, nLastScRow, nScTab ), GetDefApiScript() );
1631 
1632  // column width. If column is hidden then we should return real value (not zero)
1633  sal_uInt16 nScWidth = rDoc.GetColWidth( nScCol, nScTab, false );
1635  mnScWidth = convertTwipToMm100(nScWidth);
1636 
1637  // column flags
1638  ::set_flag( mnFlags, EXC_COLINFO_HIDDEN, rDoc.ColHidden(nScCol, nScTab) );
1639 
1640  // outline data
1641  rOutlineBfr.Update( nScCol );
1643  ::insert_value( mnFlags, rOutlineBfr.GetLevel(), 8, 3 );
1644  mnOutlineLevel = rOutlineBfr.GetLevel();
1645 }
1646 
1648 {
1650 }
1651 
1652 bool XclExpColinfo::IsDefault( const XclExpDefcolwidth& rDefColWidth )
1653 {
1654  mbCustomWidth = !rDefColWidth.IsDefWidth(mnWidth);
1655  return (maXFId.mnXFIndex == EXC_XF_DEFAULTCELL) &&
1656  (mnFlags == 0) &&
1657  (mnOutlineLevel == 0) &&
1658  !mbCustomWidth;
1659 }
1660 
1662 {
1663  if( (maXFId.mnXFIndex == rColInfo.maXFId.mnXFIndex) &&
1664  (mnWidth == rColInfo.mnWidth) &&
1665  (mnFlags == rColInfo.mnFlags) &&
1666  (mnOutlineLevel == rColInfo.mnOutlineLevel) &&
1667  (mnLastXclCol + 1 == rColInfo.mnFirstXclCol) )
1668  {
1669  mnLastXclCol = rColInfo.mnLastXclCol;
1670  return true;
1671  }
1672  return false;
1673 }
1674 
1676 {
1677  // if last column is equal to last possible column, Excel adds one more
1678  sal_uInt16 nLastXclCol = mnLastXclCol;
1679  if( nLastXclCol == static_cast< sal_uInt16 >( rStrm.GetRoot().GetMaxPos().Col() ) )
1680  ++nLastXclCol;
1681 
1682  rStrm << mnFirstXclCol
1683  << nLastXclCol
1684  << mnWidth
1685  << maXFId.mnXFIndex
1686  << mnFlags
1687  << sal_uInt16( 0 );
1688 }
1689 
1691 {
1692  const double nExcelColumnWidth = mnScWidth / static_cast< double >( convertTwipToMm100( GetCharWidth() ) );
1693 
1694  // tdf#101363 In MS specification the output value is set with double precision after delimiter:
1695  // =Truncate(({width in pixels} - 5)/{Maximum Digit Width} * 100 + 0.5)/100
1696  // Explanation of magic numbers:
1697  // 5 number - are 4 pixels of margin padding (two on each side), plus 1 pixel padding for the gridlines.
1698  // It is unknown if it should be applied during LibreOffice export
1699  // 100 number - used to limit precision to 0.01 with formula =Truncate( {value}*100+0.5 ) / 100
1700  // 0.5 number (0.005 to output value) - used to increase value before truncating,
1701  // to avoid situation when 2.997 will be truncated to 2.99 and not to 3.00
1702  const double nTruncatedExcelColumnWidth = std::trunc( nExcelColumnWidth * 100.0 + 0.5 ) / 100.0;
1703  rStrm.GetCurrentStream()->singleElement( XML_col,
1704  // OOXTODO: XML_bestFit,
1705  XML_collapsed, ToPsz( ::get_flag( mnFlags, EXC_COLINFO_COLLAPSED ) ),
1706  XML_customWidth, ToPsz( mbCustomWidth ),
1707  XML_hidden, ToPsz( ::get_flag( mnFlags, EXC_COLINFO_HIDDEN ) ),
1708  XML_outlineLevel, OString::number(mnOutlineLevel),
1709  XML_max, OString::number(mnLastXclCol + 1),
1710  XML_min, OString::number(mnFirstXclCol + 1),
1711  // OOXTODO: XML_phonetic,
1712  XML_style, lcl_GetStyleId(rStrm, maXFId.mnXFIndex),
1713  XML_width, OString::number(nTruncatedExcelColumnWidth) );
1714 }
1715 
1717  XclExpRoot( rRoot ),
1718  maDefcolwidth( rRoot ),
1719  maOutlineBfr( rRoot ),
1720  mnHighestOutlineLevel( 0 )
1721 {
1722 }
1723 
1725 {
1726 
1727  for( sal_uInt16 nScCol = 0, nLastScCol = GetMaxPos().Col(); nScCol <= nLastScCol; ++nScCol )
1728  {
1729  maColInfos.AppendNewRecord( new XclExpColinfo( GetRoot(), nScCol, nLastScRow, maOutlineBfr ) );
1731  {
1733  }
1734  }
1735 }
1736 
1737 void XclExpColinfoBuffer::Finalize( ScfUInt16Vec& rXFIndexes, bool bXLS )
1738 {
1739  rXFIndexes.clear();
1740  rXFIndexes.reserve( maColInfos.GetSize() );
1741 
1742  size_t nPos, nSize;
1743 
1744  // do not cache the record list size, it may change in the loop
1745  for( nPos = 0; nPos < maColInfos.GetSize(); ++nPos )
1746  {
1747  XclExpColinfoRef xRec = maColInfos.GetRecord( nPos );
1748  xRec->ConvertXFIndexes();
1749 
1750  // try to merge with previous record
1751  if( nPos > 0 )
1752  {
1753  XclExpColinfoRef xPrevRec = maColInfos.GetRecord( nPos - 1 );
1754  if( xPrevRec->TryMerge( *xRec ) )
1755  // adjust nPos to get the next COLINFO record at the same position
1756  maColInfos.RemoveRecord( nPos-- );
1757  }
1758  }
1759 
1760  // put XF indexes into passed vector, collect use count of all different widths
1761  std::map< sal_uInt16, sal_uInt16 > aWidthMap;
1762  sal_uInt16 nMaxColCount = 0;
1763  sal_uInt16 nMaxUsedWidth = 0;
1764  for( nPos = 0, nSize = maColInfos.GetSize(); nPos < nSize; ++nPos )
1765  {
1766  XclExpColinfoRef xRec = maColInfos.GetRecord( nPos );
1767  sal_uInt16 nColCount = xRec->GetColCount();
1768 
1769  // add XF index to passed vector
1770  rXFIndexes.resize( rXFIndexes.size() + nColCount, xRec->GetXFIndex() );
1771 
1772  // collect use count of column width
1773  sal_uInt16 nWidth = xRec->GetColWidth();
1774  sal_uInt16& rnMapCount = aWidthMap[ nWidth ];
1775  rnMapCount = rnMapCount + nColCount;
1776  if( rnMapCount > nMaxColCount )
1777  {
1778  nMaxColCount = rnMapCount;
1779  nMaxUsedWidth = nWidth;
1780  }
1781  }
1782  maDefcolwidth.SetDefWidth( nMaxUsedWidth, bXLS );
1783 
1784  // remove all default COLINFO records
1785  nPos = 0;
1786  while( nPos < maColInfos.GetSize() )
1787  {
1788  XclExpColinfoRef xRec = maColInfos.GetRecord( nPos );
1789  if( xRec->IsDefault( maDefcolwidth ) )
1790  maColInfos.RemoveRecord( nPos );
1791  else
1792  ++nPos;
1793  }
1794 }
1795 
1797 {
1798  // DEFCOLWIDTH
1799  maDefcolwidth.Save( rStrm );
1800  // COLINFO records
1801  maColInfos.Save( rStrm );
1802 }
1803 
1805 {
1806  if( maColInfos.IsEmpty() )
1807  return;
1808 
1809  sax_fastparser::FSHelperPtr& rWorksheet = rStrm.GetCurrentStream();
1810  rWorksheet->startElement(XML_cols);
1811  maColInfos.SaveXml( rStrm );
1812  rWorksheet->endElement( XML_cols );
1813 }
1814 
1818 {
1819 }
1820 
1823  mnHeight( rRow.GetHeight() )
1824 {
1827 }
1828 
1829 static bool operator<( const XclExpDefaultRowData& rLeft, const XclExpDefaultRowData& rRight )
1830 {
1831  return (rLeft.mnHeight < rRight.mnHeight) ||
1832  ((rLeft.mnHeight == rRight.mnHeight) && (rLeft.mnFlags < rRight.mnFlags));
1833 }
1834 
1837 {
1838 }
1839 
1841 {
1842  maDefData = rDefData;
1843 }
1844 
1846 {
1847  OSL_ENSURE_BIFF( rStrm.GetRoot().GetBiff() >= EXC_BIFF3 );
1848  rStrm << maDefData.mnFlags << maDefData.mnHeight;
1849 }
1850 
1851 XclExpRow::XclExpRow( const XclExpRoot& rRoot, sal_uInt32 nXclRow,
1852  XclExpRowOutlineBuffer& rOutlineBfr, bool bAlwaysEmpty, bool bHidden, sal_uInt16 nHeight ) :
1853  XclExpRecord( EXC_ID3_ROW, 16 ),
1854  XclExpRoot( rRoot ),
1855  mnXclRow( nXclRow ),
1856  mnHeight( nHeight ),
1858  mnXFIndex( EXC_XF_DEFAULTCELL ),
1859  mnOutlineLevel( 0 ),
1860  mnXclRowRpt( 1 ),
1861  mnCurrentRow( nXclRow ),
1862  mbAlwaysEmpty( bAlwaysEmpty ),
1863  mbEnabled( true )
1864 {
1865  SCTAB nScTab = GetCurrScTab();
1866  SCROW nScRow = static_cast< SCROW >( mnXclRow );
1867 
1868  // *** Row flags *** ------------------------------------------------------
1869 
1870  CRFlags nRowFlags = GetDoc().GetRowFlags( nScRow, nScTab );
1871  bool bUserHeight( nRowFlags & CRFlags::ManualSize );
1872  ::set_flag( mnFlags, EXC_ROW_UNSYNCED, bUserHeight );
1873  ::set_flag( mnFlags, EXC_ROW_HIDDEN, bHidden );
1874 
1875  // *** Outline data *** ---------------------------------------------------
1876 
1877  rOutlineBfr.Update( nScRow );
1878  ::set_flag( mnFlags, EXC_ROW_COLLAPSED, rOutlineBfr.IsCollapsed() );
1879  ::insert_value( mnFlags, rOutlineBfr.GetLevel(), 0, 3 );
1880  mnOutlineLevel = rOutlineBfr.GetLevel();
1881 
1882  // *** Progress bar *** ---------------------------------------------------
1883 
1884  XclExpProgressBar& rProgress = GetProgressBar();
1885  rProgress.IncRowRecordCount();
1886  rProgress.Progress();
1887 }
1888 
1889 void XclExpRow::AppendCell( XclExpCellRef const & xCell, bool bIsMergedBase )
1890 {
1891  OSL_ENSURE( !mbAlwaysEmpty, "XclExpRow::AppendCell - row is marked to be always empty" );
1892  // try to merge with last existing cell
1893  InsertCell( xCell, maCellList.GetSize(), bIsMergedBase );
1894 }
1895 
1896 void XclExpRow::Finalize( const ScfUInt16Vec& rColXFIndexes, bool bProgress )
1897 {
1898  size_t nPos, nSize;
1899 
1900  // *** Convert XF identifiers *** -----------------------------------------
1901 
1902  // additionally collect the blank XF indexes
1903  size_t nColCount = GetMaxPos().Col() + 1;
1904  OSL_ENSURE( rColXFIndexes.size() == nColCount, "XclExpRow::Finalize - wrong column XF index count" );
1905 
1906  ScfUInt16Vec aXFIndexes( nColCount, EXC_XF_NOTFOUND );
1907  for( nPos = 0, nSize = maCellList.GetSize(); nPos < nSize; ++nPos )
1908  {
1909  XclExpCellBase* pCell = maCellList.GetRecord( nPos );
1910  pCell->ConvertXFIndexes( GetRoot() );
1911  pCell->GetBlankXFIndexes( aXFIndexes );
1912  }
1913 
1914  // *** Fill gaps with BLANK/MULBLANK cell records *** ---------------------
1915 
1916  /* This is needed because nonexistent cells in Calc are not formatted at all,
1917  but in Excel they would have the column default format. Blank cells that
1918  are equal to the respective column default are removed later in this function. */
1919  if( !mbAlwaysEmpty )
1920  {
1921  // XF identifier representing default cell XF
1923  aXFId.ConvertXFIndex( GetRoot() );
1924 
1925  nPos = 0;
1926  while( nPos <= maCellList.GetSize() ) // don't cache list size, may change in the loop
1927  {
1928  // get column index that follows previous cell
1929  sal_uInt16 nFirstFreeXclCol = (nPos > 0) ? (maCellList.GetRecord( nPos - 1 )->GetLastXclCol() + 1) : 0;
1930  // get own column index
1931  sal_uInt16 nNextUsedXclCol = (nPos < maCellList.GetSize()) ? maCellList.GetRecord( nPos )->GetXclCol() : (GetMaxPos().Col() + 1);
1932 
1933  // is there a gap?
1934  if( nFirstFreeXclCol < nNextUsedXclCol )
1935  {
1936  aXFId.mnCount = nNextUsedXclCol - nFirstFreeXclCol;
1937  XclExpCellRef xNewCell = new XclExpBlankCell( XclAddress( nFirstFreeXclCol, mnXclRow ), aXFId );
1938  // insert the cell, InsertCell() may merge it with existing BLANK records
1939  InsertCell( xNewCell, nPos, false );
1940  // insert default XF indexes into aXFIndexes
1941  ::std::fill( aXFIndexes.begin() + nFirstFreeXclCol,
1942  aXFIndexes.begin() + nNextUsedXclCol, aXFId.mnXFIndex );
1943  // don't step forward with nPos, InsertCell() may remove records
1944  }
1945  else
1946  ++nPos;
1947  }
1948  }
1949 
1950  // *** Find default row format *** ----------------------------------------
1951 
1952  // find most used XF index in the row
1953  std::map< sal_uInt16, size_t > aIndexMap;
1954  sal_uInt16 nRowXFIndex = EXC_XF_DEFAULTCELL;
1955  size_t nMaxXFCount = 0;
1956  const size_t nHalfIndexes = aXFIndexes.size() / 2;
1957  for( const auto& rXFIndex : aXFIndexes )
1958  {
1959  if( rXFIndex != EXC_XF_NOTFOUND )
1960  {
1961  size_t& rnCount = aIndexMap[ rXFIndex ];
1962  ++rnCount;
1963  if( rnCount > nMaxXFCount )
1964  {
1965  nRowXFIndex = rXFIndex;
1966  nMaxXFCount = rnCount;
1967  if (nMaxXFCount > nHalfIndexes)
1968  {
1969  // No other XF index can have a greater usage count, we
1970  // don't need to loop through the remaining cells.
1971  // Specifically for the tail of unused default
1972  // cells/columns this makes a difference.
1973  break; // for
1974  }
1975  }
1976  }
1977  }
1978 
1979  // decide whether to use the row default XF index or column default XF indexes
1980  bool bUseColDefXFs = nRowXFIndex == EXC_XF_DEFAULTCELL;
1981  if( !bUseColDefXFs )
1982  {
1983  // count needed XF indexes for blank cells with and without row default XF index
1984  size_t nXFCountWithRowDefXF = 0;
1985  size_t nXFCountWithoutRowDefXF = 0;
1986  ScfUInt16Vec::const_iterator aColIt = rColXFIndexes.begin();
1987  for( const auto& rXFIndex : aXFIndexes )
1988  {
1989  sal_uInt16 nXFIndex = rXFIndex;
1990  if( nXFIndex != EXC_XF_NOTFOUND )
1991  {
1992  if( nXFIndex != nRowXFIndex )
1993  ++nXFCountWithRowDefXF; // with row default XF index
1994  if( nXFIndex != *aColIt )
1995  ++nXFCountWithoutRowDefXF; // without row default XF index
1996  }
1997  ++aColIt;
1998  }
1999 
2000  // use column XF indexes if this would cause less or equal number of BLANK records
2001  bUseColDefXFs = nXFCountWithoutRowDefXF <= nXFCountWithRowDefXF;
2002  }
2003 
2004  // *** Remove unused BLANK cell records *** -------------------------------
2005 
2006  if( bUseColDefXFs )
2007  {
2008  // use column default XF indexes
2009  // #i194#: remove cell XF indexes equal to column default XF indexes
2010  ScfUInt16Vec::const_iterator aColIt = rColXFIndexes.begin();
2011  for( auto& rXFIndex : aXFIndexes )
2012  {
2013  if( rXFIndex == *aColIt )
2014  rXFIndex = EXC_XF_NOTFOUND;
2015  ++aColIt;
2016  }
2017  }
2018  else
2019  {
2020  // use row default XF index
2021  mnXFIndex = nRowXFIndex;
2023  // #98133#, #i194#, #i27407#: remove cell XF indexes equal to row default XF index
2024  for( auto& rXFIndex : aXFIndexes )
2025  if( rXFIndex == nRowXFIndex )
2026  rXFIndex = EXC_XF_NOTFOUND;
2027  }
2028 
2029  // remove unused parts of BLANK/MULBLANK cell records
2030  nPos = 0;
2031  while( nPos < maCellList.GetSize() ) // do not cache list size, may change in the loop
2032  {
2033  XclExpCellBase* xCell = maCellList.GetRecord( nPos );
2034  xCell->RemoveUnusedBlankCells( aXFIndexes );
2035  if( xCell->IsEmpty() )
2036  maCellList.RemoveRecord( nPos );
2037  else
2038  ++nPos;
2039  }
2040 
2041  // progress bar includes disabled rows; only update it in the lead thread.
2042  if (bProgress)
2044 }
2046 {
2048 }
2049 
2051 {
2052  return maCellList.IsEmpty() ? 0 : (maCellList.GetLastRecord()->GetLastXclCol() + 1);
2053 }
2054 
2056 {
2057  const sal_uInt16 nFlagsAlwaysMarkedAsDefault = EXC_ROW_DEFAULTFLAGS | EXC_ROW_HIDDEN | EXC_ROW_UNSYNCED;
2058  return !::get_flag( mnFlags, static_cast< sal_uInt16 >( ~nFlagsAlwaysMarkedAsDefault ) ) &&
2059  IsEmpty();
2060 }
2061 
2063 {
2064  mbEnabled = !IsDefaultable() ||
2065  (mnHeight != rDefRowData.mnHeight) ||
2066  (IsHidden() != rDefRowData.IsHidden()) ||
2067  (IsUnsynced() != rDefRowData.IsUnsynced());
2068 }
2069 
2071 {
2072  OSL_ENSURE( mbEnabled || maCellList.IsEmpty(), "XclExpRow::WriteCellList - cells in disabled row" );
2073  maCellList.Save( rStrm );
2074 }
2075 
2077 {
2078  if( mbEnabled )
2079  {
2081  for ( sal_uInt32 i = 0; i < mnXclRowRpt; ++i, ++mnCurrentRow )
2082  XclExpRecord::Save( rStrm );
2083  }
2084 }
2085 
2086 void XclExpRow::InsertCell( XclExpCellRef xCell, size_t nPos, bool bIsMergedBase )
2087 {
2088  OSL_ENSURE( xCell, "XclExpRow::InsertCell - missing cell" );
2089 
2090  /* If we have a multi-line text in a merged cell, and the resulting
2091  row height has not been confirmed, we need to force the EXC_ROW_UNSYNCED
2092  flag to be true to ensure Excel works correctly. */
2093  if( bIsMergedBase && xCell->IsMultiLineText() )
2095 
2096  // try to merge with previous cell, insert the new cell if not successful
2097  XclExpCellBase* xPrevCell = maCellList.GetRecord( nPos - 1 );
2098  if( xPrevCell && xPrevCell->TryMerge( *xCell ) )
2099  xCell = xPrevCell;
2100  else
2101  maCellList.InsertRecord( xCell, nPos++ );
2102  // nPos points now to following cell
2103 
2104  // try to merge with following cell, remove it if successful
2105  XclExpCellRef xNextCell = maCellList.GetRecord( nPos );
2106  if( xNextCell && xCell->TryMerge( *xNextCell ) )
2107  maCellList.RemoveRecord( nPos );
2108 }
2109 
2111 {
2112  rStrm << static_cast< sal_uInt16 >(mnCurrentRow)
2113  << GetFirstUsedXclCol()
2114  << GetFirstFreeXclCol()
2115  << mnHeight
2116  << sal_uInt32( 0 )
2117  << mnFlags
2118  << mnXFIndex;
2119 }
2120 
2122 {
2123  if( !mbEnabled )
2124  return;
2125  sax_fastparser::FSHelperPtr& rWorksheet = rStrm.GetCurrentStream();
2126  bool haveFormat = ::get_flag( mnFlags, EXC_ROW_USEDEFXF );
2127  mnCurrentRow = mnXclRow + 1;
2128  for ( sal_uInt32 i=0; i<mnXclRowRpt; ++i )
2129  {
2130  rWorksheet->startElement( XML_row,
2131  XML_r, OString::number(mnCurrentRow++),
2132  // OOXTODO: XML_spans, optional
2133  XML_s, haveFormat ? lcl_GetStyleId( rStrm, mnXFIndex ).getStr() : nullptr,
2134  XML_customFormat, ToPsz( haveFormat ),
2135  XML_ht, OString::number(static_cast<double>(mnHeight) / 20.0),
2136  XML_hidden, ToPsz( ::get_flag( mnFlags, EXC_ROW_HIDDEN ) ),
2137  XML_customHeight, ToPsz( ::get_flag( mnFlags, EXC_ROW_UNSYNCED ) ),
2138  XML_outlineLevel, OString::number(mnOutlineLevel),
2139  XML_collapsed, ToPsz( ::get_flag( mnFlags, EXC_ROW_COLLAPSED ) )
2140  // OOXTODO: XML_thickTop, bool
2141  // OOXTODO: XML_thickBot, bool
2142  // OOXTODO: XML_ph, bool
2143  );
2144  // OOXTODO: XML_extLst
2145  maCellList.SaveXml( rStrm );
2146  rWorksheet->endElement( XML_row );
2147  }
2148 }
2149 
2151  XclExpRoot( rRoot ),
2152  maOutlineBfr( rRoot ),
2153  maDimensions( rRoot ),
2154  mnHighestOutlineLevel( 0 )
2155 {
2156 }
2157 
2158 void XclExpRowBuffer::AppendCell( XclExpCellRef const & xCell, bool bIsMergedBase )
2159 {
2160  OSL_ENSURE( xCell, "XclExpRowBuffer::AppendCell - missing cell" );
2161  GetOrCreateRow( xCell->GetXclRow(), false ).AppendCell( xCell, bIsMergedBase );
2162 }
2163 
2164 void XclExpRowBuffer::CreateRows( SCROW nFirstFreeScRow )
2165 {
2166  if( nFirstFreeScRow > 0 )
2167  GetOrCreateRow( ::std::max ( nFirstFreeScRow - 1, GetMaxPos().Row() ), true );
2168 }
2169 
2170 namespace {
2171 
2172 class RowFinalizeTask : public comphelper::ThreadTask
2173 {
2174  bool mbProgress;
2175  const ScfUInt16Vec& mrColXFIndexes;
2176  std::vector< XclExpRow * > maRows;
2177 public:
2178  RowFinalizeTask( const std::shared_ptr<comphelper::ThreadTaskTag> & pTag,
2179  const ScfUInt16Vec& rColXFIndexes,
2180  bool bProgress ) :
2181  comphelper::ThreadTask( pTag ),
2182  mbProgress( bProgress ),
2183  mrColXFIndexes( rColXFIndexes ) {}
2184 
2185  void push_back( XclExpRow *pRow ) { maRows.push_back( pRow ); }
2186  virtual void doWork() override
2187  {
2188  for (XclExpRow* p : maRows)
2189  p->Finalize( mrColXFIndexes, mbProgress );
2190  }
2191 };
2192 
2193 }
2194 
2195 void XclExpRowBuffer::Finalize( XclExpDefaultRowData& rDefRowData, const ScfUInt16Vec& rColXFIndexes )
2196 {
2197  // *** Finalize all rows *** ----------------------------------------------
2198 
2200 
2201 #if 1
2202  // This is staggeringly slow, and each element operates only
2203  // on its own data.
2204  const size_t nRows = maRowMap.size();
2205  const size_t nThreads = nRows < 128 ? 1 : comphelper::ThreadPool::getPreferredConcurrency();
2206 #else
2207  const size_t nThreads = 1; // globally disable multi-threading for now.
2208 #endif
2209  if (nThreads == 1)
2210  {
2211  for (auto& rEntry : maRowMap)
2212  rEntry.second->Finalize( rColXFIndexes, true );
2213  }
2214  else
2215  {
2217  std::shared_ptr<comphelper::ThreadTaskTag> pTag = comphelper::ThreadPool::createThreadTaskTag();
2218  std::vector<std::unique_ptr<RowFinalizeTask>> aTasks(nThreads);
2219  for ( size_t i = 0; i < nThreads; i++ )
2220  aTasks[ i ].reset( new RowFinalizeTask( pTag, rColXFIndexes, i == 0 ) );
2221 
2222  size_t nIdx = 0;
2223  for ( const auto& rEntry : maRowMap )
2224  {
2225  aTasks[ nIdx % nThreads ]->push_back( rEntry.second.get() );
2226  ++nIdx;
2227  }
2228 
2229  for ( size_t i = 1; i < nThreads; i++ )
2230  rPool.pushTask( std::move(aTasks[ i ]) );
2231 
2232  // Progress bar updates must be synchronous to avoid deadlock
2233  aTasks[0]->doWork();
2234 
2235  rPool.waitUntilDone(pTag);
2236  }
2237 
2238  // *** Default row format *** ---------------------------------------------
2239 
2240  std::map< XclExpDefaultRowData, size_t > aDefRowMap;
2241 
2242  XclExpDefaultRowData aMaxDefData;
2243  size_t nMaxDefCount = 0;
2244  // only look for default format in existing rows, if there are more than unused
2245  // if the row is hidden, then row xml must be created even if it not contain cells
2246  XclExpRow* pPrev = nullptr;
2247  std::vector< XclExpRow* > aRepeated;
2248  for (const auto& rEntry : maRowMap)
2249  {
2250  const RowRef& rRow = rEntry.second;
2251  if ( rRow->IsDefaultable() )
2252  {
2253  XclExpDefaultRowData aDefData( *rRow );
2254  size_t& rnDefCount = aDefRowMap[ aDefData ];
2255  ++rnDefCount;
2256  if( rnDefCount > nMaxDefCount )
2257  {
2258  nMaxDefCount = rnDefCount;
2259  aMaxDefData = aDefData;
2260  }
2261  }
2262  if ( pPrev )
2263  {
2264  if ( pPrev->IsDefaultable() )
2265  {
2266  // if the previous row we processed is not
2267  // defaultable then afaict the rows in between are
2268  // not used ( and not repeatable )
2269  sal_uInt32 nRpt = rRow->GetXclRow() - pPrev->GetXclRow();
2270  if ( nRpt > 1 )
2271  aRepeated.push_back( pPrev );
2272  pPrev->SetXclRowRpt( nRpt );
2273  XclExpDefaultRowData aDefData( *pPrev );
2274  size_t& rnDefCount = aDefRowMap[ aDefData ];
2275  rnDefCount += ( pPrev->GetXclRowRpt() - 1 );
2276  if( rnDefCount > nMaxDefCount )
2277  {
2278  nMaxDefCount = rnDefCount;
2279  aMaxDefData = aDefData;
2280  }
2281  }
2282  }
2283  pPrev = rRow.get();
2284  }
2285  // return the default row format to caller
2286  rDefRowData = aMaxDefData;
2287 
2288  // now disable repeating extra (empty) rows that are equal to the default row
2289  for (auto& rpRow : aRepeated)
2290  {
2291  if ( rpRow->GetXclRowRpt() > 1
2292  && rpRow->GetHeight() == rDefRowData.mnHeight
2293  && rpRow->IsHidden() == rDefRowData.IsHidden() )
2294  {
2295  rpRow->SetXclRowRpt( 1 );
2296  }
2297  }
2298 
2299  // *** Disable unused ROW records, find used area *** ---------------------
2300 
2301  sal_uInt16 nFirstUsedXclCol = SAL_MAX_UINT16;
2302  sal_uInt16 nFirstFreeXclCol = 0;
2303  sal_uInt32 nFirstUsedXclRow = SAL_MAX_UINT32;
2304  sal_uInt32 nFirstFreeXclRow = 0;
2305 
2306  for (const auto& rEntry : maRowMap)
2307  {
2308  const RowRef& rRow = rEntry.second;
2309  // disable unused rows
2310  rRow->DisableIfDefault( aMaxDefData );
2311 
2312  // find used column range
2313  if( !rRow->IsEmpty() ) // empty rows return (0...0) as used range
2314  {
2315  nFirstUsedXclCol = ::std::min( nFirstUsedXclCol, rRow->GetFirstUsedXclCol() );
2316  nFirstFreeXclCol = ::std::max( nFirstFreeXclCol, rRow->GetFirstFreeXclCol() );
2317  }
2318 
2319  // find used row range
2320  if( rRow->IsEnabled() )
2321  {
2322  sal_uInt32 nXclRow = rRow->GetXclRow();
2323  nFirstUsedXclRow = ::std::min< sal_uInt32 >( nFirstUsedXclRow, nXclRow );
2324  nFirstFreeXclRow = ::std::max< sal_uInt32 >( nFirstFreeXclRow, nXclRow + 1 );
2325  }
2326  }
2327 
2328  // adjust start position, if there are no or only empty/disabled ROW records
2329  nFirstUsedXclCol = ::std::min( nFirstUsedXclCol, nFirstFreeXclCol );
2330  nFirstUsedXclRow = ::std::min( nFirstUsedXclRow, nFirstFreeXclRow );
2331 
2332  // initialize the DIMENSIONS record
2334  nFirstUsedXclCol, nFirstUsedXclRow, nFirstFreeXclCol, nFirstFreeXclRow );
2335 }
2336 
2338 {
2339  // DIMENSIONS record
2340  maDimensions.Save( rStrm );
2341 
2342  // save in blocks of 32 rows, each block contains first all ROWs, then all cells
2343  size_t nSize = maRowMap.size();
2344  RowMap::iterator itr = maRowMap.begin(), itrEnd = maRowMap.end();
2345  RowMap::iterator itrBlkStart = maRowMap.begin(), itrBlkEnd = maRowMap.begin();
2346  sal_uInt16 nStartXclRow = (nSize == 0) ? 0 : itr->second->GetXclRow();
2347 
2348  for (; itr != itrEnd; ++itr)
2349  {
2350  // find end of row block
2351  itrBlkEnd = std::find_if_not(itrBlkEnd, itrEnd,
2352  [&nStartXclRow](const RowMap::value_type& rRow) { return rRow.second->GetXclRow() - nStartXclRow < EXC_ROW_ROWBLOCKSIZE; });
2353 
2354  // write the ROW records
2355  std::for_each(itrBlkStart, itrBlkEnd, [&rStrm](const RowMap::value_type& rRow) { rRow.second->Save( rStrm ); });
2356 
2357  // write the cell records
2358  std::for_each(itrBlkStart, itrBlkEnd, [&rStrm](const RowMap::value_type& rRow) { rRow.second->WriteCellList( rStrm ); });
2359 
2360  itrBlkStart = (itrBlkEnd == itrEnd) ? itrBlkEnd : itrBlkEnd++;
2361  nStartXclRow += EXC_ROW_ROWBLOCKSIZE;
2362  }
2363 }
2364 
2366 {
2367  if (std::none_of(maRowMap.begin(), maRowMap.end(), [](const RowMap::value_type& rRow) { return rRow.second->IsEnabled(); }))
2368  {
2369  rStrm.GetCurrentStream()->singleElement(XML_sheetData);
2370  return;
2371  }
2372 
2373  sax_fastparser::FSHelperPtr& rWorksheet = rStrm.GetCurrentStream();
2374  rWorksheet->startElement(XML_sheetData);
2375  for (const auto& rEntry : maRowMap)
2376  rEntry.second->SaveXml(rStrm);
2377  rWorksheet->endElement( XML_sheetData );
2378 }
2379 
2380 XclExpRow& XclExpRowBuffer::GetOrCreateRow( sal_uInt32 nXclRow, bool bRowAlwaysEmpty )
2381 {
2382  RowMap::iterator itr = maRowMap.lower_bound( nXclRow );
2383  const bool bFound = itr != maRowMap.end();
2384  // bFoundHigher: nXclRow was identical to the previous entry, so not explicitly created earlier
2385  const bool bFoundHigher = bFound && itr != maRowMap.find( nXclRow );
2386  if( !bFound || bFoundHigher )
2387  {
2388  size_t nFrom = 0;
2389  RowRef pPrevEntry;
2390  if( itr != maRowMap.begin() )
2391  {
2392  --itr;
2393  pPrevEntry = itr->second;
2394  if( bFoundHigher )
2395  nFrom = nXclRow;
2396  else
2397  nFrom = itr->first + 1;
2398  }
2399 
2400  const ScDocument& rDoc = GetRoot().GetDoc();
2401  const SCTAB nScTab = GetRoot().GetCurrScTab();
2402  // create the missing rows first
2403  while( nFrom <= nXclRow )
2404  {
2405  // only create RowMap entries if it is first row in spreadsheet,
2406  // if it is the desired row, or for rows that differ from previous.
2407  const bool bHidden = rDoc.RowHidden(nFrom, nScTab);
2408  // Always get the actual row height even if the manual size flag is
2409  // not set, to correctly export the heights of rows with wrapped
2410  // texts.
2411  const sal_uInt16 nHeight = rDoc.GetRowHeight(nFrom, nScTab, false);
2412  if ( !pPrevEntry || ( nFrom == nXclRow ) ||
2413  ( maOutlineBfr.IsCollapsed() ) ||
2414  ( maOutlineBfr.GetLevel() != 0 ) ||
2415  ( bRowAlwaysEmpty && !pPrevEntry->IsEmpty() ) ||
2416  ( bHidden != pPrevEntry->IsHidden() ) ||
2417  ( nHeight != pPrevEntry->GetHeight() ) )
2418  {
2420  {
2422  }
2423  RowRef p = std::make_shared<XclExpRow>(GetRoot(), nFrom, maOutlineBfr, bRowAlwaysEmpty, bHidden, nHeight);
2424  maRowMap.emplace(nFrom, p);
2425  pPrevEntry = p;
2426  }
2427  ++nFrom;
2428  }
2429  }
2430  itr = maRowMap.find(nXclRow);
2431  return *itr->second;
2432 }
2433 
2434 // Cell Table
2435 
2437  XclExpRoot( rRoot ),
2438  maColInfoBfr( rRoot ),
2439  maRowBfr( rRoot ),
2440  maArrayBfr( rRoot ),
2441  maShrfmlaBfr( rRoot ),
2442  maTableopBfr( rRoot ),
2443  mxDefrowheight( new XclExpDefrowheight() ),
2444  mxGuts( new XclExpGuts( rRoot ) ),
2445  mxNoteList( new XclExpNoteList ),
2446  mxMergedcells( new XclExpMergedcells( rRoot ) ),
2447  mxHyperlinkList( new XclExpHyperlinkList ),
2448  mxDval( new XclExpDval( rRoot ) ),
2449  mxExtLst( new XclExtLst( rRoot ) )
2450 {
2451  ScDocument& rDoc = GetDoc();
2452  SCTAB nScTab = GetCurrScTab();
2453  SvNumberFormatter& rFormatter = GetFormatter();
2454 
2455  // maximum sheet limits
2456  SCCOL nMaxScCol = GetMaxPos().Col();
2457  SCROW nMaxScRow = GetMaxPos().Row();
2458 
2459  // find used area (non-empty cells)
2460  SCCOL nLastUsedScCol;
2461  SCROW nLastUsedScRow;
2462  rDoc.GetTableArea( nScTab, nLastUsedScCol, nLastUsedScRow );
2463 
2464  if(nLastUsedScCol > nMaxScCol)
2465  nLastUsedScCol = nMaxScCol;
2466 
2467  // check extra blank rows to avoid of losing their not default settings (workaround for tdf#41425)
2468  nLastUsedScRow += 1000;
2469 
2470  if(nLastUsedScRow > nMaxScRow)
2471  nLastUsedScRow = nMaxScRow;
2472 
2473  ScRange aUsedRange( 0, 0, nScTab, nLastUsedScCol, nLastUsedScRow, nScTab );
2474  GetAddressConverter().ValidateRange( aUsedRange, true );
2475  nLastUsedScRow = aUsedRange.aEnd.Row();
2476 
2477  // first row without any set attributes (height/hidden/...)
2478  SCROW nFirstUnflaggedScRow = rDoc.GetLastFlaggedRow( nScTab ) + 1;
2479 
2480  // find range of outlines
2481  SCROW nFirstUngroupedScRow = 0;
2482  if( const ScOutlineTable* pOutlineTable = rDoc.GetOutlineTable( nScTab ) )
2483  {
2484  SCCOLROW nScStartPos, nScEndPos;
2485  const ScOutlineArray& rRowArray = pOutlineTable->GetRowArray();
2486  rRowArray.GetRange( nScStartPos, nScEndPos );
2487  // +1 because open/close button is in next row in Excel, +1 for "end->first unused"
2488  nFirstUngroupedScRow = static_cast< SCROW >( nScEndPos + 2 );
2489  }
2490 
2491  // column settings
2492  /* #i30411# Files saved with SO7/OOo1.x with nonstandard default column
2493  formatting cause big Excel files, because all rows from row 1 to row
2494  32000 are exported. Now, if the used area goes exactly to row 32000,
2495  use this row as default and ignore all rows >32000.
2496  #i59220# Tolerance of +-128 rows for inserted/removed rows. */
2497  if( (31871 <= nLastUsedScRow) && (nLastUsedScRow <= 32127) && (nFirstUnflaggedScRow < nLastUsedScRow) && (nFirstUngroupedScRow <= nLastUsedScRow) )
2498  nMaxScRow = nLastUsedScRow;
2499  maColInfoBfr.Initialize( nMaxScRow );
2500 
2501  // range for cell iterator
2502  SCCOL nLastIterScCol = nMaxScCol;
2503  SCROW nLastIterScRow = ulimit_cast< SCROW >( nLastUsedScRow, nMaxScRow );
2504  ScUsedAreaIterator aIt( rDoc, nScTab, 0, 0, nLastIterScCol, nLastIterScRow );
2505 
2506  // activate the correct segment and sub segment at the progress bar
2508 
2509  for( bool bIt = aIt.GetNext(); bIt; bIt = aIt.GetNext() )
2510  {
2511  SCCOL nScCol = aIt.GetStartCol();
2512  SCROW nScRow = aIt.GetRow();
2513  SCCOL nLastScCol = aIt.GetEndCol();
2514  ScAddress aScPos( nScCol, nScRow, nScTab );
2515 
2516  XclAddress aXclPos( static_cast< sal_uInt16 >( nScCol ), static_cast< sal_uInt32 >( nScRow ) );
2517  sal_uInt16 nLastXclCol = static_cast< sal_uInt16 >( nLastScCol );
2518 
2519  const ScRefCellValue& rScCell = aIt.GetCell();
2520  XclExpCellRef xCell;
2521 
2522  const ScPatternAttr* pPattern = aIt.GetPattern();
2523 
2524  // handle overlapped merged cells before creating the cell record
2525  sal_uInt32 nMergeBaseXFId = EXC_XFID_NOTFOUND;
2526  bool bIsMergedBase = false;
2527  if( pPattern )
2528  {
2529  const SfxItemSet& rItemSet = pPattern->GetItemSet();
2530  // base cell in a merged range
2531  const ScMergeAttr& rMergeItem = rItemSet.Get( ATTR_MERGE );
2532  bIsMergedBase = rMergeItem.IsMerged();
2533  /* overlapped cell in a merged range; in Excel all merged cells
2534  must contain same XF index, for correct border */
2535  const ScMergeFlagAttr& rMergeFlagItem = rItemSet.Get( ATTR_MERGE_FLAG );
2536  if( rMergeFlagItem.IsOverlapped() )
2537  nMergeBaseXFId = mxMergedcells->GetBaseXFId( aScPos );
2538  }
2539 
2540  OUString aAddNoteText; // additional text to be appended to a note
2541 
2542  switch (rScCell.meType)
2543  {
2544  case CELLTYPE_VALUE:
2545  {
2546  double fValue = rScCell.mfValue;
2547 
2548  if (pPattern)
2549  {
2550  OUString aUrl = pPattern->GetItemSet().Get(ATTR_HYPERLINK).GetValue();
2551  if (!aUrl.isEmpty())
2552  {
2554  new XclExpHyperlink(GetRoot(), SvxURLField(aUrl, aUrl), aScPos);
2555  mxHyperlinkList->AppendRecord(aLink);
2556  }
2557  }
2558 
2559  // try to create a Boolean cell
2560  if( pPattern && ((fValue == 0.0) || (fValue == 1.0)) )
2561  {
2562  sal_uInt32 nScNumFmt = pPattern->GetItemSet().Get( ATTR_VALUE_FORMAT ).GetValue();
2563  if( rFormatter.GetType( nScNumFmt ) == SvNumFormatType::LOGICAL )
2564  xCell = new XclExpBooleanCell(
2565  GetRoot(), aXclPos, pPattern, nMergeBaseXFId, fValue != 0.0 );
2566  }
2567 
2568  // try to create an RK value (compressed floating-point number)
2569  sal_Int32 nRkValue;
2570  if( !xCell && XclTools::GetRKFromDouble( nRkValue, fValue ) )
2571  xCell = new XclExpRkCell(
2572  GetRoot(), aXclPos, pPattern, nMergeBaseXFId, nRkValue );
2573 
2574  // else: simple floating-point number cell
2575  if( !xCell )
2576  xCell = new XclExpNumberCell(
2577  GetRoot(), aXclPos, pPattern, nMergeBaseXFId, fValue );
2578  }
2579  break;
2580 
2581  case CELLTYPE_STRING:
2582  {
2583  xCell = new XclExpLabelCell(
2584  GetRoot(), aXclPos, pPattern, nMergeBaseXFId, rScCell.mpString->getString());
2585  }
2586  break;
2587 
2588  case CELLTYPE_EDIT:
2589  {
2590  XclExpHyperlinkHelper aLinkHelper( GetRoot(), aScPos );
2591  xCell = new XclExpLabelCell(
2592  GetRoot(), aXclPos, pPattern, nMergeBaseXFId, rScCell.mpEditText, aLinkHelper);
2593 
2594  // add a single created HLINK record to the record list
2595  if( aLinkHelper.HasLinkRecord() )
2596  mxHyperlinkList->AppendRecord( aLinkHelper.GetLinkRecord() );
2597  // add list of multiple URLs to the additional cell note text
2598  if( aLinkHelper.HasMultipleUrls() )
2599  aAddNoteText = ScGlobal::addToken( aAddNoteText, aLinkHelper.GetUrlList(), '\n', 2 );
2600  }
2601  break;
2602 
2603  case CELLTYPE_FORMULA:
2604  {
2605  if (pPattern)
2606  {
2607  OUString aUrl = pPattern->GetItemSet().Get(ATTR_HYPERLINK).GetValue();
2608  if (!aUrl.isEmpty())
2609  {
2611  new XclExpHyperlink(GetRoot(), SvxURLField(aUrl, aUrl), aScPos);
2612  mxHyperlinkList->AppendRecord(aLink);
2613  }
2614  }
2615 
2616  xCell = new XclExpFormulaCell(
2617  GetRoot(), aXclPos, pPattern, nMergeBaseXFId,
2619  }
2620  break;
2621 
2622  default:
2623  OSL_FAIL( "XclExpCellTable::XclExpCellTable - unknown cell type" );
2624  [[fallthrough]];
2625  case CELLTYPE_NONE:
2626  {
2627  xCell = new XclExpBlankCell(
2628  GetRoot(), aXclPos, nLastXclCol, pPattern, nMergeBaseXFId );
2629  }
2630  break;
2631  }
2632 
2633  assert(xCell && "can only reach here with xCell set");
2634 
2635  // insert the cell into the current row
2636  maRowBfr.AppendCell( xCell, bIsMergedBase );
2637 
2638  if ( !aAddNoteText.isEmpty() )
2639  mxNoteList->AppendNewRecord( new XclExpNote( GetRoot(), aScPos, nullptr, aAddNoteText ) );
2640 
2641  // other sheet contents
2642  if( pPattern )
2643  {
2644  const SfxItemSet& rItemSet = pPattern->GetItemSet();
2645 
2646  // base cell in a merged range
2647  if( bIsMergedBase )
2648  {
2649  const ScMergeAttr& rMergeItem = rItemSet.Get( ATTR_MERGE );
2650  ScRange aScRange( aScPos );
2651  aScRange.aEnd.IncCol( rMergeItem.GetColMerge() - 1 );
2652  aScRange.aEnd.IncRow( rMergeItem.GetRowMerge() - 1 );
2653  sal_uInt32 nXFId = xCell->GetFirstXFId();
2654  // blank cells merged vertically may occur repeatedly
2655  OSL_ENSURE( (aScRange.aStart.Col() == aScRange.aEnd.Col()) || (nScCol == nLastScCol),
2656  "XclExpCellTable::XclExpCellTable - invalid repeated blank merged cell" );
2657  for( SCCOL nIndex = nScCol; nIndex <= nLastScCol; ++nIndex )
2658  {
2659  mxMergedcells->AppendRange( aScRange, nXFId );
2660  aScRange.aStart.IncCol();
2661  aScRange.aEnd.IncCol();
2662  }
2663  }
2664 
2665  // data validation
2666  if( ScfTools::CheckItem( rItemSet, ATTR_VALIDDATA, false ) )
2667  {
2668  sal_uLong nScHandle = rItemSet.Get( ATTR_VALIDDATA ).GetValue();
2669  ScRange aScRange( aScPos );
2670  aScRange.aEnd.SetCol( nLastScCol );
2671  mxDval->InsertCellRange( aScRange, nScHandle );
2672  }
2673  }
2674  }
2675 
2676  // create missing row settings for rows anyhow flagged or with outlines
2677  maRowBfr.CreateRows( ::std::max( nFirstUnflaggedScRow, nFirstUngroupedScRow ) );
2678 }
2679 
2681 {
2682  // Finalize multiple operations.
2684 
2685  /* Finalize column buffer. This calculates column default XF indexes from
2686  the XF identifiers and fills a vector with these XF indexes. */
2687  ScfUInt16Vec aColXFIndexes;
2688  maColInfoBfr.Finalize( aColXFIndexes, bXLS );
2689 
2690  /* Finalize row buffer. This calculates all cell XF indexes from the XF
2691  identifiers. Then the XF index vector aColXFIndexes (filled above) is
2692  used to calculate the row default formats. With this, all unneeded blank
2693  cell records (equal to row default or column default) will be removed.
2694  The function returns the (most used) default row format in aDefRowData. */
2695  XclExpDefaultRowData aDefRowData;
2696  maRowBfr.Finalize( aDefRowData, aColXFIndexes );
2697 
2698  // Initialize the DEFROWHEIGHT record.
2699  mxDefrowheight->SetDefaultData( aDefRowData );
2700 }
2701 
2703 {
2704  XclExpRecordRef xRec;
2705  switch( nRecId )
2706  {
2707  case EXC_ID3_DIMENSIONS: xRec = new XclExpDelegatingRecord( &const_cast<XclExpRowBuffer*>(&maRowBfr)->GetDimensions() ); break;
2708  case EXC_ID2_DEFROWHEIGHT: xRec = mxDefrowheight; break;
2709  case EXC_ID_GUTS: xRec = mxGuts; break;
2710  case EXC_ID_NOTE: xRec = mxNoteList; break;
2711  case EXC_ID_MERGEDCELLS: xRec = mxMergedcells; break;
2712  case EXC_ID_HLINK: xRec = mxHyperlinkList; break;
2713  case EXC_ID_DVAL: xRec = mxDval; break;
2714  case EXC_ID_EXTLST: xRec = mxExtLst; break;
2715  default: OSL_FAIL( "XclExpCellTable::CreateRecord - unknown record id" );
2716  }
2717  return xRec;
2718 }
2719 
2721 {
2722  // DEFCOLWIDTH and COLINFOs
2723  maColInfoBfr.Save( rStrm );
2724  // ROWs and cell records
2725  maRowBfr.Save( rStrm );
2726 }
2727 
2729 {
2730  // DEFAULT row height
2731  XclExpDefaultRowData& rDefData = mxDefrowheight->GetDefaultData();
2732  sax_fastparser::FSHelperPtr& rWorksheet = rStrm.GetCurrentStream();
2733  rWorksheet->startElement( XML_sheetFormatPr,
2734  // OOXTODO: XML_baseColWidth
2735  XML_defaultColWidth, OString::number(maColInfoBfr.GetDefColWidth()),
2736  // OOXTODO: XML_customHeight
2737  // OOXTODO: XML_thickTop
2738  // OOXTODO: XML_thickBottom
2739  XML_defaultRowHeight, OString::number(static_cast<double> (rDefData.mnHeight) / 20.0),
2740  XML_zeroHeight, ToPsz( rDefData.IsHidden() ),
2741  XML_outlineLevelRow, OString::number(maRowBfr.GetHighestOutlineLevel()),
2742  XML_outlineLevelCol, OString::number(maColInfoBfr.GetHighestOutlineLevel()) );
2743  rWorksheet->endElement( XML_sheetFormatPr );
2744 
2745  maColInfoBfr.SaveXml( rStrm );
2746  maRowBfr.SaveXml( rStrm );
2747  mxExtLst->SaveXml( rStrm );
2748 }
2749 
2750 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
void SetValue(const Type &rValue)
Sets a new record value.
Definition: xerecord.hxx:209
XclExpStringRef mxText
Definition: xetable.hxx:423
SC_DLLPUBLIC const ScPatternAttr * GetMostUsedPattern(SCCOL nCol, SCROW nStartRow, SCROW nEndRow, SCTAB nTab) const
Definition: document.cxx:4781
sal_uInt16 GetFirstUsedXclCol() const
Returns the column index of the first used cell in this row.
Definition: xetable.cxx:2045
double mnHeight
virtual sal_uInt32 GetFirstXFId() const override
Return the XF identifier of the cell.
Definition: xetable.cxx:593
virtual void Save(XclExpStream &rStrm) override
Writes the complete record list.
Definition: xerecord.hxx:374
SCCOL GetColMerge() const
Definition: attrib.hxx:68
const sal_uInt16 EXC_TABLEOP_BOTH
Definition: xltable.hxx:129
#define DBG_ERROR_BIFF()
Definition: xltools.hxx:33
XclExpCellBase(sal_uInt16 nRecId, std::size_t nContSize, const XclAddress &rXclPos)
Definition: xetable.cxx:540
void Finalize()
Finalizes all contained TABLEOP records.
Definition: xetable.cxx:481
XclExpBlankCell(const XclAddress &rXclPos, const XclExpMultiXFId &rXFId)
Definition: xetable.cxx:1307
static void GetFormulaTypeAndValue(ScFormulaCell &rCell, const char *&sType, OUString &rValue)
Definition: xestream.cxx:662
const sal_uInt16 EXC_ID2_DIMENSIONS
Definition: xltable.hxx:32
XclExpColinfoBuffer maColInfoBfr
Definition: xetable.hxx:1002
const sal_uInt16 EXC_STR_MAXLEN
Definition: xlstring.hxx:42
static OString ToOString(const Color &rColor)
Definition: xestream.cxx:703
virtual void SaveXml(XclExpXmlStream &rStrm) override
Definition: xetable.cxx:672
sal_uInt32 mnColInpXclRow
Column index of column input cell.
Definition: xetable.hxx:237
sal_Int32 nIndex
OUString getString() const
bool mbCustomWidth
The XF identifier for column default format.
Definition: xetable.hxx:733
XclBiff
An enumeration for all Excel file format types (BIFF types).
Definition: xlconst.hxx:29
virtual bool IsEmpty() const override
Returns true, if this record does not contain at least one valid cell.
Definition: xetable.cxx:1119
XclExpShrfmla(const XclTokenArrayRef &xTokArr, const ScAddress &rScPos)
Creates a SHRFMLA record that consists of the passed cell address only.
Definition: xetable.cxx:181
ScAddress aStart
Definition: address.hxx:499
XclExpStringRec(const XclExpRoot &rRoot, const OUString &rResult)
Definition: xetable.cxx:55
ScAddress maRowFirstScPos
Definition: xlformula.hxx:473
const sal_uInt8 EXC_ERR_NA
Definition: xlconst.hxx:110
virtual void WriteContents(XclExpStream &rStrm, sal_uInt16 nRelCol) override
Writes the remaining contents of the specified cell (without XF index).
Definition: xetable.cxx:1340
XclExpNumberCell(const XclExpRoot &rRoot, const XclAddress &rXclPos, const ScPatternAttr *pPattern, sal_uInt32 nForcedXFId, double fValue)
Definition: xetable.cxx:621
The main progress bar for the export filter.
Definition: xehelper.hxx:43
sal_uInt16 mnColWidth
Number of visible column outline levels.
Definition: xetable.hxx:635
static bool CheckItem(const SfxItemSet &rItemSet, sal_uInt16 nWhichId, bool bDeep)
Returns true, if the passed item set contains the item.
Definition: ftools.cxx:195
const sal_uInt16 EXC_XF_DEFAULTCELL
Excel index to default style XF.
Definition: xlstyle.hxx:139
#define EMPTY_OUSTRING
Definition: global.hxx:213
const XclExpRoot & GetRoot() const
Returns the filter root data.
Definition: xestream.hxx:291
void ActivateCreateRowsSegment()
Activates the progress segment to create ROW records.
Definition: xehelper.cxx:112
void AppendCell(XclExpCellRef const &xCell, bool bIsMergedBase)
Appends the passed cell object to this row.
Definition: xetable.cxx:1889
static sal_Int32 getPreferredConcurrency()
bool IsEmpty() const
Returns true, if this row does not contain at least one valid cell.
Definition: xetable.hxx:836
virtual bool IsEmpty() const =0
Derived classes return true, if this record does not contain at least one valid cell.
static double GetXclDefColWidthCorrection(tools::Long nXclDefFontHeight)
Returns a correction value to convert column widths from/to default column widths.
Definition: xltools.cxx:321
bool IsAppendable(sal_uInt16 nXclCol, sal_uInt16 nXclRow) const
Returns true, if the passed cell position can be appended to this record.
Definition: xetable.cxx:426
sal_uInt32 GetStandardFormat() const
Returns the core index of the current standard number format.
Definition: xestyle.hxx:275
This class is used to export Excel record streams.
Definition: xestream.hxx:72
SCROW Row() const
Definition: address.hxx:261
OStringBuffer & GetStringBuf() const
Clean and return the OStringBuffer.
Definition: xeroot.hxx:158
virtual void SaveXml(XclExpXmlStream &rStrm) override
Definition: xetable.cxx:643
sal_uInt16 GetXclCol() const
Returns the (first) Excel column index of the cell(s).
Definition: xetable.hxx:279
virtual void WriteContents(XclExpStream &rStrm) override
Derived classes write the contents of the specified cell (without XF index).
Definition: xetable.cxx:1042
virtual bool IsMultiLineText() const
Derived classes return whether the cell contains multi-line text.
Definition: xetable.cxx:547
XclExpArrayBuffer maArrayBfr
Rows and cell records.
Definition: xetable.hxx:1004
virtual void SaveXml(XclExpXmlStream &rStrm) override
Definition: xerecord.hxx:381
sal_uInt32 mnCurrentRow
Definition: xetable.hxx:893
const sal_uInt16 EXC_ID3_STRING
Definition: xltable.hxx:76
Single reference (one address) into the sheet.
Definition: refdata.hxx:29
void Init(const XclExpRoot &rRoot, const ScPatternAttr *pPattern, XclExpStringRef const &xText)
Initializes the record contents.
Definition: xetable.cxx:727
XclExpLabelCell(const XclExpRoot &rRoot, const XclAddress &rXclPos, const ScPatternAttr *pPattern, sal_uInt32 nForcedXFId, const OUString &rStr)
Constructs the record from an unformatted Calc string cell.
Definition: xetable.cxx:692
XclExpDimensions maDimensions
Buffer for row outline groups.
Definition: xetable.hxx:939
const sal_uInt16 EXC_ID_NOTE
Definition: xlescher.hxx:38
size_type count(const Value &v) const
sal_uInt16 mnMulRecId
Definition: xetable.hxx:515
The outline buffer for row outlines.
Definition: xetable.hxx:613
void Write(XclExpStream &rStrm, bool bCol16Bit=true) const
Definition: xladdress.cxx:63
const sal_uInt16 EXC_FORMULA_SHARED
Definition: xltable.hxx:66
virtual void Save(XclExpStream &rStrm) override
Writes cell address, XF index, and calls WriteContents() for each cell.
Definition: xetable.cxx:608
virtual bool IsMultiLineText() const override
Returns true if the cell contains multi-line text.
Definition: xetable.cxx:722
XclExpBooleanCell(const XclExpRoot &rRoot, const XclAddress &rXclPos, const ScPatternAttr *pPattern, sal_uInt32 nForcedXFId, bool bValue)
Definition: xetable.cxx:663
sal_uInt16 mnCount
Definition: xetable.hxx:459
void AppendRecord(RecType *pRec)
Appends a record to the list.
Definition: xerecord.hxx:347
const Type & GetValue() const
Returns the value of the record.
Definition: xerecord.hxx:207
static OUString ToOUString(const char *s)
Definition: xestream.cxx:788
Base class for all cell records not supporting multiple contents.
Definition: xetable.hxx:318
ScAddress toAbs(const ScSheetLimits &rLimits, const ScAddress &rPos) const
Definition: refdata.cxx:193
virtual void WriteXmlContents(XclExpXmlStream &rStrm, const XclAddress &rAddress, sal_uInt32 nXFId, sal_uInt16 nRelCol)=0
XclExpRow(const XclExpRoot &rRoot, sal_uInt32 nXclRow, XclExpRowOutlineBuffer &rOutlineBfr, bool bAlwaysEmpty, bool bHidden, sal_uInt16 nHeight)
Constructs the ROW record and converts the Calc row settings.
Definition: xetable.cxx:1851
virtual sal_uInt16 GetLastXclCol() const override
Returns the column index of the last cell this record describes.
Definition: xetable.cxx:1109
ScFormulaCell & mrScFmlaCell
Definition: xetable.hxx:449
const sal_uInt16 EXC_ID2_FORMULA
Definition: xltable.hxx:60
ScTokenArray * GetCode()
sal_uIntPtr sal_uLong
const XclAddress & GetXclPos() const
Returns the (first) address of the cell(s).
Definition: xetable.hxx:277
long Long
void Progress()
Increases the currently activated (sub) progress bar by 1 step.
Definition: xehelper.cxx:139
sal_uInt32 mnXclRow
List of cell records for this row.
Definition: xetable.hxx:887
bool ValidRange(const ScRange &rRange) const
Definition: document.hxx:878
Represents an RK or MULRK record that describes cells with a compressed double values.
Definition: xetable.hxx:544
virtual void doWork()=0
virtual void WriteBody(XclExpStream &rStrm) override
Writes the contents of the record.
Definition: xetable.cxx:1845
const sal_uInt16 EXC_ROW_USEDEFXF
Definition: xltable.hxx:85
void Finalize(ScfUInt16Vec &rXFIndexes, bool bXLS)
Converts the XF identifiers into the Excel XF indexes and merges equal columns.
Definition: xetable.cxx:1737
bool IsOverlapped() const
Definition: attrib.hxx:101
sal_uInt16 mnRowWidth
Number of visible row outline levels.
Definition: xetable.hxx:637
const sal_uInt16 EXC_DEFROW_UNSYNCED
Definition: xltable.hxx:114
double GetDefColWidth() const
Definition: xetable.hxx:765
sal_uInt32 mnFirstFreeXclRow
First used row.
Definition: xetable.hxx:659
const sal_uInt8 EXC_FORMULA_RES_EMPTY
Result is error code.
Definition: xltable.hxx:72
Represents the DEFCOLWIDTH record containing the default column width of a sheet. ...
Definition: xetable.hxx:679
XclExpFormulaCompiler & GetFormulaCompiler() const
Returns the formula compiler to produce formula token arrays.
Definition: xeroot.cxx:87
void SetRecSize(std::size_t nRecSize)
Sets a new record size prediction.
Definition: xerecord.hxx:162
sal_Int32 mnCol
Represents a NOTE record containing the relevant data of a cell note.
Definition: xeescher.hxx:343
SvNumFormatType GetType(sal_uInt32 nFIndex) const
const SfxItemSet & GetItemSet() const
void Update(SCROW nScRow)
Updates the current state by processing the settings of the passed Calc row.
Definition: xetable.hxx:620
virtual void WriteBody(XclExpStream &rStrm) override
Writes cell address, XF index, and calls WriteContents() for each cell.
Definition: xetable.cxx:615
sal_uInt16 mnHeight
Font color.
Definition: xlstyle.hxx:290
const sal_uInt16 EXC_ID3_BOOLERR
Definition: xltable.hxx:54
XclExpProgressBar & GetProgressBar() const
Returns the export progress bar.
Definition: xeroot.cxx:93
void SetDefWidth(sal_uInt16 nXclColWidth, bool bXLS)
Sets the passed column width (in 1/256 character width) as default width.
Definition: xetable.cxx:1582
const sal_uInt16 EXC_XF_NOTFOUND
Excel index to default cell XF.
Definition: xlstyle.hxx:140
virtual void SaveXml(XclExpXmlStream &rStrm) override
Definition: xetable.cxx:1804
ScAddress aEnd
Definition: address.hxx:500
XclExpDimensions(const XclExpRoot &rRoot)
Definition: xetable.cxx:1490
void set_flag(Type &rnBitField, Type nMask, bool bSet=true)
Sets or clears (according to bSet) all set bits of nMask in rnBitField.
Definition: ftools.hxx:95
XclAddress maLast
Definition: xladdress.hxx:60
sal_uInt32 mnRow
Definition: xladdress.hxx:32
Contains the column settings for a range of columns.
Definition: xetable.hxx:699
const sal_uInt16 EXC_ID2_DEFROWHEIGHT
Definition: xltable.hxx:111
Represents a BOOLERR record that describes a cell with a Boolean value.
Definition: xetable.hxx:374
XclExpRecordRef CreateRecord(sal_uInt16 nRecId) const
Returns the reference to an internal record specified by the passed record id.
Definition: xetable.cxx:2702
OpCode GetOpCode() const
bool mbEnabled
true = Do not add blank cells in Finalize().
Definition: xetable.hxx:895
std::size_t GetRecSize() const
Returns the current record size prediction.
Definition: xerecord.hxx:157
XclExpRowOutlineBuffer maOutlineBfr
Definition: xetable.hxx:938
This is very similar to ScCellValue, except that it references the original value instead of copying ...
Definition: cellvalue.hxx:103
sal_uInt8 mnHighestOutlineLevel
Buffer for column outline groups.
Definition: xetable.hxx:774
void Finalize()
Finalizes the record.
Definition: xetable.cxx:373
XclAddress maFirst
Definition: xladdress.hxx:59
virtual void WriteBody(XclExpStream &rStrm) override
Writes the contents of this COLINFO record.
Definition: xetable.cxx:1675
sal_uInt16 mnFlags
Row height in twips.
Definition: xetable.hxx:889
void ConvertXFIndexes()
Converts the XF identifier into the Excel XF index.
Definition: xetable.cxx:1647
ScDocument & GetDoc() const
Returns reference to the destination document (import) or source document (export).
Definition: xlroot.cxx:276
void ActivateFinalRowsSegment()
Activates the progress segment to finalize ROW records.
Definition: xehelper.cxx:127
SvNumberFormatter & GetFormatter() const
Returns the number formatter of the Calc document.
Definition: xlroot.cxx:313
const sal_uInt16 EXC_DEFROW_DEFAULTHEIGHT
Definition: xltable.hxx:120
const XclExpXF * GetXFById(sal_uInt32 nXFId) const
Returns an XF record by its unique identifier.
Definition: xestyle.cxx:2492
Represents a BLANK or MULBLANK record that describes empty but formatted cells.
Definition: xetable.hxx:521
virtual void WriteBody(XclExpStream &rStrm) override
Writes the contents of the DIMENSIONS record.
Definition: xetable.cxx:1538
const ScOutlineEntry * GetEntryByPos(size_t nLevel, SCCOLROW nPos) const
Definition: olinetab.cxx:464
const sal_uInt16 EXC_FORMULA_DEFAULTFLAGS
Definition: xltable.hxx:67
std::size_t mnContSize
Record ID for multiple record variant.
Definition: xetable.hxx:516
XclExpRecordRef mxStringRec
Additional record for matrix/shared formulas.
Definition: xetable.hxx:452
sal_uInt8 mnOutlineLevel
Default row formatting.
Definition: xetable.hxx:891
void waitUntilDone(const std::shared_ptr< ThreadTaskTag > &, bool bJoin=true)
svExternalName
sal_uInt32 GetXclRow() const
Returns the Excel row index of the cell.
Definition: xetable.hxx:281
virtual void WriteContents(XclExpStream &rStrm)=0
Derived classes write the contents of the specified cell (without XF index).
const sal_uInt8 EXC_TOKID_TBL
Array or shared formula reference.
Definition: xlformula.hxx:53
virtual XclTokenArrayRef CreateCellTokenArray(const XclExpRoot &rRoot) const override
Creates and returns the token array for a corresponding FORMULA cell record.
Definition: xetable.cxx:123
bool TryExtend(const ScAddress &rScPos, const XclMultipleOpRefs &rRefs)
Returns true, if the cell range has been extended to the passed position.
Definition: xetable.cxx:309
const ScOutlineArray * mpScOLArray
Definition: xetable.hxx:593
bool IsMultilineResult()
Determines whether or not the result string contains more than one paragraph.
XclExpDefrowhRef mxDefrowheight
Buffer for TABLEOP records.
Definition: xetable.hxx:1007
void SetDimensions(sal_uInt16 nFirstUsedXclCol, sal_uInt32 nFirstUsedXclRow, sal_uInt16 nFirstFreeXclCol, sal_uInt32 nFirstFreeXclRow)
Sets the used area to the record.
Definition: xetable.cxx:1508
constexpr TypedWhichId< ScMergeAttr > ATTR_MERGE(144)
const XclExpRoot & mrRoot
Definition: xetable.hxx:657
SC_DLLPUBLIC sal_uInt16 GetRowHeight(SCROW nRow, SCTAB nTab, bool bHiddenAsZero=true) const
Definition: document.cxx:4192
static bool GetRKFromDouble(sal_Int32 &rnRKValue, double fValue)
Calculates an RK value (encoded integer or double) from a double value.
Definition: xltools.cxx:124
sal_uInt8 mnOutlineLevel
Additional column flags.
Definition: xetable.hxx:737
const sal_uInt16 EXC_ID3_DIMENSIONS
Definition: xltable.hxx:33
sal_uInt16 GetRecId() const
Returns the current record ID.
Definition: xerecord.hxx:155
sal_uInt16 mnLastXclCol
Index to first column.
Definition: xetable.hxx:739
constexpr auto convertTwipToMm100(N n)
sal_uInt16 mnFirstUsedXclCol
First unused row after used area.
Definition: xetable.hxx:660
XclExpArrayBuffer(const XclExpRoot &rRoot)
Definition: xetable.cxx:141
sal_uInt8 mnUsedCount
The token array of a shared formula.
Definition: xetable.hxx:170
#define SAL_MAX_UINT32
const sal_uInt8 EXC_OUTLINE_MAX
Definition: xltable.hxx:28
XclExpRecordList< XclExpTableop > maTableopList
Definition: xetable.hxx:267
FuncFlags mnFlags
Information about all parameters.
Represents an ARRAY record that contains the token array of a matrix formula.
Definition: xetable.hxx:107
const OUString & GetUrlList() const
Returns a string containing all processed URLs.
Definition: xehelper.hxx:197
void WriteRangeAddress(XclExpStream &rStrm) const
Writes the range address covered by this record.
Definition: xetable.cxx:110
XclExpMultiCellBase(sal_uInt16 nRecId, sal_uInt16 nMulRecId, std::size_t nContSize, const XclAddress &rXclPos)
Definition: xetable.cxx:1101
The formula compiler to create Excel token arrays from Calc token arrays.
Definition: xeformula.hxx:51
virtual bool IsVolatile() const override
Returns true, if the array formula contains volatile functions.
Definition: xetable.cxx:128
sal_uInt32 mnSstIndex
The cell text.
Definition: xetable.hxx:424
Access to global data from other classes.
Definition: xeroot.hxx:112
RecType * GetLastRecord() const
Returns reference to the last existing record or empty reference, if list is empty.
Definition: xerecord.hxx:338
const EditTextObject * mpEditText
Definition: cellvalue.hxx:109
const sal_uInt16 EXC_FONT_NOTFOUND
Application font index.
Definition: xlstyle.hxx:77
bool TryMergeXFIds(const XclExpMultiCellBase &rCell)
Tries to merge the XF ID list of the passed cell with the own list.
Definition: xetable.cxx:1258
sal_uInt16 mnHeight
Default flags for unspecified rows.
Definition: xetable.hxx:783
MS Excel 4.0.
Definition: xlconst.hxx:34
static OString lcl_GetStyleId(const XclExpXmlStream &rStrm, sal_uInt32 nXFIndex)
Definition: xetable.cxx:630
#define SAL_MAX_UINT16
sal_Int32 SCCOLROW
a type capable of holding either SCCOL or SCROW
Definition: types.hxx:23
SC_DLLPUBLIC SCROW GetLastFlaggedRow(SCTAB nTab) const
Definition: document.cxx:4603
sal_Int32 GetXmlCellIndex(sal_uInt32 nXFId) const
Definition: xestyle.cxx:2612
ReturnType ulimit_cast(Type nValue, ReturnType nMax)
Returns the value, if it is not greater than nMax, otherwise nMax.
Definition: ftools.hxx:53
virtual bool TryMerge(const XclExpCellBase &rCell) override
Tries to merge the contents of the passed cell to own data.
Definition: xetable.cxx:1362
Helper to create HLINK records during creation of formatted cell strings.
Definition: xehelper.hxx:177
XclExpTableopRef TryCreate(const ScAddress &rScPos, const XclMultipleOpRefs &rRefs)
Tries to create a new TABLEOP record, if rRefs contains valid references.
Definition: xetable.cxx:487
void DisableIfDefault(const XclExpDefaultRowData &rDefRowData)
Disables this row, if it is defaultable and has the passed default format.
Definition: xetable.cxx:2062
const sal_uInt16 EXC_ID_MERGEDCELLS
Definition: xlcontent.hxx:32
double GetValue()
XclExpSingleCellBase(sal_uInt16 nRecId, std::size_t nContSize, const XclAddress &rXclPos, sal_uInt32 nXFId)
Definition: xetable.cxx:569
ScAddress maFmlaScPos
Definition: xlformula.hxx:470
sal_uInt16 GetCellCount() const
Returns the number of cells this record represents.
Definition: xetable.cxx:1236
constexpr sal_uInt32 NUMBERFORMAT_ENTRY_NOT_FOUND
FormulaError GetErrCode()
std::shared_ptr< XclExpRow > RowRef
Definition: xetable.hxx:934
Represents a SHRFMLA record that contains the token array of a shared formula.
Definition: xetable.hxx:151
const sal_uInt8 EXC_FORMULA_RES_STRING
Definition: xltable.hxx:69
std::vector< XclExpLevelInfo > maLevelInfos
Pointer to Calc outline array.
Definition: xetable.hxx:595
size_t GetDepth() const
Definition: olinetab.hxx:110
int nCount
virtual void ConvertXFIndexes(const XclExpRoot &rRoot) override
Convert all XF identifiers into the Excel XF indexes.
Definition: xetable.cxx:1124
void WriteCellList(XclExpStream &rStrm)
Writes all cell records of this row.
Definition: xetable.cxx:2070
virtual const ScSingleRefData * GetSingleRef() const
sal_uInt16 mnWidth
True = Column width is different from default width.
Definition: xetable.hxx:734
XclTokenArrayRef CreateSpecialRefFormula(sal_uInt8 nTokenId, const XclAddress &rXclPos)
Creates a single token for a special cell reference.
Definition: xeformula.cxx:2681
virtual sal_uInt16 GetLastXclCol() const =0
Derived classes return the column index of the last contained cell.
XclExpColOutlineBuffer maOutlineBfr
The DEFCOLWIDTH record.
Definition: xetable.hxx:773
void Set(sal_uInt16 nCol1, sal_uInt32 nRow1, sal_uInt16 nCol2, sal_uInt32 nRow2)
Definition: xladdress.hxx:68
static bool operator<(const XclExpDefaultRowData &rLeft, const XclExpDefaultRowData &rRight)
Definition: xetable.cxx:1829
const sal_uInt16 EXC_ROW_ROWBLOCKSIZE
Definition: xltable.hxx:94
XclExtLstRef mxExtLst
Data validation with DVAL and DV records.
Definition: xetable.hxx:1013
ScFormulaCell * mpFormula
Definition: cellvalue.hxx:110
XclExpShrfmlaBuffer maShrfmlaBfr
Buffer for ARRAY records.
Definition: xetable.hxx:1005
SCTAB Tab() const
Definition: address.hxx:270
Represents a DEFROWHEIGHT record containing default format for unused rows.
Definition: xetable.hxx:795
void SetRow(SCROW nRowP)
Definition: address.hxx:274
void ConvertXFIndex(const XclExpRoot &rRoot)
Converts the XF identifier in mnXFId to an Excel XF index and stores it in mnXFIndex.
Definition: xestyle.cxx:2034
const sal_uInt8 EXC_BOOLERR_BOOL
Definition: xltable.hxx:56
::std::vector< XclFormatRun > XclFormatRunVec
A vector with all formatting runs for a rich-string.
Definition: xlstring.hxx:84
virtual void SaveXml(XclExpXmlStream &rStrm) override
Definition: xetable.cxx:2728
sal_uInt8 mnScMode
Row index of row input cell.
Definition: xetable.hxx:240
Stores all number formats used in the document.
Definition: xestyle.hxx:268
const sal_uInt16 EXC_ID3_DEFROWHEIGHT
Definition: xltable.hxx:112
The outline buffer for column outlines.
Definition: xetable.hxx:601
XclExpHyperlinkRef mxHyperlinkList
MERGEDCELLS record for merged cell ranges.
Definition: xetable.hxx:1011
ScAddress maColRelScPos
Definition: xlformula.hxx:472
ScAddress aPos
sax_fastparser::FSHelperPtr & GetCurrentStream()
Definition: xestream.cxx:915
virtual XclTokenArrayRef CreateCellTokenArray(const XclExpRoot &rRoot) const override
Creates and returns the token array for a corresponding FORMULA cell record.
Definition: xetable.cxx:407
void SetCol(SCCOL nColP)
Definition: address.hxx:278
SvNumFormatType GetFormatType() const
virtual void ConvertXFIndexes(const XclExpRoot &rRoot) override
Converts the XF identifier into the Excel XF index.
Definition: xetable.cxx:603
bool IsCollapsed() const
Returns true, if a collapsed group ends at the last processed position.
Definition: xetable.hxx:572
bool IsBasePos(sal_uInt16 nXclCol, sal_uInt32 nXclRow) const
Returns true, if the passed cell position is equal to own base position.
Definition: xetable.cxx:95
virtual void WriteBody(XclExpStream &rStrm) override
Writes the body of the record (without record header).
Definition: xetable.cxx:64
void ExtendRange(const ScAddress &rScPos)
Extends the cell range to include the passed cell address.
Definition: xetable.cxx:188
void GetXFIndexes(ScfUInt16Vec &rXFIndexes) const
Inserts the Excel XF index(es) into the passed vector.
Definition: xetable.cxx:1268
sal_uInt16 GetLen() const
void GetRange(SCCOLROW &rStart, SCCOLROW &rEnd) const
Definition: olinetab.cxx:555
virtual void GetBlankXFIndexes(ScfUInt16Vec &rXFIndexes) const
Derived classes for blank cells insert the Excel XF index(es) into the passed vector.
Definition: xetable.cxx:557
const sal_uInt16 EXC_ID3_BLANK
Definition: xltable.hxx:37
void SetDefaultData(const XclExpDefaultRowData &rDefData)
Sets the passed default data as current record contents.
Definition: xetable.cxx:1840
sal_uInt32 mnRowInpXclRow
Column index of row input cell.
Definition: xetable.hxx:239
bool mbLineBreak
Index into Shared String Table (only used for BIFF8).
Definition: xetable.hxx:425
bool IsDefaultable() const
Returns true, if this row may be omitted by using the DEFROWHEIGHT record.
Definition: xetable.cxx:2055
virtual void WriteXmlContents(XclExpXmlStream &rStrm, const XclAddress &rAddress, sal_uInt32 nXFId, sal_uInt16 nRelCol) override
Definition: xetable.cxx:1344
ocMatRef
const sal_uInt16 EXC_ID_DVAL
Font escapement type modified?
Definition: xlcontent.hxx:97
static ThreadPool & getSharedOptimalPool()
XclTokenArrayRef CreateErrorFormula(sal_uInt8 nErrCode)
Creates a single error token containing the passed error code.
Definition: xeformula.cxx:2676
XclTokenArrayRef mxTokArr
Definition: xetable.hxx:121
constexpr TypedWhichId< SfxUInt32Item > ATTR_VALIDDATA(153)
const sal_uInt16 EXC_ID3_NUMBER
Definition: xltable.hxx:44
Matrix (array) formula.
Definition: xlformula.hxx:163
bool IsDefault(const XclExpDefcolwidth &rDefColWidth)
Returns true, if the column has default format and width.
Definition: xetable.cxx:1652
XclExpArray(const XclTokenArrayRef &xTokArr, const ScRange &rScRange)
Definition: xetable.cxx:117
sal_uInt16 mnColInpXclCol
Column index of last appended cell.
Definition: xetable.hxx:236
sal_uInt16 mnHeight
Excel row index of this row.
Definition: xetable.hxx:888
bool TryMerge(const XclExpColinfo &rColInfo)
Tries to merge this record with the passed record.
Definition: xetable.cxx:1661
virtual void WriteContents(XclExpStream &rStrm, sal_uInt16 nRelCol) override
Writes the remaining contents of the specified cell (without XF index).
Definition: xetable.cxx:1388
sal_uInt32 GetXFId() const
Definition: xetable.hxx:344
SC_DLLPUBLIC bool ColHidden(SCCOL nCol, SCTAB nTab, SCCOL *pFirstCol=nullptr, SCCOL *pLastCol=nullptr) const
Definition: document.cxx:4476
sal_uInt16 mnFirstFreeXclCol
First used column.
Definition: xetable.hxx:661
MS Excel 5.0, MS Excel 7.0 (95)
Definition: xlconst.hxx:35
A record with a single value of type Type.
Definition: xerecord.hxx:197
XclExpFormulaCell(const XclExpRoot &rRoot, const XclAddress &rXclPos, const ScPatternAttr *pPattern, sal_uInt32 nForcedXFId, const ScFormulaCell &rScFmlaCell, XclExpArrayBuffer &rArrayBfr, XclExpShrfmlaBuffer &rShrfmlaBfr, XclExpTableopBuffer &rTableopBfr)
Definition: xetable.cxx:815
const sal_uInt16 EXC_DEFCOLWIDTH_DEF
Definition: xltable.hxx:137
Base class for all cell records supporting multiple contents.
Definition: xetable.hxx:466
const ScAddress & GetMaxPos() const
Returns the highest possible cell address valid in Calc and Excel (using current BIFF version)...
Definition: xlroot.hxx:246
OptionalString sType
XclExpAddressConverter & GetAddressConverter() const
Returns the address converter.
Definition: xeroot.cxx:81
void IncRowRecordCount()
Increases the number of existing ROW records by 1.
Definition: xehelper.cxx:107
virtual void WriteContents(XclExpStream &rStrm) override
Derived classes write the contents of the specified cell (without XF index).
Definition: xetable.cxx:796
sal_uInt16 GetFirstFreeXclCol() const
Returns the column index of the first unused cell following all used cells in this row...
Definition: xetable.cxx:2050
virtual const ScComplexRefData * GetDoubleRef() const
static double GetDoubleFromRK(sal_Int32 nRKValue)
GUID of file moniker (HLINK record).
Definition: xltools.cxx:98
XclExpTableopBuffer(const XclExpRoot &rRoot)
Definition: xetable.cxx:451
int i
void pushTask(std::unique_ptr< ThreadTask > pTask)
XclExpMultiXFIdDeq maXFIds
Data size of contents for one cell.
Definition: xetable.hxx:517
bool IsUnsynced() const
Returns true, if the rows have a manually set height by default.
Definition: xetable.hxx:791
const sal_uInt16 EXC_ID_LABELSST
Definition: xltable.hxx:159
TokensType maRecMap
Definition: xetable.hxx:200
This class contains the DV record list following the DVAL record.
Definition: xecontent.hxx:353
void IncCol(SCCOL nDelta=1)
Definition: address.hxx:303
static sal_uInt8 GetXclErrorCode(FormulaError nScError)
Converts a Calc error code to an Excel error code.
Definition: xltools.cxx:201
Caches all ARRAY records.
Definition: xetable.hxx:127
bool mbCurrCollapse
Highest level of an open group for current position.
Definition: xetable.hxx:597
XclExpGuts(const XclExpRoot &rRoot)
Definition: xetable.cxx:1455
const ScOutlineArray & GetRowArray() const
Definition: olinetab.hxx:160
const svl::SharedString * mpString
Definition: cellvalue.hxx:108
const sal_uInt16 EXC_ROW_DEFAULTFLAGS
Definition: xltable.hxx:86
sal_Int16 SCCOL
Definition: types.hxx:21
sal_uInt16 mnFlags
Calc width of the column.
Definition: xetable.hxx:736
const ScOutlineArray & GetColArray() const
Definition: olinetab.hxx:158
const sal_uInt16 EXC_ID_COLINFO
Definition: xltable.hxx:140
void UpdateColRow(SCCOLROW nScPos)
Updates the current state by processing the settings at the passed Calc position. ...
Definition: xetable.cxx:1411
virtual void SaveXml(XclExpXmlStream &rStrm) override
Definition: xetable.cxx:1518
void RemoveRecord(size_t nPos)
Removes the record at the specified position from the list.
Definition: xerecord.hxx:368
virtual void WriteBody(XclExpStream &rStrm) override
Writes the body of the record (without record header).
Definition: xetable.cxx:1485
const XclFontData & GetAppFontData() const
Returns the application font data of this file, needed e.g.
Definition: xestyle.cxx:1186
Represents an XF record which contains all formatting data of a cell or cell style.
Definition: xestyle.hxx:426
XclExpNumFmtBuffer & GetNumFmtBuffer() const
Returns the number format buffer.
Definition: xeroot.cxx:117
const sal_uInt16 EXC_ID_DEFCOLWIDTH
Definition: xltable.hxx:136
XclExpTableopRef CreateOrExtendTableop(const ScTokenArray &rScTokArr, const ScAddress &rScPos)
Tries to update an existing or to create a new TABLEOP record.
Definition: xetable.cxx:456
sal_uInt16 mnXFIndex
Flags for the ROW record.
Definition: xetable.hxx:890
XclExpArrayRef FindArray(const ScTokenArray &rScTokArr, const ScAddress &rBasePos) const
Tries to find an ARRAY record that corresponds to an ocMatRef token.
Definition: xetable.cxx:157
virtual void WriteBody(XclExpStream &rStrm) override
Writes the contents of the ROW record.
Definition: xetable.cxx:2110
void Initialize(SCROW nLastScRow)
Initializes the buffer: finds settings and formatting of all columns.
Definition: xetable.cxx:1724
XclExpHyperlinkRef GetLinkRecord() const
Returns the created single HLINk record, or an empty reference.
Definition: xehelper.cxx:329
Represents a STRING record that contains the result of a string formula.
Definition: xetable.hxx:49
void CreateRows(SCROW nFirstFreeScRow)
Forces insertion of all ROW records before the passed row.
Definition: xetable.cxx:2164
void InsertRecord(RecType *pRec, size_t nPos)
Inserts a record at the specified position into the list.
Definition: xerecord.hxx:342
void IncRow(SCROW nDelta=1)
Definition: address.hxx:299
XclExpCellTable(const XclExpRoot &rRoot)
Definition: xetable.cxx:2436
bool HasMultipleUrls() const
Returns true, if multiple URLs have been processed.
Definition: xehelper.hxx:195
void EndRecord()
Checks and corrects real record length.
Definition: xestream.cxx:122
XclExpNoteListRef mxNoteList
GUTS record for outline areas.
Definition: xetable.hxx:1009
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
svExternalDoubleRef
constexpr TypedWhichId< SfxUInt32Item > ATTR_VALUE_FORMAT(146)
MS Excel 3.0.
Definition: xlconst.hxx:33
The base class of all cell records.
Definition: xetable.hxx:273
SvNumFormatType
const sal_uInt16 EXC_ARRAY_RECALC_ALWAYS
Definition: xltable.hxx:103
bool mbLineBreak
Indentation.
Definition: xlstyle.hxx:495
bool IsDefWidth(sal_uInt16 nXclColWidth) const
Returns true, if the own default width exactly matches the passed width.
Definition: xetable.cxx:1571
FormulaToken ** GetArray() const
XclExpStringRef mxResult
Definition: xetable.hxx:58
const sal_uInt16 EXC_ROW_COLLAPSED
Definition: xltable.hxx:82
svExternalSingleRef
static sal_Int16 GetLeadingScriptType(const XclExpRoot &rRoot, const OUString &rString)
Returns the script type first text portion different to WEAK, or the system default script type...
Definition: xehelper.cxx:643
virtual XclTokenArrayRef CreateCellTokenArray(const XclExpRoot &rRoot) const override
Creates and returns the token array for a corresponding FORMULA cell record.
Definition: xetable.cxx:194
void Finalize(XclExpDefaultRowData &rDefRowData, const ScfUInt16Vec &rColXFIndexes)
Converts all XF identifiers into the Excel XF indexes and calculates default formats.
Definition: xetable.cxx:2195
Represents a TABLEOP record for a multiple operations range.
Definition: xetable.hxx:207
virtual void Save(XclExpStream &rStrm) override
Writes the FORMULA record and additional records related to the formula.
Definition: xetable.cxx:915
sal_uInt16 mnColLevels
Definition: xetable.hxx:634
virtual void Save(XclExpStream &rStrm) override
Writes the record header and calls WriteBody().
Definition: xetable.cxx:1604
void Finalize(bool bXLS)
Converts all XF identifiers into the Excel XF indexes and calculates default formats.
Definition: xetable.cxx:2680
sal_uInt16 mnCol
Definition: xladdress.hxx:31
sal_uInt32 GetXclRow() const
Returns the excel row index of this ROW record.
Definition: xetable.hxx:832
void RemoveUnusedXFIndexes(const ScfUInt16Vec &rXFIndexes)
Removes unused Excel XF index(es).
Definition: xetable.cxx:1279
virtual void SaveXml(XclExpXmlStream &rStrm) override
Definition: xetable.cxx:2365
sal_uInt16 mnRowInpXclCol
Row index of column input cell.
Definition: xetable.hxx:238
const sal_uInt16 EXC_ROW_HIDDEN
Definition: xltable.hxx:83
#define SV_COUNTRY_LANGUAGE_OFFSET
virtual void WriteBody(XclExpStream &rStrm) override
Writes the body of the record (without record header).
Definition: xetable.cxx:133
RecType * GetFirstRecord() const
Returns reference to the first existing record or empty reference, if list is empty.
Definition: xerecord.hxx:335
virtual void RemoveUnusedBlankCells(const ScfUInt16Vec &rXFIndexes)
Derived classes for blank cells remove unused Excel XF index(es).
Definition: xetable.cxx:562
sal_uInt32 mnXclRowRpt
Outline Level of row (for OOXML)
Definition: xetable.hxx:892
A 2D cell address struct with Excel column and row indexes.
Definition: xladdress.hxx:29
XclExpDefaultRowData()
Default height for unspecified rows.
Definition: xetable.cxx:1815
static SC_DLLPUBLIC OUString addToken(const OUString &rTokenList, std::u16string_view rToken, sal_Unicode cSep, sal_Int32 nSepCount=1, bool bForceSep=false)
Adds the string rToken to rTokenList, using a list separator character.
Definition: global.cxx:654
XclExpRow & GetOrCreateRow(sal_uInt32 nXclRow, bool bRowAlwaysEmpty)
Returns access to the specified ROW record.
Definition: xetable.cxx:2380
Contains all possible default row settings.
Definition: xetable.hxx:780
bool HasLinkRecord() const
Returns true, if a single HLINK record has been created.
Definition: xehelper.cxx:324
std::shared_ptr< FastSerializerHelper > FSHelperPtr
const sal_uInt16 EXC_DEFROW_HIDDEN
Definition: xltable.hxx:115
void AppendXFId(const XclExpMultiXFId &rXFId)
Appends the passed XF identifier nCount times to the list of XF identifiers.
Definition: xetable.cxx:1242
void AppendNewRecord(RecType *pRec)
Appends a newly created record to the list.
Definition: xerecord.hxx:360
std::shared_ptr< XclTokenArray > XclTokenArrayRef
Definition: xlformula.hxx:416
XclExpColinfoBuffer(const XclExpRoot &rRoot)
Definition: xetable.cxx:1716
bool ValidateRange(ScRange &rScRange, bool bWarn)
Checks and eventually crops the cell range to valid dimensions.
Definition: xehelper.cxx:210
virtual bool IsEmpty() const override
Returns true, if this record does not contain at least one valid cell.
Definition: xetable.cxx:598
svSingleRef
void Set(sal_uInt16 nCol, sal_uInt32 nRow)
Definition: xladdress.hxx:38
const svl::SharedString & GetString()
FormulaError
const sal_uInt16 EXC_ID_MULRK
Definition: xltable.hxx:150
sal_Int16 GetDefApiScript() const
Returns the default script type, e.g.
Definition: xlroot.hxx:154
SCCOL Col() const
Definition: address.hxx:266
sal_uInt8 GetHighestOutlineLevel() const
Definition: xetable.hxx:764
const XclExpRoot & GetRoot() const
Returns this root instance - for code readability in derived classes.
Definition: xeroot.hxx:118
Represents a FORMULA record that describes a cell with a formula.
Definition: xetable.hxx:431
XclExpSst & GetSst() const
Returns the shared string table.
Definition: xeroot.cxx:99
virtual bool TryMerge(const XclExpCellBase &rCell)
Derived classes try to merge the contents of the passed cell to own data.
Definition: xetable.cxx:552
SCTAB GetCurrScTab() const
Returns the current Calc sheet index.
Definition: xlroot.hxx:160
sal_uInt8 mnCurrLevel
Info for current row and all levels.
Definition: xetable.hxx:596
virtual sal_uInt32 GetFirstXFId() const override
Return the XF identifier of the first contained cell.
Definition: xetable.cxx:1114
sal_uInt32 InsertWithNumFmt(const ScPatternAttr *pPattern, sal_Int16 nScript, sal_uInt32 nForceScNumFmt, bool bForceLineBreak)
Finds or creates a cell XF record for the passed item set, with custom number format.
Definition: xestyle.cxx:2472
const sal_uInt32 EXC_XFID_NOTFOUND
Special index for "not found" state.
Definition: xlstyle.hxx:142
const sal_uInt16 EXC_FORMULA_RECALC_ALWAYS
Definition: xltable.hxx:64
bool IsMerged() const
Definition: attrib.hxx:71
XclExpTableop(const ScAddress &rScPos, const XclMultipleOpRefs &rRefs, sal_uInt8 nScMode)
Definition: xetable.cxx:296
Base record for additional range formula records (i.e.
Definition: xetable.hxx:64
const sal_uInt16 EXC_ID_GUTS
Definition: xltable.hxx:147
svDoubleRef
const sal_uInt16 EXC_TABLEOP_RECALC_ALWAYS
Definition: xltable.hxx:126
CellType meType
Definition: cellvalue.hxx:105
RecType * GetRecord(size_t nPos) const
Returns reference to an existing record or empty reference on error.
Definition: xerecord.hxx:332
static sal_uInt32 GetDefCellXFId()
Returns the XF identifier representing the default cell XF.
Definition: xestyle.cxx:2487
bool IsValidTokenArray(const ScTokenArray &rArray) const
Check for presence of token that's not allowed in Excel's shared formula.
Definition: xetable.cxx:215
XclExpRowBuffer(const XclExpRoot &rRoot)
Definition: xetable.cxx:2150
XclExpDefcolwidth maDefcolwidth
List of COLINFO records.
Definition: xetable.hxx:772
virtual bool IsVolatile() const override
Returns true, if the shared formula contains volatile functions.
Definition: xetable.cxx:199
constexpr TypedWhichId< ScMergeFlagAttr > ATTR_MERGE_FLAG(145)
CRFlags
Definition: global.hxx:134
virtual void GetBlankXFIndexes(ScfUInt16Vec &rXFIndexes) const override
Inserts the Excel XF index(es) into the passed vector.
Definition: xetable.cxx:1330
sal_Int32 SCROW
Definition: types.hxx:17
const sal_uInt16 EXC_TABLEOP_ROW
Definition: xltable.hxx:128
std::size_t mnContSize
The XF identifier of the cell formatting.
Definition: xetable.hxx:354
void PutInOrder()
Definition: address.cxx:1582
void SetContSize(std::size_t nContSize)
Definition: xetable.hxx:340
XclExpDefcolwidth(const XclExpRoot &rRoot)
Definition: xetable.cxx:1565
virtual bool TryMerge(const XclExpCellBase &rCell) override
Tries to merge the contents of the passed cell to own data.
Definition: xetable.cxx:1324
const XclExpCellAlign & GetAlignmentData() const
Returns the alignment settings of this XF.
Definition: xestyle.hxx:445
Represents a GUTS record containing the level count of row and column outlines.
Definition: xetable.hxx:625
void SetRecHeader(sal_uInt16 nRecId, std::size_t nRecSize)
Sets record ID and size with one call.
Definition: xerecord.cxx:140
XclExpOutlineBuffer(const XclExpRoot &rRoot, bool bRows)
Constructs the outline buffer.
Definition: xetable.cxx:1396
XclAddress maBaseXclPos
Range described by this record.
Definition: xetable.hxx:91
Represents a ROW record and additionally contains all cells records of a row.
Definition: xetable.hxx:822
const sal_uInt16 EXC_ID_RSTRING
Definition: xltable.hxx:156
virtual void SaveXml(XclExpXmlStream &rStrm) override
Definition: xetable.cxx:781
Contains all cell references that can be extracted from a multiple operations formula.
Definition: xlformula.hxx:468
XclExpRangeFmlaRef mxAddRec
The token array of the formula.
Definition: xetable.hxx:451
const sal_uInt8 EXC_FORMULA_RES_BOOL
Result is a string.
Definition: xltable.hxx:70
XclTokenArrayRef mxTokArr
Definition: xetable.hxx:169
XclExpColinfo(const XclExpRoot &rRoot, SCCOL nScCol, SCROW nLastScRow, XclExpColOutlineBuffer &rOutlineBfr)
Constructs the record with the settings in the Calc document.
Definition: xetable.cxx:1613
XclExpShrfmlaBuffer(const XclExpRoot &rRoot)
Definition: xetable.cxx:210
bool mbAlwaysEmpty
Definition: xetable.hxx:894
virtual void RemoveUnusedBlankCells(const ScfUInt16Vec &rXFIndexes) override
Tries to remove unused Excel XF index(es).
Definition: xetable.cxx:1335
#define OSL_ENSURE_BIFF(c)
Definition: xltools.hxx:34
::std::vector< sal_uInt16 > ScfUInt16Vec
Definition: ftools.hxx:255
ScfInt32Vec maRkValues
Definition: xetable.hxx:560
virtual void Save(XclExpStream &rStrm) override
Writes all COLINFO records of this buffer.
Definition: xetable.cxx:1796
void Extend(const ScAddress &rScPos)
Extends the cell range to include the passed cell address.
Definition: xetable.cxx:100
void AppendCell(XclExpCellRef const &xCell, bool bIsMergedBase)
Appends the passed cell object to the row that the cell specifies.
Definition: xetable.cxx:2158
const SfxPoolItem & Get(sal_uInt16 nWhich, bool bSrchInParent=true) const
SC_DLLPUBLIC bool GetTableArea(SCTAB nTab, SCCOL &rEndCol, SCROW &rEndRow, bool bCalcHiddens=false) const
Definition: document.cxx:1020
static XclExpStringRef CreateCellString(const XclExpRoot &rRoot, const OUString &rString, const ScPatternAttr *pCellAttr, XclStrFlags nFlags=XclStrFlags::NONE, sal_uInt16 nMaxLen=EXC_STR_MAXLEN)
Creates a new formatted string from a Calc string cell.
Definition: xehelper.cxx:561
XclExpArrayRef CreateArray(const ScTokenArray &rScTokArr, const ScRange &rScRange)
Inserts a new ARRAY record into the buffer and returns it.
Definition: xetable.cxx:146
sal_uInt32 GetXclRowRpt() const
Definition: xetable.hxx:875
unsigned char sal_uInt8
ScAddress maRowRelScPos
Definition: xlformula.hxx:474
sal_uInt32 mnXFId
Definition: xestyle.hxx:413
void GetMatColsRows(SCCOL &nCols, SCROW &nRows) const
XclExpShrfmlaRef CreateOrExtendShrfmla(const ScFormulaCell &rScCell, const ScAddress &rScPos)
Tries to create a new or to update an existing SHRFMLA record.
Definition: xetable.cxx:254
XclRange maXclRange
Definition: xetable.hxx:90
const sal_uInt16 EXC_ID_MULBLANK
Definition: xltable.hxx:153
virtual void SaveXml(XclExpXmlStream &rStrm) override
Definition: xetable.cxx:2121
XclExpRangeFmlaBase(sal_uInt16 nRecId, sal_uInt32 nRecSize, const ScAddress &rScPos)
Constructs the record with a single cell.
Definition: xetable.cxx:71
XclExpDefaultRowData maDefData
Definition: xetable.hxx:808
std::size_t GetContSize() const
Definition: xetable.hxx:341
virtual void SaveXml(XclExpXmlStream &rStrm) override
Definition: xetable.cxx:1690
Caches all SHRFMLA records and provides functions to update their ranges.
Definition: xetable.hxx:176
double mnWidth
Represents a NUMBER record that describes a cell with a double value.
Definition: xetable.hxx:358
void Update(SCCOL nScCol)
Updates the current state by processing the settings of the passed Calc column.
Definition: xetable.hxx:608
virtual void Save(XclExpStream &rStrm) override
Saves the entire cell table.
Definition: xetable.cxx:2720
Represents a MERGEDCELLS record containing all merged cell ranges in a sheet.
Definition: xecontent.hxx:73
virtual sal_uInt32 GetFirstXFId() const =0
Derived classes return the XF identifier of the first contained cell.
virtual void WriteContents(XclExpStream &rStrm, sal_uInt16 nRelCol)=0
Derived classes write the remaining contents of the specified cell (without XF index).
virtual void WriteBody(XclExpStream &rStrm) override
Writes the body of the record (without record header).
Definition: xetable.cxx:204
void InsertCell(XclExpCellRef xCell, size_t nPos, bool bIsMergedBase)
Inserts a cell at the specified list position, tries to merge with neighbors.
Definition: xetable.cxx:2086
SC_DLLPUBLIC ScOutlineTable * GetOutlineTable(SCTAB nTab, bool bCreate=false)
Definition: documen3.cxx:736
XclTokenArrayRef CreateFormula(XclFormulaType eType, const ScTokenArray &rScTokArr, const ScAddress *pScBasePos=nullptr, XclExpRefLog *pRefLog=nullptr)
Creates and returns the token array of a formula.
Definition: xeformula.cxx:2637
sal_uInt32 Insert(const ScPatternAttr *pPattern, sal_Int16 nScript)
Finds or creates a cell XF record for the passed item set.
Definition: xestyle.cxx:2461
void insert_value(Type &rnBitField, InsertType nValue, sal_uInt8 nStartBit, sal_uInt8 nBitCount)
Inserts a value into a bitfield.
Definition: ftools.hxx:102
const sal_uInt16 EXC_ID_RK
Definition: xltable.hxx:162
void * p
static std::shared_ptr< ThreadTaskTag > createThreadTaskTag()
const sal_uInt16 EXC_COLINFO_HIDDEN
Definition: xltable.hxx:142
Contains all created TABLEOP records and supports creating or updating them.
Definition: xetable.hxx:247
sal_uInt16 mnXFIndex
Temporary XF identifier.
Definition: xestyle.hxx:414
Simple cell formula, also used in change tracking.
Definition: xlformula.hxx:162
XclBiff GetBiff() const
Returns the current BIFF version of the importer/exporter.
Definition: xlroot.hxx:140
const sal_uInt16 EXC_TABLEOP_DEFAULTFLAGS
Definition: xltable.hxx:130
void SetXclCol(sal_uInt16 nXclCol)
Sets this record to a new column position.
Definition: xetable.hxx:307
const sal_uInt16 EXC_ID_HLINK
Definition: xlcontent.hxx:141
const sal_uInt8 EXC_LABEL_MAXLEN
Definition: xltable.hxx:50
virtual void SaveXml(XclExpXmlStream &rStrm) override
Definition: xetable.cxx:1187
XclExpRecordList< XclExpCellBase > maCellList
Definition: xetable.hxx:886
const sal_uInt16 EXC_ID3_TABLEOP
Definition: xltable.hxx:124
const sal_uInt16 EXC_ID3_ARRAY
Definition: xltable.hxx:101
sal_uInt32 Insert(const XclExpStringRef &xString)
Inserts a new string into the table.
Definition: xecontent.cxx:244
constexpr TypedWhichId< SfxStringItem > ATTR_HYPERLINK(155)
size_t GetSize() const
Definition: xerecord.hxx:326
virtual bool IsVolatile() const override
Returns true, if the multiple operations range is volatile.
Definition: xetable.cxx:415
SC_DLLPUBLIC bool RowHidden(SCROW nRow, SCTAB nTab, SCROW *pFirstRow=nullptr, SCROW *pLastRow=nullptr) const
Definition: document.cxx:4460
Complex reference (a range) into the sheet.
Definition: refdata.hxx:122
XclExpXFId maXFId
Definition: xetable.hxx:732
This class provides methods to create an XclExpString.
Definition: xehelper.hxx:214
void StartRecord(sal_uInt16 nRecId, std::size_t nRecSize)
Starts a new record: writes header data, stores calculated record size.
Definition: xestream.cxx:110
virtual void WriteXmlContents(XclExpXmlStream &rStrm, const XclAddress &rAddress, sal_uInt32 nXFId, sal_uInt16 nRelCol) override
Definition: xetable.cxx:1373
bool mbValid
Type of the multiple operation (Calc constant).
Definition: xetable.hxx:241
sal_uInt16 mnRowLevels
Width of column outline area (pixels).
Definition: xetable.hxx:636
bool IsHidden() const
Returns true, if rows are hidden by default.
Definition: xetable.hxx:789
void SetXFId(sal_uInt32 nXFId)
Definition: xetable.hxx:343
const sal_uInt8 EXC_FORMULA_RES_ERROR
Result is Boolean value.
Definition: xltable.hxx:71
const sal_uInt16 EXC_ID3_ROW
Definition: xltable.hxx:80
const sal_uInt16 EXC_ROW_UNSYNCED
Definition: xltable.hxx:84
virtual void WriteContents(XclExpStream &rStrm) override
Derived classes write the contents of the specified cell (without XF index).
Definition: xetable.cxx:687
sal_uInt8 mnHighestOutlineLevel
DIMENSIONS record for used area.
Definition: xetable.hxx:940
XclTokenArrayRef mxTokArr
The Calc formula cell.
Definition: xetable.hxx:450
virtual void SaveXml(XclExpXmlStream &rStrm) override
Definition: xetable.cxx:937
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
bool FindTouchedLevel(SCCOLROW nBlockStart, SCCOLROW nBlockEnd, size_t &rFindLevel) const
Definition: olinetab.cxx:296
SCROW GetRowMerge() const
Definition: attrib.hxx:69
const sal_uInt16 EXC_ID_SHRFMLA
Definition: xltable.hxx:165
XclExpRowBuffer maRowBfr
Buffer for column formatting.
Definition: xetable.hxx:1003
const sal_uInt16 EXC_ARRAY_DEFAULTFLAGS
Definition: xltable.hxx:105
sal_Int32 mnRow
std::shared_ptr< XclExpString > XclExpStringRef
Definition: xeroot.hxx:35
XclExpColinfoList maColInfos
Definition: xetable.hxx:771
sal_uInt16 mnFlags
Definition: xetable.hxx:782
MS Excel 2.1.
Definition: xlconst.hxx:32
const sal_uInt16 EXC_COLINFO_COLLAPSED
Definition: xltable.hxx:144
const XclExpRoot & GetRoot() const
Returns the filter root data.
Definition: xestream.hxx:87
void Finalize(const ScfUInt16Vec &rColXFIndexes, bool bUpdateProgress)
Converts all XF identifiers into the Excel XF indexes.
Definition: xetable.cxx:1896
bool IsHidden() const
Returns true, if this row is hidden.
Definition: xetable.hxx:838
XclExpRecordRef mxGuts
DEFROWHEIGHT record for default row format.
Definition: xetable.hxx:1008
std::pair< const_iterator, bool > insert(Value &&x)
SC_DLLPUBLIC sal_uInt16 GetColWidth(SCCOL nCol, SCTAB nTab, bool bHiddenAsZero=true) const
Definition: document.cxx:4151
virtual void Save(XclExpStream &rStrm) override
Writes the record, calls WriteContents() for each contained cell.
Definition: xetable.cxx:1130
virtual void WriteBody(XclExpStream &rStrm) override
Writes the contents of the TABLEOP record.
Definition: xetable.cxx:433
BadTokenArraysType maBadTokens
Map containing the SHRFMLA records.
Definition: xetable.hxx:201
bool IsEmpty() const
Definition: xerecord.hxx:325
sal_uInt16 mnScWidth
Excel width of the column.
Definition: xetable.hxx:735
virtual void Save(XclExpStream &rStrm) override
Writes the record header and calls WriteBody().
Definition: xerecord.cxx:150
sal_uInt16 mnLastAppXclCol
Definition: xetable.hxx:235
sal_uInt8 GetLevel() const
Returns the highest level of an open group at the last processed position.
Definition: xetable.hxx:574
ScMatrixMode GetMatrixFlag() const
XclExpXFBuffer & GetXFBuffer() const
Returns the cell formatting attributes buffer.
Definition: xeroot.cxx:123
void SetRecId(sal_uInt16 nRecId)
Sets a new record ID.
Definition: xerecord.hxx:160
virtual void ConvertXFIndexes(const XclExpRoot &rRoot)=0
Derived classes convert the XF identifier(s) into the Excel XF index(es).
tools::Long GetCharWidth() const
Returns the width of the '0' character (default font) for the current printer (twips).
Definition: xlroot.hxx:156
XclExpFontBuffer & GetFontBuffer() const
Returns the font buffer.
Definition: xeroot.cxx:111
#define SC_OL_MAXDEPTH
Definition: olinetab.hxx:27
StackVar GetType() const
virtual void WriteContents(XclExpStream &rStrm) override
Derived classes write the contents of the specified cell (without XF index).
Definition: xetable.cxx:658
XclExpTableopBuffer maTableopBfr
Buffer for SHRFMLA records.
Definition: xetable.hxx:1006
sc::CompileFormulaContext & GetCompileFormulaContext() const
Definition: xeroot.hxx:121
Represents a text cell record.
Definition: xetable.hxx:398
sal_uInt16 mnFirstXclCol
Outline Level of column (for OOXML)
Definition: xetable.hxx:738
sal_uInt8 GetHighestOutlineLevel() const
Definition: xetable.hxx:925
void SetXclRowRpt(sal_uInt32 nRpt)
Definition: xetable.hxx:876
XclExpArrayMap maRecMap
Definition: xetable.hxx:139
virtual void Save(XclExpStream &rStrm) override
Writes the DIMENSIONS record, all ROW records and all cell records.
Definition: xetable.cxx:2337
virtual sal_uInt16 GetLastXclCol() const override
Returns the last column, which is equal to the first column for single cells.
Definition: xetable.cxx:588
static bool GetMultipleOpRefs(const ScDocument &rDoc, XclMultipleOpRefs &rRefs, const ScTokenArray &rScTokArr, const ScAddress &rScPos)
Parses the passed formula and tries to extract references of a multiple operation.
Definition: xlformula.cxx:958
bool IsUnsynced() const
Returns true, if this row contains a manually set height.
Definition: xetable.hxx:840
RowMap maRowMap
Definition: xetable.hxx:937
const sal_uInt16 EXC_ID_EXTLST
Definition: xlcontent.hxx:184
bool mbValid
sal_uInt32 InsertWithFont(const ScPatternAttr *pPattern, sal_Int16 nScript, sal_uInt16 nForceXclFont, bool bForceLineBreak)
Finds or creates a cell XF record for the passed item set.
Definition: xestyle.cxx:2466
sal_uInt32 mnFirstUsedXclRow
Definition: xetable.hxx:658
XclExpXFId maXFId
Definition: xetable.hxx:353
const sal_uInt8 EXC_TOKID_EXP
Placeholder for invalid token id.
Definition: xlformula.hxx:52
XclExpRkCell(const XclExpRoot &rRoot, const XclAddress &rXclPos, const ScPatternAttr *pPattern, sal_uInt32 nForcedXFId, sal_Int32 nRkValue)
Definition: xetable.cxx:1352
virtual void Save(XclExpStream &rStrm) override
Writes the record if it is valid.
Definition: xetable.cxx:420
Base class for single records with any content.
Definition: xerecord.hxx:141
sal_uInt16 nPos
XclExpMergedcellsRef mxMergedcells
List of NOTE records.
Definition: xetable.hxx:1010
sal_Int16 SCTAB
Definition: types.hxx:22
SC_DLLPUBLIC CRFlags GetRowFlags(SCROW nRow, SCTAB nTab) const
Definition: document.cxx:4367
ScAddress maColFirstScPos
Position of the (first) formula cell.
Definition: xlformula.hxx:471
virtual void Save(XclExpStream &rStrm) override
Writes the ROW record if the row is not disabled (see DisableIfDefault() function).
Definition: xetable.cxx:2076
const sal_uInt16 EXC_ID3_LABEL
Definition: xltable.hxx:48
const sal_uInt16 EXC_DEFROW_DEFAULTFLAGS
Definition: xltable.hxx:118
sal_uInt16 GetXFIndex(sal_uInt32 nXFId) const
Returns the Excel XF index of the XF record with passed XF ID.
Definition: xestyle.cxx:2594
void AddRecSize(std::size_t nRecSize)
Adds a size value to the record size prediction.
Definition: xerecord.hxx:164
XclExpDvalRef mxDval
List of HLINK records.
Definition: xetable.hxx:1012
ScTokenArray * GetSharedCode()