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