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 <com/sun/star/table/XCellRange.hpp>
21 
22 #include "XMLExportIterator.hxx"
23 #include <dociter.hxx>
24 #include "xmlexprt.hxx"
25 #include "XMLExportSharedData.hxx"
26 #include "XMLStylesExportHelper.hxx"
27 #include <document.hxx>
28 #include <osl/diagnose.h>
29 
30 using namespace ::com::sun::star;
31 
ScMyIteratorBase()32 ScMyIteratorBase::ScMyIteratorBase()
33 {
34 }
35 
~ScMyIteratorBase()36 ScMyIteratorBase::~ScMyIteratorBase()
37 {
38 }
39 
UpdateAddress(ScAddress & rCellAddress)40 void ScMyIteratorBase::UpdateAddress( ScAddress& rCellAddress )
41 {
42     ScAddress aNewAddr( rCellAddress );
43     if( GetFirstAddress( aNewAddr ) )
44     {
45         if( ( aNewAddr.Tab() == rCellAddress.Tab() ) &&
46             ( ( aNewAddr.Row() < rCellAddress.Row() ) ||
47             ( ( aNewAddr.Row() == rCellAddress.Row() ) && ( aNewAddr.Col() < rCellAddress.Col() ) ) ) )
48             rCellAddress = aNewAddr;
49     }
50 }
51 
operator <(const ScMyShape & aShape) const52 inline bool ScMyShape::operator<(const ScMyShape& aShape) const
53 {
54     return aAddress.lessThanByRow( aShape.aAddress );
55 }
56 
ScMyShapesContainer()57 ScMyShapesContainer::ScMyShapesContainer()
58     : aShapeList()
59 {
60 }
61 
~ScMyShapesContainer()62 ScMyShapesContainer::~ScMyShapesContainer()
63 {
64 }
65 
AddNewShape(const ScMyShape & aShape)66 void ScMyShapesContainer::AddNewShape( const ScMyShape& aShape )
67 {
68     aShapeList.push_back(aShape);
69 }
70 
GetFirstAddress(ScAddress & rCellAddress)71 bool ScMyShapesContainer::GetFirstAddress( ScAddress& rCellAddress )
72 {
73     SCTAB nTable( rCellAddress.Tab() );
74     if( !aShapeList.empty() )
75     {
76         rCellAddress = aShapeList.begin()->aAddress;
77         return ( nTable == rCellAddress.Tab() );
78     }
79     return false;
80 }
81 
SetCellData(ScMyCell & rMyCell)82 void ScMyShapesContainer::SetCellData( ScMyCell& rMyCell )
83 {
84     rMyCell.aShapeList.clear();
85 
86     ScMyShapeList::iterator aItr(aShapeList.begin());
87     ScMyShapeList::iterator aEndItr(aShapeList.end());
88     while( (aItr != aEndItr) && (aItr->aAddress == rMyCell.maCellAddress) )
89     {
90         rMyCell.aShapeList.push_back(*aItr);
91         aItr = aShapeList.erase(aItr);
92     }
93     rMyCell.bHasShape = !rMyCell.aShapeList.empty();
94 }
95 
SkipTable(SCTAB nSkip)96 void ScMyShapesContainer::SkipTable(SCTAB nSkip)
97 {
98     ScMyShapeList::iterator aItr = std::find_if_not(aShapeList.begin(), aShapeList.end(),
99         [&nSkip](const ScMyShape& rShape) { return rShape.aAddress.Tab() == nSkip; });
100     aShapeList.erase(aShapeList.begin(), aItr);
101 }
102 
Sort()103 void ScMyShapesContainer::Sort()
104 {
105     aShapeList.sort();
106 }
107 
operator <(const ScMyNoteShape & aNote) const108 inline bool ScMyNoteShape::operator<(const ScMyNoteShape& aNote) const
109 {
110     return aPos.lessThanByRow( aNote.aPos );
111 }
112 
ScMyNoteShapesContainer()113 ScMyNoteShapesContainer::ScMyNoteShapesContainer()
114     : aNoteShapeList()
115 {
116 }
117 
~ScMyNoteShapesContainer()118 ScMyNoteShapesContainer::~ScMyNoteShapesContainer()
119 {
120 }
121 
AddNewNote(const ScMyNoteShape & aNote)122 void ScMyNoteShapesContainer::AddNewNote( const ScMyNoteShape& aNote )
123 {
124     aNoteShapeList.push_back(aNote);
125 }
126 
GetFirstAddress(ScAddress & rCellAddress)127 bool ScMyNoteShapesContainer::GetFirstAddress( ScAddress& rCellAddress )
128 {
129     SCTAB nTable = rCellAddress.Tab();
130     if( !aNoteShapeList.empty() )
131     {
132         rCellAddress = aNoteShapeList.begin()->aPos;
133         return ( nTable == rCellAddress.Tab() );
134     }
135     return false;
136 }
137 
SetCellData(ScMyCell & rMyCell)138 void ScMyNoteShapesContainer::SetCellData( ScMyCell& rMyCell )
139 {
140     ScMyNoteShapeList::iterator aItr = std::find_if_not(aNoteShapeList.begin(), aNoteShapeList.end(),
141         [&rMyCell](const ScMyNoteShape& rNoteShape) { return rNoteShape.aPos == rMyCell.maCellAddress; });
142     aNoteShapeList.erase(aNoteShapeList.begin(), aItr);
143 }
144 
SkipTable(SCTAB nSkip)145 void ScMyNoteShapesContainer::SkipTable(SCTAB nSkip)
146 {
147     ScMyNoteShapeList::iterator aItr = std::find_if_not(aNoteShapeList.begin(), aNoteShapeList.end(),
148         [&nSkip](const ScMyNoteShape& rNoteShape) { return rNoteShape.aPos.Tab() == nSkip; });
149     aNoteShapeList.erase(aNoteShapeList.begin(), aItr);
150 }
151 
Sort()152 void ScMyNoteShapesContainer::Sort()
153 {
154     aNoteShapeList.sort();
155 }
156 
operator <(const ScMyMergedRange & aRange) const157 inline bool ScMyMergedRange::operator<(const ScMyMergedRange& aRange) const
158 {
159     return aCellRange.aStart.lessThanByRow( aRange.aCellRange.aStart );
160 }
161 
ScMyMergedRangesContainer()162 ScMyMergedRangesContainer::ScMyMergedRangesContainer()
163     : aRangeList()
164 {
165 }
166 
~ScMyMergedRangesContainer()167 ScMyMergedRangesContainer::~ScMyMergedRangesContainer()
168 {
169 }
170 
AddRange(const ScRange & rMergedRange)171 void ScMyMergedRangesContainer::AddRange(const ScRange& rMergedRange)
172 {
173     SCROW nStartRow( rMergedRange.aStart.Row() );
174     SCROW nEndRow( rMergedRange.aEnd.Row() );
175 
176     ScMyMergedRange aRange;
177     aRange.bIsFirst = true;
178 
179     aRange.aCellRange = rMergedRange;
180 
181     aRange.aCellRange.aEnd.SetRow( nStartRow );
182     aRange.nRows = nEndRow - nStartRow + 1;
183     aRangeList.push_back( aRange );
184 
185     aRange.bIsFirst = false;
186     aRange.nRows = 0;
187     for( SCROW nRow = nStartRow + 1; nRow <= nEndRow; ++nRow )
188     {
189         aRange.aCellRange.aStart.SetRow( nRow );
190         aRange.aCellRange.aEnd.SetRow( nRow );
191         aRangeList.push_back(aRange);
192     }
193 }
194 
GetFirstAddress(ScAddress & rCellAddress)195 bool ScMyMergedRangesContainer::GetFirstAddress( ScAddress& rCellAddress )
196 {
197     SCTAB nTable( rCellAddress.Tab() );
198     if( !aRangeList.empty() )
199     {
200         rCellAddress = aRangeList.begin()->aCellRange.aStart;
201         return ( nTable == rCellAddress.Tab() );
202     }
203     return false;
204 }
205 
SetCellData(ScMyCell & rMyCell)206 void ScMyMergedRangesContainer::SetCellData( ScMyCell& rMyCell )
207 {
208     rMyCell.bIsMergedBase = rMyCell.bIsCovered = false;
209     ScMyMergedRangeList::iterator aItr(aRangeList.begin());
210     if( aItr != aRangeList.end() )
211     {
212         if( aItr->aCellRange.aStart == rMyCell.aCellAddress )
213         {
214             rMyCell.aMergeRange = aItr->aCellRange;
215             if (aItr->bIsFirst)
216                 rMyCell.aMergeRange.aEnd.SetRow( rMyCell.aMergeRange.aStart.Row() + aItr->nRows - 1 );
217             rMyCell.bIsMergedBase = aItr->bIsFirst;
218             rMyCell.bIsCovered = !aItr->bIsFirst;
219             if( aItr->aCellRange.aStart.Col() < aItr->aCellRange.aEnd.Col() )
220             {
221                 aItr->aCellRange.aStart.IncCol( 1 );
222                 aItr->bIsFirst = false;
223             }
224             else
225                 aRangeList.erase(aItr);
226         }
227     }
228 }
229 
SkipTable(SCTAB nSkip)230 void ScMyMergedRangesContainer::SkipTable(SCTAB nSkip)
231 {
232     ScMyMergedRangeList::iterator aItr = std::find_if_not(aRangeList.begin(), aRangeList.end(),
233         [&nSkip](const ScMyMergedRange& rRange) { return rRange.aCellRange.aStart.Tab() == nSkip; });
234     aRangeList.erase(aRangeList.begin(), aItr);
235 }
236 
Sort()237 void ScMyMergedRangesContainer::Sort()
238 {
239     aRangeList.sort();
240 }
241 
Compare(const ScMyAreaLink & rAreaLink) const242 bool ScMyAreaLink::Compare( const ScMyAreaLink& rAreaLink ) const
243 {
244     return  (GetRowCount() == rAreaLink.GetRowCount()) &&
245             (sFilter == rAreaLink.sFilter) &&
246             (sFilterOptions == rAreaLink.sFilterOptions) &&
247             (sURL == rAreaLink.sURL) &&
248             (sSourceStr == rAreaLink.sSourceStr);
249 }
250 
operator <(const ScMyAreaLink & rAreaLink) const251 inline bool ScMyAreaLink::operator<(const ScMyAreaLink& rAreaLink ) const
252 {
253     return aDestRange.aStart.lessThanByRow( rAreaLink.aDestRange.aStart );
254 }
255 
ScMyAreaLinksContainer()256 ScMyAreaLinksContainer::ScMyAreaLinksContainer() :
257     aAreaLinkList()
258 {
259 }
260 
~ScMyAreaLinksContainer()261 ScMyAreaLinksContainer::~ScMyAreaLinksContainer()
262 {
263 }
264 
GetFirstAddress(ScAddress & rCellAddress)265 bool ScMyAreaLinksContainer::GetFirstAddress( ScAddress& rCellAddress )
266 {
267     SCTAB nTable( rCellAddress.Tab() );
268     if( !aAreaLinkList.empty() )
269     {
270         rCellAddress = aAreaLinkList.begin()->aDestRange.aStart;
271         return ( nTable == rCellAddress.Tab() );
272     }
273     return false;
274 }
275 
SetCellData(ScMyCell & rMyCell)276 void ScMyAreaLinksContainer::SetCellData( ScMyCell& rMyCell )
277 {
278     rMyCell.bHasAreaLink = false;
279     ScMyAreaLinkList::iterator aItr(aAreaLinkList.begin());
280     if( aItr != aAreaLinkList.end() )
281     {
282         if( aItr->aDestRange.aStart == rMyCell.aCellAddress )
283         {
284             rMyCell.bHasAreaLink = true;
285             rMyCell.aAreaLink = *aItr;
286             aItr = aAreaLinkList.erase( aItr );
287             bool bFound = true;
288             while (aItr != aAreaLinkList.end() && bFound)
289             {
290                 if ( aItr->aDestRange.aStart == rMyCell.aCellAddress )
291                 {
292                     OSL_FAIL("more than one linked range on one cell");
293                     aItr = aAreaLinkList.erase( aItr );
294                 }
295                 else
296                     bFound = false;
297             }
298         }
299     }
300 }
301 
SkipTable(SCTAB nSkip)302 void ScMyAreaLinksContainer::SkipTable(SCTAB nSkip)
303 {
304     ScMyAreaLinkList::iterator aItr = std::find_if_not(aAreaLinkList.begin(), aAreaLinkList.end(),
305         [&nSkip](const ScMyAreaLink& rAreaLink) { return rAreaLink.aDestRange.aStart.Tab() == nSkip; });
306     aAreaLinkList.erase(aAreaLinkList.begin(), aItr);
307 }
308 
Sort()309 void ScMyAreaLinksContainer::Sort()
310 {
311     aAreaLinkList.sort();
312 }
313 
ScMyEmptyDatabaseRangesContainer()314 ScMyEmptyDatabaseRangesContainer::ScMyEmptyDatabaseRangesContainer()
315     : aDatabaseList()
316 {
317 }
318 
~ScMyEmptyDatabaseRangesContainer()319 ScMyEmptyDatabaseRangesContainer::~ScMyEmptyDatabaseRangesContainer()
320 {
321 }
322 
AddNewEmptyDatabaseRange(const table::CellRangeAddress & aCellRange)323 void ScMyEmptyDatabaseRangesContainer::AddNewEmptyDatabaseRange(const table::CellRangeAddress& aCellRange)
324 {
325     SCROW nStartRow(aCellRange.StartRow);
326     SCROW nEndRow(aCellRange.EndRow);
327     ScRange aRange( aCellRange.StartColumn, aCellRange.StartRow, aCellRange.Sheet,
328                       aCellRange.EndColumn, aCellRange.EndRow, aCellRange.Sheet );
329     for( SCROW nRow = nStartRow; nRow <= nEndRow; ++nRow )
330     {
331         aRange.aStart.SetRow( nRow );
332         aRange.aEnd.SetRow( nRow );
333         aDatabaseList.push_back( aRange );
334     }
335 }
336 
GetFirstAddress(ScAddress & rCellAddress)337 bool ScMyEmptyDatabaseRangesContainer::GetFirstAddress( ScAddress& rCellAddress )
338 {
339     SCTAB nTable( rCellAddress.Tab() );
340     if( !aDatabaseList.empty() )
341     {
342         rCellAddress = aDatabaseList.begin()->aStart;
343         return ( nTable == rCellAddress.Tab() );
344     }
345     return false;
346 }
347 
SetCellData(ScMyCell & rMyCell)348 void ScMyEmptyDatabaseRangesContainer::SetCellData( ScMyCell& rMyCell )
349 {
350     rMyCell.bHasEmptyDatabase = false;
351     ScMyEmptyDatabaseRangeList::iterator aItr(aDatabaseList.begin());
352     if( aItr != aDatabaseList.end() )
353     {
354         if( aItr->aStart == rMyCell.aCellAddress )
355         {
356             rMyCell.bHasEmptyDatabase = true;
357             if( aItr->aStart.Col() < aItr->aEnd.Col() )
358                 aItr->aStart.SetCol( aItr->aStart.Col() + 1 );
359             else
360                 aDatabaseList.erase(aItr);
361         }
362     }
363 }
364 
SkipTable(SCTAB nSkip)365 void ScMyEmptyDatabaseRangesContainer::SkipTable(SCTAB nSkip)
366 {
367     ScMyEmptyDatabaseRangeList::iterator aItr = std::find_if_not(aDatabaseList.begin(), aDatabaseList.end(),
368         [&nSkip](const ScRange& rDatabase) { return rDatabase.aStart.Tab() == nSkip; });
369     aDatabaseList.erase(aDatabaseList.begin(), aItr);
370 }
371 
Sort()372 void ScMyEmptyDatabaseRangesContainer::Sort()
373 {
374     aDatabaseList.sort();
375 }
376 
operator <(const ScMyDetectiveObj & rDetObj) const377 inline bool ScMyDetectiveObj::operator<( const ScMyDetectiveObj& rDetObj) const
378 {
379     return aPosition.lessThanByRow( rDetObj.aPosition );
380 }
381 
ScMyDetectiveObjContainer()382 ScMyDetectiveObjContainer::ScMyDetectiveObjContainer() :
383     aDetectiveObjList()
384 {
385 }
386 
~ScMyDetectiveObjContainer()387 ScMyDetectiveObjContainer::~ScMyDetectiveObjContainer()
388 {
389 }
390 
AddObject(ScDetectiveObjType eObjType,const SCTAB nSheet,const ScAddress & rPosition,const ScRange & rSourceRange,bool bHasError)391 void ScMyDetectiveObjContainer::AddObject( ScDetectiveObjType eObjType, const SCTAB nSheet,
392                                             const ScAddress& rPosition, const ScRange& rSourceRange,
393                                             bool bHasError )
394 {
395     if( (eObjType == SC_DETOBJ_ARROW) ||
396         (eObjType == SC_DETOBJ_FROMOTHERTAB) ||
397         (eObjType == SC_DETOBJ_TOOTHERTAB) ||
398         (eObjType == SC_DETOBJ_CIRCLE) )
399     {
400         ScMyDetectiveObj aDetObj;
401         aDetObj.eObjType = eObjType;
402         if( eObjType == SC_DETOBJ_TOOTHERTAB )
403             aDetObj.aPosition = rSourceRange.aStart;
404         else
405             aDetObj.aPosition = rPosition;
406         aDetObj.aSourceRange = rSourceRange;
407 
408         // #111064#; take the sheet where the object is found and not the sheet given in the ranges, because they are not always true
409         if (eObjType != SC_DETOBJ_FROMOTHERTAB)
410         {
411             // if the ObjType == SC_DETOBJ_FROMOTHERTAB then the SourceRange is not used and so it has not to be tested and changed
412             OSL_ENSURE(aDetObj.aPosition.Tab() == aDetObj.aSourceRange.aStart.Tab(), "It seems to be possible to have different sheets");
413             aDetObj.aSourceRange.aStart.SetTab( nSheet );
414             aDetObj.aSourceRange.aEnd.SetTab( nSheet );
415         }
416         aDetObj.aPosition.SetTab( nSheet );
417 
418         aDetObj.bHasError = bHasError;
419         aDetectiveObjList.push_back( aDetObj );
420     }
421 }
422 
GetFirstAddress(ScAddress & rCellAddress)423 bool ScMyDetectiveObjContainer::GetFirstAddress( ScAddress& rCellAddress )
424 {
425     SCTAB nTable( rCellAddress.Tab() );
426     if( !aDetectiveObjList.empty() )
427     {
428         rCellAddress = aDetectiveObjList.begin()->aPosition;
429         return ( nTable == rCellAddress.Tab() );
430     }
431     return false;
432 }
433 
SetCellData(ScMyCell & rMyCell)434 void ScMyDetectiveObjContainer::SetCellData( ScMyCell& rMyCell )
435 {
436     rMyCell.aDetectiveObjVec.clear();
437     ScMyDetectiveObjList::iterator aItr(aDetectiveObjList.begin());
438     ScMyDetectiveObjList::iterator aEndItr(aDetectiveObjList.end());
439     while( (aItr != aEndItr) && (aItr->aPosition == rMyCell.aCellAddress) )
440     {
441         rMyCell.aDetectiveObjVec.push_back( *aItr );
442         aItr = aDetectiveObjList.erase( aItr );
443     }
444     rMyCell.bHasDetectiveObj = (!rMyCell.aDetectiveObjVec.empty());
445 }
446 
SkipTable(SCTAB nSkip)447 void ScMyDetectiveObjContainer::SkipTable(SCTAB nSkip)
448 {
449     ScMyDetectiveObjList::iterator aItr = std::find_if_not(aDetectiveObjList.begin(), aDetectiveObjList.end(),
450         [&nSkip](const ScMyDetectiveObj& rDetectiveObj) { return rDetectiveObj.aPosition.Tab() == nSkip; });
451     aDetectiveObjList.erase(aDetectiveObjList.begin(), aItr);
452 }
453 
Sort()454 void ScMyDetectiveObjContainer::Sort()
455 {
456     aDetectiveObjList.sort();
457 }
458 
operator <(const ScMyDetectiveOp & rDetOp) const459 inline bool ScMyDetectiveOp::operator<( const ScMyDetectiveOp& rDetOp) const
460 {
461     return aPosition.lessThanByRow( rDetOp.aPosition );
462 }
463 
ScMyDetectiveOpContainer()464 ScMyDetectiveOpContainer::ScMyDetectiveOpContainer() :
465     aDetectiveOpList()
466 {
467 }
468 
~ScMyDetectiveOpContainer()469 ScMyDetectiveOpContainer::~ScMyDetectiveOpContainer()
470 {
471 }
472 
AddOperation(ScDetOpType eOpType,const ScAddress & rPosition,sal_uInt32 nIndex)473 void ScMyDetectiveOpContainer::AddOperation( ScDetOpType eOpType, const ScAddress& rPosition, sal_uInt32 nIndex )
474 {
475     ScMyDetectiveOp aDetOp;
476     aDetOp.eOpType = eOpType;
477     aDetOp.aPosition = rPosition;
478     aDetOp.nIndex = nIndex;
479     aDetectiveOpList.push_back( aDetOp );
480 }
481 
GetFirstAddress(ScAddress & rCellAddress)482 bool ScMyDetectiveOpContainer::GetFirstAddress( ScAddress& rCellAddress )
483 {
484     SCTAB nTable( rCellAddress.Tab() );
485     if( !aDetectiveOpList.empty() )
486     {
487         rCellAddress = aDetectiveOpList.begin()->aPosition;
488         return ( nTable == rCellAddress.Tab() );
489     }
490     return false;
491 }
492 
SetCellData(ScMyCell & rMyCell)493 void ScMyDetectiveOpContainer::SetCellData( ScMyCell& rMyCell )
494 {
495     rMyCell.aDetectiveOpVec.clear();
496     ScMyDetectiveOpList::iterator aItr(aDetectiveOpList.begin());
497     ScMyDetectiveOpList::iterator aEndItr(aDetectiveOpList.end());
498     while( (aItr != aEndItr) && (aItr->aPosition == rMyCell.aCellAddress) )
499     {
500         rMyCell.aDetectiveOpVec.push_back( *aItr );
501         aItr = aDetectiveOpList.erase( aItr );
502     }
503     rMyCell.bHasDetectiveOp = (!rMyCell.aDetectiveOpVec.empty());
504 }
505 
SkipTable(SCTAB nSkip)506 void ScMyDetectiveOpContainer::SkipTable(SCTAB nSkip)
507 {
508     ScMyDetectiveOpList::iterator aItr = std::find_if_not(aDetectiveOpList.begin(), aDetectiveOpList.end(),
509         [&nSkip](const ScMyDetectiveOp& rDetectiveOp) { return rDetectiveOp.aPosition.Tab() == nSkip; });
510     aDetectiveOpList.erase(aDetectiveOpList.begin(), aItr);
511 }
512 
Sort()513 void ScMyDetectiveOpContainer::Sort()
514 {
515     aDetectiveOpList.sort();
516 }
517 
ScMyCell()518 ScMyCell::ScMyCell() :
519     aShapeList(),
520     aDetectiveObjVec(),
521     pNote(nullptr),
522     nValidationIndex(-1),
523     nStyleIndex(-1),
524     nNumberFormat(-1),
525     nType(table::CellContentType_EMPTY),
526     bIsAutoStyle( false ),
527     bHasShape( false ),
528     bIsMergedBase( false ),
529     bIsCovered( false ),
530     bHasAreaLink( false ),
531     bHasEmptyDatabase( false ),
532     bHasDetectiveObj( false ),
533     bHasDetectiveOp( false ),
534     bIsMatrixBase( false ),
535     bIsMatrixCovered( false ),
536     bHasAnnotation( false )
537 {
538 }
539 
ScMyNotEmptyCellsIterator(ScXMLExport & rTempXMLExport)540 ScMyNotEmptyCellsIterator::ScMyNotEmptyCellsIterator(ScXMLExport& rTempXMLExport)
541     : pShapes(nullptr),
542     pNoteShapes(nullptr),
543     pEmptyDatabaseRanges(nullptr),
544     pMergedRanges(nullptr),
545     pAreaLinks(nullptr),
546     pDetectiveObj(nullptr),
547     pDetectiveOp(nullptr),
548     rExport(rTempXMLExport),
549     nCellCol(0),
550     nCellRow(0),
551     nCurrentTable(SCTAB_MAX)
552 {
553 }
554 
~ScMyNotEmptyCellsIterator()555 ScMyNotEmptyCellsIterator::~ScMyNotEmptyCellsIterator()
556 {
557     Clear();
558 }
559 
Clear()560 void ScMyNotEmptyCellsIterator::Clear()
561 {
562     mpCellItr.reset();
563     pShapes = nullptr;
564     pNoteShapes = nullptr;
565     pMergedRanges = nullptr;
566     pAreaLinks = nullptr;
567     pEmptyDatabaseRanges = nullptr;
568     pDetectiveObj = nullptr;
569     pDetectiveOp = nullptr;
570     nCurrentTable = SCTAB_MAX;
571 }
572 
UpdateAddress(ScAddress & rAddress)573 void ScMyNotEmptyCellsIterator::UpdateAddress( ScAddress& rAddress )
574 {
575     if (mpCellItr->GetPos(nCellCol, nCellRow))
576     {
577         rAddress.SetCol( nCellCol );
578         rAddress.SetRow( nCellRow );
579     }
580 }
581 
SetCellData(ScMyCell & rMyCell,const ScAddress & rAddress)582 void ScMyNotEmptyCellsIterator::SetCellData( ScMyCell& rMyCell, const ScAddress& rAddress )
583 {
584     rMyCell.maBaseCell.clear();
585     rMyCell.aCellAddress = rAddress;
586     rMyCell.maCellAddress = rMyCell.aCellAddress;
587 
588     if( ( nCellCol == rAddress.Col() ) && ( nCellRow == rAddress.Row() ) )
589     {
590         const ScRefCellValue* pCell = mpCellItr->GetNext(nCellCol, nCellRow);
591         if (pCell)
592             rMyCell.maBaseCell = *pCell;
593     }
594 
595     rMyCell.bIsMatrixCovered = false;
596     rMyCell.bIsMatrixBase = false;
597 
598     switch (rMyCell.maBaseCell.meType)
599     {
600         case CELLTYPE_VALUE:
601             rMyCell.nType = table::CellContentType_VALUE;
602             break;
603         case CELLTYPE_STRING:
604         case CELLTYPE_EDIT:
605             rMyCell.nType = table::CellContentType_TEXT;
606             break;
607         case CELLTYPE_FORMULA:
608             rMyCell.nType = table::CellContentType_FORMULA;
609             break;
610         default:
611             rMyCell.nType = table::CellContentType_EMPTY;
612     }
613 
614     if (rMyCell.maBaseCell.meType == CELLTYPE_FORMULA)
615     {
616         bool bIsMatrixBase = false;
617         if (rExport.IsMatrix(rMyCell.maCellAddress, rMyCell.aMatrixRange, bIsMatrixBase))
618         {
619             rMyCell.bIsMatrixBase = bIsMatrixBase;
620             rMyCell.bIsMatrixCovered = !bIsMatrixBase;
621         }
622     }
623 }
624 
HasAnnotation(ScMyCell & aCell)625 void ScMyNotEmptyCellsIterator::HasAnnotation(ScMyCell& aCell)
626 {
627     aCell.bHasAnnotation = false;
628     ScPostIt* pNote = rExport.GetDocument()->GetNote(aCell.maCellAddress);
629 
630     if(pNote)
631     {
632         aCell.bHasAnnotation = true;
633         aCell.pNote = pNote;
634     }
635 }
636 
SetCurrentTable(const SCTAB nTable,const uno::Reference<sheet::XSpreadsheet> & rxTable)637 void ScMyNotEmptyCellsIterator::SetCurrentTable(const SCTAB nTable,
638     const uno::Reference<sheet::XSpreadsheet>& rxTable)
639 {
640     aLastAddress.SetRow( 0 );
641     aLastAddress.SetCol( 0 );
642     aLastAddress.SetTab( nTable );
643     if (nCurrentTable != nTable)
644     {
645         nCurrentTable = nTable;
646 
647         mpCellItr.reset(
648             new ScHorizontalCellIterator(
649                 rExport.GetDocument(), nCurrentTable, 0, 0,
650                 static_cast<SCCOL>(rExport.GetSharedData()->GetLastColumn(nCurrentTable)),
651                 static_cast<SCROW>(rExport.GetSharedData()->GetLastRow(nCurrentTable))));
652 
653         xTable.set(rxTable);
654         xCellRange.set(xTable, uno::UNO_QUERY);
655     }
656 }
657 
SkipTable(SCTAB nSkip)658 void ScMyNotEmptyCellsIterator::SkipTable(SCTAB nSkip)
659 {
660     // Skip entries for a sheet that is copied instead of saving normally.
661     // Cells are handled separately in SetCurrentTable.
662 
663     if( pShapes )
664         pShapes->SkipTable(nSkip);
665     if( pNoteShapes )
666         pNoteShapes->SkipTable(nSkip);
667     if( pEmptyDatabaseRanges )
668         pEmptyDatabaseRanges->SkipTable(nSkip);
669     if( pMergedRanges )
670         pMergedRanges->SkipTable(nSkip);
671     if( pAreaLinks )
672         pAreaLinks->SkipTable(nSkip);
673     if( pDetectiveObj )
674         pDetectiveObj->SkipTable(nSkip);
675     if( pDetectiveOp )
676         pDetectiveOp->SkipTable(nSkip);
677 }
678 
GetNext(ScMyCell & aCell,ScFormatRangeStyles * pCellStyles)679 bool ScMyNotEmptyCellsIterator::GetNext(ScMyCell& aCell, ScFormatRangeStyles* pCellStyles)
680 {
681     ScDocument* pDoc = rExport.GetDocument();
682     ScAddress  aAddress( pDoc->MaxCol() + 1, pDoc->MaxRow() + 1, nCurrentTable );
683 
684     UpdateAddress( aAddress );
685 
686     if( pShapes )
687         pShapes->UpdateAddress( aAddress );
688     if( pNoteShapes )
689         pNoteShapes->UpdateAddress( aAddress );
690     if( pEmptyDatabaseRanges )
691         pEmptyDatabaseRanges->UpdateAddress( aAddress );
692     if( pMergedRanges )
693         pMergedRanges->UpdateAddress( aAddress );
694     if( pAreaLinks )
695         pAreaLinks->UpdateAddress( aAddress );
696     if( pDetectiveObj )
697         pDetectiveObj->UpdateAddress( aAddress );
698     if( pDetectiveOp )
699         pDetectiveOp->UpdateAddress( aAddress );
700 
701     bool bFoundCell( ( aAddress.Col() <= pDoc->MaxCol() ) && ( aAddress.Row() <= pDoc->MaxRow() + 1 ) );
702     if( bFoundCell )
703     {
704         SetCellData( aCell, aAddress );
705         if( pShapes )
706             pShapes->SetCellData( aCell );
707         if( pNoteShapes )
708             pNoteShapes->SetCellData( aCell );
709         if( pEmptyDatabaseRanges )
710             pEmptyDatabaseRanges->SetCellData( aCell );
711         if( pMergedRanges )
712             pMergedRanges->SetCellData( aCell );
713         if( pAreaLinks )
714             pAreaLinks->SetCellData( aCell );
715         if( pDetectiveObj )
716             pDetectiveObj->SetCellData( aCell );
717         if( pDetectiveOp )
718             pDetectiveOp->SetCellData( aCell );
719 
720         HasAnnotation( aCell );
721         bool bIsAutoStyle;
722         // Ranges before the previous cell are not needed by ExportFormatRanges anymore and can be removed
723         SCROW nRemoveBeforeRow = aLastAddress.Row();
724         aCell.nStyleIndex = pCellStyles->GetStyleNameIndex(aCell.maCellAddress.Tab(),
725             aCell.maCellAddress.Col(), aCell.maCellAddress.Row(),
726             bIsAutoStyle, aCell.nValidationIndex, aCell.nNumberFormat, nRemoveBeforeRow);
727         aLastAddress = aCell.aCellAddress;
728         aCell.bIsAutoStyle = bIsAutoStyle;
729 
730         //#102799#; if the cell is in a DatabaseRange which should saved empty, the cell should have the type empty
731         if (aCell.bHasEmptyDatabase)
732             aCell.nType = table::CellContentType_EMPTY;
733     }
734     return bFoundCell;
735 }
736 
737 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
738