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 // MARKER(update_precomp.py): autogen include statement, do not remove 25 #include "precompiled_sc.hxx" 26 27 28 29 // INCLUDE --------------------------------------------------------------- 30 31 #include "dpsave.hxx" 32 #include "dpdimsave.hxx" 33 #include "dpobject.hxx" // GetMemberNames used in BuildAllDimensionMembersFromSource 34 #include "miscuno.hxx" 35 #include "scerrors.hxx" 36 #include "unonames.hxx" 37 #include "global.hxx" 38 39 #include <tools/debug.hxx> 40 41 #include <com/sun/star/sheet/GeneralFunction.hpp> 42 #include <com/sun/star/sheet/DataPilotFieldAutoShowInfo.hpp> 43 #include <com/sun/star/sheet/DataPilotFieldLayoutInfo.hpp> 44 #include <com/sun/star/sheet/DataPilotFieldOrientation.hpp> 45 #include <com/sun/star/sheet/DataPilotFieldReference.hpp> 46 #include <com/sun/star/sheet/DataPilotFieldSortInfo.hpp> 47 #include <com/sun/star/sheet/DataPilotFieldSortMode.hpp> 48 #include <com/sun/star/sheet/TableFilterField.hpp> 49 #include <com/sun/star/sheet/XHierarchiesSupplier.hpp> 50 #include <com/sun/star/sheet/XLevelsSupplier.hpp> 51 #include <com/sun/star/sheet/XMembersSupplier.hpp> 52 #include <com/sun/star/container/XNamed.hpp> 53 #include <com/sun/star/util/XCloneable.hpp> 54 // Wang Xu Ming -- 2009-8-17 55 // DataPilot Migration - Cache&&Performance 56 #include "dptabsrc.hxx" 57 #include "dpglobal.hxx" 58 using namespace ScDPGlobal; 59 #ifndef _COM_SUN_STAR_SHEET_DATAPILOTFIELDREFERENCETYPE_HPP_ 60 #include <com/sun/star/sheet/DataPilotFieldReferenceType.hpp> 61 #endif 62 #ifndef _COM_SUN_STAR_SHEET_DATAPILOTFIELDREFERENCEITEMTYPE_HPP_ 63 #include <com/sun/star/sheet/DataPilotFieldReferenceItemType.hpp> 64 #endif 65 using namespace com::sun::star::sheet; 66 // End Comments 67 68 #include <hash_map> 69 70 using namespace com::sun::star; 71 using ::com::sun::star::uno::Reference; 72 using ::com::sun::star::uno::Any; 73 using ::rtl::OUString; 74 using ::rtl::OUStringHash; 75 using ::std::hash_map; 76 using ::std::auto_ptr; 77 78 // ----------------------------------------------------------------------- 79 80 #define SC_DPSAVEMODE_NO 0 81 #define SC_DPSAVEMODE_YES 1 82 #define SC_DPSAVEMODE_DONTKNOW 2 83 84 // ----------------------------------------------------------------------- 85 86 void lcl_SetBoolProperty( const uno::Reference<beans::XPropertySet>& xProp, 87 const rtl::OUString& rName, sal_Bool bValue ) 88 { 89 //! move to ScUnoHelpFunctions? 90 91 xProp->setPropertyValue( rName, uno::Any( &bValue, getBooleanCppuType() ) ); 92 } 93 94 // ----------------------------------------------------------------------- 95 96 ScDPSaveMember::ScDPSaveMember(const String& rName) : 97 aName( rName ), 98 mpLayoutName(NULL), 99 nVisibleMode( SC_DPSAVEMODE_DONTKNOW ), 100 nShowDetailsMode( SC_DPSAVEMODE_DONTKNOW ) 101 { 102 } 103 104 ScDPSaveMember::ScDPSaveMember(const ScDPSaveMember& r) : 105 aName( r.aName ), 106 mpLayoutName(NULL), 107 nVisibleMode( r.nVisibleMode ), 108 nShowDetailsMode( r.nShowDetailsMode ) 109 { 110 if (r.mpLayoutName.get()) 111 mpLayoutName.reset(new OUString(*r.mpLayoutName)); 112 } 113 114 ScDPSaveMember::~ScDPSaveMember() 115 { 116 } 117 118 sal_Bool ScDPSaveMember::operator== ( const ScDPSaveMember& r ) const 119 { 120 if ( aName != r.aName || 121 nVisibleMode != r.nVisibleMode || 122 nShowDetailsMode != r.nShowDetailsMode ) 123 return sal_False; 124 125 return sal_True; 126 } 127 128 sal_Bool ScDPSaveMember::HasIsVisible() const 129 { 130 return nVisibleMode != SC_DPSAVEMODE_DONTKNOW; 131 } 132 133 void ScDPSaveMember::SetIsVisible(sal_Bool bSet) 134 { 135 nVisibleMode = bSet; 136 } 137 138 sal_Bool ScDPSaveMember::HasShowDetails() const 139 { 140 return nShowDetailsMode != SC_DPSAVEMODE_DONTKNOW; 141 } 142 143 void ScDPSaveMember::SetShowDetails(sal_Bool bSet) 144 { 145 nShowDetailsMode = bSet; 146 } 147 148 void ScDPSaveMember::SetName( const String& rNew ) 149 { 150 // Used only if the source member was renamed (groups). 151 // For UI renaming of members, a layout name must be used. 152 153 aName = rNew; 154 } 155 156 void ScDPSaveMember::SetLayoutName( const OUString& rName ) 157 { 158 mpLayoutName.reset(new OUString(rName)); 159 } 160 161 const OUString* ScDPSaveMember::GetLayoutName() const 162 { 163 return mpLayoutName.get(); 164 } 165 166 void ScDPSaveMember::RemoveLayoutName() 167 { 168 mpLayoutName.reset(NULL); 169 } 170 171 void ScDPSaveMember::WriteToSource( const uno::Reference<uno::XInterface>& xMember, sal_Int32 nPosition ) 172 { 173 uno::Reference<beans::XPropertySet> xMembProp( xMember, uno::UNO_QUERY ); 174 DBG_ASSERT( xMembProp.is(), "no properties at member" ); 175 if ( xMembProp.is() ) 176 { 177 // exceptions are caught at ScDPSaveData::WriteToSource 178 179 if ( nVisibleMode != SC_DPSAVEMODE_DONTKNOW ) 180 lcl_SetBoolProperty( xMembProp, 181 rtl::OUString::createFromAscii(DP_PROP_ISVISIBLE), (sal_Bool)nVisibleMode ); 182 183 if ( nShowDetailsMode != SC_DPSAVEMODE_DONTKNOW ) 184 lcl_SetBoolProperty( xMembProp, 185 rtl::OUString::createFromAscii(DP_PROP_SHOWDETAILS), (sal_Bool)nShowDetailsMode ); 186 187 if (mpLayoutName.get()) 188 ScUnoHelpFunctions::SetOptionalPropertyValue(xMembProp, SC_UNO_LAYOUTNAME, *mpLayoutName); 189 190 if ( nPosition >= 0 ) 191 ScUnoHelpFunctions::SetOptionalPropertyValue(xMembProp, DP_PROP_POSITION, nPosition); 192 } 193 } 194 195 // ----------------------------------------------------------------------- 196 197 ScDPSaveDimension::ScDPSaveDimension(const String& rName, sal_Bool bDataLayout) : 198 aName( rName ), 199 pSelectedPage( NULL ), 200 mpLayoutName(NULL), 201 mpSubtotalName(NULL), 202 bIsDataLayout( bDataLayout ), 203 bDupFlag( sal_False ), 204 nOrientation( sheet::DataPilotFieldOrientation_HIDDEN ), 205 nFunction( sheet::GeneralFunction_AUTO ), 206 nUsedHierarchy( -1 ), 207 nShowEmptyMode( SC_DPSAVEMODE_DONTKNOW ), 208 bSubTotalDefault( sal_True ), 209 nSubTotalCount( 0 ), 210 pSubTotalFuncs( NULL ), 211 pReferenceValue( NULL ), 212 pSortInfo( NULL ), 213 pAutoShowInfo( NULL ), 214 pLayoutInfo( NULL ) 215 { 216 } 217 218 ScDPSaveDimension::ScDPSaveDimension(const ScDPSaveDimension& r) : 219 aName( r.aName ), 220 mpLayoutName(NULL), 221 mpSubtotalName(NULL), 222 bIsDataLayout( r.bIsDataLayout ), 223 bDupFlag( r.bDupFlag ), 224 nOrientation( r.nOrientation ), 225 nFunction( r.nFunction ), 226 nUsedHierarchy( r.nUsedHierarchy ), 227 nShowEmptyMode( r.nShowEmptyMode ), 228 bSubTotalDefault( r.bSubTotalDefault ), 229 nSubTotalCount( r.nSubTotalCount ), 230 pSubTotalFuncs( NULL ) 231 { 232 if ( nSubTotalCount && r.pSubTotalFuncs ) 233 { 234 pSubTotalFuncs = new sal_uInt16[nSubTotalCount]; 235 for (long nSub=0; nSub<nSubTotalCount; nSub++) 236 pSubTotalFuncs[nSub] = r.pSubTotalFuncs[nSub]; 237 } 238 239 for (MemberList::const_iterator i=r.maMemberList.begin(); i != r.maMemberList.end() ; i++) 240 { 241 const String& rName = (*i)->GetName(); 242 ScDPSaveMember* pNew = new ScDPSaveMember( **i ); 243 maMemberHash[rName] = pNew; 244 maMemberList.push_back( pNew ); 245 } 246 if (r.pReferenceValue) 247 pReferenceValue = new sheet::DataPilotFieldReference( *(r.pReferenceValue) ); 248 else 249 pReferenceValue = NULL; 250 if (r.pSortInfo) 251 pSortInfo = new sheet::DataPilotFieldSortInfo( *(r.pSortInfo) ); 252 else 253 pSortInfo = NULL; 254 if (r.pAutoShowInfo) 255 pAutoShowInfo = new sheet::DataPilotFieldAutoShowInfo( *(r.pAutoShowInfo) ); 256 else 257 pAutoShowInfo = NULL; 258 if (r.pLayoutInfo) 259 pLayoutInfo = new sheet::DataPilotFieldLayoutInfo( *(r.pLayoutInfo) ); 260 else 261 pLayoutInfo = NULL; 262 if (r.pSelectedPage) 263 pSelectedPage = new String( *(r.pSelectedPage) ); 264 else 265 pSelectedPage = NULL; 266 if (r.mpLayoutName.get()) 267 mpLayoutName.reset(new OUString(*r.mpLayoutName)); 268 if (r.mpSubtotalName.get()) 269 mpSubtotalName.reset(new OUString(*r.mpSubtotalName)); 270 } 271 272 ScDPSaveDimension::~ScDPSaveDimension() 273 { 274 for (MemberHash::const_iterator i=maMemberHash.begin(); i != maMemberHash.end() ; i++) 275 delete i->second; 276 delete pReferenceValue; 277 delete pSortInfo; 278 delete pAutoShowInfo; 279 delete pLayoutInfo; 280 delete pSelectedPage; 281 delete [] pSubTotalFuncs; 282 } 283 284 sal_Bool ScDPSaveDimension::operator== ( const ScDPSaveDimension& r ) const 285 { 286 if ( aName != r.aName || 287 bIsDataLayout != r.bIsDataLayout || 288 bDupFlag != r.bDupFlag || 289 nOrientation != r.nOrientation || 290 nFunction != r.nFunction || 291 nUsedHierarchy != r.nUsedHierarchy || 292 nShowEmptyMode != r.nShowEmptyMode || 293 bSubTotalDefault != r.bSubTotalDefault || 294 nSubTotalCount != r.nSubTotalCount ) 295 return sal_False; 296 297 if ( nSubTotalCount && ( !pSubTotalFuncs || !r.pSubTotalFuncs ) ) // should not happen 298 return sal_False; 299 300 long i; 301 for (i=0; i<nSubTotalCount; i++) 302 if ( pSubTotalFuncs[i] != r.pSubTotalFuncs[i] ) 303 return sal_False; 304 305 if (maMemberHash.size() != r.maMemberHash.size() ) 306 return sal_False; 307 308 MemberList::const_iterator a=maMemberList.begin(); 309 MemberList::const_iterator b=r.maMemberList.begin(); 310 for (; a != maMemberList.end() ; ++a, ++b) 311 if (!(**a == **b)) 312 return sal_False; 313 314 if ( this->HasCurrentPage() && r.HasCurrentPage() ) 315 { 316 if ( this->GetCurrentPage() != r.GetCurrentPage() ) 317 { 318 return sal_False; 319 } 320 } 321 else if ( this->HasCurrentPage() || r.HasCurrentPage() ) 322 { 323 return sal_False; 324 } 325 if( pReferenceValue && r.pReferenceValue ) 326 { 327 if ( !(*pReferenceValue == *r.pReferenceValue) ) 328 { 329 return sal_False; 330 } 331 } 332 else if ( pReferenceValue || r.pReferenceValue ) 333 { 334 return sal_False; 335 } 336 if( this->pSortInfo && r.pSortInfo ) 337 { 338 if ( !(*this->pSortInfo == *r.pSortInfo) ) 339 { 340 return sal_False; 341 } 342 } 343 else if ( this->pSortInfo || r.pSortInfo ) 344 { 345 return sal_False; 346 } 347 if( this->pAutoShowInfo && r.pAutoShowInfo ) 348 { 349 if ( !(*this->pAutoShowInfo == *r.pAutoShowInfo) ) 350 { 351 return sal_False; 352 } 353 } 354 else if ( this->pAutoShowInfo || r.pAutoShowInfo ) 355 { 356 return sal_False; 357 } 358 359 return sal_True; 360 } 361 362 void ScDPSaveDimension::AddMember(ScDPSaveMember* pMember) 363 { 364 const String & rName = pMember->GetName(); 365 MemberHash::iterator aExisting = maMemberHash.find( rName ); 366 if ( aExisting == maMemberHash.end() ) 367 { 368 std::pair< const String, ScDPSaveMember *> key( rName, pMember ); 369 maMemberHash.insert ( key ); 370 } 371 else 372 { 373 maMemberList.remove( aExisting->second ); 374 delete aExisting->second; 375 aExisting->second = pMember; 376 } 377 maMemberList.push_back( pMember ); 378 } 379 380 void ScDPSaveDimension::SetName( const String& rNew ) 381 { 382 // Used only if the source dim was renamed (groups). 383 // For UI renaming of dimensions, the layout name must be used. 384 385 aName = rNew; 386 } 387 388 void ScDPSaveDimension::SetOrientation(sal_uInt16 nNew) 389 { 390 nOrientation = nNew; 391 } 392 393 void ScDPSaveDimension::SetSubTotals(long nCount, const sal_uInt16* pFuncs) 394 { 395 if (pSubTotalFuncs) 396 delete [] pSubTotalFuncs; 397 nSubTotalCount = nCount; 398 if ( nCount && pFuncs ) 399 { 400 pSubTotalFuncs = new sal_uInt16[nCount]; 401 for (long i=0; i<nCount; i++) 402 pSubTotalFuncs[i] = pFuncs[i]; 403 } 404 else 405 pSubTotalFuncs = NULL; 406 407 bSubTotalDefault = sal_False; 408 } 409 410 bool ScDPSaveDimension::HasShowEmpty() const 411 { 412 return nShowEmptyMode != SC_DPSAVEMODE_DONTKNOW; 413 } 414 415 void ScDPSaveDimension::SetShowEmpty(sal_Bool bSet) 416 { 417 nShowEmptyMode = bSet; 418 } 419 420 void ScDPSaveDimension::SetFunction(sal_uInt16 nNew) 421 { 422 nFunction = nNew; 423 } 424 425 void ScDPSaveDimension::SetUsedHierarchy(long nNew) 426 { 427 nUsedHierarchy = nNew; 428 } 429 430 void ScDPSaveDimension::SetSubtotalName(const OUString& rName) 431 { 432 mpSubtotalName.reset(new OUString(rName)); 433 } 434 435 const OUString* ScDPSaveDimension::GetSubtotalName() const 436 { 437 return mpSubtotalName.get(); 438 } 439 440 bool ScDPSaveDimension::IsMemberNameInUse(const OUString& rName) const 441 { 442 MemberList::const_iterator itr = maMemberList.begin(), itrEnd = maMemberList.end(); 443 for (; itr != itrEnd; ++itr) 444 { 445 const ScDPSaveMember* pMem = *itr; 446 if (rName.equalsIgnoreAsciiCase(pMem->GetName())) 447 return true; 448 449 const OUString* pLayoutName = pMem->GetLayoutName(); 450 if (pLayoutName && rName.equalsIgnoreAsciiCase(*pLayoutName)) 451 return true; 452 } 453 return false; 454 } 455 456 void ScDPSaveDimension::SetLayoutName(const OUString& rName) 457 { 458 mpLayoutName.reset(new OUString(rName)); 459 } 460 461 const OUString* ScDPSaveDimension::GetLayoutName() const 462 { 463 return mpLayoutName.get(); 464 } 465 466 void ScDPSaveDimension::RemoveLayoutName() 467 { 468 mpLayoutName.reset(NULL); 469 } 470 471 void ScDPSaveDimension::SetReferenceValue(const sheet::DataPilotFieldReference* pNew) 472 { 473 delete pReferenceValue; 474 if (pNew) 475 pReferenceValue = new sheet::DataPilotFieldReference(*pNew); 476 else 477 pReferenceValue = NULL; 478 } 479 480 void ScDPSaveDimension::SetSortInfo(const sheet::DataPilotFieldSortInfo* pNew) 481 { 482 delete pSortInfo; 483 if (pNew) 484 pSortInfo = new sheet::DataPilotFieldSortInfo(*pNew); 485 else 486 pSortInfo = NULL; 487 } 488 489 void ScDPSaveDimension::SetAutoShowInfo(const sheet::DataPilotFieldAutoShowInfo* pNew) 490 { 491 delete pAutoShowInfo; 492 if (pNew) 493 pAutoShowInfo = new sheet::DataPilotFieldAutoShowInfo(*pNew); 494 else 495 pAutoShowInfo = NULL; 496 } 497 498 void ScDPSaveDimension::SetLayoutInfo(const sheet::DataPilotFieldLayoutInfo* pNew) 499 { 500 delete pLayoutInfo; 501 if (pNew) 502 pLayoutInfo = new sheet::DataPilotFieldLayoutInfo(*pNew); 503 else 504 pLayoutInfo = NULL; 505 } 506 507 void ScDPSaveDimension::SetCurrentPage( const String* pPage ) 508 { 509 delete pSelectedPage; 510 if (pPage) 511 pSelectedPage = new String( *pPage ); 512 else 513 pSelectedPage = NULL; 514 } 515 516 sal_Bool ScDPSaveDimension::HasCurrentPage() const 517 { 518 return ( pSelectedPage != NULL ); 519 } 520 521 const String& ScDPSaveDimension::GetCurrentPage() const 522 { 523 if (pSelectedPage) 524 return *pSelectedPage; 525 return EMPTY_STRING; 526 } 527 528 ScDPSaveMember* ScDPSaveDimension::GetExistingMemberByName(const String& rName) 529 { 530 MemberHash::const_iterator res = maMemberHash.find (rName); 531 if (res != maMemberHash.end()) 532 return res->second; 533 return NULL; 534 } 535 536 537 ScDPSaveMember* ScDPSaveDimension::GetMemberByName(const String& rName) 538 { 539 MemberHash::const_iterator res = maMemberHash.find (rName); 540 if (res != maMemberHash.end()) 541 return res->second; 542 543 ScDPSaveMember* pNew = new ScDPSaveMember( rName ); 544 maMemberHash[rName] = pNew; 545 maMemberList.push_back( pNew ); 546 return pNew; 547 } 548 549 void ScDPSaveDimension::SetMemberPosition( const String& rName, sal_Int32 nNewPos ) 550 { 551 ScDPSaveMember* pMember = GetMemberByName( rName ); // make sure it exists and is in the hash 552 553 maMemberList.remove( pMember ); 554 555 MemberList::iterator aIter = maMemberList.begin(); 556 for (sal_Int32 i=0; i<nNewPos && aIter != maMemberList.end(); i++) 557 ++aIter; 558 maMemberList.insert( aIter, pMember ); 559 } 560 561 void ScDPSaveDimension::WriteToSource( const uno::Reference<uno::XInterface>& xDim ) 562 { 563 uno::Reference<beans::XPropertySet> xDimProp( xDim, uno::UNO_QUERY ); 564 DBG_ASSERT( xDimProp.is(), "no properties at dimension" ); 565 if ( xDimProp.is() ) 566 { 567 // exceptions are caught at ScDPSaveData::WriteToSource 568 uno::Any aAny; 569 570 sheet::DataPilotFieldOrientation eOrient = (sheet::DataPilotFieldOrientation)nOrientation; 571 aAny <<= eOrient; 572 xDimProp->setPropertyValue( rtl::OUString::createFromAscii(DP_PROP_ORIENTATION), aAny ); 573 574 sheet::GeneralFunction eFunc = (sheet::GeneralFunction)nFunction; 575 aAny <<= eFunc; 576 xDimProp->setPropertyValue( rtl::OUString::createFromAscii(DP_PROP_FUNCTION), aAny ); 577 578 if ( nUsedHierarchy >= 0 ) 579 { 580 aAny <<= (sal_Int32)nUsedHierarchy; 581 xDimProp->setPropertyValue( rtl::OUString::createFromAscii(DP_PROP_USEDHIERARCHY), aAny ); 582 } 583 584 if ( pReferenceValue ) 585 { 586 aAny <<= *pReferenceValue; 587 xDimProp->setPropertyValue( rtl::OUString::createFromAscii(SC_UNO_REFVALUE), aAny ); 588 } 589 590 uno::Sequence<sheet::TableFilterField> aFilter; 591 // set the selected page field only if the dimension is used as page dimension 592 if ( pSelectedPage && nOrientation == sheet::DataPilotFieldOrientation_PAGE ) 593 { 594 // single filter field: first field equal to selected string 595 sheet::TableFilterField aField( sheet::FilterConnection_AND, 0, 596 sheet::FilterOperator_EQUAL, sal_False, 0.0, *pSelectedPage ); 597 aFilter = uno::Sequence<sheet::TableFilterField>( &aField, 1 ); 598 } 599 // else keep empty sequence 600 601 ScUnoHelpFunctions::SetOptionalPropertyValue(xDimProp, DP_PROP_FILTER, aFilter); 602 if (mpLayoutName.get()) 603 ScUnoHelpFunctions::SetOptionalPropertyValue(xDimProp, SC_UNO_LAYOUTNAME, *mpLayoutName); 604 605 const OUString* pSubTotalName = GetSubtotalName(); 606 if (pSubTotalName) 607 // Custom subtotal name, with '?' being replaced by the visible field name later. 608 ScUnoHelpFunctions::SetOptionalPropertyValue(xDimProp, SC_UNO_FIELD_SUBTOTALNAME, *pSubTotalName); 609 } 610 611 // Level loop outside of maMemberList loop 612 // because SubTotals have to be set independently of known members 613 614 long nCount = maMemberHash.size(); 615 616 long nHierCount = 0; 617 uno::Reference<container::XIndexAccess> xHiers; 618 uno::Reference<sheet::XHierarchiesSupplier> xHierSupp( xDim, uno::UNO_QUERY ); 619 if ( xHierSupp.is() ) 620 { 621 uno::Reference<container::XNameAccess> xHiersName = xHierSupp->getHierarchies(); 622 xHiers = new ScNameToIndexAccess( xHiersName ); 623 nHierCount = xHiers->getCount(); 624 } 625 626 sal_Bool bHasHiddenMember = false; 627 628 for (long nHier=0; nHier<nHierCount; nHier++) 629 { 630 uno::Reference<uno::XInterface> xHierarchy = ScUnoHelpFunctions::AnyToInterface( xHiers->getByIndex(nHier) ); 631 632 long nLevCount = 0; 633 uno::Reference<container::XIndexAccess> xLevels; 634 uno::Reference<sheet::XLevelsSupplier> xLevSupp( xHierarchy, uno::UNO_QUERY ); 635 if ( xLevSupp.is() ) 636 { 637 uno::Reference<container::XNameAccess> xLevelsName = xLevSupp->getLevels(); 638 xLevels = new ScNameToIndexAccess( xLevelsName ); 639 nLevCount = xLevels->getCount(); 640 } 641 642 for (long nLev=0; nLev<nLevCount; nLev++) 643 { 644 uno::Reference<uno::XInterface> xLevel = ScUnoHelpFunctions::AnyToInterface( xLevels->getByIndex(nLev) ); 645 uno::Reference<beans::XPropertySet> xLevProp( xLevel, uno::UNO_QUERY ); 646 DBG_ASSERT( xLevProp.is(), "no properties at level" ); 647 if ( xLevProp.is() ) 648 { 649 uno::Any aAny; 650 if ( !bSubTotalDefault ) 651 { 652 if ( !pSubTotalFuncs ) 653 nSubTotalCount = 0; 654 655 uno::Sequence<sheet::GeneralFunction> aSeq(nSubTotalCount); 656 sheet::GeneralFunction* pArray = aSeq.getArray(); 657 for (long i=0; i<nSubTotalCount; i++) 658 pArray[i] = (sheet::GeneralFunction)pSubTotalFuncs[i]; 659 aAny <<= aSeq; 660 xLevProp->setPropertyValue( rtl::OUString::createFromAscii(DP_PROP_SUBTOTALS), aAny ); 661 } 662 if ( nShowEmptyMode != SC_DPSAVEMODE_DONTKNOW ) 663 lcl_SetBoolProperty( xLevProp, 664 rtl::OUString::createFromAscii(DP_PROP_SHOWEMPTY), (sal_Bool)nShowEmptyMode ); 665 666 if ( pSortInfo ) 667 ScUnoHelpFunctions::SetOptionalPropertyValue(xLevProp, SC_UNO_SORTING, *pSortInfo); 668 669 if ( pAutoShowInfo ) 670 ScUnoHelpFunctions::SetOptionalPropertyValue(xLevProp, SC_UNO_AUTOSHOW, *pAutoShowInfo); 671 672 if ( pLayoutInfo ) 673 ScUnoHelpFunctions::SetOptionalPropertyValue(xLevProp, SC_UNO_LAYOUT, *pLayoutInfo); 674 675 // exceptions are caught at ScDPSaveData::WriteToSource 676 } 677 678 if ( nCount > 0 ) 679 { 680 uno::Reference<sheet::XMembersSupplier> xMembSupp( xLevel, uno::UNO_QUERY ); 681 if ( xMembSupp.is() ) 682 { 683 uno::Reference<container::XNameAccess> xMembers = xMembSupp->getMembers(); 684 if ( xMembers.is() ) 685 { 686 sal_Int32 nPosition = -1; // set position only in manual mode 687 if ( !pSortInfo || pSortInfo->Mode == sheet::DataPilotFieldSortMode::MANUAL ) 688 nPosition = 0; 689 690 for (MemberList::const_iterator i=maMemberList.begin(); i != maMemberList.end() ; i++) 691 { 692 ScDPSaveMember* pMember = *i; 693 if (!pMember->GetIsVisible()) 694 bHasHiddenMember = true; 695 rtl::OUString aMemberName = pMember->GetName(); 696 if ( xMembers->hasByName( aMemberName ) ) 697 { 698 uno::Reference<uno::XInterface> xMemberInt = ScUnoHelpFunctions::AnyToInterface( 699 xMembers->getByName( aMemberName ) ); 700 pMember->WriteToSource( xMemberInt, nPosition ); 701 702 if ( nPosition >= 0 ) 703 ++nPosition; // increase if initialized 704 } 705 // missing member is no error 706 } 707 } 708 } 709 } 710 } 711 } 712 713 if (xDimProp.is()) 714 ScUnoHelpFunctions::SetOptionalPropertyValue(xDimProp, SC_UNO_HAS_HIDDEN_MEMBER, bHasHiddenMember); 715 } 716 717 void ScDPSaveDimension::UpdateMemberVisibility(const hash_map<OUString, bool, OUStringHash>& rData) 718 { 719 typedef hash_map<OUString, bool, OUStringHash> DataMap; 720 MemberList::iterator itrMem = maMemberList.begin(), itrMemEnd = maMemberList.end(); 721 for (; itrMem != itrMemEnd; ++itrMem) 722 { 723 ScDPSaveMember* pMem = *itrMem; 724 const String& rMemName = pMem->GetName(); 725 DataMap::const_iterator itr = rData.find(rMemName); 726 if (itr != rData.end()) 727 pMem->SetIsVisible(itr->second); 728 } 729 } 730 731 bool ScDPSaveDimension::HasInvisibleMember() const 732 { 733 MemberList::const_iterator itrMem = maMemberList.begin(), itrMemEnd = maMemberList.end(); 734 for (; itrMem != itrMemEnd; ++itrMem) 735 { 736 const ScDPSaveMember* pMem = *itrMem; 737 if (!pMem->GetIsVisible()) 738 return true; 739 } 740 return false; 741 } 742 743 // ----------------------------------------------------------------------- 744 745 ScDPSaveData::ScDPSaveData() : 746 pDimensionData( NULL ), 747 nColumnGrandMode( SC_DPSAVEMODE_DONTKNOW ), 748 nRowGrandMode( SC_DPSAVEMODE_DONTKNOW ), 749 nIgnoreEmptyMode( SC_DPSAVEMODE_DONTKNOW ), 750 nRepeatEmptyMode( SC_DPSAVEMODE_DONTKNOW ), 751 bFilterButton( sal_True ), 752 bDrillDown( sal_True ), 753 // Wang Xu Ming -- 2009-8-17 754 // DataPilot Migration - Cache&&Performance 755 mnCacheId( -1), 756 // End Comments 757 mbDimensionMembersBuilt(false), 758 mpGrandTotalName(NULL) 759 { 760 } 761 762 ScDPSaveData::ScDPSaveData(const ScDPSaveData& r) : 763 nColumnGrandMode( r.nColumnGrandMode ), 764 nRowGrandMode( r.nRowGrandMode ), 765 nIgnoreEmptyMode( r.nIgnoreEmptyMode ), 766 nRepeatEmptyMode( r.nRepeatEmptyMode ), 767 bFilterButton( r.bFilterButton ), 768 bDrillDown( r.bDrillDown ), 769 // Wang Xu Ming -- 2009-8-17 770 // DataPilot Migration - Cache&&Performance 771 mnCacheId( r.mnCacheId ), 772 // End Comments 773 mbDimensionMembersBuilt(r.mbDimensionMembersBuilt), 774 mpGrandTotalName(NULL) 775 { 776 if ( r.pDimensionData ) 777 pDimensionData = new ScDPDimensionSaveData( *r.pDimensionData ); 778 else 779 pDimensionData = NULL; 780 781 long nCount = r.aDimList.Count(); 782 for (long i=0; i<nCount; i++) 783 { 784 ScDPSaveDimension* pNew = new ScDPSaveDimension( *(ScDPSaveDimension*)r.aDimList.GetObject(i) ); 785 aDimList.Insert( pNew, LIST_APPEND ); 786 } 787 788 if (r.mpGrandTotalName.get()) 789 mpGrandTotalName.reset(new OUString(*r.mpGrandTotalName)); 790 } 791 792 ScDPSaveData& ScDPSaveData::operator= ( const ScDPSaveData& r ) 793 { 794 if ( &r != this ) 795 { 796 // Wang Xu Ming -- 2009-8-17 797 // DataPilot Migration - Cache&&Performance 798 this->~ScDPSaveData(); 799 new( this ) ScDPSaveData ( r ); 800 // End Comments 801 } 802 return *this; 803 } 804 805 sal_Bool ScDPSaveData::operator== ( const ScDPSaveData& r ) const 806 { 807 if ( nColumnGrandMode != r.nColumnGrandMode || 808 nRowGrandMode != r.nRowGrandMode || 809 nIgnoreEmptyMode != r.nIgnoreEmptyMode || 810 nRepeatEmptyMode != r.nRepeatEmptyMode || 811 bFilterButton != r.bFilterButton || 812 mnCacheId != r.mnCacheId ||/// Wang Xu Ming -- 2009-6-18 DataPilot Migration 813 bDrillDown != r.bDrillDown || 814 mbDimensionMembersBuilt != r.mbDimensionMembersBuilt) 815 return sal_False; 816 817 if ( pDimensionData || r.pDimensionData ) 818 if ( !pDimensionData || !r.pDimensionData || !( *pDimensionData == *r.pDimensionData ) ) 819 return sal_False; 820 821 sal_uLong nCount = aDimList.Count(); 822 if ( nCount != r.aDimList.Count() ) 823 return sal_False; 824 825 for (sal_uLong i=0; i<nCount; i++) 826 if ( !( *(ScDPSaveDimension*)aDimList.GetObject(i) == 827 *(ScDPSaveDimension*)r.aDimList.GetObject(i) ) ) 828 return sal_False; 829 830 if (mpGrandTotalName.get()) 831 { 832 if (!r.mpGrandTotalName.get()) 833 return false; 834 if (!mpGrandTotalName->equals(*r.mpGrandTotalName)) 835 return false; 836 } 837 else if (r.mpGrandTotalName.get()) 838 return false; 839 840 return sal_True; 841 } 842 843 ScDPSaveData::~ScDPSaveData() 844 { 845 long nCount = aDimList.Count(); 846 for (long i=0; i<nCount; i++) 847 delete (ScDPSaveDimension*)aDimList.GetObject(i); 848 aDimList.Clear(); 849 850 delete pDimensionData; 851 } 852 853 void ScDPSaveData::SetGrandTotalName(const OUString& rName) 854 { 855 mpGrandTotalName.reset(new OUString(rName)); 856 } 857 858 const OUString* ScDPSaveData::GetGrandTotalName() const 859 { 860 return mpGrandTotalName.get(); 861 } 862 863 ScDPSaveDimension* ScDPSaveData::GetDimensionByName(const String& rName) 864 { 865 long nCount = aDimList.Count(); 866 for (long i=0; i<nCount; i++) 867 { 868 ScDPSaveDimension* pDim = (ScDPSaveDimension*)aDimList.GetObject(i); 869 if ( pDim->GetName() == rName && !pDim->IsDataLayout() ) 870 return pDim; 871 } 872 ScDPSaveDimension* pNew = new ScDPSaveDimension( rName, sal_False ); 873 aDimList.Insert( pNew, LIST_APPEND ); 874 mbDimensionMembersBuilt = false; // BuildAllDimensionMembers only handles existing entries in aDimList 875 return pNew; 876 } 877 878 ScDPSaveDimension* ScDPSaveData::GetExistingDimensionByName(const String& rName) const 879 { 880 long nCount = aDimList.Count(); 881 for (long i=0; i<nCount; i++) 882 { 883 ScDPSaveDimension* pDim = (ScDPSaveDimension*)aDimList.GetObject(i); 884 if ( pDim->GetName() == rName && !pDim->IsDataLayout() ) 885 return pDim; 886 } 887 return NULL; // don't create new 888 } 889 890 ScDPSaveDimension* ScDPSaveData::GetNewDimensionByName(const String& rName) 891 { 892 long nCount = aDimList.Count(); 893 for (long i=0; i<nCount; i++) 894 { 895 ScDPSaveDimension* pDim = (ScDPSaveDimension*)aDimList.GetObject(i); 896 if ( pDim->GetName() == rName && !pDim->IsDataLayout() ) 897 return DuplicateDimension(rName); 898 } 899 ScDPSaveDimension* pNew = new ScDPSaveDimension( rName, sal_False ); 900 aDimList.Insert( pNew, LIST_APPEND ); 901 mbDimensionMembersBuilt = false; // BuildAllDimensionMembers only handles existing entries in aDimList 902 return pNew; 903 } 904 905 ScDPSaveDimension* ScDPSaveData::GetDataLayoutDimension() 906 { 907 ScDPSaveDimension* pDim = GetExistingDataLayoutDimension(); 908 if (pDim) 909 return pDim; 910 911 ScDPSaveDimension* pNew = new ScDPSaveDimension( String(), sal_True ); 912 aDimList.Insert( pNew, LIST_APPEND ); 913 mbDimensionMembersBuilt = false; // BuildAllDimensionMembers only handles existing entries in aDimList 914 return pNew; 915 } 916 917 ScDPSaveDimension* ScDPSaveData::GetExistingDataLayoutDimension() const 918 { 919 long nCount = aDimList.Count(); 920 for (long i=0; i<nCount; i++) 921 { 922 ScDPSaveDimension* pDim = (ScDPSaveDimension*)aDimList.GetObject(i); 923 if ( pDim->IsDataLayout() ) 924 return pDim; 925 } 926 return NULL; 927 } 928 929 ScDPSaveDimension* ScDPSaveData::DuplicateDimension(const String& rName) 930 { 931 // always insert new 932 //! check if dimension is there? 933 934 ScDPSaveDimension* pOld = GetDimensionByName( rName ); 935 ScDPSaveDimension* pNew = new ScDPSaveDimension( *pOld ); 936 pNew->SetDupFlag( sal_True ); 937 aDimList.Insert( pNew, LIST_APPEND ); 938 mbDimensionMembersBuilt = false; // BuildAllDimensionMembers only handles existing entries in aDimList 939 return pNew; 940 } 941 942 void ScDPSaveData::RemoveDimensionByName(const String& rName) 943 { 944 long nCount = aDimList.Count(); 945 for (long i=0; i<nCount; i++) 946 { 947 ScDPSaveDimension* pDim = (ScDPSaveDimension*)aDimList.GetObject(i); 948 if ( pDim->GetName() == rName && !pDim->IsDataLayout() ) 949 { 950 delete pDim; 951 aDimList.Remove(i); 952 break; 953 } 954 } 955 } 956 957 ScDPSaveDimension& ScDPSaveData::DuplicateDimension( const ScDPSaveDimension& rDim ) 958 { 959 ScDPSaveDimension* pNew = new ScDPSaveDimension( rDim ); 960 pNew->SetDupFlag( sal_True ); 961 aDimList.Insert( pNew, LIST_APPEND ); 962 mbDimensionMembersBuilt = false; // BuildAllDimensionMembers only handles existing entries in aDimList 963 return *pNew; 964 } 965 966 ScDPSaveDimension* ScDPSaveData::GetInnermostDimension(sal_uInt16 nOrientation) 967 { 968 // return the innermost dimension for the given orientation, 969 // excluding data layout dimension 970 971 ScDPSaveDimension* pInner = NULL; 972 long nCount = aDimList.Count(); 973 for (long i=0; i<nCount; i++) 974 { 975 ScDPSaveDimension* pDim = static_cast<ScDPSaveDimension*>(aDimList.GetObject(i)); 976 if ( pDim->GetOrientation() == nOrientation && !pDim->IsDataLayout() ) 977 pInner = pDim; 978 } 979 return pInner; // the last matching one 980 } 981 982 ScDPSaveDimension* ScDPSaveData::GetFirstDimension(sheet::DataPilotFieldOrientation eOrientation) 983 { 984 long nCount = aDimList.Count(); 985 for (long i = 0; i < nCount; ++i) 986 { 987 ScDPSaveDimension* pDim = static_cast<ScDPSaveDimension*>(aDimList.GetObject(i)); 988 if (pDim->GetOrientation() == eOrientation && !pDim->IsDataLayout()) 989 return pDim; 990 } 991 return NULL; 992 } 993 994 long ScDPSaveData::GetDataDimensionCount() const 995 { 996 long nDataCount = 0; 997 998 long nCount = aDimList.Count(); 999 for (long i=0; i<nCount; i++) 1000 { 1001 const ScDPSaveDimension* pDim = static_cast<const ScDPSaveDimension*>(aDimList.GetObject(i)); 1002 if ( pDim->GetOrientation() == sheet::DataPilotFieldOrientation_DATA ) 1003 ++nDataCount; 1004 } 1005 1006 return nDataCount; 1007 } 1008 1009 void ScDPSaveData::SetPosition( ScDPSaveDimension* pDim, long nNew ) 1010 { 1011 // position (nNew) is counted within dimensions of the same orientation 1012 1013 sal_uInt16 nOrient = pDim->GetOrientation(); 1014 1015 aDimList.Remove( pDim ); 1016 sal_uLong nCount = aDimList.Count(); // after remove 1017 1018 sal_uLong nInsPos = 0; 1019 while ( nNew > 0 && nInsPos < nCount ) 1020 { 1021 if ( ((ScDPSaveDimension*)aDimList.GetObject(nInsPos))->GetOrientation() == nOrient ) 1022 --nNew; 1023 ++nInsPos; 1024 } 1025 1026 aDimList.Insert( pDim, nInsPos ); 1027 } 1028 1029 void ScDPSaveData::SetColumnGrand(sal_Bool bSet) 1030 { 1031 nColumnGrandMode = bSet; 1032 } 1033 1034 void ScDPSaveData::SetRowGrand(sal_Bool bSet) 1035 { 1036 nRowGrandMode = bSet; 1037 } 1038 1039 void ScDPSaveData::SetIgnoreEmptyRows(sal_Bool bSet) 1040 { 1041 nIgnoreEmptyMode = bSet; 1042 } 1043 1044 void ScDPSaveData::SetRepeatIfEmpty(sal_Bool bSet) 1045 { 1046 nRepeatEmptyMode = bSet; 1047 } 1048 1049 void ScDPSaveData::SetFilterButton(sal_Bool bSet) 1050 { 1051 bFilterButton = bSet; 1052 } 1053 1054 void ScDPSaveData::SetDrillDown(sal_Bool bSet) 1055 { 1056 bDrillDown = bSet; 1057 } 1058 1059 void lcl_ResetOrient( const uno::Reference<sheet::XDimensionsSupplier>& xSource ) 1060 { 1061 sheet::DataPilotFieldOrientation eOrient = sheet::DataPilotFieldOrientation_HIDDEN; 1062 1063 uno::Reference<container::XNameAccess> xDimsName = xSource->getDimensions(); 1064 uno::Reference<container::XIndexAccess> xIntDims = new ScNameToIndexAccess( xDimsName ); 1065 long nIntCount = xIntDims->getCount(); 1066 for (long nIntDim=0; nIntDim<nIntCount; nIntDim++) 1067 { 1068 uno::Reference<uno::XInterface> xIntDim = ScUnoHelpFunctions::AnyToInterface( xIntDims->getByIndex(nIntDim) ); 1069 uno::Reference<beans::XPropertySet> xDimProp( xIntDim, uno::UNO_QUERY ); 1070 if (xDimProp.is()) 1071 { 1072 uno::Any aAny; 1073 aAny <<= eOrient; 1074 xDimProp->setPropertyValue( rtl::OUString::createFromAscii(DP_PROP_ORIENTATION), aAny ); 1075 } 1076 } 1077 } 1078 1079 void ScDPSaveData::WriteToSource( const uno::Reference<sheet::XDimensionsSupplier>& xSource ) 1080 { 1081 if (!xSource.is()) 1082 return; 1083 1084 // source options must be first! 1085 1086 uno::Reference<beans::XPropertySet> xSourceProp( xSource, uno::UNO_QUERY ); 1087 DBG_ASSERT( xSourceProp.is(), "no properties at source" ); 1088 if ( xSourceProp.is() ) 1089 { 1090 // source options are not available for external sources 1091 //! use XPropertySetInfo to test for availability? 1092 1093 try 1094 { 1095 if ( nIgnoreEmptyMode != SC_DPSAVEMODE_DONTKNOW ) 1096 lcl_SetBoolProperty( xSourceProp, 1097 rtl::OUString::createFromAscii(DP_PROP_IGNOREEMPTY), (sal_Bool)nIgnoreEmptyMode ); 1098 if ( nRepeatEmptyMode != SC_DPSAVEMODE_DONTKNOW ) 1099 lcl_SetBoolProperty( xSourceProp, 1100 rtl::OUString::createFromAscii(DP_PROP_REPEATIFEMPTY), (sal_Bool)nRepeatEmptyMode ); 1101 } 1102 catch(uno::Exception&) 1103 { 1104 // no error 1105 } 1106 1107 const OUString* pGrandTotalName = GetGrandTotalName(); 1108 if (pGrandTotalName) 1109 ScUnoHelpFunctions::SetOptionalPropertyValue(xSourceProp, SC_UNO_GRANDTOTAL_NAME, *pGrandTotalName); 1110 } 1111 1112 // exceptions in the other calls are errors 1113 try 1114 { 1115 // reset all orientations 1116 //! "forgetSettings" or similar at source ????? 1117 //! reset all duplicated dimensions, or reuse them below !!! 1118 DBG_TRACE( "ScDPSaveData::WriteToSource" ); 1119 1120 lcl_ResetOrient( xSource ); 1121 1122 long nCount = aDimList.Count(); 1123 for (long i=0; i<nCount; i++) 1124 { 1125 ScDPSaveDimension* pDim = (ScDPSaveDimension*)aDimList.GetObject(i); 1126 rtl::OUString aName = pDim->GetName(); 1127 1128 DBG_TRACESTR(pDim->GetName()); 1129 1130 sal_Bool bData = pDim->IsDataLayout(); 1131 1132 //! getByName for ScDPSource, including DataLayoutDimension !!!!!!!! 1133 1134 uno::Reference<container::XNameAccess> xDimsName = xSource->getDimensions(); 1135 uno::Reference<container::XIndexAccess> xIntDims = new ScNameToIndexAccess( xDimsName ); 1136 long nIntCount = xIntDims->getCount(); 1137 sal_Bool bFound = sal_False; 1138 for (long nIntDim=0; nIntDim<nIntCount && !bFound; nIntDim++) 1139 { 1140 uno::Reference<uno::XInterface> xIntDim = ScUnoHelpFunctions::AnyToInterface( xIntDims->getByIndex(nIntDim) ); 1141 if ( bData ) 1142 { 1143 uno::Reference<beans::XPropertySet> xDimProp( xIntDim, uno::UNO_QUERY ); 1144 if ( xDimProp.is() ) 1145 { 1146 bFound = ScUnoHelpFunctions::GetBoolProperty( xDimProp, 1147 rtl::OUString::createFromAscii(DP_PROP_ISDATALAYOUT) ); 1148 //! error checking -- is "IsDataLayoutDimension" property required?? 1149 } 1150 } 1151 else 1152 { 1153 uno::Reference<container::XNamed> xDimName( xIntDim, uno::UNO_QUERY ); 1154 if ( xDimName.is() && xDimName->getName() == aName ) 1155 bFound = sal_True; 1156 } 1157 1158 if ( bFound ) 1159 { 1160 if ( pDim->GetDupFlag() ) 1161 { 1162 String aNewName = pDim->GetName(); 1163 1164 // different name for each duplication of a (real) dimension... 1165 for (long j=0; j<=i; j++) //! Test !!!!!! 1166 aNewName += '*'; //! modify name at creation of SaveDimension 1167 1168 uno::Reference<util::XCloneable> xCloneable( xIntDim, uno::UNO_QUERY ); 1169 DBG_ASSERT( xCloneable.is(), "cannot clone dimension" ); 1170 if (xCloneable.is()) 1171 { 1172 uno::Reference<util::XCloneable> xNew = xCloneable->createClone(); 1173 uno::Reference<container::XNamed> xNewName( xNew, uno::UNO_QUERY ); 1174 if (xNewName.is()) 1175 { 1176 xNewName->setName( aNewName ); 1177 pDim->WriteToSource( xNew ); 1178 } 1179 } 1180 } 1181 else 1182 pDim->WriteToSource( xIntDim ); 1183 } 1184 } 1185 DBG_ASSERT(bFound, "WriteToSource: Dimension not found"); 1186 } 1187 1188 if ( xSourceProp.is() ) 1189 { 1190 if ( nColumnGrandMode != SC_DPSAVEMODE_DONTKNOW ) 1191 lcl_SetBoolProperty( xSourceProp, 1192 rtl::OUString::createFromAscii(DP_PROP_COLUMNGRAND), (sal_Bool)nColumnGrandMode ); 1193 if ( nRowGrandMode != SC_DPSAVEMODE_DONTKNOW ) 1194 lcl_SetBoolProperty( xSourceProp, 1195 rtl::OUString::createFromAscii(DP_PROP_ROWGRAND), (sal_Bool)nRowGrandMode ); 1196 } 1197 } 1198 catch(uno::Exception&) 1199 { 1200 DBG_ERROR("exception in WriteToSource"); 1201 } 1202 } 1203 1204 sal_Bool ScDPSaveData::IsEmpty() const 1205 { 1206 long nCount = aDimList.Count(); 1207 for (long i=0; i<nCount; i++) 1208 { 1209 ScDPSaveDimension* pDim = (ScDPSaveDimension*)aDimList.GetObject(i); 1210 if ( pDim->GetOrientation() != sheet::DataPilotFieldOrientation_HIDDEN && !pDim->IsDataLayout() ) 1211 return sal_False; 1212 } 1213 return sal_True; // no entries that are not hidden 1214 } 1215 1216 ScDPDimensionSaveData* ScDPSaveData::GetDimensionData() 1217 { 1218 if (!pDimensionData) 1219 pDimensionData = new ScDPDimensionSaveData; 1220 return pDimensionData; 1221 } 1222 1223 void ScDPSaveData::SetDimensionData( const ScDPDimensionSaveData* pNew ) 1224 { 1225 delete pDimensionData; 1226 if ( pNew ) 1227 pDimensionData = new ScDPDimensionSaveData( *pNew ); 1228 else 1229 pDimensionData = NULL; 1230 } 1231 1232 void ScDPSaveData::BuildAllDimensionMembers(ScDPTableData* pData) 1233 { 1234 if (mbDimensionMembersBuilt) 1235 return; 1236 1237 // First, build a dimension name-to-index map. 1238 typedef hash_map<OUString, long, ::rtl::OUStringHash> NameIndexMap; 1239 NameIndexMap aMap; 1240 long nColCount = pData->GetColumnCount(); 1241 for (long i = 0; i < nColCount; ++i) 1242 aMap.insert( NameIndexMap::value_type(pData->getDimensionName(i), i)); 1243 1244 NameIndexMap::const_iterator itrEnd = aMap.end(); 1245 1246 sal_uInt32 n = aDimList.Count(); 1247 for (sal_uInt32 i = 0; i < n; ++i) 1248 { 1249 ScDPSaveDimension* pDim = static_cast<ScDPSaveDimension*>(aDimList.GetObject(i)); 1250 const String& rDimName = pDim->GetName(); 1251 if (!rDimName.Len()) 1252 // empty dimension name. It must be data layout. 1253 continue; 1254 1255 NameIndexMap::const_iterator itr = aMap.find(rDimName); 1256 if (itr == itrEnd) 1257 // dimension name not in the data. This should never happen! 1258 continue; 1259 1260 long nDimIndex = itr->second; 1261 const std::vector<SCROW>& rMembers = pData->GetColumnEntries(nDimIndex); 1262 size_t mMemberCount = rMembers.size(); 1263 for (size_t j = 0; j < mMemberCount; ++j) 1264 { 1265 const ScDPItemData* pMemberData = pData->GetMemberById( nDimIndex, rMembers[j] ); 1266 String aMemName = pMemberData->GetString(); 1267 if (pDim->GetExistingMemberByName(aMemName)) 1268 // this member instance already exists. nothing to do. 1269 continue; 1270 1271 auto_ptr<ScDPSaveMember> pNewMember(new ScDPSaveMember(aMemName)); 1272 pNewMember->SetIsVisible(true); 1273 pDim->AddMember(pNewMember.release()); 1274 } 1275 } 1276 1277 mbDimensionMembersBuilt = true; 1278 } 1279 1280 void ScDPSaveData::BuildAllDimensionMembersFromSource( ScDPObject* pDPObj ) 1281 { 1282 // Initialize all members like BuildAllDimensionMembers, but access only the DataPilotSource, not the table data. 1283 // This could also replace BuildAllDimensionMembers, but the performance implications still have to be checked. 1284 // ScDPObject is used for the helper method GetMemberNames. 1285 1286 if (mbDimensionMembersBuilt) 1287 return; 1288 1289 uno::Reference<sheet::XDimensionsSupplier> xSource = pDPObj->GetSource(); 1290 uno::Reference<container::XNameAccess> xDimsName = xSource->getDimensions(); 1291 // GetMemberNames uses the dimension index from getElementNames 1292 uno::Sequence<OUString> aDimNames = xDimsName->getElementNames(); 1293 1294 // First, build a dimension name-to-index map. 1295 typedef hash_map<OUString, long, ::rtl::OUStringHash> NameIndexMap; 1296 NameIndexMap aMap; 1297 long nColCount = aDimNames.getLength(); 1298 for (long i = 0; i < nColCount; ++i) 1299 aMap.insert( NameIndexMap::value_type(aDimNames[i], i) ); 1300 1301 NameIndexMap::const_iterator itrEnd = aMap.end(); 1302 1303 sal_uInt32 n = aDimList.Count(); 1304 for (sal_uInt32 i = 0; i < n; ++i) 1305 { 1306 ScDPSaveDimension* pDim = static_cast<ScDPSaveDimension*>(aDimList.GetObject(i)); 1307 const String& rDimName = pDim->GetName(); 1308 if (!rDimName.Len()) 1309 // empty dimension name. It must be data layout. 1310 continue; 1311 1312 NameIndexMap::const_iterator itr = aMap.find(rDimName); 1313 if (itr == itrEnd) 1314 // dimension name not in the data. This should never happen! 1315 continue; 1316 1317 long nDimIndex = itr->second; 1318 uno::Sequence<OUString> aMemberNames; 1319 pDPObj->GetMemberNames( nDimIndex, aMemberNames ); 1320 sal_Int32 nMemberCount = aMemberNames.getLength(); 1321 for (sal_Int32 j = 0; j < nMemberCount; ++j) 1322 { 1323 String aMemName = aMemberNames[j]; 1324 if (pDim->GetExistingMemberByName(aMemName)) 1325 // this member instance already exists. nothing to do. 1326 continue; 1327 1328 auto_ptr<ScDPSaveMember> pNewMember(new ScDPSaveMember(aMemName)); 1329 pNewMember->SetIsVisible(true); 1330 pDim->AddMember(pNewMember.release()); 1331 } 1332 } 1333 1334 mbDimensionMembersBuilt = true; 1335 } 1336 1337 bool ScDPSaveData::HasInvisibleMember(const OUString& rDimName) const 1338 { 1339 ScDPSaveDimension* pDim = GetExistingDimensionByName(rDimName); 1340 if (!pDim) 1341 return false; 1342 1343 return pDim->HasInvisibleMember(); 1344 } 1345 1346 void ScDPSaveData::Refresh( const uno::Reference<sheet::XDimensionsSupplier>& xSource ) 1347 { 1348 try 1349 { 1350 long nCount = aDimList.Count(); 1351 std::list<String> deletedDims; 1352 for (long i=nCount-1; i >=0 ; i--) 1353 { 1354 ScDPSaveDimension* pDim = (ScDPSaveDimension*)aDimList.GetObject(i); 1355 1356 rtl::OUString aName = pDim->GetName(); 1357 if ( pDim->IsDataLayout() ) 1358 continue; 1359 1360 uno::Reference<container::XNameAccess> xDimsName = xSource->getDimensions(); 1361 uno::Reference<container::XIndexAccess> xIntDims = new ScNameToIndexAccess( xDimsName ); 1362 long nIntCount = xIntDims->getCount(); 1363 sal_Bool bFound = sal_False; 1364 for (long nIntDim=0; nIntDim<nIntCount && !bFound; nIntDim++) 1365 { 1366 uno::Reference<uno::XInterface> xIntDim = ScUnoHelpFunctions::AnyToInterface( xIntDims->getByIndex(nIntDim) ); 1367 uno::Reference<container::XNamed> xDimName( xIntDim, uno::UNO_QUERY ); 1368 if ( xDimName.is() && xDimName->getName() == aName ) 1369 bFound = sal_True; 1370 } 1371 if ( !bFound ) 1372 { 1373 deletedDims.push_back( aName ); 1374 aDimList.Remove(i); 1375 DBG_TRACE( "\n Remove dim: \t" ); 1376 DBG_TRACESTR( String( aName ) ); 1377 } 1378 1379 } 1380 1381 nCount = aDimList.Count(); 1382 for (long i=nCount-1; i >=0 ; i--) //check every dimension ?? 1383 { 1384 ScDPSaveDimension* pDim = (ScDPSaveDimension*)aDimList.GetObject(i); 1385 1386 rtl::OUString aName = pDim->GetName(); 1387 if ( pDim->IsDataLayout() ) 1388 continue; 1389 pDim->Refresh( xSource, deletedDims ); 1390 1391 } 1392 1393 mbDimensionMembersBuilt = false; // there may be new members 1394 } 1395 catch(uno::Exception&) 1396 { 1397 DBG_ERROR("error in ScDPSaveData::Refresh"); 1398 } 1399 1400 } 1401 void ScDPSaveDimension::Refresh( const com::sun::star::uno::Reference< 1402 com::sun::star::sheet::XDimensionsSupplier>& xSource , 1403 const std::list<String>& deletedDims) 1404 { 1405 if ( xSource.is() ) 1406 { 1407 ScDPSource* pTabSource = static_cast<ScDPSource*>( xSource.get() ); 1408 ScDPTableDataCache* pCache = pTabSource->GetCache(); 1409 if ( pCache->GetId() == -1 ) 1410 return; 1411 1412 SCCOL nSrcDim = pCache->GetDimensionIndex( GetName() ); 1413 1414 if ( nSrcDim == -1 ) 1415 return; 1416 if ( pSelectedPage ) 1417 {//check pSelected page 1418 DBG_TRACESTR( (*pSelectedPage) ); 1419 if ( pCache->GetIdByItemData( nSrcDim, *pSelectedPage ) == -1 ) 1420 { 1421 delete pSelectedPage; 1422 pSelectedPage = NULL; 1423 } 1424 1425 }; 1426 1427 if ( pReferenceValue && pReferenceValue->ReferenceItemType == DataPilotFieldReferenceItemType::NAMED ) 1428 {//check pReferenceValue 1429 #ifdef DEBUG 1430 switch( pReferenceValue->ReferenceType) 1431 { 1432 case sheet::DataPilotFieldReferenceType::ITEM_PERCENTAGE: //both 1433 DBG_TRACE( "\n sheet::DataPilotFieldReferenceType::ITEM_PERCENTAGE \n" ); 1434 break; 1435 case sheet::DataPilotFieldReferenceType::ITEM_DIFFERENCE: //both 1436 DBG_TRACE( "\n sheet::DataPilotFieldReferenceType::ITEM_DIFFERENCE \n" ); 1437 break; 1438 case sheet::DataPilotFieldReferenceType::ITEM_PERCENTAGE_DIFFERENCE: //both 1439 DBG_TRACE( "\n sheet::DataPilotFieldReferenceType::ITEM_PERCENTAGE_DIFFERENCE \n" ); 1440 break; 1441 case sheet::DataPilotFieldReferenceType::RUNNING_TOTAL: 1442 DBG_TRACE( "\n sheet::DataPilotFieldReferenceType::RUNNING_TOTAL \n" ); //enable name 1443 break; 1444 } 1445 #endif 1446 switch( pReferenceValue->ReferenceType) 1447 { 1448 case sheet::DataPilotFieldReferenceType::ITEM_PERCENTAGE: 1449 case sheet::DataPilotFieldReferenceType::ITEM_DIFFERENCE: 1450 case sheet::DataPilotFieldReferenceType::ITEM_PERCENTAGE_DIFFERENCE: 1451 case sheet::DataPilotFieldReferenceType::RUNNING_TOTAL: 1452 { 1453 if( pReferenceValue->ReferenceItemType == DataPilotFieldReferenceItemType::NAMED ) 1454 { 1455 const String& sReferenceFieldName = pReferenceValue->ReferenceField; 1456 DBG_TRACESTR( sReferenceFieldName ); 1457 SCCOL nRefDim = pCache->GetDimensionIndex( sReferenceFieldName ); 1458 bool bValid = true; 1459 if ( nRefDim == -1 ) 1460 bValid = false; 1461 else if ( pReferenceValue->ReferenceType != sheet::DataPilotFieldReferenceType::RUNNING_TOTAL ) 1462 { //running total has not reference item 1463 const String& sReferenceItemName = pReferenceValue->ReferenceItemName; 1464 DBG_TRACESTR( sReferenceItemName ); 1465 if ( pCache->GetIdByItemData( nRefDim, sReferenceItemName ) == -1 ) 1466 bValid = false; 1467 } 1468 if ( !bValid ) 1469 { 1470 delete pReferenceValue; 1471 pReferenceValue = NULL; 1472 } 1473 } 1474 } 1475 break; 1476 } 1477 1478 }; 1479 1480 if ( pSortInfo ) 1481 { //check sortinfo 1482 if ( pSortInfo->Mode == DataPilotFieldSortMode::DATA ) 1483 { 1484 DBG_TRACE( "\n DataPilotFieldSortMode::DATA \n" ); 1485 const String& sFieldDimName = pSortInfo->Field; 1486 std::list<String>::const_iterator iter = std::find( deletedDims.begin(), deletedDims.end(), sFieldDimName ); 1487 if ( iter != deletedDims.end() && pCache->GetDimensionIndex( sFieldDimName ) == -1 ) 1488 { 1489 pSortInfo->Mode = DataPilotFieldSortMode::MANUAL; 1490 pSortInfo->Field = GetName(); 1491 } 1492 } 1493 1494 }; 1495 1496 if ( pAutoShowInfo ) 1497 { //check autoshow 1498 const String& sFieldDimName = pAutoShowInfo->DataField; 1499 std::list<String>::const_iterator iter = std::find( deletedDims.begin(), deletedDims.end(), sFieldDimName ); 1500 if ( iter != deletedDims.end() && pCache->GetDimensionIndex( sFieldDimName ) == -1 ) 1501 { 1502 delete pAutoShowInfo; 1503 pAutoShowInfo = NULL; 1504 } 1505 1506 }; 1507 1508 //remove unused members 1509 for (MemberList::iterator i=maMemberList.begin(); i != maMemberList.end() ; ) 1510 { 1511 rtl::OUString aMemberName = (*i)->GetName(); 1512 if ( pCache->GetIdByItemData( nSrcDim, aMemberName ) == -1 ) 1513 i = maMemberList.erase( i ); 1514 else 1515 i++; 1516 } 1517 } 1518 } 1519 // End Comments 1520 bool operator == (const ::com::sun::star::sheet::DataPilotFieldSortInfo &l, const ::com::sun::star::sheet::DataPilotFieldSortInfo &r ) 1521 { 1522 return l.Field == r.Field && l.IsAscending == r.IsAscending && l.Mode == r.Mode; 1523 } 1524 bool operator == (const ::com::sun::star::sheet::DataPilotFieldAutoShowInfo &l, const ::com::sun::star::sheet::DataPilotFieldAutoShowInfo &r ) 1525 { 1526 return l.IsEnabled == r.IsEnabled && 1527 l.ShowItemsMode == r.ShowItemsMode && 1528 l.ItemCount == r.ItemCount && 1529 l.DataField == r.DataField; 1530 } 1531 bool operator == (const ::com::sun::star::sheet::DataPilotFieldReference &l, const ::com::sun::star::sheet::DataPilotFieldReference &r ) 1532 { 1533 return l.ReferenceType == r.ReferenceType && 1534 l.ReferenceField == r.ReferenceField && 1535 l.ReferenceItemType == r.ReferenceItemType && 1536 l.ReferenceItemName == r.ReferenceItemName; 1537 } 1538 1539