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