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