1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: dociter.cxx,v $
10 * $Revision: 1.22.88.2 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sc.hxx"
34 // INCLUDE ---------------------------------------------------------------
36 #include <svtools/zforlist.hxx>
38 #include "scitems.hxx"
40 #include "dociter.hxx"
41 #include "document.hxx"
45 #include "attarray.hxx"
46 #include "patattr.hxx"
47 #include "docoptio.hxx"
48 #include "cellform.hxx"
51 // STATIC DATA -----------------------------------------------------------
53 ScDocumentIterator::ScDocumentIterator( ScDocument
* pDocument
,
54 SCTAB nStartTable
, SCTAB nEndTable
) :
56 nStartTab( nStartTable
),
59 PutInOrder( nStartTab
, nEndTab
);
60 if (!ValidTab(nStartTab
)) nStartTab
= MAXTAB
;
61 if (!ValidTab(nEndTab
)) nEndTab
= MAXTAB
;
63 pDefPattern
= pDoc
->GetDefPattern();
73 ScDocumentIterator::~ScDocumentIterator()
77 BOOL
ScDocumentIterator::GetThisCol()
80 while ( (pTab
= pDoc
->pTab
[nTab
]) == NULL
)
82 if ( nTab
== nEndTab
)
90 ScColumn
* pCol
= &pTab
->aCol
[nCol
];
91 ScAttrArray
* pAtt
= pCol
->pAttrArray
;
101 nAttrEnd
= pAtt
->pData
[nAttrPos
].nRow
;
105 while (nAttrEnd
< nRow
);
109 nColRow
= (nColPos
< pCol
->nCount
) ? pCol
->pItems
[nColPos
].nRow
: MAXROW
+1;
113 while (nColRow
< nRow
);
118 pCell
= pCol
->pItems
[nColPos
].pCell
;
119 pPattern
= pAtt
->pData
[nAttrPos
].pPattern
;
121 else if ( pAtt
->pData
[nAttrPos
].pPattern
!= pDefPattern
)
125 pPattern
= pAtt
->pData
[nAttrPos
].pPattern
;
129 nRow
= Min( (SCROW
)nColRow
, (SCROW
)(nAttrEnd
+1) );
132 while (!bFound
&& nRow
<= MAXROW
);
137 BOOL
ScDocumentIterator::GetThis()
140 BOOL bSuccess
= FALSE
;
142 while ( !bSuccess
&& !bEnd
)
147 bSuccess
= GetThisCol();
168 BOOL
ScDocumentIterator::GetFirst()
180 BOOL
ScDocumentIterator::GetNext()
187 //------------------------------------------------------------------------
189 ScBaseCell
* ScDocumentIterator::GetCell()
194 const ScPatternAttr
* ScDocumentIterator::GetPattern()
199 void ScDocumentIterator::GetPos( SCCOL
& rCol
, SCROW
& rRow
, SCTAB
& rTab
)
207 //------------------------------------------------------------------------
208 //------------------------------------------------------------------------
209 void lcl_IterGetNumberFormat( ULONG
& nFormat
, const ScAttrArray
*& rpArr
,
210 SCROW
& nAttrEndRow
, const ScAttrArray
* pNewArr
, SCROW nRow
,
213 if ( rpArr
!= pNewArr
|| nAttrEndRow
< nRow
)
216 pNewArr
->Search( nRow
, nPos
); // nPos 0 gueltig wenn nicht gefunden
217 const ScPatternAttr
* pPattern
= pNewArr
->pData
[nPos
].pPattern
;
218 nFormat
= pPattern
->GetNumberFormat( pDoc
->GetFormatTable() );
220 nAttrEndRow
= pNewArr
->pData
[nPos
].nRow
;
224 //UNUSED2008-05 ScValueIterator::ScValueIterator( ScDocument* pDocument,
225 //UNUSED2008-05 SCCOL nSCol, SCROW nSRow, SCTAB nSTab,
226 //UNUSED2008-05 SCCOL nECol, SCROW nERow, SCTAB nETab,
227 //UNUSED2008-05 BOOL bSTotal, BOOL bTextZero ) :
228 //UNUSED2008-05 pDoc( pDocument ),
229 //UNUSED2008-05 nNumFmtIndex(0),
230 //UNUSED2008-05 nStartCol( nSCol),
231 //UNUSED2008-05 nStartRow( nSRow),
232 //UNUSED2008-05 nStartTab( nSTab ),
233 //UNUSED2008-05 nEndCol( nECol ),
234 //UNUSED2008-05 nEndRow( nERow),
235 //UNUSED2008-05 nEndTab( nETab ),
236 //UNUSED2008-05 nNumFmtType( NUMBERFORMAT_UNDEFINED ),
237 //UNUSED2008-05 bNumValid( FALSE ),
238 //UNUSED2008-05 bSubTotal(bSTotal),
239 //UNUSED2008-05 bNextValid( FALSE ),
240 //UNUSED2008-05 bCalcAsShown( pDocument->GetDocOptions().IsCalcAsShown() ),
241 //UNUSED2008-05 bTextAsZero( bTextZero )
243 //UNUSED2008-05 PutInOrder( nStartCol, nEndCol);
244 //UNUSED2008-05 PutInOrder( nStartRow, nEndRow);
245 //UNUSED2008-05 PutInOrder( nStartTab, nEndTab );
247 //UNUSED2008-05 if (!ValidCol(nStartCol)) nStartCol = MAXCOL;
248 //UNUSED2008-05 if (!ValidCol(nEndCol)) nEndCol = MAXCOL;
249 //UNUSED2008-05 if (!ValidRow(nStartRow)) nStartRow = MAXROW;
250 //UNUSED2008-05 if (!ValidRow(nEndRow)) nEndRow = MAXROW;
251 //UNUSED2008-05 if (!ValidTab(nStartTab)) nStartTab = MAXTAB;
252 //UNUSED2008-05 if (!ValidTab(nEndTab)) nEndTab = MAXTAB;
254 //UNUSED2008-05 nCol = nStartCol;
255 //UNUSED2008-05 nRow = nStartRow;
256 //UNUSED2008-05 nTab = nStartTab;
258 //UNUSED2008-05 nColRow = 0; // wird bei GetFirst initialisiert
260 //UNUSED2008-05 nNumFormat = 0; // werden bei GetNumberFormat initialisiert
261 //UNUSED2008-05 pAttrArray = 0;
262 //UNUSED2008-05 nAttrEndRow = 0;
265 ScValueIterator::ScValueIterator( ScDocument
* pDocument
, const ScRange
& rRange
,
266 BOOL bSTotal
, BOOL bTextZero
) :
269 nStartCol( rRange
.aStart
.Col() ),
270 nStartRow( rRange
.aStart
.Row() ),
271 nStartTab( rRange
.aStart
.Tab() ),
272 nEndCol( rRange
.aEnd
.Col() ),
273 nEndRow( rRange
.aEnd
.Row() ),
274 nEndTab( rRange
.aEnd
.Tab() ),
275 nNumFmtType( NUMBERFORMAT_UNDEFINED
),
279 bCalcAsShown( pDocument
->GetDocOptions().IsCalcAsShown() ),
280 bTextAsZero( bTextZero
)
282 PutInOrder( nStartCol
, nEndCol
);
283 PutInOrder( nStartRow
, nEndRow
);
284 PutInOrder( nStartTab
, nEndTab
);
286 if (!ValidCol(nStartCol
)) nStartCol
= MAXCOL
;
287 if (!ValidCol(nEndCol
)) nEndCol
= MAXCOL
;
288 if (!ValidRow(nStartRow
)) nStartRow
= MAXROW
;
289 if (!ValidRow(nEndRow
)) nEndRow
= MAXROW
;
290 if (!ValidTab(nStartTab
)) nStartTab
= MAXTAB
;
291 if (!ValidTab(nEndTab
)) nEndTab
= MAXTAB
;
297 nColRow
= 0; // wird bei GetFirst initialisiert
299 nNumFormat
= 0; // werden bei GetNumberFormat initialisiert
304 BOOL
ScValueIterator::GetThis(double& rValue
, USHORT
& rErr
)
306 ScColumn
* pCol
= &(pDoc
->pTab
[nTab
])->aCol
[nCol
];
309 if ( nRow
> nEndRow
)
315 if ( nCol
> nEndCol
)
319 if ( nTab
> nEndTab
)
321 // rValue = 0.0; //! do not change caller's value!
323 return FALSE
; // Ende und Aus
326 pCol
= &(pDoc
->pTab
[nTab
])->aCol
[nCol
];
327 } while ( pCol
->nCount
== 0 );
328 pCol
->Search( nRow
, nColRow
);
331 while (( nColRow
< pCol
->nCount
) && ( pCol
->pItems
[nColRow
].nRow
< nRow
))
334 if ( nColRow
< pCol
->nCount
&& pCol
->pItems
[nColRow
].nRow
<= nEndRow
)
336 nRow
= pCol
->pItems
[nColRow
].nRow
+ 1;
337 if ( !bSubTotal
|| !pDoc
->pTab
[nTab
]->IsFiltered( nRow
-1 ) )
339 ScBaseCell
* pCell
= pCol
->pItems
[nColRow
].pCell
;
341 switch (pCell
->GetCellType())
346 rValue
= ((ScValueCell
*)pCell
)->GetValue();
351 lcl_IterGetNumberFormat( nNumFormat
, pAttrArray
,
352 nAttrEndRow
, pCol
->pAttrArray
, nRow
, pDoc
);
353 rValue
= pDoc
->RoundValueAsShown( rValue
, nNumFormat
);
356 // wenn in der selben Spalte gleich noch eine Value-Cell folgt, die
357 // auch noch im Block liegt, den Wert jetzt schon holen
359 if ( nColRow
< pCol
->nCount
&&
360 pCol
->pItems
[nColRow
].nRow
<= nEndRow
&&
361 pCol
->pItems
[nColRow
].pCell
->GetCellType() == CELLTYPE_VALUE
&&
364 fNextValue
= ((ScValueCell
*)pCol
->pItems
[nColRow
].pCell
)->GetValue();
365 nNextRow
= pCol
->pItems
[nColRow
].nRow
;
369 lcl_IterGetNumberFormat( nNumFormat
, pAttrArray
,
370 nAttrEndRow
, pCol
->pAttrArray
, nNextRow
, pDoc
);
371 fNextValue
= pDoc
->RoundValueAsShown( fNextValue
, nNumFormat
);
375 return TRUE
; // gefunden
378 case CELLTYPE_FORMULA
:
380 if (!bSubTotal
|| !((ScFormulaCell
*)pCell
)->IsSubTotal())
382 rErr
= ((ScFormulaCell
*)pCell
)->GetErrCode();
383 if ( rErr
|| ((ScFormulaCell
*)pCell
)->IsValue() )
385 rValue
= ((ScFormulaCell
*)pCell
)->GetValue();
388 return TRUE
; // gefunden
390 else if ( bTextAsZero
)
400 case CELLTYPE_STRING
:
407 nNumFmtType
= NUMBERFORMAT_NUMBER
;
417 // added to avoid warnings
423 nRow
= nEndRow
+ 1; // naechste Spalte
427 void ScValueIterator::GetCurNumFmtInfo( short& nType
, ULONG
& nIndex
)
431 const ScColumn
* pCol
= &(pDoc
->pTab
[nTab
])->aCol
[nCol
];
432 nNumFmtIndex
= pCol
->GetNumberFormat( nRow
);
433 if ( (nNumFmtIndex
% SV_COUNTRY_LANGUAGE_OFFSET
) == 0 )
435 const ScBaseCell
* pCell
;
436 SCSIZE nIdx
= nColRow
- 1;
437 // there might be rearranged something, so be on the safe side
438 if ( nIdx
< pCol
->nCount
&& pCol
->pItems
[nIdx
].nRow
== nRow
)
439 pCell
= pCol
->pItems
[nIdx
].pCell
;
442 if ( pCol
->Search( nRow
, nIdx
) )
443 pCell
= pCol
->pItems
[nIdx
].pCell
;
447 if ( pCell
&& pCell
->GetCellType() == CELLTYPE_FORMULA
)
448 ((const ScFormulaCell
*)pCell
)->GetFormatInfo( nNumFmtType
, nNumFmtIndex
);
450 nNumFmtType
= pDoc
->GetFormatTable()->GetType( nNumFmtIndex
);
453 nNumFmtType
= pDoc
->GetFormatTable()->GetType( nNumFmtIndex
);
457 nIndex
= nNumFmtIndex
;
460 BOOL
ScValueIterator::GetFirst(double& rValue
, USHORT
& rErr
)
467 ScColumn
* pCol
= &(pDoc
->pTab
[nTab
])->aCol
[nCol
];
468 pCol
->Search( nRow
, nColRow
);
470 nNumFormat
= 0; // werden bei GetNumberFormat initialisiert
474 return GetThis(rValue
, rErr
);
478 BOOL ScValueIterator::GetNext(double& rValue, USHORT& rErr)
481 return GetThis(rValue, rErr);
485 //------------------------------------------------------------------------
486 //------------------------------------------------------------------------
488 ScQueryValueIterator::ScQueryValueIterator(ScDocument
* pDocument
, SCTAB nTable
, const ScQueryParam
& rParam
) :
493 nNumFmtType( NUMBERFORMAT_UNDEFINED
),
494 bCalcAsShown( pDocument
->GetDocOptions().IsCalcAsShown() )
498 nColRow
= 0; // wird bei GetFirst initialisiert
500 SCSIZE nCount
= aParam
.GetEntryCount();
501 for (i
=0; (i
<nCount
) && (aParam
.GetEntry(i
).bDoQuery
); i
++)
503 ScQueryEntry
& rEntry
= aParam
.GetEntry(i
);
504 sal_uInt32 nIndex
= 0;
505 rEntry
.bQueryByString
=
506 !(pDoc
->GetFormatTable()->IsNumberFormat(*rEntry
.pStr
, nIndex
, rEntry
.nVal
));
508 nNumFormat
= 0; // werden bei GetNumberFormat initialisiert
513 BOOL
ScQueryValueIterator::GetThis(double& rValue
, USHORT
& rErr
)
515 ScColumn
* pCol
= &(pDoc
->pTab
[nTab
])->aCol
[nCol
];
516 SCCOLROW nFirstQueryField
= aParam
.GetEntry(0).nField
;
519 if ( nRow
> aParam
.nRow2
)
522 if (aParam
.bHasHeader
)
527 if ( nCol
> aParam
.nCol2
)
529 // rValue = 0.0; // do not change caller's value!
531 return FALSE
; // Ende und Aus
533 pCol
= &(pDoc
->pTab
[nTab
])->aCol
[nCol
];
534 } while ( pCol
->nCount
== 0 );
535 pCol
->Search( nRow
, nColRow
);
538 while ( (nColRow
< pCol
->nCount
) && (pCol
->pItems
[nColRow
].nRow
< nRow
) )
541 if ( nColRow
< pCol
->nCount
&& pCol
->pItems
[nColRow
].nRow
<= aParam
.nRow2
)
543 nRow
= pCol
->pItems
[nColRow
].nRow
;
544 ScBaseCell
* pCell
= pCol
->pItems
[nColRow
].pCell
;
545 if ( (pDoc
->pTab
[nTab
])->ValidQuery( nRow
, aParam
, NULL
,
546 (nCol
== static_cast<SCCOL
>(nFirstQueryField
) ? pCell
: NULL
) ) )
548 switch (pCell
->GetCellType())
552 rValue
= ((ScValueCell
*)pCell
)->GetValue();
555 lcl_IterGetNumberFormat( nNumFormat
, pAttrArray
,
556 nAttrEndRow
, pCol
->pAttrArray
, nRow
, pDoc
);
557 rValue
= pDoc
->RoundValueAsShown( rValue
, nNumFormat
);
559 nNumFmtType
= NUMBERFORMAT_NUMBER
;
562 return TRUE
; // gefunden
565 case CELLTYPE_FORMULA
:
567 if (((ScFormulaCell
*)pCell
)->IsValue())
569 rValue
= ((ScFormulaCell
*)pCell
)->GetValue();
570 pDoc
->GetNumberFormatInfo( nNumFmtType
,
571 nNumFmtIndex
, ScAddress( nCol
, nRow
, nTab
),
573 rErr
= ((ScFormulaCell
*)pCell
)->GetErrCode();
574 return TRUE
; // gefunden
589 nRow
= aParam
.nRow2
+ 1; // Naechste Spalte
594 BOOL
ScQueryValueIterator::GetFirst(double& rValue
, USHORT
& rErr
)
598 if (aParam
.bHasHeader
)
601 ScColumn
* pCol
= &(pDoc
->pTab
[nTab
])->aCol
[nCol
];
602 pCol
->Search( nRow
, nColRow
);
603 return GetThis(rValue
, rErr
);
606 BOOL
ScQueryValueIterator::GetNext(double& rValue
, USHORT
& rErr
)
609 return GetThis(rValue
, rErr
);
612 //-------------------------------------------------------------------------------
614 ScCellIterator::ScCellIterator( ScDocument
* pDocument
,
615 SCCOL nSCol
, SCROW nSRow
, SCTAB nSTab
,
616 SCCOL nECol
, SCROW nERow
, SCTAB nETab
, BOOL bSTotal
) :
627 PutInOrder( nStartCol
, nEndCol
);
628 PutInOrder( nStartRow
, nEndRow
);
629 PutInOrder( nStartTab
, nEndTab
);
631 if (!ValidCol(nStartCol
)) nStartCol
= MAXCOL
;
632 if (!ValidCol(nEndCol
)) nEndCol
= MAXCOL
;
633 if (!ValidRow(nStartRow
)) nStartRow
= MAXROW
;
634 if (!ValidRow(nEndRow
)) nEndRow
= MAXROW
;
635 if (!ValidTab(nStartTab
)) nStartTab
= MAXTAB
;
636 if (!ValidTab(nEndTab
)) nEndTab
= MAXTAB
;
638 while (nEndTab
>0 && !pDoc
->pTab
[nEndTab
])
639 --nEndTab
; // nur benutzte Tabellen
640 if (nStartTab
>nEndTab
)
646 nColRow
= 0; // wird bei GetFirst initialisiert
648 if (!pDoc
->pTab
[nTab
])
650 DBG_ERROR("Tabelle nicht gefunden");
651 nStartCol
= nCol
= MAXCOL
+1;
652 nStartRow
= nRow
= MAXROW
+1;
653 nStartTab
= nTab
= MAXTAB
+1; // -> Abbruch bei GetFirst
657 ScCellIterator::ScCellIterator
658 ( ScDocument
* pDocument
, const ScRange
& rRange
, BOOL bSTotal
) :
660 nStartCol( rRange
.aStart
.Col() ),
661 nStartRow( rRange
.aStart
.Row() ),
662 nStartTab( rRange
.aStart
.Tab() ),
663 nEndCol( rRange
.aEnd
.Col() ),
664 nEndRow( rRange
.aEnd
.Row() ),
665 nEndTab( rRange
.aEnd
.Tab() ),
669 PutInOrder( nStartCol
, nEndCol
);
670 PutInOrder( nStartRow
, nEndRow
);
671 PutInOrder( nStartTab
, nEndTab
);
673 if (!ValidCol(nStartCol
)) nStartCol
= MAXCOL
;
674 if (!ValidCol(nEndCol
)) nEndCol
= MAXCOL
;
675 if (!ValidRow(nStartRow
)) nStartRow
= MAXROW
;
676 if (!ValidRow(nEndRow
)) nEndRow
= MAXROW
;
677 if (!ValidTab(nStartTab
)) nStartTab
= MAXTAB
;
678 if (!ValidTab(nEndTab
)) nEndTab
= MAXTAB
;
680 while (nEndTab
>0 && !pDoc
->pTab
[nEndTab
])
681 --nEndTab
; // nur benutzte Tabellen
682 if (nStartTab
>nEndTab
)
688 nColRow
= 0; // wird bei GetFirst initialisiert
690 if (!pDoc
->pTab
[nTab
])
692 DBG_ERROR("Tabelle nicht gefunden");
693 nStartCol
= nCol
= MAXCOL
+1;
694 nStartRow
= nRow
= MAXROW
+1;
695 nStartTab
= nTab
= MAXTAB
+1; // -> Abbruch bei GetFirst
699 ScBaseCell
* ScCellIterator::GetThis()
701 ScColumn
* pCol
= &(pDoc
->pTab
[nTab
])->aCol
[nCol
];
704 if ( nRow
> nEndRow
)
710 if ( nCol
> nEndCol
)
714 if ( nTab
> nEndTab
)
715 return NULL
; // Ende und Aus
717 pCol
= &(pDoc
->pTab
[nTab
])->aCol
[nCol
];
718 } while ( pCol
->nCount
== 0 );
719 pCol
->Search( nRow
, nColRow
);
722 while ( (nColRow
< pCol
->nCount
) && (pCol
->pItems
[nColRow
].nRow
< nRow
) )
725 if ( nColRow
< pCol
->nCount
&& pCol
->pItems
[nColRow
].nRow
<= nEndRow
)
727 nRow
= pCol
->pItems
[nColRow
].nRow
;
728 if ( !bSubTotal
|| !pDoc
->pTab
[nTab
]->IsFiltered( nRow
) )
730 ScBaseCell
* pCell
= pCol
->pItems
[nColRow
].pCell
;
732 if ( bSubTotal
&& pCell
->GetCellType() == CELLTYPE_FORMULA
733 && ((ScFormulaCell
*)pCell
)->IsSubTotal() )
734 nRow
++; // Sub-Total-Zeilen nicht
736 return pCell
; // gefunden
742 nRow
= nEndRow
+ 1; // Naechste Spalte
746 ScBaseCell
* ScCellIterator::GetFirst()
748 if ( !ValidTab(nTab
) )
754 ScColumn
* pCol
= &(pDoc
->pTab
[nTab
])->aCol
[nCol
];
755 pCol
->Search( nRow
, nColRow
);
759 ScBaseCell
* ScCellIterator::GetNext()
765 //-------------------------------------------------------------------------------
767 ScQueryCellIterator::ScQueryCellIterator(ScDocument
* pDocument
, SCTAB nTable
,
768 const ScQueryParam
& rParam
, BOOL bMod
) :
772 nStopOnMismatch( nStopOnMismatchDisabled
),
773 nTestEqualCondition( nTestEqualConditionDisabled
),
774 bAdvanceQuery( FALSE
),
775 bIgnoreMismatchOnLeadingStrings( FALSE
)
779 nColRow
= 0; // wird bei GetFirst initialisiert
781 if (bMod
) // sonst schon eingetragen
783 for (i
=0; (i
<MAXQUERY
) && (aParam
.GetEntry(i
).bDoQuery
); i
++)
785 ScQueryEntry
& rEntry
= aParam
.GetEntry(i
);
786 sal_uInt32 nIndex
= 0;
787 rEntry
.bQueryByString
=
788 !(pDoc
->GetFormatTable()->IsNumberFormat(*rEntry
.pStr
,
789 nIndex
, rEntry
.nVal
));
792 nNumFormat
= 0; // werden bei GetNumberFormat initialisiert
797 ScBaseCell
* ScQueryCellIterator::GetThis()
799 ScColumn
* pCol
= &(pDoc
->pTab
[nTab
])->aCol
[nCol
];
800 const ScQueryEntry
& rEntry
= aParam
.GetEntry(0);
801 SCCOLROW nFirstQueryField
= rEntry
.nField
;
802 bool bAllStringIgnore
= bIgnoreMismatchOnLeadingStrings
&&
803 !rEntry
.bQueryByString
;
804 bool bFirstStringIgnore
= bIgnoreMismatchOnLeadingStrings
&&
805 !aParam
.bHasHeader
&& rEntry
.bQueryByString
&&
806 ((aParam
.bByRow
&& nRow
== aParam
.nRow1
) ||
807 (!aParam
.bByRow
&& nCol
== aParam
.nCol1
));
810 if ( nRow
> aParam
.nRow2
)
813 if (aParam
.bHasHeader
&& aParam
.bByRow
)
817 if ( ++nCol
> aParam
.nCol2
)
818 return NULL
; // Ende und Aus
821 AdvanceQueryParamEntryField();
822 nFirstQueryField
= rEntry
.nField
;
824 pCol
= &(pDoc
->pTab
[nTab
])->aCol
[nCol
];
825 } while ( pCol
->nCount
== 0 );
826 pCol
->Search( nRow
, nColRow
);
827 bFirstStringIgnore
= bIgnoreMismatchOnLeadingStrings
&&
828 !aParam
.bHasHeader
&& rEntry
.bQueryByString
&&
832 while ( nColRow
< pCol
->nCount
&& pCol
->pItems
[nColRow
].nRow
< nRow
)
835 if ( nColRow
< pCol
->nCount
&&
836 (nRow
= pCol
->pItems
[nColRow
].nRow
) <= aParam
.nRow2
)
838 ScBaseCell
* pCell
= pCol
->pItems
[nColRow
].pCell
;
839 if ( pCell
->GetCellType() == CELLTYPE_NOTE
)
841 else if (bAllStringIgnore
&& pCell
->HasStringData())
845 BOOL bTestEqualCondition
;
846 if ( (pDoc
->pTab
[nTab
])->ValidQuery( nRow
, aParam
, NULL
,
847 (nCol
== static_cast<SCCOL
>(nFirstQueryField
) ? pCell
: NULL
),
848 (nTestEqualCondition
? &bTestEqualCondition
: NULL
) ) )
850 if ( nTestEqualCondition
&& bTestEqualCondition
)
851 nTestEqualCondition
|= nTestEqualConditionMatched
;
852 return pCell
; // found
854 else if ( nStopOnMismatch
)
856 // Yes, even a mismatch may have a fulfilled equal
857 // condition if regular expressions were involved and
858 // SC_LESS_EQUAL or SC_GREATER_EQUAL were queried.
859 if ( nTestEqualCondition
&& bTestEqualCondition
)
861 nTestEqualCondition
|= nTestEqualConditionMatched
;
862 nStopOnMismatch
|= nStopOnMismatchOccured
;
866 if (bFirstStringIgnore
)
868 if (pCell
->HasStringData())
880 nStopOnMismatch
|= nStopOnMismatchOccured
;
889 nRow
= aParam
.nRow2
+ 1; // Naechste Spalte
890 bFirstStringIgnore
= false;
894 ScBaseCell
* ScQueryCellIterator::GetFirst()
898 if (aParam
.bHasHeader
)
901 ScColumn
* pCol
= &(pDoc
->pTab
[nTab
])->aCol
[nCol
];
902 pCol
->Search( nRow
, nColRow
);
906 ScBaseCell
* ScQueryCellIterator::GetNext()
909 if ( nStopOnMismatch
)
910 nStopOnMismatch
= nStopOnMismatchEnabled
;
911 if ( nTestEqualCondition
)
912 nTestEqualCondition
= nTestEqualConditionEnabled
;
916 ULONG
ScQueryCellIterator::GetNumberFormat()
918 ScColumn
* pCol
= &(pDoc
->pTab
[nTab
])->aCol
[nCol
];
919 lcl_IterGetNumberFormat( nNumFormat
, pAttrArray
,
920 nAttrEndRow
, pCol
->pAttrArray
, nRow
, pDoc
);
924 void ScQueryCellIterator::AdvanceQueryParamEntryField()
926 SCSIZE nEntries
= aParam
.GetEntryCount();
927 for ( SCSIZE j
= 0; j
< nEntries
; j
++ )
929 ScQueryEntry
& rEntry
= aParam
.GetEntry( j
);
930 if ( rEntry
.bDoQuery
)
932 if ( rEntry
.nField
< MAXCOL
)
936 DBG_ERRORFILE( "AdvanceQueryParamEntryField: ++rEntry.nField > MAXCOL" );
945 BOOL
ScQueryCellIterator::FindEqualOrSortedLastInRange( SCCOL
& nFoundCol
,
946 SCROW
& nFoundRow
, BOOL bSearchForEqualAfterMismatch
,
947 BOOL bIgnoreMismatchOnLeadingStringsP
)
949 nFoundCol
= MAXCOL
+1;
950 nFoundRow
= MAXROW
+1;
951 SetStopOnMismatch( TRUE
); // assume sorted keys
952 SetTestEqualCondition( TRUE
);
953 bIgnoreMismatchOnLeadingStrings
= bIgnoreMismatchOnLeadingStringsP
;
954 bool bRegExp
= aParam
.bRegExp
&& aParam
.GetEntry(0).bQueryByString
;
955 bool bBinary
= !bRegExp
&& aParam
.bByRow
&& (aParam
.GetEntry(0).eOp
==
956 SC_LESS_EQUAL
|| aParam
.GetEntry(0).eOp
== SC_GREATER_EQUAL
);
957 if (bBinary
? (BinarySearch() ? GetThis() : 0) : GetFirst())
959 // First equal entry or last smaller than (greater than) entry.
961 ScBaseCell
* pNext
= 0;
964 nFoundCol
= GetCol();
965 nFoundRow
= GetRow();
966 nColRowSave
= nColRow
;
967 } while ( !IsEqualConditionFulfilled() && (pNext
= GetNext()) != NULL
);
968 // There may be no pNext but equal condition fulfilled if regular
969 // expressions are involved. Keep the found entry and proceed.
970 if (!pNext
&& !IsEqualConditionFulfilled())
972 // Step back to last in range and adjust position markers for
973 // GetNumberFormat() or similar.
976 nColRow
= nColRowSave
;
979 if ( IsEqualConditionFulfilled() )
981 // Position on last equal entry.
982 SCSIZE nEntries
= aParam
.GetEntryCount();
983 for ( SCSIZE j
= 0; j
< nEntries
; j
++ )
985 ScQueryEntry
& rEntry
= aParam
.GetEntry( j
);
986 if ( rEntry
.bDoQuery
)
988 switch ( rEntry
.eOp
)
991 case SC_GREATER_EQUAL
:
992 rEntry
.eOp
= SC_EQUAL
;
996 // added to avoid warnings
1004 bIgnoreMismatchOnLeadingStrings
= FALSE
;
1005 SetTestEqualCondition( FALSE
);
1008 nFoundCol
= GetCol();
1009 nFoundRow
= GetRow();
1010 nColRowSave
= nColRow
;
1011 } while (GetNext());
1012 // Step back conditions same as above
1015 nColRow
= nColRowSave
;
1018 if ( (bSearchForEqualAfterMismatch
|| aParam
.bRegExp
) &&
1019 StoppedOnMismatch() )
1021 // Assume found entry to be the last value less than respectively
1022 // greater than the query. But keep on searching for an equal match.
1023 SCSIZE nEntries
= aParam
.GetEntryCount();
1024 for ( SCSIZE j
= 0; j
< nEntries
; j
++ )
1026 ScQueryEntry
& rEntry
= aParam
.GetEntry( j
);
1027 if ( rEntry
.bDoQuery
)
1029 switch ( rEntry
.eOp
)
1031 case SC_LESS_EQUAL
:
1032 case SC_GREATER_EQUAL
:
1033 rEntry
.eOp
= SC_EQUAL
;
1037 // added to avoid warnings
1044 SetStopOnMismatch( FALSE
);
1045 SetTestEqualCondition( FALSE
);
1048 // Last of a consecutive area, avoid searching the entire parameter
1049 // range as it is a real performance bottleneck in case of regular
1054 nFoundCol
= GetCol();
1055 nFoundRow
= GetRow();
1056 nColRowSave
= nColRow
;
1057 SetStopOnMismatch( TRUE
);
1058 } while (GetNext());
1061 nColRow
= nColRowSave
;
1064 return (nFoundCol
<= MAXCOL
) && (nFoundRow
<= MAXROW
);
1068 ScBaseCell
* ScQueryCellIterator::BinarySearch()
1070 nCol
= aParam
.nCol1
;
1071 ScColumn
* pCol
= &(pDoc
->pTab
[nTab
])->aCol
[nCol
];
1077 CollatorWrapper
* pCollator
= (aParam
.bCaseSens
? ScGlobal::pCaseCollator
:
1078 ScGlobal::pCollator
);
1079 SvNumberFormatter
& rFormatter
= *(pDoc
->GetFormatTable());
1080 const ScQueryEntry
& rEntry
= aParam
.GetEntry(0);
1081 bool bLessEqual
= rEntry
.eOp
== SC_LESS_EQUAL
;
1082 bool bByString
= rEntry
.bQueryByString
;
1083 bool bAllStringIgnore
= bIgnoreMismatchOnLeadingStrings
&& !bByString
;
1084 bool bFirstStringIgnore
= bIgnoreMismatchOnLeadingStrings
&&
1085 !aParam
.bHasHeader
&& bByString
;
1087 nRow
= aParam
.nRow1
;
1088 if (aParam
.bHasHeader
)
1090 const ColEntry
* pItems
= pCol
->pItems
;
1091 if (pCol
->Search( nRow
, nLo
) && bFirstStringIgnore
&&
1092 pItems
[nLo
].pCell
->HasStringData())
1095 ULONG nFormat
= pCol
->GetNumberFormat( pItems
[nLo
].nRow
);
1096 ScCellFormat::GetInputString( pItems
[nLo
].pCell
, nFormat
, aCellStr
,
1098 sal_Int32 nTmp
= pCollator
->compareString( aCellStr
, *rEntry
.pStr
);
1099 if ((rEntry
.eOp
== SC_LESS_EQUAL
&& nTmp
> 0) ||
1100 (rEntry
.eOp
== SC_GREATER_EQUAL
&& nTmp
< 0) ||
1101 (rEntry
.eOp
== SC_EQUAL
&& nTmp
!= 0))
1104 if (!pCol
->Search( aParam
.nRow2
, nHi
) && nHi
>0)
1106 while (bAllStringIgnore
&& nLo
<= nHi
&& nLo
< pCol
->nCount
&&
1107 pItems
[nLo
].pCell
->HasStringData())
1110 // Bookkeeping values for breaking up the binary search in case the data
1111 // range isn't strictly sorted.
1112 SCSIZE nLastInRange
= nLo
;
1113 SCSIZE nFirstLastInRange
= nLastInRange
;
1114 double fLastInRangeValue
= bLessEqual
?
1115 -(::std::numeric_limits
<double>::max()) :
1116 ::std::numeric_limits
<double>::max();
1117 String aLastInRangeString
;
1119 aLastInRangeString
.Assign( sal_Unicode(0xFFFF));
1120 if (nLastInRange
< pCol
->nCount
)
1122 pCell
= pItems
[nLastInRange
].pCell
;
1123 if (pCell
->HasStringData())
1125 ULONG nFormat
= pCol
->GetNumberFormat( pItems
[nLastInRange
].nRow
);
1126 ScCellFormat::GetInputString( pCell
, nFormat
, aLastInRangeString
,
1131 switch ( pCell
->GetCellType() )
1133 case CELLTYPE_VALUE
:
1135 static_cast<ScValueCell
*>(pCell
)->GetValue();
1137 case CELLTYPE_FORMULA
:
1139 static_cast<ScFormulaCell
*>(pCell
)->GetValue();
1143 // added to avoid warnings
1150 bool bFound
= false;
1152 while (nLo
<= nHi
&& !bDone
)
1154 SCSIZE nMid
= (nLo
+nHi
)/2;
1156 while (i
<= nHi
&& pItems
[i
].pCell
->GetCellType() == CELLTYPE_NOTE
)
1166 BOOL bStr
= pItems
[i
].pCell
->HasStringData();
1168 // compares are content<query:-1, content>query:1
1169 // Cell value comparison similar to ScTable::ValidQuery()
1170 if (!bStr
&& !bByString
)
1173 pCell
= pItems
[i
].pCell
;
1174 switch ( pCell
->GetCellType() )
1176 case CELLTYPE_VALUE
:
1177 nCellVal
= static_cast<ScValueCell
*>(pCell
)->GetValue();
1179 case CELLTYPE_FORMULA
:
1180 nCellVal
= static_cast<ScFormulaCell
*>(pCell
)->GetValue();
1185 if ((nCellVal
< rEntry
.nVal
) && !::rtl::math::approxEqual(
1186 nCellVal
, rEntry
.nVal
))
1191 if (fLastInRangeValue
< nCellVal
)
1193 fLastInRangeValue
= nCellVal
;
1196 else if (fLastInRangeValue
> nCellVal
)
1198 // not strictly sorted, continue with GetThis()
1199 nLastInRange
= nFirstLastInRange
;
1204 else if ((nCellVal
> rEntry
.nVal
) && !::rtl::math::approxEqual(
1205 nCellVal
, rEntry
.nVal
))
1210 if (fLastInRangeValue
> nCellVal
)
1212 fLastInRangeValue
= nCellVal
;
1215 else if (fLastInRangeValue
< nCellVal
)
1217 // not strictly sorted, continue with GetThis()
1218 nLastInRange
= nFirstLastInRange
;
1224 else if (bStr
&& bByString
)
1227 ULONG nFormat
= pCol
->GetNumberFormat( pItems
[i
].nRow
);
1228 ScCellFormat::GetInputString( pItems
[i
].pCell
, nFormat
, aCellStr
,
1230 nRes
= pCollator
->compareString( aCellStr
, *rEntry
.pStr
);
1231 if (nRes
< 0 && bLessEqual
)
1233 sal_Int32 nTmp
= pCollator
->compareString( aLastInRangeString
,
1237 aLastInRangeString
= aCellStr
;
1242 // not strictly sorted, continue with GetThis()
1243 nLastInRange
= nFirstLastInRange
;
1247 else if (nRes
> 0 && !bLessEqual
)
1249 sal_Int32 nTmp
= pCollator
->compareString( aLastInRangeString
,
1253 aLastInRangeString
= aCellStr
;
1258 // not strictly sorted, continue with GetThis()
1259 nLastInRange
= nFirstLastInRange
;
1264 else if (!bStr
&& bByString
)
1266 nRes
= -1; // numeric < string
1270 else // if (bStr && !bByString)
1272 nRes
= 1; // string > numeric
1280 else // assumed to be SC_GREATER_EQUAL
1297 else // assumed to be SC_GREATER_EQUAL
1303 bDone
= bFound
= true;
1308 // If all hits didn't result in a moving limit there's something
1309 // strange, e.g. data range not properly sorted, or only identical
1310 // values encountered, which doesn't mean there aren't any others in
1311 // between.. leave it to GetThis(). The condition for this would be
1312 // if (nLastInRange == nFirstLastInRange) nLo = nFirstLastInRange;
1313 // Else, in case no exact match was found, we step back for a
1314 // subsequent GetThis() to find the last in range. Effectively this is
1315 // --nLo with nLastInRange == nLo-1. Both conditions combined yield:
1318 if (nLo
< pCol
->nCount
&& pCol
->pItems
[nLo
].nRow
<= aParam
.nRow2
)
1320 nRow
= pItems
[nLo
].nRow
;
1321 pCell
= pItems
[nLo
].pCell
;
1326 nRow
= aParam
.nRow2
+ 1;
1328 nColRow
= pCol
->nCount
- 1;
1334 //-------------------------------------------------------------------------------
1336 ScHorizontalCellIterator::ScHorizontalCellIterator(ScDocument
* pDocument
, SCTAB nTable
,
1337 SCCOL nCol1
, SCROW nRow1
, SCCOL nCol2
, SCROW nRow2
) :
1350 pNextRows
= new SCROW
[ nCol2
-nCol1
+1 ];
1351 pNextIndices
= new SCSIZE
[ nCol2
-nCol1
+1 ];
1353 for (i
=nStartCol
; i
<=nEndCol
; i
++)
1355 ScColumn
* pCol
= &pDoc
->pTab
[nTab
]->aCol
[i
];
1357 pCol
->Search( nRow1
, nIndex
);
1358 if ( nIndex
< pCol
->nCount
)
1360 pNextRows
[i
-nStartCol
] = pCol
->pItems
[nIndex
].nRow
;
1361 pNextIndices
[i
-nStartCol
] = nIndex
;
1365 pNextRows
[i
-nStartCol
] = MAXROWCOUNT
; // nichts gefunden
1366 pNextIndices
[i
-nStartCol
] = MAXROWCOUNT
;
1370 if (pNextRows
[0] != nRow1
)
1374 ScHorizontalCellIterator::~ScHorizontalCellIterator()
1376 delete [] pNextRows
;
1377 delete [] pNextIndices
;
1380 ScBaseCell
* ScHorizontalCellIterator::GetNext( SCCOL
& rCol
, SCROW
& rRow
)
1387 ScColumn
* pCol
= &pDoc
->pTab
[nTab
]->aCol
[nCol
];
1388 SCSIZE nIndex
= pNextIndices
[nCol
-nStartCol
];
1389 DBG_ASSERT( nIndex
< pCol
->nCount
, "ScHorizontalCellIterator::GetNext: nIndex out of range" );
1390 ScBaseCell
* pCell
= pCol
->pItems
[nIndex
].pCell
;
1391 if ( ++nIndex
< pCol
->nCount
)
1393 pNextRows
[nCol
-nStartCol
] = pCol
->pItems
[nIndex
].nRow
;
1394 pNextIndices
[nCol
-nStartCol
] = nIndex
;
1398 pNextRows
[nCol
-nStartCol
] = MAXROWCOUNT
; // nichts gefunden
1399 pNextIndices
[nCol
-nStartCol
] = MAXROWCOUNT
;
1409 BOOL
ScHorizontalCellIterator::ReturnNext( SCCOL
& rCol
, SCROW
& rRow
)
1416 void ScHorizontalCellIterator::Advance()
1418 BOOL bFound
= FALSE
;
1421 for (i
=nCol
+1; i
<=nEndCol
&& !bFound
; i
++)
1422 if (pNextRows
[i
-nStartCol
] == nRow
)
1430 SCROW nMinRow
= MAXROW
+1;
1431 for (i
=nStartCol
; i
<=nEndCol
; i
++)
1432 if (pNextRows
[i
-nStartCol
] < nMinRow
)
1435 nMinRow
= pNextRows
[i
-nStartCol
];
1438 if (nMinRow
<= nEndRow
)
1449 //-------------------------------------------------------------------------------
1451 ScHorizontalAttrIterator::ScHorizontalAttrIterator( ScDocument
* pDocument
, SCTAB nTable
,
1452 SCCOL nCol1
, SCROW nRow1
, SCCOL nCol2
, SCROW nRow2
) :
1460 DBG_ASSERT( pDoc
->pTab
[nTab
], "Tabelle nicht da" );
1468 pIndices
= new SCSIZE
[nEndCol
-nStartCol
+1];
1469 pNextEnd
= new SCROW
[nEndCol
-nStartCol
+1];
1470 ppPatterns
= new const ScPatternAttr
*[nEndCol
-nStartCol
+1];
1472 SCROW nSkipTo
= MAXROW
;
1474 for (i
=nStartCol
; i
<=nEndCol
; i
++)
1476 SCCOL nPos
= i
- nStartCol
;
1477 ScAttrArray
* pArray
= pDoc
->pTab
[nTab
]->aCol
[i
].pAttrArray
;
1478 DBG_ASSERT( pArray
, "pArray == 0" );
1481 pArray
->Search( nStartRow
, nIndex
);
1483 const ScPatternAttr
* pPattern
= pArray
->pData
[nIndex
].pPattern
;
1484 SCROW nThisEnd
= pArray
->pData
[nIndex
].nRow
;
1485 if ( IsDefaultItem( pPattern
) )
1488 if ( nThisEnd
< nSkipTo
)
1489 nSkipTo
= nThisEnd
; // nSkipTo kann gleich hier gesetzt werden
1492 bEmpty
= FALSE
; // Attribute gefunden
1494 pIndices
[nPos
] = nIndex
;
1495 pNextEnd
[nPos
] = nThisEnd
;
1496 ppPatterns
[nPos
] = pPattern
;
1500 nRow
= nSkipTo
; // bis zum naechsten Bereichsende ueberspringen
1504 ScHorizontalAttrIterator::~ScHorizontalAttrIterator()
1506 delete[] (ScPatternAttr
**)ppPatterns
;
1511 const ScPatternAttr
* ScHorizontalAttrIterator::GetNext( SCCOL
& rCol1
, SCCOL
& rCol2
, SCROW
& rRow
)
1517 // in dieser Zeile suchen
1519 while ( nCol
<= nEndCol
&& !ppPatterns
[nCol
-nStartCol
] )
1522 if ( nCol
<= nEndCol
)
1524 const ScPatternAttr
* pPat
= ppPatterns
[nCol
-nStartCol
];
1527 while ( nCol
< nEndCol
&& ppPatterns
[nCol
+1-nStartCol
] == pPat
)
1530 ++nCol
; // hochzaehlen fuer naechsten Aufruf
1531 return pPat
; // gefunden
1538 if ( nRow
> nEndRow
) // schon am Ende?
1539 return NULL
; // nichts gefunden
1544 for ( i
= nStartCol
; i
<= nEndCol
; i
++)
1546 SCCOL nPos
= i
-nStartCol
;
1547 if ( pNextEnd
[nPos
] < nRow
)
1549 ScAttrArray
* pArray
= pDoc
->pTab
[nTab
]->aCol
[i
].pAttrArray
;
1551 SCSIZE nIndex
= ++pIndices
[nPos
];
1552 if ( nIndex
< pArray
->nCount
)
1554 const ScPatternAttr
* pPattern
= pArray
->pData
[nIndex
].pPattern
;
1555 SCROW nThisEnd
= pArray
->pData
[nIndex
].nRow
;
1556 if ( IsDefaultItem( pPattern
) )
1559 bEmpty
= FALSE
; // Attribute gefunden
1561 pNextEnd
[nPos
] = nThisEnd
;
1562 ppPatterns
[nPos
] = pPattern
;
1564 DBG_ASSERT( pNextEnd
[nPos
] >= nRow
, "Reihenfolge durcheinander" );
1568 DBG_ERROR("AttrArray reicht nicht bis MAXROW");
1569 pNextEnd
[nPos
] = MAXROW
;
1570 ppPatterns
[nPos
] = NULL
;
1573 else if ( ppPatterns
[nPos
] )
1574 bEmpty
= FALSE
; // Bereich noch nicht zuende
1579 SCCOL nCount
= nEndCol
-nStartCol
+1;
1580 SCROW nSkipTo
= pNextEnd
[0]; // naechstes Bereichsende suchen
1581 for (i
=1; i
<nCount
; i
++)
1582 if ( pNextEnd
[i
] < nSkipTo
)
1583 nSkipTo
= pNextEnd
[i
];
1584 nRow
= nSkipTo
; // leere Zeilen ueberspringen
1587 nCol
= nStartCol
; // wieder links anfangen
1593 //-------------------------------------------------------------------------------
1595 inline BOOL
IsGreater( SCCOL nCol1
, SCROW nRow1
, SCCOL nCol2
, SCROW nRow2
)
1597 return ( nRow1
> nRow2
) || ( nRow1
== nRow2
&& nCol1
> nCol2
);
1600 ScUsedAreaIterator::ScUsedAreaIterator( ScDocument
* pDocument
, SCTAB nTable
,
1601 SCCOL nCol1
, SCROW nRow1
, SCCOL nCol2
, SCROW nRow2
) :
1602 aCellIter( pDocument
, nTable
, nCol1
, nRow1
, nCol2
, nRow2
),
1603 aAttrIter( pDocument
, nTable
, nCol1
, nRow1
, nCol2
, nRow2
),
1607 pCell
= aCellIter
.GetNext( nCellCol
, nCellRow
);
1608 pPattern
= aAttrIter
.GetNext( nAttrCol1
, nAttrCol2
, nAttrRow
);
1611 ScUsedAreaIterator::~ScUsedAreaIterator()
1615 BOOL
ScUsedAreaIterator::GetNext()
1617 // Iteratoren weiterzaehlen
1619 if ( pCell
&& IsGreater( nNextCol
, nNextRow
, nCellCol
, nCellRow
) )
1620 pCell
= aCellIter
.GetNext( nCellCol
, nCellRow
);
1622 while ( pCell
&& pCell
->IsBlank() )
1623 pCell
= aCellIter
.GetNext( nCellCol
, nCellRow
);
1625 if ( pPattern
&& IsGreater( nNextCol
, nNextRow
, nAttrCol2
, nAttrRow
) )
1626 pPattern
= aAttrIter
.GetNext( nAttrCol1
, nAttrCol2
, nAttrRow
);
1628 if ( pPattern
&& nAttrRow
== nNextRow
&& nAttrCol1
< nNextCol
)
1629 nAttrCol1
= nNextCol
;
1631 // naechsten Abschnitt heraussuchen
1634 BOOL bUseCell
= FALSE
;
1636 if ( pCell
&& pPattern
)
1638 if ( IsGreater( nCellCol
, nCellRow
, nAttrCol1
, nAttrRow
) ) // vorne nur Attribute ?
1641 pFoundPattern
= pPattern
;
1642 nFoundRow
= nAttrRow
;
1643 nFoundStartCol
= nAttrCol1
;
1644 if ( nCellRow
== nAttrRow
&& nCellCol
<= nAttrCol2
) // auch Zelle im Bereich ?
1645 nFoundEndCol
= nCellCol
- 1; // nur bis vor der Zelle
1647 nFoundEndCol
= nAttrCol2
; // alles
1652 if ( nAttrRow
== nCellRow
&& nAttrCol1
== nCellCol
) // Attribute auf der Zelle ?
1653 pFoundPattern
= pPattern
;
1655 pFoundPattern
= NULL
;
1658 else if ( pCell
) // nur Zelle -> direkt uebernehmen
1660 pFoundPattern
= NULL
;
1661 bUseCell
= TRUE
; // Position von Zelle
1663 else if ( pPattern
) // nur Attribute -> direkt uebernehmen
1666 pFoundPattern
= pPattern
;
1667 nFoundRow
= nAttrRow
;
1668 nFoundStartCol
= nAttrCol1
;
1669 nFoundEndCol
= nAttrCol2
;
1674 if ( bUseCell
) // Position von Zelle
1677 nFoundRow
= nCellRow
;
1678 nFoundStartCol
= nFoundEndCol
= nCellCol
;
1683 nNextRow
= nFoundRow
;
1684 nNextCol
= nFoundEndCol
+ 1;
1690 //-------------------------------------------------------------------------------
1692 ScDocAttrIterator::ScDocAttrIterator(ScDocument
* pDocument
, SCTAB nTable
,
1693 SCCOL nCol1
, SCROW nRow1
,
1694 SCCOL nCol2
, SCROW nRow2
) :
1702 if ( ValidTab(nTab
) && pDoc
->pTab
[nTab
] )
1703 pColIter
= pDoc
->pTab
[nTab
]->aCol
[nCol
].CreateAttrIterator( nStartRow
, nEndRow
);
1708 ScDocAttrIterator::~ScDocAttrIterator()
1713 const ScPatternAttr
* ScDocAttrIterator::GetNext( SCCOL
& rCol
, SCROW
& rRow1
, SCROW
& rRow2
)
1717 const ScPatternAttr
* pPattern
= pColIter
->Next( rRow1
, rRow2
);
1726 if ( nCol
<= nEndCol
)
1727 pColIter
= pDoc
->pTab
[nTab
]->aCol
[nCol
].CreateAttrIterator( nStartRow
, nEndRow
);
1731 return NULL
; // is nix mehr
1734 //-------------------------------------------------------------------------------
1736 ScAttrRectIterator::ScAttrRectIterator(ScDocument
* pDocument
, SCTAB nTable
,
1737 SCCOL nCol1
, SCROW nRow1
,
1738 SCCOL nCol2
, SCROW nRow2
) :
1744 nIterStartCol( nCol1
),
1745 nIterEndCol( nCol1
)
1747 if ( ValidTab(nTab
) && pDoc
->pTab
[nTab
] )
1749 pColIter
= pDoc
->pTab
[nTab
]->aCol
[nIterStartCol
].CreateAttrIterator( nStartRow
, nEndRow
);
1750 while ( nIterEndCol
< nEndCol
&&
1751 pDoc
->pTab
[nTab
]->aCol
[nIterEndCol
].IsAllAttrEqual(
1752 pDoc
->pTab
[nTab
]->aCol
[nIterEndCol
+1], nStartRow
, nEndRow
) )
1759 ScAttrRectIterator::~ScAttrRectIterator()
1764 void ScAttrRectIterator::DataChanged()
1768 SCROW nNextRow
= pColIter
->GetNextRow();
1770 pColIter
= pDoc
->pTab
[nTab
]->aCol
[nIterStartCol
].CreateAttrIterator( nNextRow
, nEndRow
);
1774 const ScPatternAttr
* ScAttrRectIterator::GetNext( SCCOL
& rCol1
, SCCOL
& rCol2
,
1775 SCROW
& rRow1
, SCROW
& rRow2
)
1779 const ScPatternAttr
* pPattern
= pColIter
->Next( rRow1
, rRow2
);
1782 rCol1
= nIterStartCol
;
1783 rCol2
= nIterEndCol
;
1788 nIterStartCol
= nIterEndCol
+1;
1789 if ( nIterStartCol
<= nEndCol
)
1791 nIterEndCol
= nIterStartCol
;
1792 pColIter
= pDoc
->pTab
[nTab
]->aCol
[nIterStartCol
].CreateAttrIterator( nStartRow
, nEndRow
);
1793 while ( nIterEndCol
< nEndCol
&&
1794 pDoc
->pTab
[nTab
]->aCol
[nIterEndCol
].IsAllAttrEqual(
1795 pDoc
->pTab
[nTab
]->aCol
[nIterEndCol
+1], nStartRow
, nEndRow
) )
1801 return NULL
; // is nix mehr