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