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