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