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