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 // MARKER(update_precomp.py): autogen include statement, do not remove 24 #include "precompiled_sc.hxx" 25 // INCLUDE --------------------------------------------------------------- 26 #include "dptablecache.hxx" 27 #include "dptabdat.hxx" 28 #include "document.hxx" 29 #include "cell.hxx" 30 #include "globstr.hrc" 31 32 #include <rtl/math.hxx> 33 #include "queryparam.hxx" 34 #include "dpglobal.hxx" 35 36 #include "docoptio.hxx" //for ValidQuery 37 #include <unotools/textsearch.hxx> //for ValidQuery 38 39 #include <com/sun/star/sdbc/DataType.hpp> 40 #include <com/sun/star/sdbc/XRow.hpp> 41 #include <com/sun/star/sdbc/XRowSet.hpp> 42 #include <com/sun/star/sdbc/XResultSetMetaData.hpp> 43 #include <com/sun/star/sdbc/XResultSetMetaDataSupplier.hpp> 44 const double D_TIMEFACTOR = 86400.0; 45 46 using namespace ::com::sun::star; 47 48 using ::com::sun::star::uno::Exception; 49 using ::com::sun::star::uno::Reference; 50 using ::com::sun::star::uno::UNO_QUERY; 51 using ::com::sun::star::uno::UNO_QUERY_THROW; 52 // ----------------------------------------------------------------------- 53 namespace 54 { 55 sal_Bool lcl_isDate( sal_uLong nNumType ) 56 { 57 return ( (nNumType & NUMBERFORMAT_DATE) != 0 )? 1:0 ; 58 } 59 60 sal_Bool lcl_Search( const std::vector<ScDPItemData*>& list, const ::std::vector<SCROW>& rOrder, const ScDPItemData& item, SCROW& rIndex) 61 { 62 rIndex = list.size(); 63 sal_Bool bFound = sal_False; 64 SCROW nLo = 0; 65 SCROW nHi = list.size() - 1; 66 SCROW nIndex; 67 long nCompare; 68 while (nLo <= nHi) 69 { 70 nIndex = (nLo + nHi) / 2; 71 nCompare = ScDPItemData::Compare( *list[rOrder[nIndex]], item ); 72 if (nCompare < 0) 73 nLo = nIndex + 1; 74 else 75 { 76 nHi = nIndex - 1; 77 if (nCompare == 0) 78 { 79 bFound = sal_True; 80 nLo = nIndex; 81 } 82 } 83 } 84 rIndex = nLo; 85 return bFound; 86 } 87 88 ScDPItemData* lcl_GetItemValue(const Reference<sdbc::XRow>& xRow, sal_Int32 nType, long nCol, 89 const Date& rNullDate ) 90 { 91 short nNumType = NUMBERFORMAT_NUMBER; 92 try 93 { 94 String rStr = xRow->getString(nCol); 95 double fValue = 0.0; 96 switch (nType) 97 { 98 case sdbc::DataType::BIT: 99 case sdbc::DataType::BOOLEAN: 100 { 101 nNumType = NUMBERFORMAT_LOGICAL; 102 fValue = xRow->getBoolean(nCol) ? 1 : 0; 103 return new ScDPItemData( rStr, fValue,sal_True,nNumType); 104 } 105 //break; 106 107 case sdbc::DataType::TINYINT: 108 case sdbc::DataType::SMALLINT: 109 case sdbc::DataType::INTEGER: 110 case sdbc::DataType::BIGINT: 111 case sdbc::DataType::FLOAT: 112 case sdbc::DataType::REAL: 113 case sdbc::DataType::DOUBLE: 114 case sdbc::DataType::NUMERIC: 115 case sdbc::DataType::DECIMAL: 116 { 117 //! do the conversion here? 118 fValue = xRow->getDouble(nCol); 119 return new ScDPItemData( rStr, fValue,sal_True); 120 } 121 //break; 122 123 case sdbc::DataType::DATE: 124 { 125 nNumType = NUMBERFORMAT_DATE; 126 127 util::Date aDate = xRow->getDate(nCol); 128 fValue = Date(aDate.Day, aDate.Month, aDate.Year) - rNullDate; 129 return new ScDPItemData( rStr, fValue, sal_True, nNumType ); 130 } 131 //break; 132 133 case sdbc::DataType::TIME: 134 { 135 nNumType = NUMBERFORMAT_TIME; 136 137 util::Time aTime = xRow->getTime(nCol); 138 fValue = ( aTime.Hours * 3600 + aTime.Minutes * 60 + 139 aTime.Seconds + aTime.HundredthSeconds / 100.0 ) / D_TIMEFACTOR; 140 return new ScDPItemData( rStr,fValue, sal_True, nNumType ); 141 } 142 //break; 143 144 case sdbc::DataType::TIMESTAMP: 145 { 146 nNumType = NUMBERFORMAT_DATETIME; 147 148 util::DateTime aStamp = xRow->getTimestamp(nCol); 149 fValue = ( Date( aStamp.Day, aStamp.Month, aStamp.Year ) - rNullDate ) + 150 ( aStamp.Hours * 3600 + aStamp.Minutes * 60 + 151 aStamp.Seconds + aStamp.HundredthSeconds / 100.0 ) / D_TIMEFACTOR; 152 return new ScDPItemData( rStr,fValue, sal_True, nNumType ); 153 } 154 //break; 155 case sdbc::DataType::CHAR: 156 case sdbc::DataType::VARCHAR: 157 case sdbc::DataType::LONGVARCHAR: 158 case sdbc::DataType::SQLNULL: 159 case sdbc::DataType::BINARY: 160 case sdbc::DataType::VARBINARY: 161 case sdbc::DataType::LONGVARBINARY: 162 default: 163 return new ScDPItemData ( rStr ); 164 //break; 165 } 166 } 167 catch (uno::Exception&) 168 { 169 } 170 catch ( ... ) 171 { 172 173 } 174 return NULL; 175 } 176 } 177 // Wang Xu Ming -- 12/23/2008 178 //Refactor cache data 179 ScDPItemData::ScDPItemData( const String& rS, double fV/* = 0.0*/, sal_Bool bHV/* = sal_False*/, const sal_uLong nNumFormatP /*= 0*/ , sal_Bool bData/* = sal_True*/) : 180 nNumFormat( nNumFormatP ), aString(rS), fValue(fV), 181 mbFlag( (MK_VAL*!!bHV) | (MK_DATA*!!bData) | (MK_ERR*!!sal_False) | (MK_DATE*!!lcl_isDate( nNumFormat ) ) ) 182 { 183 } 184 185 ScDPItemData::ScDPItemData( ScDocument* pDoc, SCROW nRow, sal_uInt16 nCol, sal_uInt16 nDocTab ): 186 nNumFormat( 0 ), fValue(0.0), mbFlag( 0 ) 187 { 188 String aDocStr; 189 pDoc->GetString( nCol, nRow, nDocTab, aDocStr ); 190 191 SvNumberFormatter* pFormatter = pDoc->GetFormatTable(); 192 193 ScAddress aPos( nCol, nRow, nDocTab ); 194 ScBaseCell* pCell = pDoc->GetCell( aPos ); 195 196 if ( pCell && pCell->GetCellType() == CELLTYPE_FORMULA && ((ScFormulaCell*)pCell)->GetErrCode() ) 197 { 198 SetString ( aDocStr ); //[SODC_19347] add liyi 199 //bErr = sal_True; //[SODC_19347] del liyi 200 mbFlag |= MK_ERR; 201 } 202 else if ( pDoc->HasValueData( nCol, nRow, nDocTab ) ) 203 { 204 double fVal = pDoc->GetValue(ScAddress(nCol, nRow, nDocTab)); 205 nNumFormat = pDoc->GetNumberFormat( ScAddress( nCol, nRow, nDocTab ) ); 206 sal_uLong nFormat = NUMBERFORMAT_NUMBER; 207 if ( pFormatter ) 208 nFormat = pFormatter->GetType( nNumFormat ); 209 aString = aDocStr; 210 fValue = fVal; 211 mbFlag |= MK_VAL|MK_DATA; 212 lcl_isDate( nFormat ) ? ( mbFlag |= MK_DATE ) : (mbFlag &= ~MK_DATE); 213 } 214 else if ( pDoc->HasData( nCol,nRow, nDocTab ) ) 215 SetString ( aDocStr ); 216 } 217 // End Comments 218 219 sal_Bool ScDPItemData::IsCaseInsEqual( const ScDPItemData& r ) const 220 { //TODO: indified Date? 221 //! pass Transliteration? 222 //! inline? 223 return IsValue() ? ( r.IsValue() && rtl::math::approxEqual( fValue, r.fValue ) ) : 224 ( !r.IsValue() && 225 ScGlobal::GetpTransliteration()->isEqual( aString, r.aString ) ); 226 } 227 228 size_t ScDPItemData::Hash() const 229 { 230 if ( IsValue() ) 231 return (size_t) rtl::math::approxFloor( fValue ); 232 else 233 // If we do unicode safe case insensitive hash we can drop 234 // ScDPItemData::operator== and use ::IsCasInsEqual 235 return rtl_ustr_hashCode_WithLength( aString.GetBuffer(), aString.Len() ); 236 } 237 238 sal_Bool ScDPItemData::operator==( const ScDPItemData& r ) const 239 { 240 if ( IsValue() ) 241 { 242 if( (HasDatePart() != r.HasDatePart()) || (HasDatePart() && mnDatePart != r.mnDatePart) ) 243 return sal_False; 244 245 // Wang Xu Ming -- 1/9/2009 246 // Add Data Cache Support. 247 // Identify date 248 if ( IsDate() != r.IsDate() ) 249 return sal_False; 250 else 251 if ( r.IsValue() ) 252 return rtl::math::approxEqual( fValue, r.fValue ); 253 else 254 return sal_False; 255 // End Comments 256 } 257 else if ( r.IsValue() ) 258 return sal_False; 259 else 260 // need exact equality until we have a safe case insensitive string hash 261 return aString == r.aString; 262 } 263 264 sal_Int32 ScDPItemData::Compare( const ScDPItemData& rA, 265 const ScDPItemData& rB ) 266 { 267 if ( rA.IsValue() ) 268 { 269 if ( rB.IsValue() ) 270 { 271 if ( rtl::math::approxEqual( rA.fValue, rB.fValue ) ) 272 { 273 // Wang Xu Ming -- 1/9/2009 274 // Add Data Cache Support. 275 // Date > number 276 if ( rA.IsDate() == rB.IsDate() ) 277 return 0; 278 else 279 return rA.IsDate() ? 1: -1; 280 // End Comments 281 } 282 else if ( rA.fValue < rB.fValue ) 283 return -1; 284 else 285 return 1; 286 } 287 else 288 return -1; // values first 289 } 290 else if ( rB.IsValue() ) 291 return 1; // values first 292 else 293 return ScGlobal::GetCollator()->compareString( rA.aString, rB.aString ); 294 } 295 // 296 //Wang Xu Ming SODC_17561 297 #ifdef DEBUG 298 void ScDPItemData::dump() const 299 { 300 DBG_TRACE1( "Numberformat= %o", nNumFormat ); 301 DBG_TRACESTR(aString ); 302 DBG_TRACE1( "fValue= %f", fValue ); 303 DBG_TRACE1( "mbFlag= %d", mbFlag); 304 } 305 #endif 306 //End 307 308 TypedStrData* ScDPItemData::CreateTypeString( ) 309 { 310 if ( IsValue() ) 311 return new TypedStrData( aString, fValue, SC_STRTYPE_VALUE ); 312 else 313 return new TypedStrData( aString ); 314 } 315 316 sal_uInt8 ScDPItemData::GetType() const 317 { 318 319 if ( IsHasErr() ) 320 return SC_VALTYPE_ERROR; 321 else if ( !IsHasData() ) 322 return SC_VALTYPE_EMPTY; 323 else if ( IsValue()) 324 return SC_VALTYPE_VALUE; 325 else 326 return SC_VALTYPE_STRING; 327 328 } 329 330 sal_Bool ScDPItemData::IsHasData() const 331 { 332 return !!(mbFlag&MK_DATA); 333 } 334 335 sal_Bool ScDPItemData::IsHasErr() const 336 { 337 return !!(mbFlag&MK_ERR); 338 } 339 340 sal_Bool ScDPItemData::IsValue() const 341 { 342 return !!(mbFlag&MK_VAL); 343 } 344 345 String ScDPItemData::GetString() const 346 { 347 348 return aString; 349 } 350 351 double ScDPItemData::GetValue() const 352 { 353 return fValue; 354 } 355 sal_uLong ScDPItemData::GetNumFormat() const 356 { 357 return nNumFormat; 358 } 359 360 sal_Bool ScDPItemData::HasStringData() const 361 362 { 363 return IsHasData()&&!IsHasErr()&&!IsValue(); 364 } 365 sal_Bool ScDPItemData::IsDate() const 366 { 367 return !!(mbFlag&MK_DATE); 368 } 369 sal_Bool ScDPItemData::HasDatePart() const 370 { 371 return !!(mbFlag&MK_DATEPART); 372 } 373 void ScDPItemData::SetDate( sal_Bool b ) 374 { 375 b ? ( mbFlag |= MK_DATE ) : ( mbFlag &= ~MK_DATE ); 376 } 377 378 // ----------------------------------------------------------------------- 379 //class ScDPTableDataCache 380 //To cache the pivot table data source 381 382 sal_Bool ScDPTableDataCache::operator== ( const ScDPTableDataCache& r ) const 383 { 384 if ( GetColumnCount() == r.GetColumnCount() ) 385 { 386 for ( SCCOL i = 0 ; i < GetColumnCount(); i++ ) 387 { //check dim names 388 if ( GetDimensionName( i ) != r.GetDimensionName( i ) ) 389 return sal_False; 390 //check rows count 391 if ( GetRowCount() != r.GetRowCount() ) 392 return sal_False; 393 //check dim member values 394 size_t nMembersCount = GetDimMemberValues( i ).size(); 395 if ( GetDimMemberValues( i ).size() == r. GetDimMemberValues( i ).size() ) 396 { 397 for ( size_t j = 0; j < nMembersCount; j++ ) 398 { 399 if ( *( GetDimMemberValues( i )[j] ) == *( r.GetDimMemberValues( i )[j] ) ) 400 continue; 401 else 402 return sal_False; 403 } 404 } 405 else 406 return sal_False; 407 //check source table index 408 for ( SCROW k=0 ; k < GetRowCount(); k ++ ) 409 { 410 if ( GetItemDataId( i, k, sal_False ) == r.GetItemDataId( i,k,sal_False) ) 411 continue; 412 else 413 return sal_False; 414 } 415 } 416 } 417 return sal_True; 418 } 419 420 ScDPTableDataCache::ScDPTableDataCache( ScDocument* pDoc ) : 421 mpDoc( pDoc ), 422 mnColumnCount ( 0 ), 423 mpTableDataValues ( NULL ), 424 mpSourceData ( NULL ), 425 mpGlobalOrder( NULL ), 426 mpIndexOrder( NULL) 427 { 428 mnID = -1; 429 } 430 431 ScDPTableDataCache::~ScDPTableDataCache() 432 { 433 if ( IsValid() ) 434 { 435 // Wang Xu Ming -- 2/17/2009 436 // Performance issue 437 sal_uInt16 nCol; 438 for ( nCol=0; nCol < GetColumnCount() ; nCol++ ) 439 { 440 for ( sal_uLong row = 0 ; row < mpTableDataValues[nCol].size(); row++ ) 441 delete mpTableDataValues[nCol][row]; 442 } 443 for ( nCol =0; nCol < mrLabelNames.size(); nCol++ ) 444 delete mrLabelNames[nCol]; 445 // End Comments 446 447 mnColumnCount = 0; 448 delete [] mpTableDataValues; 449 mpTableDataValues = NULL; 450 delete [] mpSourceData; 451 mpSourceData = NULL; 452 delete [] mpGlobalOrder; 453 mpGlobalOrder = NULL; 454 delete [] mpIndexOrder; 455 mpIndexOrder = NULL; 456 } 457 } 458 459 // ----------------------------------------------------------------------- 460 void ScDPTableDataCache::AddRow( ScDPItemData* pRow, sal_uInt16 nCount ) 461 { 462 DBG_ASSERT( pRow , " empty pointer" ); 463 if ( !mrLabelNames.size() ) 464 { 465 mnColumnCount= nCount; 466 mpTableDataValues = new std::vector<ScDPItemData*>[ mnColumnCount ]; 467 mpSourceData = new std::vector<SCROW>[ mnColumnCount ]; 468 mpGlobalOrder = new std::vector<SCROW>[ mnColumnCount ]; 469 mpIndexOrder = new std::vector<SCROW>[ mnColumnCount ]; 470 471 for ( sal_uInt16 i = 0; i < nCount ; i ++ ) 472 AddLabel( new ScDPItemData( pRow[i] ) ); 473 } 474 else 475 { 476 for ( sal_uInt16 i = 0; i < nCount && i < mnColumnCount; i ++ ) 477 AddData( i, new ScDPItemData( pRow[i] ) ); 478 } 479 } 480 481 // ----------------------------------------------------------------------- 482 bool ScDPTableDataCache::IsValid() const 483 { //TODO: continue check valid 484 return mpTableDataValues!=NULL && mpSourceData!= NULL && mnColumnCount>0; 485 } 486 487 // ----------------------------------------------------------------------- 488 489 namespace { 490 491 /** 492 * While the macro interpret level is incremented, the formula cells are 493 * (semi-)guaranteed to be interpreted. 494 */ 495 class MacroInterpretIncrementer 496 { 497 public: 498 MacroInterpretIncrementer(ScDocument* pDoc) : 499 mpDoc(pDoc) 500 { 501 mpDoc->IncMacroInterpretLevel(); 502 } 503 ~MacroInterpretIncrementer() 504 { 505 mpDoc->DecMacroInterpretLevel(); 506 } 507 private: 508 ScDocument* mpDoc; 509 }; 510 511 } 512 513 // ----------------------------------------------------------------------- 514 bool ScDPTableDataCache::InitFromDoc( ScDocument* pDoc, const ScRange& rRange ) 515 { 516 // Make sure the formula cells within the data range are interpreted 517 // during this call, for this method may be called from the interpretation 518 // of GETPIVOTDATA, which disables nested formula interpretation without 519 // increasing the macro level. 520 MacroInterpretIncrementer aMacroInc(pDoc); 521 522 // 523 SCROW nStartRow = rRange.aStart.Row(); // start of data 524 SCROW nEndRow = rRange.aEnd.Row(); 525 sal_uInt16 nStartCol = rRange.aStart.Col(); 526 sal_uInt16 nEndCol = rRange.aEnd.Col(); 527 sal_uInt16 nDocTab = rRange.aStart.Tab(); 528 529 //init 530 long nOldColumCount = mnColumnCount; 531 mnColumnCount = nEndCol - nStartCol + 1; 532 if ( IsValid() ) 533 { 534 for ( sal_uInt16 nCol=0; nCol < nOldColumCount ; nCol++ ) 535 { 536 for ( sal_uLong row = 0 ; row < mpTableDataValues[nCol].size(); row++ ) 537 delete mpTableDataValues[nCol][row]; 538 delete mrLabelNames[nCol]; 539 } 540 delete [] mpTableDataValues; 541 delete [] mpSourceData; 542 delete [] mpGlobalOrder; 543 delete [] mpIndexOrder; 544 mrLabelNames.clear(); 545 } 546 547 mpTableDataValues = new std::vector<ScDPItemData*>[ mnColumnCount ]; 548 mpSourceData = new std::vector<SCROW>[ mnColumnCount ]; 549 mpGlobalOrder = new std::vector<SCROW>[ mnColumnCount ]; 550 mpIndexOrder = new std::vector<SCROW>[ mnColumnCount ]; 551 //check valid 552 for ( SCROW nRow = nStartRow; nRow <= nEndRow; nRow ++ ) 553 { 554 for ( sal_uInt16 nCol = nStartCol; nCol <= nEndCol; nCol++ ) 555 { 556 if ( nRow == nStartRow ) 557 AddLabel( new ScDPItemData( pDoc, nRow, nCol, nDocTab ) ); 558 else 559 AddData( nCol - nStartCol, new ScDPItemData( pDoc, nRow, nCol, nDocTab ) ); 560 } 561 } 562 return sal_True; 563 } 564 565 // ----------------------------------------------------------------------- 566 bool ScDPTableDataCache::InitFromDataBase (const Reference<sdbc::XRowSet>& xRowSet, const Date& rNullDate) 567 { 568 if (!xRowSet.is()) 569 // Dont' even waste time to go any further. 570 return false; 571 try 572 { 573 Reference<sdbc::XResultSetMetaDataSupplier> xMetaSupp(xRowSet, UNO_QUERY_THROW); 574 Reference<sdbc::XResultSetMetaData> xMeta = xMetaSupp->getMetaData(); 575 if (!xMeta.is()) 576 return false; 577 578 long nOldColumCount = mnColumnCount; 579 mnColumnCount = xMeta->getColumnCount(); 580 if ( IsValid() ) 581 { 582 for ( sal_uInt16 nCol=0; nCol < nOldColumCount ; nCol++ ) 583 { 584 for ( sal_uLong row = 0 ; row < mpTableDataValues[nCol].size(); row++ ) 585 delete mpTableDataValues[nCol][row]; 586 delete mrLabelNames[nCol]; 587 } 588 delete [] mpTableDataValues; 589 delete [] mpSourceData; 590 delete [] mpGlobalOrder; 591 delete [] mpIndexOrder; 592 mrLabelNames.clear(); 593 } 594 // Get column titles and types. 595 mrLabelNames.reserve(mnColumnCount); 596 mpTableDataValues = new std::vector<ScDPItemData*>[ mnColumnCount ]; 597 mpSourceData = new std::vector<SCROW>[ mnColumnCount ]; 598 mpGlobalOrder = new std::vector<SCROW>[ mnColumnCount ]; 599 mpIndexOrder = new std::vector<SCROW>[ mnColumnCount ]; 600 601 std::vector<sal_Int32> aColTypes(mnColumnCount); 602 603 for (sal_Int32 nCol = 0; nCol < mnColumnCount; ++nCol) 604 { 605 String aColTitle = xMeta->getColumnLabel(nCol+1); 606 aColTypes[nCol] = xMeta->getColumnType(nCol+1); 607 AddLabel( new ScDPItemData( aColTitle) ); 608 } 609 610 // Now get the data rows. 611 Reference<sdbc::XRow> xRow(xRowSet, UNO_QUERY_THROW); 612 xRowSet->first(); 613 do 614 { 615 for (sal_Int32 nCol = 0; nCol < mnColumnCount; ++nCol) 616 { 617 ScDPItemData * pNew = lcl_GetItemValue( xRow, aColTypes[nCol], nCol+1, rNullDate ); 618 if ( pNew ) 619 AddData( nCol , pNew ); 620 } 621 } 622 while (xRowSet->next()); 623 624 xRowSet->beforeFirst(); 625 626 return true; 627 } 628 catch (const Exception&) 629 { 630 return false; 631 } 632 } 633 // ----------------------------------------------------------------------- 634 sal_uLong ScDPTableDataCache::GetDimNumType( SCCOL nDim) const 635 { 636 DBG_ASSERT( IsValid(), " IsValid() == false " ); 637 DBG_ASSERT( nDim < mnColumnCount && nDim >=0, " dimention out of bound " ); 638 if ( mpTableDataValues[nDim].size()==0 ) 639 return NUMBERFORMAT_UNDEFINED; 640 else 641 return GetNumType(mpTableDataValues[nDim][0]->nNumFormat); 642 } 643 644 // ----------------------------------------------------------------------- 645 bool ScDPTableDataCache::ValidQuery( SCROW nRow, const ScQueryParam &rParam, sal_Bool *pSpecial) 646 { //Copied and modified from ScTable::ValidQuery 647 if (!rParam.GetEntry(0).bDoQuery) 648 return sal_True; 649 sal_Bool bMatchWholeCell = mpDoc->GetDocOptions().IsMatchWholeCell(); 650 651 //--------------------------------------------------------------- 652 653 const SCSIZE nFixedBools = 32; 654 sal_Bool aBool[nFixedBools]; 655 sal_Bool aTest[nFixedBools]; 656 SCSIZE nEntryCount = rParam.GetEntryCount(); 657 sal_Bool* pPasst = ( nEntryCount <= nFixedBools ? &aBool[0] : new sal_Bool[nEntryCount] ); 658 sal_Bool* pTest = ( nEntryCount <= nFixedBools ? &aTest[0] : new sal_Bool[nEntryCount] ); 659 660 long nPos = -1; 661 SCSIZE i = 0; 662 CollatorWrapper* pCollator = (rParam.bCaseSens ? ScGlobal::GetCaseCollator() : 663 ScGlobal::GetCollator() ); 664 ::utl::TransliterationWrapper* pTransliteration = (rParam.bCaseSens ? 665 ScGlobal::GetCaseTransliteration() : ScGlobal::GetpTransliteration()); 666 667 while ( (i < nEntryCount) && rParam.GetEntry(i).bDoQuery ) 668 { 669 ScQueryEntry& rEntry = rParam.GetEntry(i); 670 // we can only handle one single direct query 671 // #i115431# nField in QueryParam is the sheet column, not the field within the source range 672 SCCOL nQueryCol = (SCCOL)rEntry.nField; 673 if ( nQueryCol < rParam.nCol1 ) 674 nQueryCol = rParam.nCol1; 675 if ( nQueryCol > rParam.nCol2 ) 676 nQueryCol = rParam.nCol2; 677 SCCOL nSourceField = nQueryCol - rParam.nCol1; 678 SCROW nId = GetItemDataId( nSourceField, nRow, sal_False ); 679 const ScDPItemData* pCellData = GetItemDataById( nSourceField, nId ); 680 681 sal_Bool bOk = sal_False; 682 sal_Bool bTestEqual = sal_False; 683 684 if ( pSpecial && pSpecial[i] ) 685 { 686 if (rEntry.nVal == SC_EMPTYFIELDS) 687 bOk = ! pCellData->IsHasData(); 688 else // if (rEntry.nVal == SC_NONEMPTYFIELDS) 689 bOk = pCellData->IsHasData(); 690 } 691 else if ( !rEntry.bQueryByString && pCellData->IsValue() ) 692 { // by Value 693 double nCellVal = pCellData->GetValue(); 694 695 switch (rEntry.eOp) 696 { 697 case SC_EQUAL : 698 bOk = ::rtl::math::approxEqual( nCellVal, rEntry.nVal ); 699 break; 700 case SC_LESS : 701 bOk = (nCellVal < rEntry.nVal) && !::rtl::math::approxEqual( nCellVal, rEntry.nVal ); 702 break; 703 case SC_GREATER : 704 bOk = (nCellVal > rEntry.nVal) && !::rtl::math::approxEqual( nCellVal, rEntry.nVal ); 705 break; 706 case SC_LESS_EQUAL : 707 bOk = (nCellVal < rEntry.nVal) || ::rtl::math::approxEqual( nCellVal, rEntry.nVal ); 708 break; 709 case SC_GREATER_EQUAL : 710 bOk = (nCellVal > rEntry.nVal) || ::rtl::math::approxEqual( nCellVal, rEntry.nVal ); 711 break; 712 case SC_NOT_EQUAL : 713 bOk = !::rtl::math::approxEqual( nCellVal, rEntry.nVal ); 714 break; 715 default: 716 bOk= sal_False; 717 break; 718 } 719 } 720 else if ( (rEntry.eOp == SC_EQUAL || rEntry.eOp == SC_NOT_EQUAL) 721 || (rEntry.bQueryByString 722 && pCellData->HasStringData() ) 723 ) 724 { // by String 725 String aCellStr = pCellData->GetString(); 726 727 sal_Bool bRealRegExp = (rParam.bRegExp && ((rEntry.eOp == SC_EQUAL) 728 || (rEntry.eOp == SC_NOT_EQUAL))); 729 sal_Bool bTestRegExp = sal_False; 730 if ( bRealRegExp || bTestRegExp ) 731 { 732 xub_StrLen nStart = 0; 733 xub_StrLen nEnd = aCellStr.Len(); 734 sal_Bool bMatch = (sal_Bool) rEntry.GetSearchTextPtr( rParam.bCaseSens ) 735 ->SearchFrwrd( aCellStr, &nStart, &nEnd ); 736 // from 614 on, nEnd is behind the found text 737 if ( bMatch && bMatchWholeCell 738 && (nStart != 0 || nEnd != aCellStr.Len()) ) 739 bMatch = sal_False; // RegExp must match entire cell string 740 if ( bRealRegExp ) 741 bOk = ((rEntry.eOp == SC_NOT_EQUAL) ? !bMatch : bMatch); 742 else 743 bTestEqual = bMatch; 744 } 745 if ( !bRealRegExp ) 746 { 747 if ( rEntry.eOp == SC_EQUAL || rEntry.eOp == SC_NOT_EQUAL ) 748 { 749 if ( bMatchWholeCell ) 750 { 751 bOk = pTransliteration->isEqual( aCellStr, *rEntry.pStr ); 752 //Added by zhaosz,for sodc_2702,20060808 753 String aStr = *rEntry.pStr;//"f*" 754 //modified by weihuaw,for SODC_16698 755 //use another way to find "*" in aStr 756 sal_Bool bHasStar = sal_False; 757 xub_StrLen nIndex; 758 if( ( nIndex = aStr.Search('*') ) != STRING_NOTFOUND ) 759 bHasStar = sal_True; 760 if(bHasStar && (nIndex>0)) 761 { 762 for(i=0;(i<nIndex) && (i< aCellStr.Len()) ; i++) 763 { 764 if(aCellStr.GetChar( (sal_uInt16)i ) == aStr.GetChar((sal_uInt16) i )) 765 { 766 bOk=1; 767 } 768 else 769 { 770 bOk=0; 771 break; 772 } 773 } 774 } 775 //end modified 776 //Added end,20060808 777 } 778 else 779 { 780 ::com::sun::star::uno::Sequence< sal_Int32 > xOff; 781 String aCell( pTransliteration->transliterate( 782 aCellStr, ScGlobal::eLnge, 0, aCellStr.Len(), 783 &xOff ) ); 784 String aQuer( pTransliteration->transliterate( 785 *rEntry.pStr, ScGlobal::eLnge, 0, rEntry.pStr->Len(), 786 &xOff ) ); 787 bOk = (aCell.Search( aQuer ) != STRING_NOTFOUND); 788 } 789 if ( rEntry.eOp == SC_NOT_EQUAL ) 790 bOk = !bOk; 791 } 792 else 793 { // use collator here because data was probably sorted 794 sal_Int32 nCompare = pCollator->compareString( 795 aCellStr, *rEntry.pStr ); 796 switch (rEntry.eOp) 797 { 798 case SC_LESS : 799 bOk = (nCompare < 0); 800 break; 801 case SC_GREATER : 802 bOk = (nCompare > 0); 803 break; 804 case SC_LESS_EQUAL : 805 bOk = (nCompare <= 0); 806 break; 807 case SC_GREATER_EQUAL : 808 bOk = (nCompare >= 0); 809 break; 810 case SC_NOT_EQUAL: 811 DBG_ASSERT( false , "SC_NOT_EQUAL"); 812 break; 813 case SC_TOPVAL: 814 case SC_BOTVAL: 815 case SC_TOPPERC: 816 case SC_BOTPERC: 817 default: 818 break; 819 } 820 } 821 } 822 } 823 824 if (nPos == -1) 825 { 826 nPos++; 827 pPasst[nPos] = bOk; 828 pTest[nPos] = bTestEqual; 829 } 830 else 831 { 832 if (rEntry.eConnect == SC_AND) 833 { 834 pPasst[nPos] = pPasst[nPos] && bOk; 835 pTest[nPos] = pTest[nPos] && bTestEqual; 836 } 837 else 838 { 839 nPos++; 840 pPasst[nPos] = bOk; 841 pTest[nPos] = bTestEqual; 842 } 843 } 844 i++; 845 } 846 847 for ( long j=1; j <= nPos; j++ ) 848 { 849 pPasst[0] = pPasst[0] || pPasst[j]; 850 pTest[0] = pTest[0] || pTest[j]; 851 } 852 853 sal_Bool bRet = pPasst[0]; 854 if ( pPasst != &aBool[0] ) 855 delete [] pPasst; 856 if ( pTest != &aTest[0] ) 857 delete [] pTest; 858 859 return bRet; 860 } 861 862 // ----------------------------------------------------------------------- 863 bool ScDPTableDataCache::IsRowEmpty( SCROW nRow ) const 864 { 865 return mbEmptyRow[ nRow ]; 866 867 } 868 869 // ----------------------------------------------------------------------- 870 bool ScDPTableDataCache::IsEmptyMember( SCROW nRow, sal_uInt16 nColumn ) const 871 { 872 return !GetItemDataById( nColumn, GetItemDataId( nColumn, nRow, sal_False ) )->IsHasData(); 873 } 874 875 sal_Bool ScDPTableDataCache::AddData(long nDim, ScDPItemData* pitemData) 876 { 877 DBG_ASSERT( IsValid(), " IsValid() == false " ); 878 DBG_ASSERT( nDim < mnColumnCount && nDim >=0 , "dimension out of bound" ); 879 SCROW nIndex = 0; 880 881 sal_Bool bInserted = sal_False; 882 883 pitemData->SetDate( lcl_isDate( GetNumType( pitemData->nNumFormat ) ) ); 884 885 if ( !lcl_Search( mpTableDataValues[nDim], mpGlobalOrder[nDim], *pitemData, nIndex ) ) 886 { 887 mpTableDataValues[nDim].push_back( pitemData ); 888 mpGlobalOrder[nDim].insert( mpGlobalOrder[nDim].begin()+nIndex, mpTableDataValues[nDim].size()-1 ); 889 DBG_ASSERT( (size_t) mpGlobalOrder[nDim][nIndex] == mpTableDataValues[nDim].size()-1 ,"ScDPTableDataCache::AddData "); 890 mpSourceData[nDim].push_back( mpTableDataValues[nDim].size()-1 ); 891 bInserted = sal_True; 892 } 893 else 894 mpSourceData[nDim].push_back( mpGlobalOrder[nDim][nIndex] ); 895 //init empty row tag 896 size_t nCurRow = mpSourceData[nDim].size() -1 ; 897 898 while ( mbEmptyRow.size() <= nCurRow ) 899 mbEmptyRow.push_back( sal_True ); 900 901 if ( pitemData->IsHasData() ) 902 mbEmptyRow[ nCurRow ] = sal_False; 903 904 if ( !bInserted ) 905 delete pitemData; 906 907 return sal_True; 908 } 909 910 911 String ScDPTableDataCache::GetDimensionName( sal_uInt16 nColumn ) const 912 { 913 DBG_ASSERT( /* nColumn>=0 && */ nColumn < mrLabelNames.size()-1 , "ScDPTableDataCache::GetDimensionName"); 914 DBG_ASSERT( mrLabelNames.size() == static_cast <sal_uInt16> (mnColumnCount+1), "ScDPTableDataCache::GetDimensionName"); 915 if ( static_cast<size_t>(nColumn+1) < mrLabelNames.size() ) 916 { 917 return mrLabelNames[nColumn+1]->aString; 918 } 919 else 920 return String(); 921 } 922 923 void ScDPTableDataCache::AddLabel(ScDPItemData *pData) 924 { 925 DBG_ASSERT( IsValid(), " IsValid() == false " ); 926 927 if ( mrLabelNames.size() == 0 ) 928 mrLabelNames.push_back( new ScDPItemData( ScGlobal::GetRscString(STR_PIVOT_DATA) ) ); 929 930 931 //reset name if needed 932 String strNewName = pData->aString; 933 934 // #i116457# don't modify empty column titles 935 if ( strNewName.Len() ) 936 { 937 sal_Bool bFound = sal_False; 938 long nIndex = 1; 939 do 940 { 941 for ( long i= mrLabelNames.size()-1; i>=0; i-- ) 942 { 943 if( mrLabelNames[i]->aString == strNewName ) 944 { 945 strNewName = pData->aString; 946 strNewName += String::CreateFromInt32( nIndex ); 947 nIndex ++ ; 948 bFound = sal_True; 949 } 950 } 951 bFound = !bFound; 952 } 953 while ( !bFound ); 954 } 955 956 pData->aString = strNewName; 957 mrLabelNames.push_back( pData ); 958 } 959 960 SCROW ScDPTableDataCache::GetItemDataId(sal_uInt16 nDim, SCROW nRow, sal_Bool bRepeatIfEmpty) const 961 { // 962 DBG_ASSERT( IsValid(), " IsValid() == false " ); 963 DBG_ASSERT( /* nDim >= 0 && */ nDim < mnColumnCount, "ScDPTableDataCache::GetItemDataId " ); 964 965 if ( bRepeatIfEmpty ) 966 { 967 while ( nRow >0 && !mpTableDataValues[nDim][ mpSourceData[nDim][nRow] ]->IsHasData() ) 968 --nRow; 969 } 970 971 return mpSourceData[nDim][nRow]; 972 } 973 974 const ScDPItemData* ScDPTableDataCache::GetItemDataById(long nDim, SCROW nId) const 975 { 976 if ( nId >= GetRowCount() ) 977 return maAdditionalDatas.getData( nId - GetRowCount() ); 978 979 if ( (size_t)nId >= mpTableDataValues[nDim].size() || nDim >= mnColumnCount || nId < 0 ) 980 return NULL; 981 else 982 return mpTableDataValues[nDim][nId]; 983 } 984 985 SCROW ScDPTableDataCache::GetRowCount() const 986 { 987 if ( IsValid() ) 988 return mpSourceData[0].size(); 989 else 990 return 0; 991 } 992 993 const std::vector<ScDPItemData*>& ScDPTableDataCache::GetDimMemberValues(SCCOL nDim) const 994 { 995 DBG_ASSERT( nDim>=0 && nDim < mnColumnCount ," nDim < mnColumnCount "); 996 return mpTableDataValues[nDim]; 997 } 998 999 SCROW ScDPTableDataCache::GetSortedItemDataId(SCCOL nDim, SCROW nOrder) const 1000 { 1001 DBG_ASSERT ( IsValid(), "IsValid"); 1002 DBG_ASSERT( nDim>=0 && nDim < mnColumnCount, "nDim < mnColumnCount"); 1003 DBG_ASSERT( nOrder >= 0 && (size_t) nOrder < mpGlobalOrder[nDim].size(), "nOrder < mpGlobalOrder[nDim].size()" ); 1004 1005 return mpGlobalOrder[nDim][nOrder]; 1006 } 1007 1008 sal_uLong ScDPTableDataCache::GetNumType(sal_uLong nFormat) const 1009 { 1010 SvNumberFormatter* pFormatter = mpDoc->GetFormatTable(); 1011 sal_uLong nType = NUMBERFORMAT_NUMBER; 1012 if ( pFormatter ) 1013 nType = pFormatter->GetType( nFormat ); 1014 return nType; 1015 } 1016 1017 sal_uLong ScDPTableDataCache::GetNumberFormat( long nDim ) const 1018 { 1019 if ( nDim >= mnColumnCount ) 1020 return 0; 1021 1022 // #i113411# take the number format from the first value entry 1023 size_t nSize = mpTableDataValues[nDim].size(); 1024 size_t nPos = 0; 1025 while ( nPos < nSize && mpTableDataValues[nDim][nPos]->GetType() != SC_VALTYPE_VALUE ) 1026 ++nPos; 1027 if ( nPos < nSize ) 1028 return mpTableDataValues[nDim][nPos]->nNumFormat; 1029 return 0; 1030 } 1031 1032 sal_Bool ScDPTableDataCache::IsDateDimension( long nDim ) const 1033 { 1034 if ( nDim >= mnColumnCount ) 1035 return false; 1036 else if ( mpTableDataValues[nDim].size()==0 ) 1037 return false; 1038 else 1039 return mpTableDataValues[nDim][0]->IsDate(); 1040 1041 } 1042 1043 SCROW ScDPTableDataCache::GetDimMemberCount( SCCOL nDim ) const 1044 { 1045 DBG_ASSERT( nDim>=0 && nDim < mnColumnCount ," ScDPTableDataCache::GetDimMemberCount : out of bound "); 1046 return mpTableDataValues[nDim].size(); 1047 } 1048 1049 const ScDPItemData* ScDPTableDataCache::GetSortedItemData(SCCOL nDim, SCROW nOrder) const 1050 { 1051 SCROW n = GetSortedItemDataId( nDim, nOrder ); 1052 return GetItemDataById( nDim, n ); 1053 } 1054 1055 SCCOL ScDPTableDataCache::GetDimensionIndex(String sName) const 1056 { 1057 for ( size_t n = 1; n < mrLabelNames.size(); n ++ ) //defects, label name map wrong SODC_17590, SODC_18932,SODC_18827,SODC_18960,SODC_18923 1058 { 1059 if ( mrLabelNames[n]->GetString() == sName ) 1060 return (SCCOL)(n-1); 1061 } 1062 return -1; 1063 } 1064 1065 SCROW ScDPTableDataCache::GetIdByItemData(long nDim, String sItemData ) const 1066 { 1067 if ( nDim < mnColumnCount && nDim >=0 ) 1068 { 1069 for ( size_t n = 0; n< mpTableDataValues[nDim].size(); n++ ) 1070 { 1071 if ( mpTableDataValues[nDim][n]->GetString() == sItemData ) 1072 return n; 1073 } 1074 } 1075 1076 ScDPItemData rData ( sItemData ); 1077 return GetRowCount() +maAdditionalDatas.getDataId(rData); 1078 } 1079 1080 SCROW ScDPTableDataCache::GetIdByItemData( long nDim, const ScDPItemData& rData ) const 1081 { 1082 if ( nDim < mnColumnCount && nDim >=0 ) 1083 { 1084 for ( size_t n = 0; n< mpTableDataValues[nDim].size(); n++ ) 1085 { 1086 if ( *mpTableDataValues[nDim][n] == rData ) 1087 return n; 1088 } 1089 } 1090 return GetRowCount() + maAdditionalDatas.getDataId(rData); 1091 } 1092 1093 SCROW ScDPTableDataCache::GetAdditionalItemID ( String sItemData ) 1094 { 1095 ScDPItemData rData ( sItemData ); 1096 return GetAdditionalItemID( rData ); 1097 } 1098 1099 SCROW ScDPTableDataCache::GetAdditionalItemID( const ScDPItemData& rData ) 1100 { 1101 return GetRowCount() + maAdditionalDatas.insertData( rData ); 1102 } 1103 1104 1105 SCROW ScDPTableDataCache::GetOrder(long nDim, SCROW nIndex) const 1106 { 1107 DBG_ASSERT( IsValid(), " IsValid() == false " ); 1108 DBG_ASSERT( nDim >=0 && nDim < mnColumnCount, "ScDPTableDataCache::GetOrder : out of bound" ); 1109 1110 if ( mpIndexOrder[nDim].size() != mpGlobalOrder[nDim].size() ) 1111 { //not inited 1112 SCROW i = 0; 1113 mpIndexOrder[nDim].resize( mpGlobalOrder[nDim].size(), 0 ); 1114 for ( size_t n = 0 ; n< mpGlobalOrder[nDim].size(); n++ ) 1115 { 1116 i = mpGlobalOrder[nDim][n]; 1117 mpIndexOrder[nDim][ i ] = n; 1118 } 1119 } 1120 1121 DBG_ASSERT( nIndex>=0 && (size_t)nIndex < mpIndexOrder[nDim].size() , "ScDPTableDataCache::GetOrder"); 1122 return mpIndexOrder[nDim][nIndex]; 1123 } 1124 1125 ScDocument* ScDPTableDataCache::GetDoc() const 1126 { 1127 return mpDoc; 1128 }; 1129 1130 long ScDPTableDataCache::GetColumnCount() const 1131 { 1132 return mnColumnCount; 1133 } 1134 long ScDPTableDataCache::GetId() const 1135 { 1136 return mnID; 1137 } 1138 1139