1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 #ifndef SC_DOCITER_HXX 29 #define SC_DOCITER_HXX 30 31 #include "address.hxx" 32 #include <tools/solar.h> 33 #include "global.hxx" 34 #include "scdllapi.h" 35 #include "queryparam.hxx" 36 37 #include <memory> 38 39 #include <set> 40 41 class ScDocument; 42 class ScBaseCell; 43 class ScPatternAttr; 44 class ScAttrArray; 45 class ScAttrIterator; 46 class ScRange; 47 48 class ScDocumentIterator // alle nichtleeren Zellen durchgehen 49 { 50 private: 51 ScDocument* pDoc; 52 SCTAB nStartTab; 53 SCTAB nEndTab; 54 55 const ScPatternAttr* pDefPattern; 56 57 SCCOL nCol; 58 SCROW nRow; 59 SCTAB nTab; 60 ScBaseCell* pCell; 61 const ScPatternAttr* pPattern; 62 63 64 SCSIZE nColPos; 65 SCSIZE nAttrPos; 66 67 sal_Bool GetThis(); 68 sal_Bool GetThisCol(); 69 70 public: 71 ScDocumentIterator( ScDocument* pDocument, SCTAB nStartTable, SCTAB nEndTable ); 72 ~ScDocumentIterator(); 73 74 sal_Bool GetFirst(); 75 sal_Bool GetNext(); 76 77 ScBaseCell* GetCell(); 78 const ScPatternAttr* GetPattern(); 79 void GetPos( SCCOL& rCol, SCROW& rRow, SCTAB& rTab ); 80 }; 81 82 class ScValueIterator // alle Zahlenwerte in einem Bereich durchgehen 83 { 84 private: 85 double fNextValue; 86 ScDocument* pDoc; 87 const ScAttrArray* pAttrArray; 88 sal_uLong nNumFormat; // fuer CalcAsShown 89 sal_uLong nNumFmtIndex; 90 SCCOL nStartCol; 91 SCROW nStartRow; 92 SCTAB nStartTab; 93 SCCOL nEndCol; 94 SCROW nEndRow; 95 SCTAB nEndTab; 96 SCCOL nCol; 97 SCROW nRow; 98 SCTAB nTab; 99 SCSIZE nColRow; 100 SCROW nNextRow; 101 SCROW nAttrEndRow; 102 short nNumFmtType; 103 sal_Bool bNumValid; 104 sal_Bool bSubTotal; 105 sal_Bool bNextValid; 106 sal_Bool bCalcAsShown; 107 sal_Bool bTextAsZero; 108 109 sal_Bool GetThis(double& rValue, sal_uInt16& rErr); 110 public: 111 //UNUSED2008-05 ScValueIterator(ScDocument* pDocument, 112 //UNUSED2008-05 SCCOL nSCol, SCROW nSRow, SCTAB nSTab, 113 //UNUSED2008-05 SCCOL nECol, SCROW nERow, SCTAB nETab, 114 //UNUSED2008-05 sal_Bool bSTotal = sal_False, sal_Bool bTextAsZero = sal_False); 115 116 ScValueIterator(ScDocument* pDocument, 117 const ScRange& rRange, sal_Bool bSTotal = sal_False, 118 sal_Bool bTextAsZero = sal_False ); 119 void GetCurNumFmtInfo( short& nType, sal_uLong& nIndex ); 120 /// Does NOT reset rValue if no value found! 121 sal_Bool GetFirst(double& rValue, sal_uInt16& rErr); 122 /// Does NOT reset rValue if no value found! 123 sal_Bool GetNext(double& rValue, sal_uInt16& rErr) 124 { 125 return bNextValid ? ( bNextValid = sal_False, rValue = fNextValue, 126 rErr = 0, nRow = nNextRow, 127 ++nColRow, bNumValid = sal_False, sal_True ) 128 : ( ++nRow, GetThis(rValue, rErr) ); 129 } 130 }; 131 132 // ============================================================================ 133 134 class ScDBQueryDataIterator 135 { 136 public: 137 struct Value 138 { 139 ::rtl::OUString maString; 140 double mfValue; 141 sal_uInt16 mnError; 142 bool mbIsNumber; 143 144 Value(); 145 }; 146 147 private: 148 static SCROW GetRowByColEntryIndex(ScDocument& rDoc, SCTAB nTab, SCCOL nCol, SCSIZE nColRow); 149 static ScBaseCell* GetCellByColEntryIndex(ScDocument& rDoc, SCTAB nTab, SCCOL nCol, SCSIZE nColRow); 150 static ScAttrArray* GetAttrArrayByCol(ScDocument& rDoc, SCTAB nTab, SCCOL nCol); 151 static bool IsQueryValid(ScDocument& rDoc, const ScQueryParam& rParam, SCTAB nTab, SCROW nRow, ScBaseCell* pCell); 152 static SCSIZE SearchColEntryIndex(ScDocument& rDoc, SCTAB nTab, SCROW nRow, SCCOL nCol); 153 154 class DataAccess 155 { 156 public: 157 DataAccess(const ScDBQueryDataIterator* pParent); 158 virtual ~DataAccess() = 0; 159 virtual bool getCurrent(Value& rValue) = 0; 160 virtual bool getFirst(Value& rValue) = 0; 161 virtual bool getNext(Value& rValue) = 0; 162 protected: 163 const ScDBQueryDataIterator* mpParent; 164 }; 165 166 class DataAccessInternal : public DataAccess 167 { 168 public: 169 DataAccessInternal(const ScDBQueryDataIterator* pParent, ScDBQueryParamInternal* pParam, ScDocument* pDoc); 170 virtual ~DataAccessInternal(); 171 virtual bool getCurrent(Value& rValue); 172 virtual bool getFirst(Value& rValue); 173 virtual bool getNext(Value& rValue); 174 175 private: 176 ScDBQueryParamInternal* mpParam; 177 ScDocument* mpDoc; 178 const ScAttrArray* pAttrArray; 179 sal_uLong nNumFormat; // for CalcAsShown 180 sal_uLong nNumFmtIndex; 181 SCCOL nCol; 182 SCROW nRow; 183 SCSIZE nColRow; 184 SCROW nAttrEndRow; 185 SCTAB nTab; 186 short nNumFmtType; 187 bool bCalcAsShown; 188 }; 189 190 class DataAccessMatrix : public DataAccess 191 { 192 public: 193 DataAccessMatrix(const ScDBQueryDataIterator* pParent, ScDBQueryParamMatrix* pParam); 194 virtual ~DataAccessMatrix(); 195 virtual bool getCurrent(Value& rValue); 196 virtual bool getFirst(Value& rValue); 197 virtual bool getNext(Value& rValue); 198 199 private: 200 bool isValidQuery(SCROW mnRow, const ScMatrix& rMat) const; 201 202 ScDBQueryParamMatrix* mpParam; 203 SCROW mnCurRow; 204 SCROW mnRows; 205 SCCOL mnCols; 206 }; 207 208 ::std::auto_ptr<ScDBQueryParamBase> mpParam; 209 ::std::auto_ptr<DataAccess> mpData; 210 211 public: 212 ScDBQueryDataIterator(ScDocument* pDocument, ScDBQueryParamBase* pParam); 213 /// Does NOT reset rValue if no value found! 214 bool GetFirst(Value& rValue); 215 /// Does NOT reset rValue if no value found! 216 bool GetNext(Value& rValue); 217 }; 218 219 // ============================================================================ 220 221 class ScCellIterator // alle Zellen in einem Bereich durchgehen 222 { // bei SubTotal aber keine ausgeblendeten und 223 private: // SubTotalZeilen 224 ScDocument* pDoc; 225 SCCOL nStartCol; 226 SCROW nStartRow; 227 SCTAB nStartTab; 228 SCCOL nEndCol; 229 SCROW nEndRow; 230 SCTAB nEndTab; 231 SCCOL nCol; 232 SCROW nRow; 233 SCTAB nTab; 234 SCSIZE nColRow; 235 sal_Bool bSubTotal; 236 237 ScBaseCell* GetThis(); 238 public: 239 ScCellIterator(ScDocument* pDocument, 240 SCCOL nSCol, SCROW nSRow, SCTAB nSTab, 241 SCCOL nECol, SCROW nERow, SCTAB nETab, 242 sal_Bool bSTotal = sal_False); 243 ScCellIterator(ScDocument* pDocument, 244 const ScRange& rRange, sal_Bool bSTotal = sal_False); 245 ScBaseCell* GetFirst(); 246 ScBaseCell* GetNext(); 247 SCCOL GetCol() const { return nCol; } 248 SCROW GetRow() const { return nRow; } 249 SCTAB GetTab() const { return nTab; } 250 ScAddress GetPos() const { return ScAddress( nCol, nRow, nTab ); } 251 }; 252 253 class ScQueryCellIterator // alle nichtleeren Zellen in einem Bereich 254 { // durchgehen 255 enum StopOnMismatchBits 256 { 257 nStopOnMismatchDisabled = 0x00, 258 nStopOnMismatchEnabled = 0x01, 259 nStopOnMismatchOccured = 0x02, 260 nStopOnMismatchExecuted = nStopOnMismatchEnabled | nStopOnMismatchOccured 261 }; 262 263 enum TestEqualConditionBits 264 { 265 nTestEqualConditionDisabled = 0x00, 266 nTestEqualConditionEnabled = 0x01, 267 nTestEqualConditionMatched = 0x02, 268 nTestEqualConditionFulfilled = nTestEqualConditionEnabled | nTestEqualConditionMatched 269 }; 270 271 private: 272 ScQueryParam aParam; 273 ScDocument* pDoc; 274 const ScAttrArray* pAttrArray; 275 sal_uLong nNumFormat; 276 SCTAB nTab; 277 SCCOL nCol; 278 SCROW nRow; 279 SCSIZE nColRow; 280 SCROW nAttrEndRow; 281 sal_uInt8 nStopOnMismatch; 282 sal_uInt8 nTestEqualCondition; 283 sal_Bool bAdvanceQuery; 284 sal_Bool bIgnoreMismatchOnLeadingStrings; 285 286 ScBaseCell* GetThis(); 287 288 /* Only works if no regular expression is involved, only 289 searches for rows in one column, and only the first 290 query entry is considered with simple conditions 291 SC_LESS_EQUAL (sorted ascending) or SC_GREATER_EQUAL 292 (sorted descending). Check these things before 293 invocation! Delivers a starting point, continue with 294 GetThis() and GetNext() afterwards. Introduced for 295 FindEqualOrSortedLastInRange() 296 */ 297 ScBaseCell* BinarySearch(); 298 299 public: 300 ScQueryCellIterator(ScDocument* pDocument, SCTAB nTable, 301 const ScQueryParam& aParam, sal_Bool bMod = sal_True); 302 // fuer bMod = sal_False muss der QueryParam 303 // weiter aufgefuellt sein (bIsString) 304 ScBaseCell* GetFirst(); 305 ScBaseCell* GetNext(); 306 SCCOL GetCol() { return nCol; } 307 SCROW GetRow() { return nRow; } 308 309 // setzt alle Entry.nField einen weiter, wenn Spalte 310 // wechselt, fuer ScInterpreter ScHLookup() 311 void SetAdvanceQueryParamEntryField( sal_Bool bVal ) 312 { bAdvanceQuery = bVal; } 313 void AdvanceQueryParamEntryField(); 314 315 /** If set, iterator stops on first non-matching cell 316 content. May be used in SC_LESS_EQUAL queries where a 317 cell range is assumed to be sorted; stops on first 318 value being greater than the queried value and 319 GetFirst()/GetNext() return NULL. StoppedOnMismatch() 320 returns sal_True then. 321 However, the iterator's conditions are not set to end 322 all queries, GetCol() and GetRow() return values for 323 the non-matching cell, further GetNext() calls may be 324 executed. */ 325 void SetStopOnMismatch( sal_Bool bVal ) 326 { 327 nStopOnMismatch = sal::static_int_cast<sal_uInt8>(bVal ? nStopOnMismatchEnabled : 328 nStopOnMismatchDisabled); 329 } 330 sal_Bool StoppedOnMismatch() const 331 { return nStopOnMismatch == nStopOnMismatchExecuted; } 332 333 /** If set, an additional test for SC_EQUAL condition is 334 executed in ScTable::ValidQuery() if SC_LESS_EQUAL or 335 SC_GREATER_EQUAL conditions are to be tested. May be 336 used where a cell range is assumed to be sorted to stop 337 if an equal match is found. */ 338 void SetTestEqualCondition( sal_Bool bVal ) 339 { 340 nTestEqualCondition = sal::static_int_cast<sal_uInt8>(bVal ? 341 nTestEqualConditionEnabled : 342 nTestEqualConditionDisabled); 343 } 344 sal_Bool IsEqualConditionFulfilled() const 345 { return nTestEqualCondition == nTestEqualConditionFulfilled; } 346 347 /** In a range assumed to be sorted find either the last of 348 a sequence of equal entries or the last being less than 349 (or greater than) the queried value. Used by the 350 interpreter for [HV]?LOOKUP() and MATCH(). Column and 351 row position of the found entry are returned, otherwise 352 invalid. 353 354 @param bSearchForEqualAfterMismatch 355 Continue searching for an equal entry even if the 356 last entry matching the range was found, in case 357 the data is not sorted. Is always done if regular 358 expressions are involved. 359 360 @param bIgnoreMismatchOnLeadingStrings 361 Normally strings are sorted behind numerical 362 values. If this parameter is sal_True, the search does 363 not stop when encountering a string and does not 364 assume that no values follow anymore. 365 If querying for a string a mismatch on the first 366 entry, e.g. column header, is ignored. 367 368 @ATTENTION! StopOnMismatch, TestEqualCondition and 369 the internal IgnoreMismatchOnLeadingStrings and query 370 params are in an undefined state upon return! The 371 iterator is not usable anymore except for obtaining the 372 number format! 373 */ 374 sal_Bool FindEqualOrSortedLastInRange( SCCOL& nFoundCol, 375 SCROW& nFoundRow, sal_Bool bSearchForEqualAfterMismatch = sal_False, 376 sal_Bool bIgnoreMismatchOnLeadingStrings = sal_True ); 377 }; 378 379 class ScDocAttrIterator // alle Attribut-Bereiche 380 { 381 private: 382 ScDocument* pDoc; 383 SCTAB nTab; 384 SCCOL nEndCol; 385 SCROW nStartRow; 386 SCROW nEndRow; 387 SCCOL nCol; 388 ScAttrIterator* pColIter; 389 390 public: 391 ScDocAttrIterator(ScDocument* pDocument, SCTAB nTable, 392 SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2); 393 ~ScDocAttrIterator(); 394 395 const ScPatternAttr* GetNext( SCCOL& rCol, SCROW& rRow1, SCROW& rRow2 ); 396 }; 397 398 class ScAttrRectIterator // alle Attribut-Bereiche, auch Bereiche ueber mehrere Spalten 399 { 400 private: 401 ScDocument* pDoc; 402 SCTAB nTab; 403 SCCOL nEndCol; 404 SCROW nStartRow; 405 SCROW nEndRow; 406 SCCOL nIterStartCol; 407 SCCOL nIterEndCol; 408 ScAttrIterator* pColIter; 409 410 public: 411 ScAttrRectIterator(ScDocument* pDocument, SCTAB nTable, 412 SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2); 413 ~ScAttrRectIterator(); 414 415 void DataChanged(); 416 const ScPatternAttr* GetNext( SCCOL& rCol1, SCCOL& rCol2, SCROW& rRow1, SCROW& rRow2 ); 417 }; 418 419 class ScHorizontalCellIterator // alle nichtleeren Zellen in einem Bereich 420 { // zeilenweise durchgehen 421 private: 422 ScDocument* pDoc; 423 SCTAB nTab; 424 SCCOL nStartCol; 425 SCCOL nEndCol; 426 SCROW nStartRow; 427 SCROW nEndRow; 428 SCROW* pNextRows; 429 SCSIZE* pNextIndices; 430 SCCOL nCol; 431 SCROW nRow; 432 sal_Bool bMore; 433 434 public: 435 ScHorizontalCellIterator(ScDocument* pDocument, SCTAB nTable, 436 SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2); 437 ~ScHorizontalCellIterator(); 438 439 ScBaseCell* GetNext( SCCOL& rCol, SCROW& rRow ); 440 sal_Bool ReturnNext( SCCOL& rCol, SCROW& rRow ); 441 /// Set a(nother) sheet and (re)init. 442 void SetTab( SCTAB nTab ); 443 444 private: 445 void Advance(); 446 }; 447 448 449 /** Row-wise value iterator. */ 450 class ScHorizontalValueIterator 451 { 452 private: 453 ScDocument *pDoc; 454 const ScAttrArray *pAttrArray; 455 ScHorizontalCellIterator *pCellIter; 456 sal_uLong nNumFormat; // for CalcAsShown 457 sal_uLong nNumFmtIndex; 458 SCTAB nEndTab; 459 SCCOL nCurCol; 460 SCROW nCurRow; 461 SCTAB nCurTab; 462 SCROW nAttrEndRow; 463 short nNumFmtType; 464 bool bNumValid; 465 bool bSubTotal; 466 bool bCalcAsShown; 467 bool bTextAsZero; 468 469 public: 470 471 ScHorizontalValueIterator( ScDocument* pDocument, 472 const ScRange& rRange, 473 bool bSTotal = false, 474 bool bTextAsZero = false ); 475 ~ScHorizontalValueIterator(); 476 void GetCurNumFmtInfo( short& nType, sal_uLong& nIndex ); 477 /// Does NOT reset rValue if no value found! 478 bool GetNext( double& rValue, sal_uInt16& rErr ); 479 }; 480 481 482 // 483 // gibt alle Bereiche mit nicht-Default-Formatierung zurueck (horizontal) 484 // 485 486 class ScHorizontalAttrIterator 487 { 488 private: 489 ScDocument* pDoc; 490 SCTAB nTab; 491 SCCOL nStartCol; 492 SCROW nStartRow; 493 SCCOL nEndCol; 494 SCROW nEndRow; 495 496 SCROW* pNextEnd; 497 SCSIZE* pIndices; 498 const ScPatternAttr** ppPatterns; 499 SCCOL nCol; 500 SCROW nRow; 501 sal_Bool bRowEmpty; 502 503 public: 504 ScHorizontalAttrIterator( ScDocument* pDocument, SCTAB nTable, 505 SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2 ); 506 ~ScHorizontalAttrIterator(); 507 508 const ScPatternAttr* GetNext( SCCOL& rCol1, SCCOL& rCol2, SCROW& rRow ); 509 }; 510 511 // 512 // gibt nichtleere Zellen und Bereiche mit Formatierung zurueck (horizontal) 513 // 514 515 class SC_DLLPUBLIC ScUsedAreaIterator 516 { 517 private: 518 ScHorizontalCellIterator aCellIter; 519 ScHorizontalAttrIterator aAttrIter; 520 521 SCCOL nNextCol; 522 SCROW nNextRow; 523 524 SCCOL nCellCol; 525 SCROW nCellRow; 526 const ScBaseCell* pCell; 527 SCCOL nAttrCol1; 528 SCCOL nAttrCol2; 529 SCROW nAttrRow; 530 const ScPatternAttr* pPattern; 531 532 SCCOL nFoundStartCol; // Ergebnisse nach GetNext 533 SCCOL nFoundEndCol; 534 SCROW nFoundRow; 535 const ScPatternAttr* pFoundPattern; 536 const ScBaseCell* pFoundCell; 537 538 public: 539 ScUsedAreaIterator( ScDocument* pDocument, SCTAB nTable, 540 SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2 ); 541 ~ScUsedAreaIterator(); 542 543 sal_Bool GetNext(); 544 545 SCCOL GetStartCol() const { return nFoundStartCol; } 546 SCCOL GetEndCol() const { return nFoundEndCol; } 547 SCROW GetRow() const { return nFoundRow; } 548 const ScPatternAttr* GetPattern() const { return pFoundPattern; } 549 const ScBaseCell* GetCell() const { return pFoundCell; } 550 }; 551 552 // ============================================================================ 553 554 class ScRowBreakIterator 555 { 556 public: 557 static SCROW NOT_FOUND; 558 559 explicit ScRowBreakIterator(::std::set<SCROW>& rBreaks); 560 SCROW first(); 561 SCROW next(); 562 563 private: 564 ::std::set<SCROW>& mrBreaks; 565 ::std::set<SCROW>::const_iterator maItr; 566 ::std::set<SCROW>::const_iterator maEnd; 567 }; 568 569 #endif 570 571 572