1*b3f79822SAndrew Rist /************************************************************** 2cdf0e10cSrcweir * 3*b3f79822SAndrew Rist * Licensed to the Apache Software Foundation (ASF) under one 4*b3f79822SAndrew Rist * or more contributor license agreements. See the NOTICE file 5*b3f79822SAndrew Rist * distributed with this work for additional information 6*b3f79822SAndrew Rist * regarding copyright ownership. The ASF licenses this file 7*b3f79822SAndrew Rist * to you under the Apache License, Version 2.0 (the 8*b3f79822SAndrew Rist * "License"); you may not use this file except in compliance 9*b3f79822SAndrew Rist * with the License. You may obtain a copy of the License at 10*b3f79822SAndrew Rist * 11*b3f79822SAndrew Rist * http://www.apache.org/licenses/LICENSE-2.0 12*b3f79822SAndrew Rist * 13*b3f79822SAndrew Rist * Unless required by applicable law or agreed to in writing, 14*b3f79822SAndrew Rist * software distributed under the License is distributed on an 15*b3f79822SAndrew Rist * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16*b3f79822SAndrew Rist * KIND, either express or implied. See the License for the 17*b3f79822SAndrew Rist * specific language governing permissions and limitations 18*b3f79822SAndrew Rist * under the License. 19*b3f79822SAndrew Rist * 20*b3f79822SAndrew Rist *************************************************************/ 21*b3f79822SAndrew Rist 22*b3f79822SAndrew Rist 23cdf0e10cSrcweir 24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove 25cdf0e10cSrcweir #include "precompiled_sc.hxx" 26cdf0e10cSrcweir 27cdf0e10cSrcweir 28cdf0e10cSrcweir 29cdf0e10cSrcweir // INCLUDE --------------------------------------------------------------- 30cdf0e10cSrcweir 31cdf0e10cSrcweir #include "dbfunc.hxx" 32cdf0e10cSrcweir #include "scitems.hxx" 33cdf0e10cSrcweir #include <sfx2/bindings.hxx> 34cdf0e10cSrcweir #include <vcl/svapp.hxx> 35cdf0e10cSrcweir #include <vcl/msgbox.hxx> 36cdf0e10cSrcweir #include <vcl/sound.hxx> 37cdf0e10cSrcweir #include <vcl/waitobj.hxx> 38cdf0e10cSrcweir #include <svl/zforlist.hxx> 39cdf0e10cSrcweir #include <sfx2/app.hxx> 40cdf0e10cSrcweir #include <com/sun/star/beans/XPropertySet.hpp> 41cdf0e10cSrcweir #include <com/sun/star/container/XNameAccess.hpp> 42cdf0e10cSrcweir #include <com/sun/star/sheet/DataPilotFieldFilter.hpp> 43cdf0e10cSrcweir #include <com/sun/star/sheet/DataPilotFieldGroupBy.hpp> 44cdf0e10cSrcweir #include <com/sun/star/sheet/DataPilotFieldOrientation.hpp> 45cdf0e10cSrcweir #include <com/sun/star/sheet/DataPilotFieldSortMode.hpp> 46cdf0e10cSrcweir #include <com/sun/star/sheet/DataPilotTableHeaderData.hpp> 47cdf0e10cSrcweir #include <com/sun/star/sheet/GeneralFunction.hpp> 48cdf0e10cSrcweir #include <com/sun/star/sheet/MemberResultFlags.hpp> 49cdf0e10cSrcweir #include <com/sun/star/sheet/XDimensionsSupplier.hpp> 50cdf0e10cSrcweir #include <com/sun/star/sheet/XDrillDownDataSupplier.hpp> 51cdf0e10cSrcweir 52cdf0e10cSrcweir #include "global.hxx" 53cdf0e10cSrcweir #include "globstr.hrc" 54cdf0e10cSrcweir #include "sc.hrc" 55cdf0e10cSrcweir #include "undotab.hxx" 56cdf0e10cSrcweir #include "undodat.hxx" 57cdf0e10cSrcweir #include "dbcolect.hxx" 58cdf0e10cSrcweir #include "rangenam.hxx" 59cdf0e10cSrcweir #include "rangeutl.hxx" 60cdf0e10cSrcweir #include "docsh.hxx" 61cdf0e10cSrcweir #include "olinetab.hxx" 62cdf0e10cSrcweir #include "consoli.hxx" 63cdf0e10cSrcweir #include "olinefun.hxx" 64cdf0e10cSrcweir #include "dpobject.hxx" 65cdf0e10cSrcweir #include "dpsave.hxx" 66cdf0e10cSrcweir #include "dpdimsave.hxx" 67cdf0e10cSrcweir #include "dbdocfun.hxx" 68cdf0e10cSrcweir #include "dpoutput.hxx" 69cdf0e10cSrcweir #include "dptabsrc.hxx" 70cdf0e10cSrcweir #include "editable.hxx" 71cdf0e10cSrcweir #include "docpool.hxx" 72cdf0e10cSrcweir #include "patattr.hxx" 73cdf0e10cSrcweir #include "unonames.hxx" 74cdf0e10cSrcweir #include "cell.hxx" 75cdf0e10cSrcweir #include "userlist.hxx" 76cdf0e10cSrcweir 77cdf0e10cSrcweir #include <hash_set> 78cdf0e10cSrcweir #include <hash_map> 79cdf0e10cSrcweir #include <memory> 80cdf0e10cSrcweir #include <list> 81cdf0e10cSrcweir #include <vector> 82cdf0e10cSrcweir 83cdf0e10cSrcweir using namespace com::sun::star; 84cdf0e10cSrcweir using ::com::sun::star::uno::Any; 85cdf0e10cSrcweir using ::com::sun::star::uno::Sequence; 86cdf0e10cSrcweir using ::com::sun::star::uno::Reference; 87cdf0e10cSrcweir using ::com::sun::star::uno::UNO_QUERY; 88cdf0e10cSrcweir using ::com::sun::star::beans::XPropertySet; 89cdf0e10cSrcweir using ::com::sun::star::container::XNameAccess; 90cdf0e10cSrcweir using ::com::sun::star::sheet::XDimensionsSupplier; 91cdf0e10cSrcweir using ::rtl::OUString; 92cdf0e10cSrcweir using ::rtl::OUStringHash; 93cdf0e10cSrcweir using ::rtl::OUStringBuffer; 94cdf0e10cSrcweir using ::std::auto_ptr; 95cdf0e10cSrcweir using ::std::list; 96cdf0e10cSrcweir using ::std::vector; 97cdf0e10cSrcweir using ::std::hash_map; 98cdf0e10cSrcweir using ::std::hash_set; 99cdf0e10cSrcweir 100cdf0e10cSrcweir // STATIC DATA ----------------------------------------------------------- 101cdf0e10cSrcweir 102cdf0e10cSrcweir 103cdf0e10cSrcweir //================================================================== 104cdf0e10cSrcweir 105cdf0e10cSrcweir // 106cdf0e10cSrcweir // Outliner 107cdf0e10cSrcweir // 108cdf0e10cSrcweir 109cdf0e10cSrcweir // Outline-Gruppierung erzeugen 110cdf0e10cSrcweir 111cdf0e10cSrcweir void ScDBFunc::MakeOutline( sal_Bool bColumns, sal_Bool bRecord ) 112cdf0e10cSrcweir { 113cdf0e10cSrcweir ScRange aRange; 114cdf0e10cSrcweir if (GetViewData()->GetSimpleArea(aRange) == SC_MARK_SIMPLE) 115cdf0e10cSrcweir { 116cdf0e10cSrcweir ScDocShell* pDocSh = GetViewData()->GetDocShell(); 117cdf0e10cSrcweir ScOutlineDocFunc aFunc(*pDocSh); 118cdf0e10cSrcweir aFunc.MakeOutline( aRange, bColumns, bRecord, sal_False ); 119cdf0e10cSrcweir } 120cdf0e10cSrcweir else 121cdf0e10cSrcweir ErrorMessage(STR_NOMULTISELECT); 122cdf0e10cSrcweir } 123cdf0e10cSrcweir 124cdf0e10cSrcweir // Outline-Gruppierung loeschen 125cdf0e10cSrcweir 126cdf0e10cSrcweir void ScDBFunc::RemoveOutline( sal_Bool bColumns, sal_Bool bRecord ) 127cdf0e10cSrcweir { 128cdf0e10cSrcweir ScRange aRange; 129cdf0e10cSrcweir if (GetViewData()->GetSimpleArea(aRange) == SC_MARK_SIMPLE) 130cdf0e10cSrcweir { 131cdf0e10cSrcweir ScDocShell* pDocSh = GetViewData()->GetDocShell(); 132cdf0e10cSrcweir ScOutlineDocFunc aFunc(*pDocSh); 133cdf0e10cSrcweir aFunc.RemoveOutline( aRange, bColumns, bRecord, sal_False ); 134cdf0e10cSrcweir } 135cdf0e10cSrcweir else 136cdf0e10cSrcweir ErrorMessage(STR_NOMULTISELECT); 137cdf0e10cSrcweir } 138cdf0e10cSrcweir 139cdf0e10cSrcweir // Menue-Status: Outlines loeschen 140cdf0e10cSrcweir 141cdf0e10cSrcweir void ScDBFunc::TestRemoveOutline( sal_Bool& rCol, sal_Bool& rRow ) 142cdf0e10cSrcweir { 143cdf0e10cSrcweir sal_Bool bColFound = sal_False; 144cdf0e10cSrcweir sal_Bool bRowFound = sal_False; 145cdf0e10cSrcweir 146cdf0e10cSrcweir SCCOL nStartCol, nEndCol; 147cdf0e10cSrcweir SCROW nStartRow, nEndRow; 148cdf0e10cSrcweir SCTAB nStartTab, nEndTab; 149cdf0e10cSrcweir if (GetViewData()->GetSimpleArea(nStartCol,nStartRow,nStartTab,nEndCol,nEndRow,nEndTab) == SC_MARK_SIMPLE) 150cdf0e10cSrcweir { 151cdf0e10cSrcweir SCTAB nTab = nStartTab; 152cdf0e10cSrcweir ScDocument* pDoc = GetViewData()->GetDocument(); 153cdf0e10cSrcweir ScOutlineTable* pTable = pDoc->GetOutlineTable( nTab ); 154cdf0e10cSrcweir if (pTable) 155cdf0e10cSrcweir { 156cdf0e10cSrcweir ScOutlineArray* pArray; 157cdf0e10cSrcweir ScOutlineEntry* pEntry; 158cdf0e10cSrcweir SCCOLROW nStart; 159cdf0e10cSrcweir SCCOLROW nEnd; 160cdf0e10cSrcweir sal_Bool bColMarked = ( nStartRow == 0 && nEndRow == MAXROW ); 161cdf0e10cSrcweir sal_Bool bRowMarked = ( nStartCol == 0 && nEndCol == MAXCOL ); 162cdf0e10cSrcweir 163cdf0e10cSrcweir // Spalten 164cdf0e10cSrcweir 165cdf0e10cSrcweir if ( !bRowMarked || bColMarked ) // nicht wenn ganze Zeilen markiert 166cdf0e10cSrcweir { 167cdf0e10cSrcweir pArray = pTable->GetColArray(); 168cdf0e10cSrcweir ScSubOutlineIterator aColIter( pArray ); 169cdf0e10cSrcweir while ((pEntry=aColIter.GetNext()) != NULL && !bColFound) 170cdf0e10cSrcweir { 171cdf0e10cSrcweir nStart = pEntry->GetStart(); 172cdf0e10cSrcweir nEnd = pEntry->GetEnd(); 173cdf0e10cSrcweir if ( nStartCol<=static_cast<SCCOL>(nEnd) && nEndCol>=static_cast<SCCOL>(nStart) ) 174cdf0e10cSrcweir bColFound = sal_True; 175cdf0e10cSrcweir } 176cdf0e10cSrcweir } 177cdf0e10cSrcweir 178cdf0e10cSrcweir // Zeilen 179cdf0e10cSrcweir 180cdf0e10cSrcweir if ( !bColMarked || bRowMarked ) // nicht wenn ganze Spalten markiert 181cdf0e10cSrcweir { 182cdf0e10cSrcweir pArray = pTable->GetRowArray(); 183cdf0e10cSrcweir ScSubOutlineIterator aRowIter( pArray ); 184cdf0e10cSrcweir while ((pEntry=aRowIter.GetNext()) != NULL && !bRowFound) 185cdf0e10cSrcweir { 186cdf0e10cSrcweir nStart = pEntry->GetStart(); 187cdf0e10cSrcweir nEnd = pEntry->GetEnd(); 188cdf0e10cSrcweir if ( nStartRow<=nEnd && nEndRow>=nStart ) 189cdf0e10cSrcweir bRowFound = sal_True; 190cdf0e10cSrcweir } 191cdf0e10cSrcweir } 192cdf0e10cSrcweir } 193cdf0e10cSrcweir } 194cdf0e10cSrcweir 195cdf0e10cSrcweir rCol = bColFound; 196cdf0e10cSrcweir rRow = bRowFound; 197cdf0e10cSrcweir } 198cdf0e10cSrcweir 199cdf0e10cSrcweir void ScDBFunc::RemoveAllOutlines( sal_Bool bRecord ) 200cdf0e10cSrcweir { 201cdf0e10cSrcweir SCTAB nTab = GetViewData()->GetTabNo(); 202cdf0e10cSrcweir ScDocShell* pDocSh = GetViewData()->GetDocShell(); 203cdf0e10cSrcweir ScOutlineDocFunc aFunc(*pDocSh); 204cdf0e10cSrcweir 205cdf0e10cSrcweir HideCursor(); 206cdf0e10cSrcweir sal_Bool bOk = aFunc.RemoveAllOutlines( nTab, bRecord, sal_False ); 207cdf0e10cSrcweir ShowCursor(); 208cdf0e10cSrcweir 209cdf0e10cSrcweir if (bOk) 210cdf0e10cSrcweir UpdateScrollBars(); 211cdf0e10cSrcweir } 212cdf0e10cSrcweir 213cdf0e10cSrcweir // Auto-Outlines 214cdf0e10cSrcweir 215cdf0e10cSrcweir void ScDBFunc::AutoOutline( sal_Bool bRecord ) 216cdf0e10cSrcweir { 217cdf0e10cSrcweir SCTAB nTab = GetViewData()->GetTabNo(); 218cdf0e10cSrcweir ScRange aRange( 0,0,nTab, MAXCOL,MAXROW,nTab ); // ganze Tabelle, wenn nichts markiert 219cdf0e10cSrcweir ScMarkData& rMark = GetViewData()->GetMarkData(); 220cdf0e10cSrcweir if ( rMark.IsMarked() || rMark.IsMultiMarked() ) 221cdf0e10cSrcweir { 222cdf0e10cSrcweir rMark.MarkToMulti(); 223cdf0e10cSrcweir rMark.GetMultiMarkArea( aRange ); 224cdf0e10cSrcweir } 225cdf0e10cSrcweir 226cdf0e10cSrcweir ScDocShell* pDocSh = GetViewData()->GetDocShell(); 227cdf0e10cSrcweir ScOutlineDocFunc aFunc(*pDocSh); 228cdf0e10cSrcweir aFunc.AutoOutline( aRange, bRecord, sal_False ); 229cdf0e10cSrcweir } 230cdf0e10cSrcweir 231cdf0e10cSrcweir // Outline-Ebene auswaehlen 232cdf0e10cSrcweir 233cdf0e10cSrcweir void ScDBFunc::SelectLevel( sal_Bool bColumns, sal_uInt16 nLevel, sal_Bool bRecord, sal_Bool bPaint ) 234cdf0e10cSrcweir { 235cdf0e10cSrcweir SCTAB nTab = GetViewData()->GetTabNo(); 236cdf0e10cSrcweir ScDocShell* pDocSh = GetViewData()->GetDocShell(); 237cdf0e10cSrcweir ScOutlineDocFunc aFunc(*pDocSh); 238cdf0e10cSrcweir 239cdf0e10cSrcweir HideCursor(); 240cdf0e10cSrcweir sal_Bool bOk = aFunc.SelectLevel( nTab, bColumns, nLevel, bRecord, bPaint, sal_False ); 241cdf0e10cSrcweir ShowCursor(); 242cdf0e10cSrcweir 243cdf0e10cSrcweir if (bOk) 244cdf0e10cSrcweir UpdateScrollBars(); 245cdf0e10cSrcweir } 246cdf0e10cSrcweir 247cdf0e10cSrcweir // einzelne Outline-Gruppe einblenden 248cdf0e10cSrcweir 249cdf0e10cSrcweir void ScDBFunc::ShowOutline( sal_Bool bColumns, sal_uInt16 nLevel, sal_uInt16 nEntry, sal_Bool bRecord, sal_Bool bPaint ) 250cdf0e10cSrcweir { 251cdf0e10cSrcweir SCTAB nTab = GetViewData()->GetTabNo(); 252cdf0e10cSrcweir ScDocShell* pDocSh = GetViewData()->GetDocShell(); 253cdf0e10cSrcweir ScOutlineDocFunc aFunc(*pDocSh); 254cdf0e10cSrcweir 255cdf0e10cSrcweir HideCursor(); 256cdf0e10cSrcweir sal_Bool bOk = aFunc.ShowOutline( nTab, bColumns, nLevel, nEntry, bRecord, bPaint, sal_False ); 257cdf0e10cSrcweir ShowCursor(); 258cdf0e10cSrcweir 259cdf0e10cSrcweir if ( bOk && bPaint ) 260cdf0e10cSrcweir UpdateScrollBars(); 261cdf0e10cSrcweir } 262cdf0e10cSrcweir 263cdf0e10cSrcweir // einzelne Outline-Gruppe ausblenden 264cdf0e10cSrcweir 265cdf0e10cSrcweir void ScDBFunc::HideOutline( sal_Bool bColumns, sal_uInt16 nLevel, sal_uInt16 nEntry, sal_Bool bRecord, sal_Bool bPaint ) 266cdf0e10cSrcweir { 267cdf0e10cSrcweir SCTAB nTab = GetViewData()->GetTabNo(); 268cdf0e10cSrcweir ScDocShell* pDocSh = GetViewData()->GetDocShell(); 269cdf0e10cSrcweir ScOutlineDocFunc aFunc(*pDocSh); 270cdf0e10cSrcweir 271cdf0e10cSrcweir HideCursor(); 272cdf0e10cSrcweir sal_Bool bOk = aFunc.HideOutline( nTab, bColumns, nLevel, nEntry, bRecord, bPaint, sal_False ); 273cdf0e10cSrcweir ShowCursor(); 274cdf0e10cSrcweir 275cdf0e10cSrcweir if ( bOk && bPaint ) 276cdf0e10cSrcweir UpdateScrollBars(); 277cdf0e10cSrcweir } 278cdf0e10cSrcweir 279cdf0e10cSrcweir // Menue-Status: markierten Bereich ein-/ausblenden 280cdf0e10cSrcweir 281cdf0e10cSrcweir sal_Bool ScDBFunc::OutlinePossible(sal_Bool bHide) 282cdf0e10cSrcweir { 283cdf0e10cSrcweir sal_Bool bEnable = sal_False; 284cdf0e10cSrcweir 285cdf0e10cSrcweir SCCOL nStartCol; 286cdf0e10cSrcweir SCROW nStartRow; 287cdf0e10cSrcweir SCTAB nStartTab; 288cdf0e10cSrcweir SCCOL nEndCol; 289cdf0e10cSrcweir SCROW nEndRow; 290cdf0e10cSrcweir SCTAB nEndTab; 291cdf0e10cSrcweir 292cdf0e10cSrcweir if (GetViewData()->GetSimpleArea(nStartCol,nStartRow,nStartTab,nEndCol,nEndRow,nEndTab) == SC_MARK_SIMPLE) 293cdf0e10cSrcweir { 294cdf0e10cSrcweir ScDocument* pDoc = GetViewData()->GetDocument(); 295cdf0e10cSrcweir SCTAB nTab = GetViewData()->GetTabNo(); 296cdf0e10cSrcweir ScOutlineTable* pTable = pDoc->GetOutlineTable( nTab ); 297cdf0e10cSrcweir if (pTable) 298cdf0e10cSrcweir { 299cdf0e10cSrcweir ScOutlineArray* pArray; 300cdf0e10cSrcweir ScOutlineEntry* pEntry; 301cdf0e10cSrcweir SCCOLROW nStart; 302cdf0e10cSrcweir SCCOLROW nEnd; 303cdf0e10cSrcweir 304cdf0e10cSrcweir // Spalten 305cdf0e10cSrcweir 306cdf0e10cSrcweir pArray = pTable->GetColArray(); 307cdf0e10cSrcweir ScSubOutlineIterator aColIter( pArray ); 308cdf0e10cSrcweir while ((pEntry=aColIter.GetNext()) != NULL && !bEnable) 309cdf0e10cSrcweir { 310cdf0e10cSrcweir nStart = pEntry->GetStart(); 311cdf0e10cSrcweir nEnd = pEntry->GetEnd(); 312cdf0e10cSrcweir if ( bHide ) 313cdf0e10cSrcweir { 314cdf0e10cSrcweir if ( nStartCol<=static_cast<SCCOL>(nEnd) && nEndCol>=static_cast<SCCOL>(nStart) ) 315cdf0e10cSrcweir if (!pEntry->IsHidden()) 316cdf0e10cSrcweir bEnable = sal_True; 317cdf0e10cSrcweir } 318cdf0e10cSrcweir else 319cdf0e10cSrcweir { 320cdf0e10cSrcweir if ( nStart>=nStartCol && nEnd<=nEndCol ) 321cdf0e10cSrcweir if (pEntry->IsHidden()) 322cdf0e10cSrcweir bEnable = sal_True; 323cdf0e10cSrcweir } 324cdf0e10cSrcweir } 325cdf0e10cSrcweir 326cdf0e10cSrcweir // Zeilen 327cdf0e10cSrcweir 328cdf0e10cSrcweir pArray = pTable->GetRowArray(); 329cdf0e10cSrcweir ScSubOutlineIterator aRowIter( pArray ); 330cdf0e10cSrcweir while ((pEntry=aRowIter.GetNext()) != NULL) 331cdf0e10cSrcweir { 332cdf0e10cSrcweir nStart = pEntry->GetStart(); 333cdf0e10cSrcweir nEnd = pEntry->GetEnd(); 334cdf0e10cSrcweir if ( bHide ) 335cdf0e10cSrcweir { 336cdf0e10cSrcweir if ( nStartRow<=nEnd && nEndRow>=nStart ) 337cdf0e10cSrcweir if (!pEntry->IsHidden()) 338cdf0e10cSrcweir bEnable = sal_True; 339cdf0e10cSrcweir } 340cdf0e10cSrcweir else 341cdf0e10cSrcweir { 342cdf0e10cSrcweir if ( nStart>=nStartRow && nEnd<=nEndRow ) 343cdf0e10cSrcweir if (pEntry->IsHidden()) 344cdf0e10cSrcweir bEnable = sal_True; 345cdf0e10cSrcweir } 346cdf0e10cSrcweir } 347cdf0e10cSrcweir } 348cdf0e10cSrcweir } 349cdf0e10cSrcweir 350cdf0e10cSrcweir return bEnable; 351cdf0e10cSrcweir } 352cdf0e10cSrcweir 353cdf0e10cSrcweir // markierten Bereich einblenden 354cdf0e10cSrcweir 355cdf0e10cSrcweir void ScDBFunc::ShowMarkedOutlines( sal_Bool bRecord ) 356cdf0e10cSrcweir { 357cdf0e10cSrcweir ScRange aRange; 358cdf0e10cSrcweir if (GetViewData()->GetSimpleArea(aRange) == SC_MARK_SIMPLE) 359cdf0e10cSrcweir { 360cdf0e10cSrcweir ScDocShell* pDocSh = GetViewData()->GetDocShell(); 361cdf0e10cSrcweir ScOutlineDocFunc aFunc(*pDocSh); 362cdf0e10cSrcweir HideCursor(); 363cdf0e10cSrcweir sal_Bool bDone = aFunc.ShowMarkedOutlines( aRange, bRecord, sal_False ); 364cdf0e10cSrcweir ShowCursor(); 365cdf0e10cSrcweir if (bDone) 366cdf0e10cSrcweir UpdateScrollBars(); 367cdf0e10cSrcweir } 368cdf0e10cSrcweir else 369cdf0e10cSrcweir ErrorMessage(STR_NOMULTISELECT); 370cdf0e10cSrcweir } 371cdf0e10cSrcweir 372cdf0e10cSrcweir // markierten Bereich ausblenden 373cdf0e10cSrcweir 374cdf0e10cSrcweir void ScDBFunc::HideMarkedOutlines( sal_Bool bRecord ) 375cdf0e10cSrcweir { 376cdf0e10cSrcweir ScRange aRange; 377cdf0e10cSrcweir if (GetViewData()->GetSimpleArea(aRange) == SC_MARK_SIMPLE) 378cdf0e10cSrcweir { 379cdf0e10cSrcweir ScDocShell* pDocSh = GetViewData()->GetDocShell(); 380cdf0e10cSrcweir ScOutlineDocFunc aFunc(*pDocSh); 381cdf0e10cSrcweir HideCursor(); 382cdf0e10cSrcweir sal_Bool bDone = aFunc.HideMarkedOutlines( aRange, bRecord, sal_False ); 383cdf0e10cSrcweir ShowCursor(); 384cdf0e10cSrcweir if (bDone) 385cdf0e10cSrcweir UpdateScrollBars(); 386cdf0e10cSrcweir } 387cdf0e10cSrcweir else 388cdf0e10cSrcweir ErrorMessage(STR_NOMULTISELECT); 389cdf0e10cSrcweir } 390cdf0e10cSrcweir 391cdf0e10cSrcweir // -------------------------------------------------------------------------- 392cdf0e10cSrcweir 393cdf0e10cSrcweir // 394cdf0e10cSrcweir // Teilergebnisse 395cdf0e10cSrcweir // 396cdf0e10cSrcweir 397cdf0e10cSrcweir void ScDBFunc::DoSubTotals( const ScSubTotalParam& rParam, sal_Bool bRecord, 398cdf0e10cSrcweir const ScSortParam* pForceNewSort ) 399cdf0e10cSrcweir { 400cdf0e10cSrcweir sal_Bool bDo = !rParam.bRemoveOnly; // sal_False = nur loeschen 401cdf0e10cSrcweir 402cdf0e10cSrcweir ScDocShell* pDocSh = GetViewData()->GetDocShell(); 403cdf0e10cSrcweir ScDocument* pDoc = pDocSh->GetDocument(); 404cdf0e10cSrcweir ScMarkData& rMark = GetViewData()->GetMarkData(); 405cdf0e10cSrcweir SCTAB nTab = GetViewData()->GetTabNo(); 406cdf0e10cSrcweir if (bRecord && !pDoc->IsUndoEnabled()) 407cdf0e10cSrcweir bRecord = sal_False; 408cdf0e10cSrcweir 409cdf0e10cSrcweir ScDBData* pDBData = pDoc->GetDBAtArea( nTab, rParam.nCol1, rParam.nRow1, 410cdf0e10cSrcweir rParam.nCol2, rParam.nRow2 ); 411cdf0e10cSrcweir if (!pDBData) 412cdf0e10cSrcweir { 413cdf0e10cSrcweir DBG_ERROR( "SubTotals: keine DBData" ); 414cdf0e10cSrcweir return; 415cdf0e10cSrcweir } 416cdf0e10cSrcweir 417cdf0e10cSrcweir ScEditableTester aTester( pDoc, nTab, 0,rParam.nRow1+1, MAXCOL,MAXROW ); 418cdf0e10cSrcweir if (!aTester.IsEditable()) 419cdf0e10cSrcweir { 420cdf0e10cSrcweir ErrorMessage(aTester.GetMessageId()); 421cdf0e10cSrcweir return; 422cdf0e10cSrcweir } 423cdf0e10cSrcweir 424cdf0e10cSrcweir if (pDoc->HasAttrib( rParam.nCol1, rParam.nRow1+1, nTab, 425cdf0e10cSrcweir rParam.nCol2, rParam.nRow2, nTab, HASATTR_MERGED | HASATTR_OVERLAPPED )) 426cdf0e10cSrcweir { 427cdf0e10cSrcweir ErrorMessage(STR_MSSG_INSERTCELLS_0); // nicht in zusammengefasste einfuegen 428cdf0e10cSrcweir return; 429cdf0e10cSrcweir } 430cdf0e10cSrcweir 431cdf0e10cSrcweir WaitObject aWait( GetViewData()->GetDialogParent() ); 432cdf0e10cSrcweir sal_Bool bOk = sal_True; 433cdf0e10cSrcweir sal_Bool bDelete = sal_False; 434cdf0e10cSrcweir if (rParam.bReplace) 435cdf0e10cSrcweir if (pDoc->TestRemoveSubTotals( nTab, rParam )) 436cdf0e10cSrcweir { 437cdf0e10cSrcweir bDelete = sal_True; 438cdf0e10cSrcweir bOk = ( MessBox( GetViewData()->GetDialogParent(), WinBits(WB_YES_NO | WB_DEF_YES), 439cdf0e10cSrcweir // "StarCalc" "Daten loeschen?" 440cdf0e10cSrcweir ScGlobal::GetRscString( STR_MSSG_DOSUBTOTALS_0 ), 441cdf0e10cSrcweir ScGlobal::GetRscString( STR_MSSG_DOSUBTOTALS_1 ) ).Execute() 442cdf0e10cSrcweir == RET_YES ); 443cdf0e10cSrcweir } 444cdf0e10cSrcweir 445cdf0e10cSrcweir if (bOk) 446cdf0e10cSrcweir { 447cdf0e10cSrcweir ScDocShellModificator aModificator( *pDocSh ); 448cdf0e10cSrcweir 449cdf0e10cSrcweir ScSubTotalParam aNewParam( rParam ); // Bereichsende wird veraendert 450cdf0e10cSrcweir ScDocument* pUndoDoc = NULL; 451cdf0e10cSrcweir ScOutlineTable* pUndoTab = NULL; 452cdf0e10cSrcweir ScRangeName* pUndoRange = NULL; 453cdf0e10cSrcweir ScDBCollection* pUndoDB = NULL; 454cdf0e10cSrcweir SCTAB nTabCount = 0; // fuer Referenz-Undo 455cdf0e10cSrcweir 456cdf0e10cSrcweir if (bRecord) // alte Daten sichern 457cdf0e10cSrcweir { 458cdf0e10cSrcweir sal_Bool bOldFilter = bDo && rParam.bDoSort; 459cdf0e10cSrcweir 460cdf0e10cSrcweir nTabCount = pDoc->GetTableCount(); 461cdf0e10cSrcweir pUndoDoc = new ScDocument( SCDOCMODE_UNDO ); 462cdf0e10cSrcweir ScOutlineTable* pTable = pDoc->GetOutlineTable( nTab ); 463cdf0e10cSrcweir if (pTable) 464cdf0e10cSrcweir { 465cdf0e10cSrcweir pUndoTab = new ScOutlineTable( *pTable ); 466cdf0e10cSrcweir 467cdf0e10cSrcweir SCCOLROW nOutStartCol; // Zeilen/Spaltenstatus 468cdf0e10cSrcweir SCCOLROW nOutStartRow; 469cdf0e10cSrcweir SCCOLROW nOutEndCol; 470cdf0e10cSrcweir SCCOLROW nOutEndRow; 471cdf0e10cSrcweir pTable->GetColArray()->GetRange( nOutStartCol, nOutEndCol ); 472cdf0e10cSrcweir pTable->GetRowArray()->GetRange( nOutStartRow, nOutEndRow ); 473cdf0e10cSrcweir 474cdf0e10cSrcweir pUndoDoc->InitUndo( pDoc, nTab, nTab, sal_True, sal_True ); 475cdf0e10cSrcweir pDoc->CopyToDocument( static_cast<SCCOL>(nOutStartCol), 0, nTab, static_cast<SCCOL>(nOutEndCol), MAXROW, nTab, IDF_NONE, sal_False, pUndoDoc ); 476cdf0e10cSrcweir pDoc->CopyToDocument( 0, nOutStartRow, nTab, MAXCOL, nOutEndRow, nTab, IDF_NONE, sal_False, pUndoDoc ); 477cdf0e10cSrcweir } 478cdf0e10cSrcweir else 479cdf0e10cSrcweir pUndoDoc->InitUndo( pDoc, nTab, nTab, sal_False, bOldFilter ); 480cdf0e10cSrcweir 481cdf0e10cSrcweir // Datenbereich sichern - incl. Filter-Ergebnis 482cdf0e10cSrcweir pDoc->CopyToDocument( 0,rParam.nRow1+1,nTab, MAXCOL,rParam.nRow2,nTab, 483cdf0e10cSrcweir IDF_ALL, sal_False, pUndoDoc ); 484cdf0e10cSrcweir 485cdf0e10cSrcweir // alle Formeln wegen Referenzen 486cdf0e10cSrcweir pDoc->CopyToDocument( 0,0,0, MAXCOL,MAXROW,nTabCount-1, 487cdf0e10cSrcweir IDF_FORMULA, sal_False, pUndoDoc ); 488cdf0e10cSrcweir 489cdf0e10cSrcweir // DB- und andere Bereiche 490cdf0e10cSrcweir ScRangeName* pDocRange = pDoc->GetRangeName(); 491cdf0e10cSrcweir if (pDocRange->GetCount()) 492cdf0e10cSrcweir pUndoRange = new ScRangeName( *pDocRange ); 493cdf0e10cSrcweir ScDBCollection* pDocDB = pDoc->GetDBCollection(); 494cdf0e10cSrcweir if (pDocDB->GetCount()) 495cdf0e10cSrcweir pUndoDB = new ScDBCollection( *pDocDB ); 496cdf0e10cSrcweir } 497cdf0e10cSrcweir 498cdf0e10cSrcweir // pDoc->SetOutlineTable( nTab, NULL ); 499cdf0e10cSrcweir ScOutlineTable* pOut = pDoc->GetOutlineTable( nTab ); 500cdf0e10cSrcweir if (pOut) 501cdf0e10cSrcweir pOut->GetRowArray()->RemoveAll(); // nur Zeilen-Outlines loeschen 502cdf0e10cSrcweir 503cdf0e10cSrcweir if (rParam.bReplace) 504cdf0e10cSrcweir pDoc->RemoveSubTotals( nTab, aNewParam ); 505cdf0e10cSrcweir sal_Bool bSuccess = sal_True; 506cdf0e10cSrcweir if (bDo) 507cdf0e10cSrcweir { 508cdf0e10cSrcweir // Sortieren 509cdf0e10cSrcweir if ( rParam.bDoSort || pForceNewSort ) 510cdf0e10cSrcweir { 511cdf0e10cSrcweir pDBData->SetArea( nTab, aNewParam.nCol1,aNewParam.nRow1, aNewParam.nCol2,aNewParam.nRow2 ); 512cdf0e10cSrcweir 513cdf0e10cSrcweir // Teilergebnis-Felder vor die Sortierung setzen 514cdf0e10cSrcweir // (doppelte werden weggelassen, kann darum auch wieder aufgerufen werden) 515cdf0e10cSrcweir 516cdf0e10cSrcweir ScSortParam aOldSort; 517cdf0e10cSrcweir pDBData->GetSortParam( aOldSort ); 518cdf0e10cSrcweir ScSortParam aSortParam( aNewParam, pForceNewSort ? *pForceNewSort : aOldSort ); 519cdf0e10cSrcweir Sort( aSortParam, sal_False, sal_False ); 520cdf0e10cSrcweir } 521cdf0e10cSrcweir 522cdf0e10cSrcweir bSuccess = pDoc->DoSubTotals( nTab, aNewParam ); 523cdf0e10cSrcweir } 524cdf0e10cSrcweir ScRange aDirtyRange( aNewParam.nCol1, aNewParam.nRow1, nTab, 525cdf0e10cSrcweir aNewParam.nCol2, aNewParam.nRow2, nTab ); 526cdf0e10cSrcweir pDoc->SetDirty( aDirtyRange ); 527cdf0e10cSrcweir 528cdf0e10cSrcweir if (bRecord) 529cdf0e10cSrcweir { 530cdf0e10cSrcweir // ScDBData* pUndoDBData = pDBData ? new ScDBData( *pDBData ) : NULL; 531cdf0e10cSrcweir pDocSh->GetUndoManager()->AddUndoAction( 532cdf0e10cSrcweir new ScUndoSubTotals( pDocSh, nTab, 533cdf0e10cSrcweir rParam, aNewParam.nRow2, 534cdf0e10cSrcweir pUndoDoc, pUndoTab, // pUndoDBData, 535cdf0e10cSrcweir pUndoRange, pUndoDB ) ); 536cdf0e10cSrcweir } 537cdf0e10cSrcweir 538cdf0e10cSrcweir if (!bSuccess) 539cdf0e10cSrcweir { 540cdf0e10cSrcweir // "Kann keine Zeilen einfuegen" 541cdf0e10cSrcweir ErrorMessage(STR_MSSG_DOSUBTOTALS_2); 542cdf0e10cSrcweir } 543cdf0e10cSrcweir 544cdf0e10cSrcweir // merken 545cdf0e10cSrcweir pDBData->SetSubTotalParam( aNewParam ); 546cdf0e10cSrcweir pDBData->SetArea( nTab, aNewParam.nCol1,aNewParam.nRow1, aNewParam.nCol2,aNewParam.nRow2 ); 547cdf0e10cSrcweir pDoc->CompileDBFormula(); 548cdf0e10cSrcweir 549cdf0e10cSrcweir DoneBlockMode(); 550cdf0e10cSrcweir InitOwnBlockMode(); 551cdf0e10cSrcweir rMark.SetMarkArea( ScRange( aNewParam.nCol1,aNewParam.nRow1,nTab, 552cdf0e10cSrcweir aNewParam.nCol2,aNewParam.nRow2,nTab ) ); 553cdf0e10cSrcweir MarkDataChanged(); 554cdf0e10cSrcweir 555cdf0e10cSrcweir pDocSh->PostPaint( 0,0,nTab, MAXCOL,MAXROW,nTab, 556cdf0e10cSrcweir PAINT_GRID | PAINT_LEFT | PAINT_TOP | PAINT_SIZE ); 557cdf0e10cSrcweir 558cdf0e10cSrcweir aModificator.SetDocumentModified(); 559cdf0e10cSrcweir 560cdf0e10cSrcweir SelectionChanged(); 561cdf0e10cSrcweir } 562cdf0e10cSrcweir } 563cdf0e10cSrcweir 564cdf0e10cSrcweir // 565cdf0e10cSrcweir // Consolidate 566cdf0e10cSrcweir // 567cdf0e10cSrcweir 568cdf0e10cSrcweir void ScDBFunc::Consolidate( const ScConsolidateParam& rParam, sal_Bool bRecord ) 569cdf0e10cSrcweir { 570cdf0e10cSrcweir ScDocShell* pDocShell = GetViewData()->GetDocShell(); 571cdf0e10cSrcweir pDocShell->DoConsolidate( rParam, bRecord ); 572cdf0e10cSrcweir SetTabNo( rParam.nTab, sal_True ); 573cdf0e10cSrcweir } 574cdf0e10cSrcweir 575cdf0e10cSrcweir // 576cdf0e10cSrcweir // Pivot 577cdf0e10cSrcweir // 578cdf0e10cSrcweir 579cdf0e10cSrcweir String lcl_MakePivotTabName( const String& rPrefix, SCTAB nNumber ) 580cdf0e10cSrcweir { 581cdf0e10cSrcweir String aName = rPrefix; 582cdf0e10cSrcweir aName += String::CreateFromInt32( nNumber ); 583cdf0e10cSrcweir return aName; 584cdf0e10cSrcweir } 585cdf0e10cSrcweir 586cdf0e10cSrcweir bool ScDBFunc::MakePivotTable( const ScDPSaveData& rData, const ScRange& rDest, sal_Bool bNewTable, 587cdf0e10cSrcweir const ScDPObject& rSource, sal_Bool bApi ) 588cdf0e10cSrcweir { 589cdf0e10cSrcweir // #70096# error message if no fields are set 590cdf0e10cSrcweir // this must be removed when drag&drop of fields from a toolbox is available 591cdf0e10cSrcweir 592cdf0e10cSrcweir if ( rData.IsEmpty() && !bApi ) 593cdf0e10cSrcweir { 594cdf0e10cSrcweir ErrorMessage(STR_PIVOT_NODATA); 595cdf0e10cSrcweir return false; 596cdf0e10cSrcweir } 597cdf0e10cSrcweir 598cdf0e10cSrcweir ScDocShell* pDocSh = GetViewData()->GetDocShell(); 599cdf0e10cSrcweir ScDocument* pDoc = GetViewData()->GetDocument(); 600cdf0e10cSrcweir sal_Bool bUndo(pDoc->IsUndoEnabled()); 601cdf0e10cSrcweir 602cdf0e10cSrcweir ScRange aDestRange = rDest; 603cdf0e10cSrcweir if ( bNewTable ) 604cdf0e10cSrcweir { 605cdf0e10cSrcweir SCTAB nSrcTab = GetViewData()->GetTabNo(); 606cdf0e10cSrcweir 607cdf0e10cSrcweir String aName( ScGlobal::GetRscString(STR_PIVOT_TABLE) ); 608cdf0e10cSrcweir String aStr; 609cdf0e10cSrcweir 610cdf0e10cSrcweir pDoc->GetName( nSrcTab, aStr ); 611cdf0e10cSrcweir aName += '_'; 612cdf0e10cSrcweir aName += aStr; 613cdf0e10cSrcweir aName += '_'; 614cdf0e10cSrcweir 615cdf0e10cSrcweir SCTAB nNewTab = nSrcTab+1; 616cdf0e10cSrcweir 617cdf0e10cSrcweir SCTAB i=1; 618cdf0e10cSrcweir while ( !pDoc->InsertTab( nNewTab, lcl_MakePivotTabName( aName, i ) ) && i <= MAXTAB ) 619cdf0e10cSrcweir i++; 620cdf0e10cSrcweir 621cdf0e10cSrcweir sal_Bool bAppend = ( nNewTab+1 == pDoc->GetTableCount() ); 622cdf0e10cSrcweir if (bUndo) 623cdf0e10cSrcweir { 624cdf0e10cSrcweir pDocSh->GetUndoManager()->AddUndoAction( 625cdf0e10cSrcweir new ScUndoInsertTab( pDocSh, nNewTab, bAppend, lcl_MakePivotTabName( aName, i ) )); 626cdf0e10cSrcweir } 627cdf0e10cSrcweir 628cdf0e10cSrcweir GetViewData()->InsertTab( nNewTab ); 629cdf0e10cSrcweir SetTabNo( nNewTab, sal_True ); 630cdf0e10cSrcweir 631cdf0e10cSrcweir aDestRange = ScRange( 0, 0, nNewTab ); 632cdf0e10cSrcweir } 633cdf0e10cSrcweir 634cdf0e10cSrcweir ScDPObject* pDPObj = pDoc->GetDPAtCursor( 635cdf0e10cSrcweir aDestRange.aStart.Col(), aDestRange.aStart.Row(), aDestRange.aStart.Tab() ); 636cdf0e10cSrcweir 637cdf0e10cSrcweir ScDPObject aObj( rSource ); 638cdf0e10cSrcweir aObj.SetOutRange( aDestRange ); 639cdf0e10cSrcweir if ( pDPObj && !rData.GetExistingDimensionData() ) 640cdf0e10cSrcweir { 641cdf0e10cSrcweir // copy dimension data from old object - lost in the dialog 642cdf0e10cSrcweir //! change the dialog to keep the dimension data 643cdf0e10cSrcweir 644cdf0e10cSrcweir ScDPSaveData aNewData( rData ); 645cdf0e10cSrcweir const ScDPSaveData* pOldData = pDPObj->GetSaveData(); 646cdf0e10cSrcweir if ( pOldData ) 647cdf0e10cSrcweir { 648cdf0e10cSrcweir const ScDPDimensionSaveData* pDimSave = pOldData->GetExistingDimensionData(); 649cdf0e10cSrcweir aNewData.SetDimensionData( pDimSave ); 650cdf0e10cSrcweir } 651cdf0e10cSrcweir aObj.SetSaveData( aNewData ); 652cdf0e10cSrcweir } 653cdf0e10cSrcweir else 654cdf0e10cSrcweir aObj.SetSaveData( rData ); 655cdf0e10cSrcweir 656cdf0e10cSrcweir sal_Bool bAllowMove = ( pDPObj != NULL ); // allow re-positioning when editing existing table 657cdf0e10cSrcweir 658cdf0e10cSrcweir ScDBDocFunc aFunc( *pDocSh ); 659cdf0e10cSrcweir bool bSuccess = aFunc.DataPilotUpdate( pDPObj, &aObj, sal_True, sal_False, bAllowMove ); 660cdf0e10cSrcweir 661cdf0e10cSrcweir CursorPosChanged(); // shells may be switched 662cdf0e10cSrcweir 663cdf0e10cSrcweir if ( bNewTable ) 664cdf0e10cSrcweir { 665cdf0e10cSrcweir pDocSh->PostPaintExtras(); 666cdf0e10cSrcweir SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_TABLES_CHANGED ) ); 667cdf0e10cSrcweir } 668cdf0e10cSrcweir 669cdf0e10cSrcweir return bSuccess; 670cdf0e10cSrcweir } 671cdf0e10cSrcweir 672cdf0e10cSrcweir void ScDBFunc::DeletePivotTable() 673cdf0e10cSrcweir { 674cdf0e10cSrcweir ScDocShell* pDocSh = GetViewData()->GetDocShell(); 675cdf0e10cSrcweir ScDocument* pDoc = pDocSh->GetDocument(); 676cdf0e10cSrcweir ScDPObject* pDPObj = pDoc->GetDPAtCursor( GetViewData()->GetCurX(), 677cdf0e10cSrcweir GetViewData()->GetCurY(), 678cdf0e10cSrcweir GetViewData()->GetTabNo() ); 679cdf0e10cSrcweir if ( pDPObj ) 680cdf0e10cSrcweir { 681cdf0e10cSrcweir ScDBDocFunc aFunc( *pDocSh ); 682cdf0e10cSrcweir aFunc.DataPilotUpdate( pDPObj, NULL, sal_True, sal_False ); 683cdf0e10cSrcweir CursorPosChanged(); // shells may be switched 684cdf0e10cSrcweir } 685cdf0e10cSrcweir else 686cdf0e10cSrcweir ErrorMessage(STR_PIVOT_NOTFOUND); 687cdf0e10cSrcweir } 688cdf0e10cSrcweir sal_uLong RefreshDPObject( ScDPObject *pDPObj, ScDocument *pDoc, ScDocShell *pDocSh, sal_Bool bRecord, sal_Bool bApi ) 689cdf0e10cSrcweir { 690cdf0e10cSrcweir if( !pDPObj ) 691cdf0e10cSrcweir return STR_PIVOT_NOTFOUND; 692cdf0e10cSrcweir 693cdf0e10cSrcweir if ( pDocSh && !pDoc ) 694cdf0e10cSrcweir pDoc = pDocSh->GetDocument(); 695cdf0e10cSrcweir 696cdf0e10cSrcweir if( !pDoc ) 697cdf0e10cSrcweir return static_cast<sal_uLong>(-1); 698cdf0e10cSrcweir 699cdf0e10cSrcweir if( !pDocSh && ( pDocSh = PTR_CAST( ScDocShell, pDoc->GetDocumentShell() ) ) == NULL ) 700cdf0e10cSrcweir return static_cast<sal_uLong>(-1); 701cdf0e10cSrcweir 702cdf0e10cSrcweir if( sal_uLong nErrId = pDPObj->RefreshCache() ) 703cdf0e10cSrcweir return nErrId; 704cdf0e10cSrcweir else if ( nErrId == 0 ) 705cdf0e10cSrcweir { 706cdf0e10cSrcweir //Refresh all dpobjects 707cdf0e10cSrcweir ScDPCollection* pDPCollection = pDoc->GetDPCollection(); 708cdf0e10cSrcweir sal_uInt16 nCount = pDPCollection->GetCount(); 709cdf0e10cSrcweir for (sal_uInt16 i=0; i<nCount; i++) 710cdf0e10cSrcweir { 711cdf0e10cSrcweir if ( (*pDPCollection)[i]->GetCacheId() == pDPObj->GetCacheId() ) 712cdf0e10cSrcweir { 713cdf0e10cSrcweir ScDBDocFunc aFunc( * pDocSh ); 714cdf0e10cSrcweir if ( !aFunc.DataPilotUpdate( (*pDPCollection)[i], (*pDPCollection)[i], bRecord, bApi ) ) 715cdf0e10cSrcweir break; 716cdf0e10cSrcweir } 717cdf0e10cSrcweir } 718cdf0e10cSrcweir 719cdf0e10cSrcweir return nErrId; 720cdf0e10cSrcweir } 721cdf0e10cSrcweir 722cdf0e10cSrcweir return 0U; 723cdf0e10cSrcweir } 724cdf0e10cSrcweir 725cdf0e10cSrcweir sal_uLong ScDBFunc::RecalcPivotTable() 726cdf0e10cSrcweir { 727cdf0e10cSrcweir ScDocShell* pDocSh = GetViewData()->GetDocShell(); 728cdf0e10cSrcweir ScDocument* pDoc = GetViewData()->GetDocument(); 729cdf0e10cSrcweir 730cdf0e10cSrcweir // old pivot not used any more 731cdf0e10cSrcweir 732cdf0e10cSrcweir ScDPObject* pDPObj = pDoc->GetDPAtCursor( GetViewData()->GetCurX(), 733cdf0e10cSrcweir GetViewData()->GetCurY(), 734cdf0e10cSrcweir GetViewData()->GetTabNo() ); 735cdf0e10cSrcweir if ( pDPObj ) 736cdf0e10cSrcweir { 737cdf0e10cSrcweir // Wang Xu Ming -- 2009-6-17 738cdf0e10cSrcweir // DataPilot Migration 739cdf0e10cSrcweir //ScDBDocFunc aFunc( *pDocSh ); 740cdf0e10cSrcweir //aFunc.DataPilotUpdate( pDPObj, pDPObj, sal_True, sal_False ); 741cdf0e10cSrcweir //CursorPosChanged(); // shells may be switched 742cdf0e10cSrcweir sal_uLong nErrId = RefreshDPObject( pDPObj, pDoc, pDocSh, sal_True, sal_False );//pDPObj->RefreshCache(); 743cdf0e10cSrcweir if ( nErrId == 0 ) 744cdf0e10cSrcweir { 745cdf0e10cSrcweir // There is no undo for the refresh of the cache table, but the undo history for cell changes 746cdf0e10cSrcweir // remains valid and should be preserved, so the history isn't cleared here. 747cdf0e10cSrcweir //GetViewData()->GetDocShell()->GetUndoManager()->Clear(); 748cdf0e10cSrcweir } 749cdf0e10cSrcweir else if (nErrId <= USHRT_MAX) 750cdf0e10cSrcweir ErrorMessage(static_cast<sal_uInt16>(nErrId)); 751cdf0e10cSrcweir return nErrId; 752cdf0e10cSrcweir // End Comments 753cdf0e10cSrcweir } 754cdf0e10cSrcweir else 755cdf0e10cSrcweir ErrorMessage(STR_PIVOT_NOTFOUND); 756cdf0e10cSrcweir return STR_PIVOT_NOTFOUND; 757cdf0e10cSrcweir } 758cdf0e10cSrcweir 759cdf0e10cSrcweir void ScDBFunc::GetSelectedMemberList( ScStrCollection& rEntries, long& rDimension ) 760cdf0e10cSrcweir { 761cdf0e10cSrcweir ScDPObject* pDPObj = GetViewData()->GetDocument()->GetDPAtCursor( GetViewData()->GetCurX(), 762cdf0e10cSrcweir GetViewData()->GetCurY(), GetViewData()->GetTabNo() ); 763cdf0e10cSrcweir if ( !pDPObj ) 764cdf0e10cSrcweir return; 765cdf0e10cSrcweir 766cdf0e10cSrcweir long nStartDimension = -1; 767cdf0e10cSrcweir long nStartHierarchy = -1; 768cdf0e10cSrcweir long nStartLevel = -1; 769cdf0e10cSrcweir 770cdf0e10cSrcweir ScRangeListRef xRanges; 771cdf0e10cSrcweir GetViewData()->GetMultiArea( xRanges ); // incl. cursor if nothing is selected 772cdf0e10cSrcweir sal_uLong nRangeCount = xRanges->Count(); 773cdf0e10cSrcweir sal_Bool bContinue = sal_True; 774cdf0e10cSrcweir 775cdf0e10cSrcweir for (sal_uLong nRangePos=0; nRangePos<nRangeCount && bContinue; nRangePos++) 776cdf0e10cSrcweir { 777cdf0e10cSrcweir ScRange aRange = *xRanges->GetObject(nRangePos); 778cdf0e10cSrcweir SCCOL nStartCol = aRange.aStart.Col(); 779cdf0e10cSrcweir SCROW nStartRow = aRange.aStart.Row(); 780cdf0e10cSrcweir SCCOL nEndCol = aRange.aEnd.Col(); 781cdf0e10cSrcweir SCROW nEndRow = aRange.aEnd.Row(); 782cdf0e10cSrcweir SCTAB nTab = aRange.aStart.Tab(); 783cdf0e10cSrcweir 784cdf0e10cSrcweir for (SCROW nRow=nStartRow; nRow<=nEndRow && bContinue; nRow++) 785cdf0e10cSrcweir for (SCCOL nCol=nStartCol; nCol<=nEndCol && bContinue; nCol++) 786cdf0e10cSrcweir { 787cdf0e10cSrcweir sheet::DataPilotTableHeaderData aData; 788cdf0e10cSrcweir pDPObj->GetHeaderPositionData(ScAddress(nCol, nRow, nTab), aData); 789cdf0e10cSrcweir if ( aData.Dimension < 0 ) 790cdf0e10cSrcweir bContinue = sal_False; // not part of any dimension 791cdf0e10cSrcweir else 792cdf0e10cSrcweir { 793cdf0e10cSrcweir if ( nStartDimension < 0 ) // first member? 794cdf0e10cSrcweir { 795cdf0e10cSrcweir nStartDimension = aData.Dimension; 796cdf0e10cSrcweir nStartHierarchy = aData.Hierarchy; 797cdf0e10cSrcweir nStartLevel = aData.Level; 798cdf0e10cSrcweir } 799cdf0e10cSrcweir if ( aData.Dimension != nStartDimension || 800cdf0e10cSrcweir aData.Hierarchy != nStartHierarchy || 801cdf0e10cSrcweir aData.Level != nStartLevel ) 802cdf0e10cSrcweir { 803cdf0e10cSrcweir bContinue = sal_False; // cannot mix dimensions 804cdf0e10cSrcweir } 805cdf0e10cSrcweir } 806cdf0e10cSrcweir if ( bContinue ) 807cdf0e10cSrcweir { 808cdf0e10cSrcweir // accept any part of a member description, also subtotals, 809cdf0e10cSrcweir // but don't stop if empty parts are contained 810cdf0e10cSrcweir if ( aData.Flags & sheet::MemberResultFlags::HASMEMBER ) 811cdf0e10cSrcweir { 812cdf0e10cSrcweir StrData* pNew = new StrData( aData.MemberName ); 813cdf0e10cSrcweir if ( !rEntries.Insert( pNew ) ) 814cdf0e10cSrcweir delete pNew; 815cdf0e10cSrcweir } 816cdf0e10cSrcweir } 817cdf0e10cSrcweir } 818cdf0e10cSrcweir } 819cdf0e10cSrcweir 820cdf0e10cSrcweir rDimension = nStartDimension; // dimension from which the found members came 821cdf0e10cSrcweir if (!bContinue) 822cdf0e10cSrcweir rEntries.FreeAll(); // remove all if not valid 823cdf0e10cSrcweir } 824cdf0e10cSrcweir 825cdf0e10cSrcweir sal_Bool ScDBFunc::HasSelectionForDateGroup( ScDPNumGroupInfo& rOldInfo, sal_Int32& rParts ) 826cdf0e10cSrcweir { 827cdf0e10cSrcweir // determine if the date group dialog has to be shown for the current selection 828cdf0e10cSrcweir 829cdf0e10cSrcweir sal_Bool bFound = sal_False; 830cdf0e10cSrcweir 831cdf0e10cSrcweir SCCOL nCurX = GetViewData()->GetCurX(); 832cdf0e10cSrcweir SCROW nCurY = GetViewData()->GetCurY(); 833cdf0e10cSrcweir SCTAB nTab = GetViewData()->GetTabNo(); 834cdf0e10cSrcweir ScDocument* pDoc = GetViewData()->GetDocument(); 835cdf0e10cSrcweir 836cdf0e10cSrcweir ScDPObject* pDPObj = pDoc->GetDPAtCursor( nCurX, nCurY, nTab ); 837cdf0e10cSrcweir if ( pDPObj ) 838cdf0e10cSrcweir { 839cdf0e10cSrcweir ScStrCollection aEntries; 840cdf0e10cSrcweir long nSelectDimension = -1; 841cdf0e10cSrcweir GetSelectedMemberList( aEntries, nSelectDimension ); 842cdf0e10cSrcweir 843cdf0e10cSrcweir if ( aEntries.GetCount() > 0 ) 844cdf0e10cSrcweir { 845cdf0e10cSrcweir sal_Bool bIsDataLayout; 846cdf0e10cSrcweir String aDimName = pDPObj->GetDimName( nSelectDimension, bIsDataLayout ); 847cdf0e10cSrcweir String aBaseDimName( aDimName ); 848cdf0e10cSrcweir 849cdf0e10cSrcweir sal_Bool bInGroupDim = sal_False; 850cdf0e10cSrcweir sal_Bool bFoundParts = sal_False; 851cdf0e10cSrcweir 852cdf0e10cSrcweir ScDPDimensionSaveData* pDimData = 853cdf0e10cSrcweir const_cast<ScDPDimensionSaveData*>( pDPObj->GetSaveData()->GetExistingDimensionData() ); 854cdf0e10cSrcweir if ( pDimData ) 855cdf0e10cSrcweir { 856cdf0e10cSrcweir const ScDPSaveNumGroupDimension* pNumGroupDim = pDimData->GetNumGroupDim( aDimName ); 857cdf0e10cSrcweir const ScDPSaveGroupDimension* pGroupDim = pDimData->GetNamedGroupDim( aDimName ); 858cdf0e10cSrcweir if ( pNumGroupDim ) 859cdf0e10cSrcweir { 860cdf0e10cSrcweir // existing num group dimension 861cdf0e10cSrcweir 862cdf0e10cSrcweir if ( pNumGroupDim->GetDatePart() != 0 ) 863cdf0e10cSrcweir { 864cdf0e10cSrcweir // dimension has date info -> edit settings of this dimension 865cdf0e10cSrcweir // (parts are collected below) 866cdf0e10cSrcweir 867cdf0e10cSrcweir rOldInfo = pNumGroupDim->GetDateInfo(); 868cdf0e10cSrcweir bFound = sal_True; 869cdf0e10cSrcweir } 870cdf0e10cSrcweir else if ( pNumGroupDim->GetInfo().DateValues ) 871cdf0e10cSrcweir { 872cdf0e10cSrcweir // Numerical grouping with DateValues flag is used for grouping 873cdf0e10cSrcweir // of days with a "Number of days" value. 874cdf0e10cSrcweir 875cdf0e10cSrcweir rOldInfo = pNumGroupDim->GetInfo(); 876cdf0e10cSrcweir rParts = com::sun::star::sheet::DataPilotFieldGroupBy::DAYS; // not found in CollectDateParts 877cdf0e10cSrcweir bFoundParts = sal_True; 878cdf0e10cSrcweir bFound = sal_True; 879cdf0e10cSrcweir } 880cdf0e10cSrcweir bInGroupDim = sal_True; 881cdf0e10cSrcweir } 882cdf0e10cSrcweir else if ( pGroupDim ) 883cdf0e10cSrcweir { 884cdf0e10cSrcweir // existing additional group dimension 885cdf0e10cSrcweir 886cdf0e10cSrcweir if ( pGroupDim->GetDatePart() != 0 ) 887cdf0e10cSrcweir { 888cdf0e10cSrcweir // dimension has date info -> edit settings of this dimension 889cdf0e10cSrcweir // (parts are collected below) 890cdf0e10cSrcweir 891cdf0e10cSrcweir rOldInfo = pGroupDim->GetDateInfo(); 892cdf0e10cSrcweir aBaseDimName = pGroupDim->GetSourceDimName(); 893cdf0e10cSrcweir bFound = sal_True; 894cdf0e10cSrcweir } 895cdf0e10cSrcweir bInGroupDim = sal_True; 896cdf0e10cSrcweir } 897cdf0e10cSrcweir } 898cdf0e10cSrcweir if ( bFound && !bFoundParts ) 899cdf0e10cSrcweir { 900cdf0e10cSrcweir // collect date parts from all group dimensions 901cdf0e10cSrcweir rParts = pDimData->CollectDateParts( aBaseDimName ); 902cdf0e10cSrcweir } 903cdf0e10cSrcweir if ( !bFound && !bInGroupDim ) 904cdf0e10cSrcweir { 905cdf0e10cSrcweir // create new date group dimensions if the selection is a single cell 906cdf0e10cSrcweir // in a normal dimension with date content 907cdf0e10cSrcweir 908cdf0e10cSrcweir ScRange aSelRange; 909cdf0e10cSrcweir if ( (GetViewData()->GetSimpleArea( aSelRange ) == SC_MARK_SIMPLE) && 910cdf0e10cSrcweir aSelRange.aStart == aSelRange.aEnd ) 911cdf0e10cSrcweir { 912cdf0e10cSrcweir SCCOL nSelCol = aSelRange.aStart.Col(); 913cdf0e10cSrcweir SCROW nSelRow = aSelRange.aStart.Row(); 914cdf0e10cSrcweir SCTAB nSelTab = aSelRange.aStart.Tab(); 915cdf0e10cSrcweir if ( pDoc->HasValueData( nSelCol, nSelRow, nSelTab ) ) 916cdf0e10cSrcweir { 917cdf0e10cSrcweir sal_uLong nIndex = static_cast<const SfxUInt32Item*>(pDoc->GetAttr( 918cdf0e10cSrcweir nSelCol, nSelRow, nSelTab, ATTR_VALUE_FORMAT))->GetValue(); 919cdf0e10cSrcweir short nType = pDoc->GetFormatTable()->GetType(nIndex); 920cdf0e10cSrcweir if ( nType == NUMBERFORMAT_DATE || nType == NUMBERFORMAT_TIME || nType == NUMBERFORMAT_DATETIME ) 921cdf0e10cSrcweir { 922cdf0e10cSrcweir bFound = sal_True; 923cdf0e10cSrcweir // use currently selected value for automatic limits 924cdf0e10cSrcweir if( rOldInfo.AutoStart ) 925cdf0e10cSrcweir rOldInfo.Start = pDoc->GetValue( aSelRange.aStart ); 926cdf0e10cSrcweir if( rOldInfo.AutoEnd ) 927cdf0e10cSrcweir rOldInfo.End = pDoc->GetValue( aSelRange.aStart ); 928cdf0e10cSrcweir } 929cdf0e10cSrcweir } 930cdf0e10cSrcweir } 931cdf0e10cSrcweir } 932cdf0e10cSrcweir } 933cdf0e10cSrcweir } 934cdf0e10cSrcweir 935cdf0e10cSrcweir return bFound; 936cdf0e10cSrcweir } 937cdf0e10cSrcweir 938cdf0e10cSrcweir sal_Bool ScDBFunc::HasSelectionForNumGroup( ScDPNumGroupInfo& rOldInfo ) 939cdf0e10cSrcweir { 940cdf0e10cSrcweir // determine if the numeric group dialog has to be shown for the current selection 941cdf0e10cSrcweir 942cdf0e10cSrcweir sal_Bool bFound = sal_False; 943cdf0e10cSrcweir 944cdf0e10cSrcweir SCCOL nCurX = GetViewData()->GetCurX(); 945cdf0e10cSrcweir SCROW nCurY = GetViewData()->GetCurY(); 946cdf0e10cSrcweir SCTAB nTab = GetViewData()->GetTabNo(); 947cdf0e10cSrcweir ScDocument* pDoc = GetViewData()->GetDocument(); 948cdf0e10cSrcweir 949cdf0e10cSrcweir ScDPObject* pDPObj = pDoc->GetDPAtCursor( nCurX, nCurY, nTab ); 950cdf0e10cSrcweir if ( pDPObj ) 951cdf0e10cSrcweir { 952cdf0e10cSrcweir ScStrCollection aEntries; 953cdf0e10cSrcweir long nSelectDimension = -1; 954cdf0e10cSrcweir GetSelectedMemberList( aEntries, nSelectDimension ); 955cdf0e10cSrcweir 956cdf0e10cSrcweir if ( aEntries.GetCount() > 0 ) 957cdf0e10cSrcweir { 958cdf0e10cSrcweir sal_Bool bIsDataLayout; 959cdf0e10cSrcweir String aDimName = pDPObj->GetDimName( nSelectDimension, bIsDataLayout ); 960cdf0e10cSrcweir 961cdf0e10cSrcweir sal_Bool bInGroupDim = sal_False; 962cdf0e10cSrcweir 963cdf0e10cSrcweir ScDPDimensionSaveData* pDimData = 964cdf0e10cSrcweir const_cast<ScDPDimensionSaveData*>( pDPObj->GetSaveData()->GetExistingDimensionData() ); 965cdf0e10cSrcweir if ( pDimData ) 966cdf0e10cSrcweir { 967cdf0e10cSrcweir const ScDPSaveNumGroupDimension* pNumGroupDim = pDimData->GetNumGroupDim( aDimName ); 968cdf0e10cSrcweir if ( pNumGroupDim ) 969cdf0e10cSrcweir { 970cdf0e10cSrcweir // existing num group dimension 971cdf0e10cSrcweir // -> edit settings of this dimension 972cdf0e10cSrcweir 973cdf0e10cSrcweir rOldInfo = pNumGroupDim->GetInfo(); 974cdf0e10cSrcweir bFound = sal_True; 975cdf0e10cSrcweir } 976cdf0e10cSrcweir else if ( pDimData->GetNamedGroupDim( aDimName ) ) 977cdf0e10cSrcweir bInGroupDim = sal_True; // in a group dimension 978cdf0e10cSrcweir } 979cdf0e10cSrcweir if ( !bFound && !bInGroupDim ) 980cdf0e10cSrcweir { 981cdf0e10cSrcweir // create a new num group dimension if the selection is a single cell 982cdf0e10cSrcweir // in a normal dimension with numeric content 983cdf0e10cSrcweir 984cdf0e10cSrcweir ScRange aSelRange; 985cdf0e10cSrcweir if ( (GetViewData()->GetSimpleArea( aSelRange ) == SC_MARK_SIMPLE) && 986cdf0e10cSrcweir aSelRange.aStart == aSelRange.aEnd ) 987cdf0e10cSrcweir { 988cdf0e10cSrcweir if ( pDoc->HasValueData( aSelRange.aStart.Col(), aSelRange.aStart.Row(), 989cdf0e10cSrcweir aSelRange.aStart.Tab() ) ) 990cdf0e10cSrcweir { 991cdf0e10cSrcweir bFound = sal_True; 992cdf0e10cSrcweir // use currently selected value for automatic limits 993cdf0e10cSrcweir if( rOldInfo.AutoStart ) 994cdf0e10cSrcweir rOldInfo.Start = pDoc->GetValue( aSelRange.aStart ); 995cdf0e10cSrcweir if( rOldInfo.AutoEnd ) 996cdf0e10cSrcweir rOldInfo.End = pDoc->GetValue( aSelRange.aStart ); 997cdf0e10cSrcweir } 998cdf0e10cSrcweir } 999cdf0e10cSrcweir } 1000cdf0e10cSrcweir } 1001cdf0e10cSrcweir } 1002cdf0e10cSrcweir 1003cdf0e10cSrcweir return bFound; 1004cdf0e10cSrcweir } 1005cdf0e10cSrcweir 1006cdf0e10cSrcweir void ScDBFunc::DateGroupDataPilot( const ScDPNumGroupInfo& rInfo, sal_Int32 nParts ) 1007cdf0e10cSrcweir { 1008cdf0e10cSrcweir ScDPObject* pDPObj = GetViewData()->GetDocument()->GetDPAtCursor( GetViewData()->GetCurX(), 1009cdf0e10cSrcweir GetViewData()->GetCurY(), GetViewData()->GetTabNo() ); 1010cdf0e10cSrcweir if ( pDPObj ) 1011cdf0e10cSrcweir { 1012cdf0e10cSrcweir ScStrCollection aEntries; 1013cdf0e10cSrcweir long nSelectDimension = -1; 1014cdf0e10cSrcweir GetSelectedMemberList( aEntries, nSelectDimension ); 1015cdf0e10cSrcweir 1016cdf0e10cSrcweir if ( aEntries.GetCount() > 0 ) 1017cdf0e10cSrcweir { 1018cdf0e10cSrcweir sal_Bool bIsDataLayout; 1019cdf0e10cSrcweir String aDimName = pDPObj->GetDimName( nSelectDimension, bIsDataLayout ); 1020cdf0e10cSrcweir 1021cdf0e10cSrcweir ScDPSaveData aData( *pDPObj->GetSaveData() ); 1022cdf0e10cSrcweir ScDPDimensionSaveData* pDimData = aData.GetDimensionData(); // created if not there 1023cdf0e10cSrcweir 1024cdf0e10cSrcweir // find original base 1025cdf0e10cSrcweir String aBaseDimName = aDimName; 1026cdf0e10cSrcweir if( const ScDPSaveGroupDimension* pBaseGroupDim = pDimData->GetNamedGroupDim( aDimName ) ) 1027cdf0e10cSrcweir aBaseDimName = pBaseGroupDim->GetSourceDimName(); 1028cdf0e10cSrcweir 1029cdf0e10cSrcweir // remove all existing parts (the grouping is built completely new) 1030cdf0e10cSrcweir 1031cdf0e10cSrcweir /* Remove numeric group dimension (exists once at most). No need 1032cdf0e10cSrcweir to delete anything in save data (grouping was done inplace in 1033cdf0e10cSrcweir an existing base dimension). */ 1034cdf0e10cSrcweir pDimData->RemoveNumGroupDimension( aBaseDimName ); 1035cdf0e10cSrcweir 1036cdf0e10cSrcweir /* Remove named group dimension(s). Collect deleted dimension 1037cdf0e10cSrcweir names which may be reused while recreating the groups. 1038cdf0e10cSrcweir Dimensions have to be removed from dimension save data and from 1039cdf0e10cSrcweir save data too. */ 1040cdf0e10cSrcweir std::vector< String > aDeletedNames; 1041cdf0e10cSrcweir const ScDPSaveGroupDimension* pExistingGroup = pDimData->GetGroupDimForBase( aBaseDimName ); 1042cdf0e10cSrcweir while ( pExistingGroup ) 1043cdf0e10cSrcweir { 1044cdf0e10cSrcweir String aGroupDimName = pExistingGroup->GetGroupDimName(); 1045cdf0e10cSrcweir pDimData->RemoveGroupDimension( aGroupDimName ); // pExistingGroup is deleted 1046cdf0e10cSrcweir 1047cdf0e10cSrcweir // also remove SaveData settings for the dimension that no longer exists 1048cdf0e10cSrcweir aData.RemoveDimensionByName( aGroupDimName ); 1049cdf0e10cSrcweir 1050cdf0e10cSrcweir /* The name can be used for the new group dimensions, although 1051cdf0e10cSrcweir it is still in use with the DataPilotSource. */ 1052cdf0e10cSrcweir aDeletedNames.push_back( aGroupDimName ); 1053cdf0e10cSrcweir 1054cdf0e10cSrcweir // see if there are more group dimensions 1055cdf0e10cSrcweir pExistingGroup = pDimData->GetGroupDimForBase( aBaseDimName ); 1056cdf0e10cSrcweir 1057cdf0e10cSrcweir if ( pExistingGroup && pExistingGroup->GetGroupDimName() == aGroupDimName ) 1058cdf0e10cSrcweir { 1059cdf0e10cSrcweir // still get the same group dimension? 1060cdf0e10cSrcweir DBG_ERROR("couldn't remove group dimension"); 1061cdf0e10cSrcweir pExistingGroup = NULL; // avoid endless loop 1062cdf0e10cSrcweir } 1063cdf0e10cSrcweir } 1064cdf0e10cSrcweir 1065cdf0e10cSrcweir if ( nParts ) 1066cdf0e10cSrcweir { 1067cdf0e10cSrcweir // create date group dimensions 1068cdf0e10cSrcweir 1069cdf0e10cSrcweir ScDPNumGroupInfo aEmpty; 1070cdf0e10cSrcweir bool bFirst = true; 1071cdf0e10cSrcweir sal_Int32 nMask = 1; 1072cdf0e10cSrcweir for (sal_uInt16 nBit=0; nBit<32; nBit++) 1073cdf0e10cSrcweir { 1074cdf0e10cSrcweir if ( nParts & nMask ) 1075cdf0e10cSrcweir { 1076cdf0e10cSrcweir if ( bFirst ) 1077cdf0e10cSrcweir { 1078cdf0e10cSrcweir // innermost part: create NumGroupDimension (replacing original values) 1079cdf0e10cSrcweir // Dimension name is left unchanged 1080cdf0e10cSrcweir 1081cdf0e10cSrcweir if ( (nParts == sheet::DataPilotFieldGroupBy::DAYS) && (rInfo.Step >= 1.0) ) 1082cdf0e10cSrcweir { 1083cdf0e10cSrcweir // only days, and a step value specified: use numerical grouping 1084cdf0e10cSrcweir // with DateValues flag, not date grouping 1085cdf0e10cSrcweir 1086cdf0e10cSrcweir ScDPNumGroupInfo aNumInfo( rInfo ); 1087cdf0e10cSrcweir aNumInfo.DateValues = sal_True; 1088cdf0e10cSrcweir 1089cdf0e10cSrcweir ScDPSaveNumGroupDimension aNumGroupDim( aBaseDimName, aNumInfo ); 1090cdf0e10cSrcweir pDimData->AddNumGroupDimension( aNumGroupDim ); 1091cdf0e10cSrcweir } 1092cdf0e10cSrcweir else 1093cdf0e10cSrcweir { 1094cdf0e10cSrcweir ScDPSaveNumGroupDimension aNumGroupDim( aBaseDimName, rInfo, nMask ); 1095cdf0e10cSrcweir pDimData->AddNumGroupDimension( aNumGroupDim ); 1096cdf0e10cSrcweir } 1097cdf0e10cSrcweir 1098cdf0e10cSrcweir bFirst = false; 1099cdf0e10cSrcweir } 1100cdf0e10cSrcweir else 1101cdf0e10cSrcweir { 1102cdf0e10cSrcweir // additional parts: create GroupDimension (shown as additional dimensions) 1103cdf0e10cSrcweir String aGroupDimName = pDimData->CreateDateGroupDimName( nMask, *pDPObj, true, &aDeletedNames ); 1104cdf0e10cSrcweir ScDPSaveGroupDimension aGroupDim( aBaseDimName, aGroupDimName ); 1105cdf0e10cSrcweir aGroupDim.SetDateInfo( rInfo, nMask ); 1106cdf0e10cSrcweir pDimData->AddGroupDimension( aGroupDim ); 1107cdf0e10cSrcweir 1108cdf0e10cSrcweir // set orientation 1109cdf0e10cSrcweir ScDPSaveDimension* pSaveDimension = aData.GetDimensionByName( aGroupDimName ); 1110cdf0e10cSrcweir if ( pSaveDimension->GetOrientation() == sheet::DataPilotFieldOrientation_HIDDEN ) 1111cdf0e10cSrcweir { 1112cdf0e10cSrcweir ScDPSaveDimension* pOldDimension = aData.GetDimensionByName( aBaseDimName ); 1113cdf0e10cSrcweir pSaveDimension->SetOrientation( pOldDimension->GetOrientation() ); 1114cdf0e10cSrcweir long nPosition = 0; //! before (immediate) base 1115cdf0e10cSrcweir aData.SetPosition( pSaveDimension, nPosition ); 1116cdf0e10cSrcweir } 1117cdf0e10cSrcweir } 1118cdf0e10cSrcweir } 1119cdf0e10cSrcweir nMask *= 2; 1120cdf0e10cSrcweir } 1121cdf0e10cSrcweir } 1122cdf0e10cSrcweir 1123cdf0e10cSrcweir // apply changes 1124cdf0e10cSrcweir ScDBDocFunc aFunc( *GetViewData()->GetDocShell() ); 1125cdf0e10cSrcweir ScDPObject* pNewObj = new ScDPObject( *pDPObj ); 1126cdf0e10cSrcweir pNewObj->SetSaveData( aData ); 1127cdf0e10cSrcweir aFunc.DataPilotUpdate( pDPObj, pNewObj, sal_True, sal_False ); 1128cdf0e10cSrcweir delete pNewObj; 1129cdf0e10cSrcweir 1130cdf0e10cSrcweir // unmark cell selection 1131cdf0e10cSrcweir Unmark(); 1132cdf0e10cSrcweir } 1133cdf0e10cSrcweir } 1134cdf0e10cSrcweir } 1135cdf0e10cSrcweir 1136cdf0e10cSrcweir void ScDBFunc::NumGroupDataPilot( const ScDPNumGroupInfo& rInfo ) 1137cdf0e10cSrcweir { 1138cdf0e10cSrcweir ScDPObject* pDPObj = GetViewData()->GetDocument()->GetDPAtCursor( GetViewData()->GetCurX(), 1139cdf0e10cSrcweir GetViewData()->GetCurY(), GetViewData()->GetTabNo() ); 1140cdf0e10cSrcweir if ( pDPObj ) 1141cdf0e10cSrcweir { 1142cdf0e10cSrcweir ScStrCollection aEntries; 1143cdf0e10cSrcweir long nSelectDimension = -1; 1144cdf0e10cSrcweir GetSelectedMemberList( aEntries, nSelectDimension ); 1145cdf0e10cSrcweir 1146cdf0e10cSrcweir if ( aEntries.GetCount() > 0 ) 1147cdf0e10cSrcweir { 1148cdf0e10cSrcweir sal_Bool bIsDataLayout; 1149cdf0e10cSrcweir String aDimName = pDPObj->GetDimName( nSelectDimension, bIsDataLayout ); 1150cdf0e10cSrcweir 1151cdf0e10cSrcweir ScDPSaveData aData( *pDPObj->GetSaveData() ); 1152cdf0e10cSrcweir ScDPDimensionSaveData* pDimData = aData.GetDimensionData(); // created if not there 1153cdf0e10cSrcweir 1154cdf0e10cSrcweir ScDPSaveNumGroupDimension* pExisting = pDimData->GetNumGroupDimAcc( aDimName ); 1155cdf0e10cSrcweir if ( pExisting ) 1156cdf0e10cSrcweir { 1157cdf0e10cSrcweir // modify existing group dimension 1158cdf0e10cSrcweir pExisting->SetGroupInfo( rInfo ); 1159cdf0e10cSrcweir } 1160cdf0e10cSrcweir else 1161cdf0e10cSrcweir { 1162cdf0e10cSrcweir // create new group dimension 1163cdf0e10cSrcweir ScDPSaveNumGroupDimension aNumGroupDim( aDimName, rInfo ); 1164cdf0e10cSrcweir pDimData->AddNumGroupDimension( aNumGroupDim ); 1165cdf0e10cSrcweir } 1166cdf0e10cSrcweir 1167cdf0e10cSrcweir // apply changes 1168cdf0e10cSrcweir ScDBDocFunc aFunc( *GetViewData()->GetDocShell() ); 1169cdf0e10cSrcweir ScDPObject* pNewObj = new ScDPObject( *pDPObj ); 1170cdf0e10cSrcweir pNewObj->SetSaveData( aData ); 1171cdf0e10cSrcweir aFunc.DataPilotUpdate( pDPObj, pNewObj, sal_True, sal_False ); 1172cdf0e10cSrcweir delete pNewObj; 1173cdf0e10cSrcweir 1174cdf0e10cSrcweir // unmark cell selection 1175cdf0e10cSrcweir Unmark(); 1176cdf0e10cSrcweir } 1177cdf0e10cSrcweir } 1178cdf0e10cSrcweir } 1179cdf0e10cSrcweir 1180cdf0e10cSrcweir void ScDBFunc::GroupDataPilot() 1181cdf0e10cSrcweir { 1182cdf0e10cSrcweir ScDPObject* pDPObj = GetViewData()->GetDocument()->GetDPAtCursor( GetViewData()->GetCurX(), 1183cdf0e10cSrcweir GetViewData()->GetCurY(), GetViewData()->GetTabNo() ); 1184cdf0e10cSrcweir if ( pDPObj ) 1185cdf0e10cSrcweir { 1186cdf0e10cSrcweir ScStrCollection aEntries; 1187cdf0e10cSrcweir long nSelectDimension = -1; 1188cdf0e10cSrcweir GetSelectedMemberList( aEntries, nSelectDimension ); 1189cdf0e10cSrcweir 1190cdf0e10cSrcweir if ( aEntries.GetCount() > 0 ) 1191cdf0e10cSrcweir { 1192cdf0e10cSrcweir sal_Bool bIsDataLayout; 1193cdf0e10cSrcweir String aDimName = pDPObj->GetDimName( nSelectDimension, bIsDataLayout ); 1194cdf0e10cSrcweir 1195cdf0e10cSrcweir ScDPSaveData aData( *pDPObj->GetSaveData() ); 1196cdf0e10cSrcweir ScDPDimensionSaveData* pDimData = aData.GetDimensionData(); // created if not there 1197cdf0e10cSrcweir 1198cdf0e10cSrcweir // find original base 1199cdf0e10cSrcweir String aBaseDimName( aDimName ); 1200cdf0e10cSrcweir const ScDPSaveGroupDimension* pBaseGroupDim = pDimData->GetNamedGroupDim( aDimName ); 1201cdf0e10cSrcweir if ( pBaseGroupDim ) 1202cdf0e10cSrcweir { 1203cdf0e10cSrcweir // any entry's SourceDimName is the original base 1204cdf0e10cSrcweir aBaseDimName = pBaseGroupDim->GetSourceDimName(); 1205cdf0e10cSrcweir } 1206cdf0e10cSrcweir 1207cdf0e10cSrcweir // find existing group dimension 1208cdf0e10cSrcweir // (using the selected dim, can be intermediate group dim) 1209cdf0e10cSrcweir ScDPSaveGroupDimension* pGroupDimension = pDimData->GetGroupDimAccForBase( aDimName ); 1210cdf0e10cSrcweir 1211cdf0e10cSrcweir // remove the selected items from their groups 1212cdf0e10cSrcweir // (empty groups are removed, too) 1213cdf0e10cSrcweir sal_uInt16 nEntryCount = aEntries.GetCount(); 1214cdf0e10cSrcweir sal_uInt16 nEntry; 1215cdf0e10cSrcweir if ( pGroupDimension ) 1216cdf0e10cSrcweir { 1217cdf0e10cSrcweir for (nEntry=0; nEntry<nEntryCount; nEntry++) 1218cdf0e10cSrcweir { 1219cdf0e10cSrcweir String aEntryName = aEntries[nEntry]->GetString(); 1220cdf0e10cSrcweir if ( pBaseGroupDim ) 1221cdf0e10cSrcweir { 1222cdf0e10cSrcweir // for each selected (intermediate) group, remove all its items 1223cdf0e10cSrcweir // (same logic as for adding, below) 1224cdf0e10cSrcweir const ScDPSaveGroupItem* pBaseGroup = pBaseGroupDim->GetNamedGroup( aEntryName ); 1225cdf0e10cSrcweir if ( pBaseGroup ) 1226cdf0e10cSrcweir pBaseGroup->RemoveElementsFromGroups( *pGroupDimension ); // remove all elements 1227cdf0e10cSrcweir else 1228cdf0e10cSrcweir pGroupDimension->RemoveFromGroups( aEntryName ); 1229cdf0e10cSrcweir } 1230cdf0e10cSrcweir else 1231cdf0e10cSrcweir pGroupDimension->RemoveFromGroups( aEntryName ); 1232cdf0e10cSrcweir } 1233cdf0e10cSrcweir } 1234cdf0e10cSrcweir 1235cdf0e10cSrcweir ScDPSaveGroupDimension* pNewGroupDim = NULL; 1236cdf0e10cSrcweir if ( !pGroupDimension ) 1237cdf0e10cSrcweir { 1238cdf0e10cSrcweir // create a new group dimension 1239cdf0e10cSrcweir String aGroupDimName = pDimData->CreateGroupDimName( aBaseDimName, *pDPObj, false, NULL ); 1240cdf0e10cSrcweir pNewGroupDim = new ScDPSaveGroupDimension( aBaseDimName, aGroupDimName ); 1241cdf0e10cSrcweir 1242cdf0e10cSrcweir pGroupDimension = pNewGroupDim; // make changes to the new dim if none existed 1243cdf0e10cSrcweir 1244cdf0e10cSrcweir if ( pBaseGroupDim ) 1245cdf0e10cSrcweir { 1246cdf0e10cSrcweir // If it's a higher-order group dimension, pre-allocate groups for all 1247cdf0e10cSrcweir // non-selected original groups, so the individual base members aren't 1248cdf0e10cSrcweir // used for automatic groups (this would make the original groups hard 1249cdf0e10cSrcweir // to find). 1250cdf0e10cSrcweir //! Also do this when removing groups? 1251cdf0e10cSrcweir //! Handle this case dynamically with automatic groups? 1252cdf0e10cSrcweir 1253cdf0e10cSrcweir long nGroupCount = pBaseGroupDim->GetGroupCount(); 1254cdf0e10cSrcweir for ( long nGroup = 0; nGroup < nGroupCount; nGroup++ ) 1255cdf0e10cSrcweir { 1256cdf0e10cSrcweir const ScDPSaveGroupItem* pBaseGroup = pBaseGroupDim->GetGroupByIndex( nGroup ); 1257cdf0e10cSrcweir 1258cdf0e10cSrcweir StrData aStrData( pBaseGroup->GetGroupName() ); 1259cdf0e10cSrcweir sal_uInt16 nCollIndex; 1260cdf0e10cSrcweir if ( !aEntries.Search( &aStrData, nCollIndex ) ) //! ignore case? 1261cdf0e10cSrcweir { 1262cdf0e10cSrcweir // add an additional group for each item that is not in the selection 1263cdf0e10cSrcweir ScDPSaveGroupItem aGroup( pBaseGroup->GetGroupName() ); 1264cdf0e10cSrcweir aGroup.AddElementsFromGroup( *pBaseGroup ); 1265cdf0e10cSrcweir pGroupDimension->AddGroupItem( aGroup ); 1266cdf0e10cSrcweir } 1267cdf0e10cSrcweir } 1268cdf0e10cSrcweir } 1269cdf0e10cSrcweir } 1270cdf0e10cSrcweir String aGroupDimName = pGroupDimension->GetGroupDimName(); 1271cdf0e10cSrcweir 1272cdf0e10cSrcweir //! localized prefix string 1273cdf0e10cSrcweir String aGroupName = pGroupDimension->CreateGroupName( String::CreateFromAscii("Group") ); 1274cdf0e10cSrcweir ScDPSaveGroupItem aGroup( aGroupName ); 1275cdf0e10cSrcweir for (nEntry=0; nEntry<nEntryCount; nEntry++) 1276cdf0e10cSrcweir { 1277cdf0e10cSrcweir String aEntryName = aEntries[nEntry]->GetString(); 1278cdf0e10cSrcweir if ( pBaseGroupDim ) 1279cdf0e10cSrcweir { 1280cdf0e10cSrcweir // for each selected (intermediate) group, add all its items 1281cdf0e10cSrcweir const ScDPSaveGroupItem* pBaseGroup = pBaseGroupDim->GetNamedGroup( aEntryName ); 1282cdf0e10cSrcweir if ( pBaseGroup ) 1283cdf0e10cSrcweir aGroup.AddElementsFromGroup( *pBaseGroup ); 1284cdf0e10cSrcweir else 1285cdf0e10cSrcweir aGroup.AddElement( aEntryName ); // no group found -> automatic group, add the item itself 1286cdf0e10cSrcweir } 1287cdf0e10cSrcweir else 1288cdf0e10cSrcweir aGroup.AddElement( aEntryName ); // no group dimension, add all items directly 1289cdf0e10cSrcweir } 1290cdf0e10cSrcweir 1291cdf0e10cSrcweir pGroupDimension->AddGroupItem( aGroup ); 1292cdf0e10cSrcweir 1293cdf0e10cSrcweir if ( pNewGroupDim ) 1294cdf0e10cSrcweir { 1295cdf0e10cSrcweir pDimData->AddGroupDimension( *pNewGroupDim ); 1296cdf0e10cSrcweir delete pNewGroupDim; // AddGroupDimension copies the object 1297cdf0e10cSrcweir // don't access pGroupDimension after here 1298cdf0e10cSrcweir } 1299cdf0e10cSrcweir pGroupDimension = pNewGroupDim = NULL; 1300cdf0e10cSrcweir 1301cdf0e10cSrcweir // set orientation 1302cdf0e10cSrcweir ScDPSaveDimension* pSaveDimension = aData.GetDimensionByName( aGroupDimName ); 1303cdf0e10cSrcweir if ( pSaveDimension->GetOrientation() == sheet::DataPilotFieldOrientation_HIDDEN ) 1304cdf0e10cSrcweir { 1305cdf0e10cSrcweir ScDPSaveDimension* pOldDimension = aData.GetDimensionByName( aDimName ); 1306cdf0e10cSrcweir pSaveDimension->SetOrientation( pOldDimension->GetOrientation() ); 1307cdf0e10cSrcweir long nPosition = 0; //! before (immediate) base 1308cdf0e10cSrcweir aData.SetPosition( pSaveDimension, nPosition ); 1309cdf0e10cSrcweir } 1310cdf0e10cSrcweir 1311cdf0e10cSrcweir // apply changes 1312cdf0e10cSrcweir ScDBDocFunc aFunc( *GetViewData()->GetDocShell() ); 1313cdf0e10cSrcweir ScDPObject* pNewObj = new ScDPObject( *pDPObj ); 1314cdf0e10cSrcweir pNewObj->SetSaveData( aData ); 1315cdf0e10cSrcweir aFunc.DataPilotUpdate( pDPObj, pNewObj, sal_True, sal_False ); 1316cdf0e10cSrcweir delete pNewObj; 1317cdf0e10cSrcweir 1318cdf0e10cSrcweir // unmark cell selection 1319cdf0e10cSrcweir Unmark(); 1320cdf0e10cSrcweir } 1321cdf0e10cSrcweir } 1322cdf0e10cSrcweir } 1323cdf0e10cSrcweir 1324cdf0e10cSrcweir void ScDBFunc::UngroupDataPilot() 1325cdf0e10cSrcweir { 1326cdf0e10cSrcweir ScDPObject* pDPObj = GetViewData()->GetDocument()->GetDPAtCursor( GetViewData()->GetCurX(), 1327cdf0e10cSrcweir GetViewData()->GetCurY(), GetViewData()->GetTabNo() ); 1328cdf0e10cSrcweir if ( pDPObj ) 1329cdf0e10cSrcweir { 1330cdf0e10cSrcweir ScStrCollection aEntries; 1331cdf0e10cSrcweir long nSelectDimension = -1; 1332cdf0e10cSrcweir GetSelectedMemberList( aEntries, nSelectDimension ); 1333cdf0e10cSrcweir 1334cdf0e10cSrcweir if ( aEntries.GetCount() > 0 ) 1335cdf0e10cSrcweir { 1336cdf0e10cSrcweir sal_Bool bIsDataLayout; 1337cdf0e10cSrcweir String aDimName = pDPObj->GetDimName( nSelectDimension, bIsDataLayout ); 1338cdf0e10cSrcweir 1339cdf0e10cSrcweir ScDPSaveData aData( *pDPObj->GetSaveData() ); 1340cdf0e10cSrcweir ScDPDimensionSaveData* pDimData = aData.GetDimensionData(); // created if not there 1341cdf0e10cSrcweir //! test first if DimensionData exists? 1342cdf0e10cSrcweir 1343cdf0e10cSrcweir sal_Bool bApply = sal_False; 1344cdf0e10cSrcweir 1345cdf0e10cSrcweir ScDPSaveGroupDimension* pGroupDim = pDimData->GetNamedGroupDimAcc( aDimName ); 1346cdf0e10cSrcweir const ScDPSaveNumGroupDimension* pNumGroupDim = pDimData->GetNumGroupDim( aDimName ); 1347cdf0e10cSrcweir if ( ( pGroupDim && pGroupDim->GetDatePart() != 0 ) || 1348cdf0e10cSrcweir ( pNumGroupDim && pNumGroupDim->GetDatePart() != 0 ) ) 1349cdf0e10cSrcweir { 1350cdf0e10cSrcweir // Date grouping: need to remove all affected group dimensions. 1351cdf0e10cSrcweir // This is done using DateGroupDataPilot with nParts=0. 1352cdf0e10cSrcweir 1353cdf0e10cSrcweir DateGroupDataPilot( ScDPNumGroupInfo(), 0 ); 1354cdf0e10cSrcweir // bApply remains FALSE 1355cdf0e10cSrcweir // dimension pointers become invalid 1356cdf0e10cSrcweir } 1357cdf0e10cSrcweir else if ( pGroupDim ) 1358cdf0e10cSrcweir { 1359cdf0e10cSrcweir sal_uInt16 nEntryCount = aEntries.GetCount(); 1360cdf0e10cSrcweir for (sal_uInt16 nEntry=0; nEntry<nEntryCount; nEntry++) 1361cdf0e10cSrcweir { 1362cdf0e10cSrcweir String aEntryName = aEntries[nEntry]->GetString(); 1363cdf0e10cSrcweir pGroupDim->RemoveGroup( aEntryName ); 1364cdf0e10cSrcweir } 1365cdf0e10cSrcweir // remove group dimension if empty 1366cdf0e10cSrcweir bool bEmptyDim = pGroupDim->IsEmpty(); 1367cdf0e10cSrcweir if ( !bEmptyDim ) 1368cdf0e10cSrcweir { 1369cdf0e10cSrcweir // If all remaining groups in the dimension aren't shown, remove 1370cdf0e10cSrcweir // the dimension too, as if it was completely empty. 1371cdf0e10cSrcweir ScStrCollection aVisibleEntries; 1372cdf0e10cSrcweir pDPObj->GetMemberResultNames( aVisibleEntries, nSelectDimension ); 1373cdf0e10cSrcweir bEmptyDim = pGroupDim->HasOnlyHidden( aVisibleEntries ); 1374cdf0e10cSrcweir } 1375cdf0e10cSrcweir if ( bEmptyDim ) 1376cdf0e10cSrcweir { 1377cdf0e10cSrcweir pDimData->RemoveGroupDimension( aDimName ); // pGroupDim is deleted 1378cdf0e10cSrcweir 1379cdf0e10cSrcweir // also remove SaveData settings for the dimension that no longer exists 1380cdf0e10cSrcweir aData.RemoveDimensionByName( aDimName ); 1381cdf0e10cSrcweir } 1382cdf0e10cSrcweir bApply = sal_True; 1383cdf0e10cSrcweir } 1384cdf0e10cSrcweir else if ( pNumGroupDim ) 1385cdf0e10cSrcweir { 1386cdf0e10cSrcweir // remove the numerical grouping 1387cdf0e10cSrcweir pDimData->RemoveNumGroupDimension( aDimName ); 1388cdf0e10cSrcweir // SaveData settings can remain unchanged - the same dimension still exists 1389cdf0e10cSrcweir bApply = sal_True; 1390cdf0e10cSrcweir } 1391cdf0e10cSrcweir 1392cdf0e10cSrcweir if ( bApply ) 1393cdf0e10cSrcweir { 1394cdf0e10cSrcweir // apply changes 1395cdf0e10cSrcweir ScDBDocFunc aFunc( *GetViewData()->GetDocShell() ); 1396cdf0e10cSrcweir ScDPObject* pNewObj = new ScDPObject( *pDPObj ); 1397cdf0e10cSrcweir pNewObj->SetSaveData( aData ); 1398cdf0e10cSrcweir aFunc.DataPilotUpdate( pDPObj, pNewObj, sal_True, sal_False ); 1399cdf0e10cSrcweir delete pNewObj; 1400cdf0e10cSrcweir 1401cdf0e10cSrcweir // unmark cell selection 1402cdf0e10cSrcweir Unmark(); 1403cdf0e10cSrcweir } 1404cdf0e10cSrcweir } 1405cdf0e10cSrcweir } 1406cdf0e10cSrcweir } 1407cdf0e10cSrcweir 1408cdf0e10cSrcweir static OUString lcl_replaceMemberNameInSubtotal(const OUString& rSubtotal, const OUString& rMemberName) 1409cdf0e10cSrcweir { 1410cdf0e10cSrcweir sal_Int32 n = rSubtotal.getLength(); 1411cdf0e10cSrcweir const sal_Unicode* p = rSubtotal.getStr(); 1412cdf0e10cSrcweir OUStringBuffer aBuf, aWordBuf; 1413cdf0e10cSrcweir for (sal_Int32 i = 0; i < n; ++i) 1414cdf0e10cSrcweir { 1415cdf0e10cSrcweir sal_Unicode c = p[i]; 1416cdf0e10cSrcweir if (c == sal_Unicode(' ')) 1417cdf0e10cSrcweir { 1418cdf0e10cSrcweir OUString aWord = aWordBuf.makeStringAndClear(); 1419cdf0e10cSrcweir if (aWord.equals(rMemberName)) 1420cdf0e10cSrcweir aBuf.append(sal_Unicode('?')); 1421cdf0e10cSrcweir else 1422cdf0e10cSrcweir aBuf.append(aWord); 1423cdf0e10cSrcweir aBuf.append(c); 1424cdf0e10cSrcweir } 1425cdf0e10cSrcweir else if (c == sal_Unicode('\\')) 1426cdf0e10cSrcweir { 1427cdf0e10cSrcweir // Escape a backslash character. 1428cdf0e10cSrcweir aWordBuf.append(c); 1429cdf0e10cSrcweir aWordBuf.append(c); 1430cdf0e10cSrcweir } 1431cdf0e10cSrcweir else if (c == sal_Unicode('?')) 1432cdf0e10cSrcweir { 1433cdf0e10cSrcweir // A literal '?' must be escaped with a backslash ('\'); 1434cdf0e10cSrcweir aWordBuf.append(sal_Unicode('\\')); 1435cdf0e10cSrcweir aWordBuf.append(c); 1436cdf0e10cSrcweir } 1437cdf0e10cSrcweir else 1438cdf0e10cSrcweir aWordBuf.append(c); 1439cdf0e10cSrcweir } 1440cdf0e10cSrcweir 1441cdf0e10cSrcweir if (aWordBuf.getLength() > 0) 1442cdf0e10cSrcweir { 1443cdf0e10cSrcweir OUString aWord = aWordBuf.makeStringAndClear(); 1444cdf0e10cSrcweir if (aWord.equals(rMemberName)) 1445cdf0e10cSrcweir aBuf.append(sal_Unicode('?')); 1446cdf0e10cSrcweir else 1447cdf0e10cSrcweir aBuf.append(aWord); 1448cdf0e10cSrcweir } 1449cdf0e10cSrcweir 1450cdf0e10cSrcweir return aBuf.makeStringAndClear(); 1451cdf0e10cSrcweir } 1452cdf0e10cSrcweir 1453cdf0e10cSrcweir void ScDBFunc::DataPilotInput( const ScAddress& rPos, const String& rString ) 1454cdf0e10cSrcweir { 1455cdf0e10cSrcweir using namespace ::com::sun::star::sheet; 1456cdf0e10cSrcweir 1457cdf0e10cSrcweir String aNewName( rString ); 1458cdf0e10cSrcweir 1459cdf0e10cSrcweir ScDocument* pDoc = GetViewData()->GetDocument(); 1460cdf0e10cSrcweir ScDPObject* pDPObj = pDoc->GetDPAtCursor( rPos.Col(), rPos.Row(), rPos.Tab() ); 1461cdf0e10cSrcweir if (!pDPObj) 1462cdf0e10cSrcweir return; 1463cdf0e10cSrcweir 1464cdf0e10cSrcweir String aOldText; 1465cdf0e10cSrcweir pDoc->GetString( rPos.Col(), rPos.Row(), rPos.Tab(), aOldText ); 1466cdf0e10cSrcweir 1467cdf0e10cSrcweir if ( aOldText == rString ) 1468cdf0e10cSrcweir { 1469cdf0e10cSrcweir // nothing to do: silently exit 1470cdf0e10cSrcweir return; 1471cdf0e10cSrcweir } 1472cdf0e10cSrcweir 1473cdf0e10cSrcweir sal_uInt16 nErrorId = 0; 1474cdf0e10cSrcweir 1475cdf0e10cSrcweir pDPObj->BuildAllDimensionMembers(); 1476cdf0e10cSrcweir ScDPSaveData aData( *pDPObj->GetSaveData() ); 1477cdf0e10cSrcweir sal_Bool bChange = sal_False; 1478cdf0e10cSrcweir 1479cdf0e10cSrcweir sal_uInt16 nOrient = DataPilotFieldOrientation_HIDDEN; 1480cdf0e10cSrcweir long nField = pDPObj->GetHeaderDim( rPos, nOrient ); 1481cdf0e10cSrcweir if ( nField >= 0 ) 1482cdf0e10cSrcweir { 1483cdf0e10cSrcweir // changing a field title 1484cdf0e10cSrcweir if ( aData.GetExistingDimensionData() ) 1485cdf0e10cSrcweir { 1486cdf0e10cSrcweir // only group dimensions can be renamed 1487cdf0e10cSrcweir 1488cdf0e10cSrcweir ScDPDimensionSaveData* pDimData = aData.GetDimensionData(); 1489cdf0e10cSrcweir ScDPSaveGroupDimension* pGroupDim = pDimData->GetNamedGroupDimAcc( aOldText ); 1490cdf0e10cSrcweir if ( pGroupDim ) 1491cdf0e10cSrcweir { 1492cdf0e10cSrcweir // valid name: not empty, no existing dimension (group or other) 1493cdf0e10cSrcweir if ( rString.Len() && !pDPObj->IsDimNameInUse(rString) ) 1494cdf0e10cSrcweir { 1495cdf0e10cSrcweir pGroupDim->Rename( aNewName ); 1496cdf0e10cSrcweir 1497cdf0e10cSrcweir // also rename in SaveData to preserve the field settings 1498cdf0e10cSrcweir ScDPSaveDimension* pSaveDim = aData.GetDimensionByName( aOldText ); 1499cdf0e10cSrcweir pSaveDim->SetName( aNewName ); 1500cdf0e10cSrcweir 1501cdf0e10cSrcweir bChange = sal_True; 1502cdf0e10cSrcweir } 1503cdf0e10cSrcweir else 1504cdf0e10cSrcweir nErrorId = STR_INVALIDNAME; 1505cdf0e10cSrcweir } 1506cdf0e10cSrcweir } 1507cdf0e10cSrcweir else if (nOrient == DataPilotFieldOrientation_COLUMN || nOrient == DataPilotFieldOrientation_ROW) 1508cdf0e10cSrcweir { 1509cdf0e10cSrcweir sal_Bool bDataLayout = false; 1510cdf0e10cSrcweir String aDimName = pDPObj->GetDimName(nField, bDataLayout); 1511cdf0e10cSrcweir ScDPSaveDimension* pDim = bDataLayout ? aData.GetDataLayoutDimension() : aData.GetDimensionByName(aDimName); 1512cdf0e10cSrcweir if (pDim) 1513cdf0e10cSrcweir { 1514cdf0e10cSrcweir if (rString.Len()) 1515cdf0e10cSrcweir { 1516cdf0e10cSrcweir if (rString.EqualsIgnoreCaseAscii(aDimName)) 1517cdf0e10cSrcweir { 1518cdf0e10cSrcweir pDim->RemoveLayoutName(); 1519cdf0e10cSrcweir bChange = true; 1520cdf0e10cSrcweir } 1521cdf0e10cSrcweir else if (!pDPObj->IsDimNameInUse(rString)) 1522cdf0e10cSrcweir { 1523cdf0e10cSrcweir pDim->SetLayoutName(rString); 1524cdf0e10cSrcweir bChange = true; 1525cdf0e10cSrcweir } 1526cdf0e10cSrcweir else 1527cdf0e10cSrcweir nErrorId = STR_INVALIDNAME; 1528cdf0e10cSrcweir } 1529cdf0e10cSrcweir else 1530cdf0e10cSrcweir nErrorId = STR_INVALIDNAME; 1531cdf0e10cSrcweir } 1532cdf0e10cSrcweir } 1533cdf0e10cSrcweir } 1534cdf0e10cSrcweir else if (pDPObj->IsDataDescriptionCell(rPos)) 1535cdf0e10cSrcweir { 1536cdf0e10cSrcweir // There is only one data dimension. 1537cdf0e10cSrcweir ScDPSaveDimension* pDim = aData.GetFirstDimension(sheet::DataPilotFieldOrientation_DATA); 1538cdf0e10cSrcweir if (pDim) 1539cdf0e10cSrcweir { 1540cdf0e10cSrcweir if (rString.Len()) 1541cdf0e10cSrcweir { 1542cdf0e10cSrcweir if (rString.EqualsIgnoreCaseAscii(pDim->GetName())) 1543cdf0e10cSrcweir { 1544cdf0e10cSrcweir pDim->RemoveLayoutName(); 1545cdf0e10cSrcweir bChange = true; 1546cdf0e10cSrcweir } 1547cdf0e10cSrcweir else if (!pDPObj->IsDimNameInUse(rString)) 1548cdf0e10cSrcweir { 1549cdf0e10cSrcweir pDim->SetLayoutName(rString); 1550cdf0e10cSrcweir bChange = true; 1551cdf0e10cSrcweir } 1552cdf0e10cSrcweir else 1553cdf0e10cSrcweir nErrorId = STR_INVALIDNAME; 1554cdf0e10cSrcweir } 1555cdf0e10cSrcweir else 1556cdf0e10cSrcweir nErrorId = STR_INVALIDNAME; 1557cdf0e10cSrcweir } 1558cdf0e10cSrcweir } 1559cdf0e10cSrcweir else 1560cdf0e10cSrcweir { 1561cdf0e10cSrcweir // This is not a field header. 1562cdf0e10cSrcweir sheet::DataPilotTableHeaderData aPosData; 1563cdf0e10cSrcweir pDPObj->GetHeaderPositionData(rPos, aPosData); 1564cdf0e10cSrcweir 1565cdf0e10cSrcweir if ( (aPosData.Flags & MemberResultFlags::HASMEMBER) && aOldText.Len() ) 1566cdf0e10cSrcweir { 1567cdf0e10cSrcweir if ( aData.GetExistingDimensionData() && !(aPosData.Flags & MemberResultFlags::SUBTOTAL)) 1568cdf0e10cSrcweir { 1569cdf0e10cSrcweir sal_Bool bIsDataLayout; 1570cdf0e10cSrcweir String aDimName = pDPObj->GetDimName( aPosData.Dimension, bIsDataLayout ); 1571cdf0e10cSrcweir 1572cdf0e10cSrcweir ScDPDimensionSaveData* pDimData = aData.GetDimensionData(); 1573cdf0e10cSrcweir ScDPSaveGroupDimension* pGroupDim = pDimData->GetNamedGroupDimAcc( aDimName ); 1574cdf0e10cSrcweir if ( pGroupDim ) 1575cdf0e10cSrcweir { 1576cdf0e10cSrcweir // valid name: not empty, no existing group in this dimension 1577cdf0e10cSrcweir //! ignore case? 1578cdf0e10cSrcweir if ( aNewName.Len() && !pGroupDim->GetNamedGroup( aNewName ) ) 1579cdf0e10cSrcweir { 1580cdf0e10cSrcweir ScDPSaveGroupItem* pGroup = pGroupDim->GetNamedGroupAcc( aOldText ); 1581cdf0e10cSrcweir if ( pGroup ) 1582cdf0e10cSrcweir pGroup->Rename( aNewName ); // rename the existing group 1583cdf0e10cSrcweir else 1584cdf0e10cSrcweir { 1585cdf0e10cSrcweir // create a new group to replace the automatic group 1586cdf0e10cSrcweir ScDPSaveGroupItem aGroup( aNewName ); 1587cdf0e10cSrcweir aGroup.AddElement( aOldText ); 1588cdf0e10cSrcweir pGroupDim->AddGroupItem( aGroup ); 1589cdf0e10cSrcweir } 1590cdf0e10cSrcweir 1591cdf0e10cSrcweir // in both cases also adjust savedata, to preserve member settings (show details) 1592cdf0e10cSrcweir ScDPSaveDimension* pSaveDim = aData.GetDimensionByName( aDimName ); 1593cdf0e10cSrcweir ScDPSaveMember* pSaveMember = pSaveDim->GetExistingMemberByName( aOldText ); 1594cdf0e10cSrcweir if ( pSaveMember ) 1595cdf0e10cSrcweir pSaveMember->SetName( aNewName ); 1596cdf0e10cSrcweir 1597cdf0e10cSrcweir bChange = sal_True; 1598cdf0e10cSrcweir } 1599cdf0e10cSrcweir else 1600cdf0e10cSrcweir nErrorId = STR_INVALIDNAME; 1601cdf0e10cSrcweir } 1602cdf0e10cSrcweir } 1603cdf0e10cSrcweir else if ((aPosData.Flags & MemberResultFlags::GRANDTOTAL)) 1604cdf0e10cSrcweir { 1605cdf0e10cSrcweir aData.SetGrandTotalName(rString); 1606cdf0e10cSrcweir bChange = true; 1607cdf0e10cSrcweir } 1608cdf0e10cSrcweir else if (aPosData.Dimension >= 0 && aPosData.MemberName.getLength() > 0) 1609cdf0e10cSrcweir { 1610cdf0e10cSrcweir sal_Bool bDataLayout = false; 1611cdf0e10cSrcweir String aDimName = pDPObj->GetDimName(static_cast<long>(aPosData.Dimension), bDataLayout); 1612cdf0e10cSrcweir if (bDataLayout) 1613cdf0e10cSrcweir { 1614cdf0e10cSrcweir // data dimension 1615cdf0e10cSrcweir do 1616cdf0e10cSrcweir { 1617cdf0e10cSrcweir if ((aPosData.Flags & MemberResultFlags::SUBTOTAL)) 1618cdf0e10cSrcweir break; 1619cdf0e10cSrcweir 1620cdf0e10cSrcweir ScDPSaveDimension* pDim = aData.GetDimensionByName(aPosData.MemberName); 1621cdf0e10cSrcweir if (!pDim) 1622cdf0e10cSrcweir break; 1623cdf0e10cSrcweir 1624cdf0e10cSrcweir if (!rString.Len()) 1625cdf0e10cSrcweir { 1626cdf0e10cSrcweir nErrorId = STR_INVALIDNAME; 1627cdf0e10cSrcweir break; 1628cdf0e10cSrcweir } 1629cdf0e10cSrcweir 1630cdf0e10cSrcweir if (aPosData.MemberName.equalsIgnoreAsciiCase(rString)) 1631cdf0e10cSrcweir { 1632cdf0e10cSrcweir pDim->RemoveLayoutName(); 1633cdf0e10cSrcweir bChange = true; 1634cdf0e10cSrcweir } 1635cdf0e10cSrcweir else if (!pDPObj->IsDimNameInUse(rString)) 1636cdf0e10cSrcweir { 1637cdf0e10cSrcweir pDim->SetLayoutName(rString); 1638cdf0e10cSrcweir bChange = true; 1639cdf0e10cSrcweir } 1640cdf0e10cSrcweir else 1641cdf0e10cSrcweir nErrorId = STR_INVALIDNAME; 1642cdf0e10cSrcweir } 1643cdf0e10cSrcweir while (false); 1644cdf0e10cSrcweir } 1645cdf0e10cSrcweir else 1646cdf0e10cSrcweir { 1647cdf0e10cSrcweir // field member 1648cdf0e10cSrcweir do 1649cdf0e10cSrcweir { 1650cdf0e10cSrcweir ScDPSaveDimension* pDim = aData.GetDimensionByName(aDimName); 1651cdf0e10cSrcweir if (!pDim) 1652cdf0e10cSrcweir break; 1653cdf0e10cSrcweir 1654cdf0e10cSrcweir ScDPSaveMember* pMem = pDim->GetExistingMemberByName(aPosData.MemberName); 1655cdf0e10cSrcweir if (!pMem) 1656cdf0e10cSrcweir break; 1657cdf0e10cSrcweir 1658cdf0e10cSrcweir if ((aPosData.Flags & MemberResultFlags::SUBTOTAL)) 1659cdf0e10cSrcweir { 1660cdf0e10cSrcweir // Change subtotal only when the table has one data dimension. 1661cdf0e10cSrcweir if (aData.GetDataDimensionCount() > 1) 1662cdf0e10cSrcweir break; 1663cdf0e10cSrcweir 1664cdf0e10cSrcweir // display name for subtotal is allowed only if the subtotal type is 'Automatic'. 1665cdf0e10cSrcweir if (pDim->GetSubTotalsCount() != 1) 1666cdf0e10cSrcweir break; 1667cdf0e10cSrcweir 1668cdf0e10cSrcweir if (pDim->GetSubTotalFunc(0) != sheet::GeneralFunction_AUTO) 1669cdf0e10cSrcweir break; 1670cdf0e10cSrcweir 1671cdf0e10cSrcweir const OUString* pLayoutName = pMem->GetLayoutName(); 1672cdf0e10cSrcweir String aMemberName; 1673cdf0e10cSrcweir if (pLayoutName) 1674cdf0e10cSrcweir aMemberName = *pLayoutName; 1675cdf0e10cSrcweir else 1676cdf0e10cSrcweir aMemberName = aPosData.MemberName; 1677cdf0e10cSrcweir 1678cdf0e10cSrcweir String aNew = lcl_replaceMemberNameInSubtotal(rString, aMemberName); 1679cdf0e10cSrcweir pDim->SetSubtotalName(aNew); 1680cdf0e10cSrcweir bChange = true; 1681cdf0e10cSrcweir } 1682cdf0e10cSrcweir else 1683cdf0e10cSrcweir { 1684cdf0e10cSrcweir // Check to make sure the member name isn't 1685cdf0e10cSrcweir // already used. 1686cdf0e10cSrcweir if (rString.Len()) 1687cdf0e10cSrcweir { 1688cdf0e10cSrcweir if (rString.EqualsIgnoreCaseAscii(pMem->GetName())) 1689cdf0e10cSrcweir { 1690cdf0e10cSrcweir pMem->RemoveLayoutName(); 1691cdf0e10cSrcweir bChange = true; 1692cdf0e10cSrcweir } 1693cdf0e10cSrcweir else if (!pDim->IsMemberNameInUse(rString)) 1694cdf0e10cSrcweir { 1695cdf0e10cSrcweir pMem->SetLayoutName(rString); 1696cdf0e10cSrcweir bChange = true; 1697cdf0e10cSrcweir } 1698cdf0e10cSrcweir else 1699cdf0e10cSrcweir nErrorId = STR_INVALIDNAME; 1700cdf0e10cSrcweir } 1701cdf0e10cSrcweir else 1702cdf0e10cSrcweir nErrorId = STR_INVALIDNAME; 1703cdf0e10cSrcweir } 1704cdf0e10cSrcweir } 1705cdf0e10cSrcweir while (false); 1706cdf0e10cSrcweir } 1707cdf0e10cSrcweir } 1708cdf0e10cSrcweir } 1709cdf0e10cSrcweir } 1710cdf0e10cSrcweir 1711cdf0e10cSrcweir if ( bChange ) 1712cdf0e10cSrcweir { 1713cdf0e10cSrcweir // apply changes 1714cdf0e10cSrcweir ScDBDocFunc aFunc( *GetViewData()->GetDocShell() ); 1715cdf0e10cSrcweir ScDPObject* pNewObj = new ScDPObject( *pDPObj ); 1716cdf0e10cSrcweir pNewObj->SetSaveData( aData ); 1717cdf0e10cSrcweir aFunc.DataPilotUpdate( pDPObj, pNewObj, sal_True, sal_False ); 1718cdf0e10cSrcweir delete pNewObj; 1719cdf0e10cSrcweir } 1720cdf0e10cSrcweir else 1721cdf0e10cSrcweir { 1722cdf0e10cSrcweir if ( !nErrorId ) 1723cdf0e10cSrcweir nErrorId = STR_ERR_DATAPILOT_INPUT; 1724cdf0e10cSrcweir ErrorMessage( nErrorId ); 1725cdf0e10cSrcweir } 1726cdf0e10cSrcweir } 1727cdf0e10cSrcweir 1728cdf0e10cSrcweir void lcl_MoveToEnd( ScDPSaveDimension& rDim, const String& rItemName ) 1729cdf0e10cSrcweir { 1730cdf0e10cSrcweir ScDPSaveMember* pNewMember = NULL; 1731cdf0e10cSrcweir const ScDPSaveMember* pOldMember = rDim.GetExistingMemberByName( rItemName ); 1732cdf0e10cSrcweir if ( pOldMember ) 1733cdf0e10cSrcweir pNewMember = new ScDPSaveMember( *pOldMember ); 1734cdf0e10cSrcweir else 1735cdf0e10cSrcweir pNewMember = new ScDPSaveMember( rItemName ); 1736cdf0e10cSrcweir rDim.AddMember( pNewMember ); 1737cdf0e10cSrcweir // AddMember takes ownership of the new pointer, 1738cdf0e10cSrcweir // puts it to the end of the list even if it was in the list before. 1739cdf0e10cSrcweir } 1740cdf0e10cSrcweir 1741cdf0e10cSrcweir struct ScOUStringCollate 1742cdf0e10cSrcweir { 1743cdf0e10cSrcweir CollatorWrapper* mpCollator; 1744cdf0e10cSrcweir 1745cdf0e10cSrcweir ScOUStringCollate(CollatorWrapper* pColl) : mpCollator(pColl) {} 1746cdf0e10cSrcweir 1747cdf0e10cSrcweir bool operator()(const rtl::OUString& rStr1, const rtl::OUString& rStr2) const 1748cdf0e10cSrcweir { 1749cdf0e10cSrcweir return ( mpCollator->compareString(rStr1, rStr2) < 0 ); 1750cdf0e10cSrcweir } 1751cdf0e10cSrcweir }; 1752cdf0e10cSrcweir 1753cdf0e10cSrcweir bool ScDBFunc::DataPilotSort( const ScAddress& rPos, bool bAscending, sal_uInt16* pUserListId ) 1754cdf0e10cSrcweir { 1755cdf0e10cSrcweir ScDocument* pDoc = GetViewData()->GetDocument(); 1756cdf0e10cSrcweir ScDPObject* pDPObj = pDoc->GetDPAtCursor(rPos.Col(), rPos.Row(), rPos.Tab()); 1757cdf0e10cSrcweir if (!pDPObj) 1758cdf0e10cSrcweir return false; 1759cdf0e10cSrcweir 1760cdf0e10cSrcweir // We need to run this to get all members later. 1761cdf0e10cSrcweir if ( pUserListId ) 1762cdf0e10cSrcweir pDPObj->BuildAllDimensionMembers(); 1763cdf0e10cSrcweir 1764cdf0e10cSrcweir sal_uInt16 nOrientation; 1765cdf0e10cSrcweir long nDimIndex = pDPObj->GetHeaderDim(rPos, nOrientation); 1766cdf0e10cSrcweir if (nDimIndex < 0) 1767cdf0e10cSrcweir // Invalid dimension index. Bail out. 1768cdf0e10cSrcweir return false; 1769cdf0e10cSrcweir 1770cdf0e10cSrcweir sal_Bool bDataLayout; 1771cdf0e10cSrcweir ScDPSaveData* pSaveData = pDPObj->GetSaveData(); 1772cdf0e10cSrcweir if (!pSaveData) 1773cdf0e10cSrcweir return false; 1774cdf0e10cSrcweir 1775cdf0e10cSrcweir ScDPSaveData aNewSaveData(*pSaveData); 1776cdf0e10cSrcweir String aDimName = pDPObj->GetDimName(nDimIndex, bDataLayout); 1777cdf0e10cSrcweir ScDPSaveDimension* pSaveDim = aNewSaveData.GetDimensionByName(aDimName); 1778cdf0e10cSrcweir if (!pSaveDim) 1779cdf0e10cSrcweir return false; 1780cdf0e10cSrcweir 1781cdf0e10cSrcweir // manual evaluation of sort order is only needed if a user list id is given 1782cdf0e10cSrcweir if ( pUserListId ) 1783cdf0e10cSrcweir { 1784cdf0e10cSrcweir typedef ScDPSaveDimension::MemberList MemList; 1785cdf0e10cSrcweir const MemList& rDimMembers = pSaveDim->GetMembers(); 1786cdf0e10cSrcweir list<OUString> aMembers; 1787cdf0e10cSrcweir hash_set<OUString, ::rtl::OUStringHash> aMemberSet; 1788cdf0e10cSrcweir size_t nMemberCount = 0; 1789cdf0e10cSrcweir for (MemList::const_iterator itr = rDimMembers.begin(), itrEnd = rDimMembers.end(); 1790cdf0e10cSrcweir itr != itrEnd; ++itr) 1791cdf0e10cSrcweir { 1792cdf0e10cSrcweir ScDPSaveMember* pMem = *itr; 1793cdf0e10cSrcweir aMembers.push_back(pMem->GetName()); 1794cdf0e10cSrcweir aMemberSet.insert(pMem->GetName()); 1795cdf0e10cSrcweir ++nMemberCount; 1796cdf0e10cSrcweir } 1797cdf0e10cSrcweir 1798cdf0e10cSrcweir // Sort the member list in ascending order. 1799cdf0e10cSrcweir ScOUStringCollate aCollate( ScGlobal::GetCollator() ); 1800cdf0e10cSrcweir aMembers.sort(aCollate); 1801cdf0e10cSrcweir 1802cdf0e10cSrcweir // Collect and rank those custom sort strings that also exist in the member name list. 1803cdf0e10cSrcweir 1804cdf0e10cSrcweir typedef hash_map<OUString, sal_uInt16, OUStringHash> UserSortMap; 1805cdf0e10cSrcweir UserSortMap aSubStrs; 1806cdf0e10cSrcweir sal_uInt16 nSubCount = 0; 1807cdf0e10cSrcweir if (pUserListId) 1808cdf0e10cSrcweir { 1809cdf0e10cSrcweir ScUserList* pUserList = ScGlobal::GetUserList(); 1810cdf0e10cSrcweir if (!pUserList) 1811cdf0e10cSrcweir return false; 1812cdf0e10cSrcweir 1813cdf0e10cSrcweir { 1814cdf0e10cSrcweir sal_uInt16 n = pUserList->GetCount(); 1815cdf0e10cSrcweir if (!n || *pUserListId >= n) 1816cdf0e10cSrcweir return false; 1817cdf0e10cSrcweir } 1818cdf0e10cSrcweir 1819cdf0e10cSrcweir ScUserListData* pData = static_cast<ScUserListData*>((*pUserList)[*pUserListId]); 1820cdf0e10cSrcweir if (pData) 1821cdf0e10cSrcweir { 1822cdf0e10cSrcweir sal_uInt16 n = pData->GetSubCount(); 1823cdf0e10cSrcweir for (sal_uInt16 i = 0; i < n; ++i) 1824cdf0e10cSrcweir { 1825cdf0e10cSrcweir OUString aSub = pData->GetSubStr(i); 1826cdf0e10cSrcweir if (!aMemberSet.count(aSub)) 1827cdf0e10cSrcweir // This string doesn't exist in the member name set. Don't add this. 1828cdf0e10cSrcweir continue; 1829cdf0e10cSrcweir 1830cdf0e10cSrcweir aSubStrs.insert(UserSortMap::value_type(aSub, nSubCount++)); 1831cdf0e10cSrcweir } 1832cdf0e10cSrcweir } 1833cdf0e10cSrcweir } 1834cdf0e10cSrcweir 1835cdf0e10cSrcweir // Rank all members. 1836cdf0e10cSrcweir 1837cdf0e10cSrcweir vector<OUString> aRankedNames(nMemberCount); 1838cdf0e10cSrcweir sal_uInt16 nCurStrId = 0; 1839cdf0e10cSrcweir for (list<OUString>::const_iterator itr = aMembers.begin(), itrEnd = aMembers.end(); 1840cdf0e10cSrcweir itr != itrEnd; ++itr) 1841cdf0e10cSrcweir { 1842cdf0e10cSrcweir OUString aName = *itr; 1843cdf0e10cSrcweir sal_uInt16 nRank = 0; 1844cdf0e10cSrcweir UserSortMap::const_iterator itrSub = aSubStrs.find(aName); 1845cdf0e10cSrcweir if (itrSub == aSubStrs.end()) 1846cdf0e10cSrcweir nRank = nSubCount + nCurStrId++; 1847cdf0e10cSrcweir else 1848cdf0e10cSrcweir nRank = itrSub->second; 1849cdf0e10cSrcweir 1850cdf0e10cSrcweir if (!bAscending) 1851cdf0e10cSrcweir nRank = static_cast< sal_uInt16 >( nMemberCount - nRank - 1 ); 1852cdf0e10cSrcweir 1853cdf0e10cSrcweir aRankedNames[nRank] = aName; 1854cdf0e10cSrcweir } 1855cdf0e10cSrcweir 1856cdf0e10cSrcweir // Re-order ScDPSaveMember instances with the new ranks. 1857cdf0e10cSrcweir 1858cdf0e10cSrcweir for (vector<OUString>::const_iterator itr = aRankedNames.begin(), itrEnd = aRankedNames.end(); 1859cdf0e10cSrcweir itr != itrEnd; ++itr) 1860cdf0e10cSrcweir { 1861cdf0e10cSrcweir const ScDPSaveMember* pOldMem = pSaveDim->GetExistingMemberByName(*itr); 1862cdf0e10cSrcweir if (!pOldMem) 1863cdf0e10cSrcweir // All members are supposed to be present. 1864cdf0e10cSrcweir continue; 1865cdf0e10cSrcweir 1866cdf0e10cSrcweir ScDPSaveMember* pNewMem = new ScDPSaveMember(*pOldMem); 1867cdf0e10cSrcweir pSaveDim->AddMember(pNewMem); 1868cdf0e10cSrcweir } 1869cdf0e10cSrcweir 1870cdf0e10cSrcweir // Set the sorting mode to manual for now. We may introduce a new sorting 1871cdf0e10cSrcweir // mode later on. 1872cdf0e10cSrcweir 1873cdf0e10cSrcweir sheet::DataPilotFieldSortInfo aSortInfo; 1874cdf0e10cSrcweir aSortInfo.Mode = sheet::DataPilotFieldSortMode::MANUAL; 1875cdf0e10cSrcweir pSaveDim->SetSortInfo(&aSortInfo); 1876cdf0e10cSrcweir } 1877cdf0e10cSrcweir else 1878cdf0e10cSrcweir { 1879cdf0e10cSrcweir // without user list id, just apply sorting mode 1880cdf0e10cSrcweir 1881cdf0e10cSrcweir sheet::DataPilotFieldSortInfo aSortInfo; 1882cdf0e10cSrcweir aSortInfo.Mode = sheet::DataPilotFieldSortMode::NAME; 1883cdf0e10cSrcweir aSortInfo.IsAscending = bAscending; 1884cdf0e10cSrcweir pSaveDim->SetSortInfo(&aSortInfo); 1885cdf0e10cSrcweir } 1886cdf0e10cSrcweir 1887cdf0e10cSrcweir // Update the datapilot with the newly sorted field members. 1888cdf0e10cSrcweir 1889cdf0e10cSrcweir auto_ptr<ScDPObject> pNewObj(new ScDPObject(*pDPObj)); 1890cdf0e10cSrcweir pNewObj->SetSaveData(aNewSaveData); 1891cdf0e10cSrcweir ScDBDocFunc aFunc(*GetViewData()->GetDocShell()); 1892cdf0e10cSrcweir 1893cdf0e10cSrcweir return aFunc.DataPilotUpdate(pDPObj, pNewObj.get(), true, false); 1894cdf0e10cSrcweir } 1895cdf0e10cSrcweir 1896cdf0e10cSrcweir sal_Bool ScDBFunc::DataPilotMove( const ScRange& rSource, const ScAddress& rDest ) 1897cdf0e10cSrcweir { 1898cdf0e10cSrcweir sal_Bool bRet = sal_False; 1899cdf0e10cSrcweir ScDocument* pDoc = GetViewData()->GetDocument(); 1900cdf0e10cSrcweir ScDPObject* pDPObj = pDoc->GetDPAtCursor( rSource.aStart.Col(), rSource.aStart.Row(), rSource.aStart.Tab() ); 1901cdf0e10cSrcweir if ( pDPObj && pDPObj == pDoc->GetDPAtCursor( rDest.Col(), rDest.Row(), rDest.Tab() ) ) 1902cdf0e10cSrcweir { 1903cdf0e10cSrcweir sheet::DataPilotTableHeaderData aDestData; 1904cdf0e10cSrcweir pDPObj->GetHeaderPositionData( rDest, aDestData ); 1905cdf0e10cSrcweir bool bValid = ( aDestData.Dimension >= 0 ); // dropping onto a field 1906cdf0e10cSrcweir 1907cdf0e10cSrcweir // look through the source range 1908cdf0e10cSrcweir std::hash_set< rtl::OUString, rtl::OUStringHash, std::equal_to<rtl::OUString> > aMembersSet; // for lookup 1909cdf0e10cSrcweir std::vector< rtl::OUString > aMembersVector; // members in original order, for inserting 1910cdf0e10cSrcweir aMembersVector.reserve( std::max( static_cast<SCSIZE>( rSource.aEnd.Col() - rSource.aStart.Col() + 1 ), 1911cdf0e10cSrcweir static_cast<SCSIZE>( rSource.aEnd.Row() - rSource.aStart.Row() + 1 ) ) ); 1912cdf0e10cSrcweir for (SCROW nRow = rSource.aStart.Row(); bValid && nRow <= rSource.aEnd.Row(); ++nRow ) 1913cdf0e10cSrcweir for (SCCOL nCol = rSource.aStart.Col(); bValid && nCol <= rSource.aEnd.Col(); ++nCol ) 1914cdf0e10cSrcweir { 1915cdf0e10cSrcweir sheet::DataPilotTableHeaderData aSourceData; 1916cdf0e10cSrcweir pDPObj->GetHeaderPositionData( ScAddress( nCol, nRow, rSource.aStart.Tab() ), aSourceData ); 1917cdf0e10cSrcweir if ( aSourceData.Dimension == aDestData.Dimension && aSourceData.MemberName.getLength() ) 1918cdf0e10cSrcweir { 1919cdf0e10cSrcweir if ( aMembersSet.find( aSourceData.MemberName ) == aMembersSet.end() ) 1920cdf0e10cSrcweir { 1921cdf0e10cSrcweir aMembersSet.insert( aSourceData.MemberName ); 1922cdf0e10cSrcweir aMembersVector.push_back( aSourceData.MemberName ); 1923cdf0e10cSrcweir } 1924cdf0e10cSrcweir // duplicates are ignored 1925cdf0e10cSrcweir } 1926cdf0e10cSrcweir else 1927cdf0e10cSrcweir bValid = false; // empty (subtotal) or different field 1928cdf0e10cSrcweir } 1929cdf0e10cSrcweir 1930cdf0e10cSrcweir if ( bValid ) 1931cdf0e10cSrcweir { 1932cdf0e10cSrcweir sal_Bool bIsDataLayout; 1933cdf0e10cSrcweir String aDimName = pDPObj->GetDimName( aDestData.Dimension, bIsDataLayout ); 1934cdf0e10cSrcweir if ( !bIsDataLayout ) 1935cdf0e10cSrcweir { 1936cdf0e10cSrcweir ScDPSaveData aData( *pDPObj->GetSaveData() ); 1937cdf0e10cSrcweir ScDPSaveDimension* pDim = aData.GetDimensionByName( aDimName ); 1938cdf0e10cSrcweir 1939cdf0e10cSrcweir // get all member names in source order 1940cdf0e10cSrcweir uno::Sequence<rtl::OUString> aMemberNames; 1941cdf0e10cSrcweir pDPObj->GetMemberNames( aDestData.Dimension, aMemberNames ); 1942cdf0e10cSrcweir 1943cdf0e10cSrcweir bool bInserted = false; 1944cdf0e10cSrcweir 1945cdf0e10cSrcweir sal_Int32 nMemberCount = aMemberNames.getLength(); 1946cdf0e10cSrcweir for (sal_Int32 nMemberPos=0; nMemberPos<nMemberCount; ++nMemberPos) 1947cdf0e10cSrcweir { 1948cdf0e10cSrcweir String aMemberStr( aMemberNames[nMemberPos] ); 1949cdf0e10cSrcweir 1950cdf0e10cSrcweir if ( !bInserted && aMemberNames[nMemberPos] == aDestData.MemberName ) 1951cdf0e10cSrcweir { 1952cdf0e10cSrcweir // insert dragged items before this item 1953cdf0e10cSrcweir for ( std::vector<rtl::OUString>::const_iterator aIter = aMembersVector.begin(); 1954cdf0e10cSrcweir aIter != aMembersVector.end(); ++aIter ) 1955cdf0e10cSrcweir lcl_MoveToEnd( *pDim, *aIter ); 1956cdf0e10cSrcweir bInserted = true; 1957cdf0e10cSrcweir } 1958cdf0e10cSrcweir 1959cdf0e10cSrcweir if ( aMembersSet.find( aMemberStr ) == aMembersSet.end() ) // skip dragged items 1960cdf0e10cSrcweir lcl_MoveToEnd( *pDim, aMemberStr ); 1961cdf0e10cSrcweir } 1962cdf0e10cSrcweir // insert dragged item at end if dest wasn't found (for example, empty) 1963cdf0e10cSrcweir if ( !bInserted ) 1964cdf0e10cSrcweir for ( std::vector<rtl::OUString>::const_iterator aIter = aMembersVector.begin(); 1965cdf0e10cSrcweir aIter != aMembersVector.end(); ++aIter ) 1966cdf0e10cSrcweir lcl_MoveToEnd( *pDim, *aIter ); 1967cdf0e10cSrcweir 1968cdf0e10cSrcweir // Items that were in SaveData, but not in the source, end up at the start of the list. 1969cdf0e10cSrcweir 1970cdf0e10cSrcweir // set flag for manual sorting 1971cdf0e10cSrcweir sheet::DataPilotFieldSortInfo aSortInfo; 1972cdf0e10cSrcweir aSortInfo.Mode = sheet::DataPilotFieldSortMode::MANUAL; 1973cdf0e10cSrcweir pDim->SetSortInfo( &aSortInfo ); 1974cdf0e10cSrcweir 1975cdf0e10cSrcweir // apply changes 1976cdf0e10cSrcweir ScDBDocFunc aFunc( *GetViewData()->GetDocShell() ); 1977cdf0e10cSrcweir ScDPObject* pNewObj = new ScDPObject( *pDPObj ); 1978cdf0e10cSrcweir pNewObj->SetSaveData( aData ); 1979cdf0e10cSrcweir aFunc.DataPilotUpdate( pDPObj, pNewObj, sal_True, sal_False ); //! bApi for drag&drop? 1980cdf0e10cSrcweir delete pNewObj; 1981cdf0e10cSrcweir 1982cdf0e10cSrcweir Unmark(); // entry was moved - no use in leaving the old cell selected 1983cdf0e10cSrcweir 1984cdf0e10cSrcweir bRet = sal_True; 1985cdf0e10cSrcweir } 1986cdf0e10cSrcweir } 1987cdf0e10cSrcweir } 1988cdf0e10cSrcweir 1989cdf0e10cSrcweir return bRet; 1990cdf0e10cSrcweir } 1991cdf0e10cSrcweir 1992cdf0e10cSrcweir sal_Bool ScDBFunc::HasSelectionForDrillDown( sal_uInt16& rOrientation ) 1993cdf0e10cSrcweir { 1994cdf0e10cSrcweir sal_Bool bRet = sal_False; 1995cdf0e10cSrcweir 1996cdf0e10cSrcweir ScDPObject* pDPObj = GetViewData()->GetDocument()->GetDPAtCursor( GetViewData()->GetCurX(), 1997cdf0e10cSrcweir GetViewData()->GetCurY(), GetViewData()->GetTabNo() ); 1998cdf0e10cSrcweir if ( pDPObj ) 1999cdf0e10cSrcweir { 2000cdf0e10cSrcweir ScStrCollection aEntries; 2001cdf0e10cSrcweir long nSelectDimension = -1; 2002cdf0e10cSrcweir GetSelectedMemberList( aEntries, nSelectDimension ); 2003cdf0e10cSrcweir 2004cdf0e10cSrcweir if ( aEntries.GetCount() > 0 ) 2005cdf0e10cSrcweir { 2006cdf0e10cSrcweir sal_Bool bIsDataLayout; 2007cdf0e10cSrcweir String aDimName = pDPObj->GetDimName( nSelectDimension, bIsDataLayout ); 2008cdf0e10cSrcweir if ( !bIsDataLayout ) 2009cdf0e10cSrcweir { 2010cdf0e10cSrcweir ScDPSaveData* pSaveData = pDPObj->GetSaveData(); 2011cdf0e10cSrcweir ScDPSaveDimension* pDim = pSaveData->GetExistingDimensionByName( aDimName ); 2012cdf0e10cSrcweir if ( pDim ) 2013cdf0e10cSrcweir { 2014cdf0e10cSrcweir sal_uInt16 nDimOrient = pDim->GetOrientation(); 2015cdf0e10cSrcweir ScDPSaveDimension* pInner = pSaveData->GetInnermostDimension( nDimOrient ); 2016cdf0e10cSrcweir if ( pDim == pInner ) 2017cdf0e10cSrcweir { 2018cdf0e10cSrcweir rOrientation = nDimOrient; 2019cdf0e10cSrcweir bRet = sal_True; 2020cdf0e10cSrcweir } 2021cdf0e10cSrcweir } 2022cdf0e10cSrcweir } 2023cdf0e10cSrcweir } 2024cdf0e10cSrcweir } 2025cdf0e10cSrcweir 2026cdf0e10cSrcweir return bRet; 2027cdf0e10cSrcweir } 2028cdf0e10cSrcweir 2029cdf0e10cSrcweir void ScDBFunc::SetDataPilotDetails( sal_Bool bShow, const String* pNewDimensionName ) 2030cdf0e10cSrcweir { 2031cdf0e10cSrcweir ScDPObject* pDPObj = GetViewData()->GetDocument()->GetDPAtCursor( GetViewData()->GetCurX(), 2032cdf0e10cSrcweir GetViewData()->GetCurY(), GetViewData()->GetTabNo() ); 2033cdf0e10cSrcweir if ( pDPObj ) 2034cdf0e10cSrcweir { 2035cdf0e10cSrcweir ScStrCollection aEntries; 2036cdf0e10cSrcweir long nSelectDimension = -1; 2037cdf0e10cSrcweir GetSelectedMemberList( aEntries, nSelectDimension ); 2038cdf0e10cSrcweir 2039cdf0e10cSrcweir if ( aEntries.GetCount() > 0 ) 2040cdf0e10cSrcweir { 2041cdf0e10cSrcweir sal_Bool bIsDataLayout; 2042cdf0e10cSrcweir String aDimName = pDPObj->GetDimName( nSelectDimension, bIsDataLayout ); 2043cdf0e10cSrcweir if ( !bIsDataLayout ) 2044cdf0e10cSrcweir { 2045cdf0e10cSrcweir ScDPSaveData aData( *pDPObj->GetSaveData() ); 2046cdf0e10cSrcweir ScDPSaveDimension* pDim = aData.GetDimensionByName( aDimName ); 2047cdf0e10cSrcweir 2048cdf0e10cSrcweir if ( bShow && pNewDimensionName ) 2049cdf0e10cSrcweir { 2050cdf0e10cSrcweir // add the new dimension with the same orientation, at the end 2051cdf0e10cSrcweir 2052cdf0e10cSrcweir ScDPSaveDimension* pNewDim = aData.GetDimensionByName( *pNewDimensionName ); 2053cdf0e10cSrcweir ScDPSaveDimension* pDuplicated = NULL; 2054cdf0e10cSrcweir if ( pNewDim->GetOrientation() == sheet::DataPilotFieldOrientation_DATA ) 2055cdf0e10cSrcweir { 2056cdf0e10cSrcweir // Need to duplicate the dimension, create column/row in addition to data: 2057cdf0e10cSrcweir // The duplicated dimension inherits the existing settings, pNewDim is modified below. 2058cdf0e10cSrcweir pDuplicated = aData.DuplicateDimension( *pNewDimensionName ); 2059cdf0e10cSrcweir } 2060cdf0e10cSrcweir 2061cdf0e10cSrcweir sal_uInt16 nOrientation = pDim->GetOrientation(); 2062cdf0e10cSrcweir pNewDim->SetOrientation( nOrientation ); 2063cdf0e10cSrcweir 2064cdf0e10cSrcweir long nPosition = LONG_MAX; 2065cdf0e10cSrcweir aData.SetPosition( pNewDim, nPosition ); 2066cdf0e10cSrcweir 2067cdf0e10cSrcweir ScDPSaveDimension* pDataLayout = aData.GetDataLayoutDimension(); 2068cdf0e10cSrcweir if ( pDataLayout->GetOrientation() == nOrientation && 2069cdf0e10cSrcweir aData.GetDataDimensionCount() <= 1 ) 2070cdf0e10cSrcweir { 2071cdf0e10cSrcweir // If there is only one data dimension, the data layout dimension 2072cdf0e10cSrcweir // must still be the last one in its orientation. 2073cdf0e10cSrcweir aData.SetPosition( pDataLayout, nPosition ); 2074cdf0e10cSrcweir } 2075cdf0e10cSrcweir 2076cdf0e10cSrcweir if ( pDuplicated ) 2077cdf0e10cSrcweir { 2078cdf0e10cSrcweir // The duplicated (data) dimension needs to be behind the original dimension 2079cdf0e10cSrcweir aData.SetPosition( pDuplicated, nPosition ); 2080cdf0e10cSrcweir } 2081cdf0e10cSrcweir 2082cdf0e10cSrcweir // Hide details for all visible members (selected are changed below). 2083cdf0e10cSrcweir //! Use all members from source level instead (including non-visible)? 2084cdf0e10cSrcweir 2085cdf0e10cSrcweir ScStrCollection aVisibleEntries; 2086cdf0e10cSrcweir pDPObj->GetMemberResultNames( aVisibleEntries, nSelectDimension ); 2087cdf0e10cSrcweir 2088cdf0e10cSrcweir sal_uInt16 nVisCount = aVisibleEntries.GetCount(); 2089cdf0e10cSrcweir for (sal_uInt16 nVisPos=0; nVisPos<nVisCount; nVisPos++) 2090cdf0e10cSrcweir { 2091cdf0e10cSrcweir String aVisName = aVisibleEntries[nVisPos]->GetString(); 2092cdf0e10cSrcweir ScDPSaveMember* pMember = pDim->GetMemberByName( aVisName ); 2093cdf0e10cSrcweir pMember->SetShowDetails( sal_False ); 2094cdf0e10cSrcweir } 2095cdf0e10cSrcweir } 2096cdf0e10cSrcweir 2097cdf0e10cSrcweir sal_uInt16 nEntryCount = aEntries.GetCount(); 2098cdf0e10cSrcweir for (sal_uInt16 nEntry=0; nEntry<nEntryCount; nEntry++) 2099cdf0e10cSrcweir { 2100cdf0e10cSrcweir String aEntryName = aEntries[nEntry]->GetString(); 2101cdf0e10cSrcweir ScDPSaveMember* pMember = pDim->GetMemberByName( aEntryName ); 2102cdf0e10cSrcweir pMember->SetShowDetails( bShow ); 2103cdf0e10cSrcweir } 2104cdf0e10cSrcweir 2105cdf0e10cSrcweir // apply changes 2106cdf0e10cSrcweir ScDBDocFunc aFunc( *GetViewData()->GetDocShell() ); 2107cdf0e10cSrcweir ScDPObject* pNewObj = new ScDPObject( *pDPObj ); 2108cdf0e10cSrcweir pNewObj->SetSaveData( aData ); 2109cdf0e10cSrcweir aFunc.DataPilotUpdate( pDPObj, pNewObj, sal_True, sal_False ); 2110cdf0e10cSrcweir delete pNewObj; 2111cdf0e10cSrcweir 2112cdf0e10cSrcweir // unmark cell selection 2113cdf0e10cSrcweir Unmark(); 2114cdf0e10cSrcweir } 2115cdf0e10cSrcweir } 2116cdf0e10cSrcweir } 2117cdf0e10cSrcweir } 2118cdf0e10cSrcweir 2119cdf0e10cSrcweir void ScDBFunc::ShowDataPilotSourceData( ScDPObject& rDPObj, const Sequence<sheet::DataPilotFieldFilter>& rFilters ) 2120cdf0e10cSrcweir { 2121cdf0e10cSrcweir ScDocument* pDoc = GetViewData()->GetDocument(); 2122cdf0e10cSrcweir if (pDoc->GetDocumentShell()->IsReadOnly()) 2123cdf0e10cSrcweir { 2124cdf0e10cSrcweir ErrorMessage(STR_READONLYERR); 2125cdf0e10cSrcweir return; 2126cdf0e10cSrcweir } 2127cdf0e10cSrcweir 2128cdf0e10cSrcweir Reference<sheet::XDimensionsSupplier> xDimSupplier = rDPObj.GetSource(); 2129cdf0e10cSrcweir Reference<container::XNameAccess> xDims = xDimSupplier->getDimensions(); 2130cdf0e10cSrcweir Reference<sheet::XDrillDownDataSupplier> xDDSupplier(xDimSupplier, UNO_QUERY); 2131cdf0e10cSrcweir if (!xDDSupplier.is()) 2132cdf0e10cSrcweir return; 2133cdf0e10cSrcweir 2134cdf0e10cSrcweir Sequence< Sequence<Any> > aTabData = xDDSupplier->getDrillDownData(rFilters); 2135cdf0e10cSrcweir sal_Int32 nRowSize = aTabData.getLength(); 2136cdf0e10cSrcweir if (nRowSize <= 1) 2137cdf0e10cSrcweir // There is no data to show. Bail out. 2138cdf0e10cSrcweir return; 2139cdf0e10cSrcweir 2140cdf0e10cSrcweir sal_Int32 nColSize = aTabData[0].getLength(); 2141cdf0e10cSrcweir 2142cdf0e10cSrcweir SCTAB nNewTab = GetViewData()->GetTabNo(); 2143cdf0e10cSrcweir 2144cdf0e10cSrcweir auto_ptr<ScDocument> pInsDoc(new ScDocument(SCDOCMODE_CLIP)); 2145cdf0e10cSrcweir pInsDoc->ResetClip( pDoc, nNewTab ); 2146cdf0e10cSrcweir for (SCROW nRow = 0; nRow < nRowSize; ++nRow) 2147cdf0e10cSrcweir { 2148cdf0e10cSrcweir for (SCCOL nCol = 0; nCol < nColSize; ++nCol) 2149cdf0e10cSrcweir { 2150cdf0e10cSrcweir const Any& rAny = aTabData[nRow][nCol]; 2151cdf0e10cSrcweir rtl::OUString aStr; 2152cdf0e10cSrcweir double fVal; 2153cdf0e10cSrcweir if (rAny >>= aStr) 2154cdf0e10cSrcweir pInsDoc->PutCell( ScAddress(nCol, nRow, nNewTab), new ScStringCell(String(aStr)) ); 2155cdf0e10cSrcweir else if (rAny >>= fVal) 2156cdf0e10cSrcweir pInsDoc->SetValue(nCol, nRow, nNewTab, fVal); 2157cdf0e10cSrcweir } 2158cdf0e10cSrcweir } 2159cdf0e10cSrcweir 2160cdf0e10cSrcweir // set number format (important for dates) 2161cdf0e10cSrcweir for (SCCOL nCol = 0; nCol < nColSize; ++nCol) 2162cdf0e10cSrcweir { 2163cdf0e10cSrcweir rtl::OUString aStr; 2164cdf0e10cSrcweir if (!(aTabData[0][nCol] >>= aStr)) 2165cdf0e10cSrcweir continue; 2166cdf0e10cSrcweir 2167cdf0e10cSrcweir Reference<XPropertySet> xPropSet(xDims->getByName(aStr), UNO_QUERY); 2168cdf0e10cSrcweir if (!xPropSet.is()) 2169cdf0e10cSrcweir continue; 2170cdf0e10cSrcweir 2171cdf0e10cSrcweir Any any = xPropSet->getPropertyValue( rtl::OUString::createFromAscii(SC_UNO_NUMBERFO) ); 2172cdf0e10cSrcweir sal_Int32 nNumFmt = 0; 2173cdf0e10cSrcweir if (!(any >>= nNumFmt)) 2174cdf0e10cSrcweir continue; 2175cdf0e10cSrcweir 2176cdf0e10cSrcweir ScPatternAttr aPattern( pInsDoc->GetPool() ); 2177cdf0e10cSrcweir aPattern.GetItemSet().Put( SfxUInt32Item(ATTR_VALUE_FORMAT, static_cast<sal_uInt32>(nNumFmt)) ); 2178cdf0e10cSrcweir pInsDoc->ApplyPatternAreaTab(nCol, 1, nCol, nRowSize-1, nNewTab, aPattern); 2179cdf0e10cSrcweir } 2180cdf0e10cSrcweir 2181cdf0e10cSrcweir SCCOL nEndCol = 0; 2182cdf0e10cSrcweir SCROW nEndRow = 0; 2183cdf0e10cSrcweir pInsDoc->GetCellArea( nNewTab, nEndCol, nEndRow ); 2184cdf0e10cSrcweir pInsDoc->SetClipArea( ScRange( 0, 0, nNewTab, nEndCol, nEndRow, nNewTab ) ); 2185cdf0e10cSrcweir 2186cdf0e10cSrcweir ::svl::IUndoManager* pMgr = GetViewData()->GetDocShell()->GetUndoManager(); 2187cdf0e10cSrcweir String aUndo = ScGlobal::GetRscString( STR_UNDO_DOOUTLINE ); 2188cdf0e10cSrcweir pMgr->EnterListAction( aUndo, aUndo ); 2189cdf0e10cSrcweir 2190cdf0e10cSrcweir String aNewTabName; 2191cdf0e10cSrcweir pDoc->CreateValidTabName(aNewTabName); 2192cdf0e10cSrcweir if ( InsertTable(aNewTabName, nNewTab) ) 2193cdf0e10cSrcweir PasteFromClip( IDF_ALL, pInsDoc.get() ); 2194cdf0e10cSrcweir 2195cdf0e10cSrcweir pMgr->LeaveListAction(); 2196cdf0e10cSrcweir } 2197cdf0e10cSrcweir 2198cdf0e10cSrcweir // 2199cdf0e10cSrcweir // DB-Operationen (Sortieren, Filtern, Teilergebnisse) wiederholen 2200cdf0e10cSrcweir // 2201cdf0e10cSrcweir 2202cdf0e10cSrcweir void ScDBFunc::RepeatDB( sal_Bool bRecord ) 2203cdf0e10cSrcweir { 2204cdf0e10cSrcweir SCCOL nCurX = GetViewData()->GetCurX(); 2205cdf0e10cSrcweir SCROW nCurY = GetViewData()->GetCurY(); 2206cdf0e10cSrcweir SCTAB nTab = GetViewData()->GetTabNo(); 2207cdf0e10cSrcweir ScDocument* pDoc = GetViewData()->GetDocument(); 2208cdf0e10cSrcweir ScDBData* pDBData = GetDBData(); 2209cdf0e10cSrcweir if (bRecord && !pDoc->IsUndoEnabled()) 2210cdf0e10cSrcweir bRecord = sal_False; 2211cdf0e10cSrcweir 2212cdf0e10cSrcweir ScQueryParam aQueryParam; 2213cdf0e10cSrcweir pDBData->GetQueryParam( aQueryParam ); 2214cdf0e10cSrcweir sal_Bool bQuery = aQueryParam.GetEntry(0).bDoQuery; 2215cdf0e10cSrcweir 2216cdf0e10cSrcweir ScSortParam aSortParam; 2217cdf0e10cSrcweir pDBData->GetSortParam( aSortParam ); 2218cdf0e10cSrcweir sal_Bool bSort = aSortParam.bDoSort[0]; 2219cdf0e10cSrcweir 2220cdf0e10cSrcweir ScSubTotalParam aSubTotalParam; 2221cdf0e10cSrcweir pDBData->GetSubTotalParam( aSubTotalParam ); 2222cdf0e10cSrcweir sal_Bool bSubTotal = aSubTotalParam.bGroupActive[0] && !aSubTotalParam.bRemoveOnly; 2223cdf0e10cSrcweir 2224cdf0e10cSrcweir if ( bQuery || bSort || bSubTotal ) 2225cdf0e10cSrcweir { 2226cdf0e10cSrcweir sal_Bool bQuerySize = sal_False; 2227cdf0e10cSrcweir ScRange aOldQuery; 2228cdf0e10cSrcweir ScRange aNewQuery; 2229cdf0e10cSrcweir if (bQuery && !aQueryParam.bInplace) 2230cdf0e10cSrcweir { 2231cdf0e10cSrcweir ScDBData* pDest = pDoc->GetDBAtCursor( aQueryParam.nDestCol, aQueryParam.nDestRow, 2232cdf0e10cSrcweir aQueryParam.nDestTab, sal_True ); 2233cdf0e10cSrcweir if (pDest && pDest->IsDoSize()) 2234cdf0e10cSrcweir { 2235cdf0e10cSrcweir pDest->GetArea( aOldQuery ); 2236cdf0e10cSrcweir bQuerySize = sal_True; 2237cdf0e10cSrcweir } 2238cdf0e10cSrcweir } 2239cdf0e10cSrcweir 2240cdf0e10cSrcweir SCTAB nDummy; 2241cdf0e10cSrcweir SCCOL nStartCol; 2242cdf0e10cSrcweir SCROW nStartRow; 2243cdf0e10cSrcweir SCCOL nEndCol; 2244cdf0e10cSrcweir SCROW nEndRow; 2245cdf0e10cSrcweir pDBData->GetArea( nDummy, nStartCol, nStartRow, nEndCol, nEndRow ); 2246cdf0e10cSrcweir 2247cdf0e10cSrcweir //! Undo nur benoetigte Daten ? 2248cdf0e10cSrcweir 2249cdf0e10cSrcweir ScDocument* pUndoDoc = NULL; 2250cdf0e10cSrcweir ScOutlineTable* pUndoTab = NULL; 2251cdf0e10cSrcweir ScRangeName* pUndoRange = NULL; 2252cdf0e10cSrcweir ScDBCollection* pUndoDB = NULL; 2253cdf0e10cSrcweir 2254cdf0e10cSrcweir if (bRecord) 2255cdf0e10cSrcweir { 2256cdf0e10cSrcweir SCTAB nTabCount = pDoc->GetTableCount(); 2257cdf0e10cSrcweir pUndoDoc = new ScDocument( SCDOCMODE_UNDO ); 2258cdf0e10cSrcweir ScOutlineTable* pTable = pDoc->GetOutlineTable( nTab ); 2259cdf0e10cSrcweir if (pTable) 2260cdf0e10cSrcweir { 2261cdf0e10cSrcweir pUndoTab = new ScOutlineTable( *pTable ); 2262cdf0e10cSrcweir 2263cdf0e10cSrcweir SCCOLROW nOutStartCol; // Zeilen/Spaltenstatus 2264cdf0e10cSrcweir SCCOLROW nOutStartRow; 2265cdf0e10cSrcweir SCCOLROW nOutEndCol; 2266cdf0e10cSrcweir SCCOLROW nOutEndRow; 2267cdf0e10cSrcweir pTable->GetColArray()->GetRange( nOutStartCol, nOutEndCol ); 2268cdf0e10cSrcweir pTable->GetRowArray()->GetRange( nOutStartRow, nOutEndRow ); 2269cdf0e10cSrcweir 2270cdf0e10cSrcweir pUndoDoc->InitUndo( pDoc, nTab, nTab, sal_True, sal_True ); 2271cdf0e10cSrcweir pDoc->CopyToDocument( static_cast<SCCOL>(nOutStartCol), 0, nTab, static_cast<SCCOL>(nOutEndCol), MAXROW, nTab, IDF_NONE, sal_False, pUndoDoc ); 2272cdf0e10cSrcweir pDoc->CopyToDocument( 0, nOutStartRow, nTab, MAXCOL, nOutEndRow, nTab, IDF_NONE, sal_False, pUndoDoc ); 2273cdf0e10cSrcweir } 2274cdf0e10cSrcweir else 2275cdf0e10cSrcweir pUndoDoc->InitUndo( pDoc, nTab, nTab, sal_False, sal_True ); 2276cdf0e10cSrcweir 2277cdf0e10cSrcweir // Datenbereich sichern - incl. Filter-Ergebnis 2278cdf0e10cSrcweir pDoc->CopyToDocument( 0,nStartRow,nTab, MAXCOL,nEndRow,nTab, IDF_ALL, sal_False, pUndoDoc ); 2279cdf0e10cSrcweir 2280cdf0e10cSrcweir // alle Formeln wegen Referenzen 2281cdf0e10cSrcweir pDoc->CopyToDocument( 0,0,0, MAXCOL,MAXROW,nTabCount-1, IDF_FORMULA, sal_False, pUndoDoc ); 2282cdf0e10cSrcweir 2283cdf0e10cSrcweir // DB- und andere Bereiche 2284cdf0e10cSrcweir ScRangeName* pDocRange = pDoc->GetRangeName(); 2285cdf0e10cSrcweir if (pDocRange->GetCount()) 2286cdf0e10cSrcweir pUndoRange = new ScRangeName( *pDocRange ); 2287cdf0e10cSrcweir ScDBCollection* pDocDB = pDoc->GetDBCollection(); 2288cdf0e10cSrcweir if (pDocDB->GetCount()) 2289cdf0e10cSrcweir pUndoDB = new ScDBCollection( *pDocDB ); 2290cdf0e10cSrcweir } 2291cdf0e10cSrcweir 2292cdf0e10cSrcweir if (bSort && bSubTotal) 2293cdf0e10cSrcweir { 2294cdf0e10cSrcweir // Sortieren ohne SubTotals 2295cdf0e10cSrcweir 2296cdf0e10cSrcweir aSubTotalParam.bRemoveOnly = sal_True; // wird unten wieder zurueckgesetzt 2297cdf0e10cSrcweir DoSubTotals( aSubTotalParam, sal_False ); 2298cdf0e10cSrcweir } 2299cdf0e10cSrcweir 2300cdf0e10cSrcweir if (bSort) 2301cdf0e10cSrcweir { 2302cdf0e10cSrcweir pDBData->GetSortParam( aSortParam ); // Bereich kann sich geaendert haben 2303cdf0e10cSrcweir Sort( aSortParam, sal_False, sal_False); 2304cdf0e10cSrcweir } 2305cdf0e10cSrcweir if (bQuery) 2306cdf0e10cSrcweir { 2307cdf0e10cSrcweir pDBData->GetQueryParam( aQueryParam ); // Bereich kann sich geaendert haben 2308cdf0e10cSrcweir ScRange aAdvSource; 2309cdf0e10cSrcweir if (pDBData->GetAdvancedQuerySource(aAdvSource)) 2310cdf0e10cSrcweir { 2311cdf0e10cSrcweir pDoc->CreateQueryParam( 2312cdf0e10cSrcweir aAdvSource.aStart.Col(), aAdvSource.aStart.Row(), 2313cdf0e10cSrcweir aAdvSource.aEnd.Col(), aAdvSource.aEnd.Row(), 2314cdf0e10cSrcweir aAdvSource.aStart.Tab(), aQueryParam ); 2315cdf0e10cSrcweir Query( aQueryParam, &aAdvSource, sal_False ); 2316cdf0e10cSrcweir } 2317cdf0e10cSrcweir else 2318cdf0e10cSrcweir Query( aQueryParam, NULL, sal_False ); 2319cdf0e10cSrcweir 2320cdf0e10cSrcweir // bei nicht-inplace kann die Tabelle umgestellt worden sein 2321cdf0e10cSrcweir if ( !aQueryParam.bInplace && aQueryParam.nDestTab != nTab ) 2322cdf0e10cSrcweir SetTabNo( nTab ); 2323cdf0e10cSrcweir } 2324cdf0e10cSrcweir if (bSubTotal) 2325cdf0e10cSrcweir { 2326cdf0e10cSrcweir pDBData->GetSubTotalParam( aSubTotalParam ); // Bereich kann sich geaendert haben 2327cdf0e10cSrcweir aSubTotalParam.bRemoveOnly = sal_False; 2328cdf0e10cSrcweir DoSubTotals( aSubTotalParam, sal_False ); 2329cdf0e10cSrcweir } 2330cdf0e10cSrcweir 2331cdf0e10cSrcweir if (bRecord) 2332cdf0e10cSrcweir { 2333cdf0e10cSrcweir SCTAB nDummyTab; 2334cdf0e10cSrcweir SCCOL nDummyCol; 2335cdf0e10cSrcweir SCROW nDummyRow, nNewEndRow; 2336cdf0e10cSrcweir pDBData->GetArea( nDummyTab, nDummyCol,nDummyRow, nDummyCol,nNewEndRow ); 2337cdf0e10cSrcweir 2338cdf0e10cSrcweir const ScRange* pOld = NULL; 2339cdf0e10cSrcweir const ScRange* pNew = NULL; 2340cdf0e10cSrcweir if (bQuerySize) 2341cdf0e10cSrcweir { 2342cdf0e10cSrcweir ScDBData* pDest = pDoc->GetDBAtCursor( aQueryParam.nDestCol, aQueryParam.nDestRow, 2343cdf0e10cSrcweir aQueryParam.nDestTab, sal_True ); 2344cdf0e10cSrcweir if (pDest) 2345cdf0e10cSrcweir { 2346cdf0e10cSrcweir pDest->GetArea( aNewQuery ); 2347cdf0e10cSrcweir pOld = &aOldQuery; 2348cdf0e10cSrcweir pNew = &aNewQuery; 2349cdf0e10cSrcweir } 2350cdf0e10cSrcweir } 2351cdf0e10cSrcweir 2352cdf0e10cSrcweir GetViewData()->GetDocShell()->GetUndoManager()->AddUndoAction( 2353cdf0e10cSrcweir new ScUndoRepeatDB( GetViewData()->GetDocShell(), nTab, 2354cdf0e10cSrcweir nStartCol, nStartRow, nEndCol, nEndRow, 2355cdf0e10cSrcweir nNewEndRow, 2356cdf0e10cSrcweir nCurX, nCurY, 2357cdf0e10cSrcweir pUndoDoc, pUndoTab, 2358cdf0e10cSrcweir pUndoRange, pUndoDB, 2359cdf0e10cSrcweir pOld, pNew ) ); 2360cdf0e10cSrcweir } 2361cdf0e10cSrcweir 2362cdf0e10cSrcweir GetViewData()->GetDocShell()->PostPaint( 0,0,nTab, MAXCOL,MAXROW,nTab, 2363cdf0e10cSrcweir PAINT_GRID | PAINT_LEFT | PAINT_TOP | PAINT_SIZE ); 2364cdf0e10cSrcweir } 2365cdf0e10cSrcweir else // "Keine Operationen auszufuehren" 2366cdf0e10cSrcweir ErrorMessage(STR_MSSG_REPEATDB_0); 2367cdf0e10cSrcweir } 2368cdf0e10cSrcweir 2369cdf0e10cSrcweir 2370cdf0e10cSrcweir 2371cdf0e10cSrcweir 2372