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 
563 void XclExpCellBase::RemoveUnusedBlankCells( const ScfUInt16Vec& /*rXFIndexes*/, size_t /*nStartAllNotFound*/ )
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, 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 += 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 
1280 void XclExpMultiCellBase::RemoveUnusedXFIndexes( const ScfUInt16Vec& rXFIndexes, size_t nStartAllNotFound )
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  // Process only all that possibly are not EXC_XF_NOTFOUND.
1289  size_t nEnd = std::min<size_t>(nLastXclCol + 1, nStartAllNotFound);
1290  for( size_t i = GetXclCol(); i < nEnd; ++i )
1291  {
1292  XclExpMultiXFId aXFId( 0 );
1293  // AppendXFId() tests XclExpXFIndex::mnXFId, set it too
1294  aXFId.mnXFId = aXFId.mnXFIndex = rXFIndexes[ i ];
1295  AppendXFId( aXFId );
1296  }
1297 
1298  // remove leading and trailing unused XF indexes
1299  if( !maXFIds.empty() && (maXFIds.front().mnXFIndex == EXC_XF_NOTFOUND) )
1300  {
1301  SetXclCol( GetXclCol() + maXFIds.front().mnCount );
1302  maXFIds.erase(maXFIds.begin(), maXFIds.begin() + 1);
1303  }
1304  if( !maXFIds.empty() && (maXFIds.back().mnXFIndex == EXC_XF_NOTFOUND) )
1305  maXFIds.pop_back();
1306 
1307  // The Save() function will skip all XF indexes equal to EXC_XF_NOTFOUND.
1308 }
1309 
1311 {
1312  sal_uInt16 col = GetXclCol();
1313  for( const auto& rXFId : maXFIds )
1314  {
1315  if( rXFId.mnXFIndex != EXC_XF_DEFAULTCELL )
1316  col += rXFId.mnCount;
1317  }
1318  return col;
1319 }
1320 
1323 {
1324  OSL_ENSURE( rXFId.mnCount > 0, "XclExpBlankCell::XclExpBlankCell - invalid count" );
1325  AppendXFId( rXFId );
1326 }
1327 
1329  const XclExpRoot& rRoot, const XclAddress& rXclPos, sal_uInt16 nLastXclCol,
1330  const ScPatternAttr* pPattern, sal_uInt32 nForcedXFId ) :
1332 {
1333  OSL_ENSURE( rXclPos.mnCol <= nLastXclCol, "XclExpBlankCell::XclExpBlankCell - invalid column range" );
1334  // #i46627# use default script type instead of ApiScriptType::WEAK
1335  AppendXFId( rRoot, pPattern, rRoot.GetDefApiScript(), nForcedXFId, nLastXclCol - rXclPos.mnCol + 1 );
1336 }
1337 
1339 {
1340  const XclExpBlankCell* pBlankCell = dynamic_cast< const XclExpBlankCell* >( &rCell );
1341  return pBlankCell && TryMergeXFIds( *pBlankCell );
1342 }
1343 
1345 {
1346  GetXFIndexes( rXFIndexes );
1347 }
1348 
1349 void XclExpBlankCell::RemoveUnusedBlankCells( const ScfUInt16Vec& rXFIndexes, size_t nStartAllNotFound )
1350 {
1351  RemoveUnusedXFIndexes( rXFIndexes, nStartAllNotFound );
1352 }
1353 
1354 void XclExpBlankCell::WriteContents( XclExpStream& /*rStrm*/, sal_uInt16 /*nRelCol*/ )
1355 {
1356 }
1357 
1358 void XclExpBlankCell::WriteXmlContents( XclExpXmlStream& rStrm, const XclAddress& rAddress, sal_uInt32 nXFId, sal_uInt16 /* nRelCol */ )
1359 {
1360  sax_fastparser::FSHelperPtr& rWorksheet = rStrm.GetCurrentStream();
1361  rWorksheet->singleElement( XML_c,
1362  XML_r, XclXmlUtils::ToOString(rStrm.GetRoot().GetStringBuf(), rAddress).getStr(),
1363  XML_s, lcl_GetStyleId(rStrm, nXFId) );
1364 }
1365 
1367  const XclExpRoot& rRoot, const XclAddress& rXclPos,
1368  const ScPatternAttr* pPattern, sal_uInt32 nForcedXFId, sal_Int32 nRkValue ) :
1370 {
1371  // #i41210# always use latin script for number cells - may look wrong for special number formats...
1372  AppendXFId( rRoot, pPattern, ApiScriptType::LATIN, nForcedXFId );
1373  maRkValues.push_back( nRkValue );
1374 }
1375 
1377 {
1378  const XclExpRkCell* pRkCell = dynamic_cast< const XclExpRkCell* >( &rCell );
1379  if( pRkCell && TryMergeXFIds( *pRkCell ) )
1380  {
1381  maRkValues.insert( maRkValues.end(), pRkCell->maRkValues.begin(), pRkCell->maRkValues.end() );
1382  return true;
1383  }
1384  return false;
1385 }
1386 
1387 void XclExpRkCell::WriteXmlContents( XclExpXmlStream& rStrm, const XclAddress& rAddress, sal_uInt32 nXFId, sal_uInt16 nRelCol )
1388 {
1389  sax_fastparser::FSHelperPtr& rWorksheet = rStrm.GetCurrentStream();
1390  rWorksheet->startElement( XML_c,
1391  XML_r, XclXmlUtils::ToOString(rStrm.GetRoot().GetStringBuf(), rAddress).getStr(),
1392  XML_s, lcl_GetStyleId(rStrm, nXFId),
1393  XML_t, "n"
1394  // OOXTODO: XML_cm, XML_vm, XML_ph
1395  );
1396  rWorksheet->startElement( XML_v );
1397  rWorksheet->write( XclTools::GetDoubleFromRK( maRkValues[ nRelCol ] ) );
1398  rWorksheet->endElement( XML_v );
1399  rWorksheet->endElement( XML_c );
1400 }
1401 
1402 void XclExpRkCell::WriteContents( XclExpStream& rStrm, sal_uInt16 nRelCol )
1403 {
1404  OSL_ENSURE( nRelCol < maRkValues.size(), "XclExpRkCell::WriteContents - overflow error" );
1405  rStrm << maRkValues[ nRelCol ];
1406 }
1407 
1408 // Rows and Columns
1409 
1411  mpScOLArray( nullptr ),
1412  maLevelInfos( SC_OL_MAXDEPTH ),
1413  mnCurrLevel( 0 ),
1414  mbCurrCollapse( false )
1415 {
1416  if( const ScOutlineTable* pOutlineTable = rRoot.GetDoc().GetOutlineTable( rRoot.GetCurrScTab() ) )
1417  mpScOLArray = &(bRows ? pOutlineTable->GetRowArray() : pOutlineTable->GetColArray());
1418 
1419  if( mpScOLArray )
1420  for( size_t nLevel = 0; nLevel < SC_OL_MAXDEPTH; ++nLevel )
1421  if( const ScOutlineEntry* pEntry = mpScOLArray->GetEntryByPos( nLevel, 0 ) )
1422  maLevelInfos[ nLevel ].mnScEndPos = pEntry->GetEnd();
1423 }
1424 
1426 {
1427  if( !mpScOLArray )
1428  return;
1429 
1430  // find open level index for passed position
1431  size_t nNewOpenScLevel = 0; // new open level (0-based Calc index)
1432  sal_uInt8 nNewLevel = 0; // new open level (1-based Excel index)
1433 
1434  if( mpScOLArray->FindTouchedLevel( nScPos, nScPos, nNewOpenScLevel ) )
1435  nNewLevel = static_cast< sal_uInt8 >( nNewOpenScLevel + 1 );
1436  // else nNewLevel keeps 0 to show that there are no groups
1437 
1438  mbCurrCollapse = false;
1439  if( nNewLevel >= mnCurrLevel )
1440  {
1441  // new level(s) opened, or no level closed - update all level infos
1442  for( size_t nScLevel = 0; nScLevel <= nNewOpenScLevel; ++nScLevel )
1443  {
1444  /* In each level: check if a new group is started (there may be
1445  neighbored groups without gap - therefore check ALL levels). */
1446  if( maLevelInfos[ nScLevel ].mnScEndPos < nScPos )
1447  {
1448  if( const ScOutlineEntry* pEntry = mpScOLArray->GetEntryByPos( nScLevel, nScPos ) )
1449  {
1450  maLevelInfos[ nScLevel ].mnScEndPos = pEntry->GetEnd();
1451  maLevelInfos[ nScLevel ].mbHidden = pEntry->IsHidden();
1452  }
1453  }
1454  }
1455  }
1456  else
1457  {
1458  // level(s) closed - check if any of the closed levels are collapsed
1459  // Calc uses 0-based level indexes
1460  sal_uInt16 nOldOpenScLevel = mnCurrLevel - 1;
1461  for( sal_uInt16 nScLevel = nNewOpenScLevel + 1; !mbCurrCollapse && (nScLevel <= nOldOpenScLevel); ++nScLevel )
1462  mbCurrCollapse = maLevelInfos[ nScLevel ].mbHidden;
1463  }
1464 
1465  // cache new opened level
1466  mnCurrLevel = nNewLevel;
1467 }
1468 
1470  XclExpRecord( EXC_ID_GUTS, 8 ),
1471  mnColLevels( 0 ),
1472  mnColWidth( 0 ),
1473  mnRowLevels( 0 ),
1474  mnRowWidth( 0 )
1475 {
1476  const ScOutlineTable* pOutlineTable = rRoot.GetDoc().GetOutlineTable( rRoot.GetCurrScTab() );
1477  if(!pOutlineTable)
1478  return;
1479 
1480  // column outline groups
1481  const ScOutlineArray& rColArray = pOutlineTable->GetColArray();
1482  mnColLevels = ulimit_cast< sal_uInt16 >( rColArray.GetDepth(), EXC_OUTLINE_MAX );
1483  if( mnColLevels )
1484  {
1485  ++mnColLevels;
1486  mnColWidth = 12 * mnColLevels + 5;
1487  }
1488 
1489  // row outline groups
1490  const ScOutlineArray& rRowArray = pOutlineTable->GetRowArray();
1491  mnRowLevels = ulimit_cast< sal_uInt16 >( rRowArray.GetDepth(), EXC_OUTLINE_MAX );
1492  if( mnRowLevels )
1493  {
1494  ++mnRowLevels;
1495  mnRowWidth = 12 * mnRowLevels + 5;
1496  }
1497 }
1498 
1500 {
1501  rStrm << mnRowWidth << mnColWidth << mnRowLevels << mnColLevels;
1502 }
1503 
1505  mrRoot(rRoot),
1506  mnFirstUsedXclRow( 0 ),
1507  mnFirstFreeXclRow( 0 ),
1508  mnFirstUsedXclCol( 0 ),
1509  mnFirstFreeXclCol( 0 )
1510 {
1511  switch( rRoot.GetBiff() )
1512  {
1513  case EXC_BIFF2: SetRecHeader( EXC_ID2_DIMENSIONS, 8 ); break;
1514  case EXC_BIFF3:
1515  case EXC_BIFF4:
1516  case EXC_BIFF5: SetRecHeader( EXC_ID3_DIMENSIONS, 10 ); break;
1517  case EXC_BIFF8: SetRecHeader( EXC_ID3_DIMENSIONS, 14 ); break;
1518  default: DBG_ERROR_BIFF();
1519  }
1520 }
1521 
1523  sal_uInt16 nFirstUsedXclCol, sal_uInt32 nFirstUsedXclRow,
1524  sal_uInt16 nFirstFreeXclCol, sal_uInt32 nFirstFreeXclRow )
1525 {
1526  mnFirstUsedXclRow = nFirstUsedXclRow;
1527  mnFirstFreeXclRow = nFirstFreeXclRow;
1528  mnFirstUsedXclCol = nFirstUsedXclCol;
1529  mnFirstFreeXclCol = nFirstFreeXclCol;
1530 }
1531 
1533 {
1534  ScRange aRange;
1535  aRange.aStart.SetRow( static_cast<SCROW>(mnFirstUsedXclRow) );
1536  aRange.aStart.SetCol( static_cast<SCCOL>(mnFirstUsedXclCol) );
1537 
1539  {
1540  aRange.aEnd.SetRow( static_cast<SCROW>(mnFirstFreeXclRow-1) );
1541  aRange.aEnd.SetCol( static_cast<SCCOL>(mnFirstFreeXclCol-1) );
1542  }
1543 
1544  aRange.PutInOrder();
1545  rStrm.GetCurrentStream()->singleElement( XML_dimension,
1546  // To be compatible with MS Office 2007,
1547  // we need full address notation format
1548  // e.g. "A1:AMJ177" and not partial like: "1:177".
1549  XML_ref, XclXmlUtils::ToOString(mrRoot.GetDoc(), aRange, true) );
1550 }
1551 
1553 {
1554  XclBiff eBiff = rStrm.GetRoot().GetBiff();
1555  if( eBiff == EXC_BIFF8 )
1557  else
1558  rStrm << static_cast< sal_uInt16 >( mnFirstUsedXclRow ) << static_cast< sal_uInt16 >( mnFirstFreeXclRow );
1560  if( eBiff >= EXC_BIFF3 )
1561  rStrm << sal_uInt16( 0 );
1562 }
1563 
1564 namespace {
1565 
1566 double lclGetCChCorrection(const XclExpRoot& rRoot)
1567 {
1568  // Convert the correction from 1/256ths of a character size to count of chars
1569  // TODO: make to fit ECMA-376-1:2016 18.3.1.81 sheetFormatPr (Sheet Format Properties):
1570  // 5 pixels are added to the base width: 2 for margin padding on each side, plus 1 for gridline
1571  // So this should depend on rRoot.GetCharWidth(), not on font height
1572 
1573  tools::Long nFontHt = rRoot.GetFontBuffer().GetAppFontData().mnHeight;
1574  return XclTools::GetXclDefColWidthCorrection(nFontHt) / 256.0;
1575 }
1576 
1577 } // namespace
1578 
1580  XclExpDoubleRecord(EXC_ID_DEFCOLWIDTH, EXC_DEFCOLWIDTH_DEF + lclGetCChCorrection(rRoot)),
1581  XclExpRoot( rRoot )
1582 {
1583 }
1584 
1585 bool XclExpDefcolwidth::IsDefWidth( sal_uInt16 nXclColWidth ) const
1586 {
1587  // This formula is taking number of characters with GetValue()
1588  // and it is translating it into default column width.
1589  // https://msdn.microsoft.com/en-us/library/documentformat.openxml.spreadsheet.column.aspx
1590  double defaultColumnWidth = 256.0 * GetValue();
1591 
1592  // exactly matched, if difference is less than 1/16 of a character to the left or to the right
1593  return std::abs(defaultColumnWidth - nXclColWidth) < 256.0 * 1.0 / 16.0;
1594 }
1595 
1596 void XclExpDefcolwidth::SetDefWidth( sal_uInt16 nXclColWidth, bool bXLS )
1597 {
1598  double fCCh = nXclColWidth / 256.0;
1599  if (bXLS)
1600  {
1601  const double fCorrection = lclGetCChCorrection(GetRoot());
1602  const double fCorrectedCCh = fCCh - fCorrection;
1603  // Now get the value which would be stored in XLS DefColWidth struct
1604  double fCChRound = std::round(fCorrectedCCh);
1605  // If default width was set to a value that is not representable as integral CCh between 0
1606  // and 255, then just ignore that value, and use an arbitrary default. That way, the stored
1607  // default might not represent the most used column width (or any used column width), but
1608  // that's OK, and it just means that those columns will explicitly store their width in
1609  // 1/256ths of char, and have fUserSet in their ColInfo records.
1610  if (fCChRound < 0.0 || fCChRound > 255.0 || std::abs(fCChRound - fCorrectedCCh) > 1.0 / 512)
1611  fCChRound = 8.0;
1612  fCCh = fCChRound + fCorrection;
1613  }
1614 
1615  SetValue(fCCh);
1616 }
1617 
1619 {
1620  double fCorrectedCCh = GetValue() - lclGetCChCorrection(GetRoot());
1621  // Convert double to sal_uInt16
1622  XclExpUInt16Record aUInt16Rec(GetRecId(),
1623  static_cast<sal_uInt16>(std::round(fCorrectedCCh)));
1624  aUInt16Rec.Save(rStrm);
1625 }
1626 
1628  SCCOL nScCol, SCROW nLastScRow, XclExpColOutlineBuffer& rOutlineBfr ) :
1630  XclExpRoot( rRoot ),
1631  mbCustomWidth( false ),
1632  mnWidth( 0 ),
1633  mnScWidth( 0 ),
1634  mnFlags( 0 ),
1635  mnOutlineLevel( 0 ),
1636  mnFirstXclCol( static_cast< sal_uInt16 >( nScCol ) ),
1637  mnLastXclCol( static_cast< sal_uInt16 >( nScCol ) )
1638 {
1639  ScDocument& rDoc = GetDoc();
1640  SCTAB nScTab = GetCurrScTab();
1641 
1642  // column default format
1644  rDoc.GetMostUsedPattern( nScCol, 0, nLastScRow, nScTab ), GetDefApiScript() );
1645 
1646  // column width. If column is hidden then we should return real value (not zero)
1647  sal_uInt16 nScWidth = rDoc.GetColWidth( nScCol, nScTab, false );
1649  mnScWidth = convertTwipToMm100(nScWidth);
1650 
1651  // column flags
1652  ::set_flag( mnFlags, EXC_COLINFO_HIDDEN, rDoc.ColHidden(nScCol, nScTab) );
1653 
1654  // outline data
1655  rOutlineBfr.Update( nScCol );
1657  ::insert_value( mnFlags, rOutlineBfr.GetLevel(), 8, 3 );
1658  mnOutlineLevel = rOutlineBfr.GetLevel();
1659 }
1660 
1662 {
1664 }
1665 
1666 bool XclExpColinfo::IsDefault( const XclExpDefcolwidth& rDefColWidth )
1667 {
1668  mbCustomWidth = !rDefColWidth.IsDefWidth(mnWidth);
1669  return (maXFId.mnXFIndex == EXC_XF_DEFAULTCELL) &&
1670  (mnFlags == 0) &&
1671  (mnOutlineLevel == 0) &&
1672  !mbCustomWidth;
1673 }
1674 
1676 {
1677  if( (maXFId.mnXFIndex == rColInfo.maXFId.mnXFIndex) &&
1678  (mnWidth == rColInfo.mnWidth) &&
1679  (mnFlags == rColInfo.mnFlags) &&
1680  (mnOutlineLevel == rColInfo.mnOutlineLevel) &&
1681  (mnLastXclCol + 1 == rColInfo.mnFirstXclCol) )
1682  {
1683  mnLastXclCol = rColInfo.mnLastXclCol;
1684  return true;
1685  }
1686  return false;
1687 }
1688 
1690 {
1691  // if last column is equal to last possible column, Excel adds one more
1692  sal_uInt16 nLastXclCol = mnLastXclCol;
1693  if( nLastXclCol == static_cast< sal_uInt16 >( rStrm.GetRoot().GetMaxPos().Col() ) )
1694  ++nLastXclCol;
1695 
1696  rStrm << mnFirstXclCol
1697  << nLastXclCol
1698  << mnWidth
1699  << maXFId.mnXFIndex
1700  << mnFlags
1701  << sal_uInt16( 0 );
1702 }
1703 
1705 {
1706  const double nExcelColumnWidth = mnScWidth / convertTwipToMm100<double>(GetCharWidth());
1707 
1708  // tdf#101363 In MS specification the output value is set with double precision after delimiter:
1709  // =Truncate(({width in pixels} - 5)/{Maximum Digit Width} * 100 + 0.5)/100
1710  // Explanation of magic numbers:
1711  // 5 number - are 4 pixels of margin padding (two on each side), plus 1 pixel padding for the gridlines.
1712  // It is unknown if it should be applied during LibreOffice export
1713  // 100 number - used to limit precision to 0.01 with formula =Truncate( {value}*100+0.5 ) / 100
1714  // 0.5 number (0.005 to output value) - used to increase value before truncating,
1715  // to avoid situation when 2.997 will be truncated to 2.99 and not to 3.00
1716  const double nTruncatedExcelColumnWidth = std::trunc( nExcelColumnWidth * 100.0 + 0.5 ) / 100.0;
1717  rStrm.GetCurrentStream()->singleElement( XML_col,
1718  // OOXTODO: XML_bestFit,
1719  XML_collapsed, ToPsz( ::get_flag( mnFlags, EXC_COLINFO_COLLAPSED ) ),
1720  XML_customWidth, ToPsz( mbCustomWidth ),
1721  XML_hidden, ToPsz( ::get_flag( mnFlags, EXC_COLINFO_HIDDEN ) ),
1722  XML_outlineLevel, OString::number(mnOutlineLevel),
1723  XML_max, OString::number(mnLastXclCol + 1),
1724  XML_min, OString::number(mnFirstXclCol + 1),
1725  // OOXTODO: XML_phonetic,
1726  XML_style, lcl_GetStyleId(rStrm, maXFId.mnXFIndex),
1727  XML_width, OString::number(nTruncatedExcelColumnWidth) );
1728 }
1729 
1731  XclExpRoot( rRoot ),
1732  maDefcolwidth( rRoot ),
1733  maOutlineBfr( rRoot ),
1734  mnHighestOutlineLevel( 0 )
1735 {
1736 }
1737 
1739 {
1740 
1741  for( sal_uInt16 nScCol = 0, nLastScCol = GetMaxPos().Col(); nScCol <= nLastScCol; ++nScCol )
1742  {
1743  maColInfos.AppendNewRecord( new XclExpColinfo( GetRoot(), nScCol, nLastScRow, maOutlineBfr ) );
1745  {
1747  }
1748  }
1749 }
1750 
1751 void XclExpColinfoBuffer::Finalize( ScfUInt16Vec& rXFIndexes, bool bXLS )
1752 {
1753  rXFIndexes.clear();
1754  rXFIndexes.reserve( maColInfos.GetSize() );
1755 
1756  if( !maColInfos.IsEmpty())
1757  {
1758  XclExpColinfo* xPrevRec = maColInfos.GetRecord( 0 );
1759  xPrevRec->ConvertXFIndexes();
1760  for( size_t nPos = 1; nPos < maColInfos.GetSize(); ++nPos )
1761  {
1763  xRec->ConvertXFIndexes();
1764 
1765  // try to merge with previous record
1766  if( xPrevRec->TryMerge( *xRec ) )
1768  else
1769  xPrevRec = xRec;
1770  }
1772  }
1773 
1774  // put XF indexes into passed vector, collect use count of all different widths
1775  std::unordered_map< sal_uInt16, sal_uInt16 > aWidthMap;
1776  sal_uInt16 nMaxColCount = 0;
1777  sal_uInt16 nMaxUsedWidth = 0;
1778  for( size_t nPos = 0; nPos < maColInfos.GetSize(); ++nPos )
1779  {
1780  const XclExpColinfo* xRec = maColInfos.GetRecord( nPos );
1781  sal_uInt16 nColCount = xRec->GetColCount();
1782 
1783  // add XF index to passed vector
1784  rXFIndexes.resize( rXFIndexes.size() + nColCount, xRec->GetXFIndex() );
1785 
1786  // collect use count of column width
1787  sal_uInt16 nWidth = xRec->GetColWidth();
1788  sal_uInt16& rnMapCount = aWidthMap[ nWidth ];
1789  rnMapCount = rnMapCount + nColCount;
1790  if( rnMapCount > nMaxColCount )
1791  {
1792  nMaxColCount = rnMapCount;
1793  nMaxUsedWidth = nWidth;
1794  }
1795  }
1796  maDefcolwidth.SetDefWidth( nMaxUsedWidth, bXLS );
1797 
1798  // remove all default COLINFO records
1799  for( size_t nPos = 0; nPos < maColInfos.GetSize(); ++nPos )
1800  {
1802  if( xRec->IsDefault( maDefcolwidth ) )
1804  }
1806 }
1807 
1809 {
1810  // DEFCOLWIDTH
1811  maDefcolwidth.Save( rStrm );
1812  // COLINFO records
1813  maColInfos.Save( rStrm );
1814 }
1815 
1817 {
1818  if( maColInfos.IsEmpty() )
1819  return;
1820 
1821  sax_fastparser::FSHelperPtr& rWorksheet = rStrm.GetCurrentStream();
1822  rWorksheet->startElement(XML_cols);
1823  maColInfos.SaveXml( rStrm );
1824  rWorksheet->endElement( XML_cols );
1825 }
1826 
1830 {
1831 }
1832 
1835  mnHeight( rRow.GetHeight() )
1836 {
1839 }
1840 
1841 static bool operator<( const XclExpDefaultRowData& rLeft, const XclExpDefaultRowData& rRight )
1842 {
1843  return (rLeft.mnHeight < rRight.mnHeight) ||
1844  ((rLeft.mnHeight == rRight.mnHeight) && (rLeft.mnFlags < rRight.mnFlags));
1845 }
1846 
1849 {
1850 }
1851 
1853 {
1854  maDefData = rDefData;
1855 }
1856 
1858 {
1859  OSL_ENSURE_BIFF( rStrm.GetRoot().GetBiff() >= EXC_BIFF3 );
1860  rStrm << maDefData.mnFlags << maDefData.mnHeight;
1861 }
1862 
1863 XclExpRow::XclExpRow( const XclExpRoot& rRoot, sal_uInt32 nXclRow,
1864  XclExpRowOutlineBuffer& rOutlineBfr, bool bAlwaysEmpty, bool bHidden, sal_uInt16 nHeight ) :
1865  XclExpRecord( EXC_ID3_ROW, 16 ),
1866  XclExpRoot( rRoot ),
1867  mnXclRow( nXclRow ),
1868  mnHeight( nHeight ),
1870  mnXFIndex( EXC_XF_DEFAULTCELL ),
1871  mnOutlineLevel( 0 ),
1872  mnXclRowRpt( 1 ),
1873  mnCurrentRow( nXclRow ),
1874  mbAlwaysEmpty( bAlwaysEmpty ),
1875  mbEnabled( true )
1876 {
1877  SCTAB nScTab = GetCurrScTab();
1878  SCROW nScRow = static_cast< SCROW >( mnXclRow );
1879 
1880  // *** Row flags *** ------------------------------------------------------
1881 
1882  CRFlags nRowFlags = GetDoc().GetRowFlags( nScRow, nScTab );
1883  bool bUserHeight( nRowFlags & CRFlags::ManualSize );
1884  ::set_flag( mnFlags, EXC_ROW_UNSYNCED, bUserHeight );
1885  ::set_flag( mnFlags, EXC_ROW_HIDDEN, bHidden );
1886 
1887  // *** Outline data *** ---------------------------------------------------
1888 
1889  rOutlineBfr.Update( nScRow );
1890  ::set_flag( mnFlags, EXC_ROW_COLLAPSED, rOutlineBfr.IsCollapsed() );
1891  ::insert_value( mnFlags, rOutlineBfr.GetLevel(), 0, 3 );
1892  mnOutlineLevel = rOutlineBfr.GetLevel();
1893 
1894  // *** Progress bar *** ---------------------------------------------------
1895 
1896  XclExpProgressBar& rProgress = GetProgressBar();
1897  rProgress.IncRowRecordCount();
1898  rProgress.Progress();
1899 }
1900 
1901 static size_t findFirstAllSameUntilEnd( const ScfUInt16Vec& rIndexes, sal_uInt16 value,
1902  size_t searchStart = std::numeric_limits<size_t>::max())
1903 {
1904  for( size_t i = std::min(rIndexes.size(), searchStart); i >= 1; --i )
1905  {
1906  if( rIndexes[ i - 1 ] != value )
1907  return i;
1908  }
1909  return 0;
1910 }
1911 
1912 void XclExpRow::AppendCell( XclExpCellRef const & xCell, bool bIsMergedBase )
1913 {
1914  OSL_ENSURE( !mbAlwaysEmpty, "XclExpRow::AppendCell - row is marked to be always empty" );
1915  // try to merge with last existing cell
1916  InsertCell( xCell, maCellList.GetSize(), bIsMergedBase );
1917 }
1918 
1919 void XclExpRow::Finalize( const ScfUInt16Vec& rColXFIndexes, ScfUInt16Vec& aXFIndexes, size_t nStartColAllDefault, bool bProgress )
1920 {
1921  size_t nPos, nSize;
1922 
1923  // *** Convert XF identifiers *** -----------------------------------------
1924 
1925  // additionally collect the blank XF indexes
1926  size_t nColCount = GetMaxPos().Col() + 1;
1927  OSL_ENSURE( rColXFIndexes.size() == nColCount, "XclExpRow::Finalize - wrong column XF index count" );
1928 
1929  // The vector should be preset to all items being EXC_XF_NOTFOUND, to avoid repeated allocations
1930  // and clearing.
1931  assert( aXFIndexes.size() == nColCount );
1932  assert( aXFIndexes.front() == EXC_XF_NOTFOUND );
1933  assert( aXFIndexes.back() == EXC_XF_NOTFOUND );
1934  for( nPos = 0, nSize = maCellList.GetSize(); nPos < nSize; ++nPos )
1935  {
1936  XclExpCellBase* pCell = maCellList.GetRecord( nPos );
1937  pCell->ConvertXFIndexes( GetRoot() );
1938  pCell->GetBlankXFIndexes( aXFIndexes );
1939  }
1940 
1941  // *** Fill gaps with BLANK/MULBLANK cell records *** ---------------------
1942 
1943  /* This is needed because nonexistent cells in Calc are not formatted at all,
1944  but in Excel they would have the column default format. Blank cells that
1945  are equal to the respective column default are removed later in this function. */
1946  if( !mbAlwaysEmpty )
1947  {
1948  // XF identifier representing default cell XF
1950  aXFId.ConvertXFIndex( GetRoot() );
1951 
1952  nPos = 0;
1953  while( nPos <= maCellList.GetSize() ) // don't cache list size, may change in the loop
1954  {
1955  // get column index that follows previous cell
1956  sal_uInt16 nFirstFreeXclCol = (nPos > 0) ? (maCellList.GetRecord( nPos - 1 )->GetLastXclCol() + 1) : 0;
1957  // get own column index
1958  sal_uInt16 nNextUsedXclCol = (nPos < maCellList.GetSize()) ? maCellList.GetRecord( nPos )->GetXclCol() : (GetMaxPos().Col() + 1);
1959 
1960  // is there a gap?
1961  if( nFirstFreeXclCol < nNextUsedXclCol )
1962  {
1963  aXFId.mnCount = nNextUsedXclCol - nFirstFreeXclCol;
1964  XclExpCellRef xNewCell = new XclExpBlankCell( XclAddress( nFirstFreeXclCol, mnXclRow ), aXFId );
1965  // insert the cell, InsertCell() may merge it with existing BLANK records
1966  InsertCell( xNewCell, nPos, false );
1967  // insert default XF indexes into aXFIndexes
1968  for( size_t i = nFirstFreeXclCol; i < nNextUsedXclCol; ++i )
1969  aXFIndexes[ i ] = aXFId.mnXFIndex;
1970  // don't step forward with nPos, InsertCell() may remove records
1971  }
1972  else
1973  ++nPos;
1974  }
1975  }
1976 
1977  // *** Find default row format *** ----------------------------------------
1978 
1979  // Often there will be many EXC_XF_DEFAULTCELL at the end, optimize by ignoring them.
1980  size_t nStartSearchAllDefault = aXFIndexes.size();
1981  if( !maCellList.IsEmpty() && dynamic_cast< const XclExpBlankCell* >( maCellList.GetLastRecord()))
1982  {
1983  const XclExpBlankCell* pLastBlank = static_cast< const XclExpBlankCell* >( maCellList.GetLastRecord());
1984  assert(pLastBlank->GetLastXclCol() == aXFIndexes.size() - 1);
1985  nStartSearchAllDefault = pLastBlank->GetStartColAllDefaultCell();
1986  }
1987  size_t nStartAllDefault = findFirstAllSameUntilEnd( aXFIndexes, EXC_XF_DEFAULTCELL, nStartSearchAllDefault);
1988 
1989  // find most used XF index in the row
1990  sal_uInt16 nRowXFIndex = EXC_XF_DEFAULTCELL;
1991  const size_t nHalfIndexes = aXFIndexes.size() / 2;
1992  if( nStartAllDefault > nHalfIndexes ) // Otherwise most are EXC_XF_DEFAULTCELL.
1993  {
1994  // Very likely the most common one is going to be the last one.
1995  nRowXFIndex = aXFIndexes.back();
1996  size_t nStartLastSame = findFirstAllSameUntilEnd( aXFIndexes, nRowXFIndex );
1997  if( nStartLastSame > nHalfIndexes ) // No, find out the most used one by counting.
1998  {
1999  std::unordered_map< sal_uInt16, size_t > aIndexMap;
2000  size_t nMaxXFCount = 0;
2001  for( const auto& rXFIndex : aXFIndexes )
2002  {
2003  if( rXFIndex != EXC_XF_NOTFOUND )
2004  {
2005  size_t& rnCount = aIndexMap[ rXFIndex ];
2006  ++rnCount;
2007  if( rnCount > nMaxXFCount )
2008  {
2009  nRowXFIndex = rXFIndex;
2010  nMaxXFCount = rnCount;
2011  if (nMaxXFCount > nHalfIndexes)
2012  {
2013  // No other XF index can have a greater usage count, we
2014  // don't need to loop through the remaining cells.
2015  // Specifically for the tail of unused default
2016  // cells/columns this makes a difference.
2017  break; // for
2018  }
2019  }
2020  }
2021  }
2022  }
2023  }
2024 
2025  // decide whether to use the row default XF index or column default XF indexes
2026  bool bUseColDefXFs = nRowXFIndex == EXC_XF_DEFAULTCELL;
2027  if( !bUseColDefXFs )
2028  {
2029  // count needed XF indexes for blank cells with and without row default XF index
2030  size_t nXFCountWithRowDefXF = 0;
2031  size_t nXFCountWithoutRowDefXF = 0;
2032  ScfUInt16Vec::const_iterator aColIt = rColXFIndexes.begin();
2033  for( const auto& rXFIndex : aXFIndexes )
2034  {
2035  sal_uInt16 nXFIndex = rXFIndex;
2036  if( nXFIndex != EXC_XF_NOTFOUND )
2037  {
2038  if( nXFIndex != nRowXFIndex )
2039  ++nXFCountWithRowDefXF; // with row default XF index
2040  if( nXFIndex != *aColIt )
2041  ++nXFCountWithoutRowDefXF; // without row default XF index
2042  }
2043  ++aColIt;
2044  }
2045 
2046  // use column XF indexes if this would cause less or equal number of BLANK records
2047  bUseColDefXFs = nXFCountWithoutRowDefXF <= nXFCountWithRowDefXF;
2048  }
2049 
2050  // *** Remove unused BLANK cell records *** -------------------------------
2051 
2052  size_t maxStartAllNotFound;
2053  if( bUseColDefXFs )
2054  {
2055  size_t maxStartAllDefault = std::max( nStartAllDefault, nStartColAllDefault );
2056  // use column default XF indexes
2057  // #i194#: remove cell XF indexes equal to column default XF indexes
2058  for( size_t i = 0; i < maxStartAllDefault; ++i )
2059  {
2060  if( aXFIndexes[ i ] == rColXFIndexes[ i ] )
2061  aXFIndexes[ i ] = EXC_XF_NOTFOUND;
2062  }
2063  // They can differ only up to maxNonDefault, in the rest they are the same.
2064  for( size_t i = maxStartAllDefault; i < aXFIndexes.size(); ++i )
2065  aXFIndexes[ i ] = EXC_XF_NOTFOUND;
2066  maxStartAllNotFound = maxStartAllDefault;
2067  }
2068  else
2069  {
2070  // use row default XF index
2071  mnXFIndex = nRowXFIndex;
2073  // #98133#, #i194#, #i27407#: remove cell XF indexes equal to row default XF index
2074  for( auto& rXFIndex : aXFIndexes )
2075  if( rXFIndex == nRowXFIndex )
2076  rXFIndex = EXC_XF_NOTFOUND;
2077  maxStartAllNotFound = aXFIndexes.size();
2078  }
2079 
2080  // remove unused parts of BLANK/MULBLANK cell records
2081  size_t nStartAllNotFound = findFirstAllSameUntilEnd( aXFIndexes, EXC_XF_NOTFOUND, maxStartAllNotFound );
2082  nPos = 0;
2083  while( nPos < maCellList.GetSize() ) // do not cache list size, may change in the loop
2084  {
2085  XclExpCellBase* xCell = maCellList.GetRecord( nPos );
2086  xCell->RemoveUnusedBlankCells( aXFIndexes, nStartAllNotFound );
2087  if( xCell->IsEmpty() )
2088  maCellList.RemoveRecord( nPos );
2089  else
2090  ++nPos;
2091  }
2092  // Ensure it's all EXC_XF_NOTFOUND again for next reuse.
2093  for( size_t i = 0; i < nStartAllNotFound; ++i )
2094  aXFIndexes[ i ] = EXC_XF_NOTFOUND;
2095 
2096  // progress bar includes disabled rows; only update it in the lead thread.
2097  if (bProgress)
2099 }
2101 {
2103 }
2104 
2106 {
2107  return maCellList.IsEmpty() ? 0 : (maCellList.GetLastRecord()->GetLastXclCol() + 1);
2108 }
2109 
2111 {
2112  const sal_uInt16 nFlagsAlwaysMarkedAsDefault = EXC_ROW_DEFAULTFLAGS | EXC_ROW_HIDDEN | EXC_ROW_UNSYNCED;
2113  return !::get_flag( mnFlags, static_cast< sal_uInt16 >( ~nFlagsAlwaysMarkedAsDefault ) ) &&
2114  IsEmpty();
2115 }
2116 
2118 {
2119  mbEnabled = !IsDefaultable() ||
2120  (mnHeight != rDefRowData.mnHeight) ||
2121  (IsHidden() != rDefRowData.IsHidden()) ||
2122  (IsUnsynced() != rDefRowData.IsUnsynced());
2123 }
2124 
2126 {
2127  OSL_ENSURE( mbEnabled || maCellList.IsEmpty(), "XclExpRow::WriteCellList - cells in disabled row" );
2128  maCellList.Save( rStrm );
2129 }
2130 
2132 {
2133  if( mbEnabled )
2134  {
2136  for ( sal_uInt32 i = 0; i < mnXclRowRpt; ++i, ++mnCurrentRow )
2137  XclExpRecord::Save( rStrm );
2138  }
2139 }
2140 
2141 void XclExpRow::InsertCell( XclExpCellRef xCell, size_t nPos, bool bIsMergedBase )
2142 {
2143  OSL_ENSURE( xCell, "XclExpRow::InsertCell - missing cell" );
2144 
2145  /* If we have a multi-line text in a merged cell, and the resulting
2146  row height has not been confirmed, we need to force the EXC_ROW_UNSYNCED
2147  flag to be true to ensure Excel works correctly. */
2148  if( bIsMergedBase && xCell->IsMultiLineText() )
2150 
2151  // try to merge with previous cell, insert the new cell if not successful
2152  XclExpCellBase* xPrevCell = maCellList.GetRecord( nPos - 1 );
2153  if( xPrevCell && xPrevCell->TryMerge( *xCell ) )
2154  xCell = xPrevCell;
2155  else
2156  maCellList.InsertRecord( xCell, nPos++ );
2157  // nPos points now to following cell
2158 
2159  // try to merge with following cell, remove it if successful
2160  XclExpCellRef xNextCell = maCellList.GetRecord( nPos );
2161  if( xNextCell && xCell->TryMerge( *xNextCell ) )
2162  maCellList.RemoveRecord( nPos );
2163 }
2164 
2166 {
2167  rStrm << static_cast< sal_uInt16 >(mnCurrentRow)
2168  << GetFirstUsedXclCol()
2169  << GetFirstFreeXclCol()
2170  << mnHeight
2171  << sal_uInt32( 0 )
2172  << mnFlags
2173  << mnXFIndex;
2174 }
2175 
2177 {
2178  if( !mbEnabled )
2179  return;
2180  sax_fastparser::FSHelperPtr& rWorksheet = rStrm.GetCurrentStream();
2181  bool haveFormat = ::get_flag( mnFlags, EXC_ROW_USEDEFXF );
2182  mnCurrentRow = mnXclRow + 1;
2183  for ( sal_uInt32 i=0; i<mnXclRowRpt; ++i )
2184  {
2185  rWorksheet->startElement( XML_row,
2186  XML_r, OString::number(mnCurrentRow++),
2187  // OOXTODO: XML_spans, optional
2188  XML_s, haveFormat ? lcl_GetStyleId( rStrm, mnXFIndex ).getStr() : nullptr,
2189  XML_customFormat, ToPsz( haveFormat ),
2190  XML_ht, OString::number(static_cast<double>(mnHeight) / 20.0),
2191  XML_hidden, ToPsz( ::get_flag( mnFlags, EXC_ROW_HIDDEN ) ),
2192  XML_customHeight, ToPsz( ::get_flag( mnFlags, EXC_ROW_UNSYNCED ) ),
2193  XML_outlineLevel, OString::number(mnOutlineLevel),
2194  XML_collapsed, ToPsz( ::get_flag( mnFlags, EXC_ROW_COLLAPSED ) )
2195  // OOXTODO: XML_thickTop, bool
2196  // OOXTODO: XML_thickBot, bool
2197  // OOXTODO: XML_ph, bool
2198  );
2199  // OOXTODO: XML_extLst
2200  maCellList.SaveXml( rStrm );
2201  rWorksheet->endElement( XML_row );
2202  }
2203 }
2204 
2206  XclExpRoot( rRoot ),
2207  maOutlineBfr( rRoot ),
2208  maDimensions( rRoot ),
2209  mnHighestOutlineLevel( 0 )
2210 {
2211 }
2212 
2213 void XclExpRowBuffer::AppendCell( XclExpCellRef const & xCell, bool bIsMergedBase )
2214 {
2215  OSL_ENSURE( xCell, "XclExpRowBuffer::AppendCell - missing cell" );
2216  GetOrCreateRow( xCell->GetXclRow(), false ).AppendCell( xCell, bIsMergedBase );
2217 }
2218 
2219 void XclExpRowBuffer::CreateRows( SCROW nFirstFreeScRow )
2220 {
2221  if( nFirstFreeScRow > 0 )
2222  GetOrCreateRow( ::std::max ( nFirstFreeScRow - 1, GetMaxPos().Row() ), true );
2223 }
2224 
2225 namespace {
2226 
2227 class RowFinalizeTask : public comphelper::ThreadTask
2228 {
2229  bool mbProgress;
2230  const ScfUInt16Vec& mrColXFIndexes;
2231  size_t mnStartColAllDefault;
2232  std::vector< XclExpRow * > maRows;
2233 public:
2234  RowFinalizeTask( const std::shared_ptr<comphelper::ThreadTaskTag> & pTag,
2235  const ScfUInt16Vec& rColXFIndexes,
2236  size_t nStartColAllDefault,
2237  bool bProgress ) :
2238  comphelper::ThreadTask( pTag ),
2239  mbProgress( bProgress ),
2240  mrColXFIndexes( rColXFIndexes ),
2241  mnStartColAllDefault( nStartColAllDefault )
2242  {}
2243 
2244  void push_back( XclExpRow *pRow ) { maRows.push_back( pRow ); }
2245  virtual void doWork() override
2246  {
2247  ScfUInt16Vec aXFIndexes( mrColXFIndexes.size(), EXC_XF_NOTFOUND );
2248  for (XclExpRow* p : maRows)
2249  p->Finalize( mrColXFIndexes, aXFIndexes, mnStartColAllDefault, mbProgress );
2250  }
2251 };
2252 
2253 }
2254 
2256  const ScfUInt16Vec& rColXFIndexes,
2257  size_t nStartColAllDefault )
2258 {
2259  // *** Finalize all rows *** ----------------------------------------------
2260 
2262 
2263 #if 1
2264  // This is staggeringly slow, and each element operates only
2265  // on its own data.
2266  const size_t nRows = maRowMap.size();
2267  const size_t nThreads = nRows < 128 ? 1 : comphelper::ThreadPool::getPreferredConcurrency();
2268 #else
2269  const size_t nThreads = 1; // globally disable multi-threading for now.
2270 #endif
2271  if (nThreads == 1)
2272  {
2273  ScfUInt16Vec aXFIndexes( rColXFIndexes.size(), EXC_XF_NOTFOUND );
2274  for (auto& rEntry : maRowMap)
2275  rEntry.second->Finalize( rColXFIndexes, aXFIndexes, nStartColAllDefault, true );
2276  }
2277  else
2278  {
2280  std::shared_ptr<comphelper::ThreadTaskTag> pTag = comphelper::ThreadPool::createThreadTaskTag();
2281  std::vector<std::unique_ptr<RowFinalizeTask>> aTasks(nThreads);
2282  for ( size_t i = 0; i < nThreads; i++ )
2283  aTasks[ i ].reset( new RowFinalizeTask( pTag, rColXFIndexes, nStartColAllDefault, i == 0 ) );
2284 
2285  size_t nIdx = 0;
2286  for ( const auto& rEntry : maRowMap )
2287  {
2288  aTasks[ nIdx % nThreads ]->push_back( rEntry.second.get() );
2289  ++nIdx;
2290  }
2291 
2292  for ( size_t i = 1; i < nThreads; i++ )
2293  rPool.pushTask( std::move(aTasks[ i ]) );
2294 
2295  // Progress bar updates must be synchronous to avoid deadlock
2296  aTasks[0]->doWork();
2297 
2298  rPool.waitUntilDone(pTag);
2299  }
2300 
2301  // *** Default row format *** ---------------------------------------------
2302 
2303  std::map< XclExpDefaultRowData, size_t > aDefRowMap;
2304 
2305  XclExpDefaultRowData aMaxDefData;
2306  size_t nMaxDefCount = 0;
2307  // only look for default format in existing rows, if there are more than unused
2308  // if the row is hidden, then row xml must be created even if it not contain cells
2309  XclExpRow* pPrev = nullptr;
2310  std::vector< XclExpRow* > aRepeated;
2311  for (const auto& rEntry : maRowMap)
2312  {
2313  const RowRef& rRow = rEntry.second;
2314  if ( rRow->IsDefaultable() )
2315  {
2316  XclExpDefaultRowData aDefData( *rRow );
2317  size_t& rnDefCount = aDefRowMap[ aDefData ];
2318  ++rnDefCount;
2319  if( rnDefCount > nMaxDefCount )
2320  {
2321  nMaxDefCount = rnDefCount;
2322  aMaxDefData = aDefData;
2323  }
2324  }
2325  if ( pPrev )
2326  {
2327  if ( pPrev->IsDefaultable() )
2328  {
2329  // if the previous row we processed is not
2330  // defaultable then afaict the rows in between are
2331  // not used ( and not repeatable )
2332  sal_uInt32 nRpt = rRow->GetXclRow() - pPrev->GetXclRow();
2333  if ( nRpt > 1 )
2334  aRepeated.push_back( pPrev );
2335  pPrev->SetXclRowRpt( nRpt );
2336  XclExpDefaultRowData aDefData( *pPrev );
2337  size_t& rnDefCount = aDefRowMap[ aDefData ];
2338  rnDefCount += ( pPrev->GetXclRowRpt() - 1 );
2339  if( rnDefCount > nMaxDefCount )
2340  {
2341  nMaxDefCount = rnDefCount;
2342  aMaxDefData = aDefData;
2343  }
2344  }
2345  }
2346  pPrev = rRow.get();
2347  }
2348  // return the default row format to caller
2349  rDefRowData = aMaxDefData;
2350 
2351  // now disable repeating extra (empty) rows that are equal to the default row
2352  for (auto& rpRow : aRepeated)
2353  {
2354  if ( rpRow->GetXclRowRpt() > 1
2355  && rpRow->GetHeight() == rDefRowData.mnHeight
2356  && rpRow->IsHidden() == rDefRowData.IsHidden() )
2357  {
2358  rpRow->SetXclRowRpt( 1 );
2359  }
2360  }
2361 
2362  // *** Disable unused ROW records, find used area *** ---------------------
2363 
2364  sal_uInt16 nFirstUsedXclCol = SAL_MAX_UINT16;
2365  sal_uInt16 nFirstFreeXclCol = 0;
2366  sal_uInt32 nFirstUsedXclRow = SAL_MAX_UINT32;
2367  sal_uInt32 nFirstFreeXclRow = 0;
2368 
2369  for (const auto& rEntry : maRowMap)
2370  {
2371  const RowRef& rRow = rEntry.second;
2372  // disable unused rows
2373  rRow->DisableIfDefault( aMaxDefData );
2374 
2375  // find used column range
2376  if( !rRow->IsEmpty() ) // empty rows return (0...0) as used range
2377  {
2378  nFirstUsedXclCol = ::std::min( nFirstUsedXclCol, rRow->GetFirstUsedXclCol() );
2379  nFirstFreeXclCol = ::std::max( nFirstFreeXclCol, rRow->GetFirstFreeXclCol() );
2380  }
2381 
2382  // find used row range
2383  if( rRow->IsEnabled() )
2384  {
2385  sal_uInt32 nXclRow = rRow->GetXclRow();
2386  nFirstUsedXclRow = ::std::min< sal_uInt32 >( nFirstUsedXclRow, nXclRow );
2387  nFirstFreeXclRow = ::std::max< sal_uInt32 >( nFirstFreeXclRow, nXclRow + 1 );
2388  }
2389  }
2390 
2391  // adjust start position, if there are no or only empty/disabled ROW records
2392  nFirstUsedXclCol = ::std::min( nFirstUsedXclCol, nFirstFreeXclCol );
2393  nFirstUsedXclRow = ::std::min( nFirstUsedXclRow, nFirstFreeXclRow );
2394 
2395  // initialize the DIMENSIONS record
2397  nFirstUsedXclCol, nFirstUsedXclRow, nFirstFreeXclCol, nFirstFreeXclRow );
2398 }
2399 
2401 {
2402  // DIMENSIONS record
2403  maDimensions.Save( rStrm );
2404 
2405  // save in blocks of 32 rows, each block contains first all ROWs, then all cells
2406  size_t nSize = maRowMap.size();
2407  RowMap::iterator itr = maRowMap.begin(), itrEnd = maRowMap.end();
2408  RowMap::iterator itrBlkStart = maRowMap.begin(), itrBlkEnd = maRowMap.begin();
2409  sal_uInt16 nStartXclRow = (nSize == 0) ? 0 : itr->second->GetXclRow();
2410 
2411  for (; itr != itrEnd; ++itr)
2412  {
2413  // find end of row block
2414  itrBlkEnd = std::find_if_not(itrBlkEnd, itrEnd,
2415  [&nStartXclRow](const RowMap::value_type& rRow) { return rRow.second->GetXclRow() - nStartXclRow < EXC_ROW_ROWBLOCKSIZE; });
2416 
2417  // write the ROW records
2418  std::for_each(itrBlkStart, itrBlkEnd, [&rStrm](const RowMap::value_type& rRow) { rRow.second->Save( rStrm ); });
2419 
2420  // write the cell records
2421  std::for_each(itrBlkStart, itrBlkEnd, [&rStrm](const RowMap::value_type& rRow) { rRow.second->WriteCellList( rStrm ); });
2422 
2423  itrBlkStart = (itrBlkEnd == itrEnd) ? itrBlkEnd : itrBlkEnd++;
2424  nStartXclRow += EXC_ROW_ROWBLOCKSIZE;
2425  }
2426 }
2427 
2429 {
2430  if (std::none_of(maRowMap.begin(), maRowMap.end(), [](const RowMap::value_type& rRow) { return rRow.second->IsEnabled(); }))
2431  {
2432  rStrm.GetCurrentStream()->singleElement(XML_sheetData);
2433  return;
2434  }
2435 
2436  sax_fastparser::FSHelperPtr& rWorksheet = rStrm.GetCurrentStream();
2437  rWorksheet->startElement(XML_sheetData);
2438  for (const auto& rEntry : maRowMap)
2439  rEntry.second->SaveXml(rStrm);
2440  rWorksheet->endElement( XML_sheetData );
2441 }
2442 
2443 XclExpRow& XclExpRowBuffer::GetOrCreateRow( sal_uInt32 nXclRow, bool bRowAlwaysEmpty )
2444 {
2445  // This is called rather often, so optimize for the most common case of saving row by row
2446  // (so the requested row is often the last one in the map or belongs after the last one).
2447  RowMap::iterator itr;
2448  if(maRowMap.empty())
2449  itr = maRowMap.end();
2450  else
2451  {
2452  RowMap::reverse_iterator last = maRowMap.rbegin();
2453  if( last->first == nXclRow )
2454  return *last->second;
2455  if( nXclRow > last->first )
2456  itr = maRowMap.end();
2457  else
2458  itr = maRowMap.lower_bound( nXclRow );
2459  }
2460  const bool bFound = itr != maRowMap.end();
2461  // bFoundHigher: nXclRow was identical to the previous entry, so not explicitly created earlier
2462  // coverity[deref_iterator : FALSE] - clearly itr if only derefed if bFound which checks for valid itr
2463  const bool bFoundHigher = bFound && itr->first != nXclRow;
2464  if( bFound && !bFoundHigher )
2465  return *itr->second;
2466 
2467  size_t nFrom = 0;
2468  RowRef pPrevEntry;
2469  if( itr != maRowMap.begin() )
2470  {
2471  --itr;
2472  pPrevEntry = itr->second;
2473  if( bFoundHigher )
2474  nFrom = nXclRow;
2475  else
2476  nFrom = itr->first + 1;
2477  }
2478 
2479  const ScDocument& rDoc = GetRoot().GetDoc();
2480  const SCTAB nScTab = GetRoot().GetCurrScTab();
2481  // Do not repeatedly call RowHidden() / GetRowHeight() for same values.
2482  bool bHidden = false;
2483  SCROW lastSameHiddenRow = -1;
2484  sal_uInt16 nHeight = 0;
2485  SCROW lastSameHeightRow = -1;
2486  // create the missing rows first
2487  while( nFrom <= nXclRow )
2488  {
2489  // only create RowMap entries if it is first row in spreadsheet,
2490  // if it is the desired row, or for rows that differ from previous.
2491  if( static_cast<SCROW>(nFrom) > lastSameHiddenRow )
2492  bHidden = rDoc.RowHidden(nFrom, nScTab, nullptr, &lastSameHiddenRow);
2493  // Always get the actual row height even if the manual size flag is
2494  // not set, to correctly export the heights of rows with wrapped
2495  // texts.
2496  if( static_cast<SCROW>(nFrom) > lastSameHeightRow )
2497  nHeight = rDoc.GetRowHeight(nFrom, nScTab, nullptr, &lastSameHeightRow, false);
2498  if ( !pPrevEntry || ( nFrom == nXclRow ) ||
2499  ( maOutlineBfr.IsCollapsed() ) ||
2500  ( maOutlineBfr.GetLevel() != 0 ) ||
2501  ( bRowAlwaysEmpty && !pPrevEntry->IsEmpty() ) ||
2502  ( bHidden != pPrevEntry->IsHidden() ) ||
2503  ( nHeight != pPrevEntry->GetHeight() ) )
2504  {
2506  {
2508  }
2509  RowRef p = std::make_shared<XclExpRow>(GetRoot(), nFrom, maOutlineBfr, bRowAlwaysEmpty, bHidden, nHeight);
2510  maRowMap.emplace(nFrom, p);
2511  pPrevEntry = p;
2512  }
2513  ++nFrom;
2514  }
2515  itr = maRowMap.find(nXclRow);
2516  return *itr->second;
2517 }
2518 
2519 // Cell Table
2520 
2522  XclExpRoot( rRoot ),
2523  maColInfoBfr( rRoot ),
2524  maRowBfr( rRoot ),
2525  maArrayBfr( rRoot ),
2526  maShrfmlaBfr( rRoot ),
2527  maTableopBfr( rRoot ),
2528  mxDefrowheight( new XclExpDefrowheight() ),
2529  mxGuts( new XclExpGuts( rRoot ) ),
2530  mxNoteList( new XclExpNoteList ),
2531  mxMergedcells( new XclExpMergedcells( rRoot ) ),
2532  mxHyperlinkList( new XclExpHyperlinkList ),
2533  mxDval( new XclExpDval( rRoot ) ),
2534  mxExtLst( new XclExtLst( rRoot ) )
2535 {
2536  ScDocument& rDoc = GetDoc();
2537  SCTAB nScTab = GetCurrScTab();
2538  SvNumberFormatter& rFormatter = GetFormatter();
2539 
2540  // maximum sheet limits
2541  SCCOL nMaxScCol = GetMaxPos().Col();
2542  SCROW nMaxScRow = GetMaxPos().Row();
2543 
2544  // find used area (non-empty cells)
2545  SCCOL nLastUsedScCol;
2546  SCROW nLastUsedScRow;
2547  rDoc.GetTableArea( nScTab, nLastUsedScCol, nLastUsedScRow );
2548 
2549  if(nLastUsedScCol > nMaxScCol)
2550  nLastUsedScCol = nMaxScCol;
2551 
2552  // check extra blank rows to avoid of losing their not default settings (workaround for tdf#41425)
2553  nLastUsedScRow += 1000;
2554 
2555  if(nLastUsedScRow > nMaxScRow)
2556  nLastUsedScRow = nMaxScRow;
2557 
2558  ScRange aUsedRange( 0, 0, nScTab, nLastUsedScCol, nLastUsedScRow, nScTab );
2559  GetAddressConverter().ValidateRange( aUsedRange, true );
2560  nLastUsedScRow = aUsedRange.aEnd.Row();
2561 
2562  // first row without any set attributes (height/hidden/...)
2563  SCROW nFirstUnflaggedScRow = rDoc.GetLastFlaggedRow( nScTab ) + 1;
2564 
2565  // find range of outlines
2566  SCROW nFirstUngroupedScRow = 0;
2567  if( const ScOutlineTable* pOutlineTable = rDoc.GetOutlineTable( nScTab ) )
2568  {
2569  SCCOLROW nScStartPos, nScEndPos;
2570  const ScOutlineArray& rRowArray = pOutlineTable->GetRowArray();
2571  rRowArray.GetRange( nScStartPos, nScEndPos );
2572  // +1 because open/close button is in next row in Excel, +1 for "end->first unused"
2573  nFirstUngroupedScRow = static_cast< SCROW >( nScEndPos + 2 );
2574  }
2575 
2576  // column settings
2577  /* #i30411# Files saved with SO7/OOo1.x with nonstandard default column
2578  formatting cause big Excel files, because all rows from row 1 to row
2579  32000 are exported. Now, if the used area goes exactly to row 32000,
2580  use this row as default and ignore all rows >32000.
2581  #i59220# Tolerance of +-128 rows for inserted/removed rows. */
2582  if( (31871 <= nLastUsedScRow) && (nLastUsedScRow <= 32127) && (nFirstUnflaggedScRow < nLastUsedScRow) && (nFirstUngroupedScRow <= nLastUsedScRow) )
2583  nMaxScRow = nLastUsedScRow;
2584  maColInfoBfr.Initialize( nMaxScRow );
2585 
2586  // range for cell iterator
2587  SCCOL nLastIterScCol = nMaxScCol;
2588  SCROW nLastIterScRow = ulimit_cast< SCROW >( nLastUsedScRow, nMaxScRow );
2589  ScUsedAreaIterator aIt( rDoc, nScTab, 0, 0, nLastIterScCol, nLastIterScRow );
2590 
2591  // activate the correct segment and sub segment at the progress bar
2593 
2594  for( bool bIt = aIt.GetNext(); bIt; bIt = aIt.GetNext() )
2595  {
2596  SCCOL nScCol = aIt.GetStartCol();
2597  SCROW nScRow = aIt.GetRow();
2598  SCCOL nLastScCol = aIt.GetEndCol();
2599  ScAddress aScPos( nScCol, nScRow, nScTab );
2600 
2601  XclAddress aXclPos( static_cast< sal_uInt16 >( nScCol ), static_cast< sal_uInt32 >( nScRow ) );
2602  sal_uInt16 nLastXclCol = static_cast< sal_uInt16 >( nLastScCol );
2603 
2604  const ScRefCellValue& rScCell = aIt.GetCell();
2605  XclExpCellRef xCell;
2606 
2607  const ScPatternAttr* pPattern = aIt.GetPattern();
2608 
2609  // handle overlapped merged cells before creating the cell record
2610  sal_uInt32 nMergeBaseXFId = EXC_XFID_NOTFOUND;
2611  bool bIsMergedBase = false;
2612  if( pPattern )
2613  {
2614  const SfxItemSet& rItemSet = pPattern->GetItemSet();
2615  // base cell in a merged range
2616  const ScMergeAttr& rMergeItem = rItemSet.Get( ATTR_MERGE );
2617  bIsMergedBase = rMergeItem.IsMerged();
2618  /* overlapped cell in a merged range; in Excel all merged cells
2619  must contain same XF index, for correct border */
2620  const ScMergeFlagAttr& rMergeFlagItem = rItemSet.Get( ATTR_MERGE_FLAG );
2621  if( rMergeFlagItem.IsOverlapped() )
2622  nMergeBaseXFId = mxMergedcells->GetBaseXFId( aScPos );
2623  }
2624 
2625  OUString aAddNoteText; // additional text to be appended to a note
2626 
2627  switch (rScCell.meType)
2628  {
2629  case CELLTYPE_VALUE:
2630  {
2631  double fValue = rScCell.mfValue;
2632 
2633  if (pPattern)
2634  {
2635  OUString aUrl = pPattern->GetItemSet().Get(ATTR_HYPERLINK).GetValue();
2636  if (!aUrl.isEmpty())
2637  {
2639  new XclExpHyperlink(GetRoot(), SvxURLField(aUrl, aUrl), aScPos);
2640  mxHyperlinkList->AppendRecord(aLink);
2641  }
2642  }
2643 
2644  // try to create a Boolean cell
2645  if( pPattern && ((fValue == 0.0) || (fValue == 1.0)) )
2646  {
2647  sal_uInt32 nScNumFmt = pPattern->GetItemSet().Get( ATTR_VALUE_FORMAT ).GetValue();
2648  if( rFormatter.GetType( nScNumFmt ) == SvNumFormatType::LOGICAL )
2649  xCell = new XclExpBooleanCell(
2650  GetRoot(), aXclPos, pPattern, nMergeBaseXFId, fValue != 0.0 );
2651  }
2652 
2653  // try to create an RK value (compressed floating-point number)
2654  sal_Int32 nRkValue;
2655  if( !xCell && XclTools::GetRKFromDouble( nRkValue, fValue ) )
2656  xCell = new XclExpRkCell(
2657  GetRoot(), aXclPos, pPattern, nMergeBaseXFId, nRkValue );
2658 
2659  // else: simple floating-point number cell
2660  if( !xCell )
2661  xCell = new XclExpNumberCell(
2662  GetRoot(), aXclPos, pPattern, nMergeBaseXFId, fValue );
2663  }
2664  break;
2665 
2666  case CELLTYPE_STRING:
2667  {
2668  xCell = new XclExpLabelCell(
2669  GetRoot(), aXclPos, pPattern, nMergeBaseXFId, rScCell.mpString->getString());
2670  }
2671  break;
2672 
2673  case CELLTYPE_EDIT:
2674  {
2675  XclExpHyperlinkHelper aLinkHelper( GetRoot(), aScPos );
2676  xCell = new XclExpLabelCell(
2677  GetRoot(), aXclPos, pPattern, nMergeBaseXFId, rScCell.mpEditText, aLinkHelper);
2678 
2679  // add a single created HLINK record to the record list
2680  if( aLinkHelper.HasLinkRecord() )
2681  mxHyperlinkList->AppendRecord( aLinkHelper.GetLinkRecord() );
2682  // add list of multiple URLs to the additional cell note text
2683  if( aLinkHelper.HasMultipleUrls() )
2684  aAddNoteText = ScGlobal::addToken( aAddNoteText, aLinkHelper.GetUrlList(), '\n', 2 );
2685  }
2686  break;
2687 
2688  case CELLTYPE_FORMULA:
2689  {
2690  if (pPattern)
2691  {
2692  OUString aUrl = pPattern->GetItemSet().Get(ATTR_HYPERLINK).GetValue();
2693  if (!aUrl.isEmpty())
2694  {
2696  new XclExpHyperlink(GetRoot(), SvxURLField(aUrl, aUrl), aScPos);
2697  mxHyperlinkList->AppendRecord(aLink);
2698  }
2699  }
2700 
2701  xCell = new XclExpFormulaCell(
2702  GetRoot(), aXclPos, pPattern, nMergeBaseXFId,
2704  }
2705  break;
2706 
2707  default:
2708  OSL_FAIL( "XclExpCellTable::XclExpCellTable - unknown cell type" );
2709  [[fallthrough]];
2710  case CELLTYPE_NONE:
2711  {
2712  xCell = new XclExpBlankCell(
2713  GetRoot(), aXclPos, nLastXclCol, pPattern, nMergeBaseXFId );
2714  }
2715  break;
2716  }
2717 
2718  assert(xCell && "can only reach here with xCell set");
2719 
2720  // insert the cell into the current row
2721  maRowBfr.AppendCell( xCell, bIsMergedBase );
2722 
2723  if ( !aAddNoteText.isEmpty() )
2724  mxNoteList->AppendNewRecord( new XclExpNote( GetRoot(), aScPos, nullptr, aAddNoteText ) );
2725 
2726  // other sheet contents
2727  if( pPattern )
2728  {
2729  const SfxItemSet& rItemSet = pPattern->GetItemSet();
2730 
2731  // base cell in a merged range
2732  if( bIsMergedBase )
2733  {
2734  const ScMergeAttr& rMergeItem = rItemSet.Get( ATTR_MERGE );
2735  ScRange aScRange( aScPos );
2736  aScRange.aEnd.IncCol( rMergeItem.GetColMerge() - 1 );
2737  aScRange.aEnd.IncRow( rMergeItem.GetRowMerge() - 1 );
2738  sal_uInt32 nXFId = xCell->GetFirstXFId();
2739  // blank cells merged vertically may occur repeatedly
2740  OSL_ENSURE( (aScRange.aStart.Col() == aScRange.aEnd.Col()) || (nScCol == nLastScCol),
2741  "XclExpCellTable::XclExpCellTable - invalid repeated blank merged cell" );
2742  for( SCCOL nIndex = nScCol; nIndex <= nLastScCol; ++nIndex )
2743  {
2744  mxMergedcells->AppendRange( aScRange, nXFId );
2745  aScRange.aStart.IncCol();
2746  aScRange.aEnd.IncCol();
2747  }
2748  }
2749 
2750  // data validation
2751  if( ScfTools::CheckItem( rItemSet, ATTR_VALIDDATA, false ) )
2752  {
2753  sal_uLong nScHandle = rItemSet.Get( ATTR_VALIDDATA ).GetValue();
2754  ScRange aScRange( aScPos );
2755  aScRange.aEnd.SetCol( nLastScCol );
2756  mxDval->InsertCellRange( aScRange, nScHandle );
2757  }
2758  }
2759  }
2760 
2761  // create missing row settings for rows anyhow flagged or with outlines
2762  maRowBfr.CreateRows( ::std::max( nFirstUnflaggedScRow, nFirstUngroupedScRow ) );
2763 }
2764 
2766 {
2767  // Finalize multiple operations.
2769 
2770  /* Finalize column buffer. This calculates column default XF indexes from
2771  the XF identifiers and fills a vector with these XF indexes. */
2772  ScfUInt16Vec aColXFIndexes;
2773  maColInfoBfr.Finalize( aColXFIndexes, bXLS );
2774 
2775  // Usually many indexes towards the end will be EXC_XF_DEFAULTCELL, find
2776  // the index that starts all EXC_XF_DEFAULTCELL until the end.
2777  size_t nStartColAllDefault = findFirstAllSameUntilEnd( aColXFIndexes, EXC_XF_DEFAULTCELL );
2778 
2779  /* Finalize row buffer. This calculates all cell XF indexes from the XF
2780  identifiers. Then the XF index vector aColXFIndexes (filled above) is
2781  used to calculate the row default formats. With this, all unneeded blank
2782  cell records (equal to row default or column default) will be removed.
2783  The function returns the (most used) default row format in aDefRowData. */
2784  XclExpDefaultRowData aDefRowData;
2785  maRowBfr.Finalize( aDefRowData, aColXFIndexes, nStartColAllDefault );
2786 
2787  // Initialize the DEFROWHEIGHT record.
2788  mxDefrowheight->SetDefaultData( aDefRowData );
2789 }
2790 
2792 {
2793  XclExpRecordRef xRec;
2794  switch( nRecId )
2795  {
2796  case EXC_ID3_DIMENSIONS: xRec = new XclExpDelegatingRecord( &const_cast<XclExpRowBuffer*>(&maRowBfr)->GetDimensions() ); break;
2797  case EXC_ID2_DEFROWHEIGHT: xRec = mxDefrowheight; break;
2798  case EXC_ID_GUTS: xRec = mxGuts; break;
2799  case EXC_ID_NOTE: xRec = mxNoteList; break;
2800  case EXC_ID_MERGEDCELLS: xRec = mxMergedcells; break;
2801  case EXC_ID_HLINK: xRec = mxHyperlinkList; break;
2802  case EXC_ID_DVAL: xRec = mxDval; break;
2803  case EXC_ID_EXTLST: xRec = mxExtLst; break;
2804  default: OSL_FAIL( "XclExpCellTable::CreateRecord - unknown record id" );
2805  }
2806  return xRec;
2807 }
2808 
2810 {
2811  // DEFCOLWIDTH and COLINFOs
2812  maColInfoBfr.Save( rStrm );
2813  // ROWs and cell records
2814  maRowBfr.Save( rStrm );
2815 }
2816 
2818 {
2819  // DEFAULT row height
2820  XclExpDefaultRowData& rDefData = mxDefrowheight->GetDefaultData();
2821  sax_fastparser::FSHelperPtr& rWorksheet = rStrm.GetCurrentStream();
2822  rWorksheet->startElement( XML_sheetFormatPr,
2823  // OOXTODO: XML_baseColWidth
2824  XML_defaultColWidth, OString::number(maColInfoBfr.GetDefColWidth()),
2825  // OOXTODO: XML_customHeight
2826  // OOXTODO: XML_thickTop
2827  // OOXTODO: XML_thickBottom
2828  XML_defaultRowHeight, OString::number(static_cast<double> (rDefData.mnHeight) / 20.0),
2829  XML_zeroHeight, ToPsz( rDefData.IsHidden() ),
2830  XML_outlineLevelRow, OString::number(maRowBfr.GetHighestOutlineLevel()),
2831  XML_outlineLevelCol, OString::number(maColInfoBfr.GetHighestOutlineLevel()) );
2832  rWorksheet->endElement( XML_sheetFormatPr );
2833 
2834  maColInfoBfr.SaveXml( rStrm );
2835  maRowBfr.SaveXml( rStrm );
2836  mxExtLst->SaveXml( rStrm );
2837 }
2838 
2839 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
void SetValue(const Type &rValue)
Sets a new record value.
Definition: xerecord.hxx:210
XclExpStringRef mxText
Definition: xetable.hxx:423
SC_DLLPUBLIC const ScPatternAttr * GetMostUsedPattern(SCCOL nCol, SCROW nStartRow, SCROW nEndRow, SCTAB nTab) const
Definition: document.cxx:4814
sal_uInt16 GetFirstUsedXclCol() const
Returns the column index of the first used cell in this row.
Definition: xetable.cxx:2100
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:375
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:1321
static void GetFormulaTypeAndValue(ScFormulaCell &rCell, const char *&sType, OUString &rValue)
Definition: xestream.cxx:665
const sal_uInt16 EXC_ID2_DIMENSIONS
Definition: xltable.hxx:32
XclExpColinfoBuffer maColInfoBfr
Definition: xetable.hxx:1014
const sal_uInt16 EXC_STR_MAXLEN
Definition: xlstring.hxx:43
static OString ToOString(const Color &rColor)
Definition: xestream.cxx:709
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:740
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:497
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:1354
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:642
static bool CheckItem(const SfxItemSet &rItemSet, sal_uInt16 nWhichId, bool bDeep)
Returns true, if the passed item set contains the item.
Definition: ftools.cxx:200
const sal_uInt16 EXC_XF_DEFAULTCELL
Excel index to default style XF.
Definition: xlstyle.hxx:139
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:1912
static sal_Int32 getPreferredConcurrency()
bool IsEmpty() const
Returns true, if this row does not contain at least one valid cell.
Definition: xetable.hxx:843
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:274
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:1016
virtual void SaveXml(XclExpXmlStream &rStrm) override
Definition: xerecord.hxx:382
sal_uInt32 mnCurrentRow
Definition: xetable.hxx:902
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:951
const sal_uInt16 EXC_ID_NOTE
Definition: xlescher.hxx:38
size_type count(const Value &v) const
sal_uInt16 mnMulRecId
Definition: xetable.hxx:520
The outline buffer for row outlines.
Definition: xetable.hxx:620
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:348
const Type & GetValue() const
Returns the value of the record.
Definition: xerecord.hxx:208
static OUString ToOUString(const char *s)
Definition: xestream.cxx:785
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:1863
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
constexpr OUStringLiteral last
sal_uInt32 mnXclRow
List of cell records for this row.
Definition: xetable.hxx:896
bool ValidRange(const ScRange &rRange) const
Definition: document.hxx:901
Represents an RK or MULRK record that describes cells with a compressed double values.
Definition: xetable.hxx:551
virtual void doWork()=0
virtual void WriteBody(XclExpStream &rStrm) override
Writes the contents of the record.
Definition: xetable.cxx:1857
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:1751
bool IsOverlapped() const
Definition: attrib.hxx:101
sal_uInt16 mnRowWidth
Number of visible row outline levels.
Definition: xetable.hxx:644
const sal_uInt16 EXC_DEFROW_UNSYNCED
Definition: xltable.hxx:114
double GetDefColWidth() const
Definition: xetable.hxx:772
sal_uInt32 mnFirstFreeXclRow
First used row.
Definition: xetable.hxx:666
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:686
XclExpFormulaCompiler & GetFormulaCompiler() const
Returns the formula compiler to produce formula token arrays.
Definition: xeroot.cxx:87
void SetRecSize(std::size_t nRecSize)
Sets a new record size prediction.
Definition: xerecord.hxx:163
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
void Update(SCROW nScRow)
Updates the current state by processing the settings of the passed Calc row.
Definition: xetable.hxx:627
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:93
void SetDefWidth(sal_uInt16 nXclColWidth, bool bXLS)
Sets the passed column width (in 1/256 character width) as default width.
Definition: xetable.cxx:1596
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:1816
ScAddress aEnd
Definition: address.hxx:498
XclExpDimensions(const XclExpRoot &rRoot)
Definition: xetable.cxx:1504
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:706
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:2791
OpCode GetOpCode() const
bool mbEnabled
true = Do not add blank cells in Finalize().
Definition: xetable.hxx:904
std::size_t GetRecSize() const
Returns the current record size prediction.
Definition: xerecord.hxx:158
XclExpRowOutlineBuffer maOutlineBfr
Definition: xetable.hxx:950
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:781
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:1689
sal_uInt16 mnFlags
Row height in twips.
Definition: xetable.hxx:898
void ConvertXFIndexes()
Converts the XF identifier into the Excel XF index.
Definition: xetable.cxx:1661
ScDocument & GetDoc() const
Returns reference to the destination document (import) or source document (export).
Definition: xlroot.cxx:285
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:322
void RemoveInvalidatedRecords()
Definition: xerecord.hxx:396
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:2488
Represents a BLANK or MULBLANK record that describes empty but formatted cells.
Definition: xetable.hxx:526
virtual void WriteBody(XclExpStream &rStrm) override
Writes the contents of the DIMENSIONS record.
Definition: xetable.cxx:1552
const ScOutlineEntry * GetEntryByPos(size_t nLevel, SCCOLROW nPos) const
Definition: olinetab.cxx:464
sal_uInt16 GetColCount() const
Returns the number of columns represented by this record.
Definition: xetable.hxx:727
const sal_uInt16 EXC_FORMULA_DEFAULTFLAGS
Definition: xltable.hxx:67
std::size_t mnContSize
Record ID for multiple record variant.
Definition: xetable.hxx:521
XclExpRecordRef mxStringRec
Additional record for matrix/shared formulas.
Definition: xetable.hxx:452
sal_uInt8 mnOutlineLevel
Default row formatting.
Definition: xetable.hxx:900
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:600
void Finalize(XclExpDefaultRowData &rDefRowData, const ScfUInt16Vec &rColXFIndexes, size_t nStartColAllDefault)
Converts all XF identifiers into the Excel XF indexes and calculates default formats.
Definition: xetable.cxx:2255
bool IsMultilineResult()
Determines whether or not the result string contains more than one paragraph.
XclExpDefrowhRef mxDefrowheight
Buffer for TABLEOP records.
Definition: xetable.hxx:1019
void SetDimensions(sal_uInt16 nFirstUsedXclCol, sal_uInt32 nFirstUsedXclRow, sal_uInt16 nFirstFreeXclCol, sal_uInt32 nFirstFreeXclRow)
Sets the used area to the record.
Definition: xetable.cxx:1522
constexpr TypedWhichId< ScMergeAttr > ATTR_MERGE(144)
const XclExpRoot & mrRoot
Definition: xetable.hxx:664
SC_DLLPUBLIC sal_uInt16 GetRowHeight(SCROW nRow, SCTAB nTab, bool bHiddenAsZero=true) const
Definition: document.cxx:4211
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:744
const sal_uInt16 EXC_ID3_DIMENSIONS
Definition: xltable.hxx:33
sal_uInt16 GetRecId() const
Returns the current record ID.
Definition: xerecord.hxx:156
sal_uInt16 mnLastXclCol
Index to first column.
Definition: xetable.hxx:746
constexpr auto convertTwipToMm100(N n)
sal_uInt16 mnFirstUsedXclCol
First unused row after used area.
Definition: xetable.hxx:667
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:339
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:790
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:4622
sal_Int32 GetXmlCellIndex(sal_uInt32 nXFId) const
Definition: xestyle.cxx:2608
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:1376
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:2117
const sal_uInt16 EXC_ID_MERGEDCELLS
Definition: xlcontent.hxx:33
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
sal_uInt16 GetStartColAllDefaultCell() const
Return starting column at which all indexes until the end are EXC_XF_DEFAULTCELL .
Definition: xetable.cxx:1310
constexpr sal_uInt32 NUMBERFORMAT_ENTRY_NOT_FOUND
FormulaError GetErrCode()
std::shared_ptr< XclExpRow > RowRef
Definition: xetable.hxx:946
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:602
size_t GetDepth() const
Definition: olinetab.hxx:110
int nCount
void RemoveUnusedXFIndexes(const ScfUInt16Vec &rXFIndexes, size_t nStartAllNotFound)
Removes unused Excel XF index(es).
Definition: xetable.cxx:1280
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:2125
virtual const ScSingleRefData * GetSingleRef() const
sal_uInt16 mnWidth
True = Column width is different from default width.
Definition: xetable.hxx:741
XclTokenArrayRef CreateSpecialRefFormula(sal_uInt8 nTokenId, const XclAddress &rXclPos)
Creates a single token for a special cell reference.
Definition: xeformula.cxx:2687
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:780
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:1841
sal_uInt16 GetColWidth() const
Returns the Excel width of the column(s).
Definition: xetable.hxx:723
const sal_uInt16 EXC_ROW_ROWBLOCKSIZE
Definition: xltable.hxx:94
XclExtLstRef mxExtLst
Data validation with DVAL and DV records.
Definition: xetable.hxx:1025
ScFormulaCell * mpFormula
Definition: cellvalue.hxx:110
XclExpShrfmlaBuffer maShrfmlaBfr
Buffer for ARRAY records.
Definition: xetable.hxx:1017
SCTAB Tab() const
Definition: address.hxx:283
Represents a DEFROWHEIGHT record containing default format for unused rows.
Definition: xetable.hxx:802
void SetRow(SCROW nRowP)
Definition: address.hxx:287
void ConvertXFIndex(const XclExpRoot &rRoot)
Converts the XF identifier in mnXFId to an Excel XF index and stores it in mnXFIndex.
Definition: xestyle.cxx:2030
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:85
virtual void SaveXml(XclExpXmlStream &rStrm) override
Definition: xetable.cxx:2817
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:608
XclExpHyperlinkRef mxHyperlinkList
MERGEDCELLS record for merged cell ranges.
Definition: xetable.hxx:1023
ScAddress maColRelScPos
Definition: xlformula.hxx:472
ScAddress aPos
sax_fastparser::FSHelperPtr & GetCurrentStream()
Definition: xestream.cxx:912
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:291
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:579
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
static size_t findFirstAllSameUntilEnd(const ScfUInt16Vec &rIndexes, sal_uInt16 value, size_t searchStart=std::numeric_limits< size_t >::max())
Definition: xetable.cxx:1901
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:1852
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:2110
virtual void WriteXmlContents(XclExpXmlStream &rStrm, const XclAddress &rAddress, sal_uInt32 nXFId, sal_uInt16 nRelCol) override
Definition: xetable.cxx:1358
ocMatRef
const sal_uInt16 EXC_ID_DVAL
Font escapement type modified?
Definition: xlcontent.hxx:98
static ThreadPool & getSharedOptimalPool()
XclTokenArrayRef CreateErrorFormula(sal_uInt8 nErrCode)
Creates a single error token containing the passed error code.
Definition: xeformula.cxx:2682
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:1666
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:897
bool TryMerge(const XclExpColinfo &rColInfo)
Tries to merge this record with the passed record.
Definition: xetable.cxx:1675
virtual void WriteContents(XclExpStream &rStrm, sal_uInt16 nRelCol) override
Writes the remaining contents of the specified cell (without XF index).
Definition: xetable.cxx:1402
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:4495
sal_uInt16 mnFirstFreeXclCol
First used column.
Definition: xetable.hxx:668
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:198
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:81
void IncRowRecordCount()
Increases the number of existing ROW records by 1.
Definition: xehelper.cxx:107
virtual void WriteContents(XclExpStream &rStrm) override
Derived classes write the contents of the specified cell (without XF index).
Definition: xetable.cxx:797
sal_uInt16 GetFirstFreeXclCol() const
Returns the column index of the first unused cell following all used cells in this row...
Definition: xetable.cxx:2105
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:522
bool IsUnsynced() const
Returns true, if the rows have a manually set height by default.
Definition: xetable.hxx:798
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:316
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:604
XclExpGuts(const XclExpRoot &rRoot)
Definition: xetable.cxx:1469
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:743
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:1425
virtual void SaveXml(XclExpXmlStream &rStrm) override
Definition: xetable.cxx:1532
void RemoveRecord(size_t nPos)
Removes the record at the specified position from the list.
Definition: xerecord.hxx:369
virtual void WriteBody(XclExpStream &rStrm) override
Writes the body of the record (without record header).
Definition: xetable.cxx:1499
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:427
XclExpNumFmtBuffer & GetNumFmtBuffer() const
Returns the number format buffer.
Definition: xeroot.cxx:117
const sal_uInt16 EXC_ID_DEFCOLWIDTH
Definition: xltable.hxx:136
XclExpTableopRef CreateOrExtendTableop(const ScTokenArray &rScTokArr, const ScAddress &rScPos)
Tries to update an existing or to create a new TABLEOP record.
Definition: xetable.cxx:457
sal_uInt16 mnXFIndex
Flags for the ROW record.
Definition: xetable.hxx:899
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:2165
void Initialize(SCROW nLastScRow)
Initializes the buffer: finds settings and formatting of all columns.
Definition: xetable.cxx:1738
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:2219
void InsertRecord(RecType *pRec, size_t nPos)
Inserts a record at the specified position into the list.
Definition: xerecord.hxx:343
void IncRow(SCROW nDelta=1)
Definition: address.hxx:312
XclExpCellTable(const XclExpRoot &rRoot)
Definition: xetable.cxx:2521
SfxItemSet & GetItemSet()
Definition: patattr.hxx:155
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:125
XclExpNoteListRef mxNoteList
GUTS record for outline areas.
Definition: xetable.hxx:1021
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:1585
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:639
virtual XclTokenArrayRef CreateCellTokenArray(const XclExpRoot &rRoot) const override
Creates and returns the token array for a corresponding FORMULA cell record.
Definition: xetable.cxx:195
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:641
virtual void Save(XclExpStream &rStrm) override
Writes the record header and calls WriteBody().
Definition: xetable.cxx:1618
void Finalize(bool bXLS)
Converts all XF identifiers into the Excel XF indexes and calculates default formats.
Definition: xetable.cxx:2765
sal_uInt16 mnCol
Definition: xladdress.hxx:31
sal_uInt32 GetXclRow() const
Returns the excel row index of this ROW record.
Definition: xetable.hxx:839
virtual void SaveXml(XclExpXmlStream &rStrm) override
Definition: xetable.cxx:2428
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:336
sal_uInt32 mnXclRowRpt
Outline Level of row (for OOXML)
Definition: xetable.hxx:901
A 2D cell address struct with Excel column and row indexes.
Definition: xladdress.hxx:29
XclExpDefaultRowData()
Default height for unspecified rows.
Definition: xetable.cxx:1827
XclExpRow & GetOrCreateRow(sal_uInt32 nXclRow, bool bRowAlwaysEmpty)
Returns access to the specified ROW record.
Definition: xetable.cxx:2443
Contains all possible default row settings.
Definition: xetable.hxx:787
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:361
sal_uInt16 GetXFIndex() const
Returns the final Excel XF index of the column(s).
Definition: xetable.hxx:725
std::shared_ptr< XclTokenArray > XclTokenArrayRef
Definition: xlformula.hxx:416
void InvalidateRecord(size_t nPos)
Optimization for repeated removal.
Definition: xerecord.hxx:395
XclExpColinfoBuffer(const XclExpRoot &rRoot)
Definition: xetable.cxx:1730
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:279
sal_uInt8 GetHighestOutlineLevel() const
Definition: xetable.hxx:771
const XclExpRoot & GetRoot() const
Returns this root instance - for code readability in derived classes.
Definition: xeroot.hxx:118
Represents a FORMULA record that describes a cell with a formula.
Definition: xetable.hxx:431
XclExpSst & GetSst() const
Returns the shared string table.
Definition: xeroot.cxx:99
virtual bool TryMerge(const XclExpCellBase &rCell)
Derived classes try to merge the contents of the passed cell to own data.
Definition: xetable.cxx: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:603
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:2468
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:333
static sal_uInt32 GetDefCellXFId()
Returns the XF identifier representing the default cell XF.
Definition: xestyle.cxx:2483
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:2205
XclExpDefcolwidth maDefcolwidth
List of COLINFO records.
Definition: xetable.hxx:779
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:124
virtual void GetBlankXFIndexes(ScfUInt16Vec &rXFIndexes) const override
Inserts the Excel XF index(es) into the passed vector.
Definition: xetable.cxx:1344
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.hxx:622
virtual void RemoveUnusedBlankCells(const ScfUInt16Vec &rXFIndexes, size_t nStartAllNotFound) override
Tries to remove unused Excel XF index(es).
Definition: xetable.cxx:1349
void SetContSize(std::size_t nContSize)
Definition: xetable.hxx:340
XclExpDefcolwidth(const XclExpRoot &rRoot)
Definition: xetable.cxx:1579
virtual bool TryMerge(const XclExpCellBase &rCell) override
Tries to merge the contents of the passed cell to own data.
Definition: xetable.cxx:1338
const XclExpCellAlign & GetAlignmentData() const
Returns the alignment settings of this XF.
Definition: xestyle.hxx:446
Represents a GUTS record containing the level count of row and column outlines.
Definition: xetable.hxx:632
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:1410
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:829
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:665
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:1627
XclExpShrfmlaBuffer(const XclExpRoot &rRoot)
Definition: xetable.cxx:211
bool mbAlwaysEmpty
Definition: xetable.hxx:903
#define OSL_ENSURE_BIFF(c)
Definition: xltools.hxx:34
::std::vector< sal_uInt16 > ScfUInt16Vec
Definition: ftools.hxx:255
ScfInt32Vec maRkValues
Definition: xetable.hxx:567
virtual void Save(XclExpStream &rStrm) override
Writes all COLINFO records of this buffer.
Definition: xetable.cxx:1808
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:2213
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:1024
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:560
void Finalize(const ScfUInt16Vec &rColXFIndexes, ScfUInt16Vec &aXFIndexes, size_t nStartColAllDefault, bool bUpdateProgress)
Converts all XF identifiers into the Excel XF indexes.
Definition: xetable.cxx:1919
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:884
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:2176
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:815
std::size_t GetContSize() const
Definition: xetable.hxx:341
virtual void SaveXml(XclExpXmlStream &rStrm) override
Definition: xetable.cxx:1704
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:615
virtual void Save(XclExpStream &rStrm) override
Saves the entire cell table.
Definition: xetable.cxx:2809
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:2141
SC_DLLPUBLIC ScOutlineTable * GetOutlineTable(SCTAB nTab, bool bCreate=false)
Definition: documen3.cxx:739
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:2643
sal_uInt32 Insert(const ScPatternAttr *pPattern, sal_Int16 nScript)
Finds or creates a cell XF record for the passed item set.
Definition: xestyle.cxx:2457
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:142
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:895
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:245
constexpr TypedWhichId< SfxStringItem > ATTR_HYPERLINK(155)
size_t GetSize() const
Definition: xerecord.hxx:327
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:4479
Complex reference (a range) into the sheet.
Definition: refdata.hxx:122
XclExpXFId maXFId
Definition: xetable.hxx:739
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:113
virtual void WriteXmlContents(XclExpXmlStream &rStrm, const XclAddress &rAddress, sal_uInt32 nXFId, sal_uInt16 nRelCol) override
Definition: xetable.cxx:1387
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:643
bool IsHidden() const
Returns true, if rows are hidden by default.
Definition: xetable.hxx:796
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:952
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
virtual void RemoveUnusedBlankCells(const ScfUInt16Vec &rXFIndexes, size_t nStartAllNotFound)
Derived classes for blank cells remove unused Excel XF index(es).
Definition: xetable.cxx:563
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:1015
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:778
sal_uInt16 mnFlags
Definition: xetable.hxx:789
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
bool IsHidden() const
Returns true, if this row is hidden.
Definition: xetable.hxx:845
XclExpRecordRef mxGuts
DEFROWHEIGHT record for default row format.
Definition: xetable.hxx:1020
std::pair< const_iterator, bool > insert(Value &&x)
SC_DLLPUBLIC sal_uInt16 GetColWidth(SCCOL nCol, SCTAB nTab, bool bHiddenAsZero=true) const
Definition: document.cxx:4170
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:326
sal_uInt16 mnScWidth
Excel width of the column.
Definition: xetable.hxx:742
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:581
ScMatrixMode GetMatrixFlag() const
XclExpXFBuffer & GetXFBuffer() const
Returns the cell formatting attributes buffer.
Definition: xeroot.cxx:123
void SetRecId(sal_uInt16 nRecId)
Sets a new record ID.
Definition: xerecord.hxx:161
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:111
#define SC_OL_MAXDEPTH
Definition: olinetab.hxx:27
StackVar GetType() const
virtual void WriteContents(XclExpStream &rStrm) override
Derived classes write the contents of the specified cell (without XF index).
Definition: xetable.cxx:659
XclExpTableopBuffer maTableopBfr
Buffer for SHRFMLA records.
Definition: xetable.hxx:1018
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:745
sal_uInt8 GetHighestOutlineLevel() const
Definition: xetable.hxx:937
bool mbValid
Definition: queryiter.cxx:911
void SetXclRowRpt(sal_uInt32 nRpt)
Definition: xetable.hxx:885
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:2400
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:847
RowMap maRowMap
Definition: xetable.hxx:949
const sal_uInt16 EXC_ID_EXTLST
Definition: xlcontent.hxx:185
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:2462
sal_uInt32 mnFirstUsedXclRow
Definition: xetable.hxx:665
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:1366
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:142
sal_uInt16 nPos
XclExpMergedcellsRef mxMergedcells
List of NOTE records.
Definition: xetable.hxx:1022
sal_Int16 SCTAB
Definition: types.hxx:22
SC_DLLPUBLIC CRFlags GetRowFlags(SCROW nRow, SCTAB nTab) const
Definition: document.cxx:4386
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:2131
const sal_uInt16 EXC_ID3_LABEL
Definition: xltable.hxx:48
bool m_bDetectedRangeSegmentation false
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:2590
void AddRecSize(std::size_t nRecSize)
Adds a size value to the record size prediction.
Definition: xerecord.hxx:165
XclExpDvalRef mxDval
List of HLINK records.
Definition: xetable.hxx:1024
ScTokenArray * GetSharedCode()