LibreOffice Module sc (master)  1
dbdocfun.cxx
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  * Licensed to the Apache Software Foundation (ASF) under one or more
12  * contributor license agreements. See the NOTICE file distributed
13  * with this work for additional information regarding copyright
14  * ownership. The ASF licenses this file to you under the Apache
15  * License, Version 2.0 (the "License"); you may not use this file
16  * except in compliance with the License. You may obtain a copy of
17  * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 
20 #include <sfx2/app.hxx>
21 #include <vcl/svapp.hxx>
22 #include <vcl/weld.hxx>
24 #include <svx/svdpage.hxx>
25 #include <svx/svdoole2.hxx>
26 #include <com/sun/star/sdb/CommandType.hpp>
27 #include <unotools/charclass.hxx>
28 #include <comphelper/lok.hxx>
29 #include <osl/diagnose.h>
30 
31 #include <dbdocfun.hxx>
32 #include <dbdata.hxx>
33 #include <undodat.hxx>
34 #include <docsh.hxx>
35 #include <docfunc.hxx>
36 #include <globstr.hrc>
37 #include <scresid.hxx>
38 #include <globalnames.hxx>
39 #include <tabvwsh.hxx>
40 #include <patattr.hxx>
41 #include <rangenam.hxx>
42 #include <olinetab.hxx>
43 #include <dpobject.hxx>
44 #include <dpsave.hxx>
45 #include <dociter.hxx>
46 #include <editable.hxx>
47 #include <attrib.hxx>
48 #include <drwlayer.hxx>
49 #include <dpshttab.hxx>
50 #include <hints.hxx>
51 #include <queryentry.hxx>
52 #include <markdata.hxx>
53 #include <progress.hxx>
54 #include <undosort.hxx>
55 #include <inputopt.hxx>
56 #include <scmod.hxx>
57 
58 #include <chartlis.hxx>
59 #include <ChartTools.hxx>
60 
61 #include <memory>
62 
63 using namespace ::com::sun::star;
64 
65 bool ScDBDocFunc::AddDBRange( const OUString& rName, const ScRange& rRange )
66 {
67 
68  ScDocShellModificator aModificator( rDocShell );
69 
71  ScDBCollection* pDocColl = rDoc.GetDBCollection();
72  bool bUndo (rDoc.IsUndoEnabled());
73 
74  std::unique_ptr<ScDBCollection> pUndoColl;
75  if (bUndo)
76  pUndoColl.reset( new ScDBCollection( *pDocColl ) );
77 
78  std::unique_ptr<ScDBData> pNew(new ScDBData( rName, rRange.aStart.Tab(),
79  rRange.aStart.Col(), rRange.aStart.Row(),
80  rRange.aEnd.Col(), rRange.aEnd.Row() ));
81 
82  // #i55926# While loading XML, formula cells only have a single string token,
83  // so CompileDBFormula would never find any name (index) tokens, and would
84  // unnecessarily loop through all cells.
85  bool bCompile = !rDoc.IsImportingXML();
86  bool bOk;
87  if ( bCompile )
89  if ( rName == STR_DB_LOCAL_NONAME )
90  {
91  rDoc.SetAnonymousDBData(rRange.aStart.Tab(), std::move(pNew));
92  bOk = true;
93  }
94  else
95  {
96  bOk = pDocColl->getNamedDBs().insert(std::move(pNew));
97  }
98  if ( bCompile )
99  rDoc.CompileHybridFormula();
100 
101  if (!bOk)
102  {
103  return false;
104  }
105 
106  if (bUndo)
107  {
109  std::make_unique<ScUndoDBData>( &rDocShell, std::move(pUndoColl),
110  std::make_unique<ScDBCollection>( *pDocColl ) ) );
111  }
112 
113  aModificator.SetDocumentModified();
114  SfxGetpApp()->Broadcast( SfxHint( SfxHintId::ScDbAreasChanged ) );
115  return true;
116 }
117 
118 bool ScDBDocFunc::DeleteDBRange(const OUString& rName)
119 {
120  bool bDone = false;
121  ScDocument& rDoc = rDocShell.GetDocument();
122  ScDBCollection* pDocColl = rDoc.GetDBCollection();
123  bool bUndo = rDoc.IsUndoEnabled();
124 
125  ScDBCollection::NamedDBs& rDBs = pDocColl->getNamedDBs();
126  auto const iter = rDBs.findByUpperName2(ScGlobal::getCharClassPtr()->uppercase(rName));
127  if (iter != rDBs.end())
128  {
129  ScDocShellModificator aModificator( rDocShell );
130 
131  std::unique_ptr<ScDBCollection> pUndoColl;
132  if (bUndo)
133  pUndoColl.reset( new ScDBCollection( *pDocColl ) );
134 
135  rDoc.PreprocessDBDataUpdate();
136  rDBs.erase(iter);
137  rDoc.CompileHybridFormula();
138 
139  if (bUndo)
140  {
142  std::make_unique<ScUndoDBData>( &rDocShell, std::move(pUndoColl),
143  std::make_unique<ScDBCollection>( *pDocColl ) ) );
144  }
145 
146  aModificator.SetDocumentModified();
147  SfxGetpApp()->Broadcast( SfxHint( SfxHintId::ScDbAreasChanged ) );
148  bDone = true;
149  }
150 
151  return bDone;
152 }
153 
154 bool ScDBDocFunc::RenameDBRange( const OUString& rOld, const OUString& rNew )
155 {
156  bool bDone = false;
157  ScDocument& rDoc = rDocShell.GetDocument();
158  ScDBCollection* pDocColl = rDoc.GetDBCollection();
159  bool bUndo = rDoc.IsUndoEnabled();
160  ScDBCollection::NamedDBs& rDBs = pDocColl->getNamedDBs();
161  auto const iterOld = rDBs.findByUpperName2(ScGlobal::getCharClassPtr()->uppercase(rOld));
162  const ScDBData* pNew = rDBs.findByUpperName(ScGlobal::getCharClassPtr()->uppercase(rNew));
163  if (iterOld != rDBs.end() && !pNew)
164  {
165  ScDocShellModificator aModificator( rDocShell );
166 
167  std::unique_ptr<ScDBData> pNewData(new ScDBData(rNew, **iterOld));
168 
169  std::unique_ptr<ScDBCollection> pUndoColl( new ScDBCollection( *pDocColl ) );
170 
171  rDoc.PreprocessDBDataUpdate();
172  rDBs.erase(iterOld);
173  bool bInserted = rDBs.insert(std::move(pNewData));
174  if (!bInserted) // error -> restore old state
175  {
176  rDoc.SetDBCollection(std::move(pUndoColl)); // belongs to the document then
177  }
178 
179  rDoc.CompileHybridFormula();
180 
181  if (bInserted) // insertion worked
182  {
183  if (bUndo)
184  {
186  std::make_unique<ScUndoDBData>( &rDocShell, std::move(pUndoColl),
187  std::make_unique<ScDBCollection>( *pDocColl ) ) );
188  }
189  else
190  pUndoColl.reset();
191 
192  aModificator.SetDocumentModified();
193  SfxGetpApp()->Broadcast( SfxHint( SfxHintId::ScDbAreasChanged ) );
194  bDone = true;
195  }
196  }
197 
198  return bDone;
199 }
200 
201 void ScDBDocFunc::ModifyDBData( const ScDBData& rNewData )
202 {
203  ScDocument& rDoc = rDocShell.GetDocument();
204  ScDBCollection* pDocColl = rDoc.GetDBCollection();
205  bool bUndo = rDoc.IsUndoEnabled();
206 
207  ScDBData* pData = nullptr;
208  if (rNewData.GetName() == STR_DB_LOCAL_NONAME)
209  {
210  ScRange aRange;
211  rNewData.GetArea(aRange);
212  SCTAB nTab = aRange.aStart.Tab();
213  pData = rDoc.GetAnonymousDBData(nTab);
214  }
215  else
216  pData = pDocColl->getNamedDBs().findByUpperName(rNewData.GetUpperName());
217 
218  if (!pData)
219  return;
220 
221  ScDocShellModificator aModificator( rDocShell );
222  ScRange aOldRange, aNewRange;
223  pData->GetArea(aOldRange);
224  rNewData.GetArea(aNewRange);
225  bool bAreaChanged = ( aOldRange != aNewRange ); // then a recompilation is needed
226 
227  std::unique_ptr<ScDBCollection> pUndoColl;
228  if (bUndo)
229  pUndoColl.reset( new ScDBCollection( *pDocColl ) );
230 
231  *pData = rNewData;
232  if (bAreaChanged)
233  rDoc.CompileDBFormula();
234 
235  if (bUndo)
236  {
238  std::make_unique<ScUndoDBData>( &rDocShell, std::move(pUndoColl),
239  std::make_unique<ScDBCollection>( *pDocColl ) ) );
240  }
241 
242  aModificator.SetDocumentModified();
243 }
244 
245 void ScDBDocFunc::ModifyAllDBData( const ScDBCollection& rNewColl, const std::vector<ScRange>& rDelAreaList )
246 {
247  ScDocShellModificator aModificator(rDocShell);
248  ScDocument& rDoc = rDocShell.GetDocument();
249  ScDBCollection* pOldColl = rDoc.GetDBCollection();
250  std::unique_ptr<ScDBCollection> pUndoColl;
251  bool bRecord = rDoc.IsUndoEnabled();
252 
253  for (const auto& rDelArea : rDelAreaList)
254  {
255  // unregistering target in SBA no longer necessary
256  const ScAddress& rStart = rDelArea.aStart;
257  const ScAddress& rEnd = rDelArea.aEnd;
259  rStart.Tab(), rStart.Col(), rStart.Row(), rEnd.Col());
260  }
261 
262  if (bRecord)
263  pUndoColl.reset( new ScDBCollection( *pOldColl ) );
264 
265  // register target in SBA no longer necessary
266 
267  rDoc.PreprocessDBDataUpdate();
268  rDoc.SetDBCollection( std::unique_ptr<ScDBCollection>(new ScDBCollection( rNewColl )) );
269  rDoc.CompileHybridFormula();
270  pOldColl = nullptr;
271  rDocShell.PostPaint(ScRange(0, 0, 0, rDoc.MaxCol(), rDoc.MaxRow(), MAXTAB), PaintPartFlags::Grid);
272  aModificator.SetDocumentModified();
273  SfxGetpApp()->Broadcast( SfxHint( SfxHintId::ScDbAreasChanged ) );
274 
275  if (bRecord)
276  {
278  std::make_unique<ScUndoDBData>(&rDocShell, std::move(pUndoColl),
279  std::make_unique<ScDBCollection>(rNewColl)));
280  }
281 }
282 
283 bool ScDBDocFunc::RepeatDB( const OUString& rDBName, bool bApi, bool bIsUnnamed, SCTAB aTab )
284 {
286 
287  bool bDone = false;
288  ScDocument& rDoc = rDocShell.GetDocument();
289  bool bRecord = true;
290  if (!rDoc.IsUndoEnabled())
291  bRecord = false;
292  ScDBData* pDBData = nullptr;
293  if (bIsUnnamed)
294  {
295  pDBData = rDoc.GetAnonymousDBData( aTab );
296  }
297  else
298  {
299  ScDBCollection* pColl = rDoc.GetDBCollection();
300  if (pColl)
301  pDBData = pColl->getNamedDBs().findByUpperName(ScGlobal::getCharClassPtr()->uppercase(rDBName));
302  }
303 
304  if ( pDBData )
305  {
306  ScQueryParam aQueryParam;
307  pDBData->GetQueryParam( aQueryParam );
308  bool bQuery = aQueryParam.GetEntry(0).bDoQuery;
309 
310  ScSortParam aSortParam;
311  pDBData->GetSortParam( aSortParam );
312  bool bSort = aSortParam.maKeyState[0].bDoSort;
313 
314  ScSubTotalParam aSubTotalParam;
315  pDBData->GetSubTotalParam( aSubTotalParam );
316  bool bSubTotal = aSubTotalParam.bGroupActive[0] && !aSubTotalParam.bRemoveOnly;
317 
318  if ( bQuery || bSort || bSubTotal )
319  {
320  bool bQuerySize = false;
321  ScRange aOldQuery;
322  ScRange aNewQuery;
323  if (bQuery && !aQueryParam.bInplace)
324  {
325  ScDBData* pDest = rDoc.GetDBAtCursor( aQueryParam.nDestCol, aQueryParam.nDestRow,
326  aQueryParam.nDestTab, ScDBDataPortion::TOP_LEFT );
327  if (pDest && pDest->IsDoSize())
328  {
329  pDest->GetArea( aOldQuery );
330  bQuerySize = true;
331  }
332  }
333 
334  SCTAB nTab;
335  SCCOL nStartCol;
336  SCROW nStartRow;
337  SCCOL nEndCol;
338  SCROW nEndRow;
339  pDBData->GetArea( nTab, nStartCol, nStartRow, nEndCol, nEndRow );
340 
342 
343  ScDocumentUniquePtr pUndoDoc;
344  std::unique_ptr<ScOutlineTable> pUndoTab;
345  std::unique_ptr<ScRangeName> pUndoRange;
346  std::unique_ptr<ScDBCollection> pUndoDB;
347 
348  if (bRecord)
349  {
350  SCTAB nTabCount = rDoc.GetTableCount();
351  pUndoDoc.reset(new ScDocument( SCDOCMODE_UNDO ));
352  ScOutlineTable* pTable = rDoc.GetOutlineTable( nTab );
353  if (pTable)
354  {
355  pUndoTab.reset(new ScOutlineTable( *pTable ));
356 
357  // column/row state
358  SCCOLROW nOutStartCol, nOutEndCol;
359  SCCOLROW nOutStartRow, nOutEndRow;
360  pTable->GetColArray().GetRange( nOutStartCol, nOutEndCol );
361  pTable->GetRowArray().GetRange( nOutStartRow, nOutEndRow );
362 
363  pUndoDoc->InitUndo( rDoc, nTab, nTab, true, true );
364  rDoc.CopyToDocument(static_cast<SCCOL>(nOutStartCol), 0,
365  nTab, static_cast<SCCOL>(nOutEndCol), rDoc.MaxRow(), nTab,
366  InsertDeleteFlags::NONE, false, *pUndoDoc);
367  rDoc.CopyToDocument(0, static_cast<SCROW>(nOutStartRow),
368  nTab, rDoc.MaxCol(), static_cast<SCROW>(nOutEndRow), nTab,
369  InsertDeleteFlags::NONE, false, *pUndoDoc);
370  }
371  else
372  pUndoDoc->InitUndo( rDoc, nTab, nTab, false, true );
373 
374  // secure data range - incl. filtering result
375  rDoc.CopyToDocument(0, nStartRow, nTab, rDoc.MaxCol(), nEndRow, nTab, InsertDeleteFlags::ALL, false, *pUndoDoc);
376 
377  // all formulas because of references
378  rDoc.CopyToDocument(0, 0, 0, rDoc.MaxCol(), rDoc.MaxRow(), nTabCount-1, InsertDeleteFlags::FORMULA, false, *pUndoDoc);
379 
380  // ranges of DB and other
381  ScRangeName* pDocRange = rDoc.GetRangeName();
382  if (!pDocRange->empty())
383  pUndoRange.reset(new ScRangeName( *pDocRange ));
384  ScDBCollection* pDocDB = rDoc.GetDBCollection();
385  if (!pDocDB->empty())
386  pUndoDB.reset(new ScDBCollection( *pDocDB ));
387  }
388 
389  if (bSort && bSubTotal)
390  {
391  // sort without SubTotals
392 
393  aSubTotalParam.bRemoveOnly = true; // will be reset again further down
394  DoSubTotals( nTab, aSubTotalParam, false, bApi );
395  }
396 
397  if (bSort)
398  {
399  pDBData->GetSortParam( aSortParam ); // range may have changed
400  (void)Sort( nTab, aSortParam, false, false, bApi );
401  }
402  if (bQuery)
403  {
404  pDBData->GetQueryParam( aQueryParam ); // range may have changed
405  ScRange aAdvSource;
406  if (pDBData->GetAdvancedQuerySource(aAdvSource))
407  Query( nTab, aQueryParam, &aAdvSource, false, bApi );
408  else
409  Query( nTab, aQueryParam, nullptr, false, bApi );
410 
411  // at not-inplace the table may have been converted
412 // if ( !aQueryParam.bInplace && aQueryParam.nDestTab != nTab )
413 // SetTabNo( nTab );
414  }
415  if (bSubTotal)
416  {
417  pDBData->GetSubTotalParam( aSubTotalParam ); // range may have changed
418  aSubTotalParam.bRemoveOnly = false;
419  DoSubTotals( nTab, aSubTotalParam, false, bApi );
420  }
421 
422  if (bRecord)
423  {
424  SCTAB nDummyTab;
425  SCCOL nDummyCol;
426  SCROW nDummyRow;
427  SCROW nNewEndRow;
428  pDBData->GetArea( nDummyTab, nDummyCol,nDummyRow, nDummyCol,nNewEndRow );
429 
430  const ScRange* pOld = nullptr;
431  const ScRange* pNew = nullptr;
432  if (bQuerySize)
433  {
434  ScDBData* pDest = rDoc.GetDBAtCursor( aQueryParam.nDestCol, aQueryParam.nDestRow,
435  aQueryParam.nDestTab, ScDBDataPortion::TOP_LEFT );
436  if (pDest)
437  {
438  pDest->GetArea( aNewQuery );
439  pOld = &aOldQuery;
440  pNew = &aNewQuery;
441  }
442  }
443 
445  std::make_unique<ScUndoRepeatDB>( &rDocShell, nTab,
446  nStartCol, nStartRow, nEndCol, nEndRow,
447  nNewEndRow,
448  //nCurX, nCurY,
449  nStartCol, nStartRow,
450  std::move(pUndoDoc), std::move(pUndoTab),
451  std::move(pUndoRange), std::move(pUndoDB),
452  pOld, pNew ) );
453  }
454 
455  rDocShell.PostPaint(ScRange(0, 0, nTab, rDoc.MaxCol(), rDoc.MaxRow(), nTab),
457  bDone = true;
458  }
459  else if (!bApi) // "Don't execute any operations"
460  rDocShell.ErrorMessage(STR_MSSG_REPEATDB_0);
461  }
462 
463  return bDone;
464 }
465 
466 bool ScDBDocFunc::Sort( SCTAB nTab, const ScSortParam& rSortParam,
467  bool bRecord, bool bPaint, bool bApi )
468 {
469  ScDocShellModificator aModificator( rDocShell );
470 
471  ScDocument& rDoc = rDocShell.GetDocument();
472  if (bRecord && !rDoc.IsUndoEnabled())
473  bRecord = false;
474 
475  ScDBData* pDBData = rDoc.GetDBAtArea( nTab, rSortParam.nCol1, rSortParam.nRow1,
476  rSortParam.nCol2, rSortParam.nRow2 );
477  if (!pDBData)
478  {
479  OSL_FAIL( "Sort: no DBData" );
480  return false;
481  }
482 
483  bool bCopy = !rSortParam.bInplace;
484  if ( bCopy && rSortParam.nDestCol == rSortParam.nCol1 &&
485  rSortParam.nDestRow == rSortParam.nRow1 && rSortParam.nDestTab == nTab )
486  bCopy = false;
487 
488  ScSortParam aLocalParam( rSortParam );
489  if ( bCopy )
490  {
491  // Copy the data range to the destination then move the sort range to it.
492  ScRange aSrcRange(rSortParam.nCol1, rSortParam.nRow1, nTab, rSortParam.nCol2, rSortParam.nRow2, nTab);
493  ScAddress aDestPos(rSortParam.nDestCol,rSortParam.nDestRow,rSortParam.nDestTab);
494 
495  ScDocFunc& rDocFunc = rDocShell.GetDocFunc();
496  bool bRet = rDocFunc.MoveBlock(aSrcRange, aDestPos, false, bRecord, bPaint, bApi);
497 
498  if (!bRet)
499  return false;
500 
501  aLocalParam.MoveToDest();
502  nTab = aLocalParam.nDestTab;
503  }
504 
505  // tdf#119804: If there is a header row/column, it won't be affected by
506  // sorting; so we can exclude it from the test.
507  SCROW nStartingRowToEdit = aLocalParam.nRow1;
508  SCCOL nStartingColToEdit = aLocalParam.nCol1;
509  if ( aLocalParam.bHasHeader )
510  {
511  if ( aLocalParam.bByRow )
512  nStartingRowToEdit++;
513  else
514  nStartingColToEdit++;
515  }
516  ScEditableTester aTester( rDoc, nTab, nStartingColToEdit, nStartingRowToEdit,
517  aLocalParam.nCol2, aLocalParam.nRow2, true /*bNoMatrixAtAll*/ );
518  if (!aTester.IsEditable())
519  {
520  if (!bApi)
522  return false;
523  }
524 
525  // Adjust aLocalParam cols/rows to used data area. Keep sticky top row or
526  // column (depending on direction) in any case, not just if it has headers,
527  // so empty leading cells will be sorted to the end.
528  bool bShrunk = false;
529  rDoc.ShrinkToUsedDataArea( bShrunk, nTab, aLocalParam.nCol1, aLocalParam.nRow1,
530  aLocalParam.nCol2, aLocalParam.nRow2, false, aLocalParam.bByRow, !aLocalParam.bByRow,
531  aLocalParam.bIncludeComments, aLocalParam.bIncludeGraphicObjects );
532 
533  SCROW nStartRow = aLocalParam.nRow1;
534  if (aLocalParam.bByRow && aLocalParam.bHasHeader && nStartRow < aLocalParam.nRow2)
535  ++nStartRow;
536 
537  if ( aLocalParam.bIncludePattern && rDoc.HasAttrib(
538  aLocalParam.nCol1, nStartRow , nTab,
539  aLocalParam.nCol2, aLocalParam.nRow2, nTab,
541  {
542  // merge attributes would be mixed up during sorting
543  if (!bApi)
544  rDocShell.ErrorMessage(STR_SORT_ERR_MERGED);
545  return false;
546  }
547 
548  // execute
549 
551 
552  // Calculate the script types for all cells in the sort range beforehand.
553  // This will speed up the row height adjustment that takes place after the
554  // sort.
555  rDoc.UpdateScriptTypes(
556  ScAddress(aLocalParam.nCol1,nStartRow,nTab),
557  aLocalParam.nCol2-aLocalParam.nCol1+1,
558  aLocalParam.nRow2-nStartRow+1);
559 
560  // No point adjusting row heights after the sort when all rows have the same height.
561  bool bUniformRowHeight =
562  rDoc.HasUniformRowHeight(nTab, nStartRow, aLocalParam.nRow2);
563 
564  bool bRepeatQuery = false; // repeat existing filter?
565  ScQueryParam aQueryParam;
566  pDBData->GetQueryParam( aQueryParam );
567  if ( aQueryParam.GetEntry(0).bDoQuery )
568  bRepeatQuery = true;
569 
570  sc::ReorderParam aUndoParam;
571 
572  // don't call ScDocument::Sort with an empty SortParam (may be empty here if bCopy is set)
573  if (aLocalParam.GetSortKeyCount() && aLocalParam.maKeyState[0].bDoSort)
574  {
575  ScInputOptions aInputOption = SC_MOD()->GetInputOptions();
576  bool bUpdateRefs = aInputOption.GetSortRefUpdate();
577  ScProgress aProgress(&rDocShell, ScResId(STR_PROGRESS_SORTING), 0, true);
578  if (!bRepeatQuery)
579  bRepeatQuery = rDoc.HasHiddenRows(aLocalParam.nRow1, aLocalParam.nRow2, nTab);
580  rDoc.Sort(nTab, aLocalParam, bRepeatQuery, bUpdateRefs, &aProgress, &aUndoParam);
581  }
582 
583  if (bRecord)
584  {
585  // Set up an undo object.
587  std::make_unique<sc::UndoSort>(&rDocShell, aUndoParam));
588  }
589 
590  pDBData->SetSortParam(rSortParam);
591  // Remember additional settings on anonymous database ranges.
592  if (pDBData == rDoc.GetAnonymousDBData( nTab) || rDoc.GetDBCollection()->getAnonDBs().has( pDBData))
593  pDBData->UpdateFromSortParam( rSortParam);
594 
596  {
597  SfxViewShell* pSomeViewForThisDoc = rDocShell.GetBestViewShell(false);
598  SfxViewShell* pViewShell = SfxViewShell::GetFirst();
599  while (pViewShell)
600  {
601  ScTabViewShell* pTabViewShell = dynamic_cast<ScTabViewShell*>(pViewShell);
602  if (pTabViewShell && pTabViewShell->GetDocId() == pSomeViewForThisDoc->GetDocId())
603  {
604  pTabViewShell->GetViewData().GetLOKHeightHelper(nTab)->invalidateByIndex(nStartRow);
605  }
606  pViewShell = SfxViewShell::GetNext(*pViewShell);
607  }
608 
610  pSomeViewForThisDoc, false /* bColumns */, true /* bRows */, true /* bSizes*/,
611  true /* bHidden */, true /* bFiltered */, true /* bGroups */, nTab);
612  }
613 
614  if (nStartRow <= aLocalParam.nRow2)
615  {
616  ScRange aDirtyRange(
617  aLocalParam.nCol1, nStartRow, nTab,
618  aLocalParam.nCol2, aLocalParam.nRow2, nTab);
619  rDoc.SetDirty( aDirtyRange, true );
620  }
621 
622  if (bPaint)
623  {
625  SCCOL nStartX = aLocalParam.nCol1;
626  SCROW nStartY = aLocalParam.nRow1;
627  SCCOL nEndX = aLocalParam.nCol2;
628  SCROW nEndY = aLocalParam.nRow2;
629  if ( bRepeatQuery )
630  {
631  nPaint |= PaintPartFlags::Left;
632  nStartX = 0;
633  nEndX = rDoc.MaxCol();
634  }
635  rDocShell.PostPaint(ScRange(nStartX, nStartY, nTab, nEndX, nEndY, nTab), nPaint);
636  }
637 
638  if (!bUniformRowHeight && nStartRow <= aLocalParam.nRow2)
639  rDocShell.AdjustRowHeight(nStartRow, aLocalParam.nRow2, nTab);
640 
641  aModificator.SetDocumentModified();
642 
643  return true;
644 }
645 
646 bool ScDBDocFunc::Query( SCTAB nTab, const ScQueryParam& rQueryParam,
647  const ScRange* pAdvSource, bool bRecord, bool bApi )
648 {
649  ScDocShellModificator aModificator( rDocShell );
650 
651  ScDocument& rDoc = rDocShell.GetDocument();
652 
654  if (pViewSh && ScTabViewShell::isAnyEditViewInRange(pViewSh, /*bColumns*/ false, rQueryParam.nRow1, rQueryParam.nRow2))
655  {
656  return false;
657  }
658 
659  if (bRecord && !rDoc.IsUndoEnabled())
660  bRecord = false;
661  ScDBData* pDBData = rDoc.GetDBAtArea( nTab, rQueryParam.nCol1, rQueryParam.nRow1,
662  rQueryParam.nCol2, rQueryParam.nRow2 );
663  if (!pDBData)
664  {
665  OSL_FAIL( "Query: no DBData" );
666  return false;
667  }
668 
669  // Change from Inplace to non-Inplace, only then cancel Inplace:
670  // (only if "Persistent" is selected in the dialog)
671 
672  if ( !rQueryParam.bInplace && pDBData->HasQueryParam() && rQueryParam.bDestPers )
673  {
674  ScQueryParam aOldQuery;
675  pDBData->GetQueryParam(aOldQuery);
676  if (aOldQuery.bInplace)
677  {
678  // cancel old filtering
679 
680  SCSIZE nEC = aOldQuery.GetEntryCount();
681  for (SCSIZE i=0; i<nEC; i++)
682  aOldQuery.GetEntry(i).bDoQuery = false;
683  aOldQuery.bDuplicate = true;
684  Query( nTab, aOldQuery, nullptr, bRecord, bApi );
685  }
686  }
687 
688  ScQueryParam aLocalParam( rQueryParam ); // for Paint / destination range
689  bool bCopy = !rQueryParam.bInplace; // copied in Table::Query
690  ScDBData* pDestData = nullptr; // range to be copied to
691  bool bDoSize = false; // adjust destination size (insert/delete)
692  SCCOL nFormulaCols = 0; // only at bDoSize
693  bool bKeepFmt = false;
694  ScRange aOldDest;
695  ScRange aDestTotal;
696  if ( bCopy && rQueryParam.nDestCol == rQueryParam.nCol1 &&
697  rQueryParam.nDestRow == rQueryParam.nRow1 && rQueryParam.nDestTab == nTab )
698  bCopy = false;
699  SCTAB nDestTab = nTab;
700  if ( bCopy )
701  {
702  aLocalParam.MoveToDest();
703  nDestTab = rQueryParam.nDestTab;
704  if ( !rDoc.ValidColRow( aLocalParam.nCol2, aLocalParam.nRow2 ) )
705  {
706  if (!bApi)
707  rDocShell.ErrorMessage(STR_PASTE_FULL);
708  return false;
709  }
710 
711  ScEditableTester aTester( rDoc, nDestTab, aLocalParam.nCol1,aLocalParam.nRow1,
712  aLocalParam.nCol2,aLocalParam.nRow2);
713  if (!aTester.IsEditable())
714  {
715  if (!bApi)
717  return false;
718  }
719 
720  pDestData = rDoc.GetDBAtCursor( rQueryParam.nDestCol, rQueryParam.nDestRow,
721  rQueryParam.nDestTab, ScDBDataPortion::TOP_LEFT );
722  if (pDestData)
723  {
724  pDestData->GetArea( aOldDest );
725  aDestTotal=ScRange( rQueryParam.nDestCol,
726  rQueryParam.nDestRow,
727  nDestTab,
728  rQueryParam.nDestCol + rQueryParam.nCol2 - rQueryParam.nCol1,
729  rQueryParam.nDestRow + rQueryParam.nRow2 - rQueryParam.nRow1,
730  nDestTab );
731 
732  bDoSize = pDestData->IsDoSize();
733  // test if formulas need to be filled in (nFormulaCols):
734  if ( bDoSize && aOldDest.aEnd.Col() == aDestTotal.aEnd.Col() )
735  {
736  SCCOL nTestCol = aOldDest.aEnd.Col() + 1; // next to the range
737  SCROW nTestRow = rQueryParam.nDestRow +
738  ( aLocalParam.bHasHeader ? 1 : 0 );
739  while ( nTestCol <= rDoc.MaxCol() &&
740  rDoc.GetCellType(ScAddress( nTestCol, nTestRow, nTab )) == CELLTYPE_FORMULA )
741  {
742  ++nTestCol;
743  ++nFormulaCols;
744  }
745  }
746 
747  bKeepFmt = pDestData->IsKeepFmt();
748  if ( bDoSize && !rDoc.CanFitBlock( aOldDest, aDestTotal ) )
749  {
750  if (!bApi)
751  rDocShell.ErrorMessage(STR_MSSG_DOSUBTOTALS_2); // cannot insert rows
752  return false;
753  }
754  }
755  }
756 
757  // execute
758 
760 
761  bool bKeepSub = false; // repeat existing partial results?
762  if (rQueryParam.GetEntry(0).bDoQuery) // not at cancellation
763  {
764  ScSubTotalParam aSubTotalParam;
765  pDBData->GetSubTotalParam( aSubTotalParam ); // partial results exist?
766 
767  if ( aSubTotalParam.bGroupActive[0] && !aSubTotalParam.bRemoveOnly )
768  bKeepSub = true;
769  }
770 
771  ScDocumentUniquePtr pUndoDoc;
772  std::unique_ptr<ScDBCollection> pUndoDB;
773  const ScRange* pOld = nullptr;
774 
775  if ( bRecord )
776  {
777  pUndoDoc.reset(new ScDocument( SCDOCMODE_UNDO ));
778  if (bCopy)
779  {
780  pUndoDoc->InitUndo( rDoc, nDestTab, nDestTab, false, true );
781  rDoc.CopyToDocument(aLocalParam.nCol1, aLocalParam.nRow1, nDestTab,
782  aLocalParam.nCol2, aLocalParam.nRow2, nDestTab,
783  InsertDeleteFlags::ALL, false, *pUndoDoc);
784  // secure attributes in case they were copied along
785 
786  if (pDestData)
787  {
788  rDoc.CopyToDocument(aOldDest, InsertDeleteFlags::ALL, false, *pUndoDoc);
789  pOld = &aOldDest;
790  }
791  }
792  else
793  {
794  pUndoDoc->InitUndo( rDoc, nTab, nTab, false, true );
795  rDoc.CopyToDocument(0, rQueryParam.nRow1, nTab, rDoc.MaxCol(), rQueryParam.nRow2, nTab,
796  InsertDeleteFlags::NONE, false, *pUndoDoc);
797  }
798 
799  ScDBCollection* pDocDB = rDoc.GetDBCollection();
800  if (!pDocDB->empty())
801  pUndoDB.reset(new ScDBCollection( *pDocDB ));
802 
803  rDoc.BeginDrawUndo();
804  }
805 
806  std::unique_ptr<ScDocument> pAttribDoc;
807  ScRange aAttribRange;
808  if (pDestData) // delete destination range
809  {
810  if ( bKeepFmt )
811  {
812  // smaller of the end columns, header+1 row
813  aAttribRange = aOldDest;
814  if ( aAttribRange.aEnd.Col() > aDestTotal.aEnd.Col() )
815  aAttribRange.aEnd.SetCol( aDestTotal.aEnd.Col() );
816  aAttribRange.aEnd.SetRow( aAttribRange.aStart.Row() +
817  ( aLocalParam.bHasHeader ? 1 : 0 ) );
818 
819  // also for filled-in formulas
820  aAttribRange.aEnd.SetCol( aAttribRange.aEnd.Col() + nFormulaCols );
821 
822  pAttribDoc.reset(new ScDocument( SCDOCMODE_UNDO ));
823  pAttribDoc->InitUndo( rDoc, nDestTab, nDestTab, false, true );
824  rDoc.CopyToDocument(aAttribRange, InsertDeleteFlags::ATTRIB, false, *pAttribDoc);
825  }
826 
827  if ( bDoSize )
828  rDoc.FitBlock( aOldDest, aDestTotal );
829  else
830  rDoc.DeleteAreaTab(aOldDest, InsertDeleteFlags::ALL); // simply delete
831  }
832 
833  // execute filtering on the document
834  SCSIZE nCount = rDoc.Query( nTab, rQueryParam, bKeepSub );
835  pDBData->CalcSaveFilteredCount( nCount );
836  if (bCopy)
837  {
838  aLocalParam.nRow2 = aLocalParam.nRow1 + nCount;
839  if (!aLocalParam.bHasHeader && nCount > 0)
840  --aLocalParam.nRow2;
841 
842  if ( bDoSize )
843  {
844  // adjust to the real result range
845  // (this here is always a reduction)
846 
847  ScRange aNewDest( aLocalParam.nCol1, aLocalParam.nRow1, nDestTab,
848  aLocalParam.nCol2, aLocalParam.nRow2, nDestTab );
849  rDoc.FitBlock( aDestTotal, aNewDest, false ); // sal_False - don't delete
850 
851  if ( nFormulaCols > 0 )
852  {
853  // fill in formulas
855 
856  ScRange aNewForm( aLocalParam.nCol2+1, aLocalParam.nRow1, nDestTab,
857  aLocalParam.nCol2+nFormulaCols, aLocalParam.nRow2, nDestTab );
858  ScRange aOldForm = aNewForm;
859  aOldForm.aEnd.SetRow( aOldDest.aEnd.Row() );
860  rDoc.FitBlock( aOldForm, aNewForm, false );
861 
862  ScMarkData aMark(rDoc.GetSheetLimits());
863  aMark.SelectOneTable(nDestTab);
864  SCROW nFStartY = aLocalParam.nRow1 + ( aLocalParam.bHasHeader ? 1 : 0 );
865 
866  sal_uLong nProgCount = nFormulaCols;
867  nProgCount *= aLocalParam.nRow2 - nFStartY;
868  ScProgress aProgress( rDoc.GetDocumentShell(),
869  ScResId(STR_FILL_SERIES_PROGRESS), nProgCount, true );
870 
871  rDoc.Fill( aLocalParam.nCol2+1, nFStartY,
872  aLocalParam.nCol2+nFormulaCols, nFStartY, &aProgress, aMark,
873  aLocalParam.nRow2 - nFStartY,
875  }
876  }
877 
878  if ( pAttribDoc ) // copy back the memorized attributes
879  {
880  // Header
881  if (aLocalParam.bHasHeader)
882  {
883  ScRange aHdrRange = aAttribRange;
884  aHdrRange.aEnd.SetRow( aHdrRange.aStart.Row() );
885  pAttribDoc->CopyToDocument(aHdrRange, InsertDeleteFlags::ATTRIB, false, rDoc);
886  }
887 
888  // Data
889  SCCOL nAttrEndCol = aAttribRange.aEnd.Col();
890  SCROW nAttrRow = aAttribRange.aStart.Row() + ( aLocalParam.bHasHeader ? 1 : 0 );
891  for (SCCOL nCol = aAttribRange.aStart.Col(); nCol<=nAttrEndCol; nCol++)
892  {
893  const ScPatternAttr* pSrcPattern = pAttribDoc->GetPattern(
894  nCol, nAttrRow, nDestTab );
895  OSL_ENSURE(pSrcPattern,"Pattern is 0");
896  if (pSrcPattern)
897  {
898  rDoc.ApplyPatternAreaTab( nCol, nAttrRow, nCol, aLocalParam.nRow2,
899  nDestTab, *pSrcPattern );
900  const ScStyleSheet* pStyle = pSrcPattern->GetStyleSheet();
901  if (pStyle)
902  rDoc.ApplyStyleAreaTab( nCol, nAttrRow, nCol, aLocalParam.nRow2,
903  nDestTab, *pStyle );
904  }
905  }
906  }
907  }
908 
909  // saving: Inplace always, otherwise depending on setting
910  // old Inplace-Filter may have already been removed
911 
912  bool bSave = rQueryParam.bInplace || rQueryParam.bDestPers;
913  if (bSave) // memorize
914  {
915  pDBData->SetQueryParam( rQueryParam );
916  pDBData->SetHeader( rQueryParam.bHasHeader );
917  pDBData->SetAdvancedQuerySource( pAdvSource ); // after SetQueryParam
918  }
919 
920  if (bCopy) // memorize new DB range
921  {
922  // Selection is done afterwards from outside (dbfunc).
923  // Currently through the DB area at the destination position,
924  // so a range must be created there in any case.
925 
926  ScDBData* pNewData;
927  if (pDestData)
928  pNewData = pDestData; // range exists -> adjust (always!)
929  else // create range
930  pNewData = rDocShell.GetDBData(
931  ScRange( aLocalParam.nCol1, aLocalParam.nRow1, nDestTab,
932  aLocalParam.nCol2, aLocalParam.nRow2, nDestTab ),
934 
935  if (pNewData)
936  {
937  pNewData->SetArea( nDestTab, aLocalParam.nCol1, aLocalParam.nRow1,
938  aLocalParam.nCol2, aLocalParam.nRow2 );
939 
940  // query parameter is no longer set at the destination, only leads to confusion
941  // and mistakes with the query parameter at the source range (#37187#)
942  }
943  else
944  {
945  OSL_FAIL("Target are not available");
946  }
947  }
948 
949  if (!bCopy)
950  {
951  rDoc.InvalidatePageBreaks(nTab);
952  rDoc.UpdatePageBreaks( nTab );
953  }
954 
955  // #i23299# Subtotal functions depend on cell's filtered states.
956  ScRange aDirtyRange(0 , aLocalParam.nRow1, nDestTab, rDoc.MaxCol(), aLocalParam.nRow2, nDestTab);
957  rDoc.SetSubTotalCellsDirty(aDirtyRange);
958 
959  if ( bRecord )
960  {
961  // create undo action after executing, because of drawing layer undo
963  std::make_unique<ScUndoQuery>( &rDocShell, nTab, rQueryParam, std::move(pUndoDoc), std::move(pUndoDB),
964  pOld, bDoSize, pAdvSource ) );
965  }
966 
967  if ( pViewSh )
968  {
969  // could there be horizontal autofilter ?
970  // maybe it would be better to set bColumns to !rQueryParam.bByRow ?
971  // anyway at the beginning the value of bByRow is 'false'
972  // then after the first sort action it becomes 'true'
973  pViewSh->OnLOKShowHideColRow(/*bColumns*/ false, rQueryParam.nRow1 - 1);
974  }
975 
976  if (bCopy)
977  {
978  SCCOL nEndX = aLocalParam.nCol2;
979  SCROW nEndY = aLocalParam.nRow2;
980  if (pDestData)
981  {
982  if ( aOldDest.aEnd.Col() > nEndX )
983  nEndX = aOldDest.aEnd.Col();
984  if ( aOldDest.aEnd.Row() > nEndY )
985  nEndY = aOldDest.aEnd.Row();
986  }
987  if (bDoSize)
988  nEndY = rDoc.MaxRow();
990  ScRange(aLocalParam.nCol1, aLocalParam.nRow1, nDestTab, nEndX, nEndY, nDestTab),
992  }
993  else
995  ScRange(0, rQueryParam.nRow1, nTab, rDoc.MaxCol(), rDoc.MaxRow(), nTab),
997  aModificator.SetDocumentModified();
998 
999  return true;
1000 }
1001 
1003  bool bRecord, bool bApi )
1004 {
1006  // then stays outside:
1007  // - mark new range (from DBData)
1008  // - SelectionChanged (?)
1009 
1010  bool bDo = !rParam.bRemoveOnly; // sal_False = only delete
1011 
1012  ScDocument& rDoc = rDocShell.GetDocument();
1013  if (bRecord && !rDoc.IsUndoEnabled())
1014  bRecord = false;
1015  ScDBData* pDBData = rDoc.GetDBAtArea( nTab, rParam.nCol1, rParam.nRow1,
1016  rParam.nCol2, rParam.nRow2 );
1017  if (!pDBData)
1018  {
1019  OSL_FAIL( "SubTotals: no DBData" );
1020  return;
1021  }
1022 
1023  ScEditableTester aTester( rDoc, nTab, 0,rParam.nRow1+1, rDoc.MaxCol(),rDoc.MaxRow() );
1024  if (!aTester.IsEditable())
1025  {
1026  if (!bApi)
1027  rDocShell.ErrorMessage(aTester.GetMessageId());
1028  return;
1029  }
1030 
1031  if (rDoc.HasAttrib( rParam.nCol1, rParam.nRow1+1, nTab,
1032  rParam.nCol2, rParam.nRow2, nTab, HasAttrFlags::Merged | HasAttrFlags::Overlapped ))
1033  {
1034  if (!bApi)
1035  rDocShell.ErrorMessage(STR_MSSG_INSERTCELLS_0); // don't insert into merged
1036  return;
1037  }
1038 
1039  bool bOk = true;
1040  if (rParam.bReplace)
1041  {
1042  if (rDoc.TestRemoveSubTotals( nTab, rParam ))
1043  {
1044  std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(ScDocShell::GetActiveDialogParent(),
1045  VclMessageType::Question,
1046  VclButtonsType::YesNo, ScResId(STR_MSSG_DOSUBTOTALS_1))); // "Delete Data?"
1047  xBox->set_title(ScResId(STR_MSSG_DOSUBTOTALS_0)); // "StarCalc"
1048  bOk = xBox->run() == RET_YES;
1049  }
1050  }
1051 
1052  if (!bOk)
1053  return;
1054 
1056  ScDocShellModificator aModificator( rDocShell );
1057 
1058  ScSubTotalParam aNewParam( rParam ); // end of range is being changed
1059  ScDocumentUniquePtr pUndoDoc;
1060  std::unique_ptr<ScOutlineTable> pUndoTab;
1061  std::unique_ptr<ScRangeName> pUndoRange;
1062  std::unique_ptr<ScDBCollection> pUndoDB;
1063 
1064  if (bRecord) // secure old data
1065  {
1066  bool bOldFilter = bDo && rParam.bDoSort;
1067 
1068  SCTAB nTabCount = rDoc.GetTableCount();
1069  pUndoDoc.reset(new ScDocument( SCDOCMODE_UNDO ));
1070  ScOutlineTable* pTable = rDoc.GetOutlineTable( nTab );
1071  if (pTable)
1072  {
1073  pUndoTab.reset(new ScOutlineTable( *pTable ));
1074 
1075  // column/row state
1076  SCCOLROW nOutStartCol, nOutEndCol;
1077  SCCOLROW nOutStartRow, nOutEndRow;
1078  pTable->GetColArray().GetRange( nOutStartCol, nOutEndCol );
1079  pTable->GetRowArray().GetRange( nOutStartRow, nOutEndRow );
1080 
1081  pUndoDoc->InitUndo( rDoc, nTab, nTab, true, true );
1082  rDoc.CopyToDocument(static_cast<SCCOL>(nOutStartCol), 0, nTab, static_cast<SCCOL>(nOutEndCol), rDoc.MaxRow(), nTab, InsertDeleteFlags::NONE, false, *pUndoDoc);
1083  rDoc.CopyToDocument(0, nOutStartRow, nTab, rDoc.MaxCol(), nOutEndRow, nTab, InsertDeleteFlags::NONE, false, *pUndoDoc);
1084  }
1085  else
1086  pUndoDoc->InitUndo( rDoc, nTab, nTab, false, bOldFilter );
1087 
1088  // secure data range - incl. filtering result
1089  rDoc.CopyToDocument(0, rParam.nRow1+1,nTab, rDoc.MaxCol(),rParam.nRow2,nTab,
1090  InsertDeleteFlags::ALL, false, *pUndoDoc);
1091 
1092  // all formulas because of references
1093  rDoc.CopyToDocument(0, 0, 0, rDoc.MaxCol(),rDoc.MaxRow(),nTabCount-1,
1094  InsertDeleteFlags::FORMULA, false, *pUndoDoc);
1095 
1096  // ranges of DB and other
1097  ScRangeName* pDocRange = rDoc.GetRangeName();
1098  if (!pDocRange->empty())
1099  pUndoRange.reset(new ScRangeName( *pDocRange ));
1100  ScDBCollection* pDocDB = rDoc.GetDBCollection();
1101  if (!pDocDB->empty())
1102  pUndoDB.reset(new ScDBCollection( *pDocDB ));
1103  }
1104 
1105 // rDoc.SetOutlineTable( nTab, NULL );
1106  ScOutlineTable* pOut = rDoc.GetOutlineTable( nTab );
1107  if (pOut)
1108  pOut->GetRowArray().RemoveAll(); // only delete row outlines
1109 
1110  if (rParam.bReplace)
1111  rDoc.RemoveSubTotals( nTab, aNewParam );
1112  bool bSuccess = true;
1113  if (bDo)
1114  {
1115  // sort
1116  if ( rParam.bDoSort )
1117  {
1118  pDBData->SetArea( nTab, aNewParam.nCol1,aNewParam.nRow1, aNewParam.nCol2,aNewParam.nRow2 );
1119 
1120  // set partial result field to before the sorting
1121  // (Duplicates are omitted, so can be called again)
1122 
1123  ScSortParam aOldSort;
1124  pDBData->GetSortParam( aOldSort );
1125  ScSortParam aSortParam( aNewParam, aOldSort );
1126  Sort( nTab, aSortParam, false, false, bApi );
1127  }
1128 
1129  bSuccess = rDoc.DoSubTotals( nTab, aNewParam );
1130  rDoc.SetDrawPageSize(nTab);
1131  }
1132  ScRange aDirtyRange( aNewParam.nCol1, aNewParam.nRow1, nTab,
1133  aNewParam.nCol2, aNewParam.nRow2, nTab );
1134  rDoc.SetDirty( aDirtyRange, true );
1135 
1136  if (bRecord)
1137  {
1138 // ScDBData* pUndoDBData = pDBData ? new ScDBData( *pDBData ) : NULL;
1140  std::make_unique<ScUndoSubTotals>( &rDocShell, nTab,
1141  rParam, aNewParam.nRow2,
1142  std::move(pUndoDoc), std::move(pUndoTab), // pUndoDBData,
1143  std::move(pUndoRange), std::move(pUndoDB) ) );
1144  }
1145 
1146  if (!bSuccess)
1147  {
1148  // "Cannot insert rows"
1149  if (!bApi)
1150  rDocShell.ErrorMessage(STR_MSSG_DOSUBTOTALS_2);
1151  }
1152 
1153  // memorize
1154  pDBData->SetSubTotalParam( aNewParam );
1155  pDBData->SetArea( nTab, aNewParam.nCol1,aNewParam.nRow1, aNewParam.nCol2,aNewParam.nRow2 );
1156  rDoc.CompileDBFormula();
1157 
1158  rDocShell.PostPaint(ScRange(0, 0, nTab, rDoc.MaxCol(),rDoc.MaxRow(),nTab),
1160  aModificator.SetDocumentModified();
1161 }
1162 
1163 namespace {
1164 
1165 bool lcl_EmptyExcept( ScDocument& rDoc, const ScRange& rRange, const ScRange& rExcept )
1166 {
1167  ScCellIterator aIter( rDoc, rRange );
1168  for (bool bHasCell = aIter.first(); bHasCell; bHasCell = aIter.next())
1169  {
1170  if (!aIter.isEmpty()) // real content?
1171  {
1172  if (!rExcept.In(aIter.GetPos()))
1173  return false; // cell found
1174  }
1175  }
1176 
1177  return true; // nothing found - empty
1178 }
1179 
1180 bool isEditable(ScDocShell& rDocShell, const ScRangeList& rRanges, bool bApi)
1181 {
1182  ScDocument& rDoc = rDocShell.GetDocument();
1183  if (!rDocShell.IsEditable() || rDoc.GetChangeTrack())
1184  {
1185  // not recorded -> disallow
1186  if (!bApi)
1187  rDocShell.ErrorMessage(STR_PROTECTIONERR);
1188 
1189  return false;
1190  }
1191 
1192  for (size_t i = 0, n = rRanges.size(); i < n; ++i)
1193  {
1194  const ScRange & r = rRanges[i];
1195  ScEditableTester aTester(rDoc, r);
1196  if (!aTester.IsEditable())
1197  {
1198  if (!bApi)
1199  rDocShell.ErrorMessage(aTester.GetMessageId());
1200 
1201  return false;
1202  }
1203  }
1204 
1205  return true;
1206 }
1207 
1208 void createUndoDoc(ScDocumentUniquePtr& pUndoDoc, ScDocument& rDoc, const ScRange& rRange)
1209 {
1210  SCTAB nTab = rRange.aStart.Tab();
1211  pUndoDoc.reset(new ScDocument(SCDOCMODE_UNDO));
1212  pUndoDoc->InitUndo(rDoc, nTab, nTab);
1213  rDoc.CopyToDocument(rRange, InsertDeleteFlags::ALL, false, *pUndoDoc);
1214 }
1215 
1216 bool checkNewOutputRange(ScDPObject& rDPObj, ScDocShell& rDocShell, ScRange& rNewOut, bool bApi)
1217 {
1218  ScDocument& rDoc = rDocShell.GetDocument();
1219 
1220  bool bOverflow = false;
1221  rNewOut = rDPObj.GetNewOutputRange(bOverflow);
1222 
1223  // Test for overlap with source data range.
1224  // TODO: Check with other pivot tables as well.
1225  const ScSheetSourceDesc* pSheetDesc = rDPObj.GetSheetDesc();
1226  if (pSheetDesc && pSheetDesc->GetSourceRange().Intersects(rNewOut))
1227  {
1228  // New output range intersteps with the source data. Move it up to
1229  // where the old range is and see if that works.
1230  ScRange aOldRange = rDPObj.GetOutRange();
1231  SCROW nDiff = aOldRange.aStart.Row() - rNewOut.aStart.Row();
1232  rNewOut.aStart.SetRow(aOldRange.aStart.Row());
1233  rNewOut.aEnd.IncRow(nDiff);
1234  if (!rDoc.ValidRow(rNewOut.aStart.Row()) || !rDoc.ValidRow(rNewOut.aEnd.Row()))
1235  bOverflow = true;
1236  }
1237 
1238  if (bOverflow)
1239  {
1240  if (!bApi)
1241  rDocShell.ErrorMessage(STR_PIVOT_ERROR);
1242 
1243  return false;
1244  }
1245 
1246  ScEditableTester aTester(rDoc, rNewOut);
1247  if (!aTester.IsEditable())
1248  {
1249  // destination area isn't editable
1250  if (!bApi)
1251  rDocShell.ErrorMessage(aTester.GetMessageId());
1252 
1253  return false;
1254  }
1255 
1256  return true;
1257 }
1258 
1259 }
1260 
1261 bool ScDBDocFunc::DataPilotUpdate( ScDPObject* pOldObj, const ScDPObject* pNewObj,
1262  bool bRecord, bool bApi, bool bAllowMove )
1263 {
1264  if (!pOldObj)
1265  {
1266  if (!pNewObj)
1267  return false;
1268 
1269  return CreatePivotTable(*pNewObj, bRecord, bApi);
1270  }
1271 
1272  if (!pNewObj)
1273  return RemovePivotTable(*pOldObj, bRecord, bApi);
1274 
1275  if (pOldObj == pNewObj)
1276  return UpdatePivotTable(*pOldObj, bRecord, bApi);
1277 
1278  OSL_ASSERT(pOldObj && pNewObj && pOldObj != pNewObj);
1279 
1280  ScDocShellModificator aModificator( rDocShell );
1282 
1283  ScRangeList aRanges;
1284  aRanges.push_back(pOldObj->GetOutRange());
1285  aRanges.push_back(pNewObj->GetOutRange().aStart); // at least one cell in the output position must be editable.
1286  if (!isEditable(rDocShell, aRanges, bApi))
1287  return false;
1288 
1289  ScDocumentUniquePtr pOldUndoDoc;
1290  ScDocumentUniquePtr pNewUndoDoc;
1291 
1292  ScDPObject aUndoDPObj(*pOldObj); // for undo or revert on failure
1293 
1294  ScDocument& rDoc = rDocShell.GetDocument();
1295  if (bRecord && !rDoc.IsUndoEnabled())
1296  bRecord = false;
1297 
1298  if (bRecord)
1299  createUndoDoc(pOldUndoDoc, rDoc, pOldObj->GetOutRange());
1300 
1301  pNewObj->WriteSourceDataTo(*pOldObj); // copy source data
1302 
1303  ScDPSaveData* pData = pNewObj->GetSaveData();
1304  OSL_ENSURE( pData, "no SaveData from living DPObject" );
1305  if (pData)
1306  pOldObj->SetSaveData(*pData); // copy SaveData
1307 
1308  pOldObj->SetAllowMove(bAllowMove);
1309  pOldObj->ReloadGroupTableData();
1310  pOldObj->SyncAllDimensionMembers();
1311  pOldObj->InvalidateData(); // before getting the new output area
1312 
1313  // make sure the table has a name (not set by dialog)
1314  if (pOldObj->GetName().isEmpty())
1315  pOldObj->SetName( rDoc.GetDPCollection()->CreateNewName() );
1316 
1317  ScRange aNewOut;
1318  if (!checkNewOutputRange(*pOldObj, rDocShell, aNewOut, bApi))
1319  {
1320  *pOldObj = aUndoDPObj;
1321  return false;
1322  }
1323 
1324  // test if new output area is empty except for old area
1325  if (!bApi)
1326  {
1327  // OutRange of pOldObj (pDestObj) is still old area
1328  if (!lcl_EmptyExcept(rDoc, aNewOut, pOldObj->GetOutRange()))
1329  {
1330  std::unique_ptr<weld::MessageDialog> xQueryBox(Application::CreateMessageDialog(ScDocShell::GetActiveDialogParent(),
1331  VclMessageType::Question, VclButtonsType::YesNo,
1332  ScResId(STR_PIVOT_NOTEMPTY)));
1333  xQueryBox->set_default_response(RET_YES);
1334  if (xQueryBox->run() == RET_NO)
1335  {
1337  *pOldObj = aUndoDPObj;
1338  return false;
1339  }
1340  }
1341  }
1342 
1343  if (bRecord)
1344  createUndoDoc(pNewUndoDoc, rDoc, aNewOut);
1345 
1346  pOldObj->Output(aNewOut.aStart);
1347  rDocShell.PostPaintGridAll();
1348 
1349  if (bRecord)
1350  {
1351  rDocShell.GetUndoManager()->AddUndoAction(
1352  std::make_unique<ScUndoDataPilot>(
1353  &rDocShell, std::move(pOldUndoDoc), std::move(pNewUndoDoc), &aUndoDPObj, pOldObj, bAllowMove));
1354  }
1355 
1356  // notify API objects
1357  rDoc.BroadcastUno( ScDataPilotModifiedHint(pOldObj->GetName()) );
1358  aModificator.SetDocumentModified();
1359 
1360  return true;
1361 }
1362 
1363 bool ScDBDocFunc::RemovePivotTable(ScDPObject& rDPObj, bool bRecord, bool bApi)
1364 {
1365  ScDocShellModificator aModificator(rDocShell);
1367 
1368  if (!isEditable(rDocShell, rDPObj.GetOutRange(), bApi))
1369  return false;
1370 
1371  ScDocument& rDoc = rDocShell.GetDocument();
1372 
1373  if (!bApi)
1374  {
1375  // If we come from GUI - ask to delete the associated pivot charts too...
1376  std::vector<SdrOle2Obj*> aListOfObjects =
1378 
1379  ScDrawLayer* pModel = rDoc.GetDrawLayer();
1380 
1381  if (pModel && !aListOfObjects.empty())
1382  {
1383  std::unique_ptr<weld::MessageDialog> xQueryBox(Application::CreateMessageDialog(ScDocShell::GetActiveDialogParent(),
1384  VclMessageType::Question, VclButtonsType::YesNo,
1385  ScResId(STR_PIVOT_REMOVE_PIVOTCHART)));
1386  xQueryBox->set_default_response(RET_YES);
1387  if (xQueryBox->run() == RET_NO)
1388  {
1389  return false;
1390  }
1391  else
1392  {
1393  for (SdrOle2Obj* pChartObject : aListOfObjects)
1394  {
1395  rDoc.GetChartListenerCollection()->removeByName(pChartObject->GetName());
1396  pModel->AddUndo(std::make_unique<SdrUndoDelObj>(*pChartObject));
1397  pChartObject->getSdrPageFromSdrObject()->RemoveObject(pChartObject->GetOrdNum());
1398  }
1399  }
1400  }
1401  }
1402 
1403  ScDocumentUniquePtr pOldUndoDoc;
1404  std::unique_ptr<ScDPObject> pUndoDPObj;
1405 
1406  if (bRecord)
1407  pUndoDPObj.reset(new ScDPObject(rDPObj)); // copy old settings for undo
1408 
1409  if (bRecord && !rDoc.IsUndoEnabled())
1410  bRecord = false;
1411 
1412  // delete table
1413 
1414  ScRange aRange = rDPObj.GetOutRange();
1415  SCTAB nTab = aRange.aStart.Tab();
1416 
1417  if (bRecord)
1418  createUndoDoc(pOldUndoDoc, rDoc, aRange);
1419 
1420  rDoc.DeleteAreaTab( aRange.aStart.Col(), aRange.aStart.Row(),
1421  aRange.aEnd.Col(), aRange.aEnd.Row(),
1422  nTab, InsertDeleteFlags::ALL );
1423  rDoc.RemoveFlagsTab( aRange.aStart.Col(), aRange.aStart.Row(),
1424  aRange.aEnd.Col(), aRange.aEnd.Row(),
1425  nTab, ScMF::Auto );
1426 
1427  rDoc.GetDPCollection()->FreeTable(&rDPObj); // object is deleted here
1428 
1429  rDocShell.PostPaintGridAll();
1430  rDocShell.PostPaint(aRange, PaintPartFlags::Grid);
1431 
1432  if (bRecord)
1433  {
1434  rDocShell.GetUndoManager()->AddUndoAction(
1435  std::make_unique<ScUndoDataPilot>(
1436  &rDocShell, std::move(pOldUndoDoc), nullptr, pUndoDPObj.get(), nullptr, false));
1437 
1438  // pUndoDPObj is copied
1439  }
1440 
1441  aModificator.SetDocumentModified();
1442  return true;
1443 }
1444 
1445 bool ScDBDocFunc::CreatePivotTable(const ScDPObject& rDPObj, bool bRecord, bool bApi)
1446 {
1447  ScDocShellModificator aModificator(rDocShell);
1449 
1450  // At least one cell in the output range should be editable. Check in advance.
1451  if (!isEditable(rDocShell, ScRange(rDPObj.GetOutRange().aStart), bApi))
1452  return false;
1453 
1454  ScDocumentUniquePtr pNewUndoDoc;
1455 
1456  ScDocument& rDoc = rDocShell.GetDocument();
1457  if (bRecord && !rDoc.IsUndoEnabled())
1458  bRecord = false;
1459 
1460  // output range must be set at pNewObj
1461  std::unique_ptr<ScDPObject> pDestObj(new ScDPObject(rDPObj));
1462 
1463  ScDPObject& rDestObj = *pDestObj;
1464 
1465  // #i94570# When changing the output position in the dialog, a new table is created
1466  // with the settings from the old table, including the name.
1467  // So we have to check for duplicate names here (before inserting).
1468  if (rDoc.GetDPCollection()->GetByName(rDestObj.GetName()))
1469  rDestObj.SetName(OUString()); // ignore the invalid name, create a new name below
1470 
1471  // Synchronize groups between linked tables
1472  {
1473  const ScDPDimensionSaveData* pGroups = nullptr;
1474  bool bRefFound = rDoc.GetDPCollection()->GetReferenceGroups(rDestObj, &pGroups);
1475  if (bRefFound)
1476  {
1477  ScDPSaveData* pSaveData = rDestObj.GetSaveData();
1478  if (pSaveData)
1479  pSaveData->SetDimensionData(pGroups);
1480  }
1481  }
1482 
1483  rDoc.GetDPCollection()->InsertNewTable(std::move(pDestObj));
1484 
1485  rDestObj.ReloadGroupTableData();
1486  rDestObj.SyncAllDimensionMembers();
1487  rDestObj.InvalidateData(); // before getting the new output area
1488 
1489  // make sure the table has a name (not set by dialog)
1490  if (rDestObj.GetName().isEmpty())
1491  rDestObj.SetName(rDoc.GetDPCollection()->CreateNewName());
1492 
1493  bool bOverflow = false;
1494  ScRange aNewOut = rDestObj.GetNewOutputRange(bOverflow);
1495 
1496  if (bOverflow)
1497  {
1498  if (!bApi)
1499  rDocShell.ErrorMessage(STR_PIVOT_ERROR);
1500 
1501  return false;
1502  }
1503 
1504  {
1505  ScEditableTester aTester(rDoc, aNewOut);
1506  if (!aTester.IsEditable())
1507  {
1508  // destination area isn't editable
1509  if (!bApi)
1510  rDocShell.ErrorMessage(aTester.GetMessageId());
1511 
1512  return false;
1513  }
1514  }
1515 
1516  // test if new output area is empty except for old area
1517  if (!bApi)
1518  {
1519  bool bEmpty = rDoc.IsBlockEmpty(
1520  aNewOut.aStart.Tab(), aNewOut.aStart.Col(), aNewOut.aStart.Row(),
1521  aNewOut.aEnd.Col(), aNewOut.aEnd.Row());
1522 
1523  if (!bEmpty)
1524  {
1525  std::unique_ptr<weld::MessageDialog> xQueryBox(Application::CreateMessageDialog(ScDocShell::GetActiveDialogParent(),
1526  VclMessageType::Question, VclButtonsType::YesNo,
1527  ScResId(STR_PIVOT_NOTEMPTY)));
1528  xQueryBox->set_default_response(RET_YES);
1529  if (xQueryBox->run() == RET_NO)
1530  {
1532  return false;
1533  }
1534  }
1535  }
1536 
1537  if (bRecord)
1538  createUndoDoc(pNewUndoDoc, rDoc, aNewOut);
1539 
1540  rDestObj.Output(aNewOut.aStart);
1541  rDocShell.PostPaintGridAll();
1542 
1543  if (bRecord)
1544  {
1545  rDocShell.GetUndoManager()->AddUndoAction(
1546  std::make_unique<ScUndoDataPilot>(&rDocShell, nullptr, std::move(pNewUndoDoc), nullptr, &rDestObj, false));
1547  }
1548 
1549  // notify API objects
1550  rDoc.BroadcastUno(ScDataPilotModifiedHint(rDestObj.GetName()));
1551  aModificator.SetDocumentModified();
1552 
1553  return true;
1554 }
1555 
1556 bool ScDBDocFunc::UpdatePivotTable(ScDPObject& rDPObj, bool bRecord, bool bApi)
1557 {
1558  ScDocShellModificator aModificator( rDocShell );
1560 
1561  if (!isEditable(rDocShell, rDPObj.GetOutRange(), bApi))
1562  return false;
1563 
1564  ScDocumentUniquePtr pOldUndoDoc;
1565  ScDocumentUniquePtr pNewUndoDoc;
1566 
1567  ScDPObject aUndoDPObj(rDPObj); // For undo or revert on failure.
1568 
1569  ScDocument& rDoc = rDocShell.GetDocument();
1570  if (bRecord && !rDoc.IsUndoEnabled())
1571  bRecord = false;
1572 
1573  if (bRecord)
1574  createUndoDoc(pOldUndoDoc, rDoc, rDPObj.GetOutRange());
1575 
1576  rDPObj.SetAllowMove(false);
1577  rDPObj.ReloadGroupTableData();
1578  if (!rDPObj.SyncAllDimensionMembers())
1579  return false;
1580 
1581  rDPObj.InvalidateData(); // before getting the new output area
1582 
1583  // make sure the table has a name (not set by dialog)
1584  if (rDPObj.GetName().isEmpty())
1585  rDPObj.SetName( rDoc.GetDPCollection()->CreateNewName() );
1586 
1587  ScRange aNewOut;
1588  if (!checkNewOutputRange(rDPObj, rDocShell, aNewOut, bApi))
1589  {
1590  rDPObj = aUndoDPObj;
1591  return false;
1592  }
1593 
1594  // test if new output area is empty except for old area
1595  if (!bApi)
1596  {
1597  if (!lcl_EmptyExcept(rDoc, aNewOut, rDPObj.GetOutRange()))
1598  {
1599  std::unique_ptr<weld::MessageDialog> xQueryBox(Application::CreateMessageDialog(ScDocShell::GetActiveDialogParent(),
1600  VclMessageType::Question, VclButtonsType::YesNo,
1601  ScResId(STR_PIVOT_NOTEMPTY)));
1602  xQueryBox->set_default_response(RET_YES);
1603  if (xQueryBox->run() == RET_NO)
1604  {
1605  rDPObj = aUndoDPObj;
1606  return false;
1607  }
1608  }
1609  }
1610 
1611  if (bRecord)
1612  createUndoDoc(pNewUndoDoc, rDoc, aNewOut);
1613 
1614  rDPObj.Output(aNewOut.aStart);
1615  rDocShell.PostPaintGridAll();
1616 
1617  if (bRecord)
1618  {
1619  rDocShell.GetUndoManager()->AddUndoAction(
1620  std::make_unique<ScUndoDataPilot>(
1621  &rDocShell, std::move(pOldUndoDoc), std::move(pNewUndoDoc), &aUndoDPObj, &rDPObj, false));
1622  }
1623 
1624  // notify API objects
1625  rDoc.BroadcastUno( ScDataPilotModifiedHint(rDPObj.GetName()) );
1626  aModificator.SetDocumentModified();
1627  return true;
1628 }
1629 
1630 void ScDBDocFunc::RefreshPivotTables(const ScDPObject* pDPObj, bool bApi)
1631 {
1632  ScDPCollection* pDPs = rDocShell.GetDocument().GetDPCollection();
1633  if (!pDPs)
1634  return;
1635 
1637  const char* pErrId = pDPs->ReloadCache(pDPObj, aRefs);
1638  if (pErrId)
1639  return;
1640 
1641  for (ScDPObject* pObj : aRefs)
1642  {
1643  // This action is intentionally not undoable since it modifies cache.
1644  UpdatePivotTable(*pObj, false, bApi);
1645  }
1646 }
1647 
1649 {
1650  if (!pDPObj)
1651  return;
1652 
1653  ScDPCollection* pDPs = rDocShell.GetDocument().GetDPCollection();
1654  if (!pDPs)
1655  return;
1656 
1657  ScDPSaveData* pSaveData = pDPObj->GetSaveData();
1658  if (!pSaveData)
1659  return;
1660 
1661  if (!pDPs->HasTable(pDPObj))
1662  {
1663  // This table is under construction so no need for a whole update (UpdatePivotTable()).
1664  pDPObj->ReloadGroupTableData();
1665  return;
1666  }
1667 
1668  // Update all linked tables, if this table is part of the cache (ScDPCollection)
1670  if (!pDPs->ReloadGroupsInCache(pDPObj, aRefs))
1671  return;
1672 
1673  // We allow pDimData being NULL.
1674  const ScDPDimensionSaveData* pDimData = pSaveData->GetExistingDimensionData();
1675  for (ScDPObject* pObj : aRefs)
1676  {
1677  if (pObj != pDPObj)
1678  {
1679  pSaveData = pObj->GetSaveData();
1680  if (pSaveData)
1681  pSaveData->SetDimensionData(pDimData);
1682  }
1683 
1684  // This action is intentionally not undoable since it modifies cache.
1685  UpdatePivotTable(*pObj, false, false);
1686  }
1687 }
1688 
1689 // database import
1690 
1691 void ScDBDocFunc::UpdateImport( const OUString& rTarget, const svx::ODataAccessDescriptor& rDescriptor )
1692 {
1693  // rTarget is the name of a database range
1694 
1695  ScDocument& rDoc = rDocShell.GetDocument();
1696  ScDBCollection& rDBColl = *rDoc.GetDBCollection();
1697  const ScDBData* pData = rDBColl.getNamedDBs().findByUpperName(ScGlobal::getCharClassPtr()->uppercase(rTarget));
1698  if (!pData)
1699  {
1700  std::unique_ptr<weld::MessageDialog> xInfoBox(Application::CreateMessageDialog(ScDocShell::GetActiveDialogParent(),
1701  VclMessageType::Info, VclButtonsType::Ok,
1702  ScResId(STR_TARGETNOTFOUND)));
1703  xInfoBox->run();
1704  return;
1705  }
1706 
1707  SCTAB nTab;
1708  SCCOL nDummyCol;
1709  SCROW nDummyRow;
1710  pData->GetArea( nTab, nDummyCol,nDummyRow,nDummyCol,nDummyRow );
1711 
1712  ScImportParam aImportParam;
1713  pData->GetImportParam( aImportParam );
1714 
1715  OUString sDBName;
1716  OUString sDBTable;
1717  sal_Int32 nCommandType = 0;
1718  sDBName = rDescriptor.getDataSource();
1719  rDescriptor[svx::DataAccessDescriptorProperty::Command] >>= sDBTable;
1720  rDescriptor[svx::DataAccessDescriptorProperty::CommandType] >>= nCommandType;
1721 
1722  aImportParam.aDBName = sDBName;
1723  aImportParam.bSql = ( nCommandType == sdb::CommandType::COMMAND );
1724  aImportParam.aStatement = sDBTable;
1725  aImportParam.bNative = false;
1726  aImportParam.nType = static_cast<sal_uInt8>( ( nCommandType == sdb::CommandType::QUERY ) ? ScDbQuery : ScDbTable );
1727  aImportParam.bImport = true;
1728 
1729  bool bContinue = DoImport( nTab, aImportParam, &rDescriptor );
1730 
1731  // repeat DB operations
1732 
1733  ScTabViewShell* pViewSh = rDocShell.GetBestViewShell();
1734  if (!pViewSh)
1735  return;
1736 
1737  ScRange aRange;
1738  pData->GetArea(aRange);
1739  pViewSh->MarkRange(aRange); // select
1740 
1741  if ( bContinue ) // error at import -> abort
1742  {
1743  // internal operations, if some are saved
1744 
1745  if ( pData->HasQueryParam() || pData->HasSortParam() || pData->HasSubTotalParam() )
1746  pViewSh->RepeatDB();
1747 
1748  // pivot tables which have the range as source data
1749 
1750  rDocShell.RefreshPivotTables(aRange);
1751  }
1752 }
1753 
1754 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
::std::vector< ScSortKeyState > maKeyState
Definition: sortparam.hxx:60
bool bGroupActive[MAXSUBTOTAL]
active groups
void BeginDrawUndo()
Definition: documen9.cxx:60
const ScDPDimensionSaveData * GetExistingDimensionData() const
Definition: dpsave.hxx:348
SCROW nRow1
Definition: sortparam.hxx:43
bool CanFitBlock(const ScRange &rOld, const ScRange &rNew)
Definition: document.cxx:1822
void UpdatePageBreaks(SCTAB nTab, const ScRange *pUserArea=nullptr)
Definition: document.cxx:6207
bool insert(std::unique_ptr< ScDBData > p)
Takes ownership of p and attempts to insert it into the collection.
Definition: dbdata.cxx:1160
SC_DLLPUBLIC void ApplyStyleAreaTab(SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow, SCTAB nTab, const ScStyleSheet &rStyle)
Definition: document.cxx:4842
void ReloadGroupTableData()
Definition: dpobject.cxx:809
void FitBlock(const ScRange &rOld, const ScRange &rNew, bool bClear=true)
Definition: document.cxx:1853
SC_DLLPUBLIC bool HasQueryParam() const
Definition: dbdata.cxx:509
SC_DLLPUBLIC ScDBCollection * GetDBCollection() const
Definition: document.hxx:813
ScAddress aStart
Definition: address.hxx:499
todo: It should be possible to have MarkArrays for each table, in order to enable "search all" across...
Definition: markdata.hxx:42
This class has to do with handling exclusively grouped dimensions? TODO: Find out what this class doe...
Definition: dpdimsave.hxx:163
SCCOL nCol2
Definition: sortparam.hxx:44
SCCOL nCol1
selected area
SC_DLLPUBLIC ScDBData * GetAnonymousDBData(SCTAB nTab)
Definition: document.cxx:306
SC_DLLPUBLIC void SetSortParam(const ScSortParam &rSortParam)
Definition: dbdata.cxx:398
SCROW Row() const
Definition: address.hxx:261
void PostPaintGridAll()
Definition: docsh3.cxx:182
bool AdjustRowHeight(SCROW nStartRow, SCROW nEndRow, SCTAB nTab)
merge with docfunc
Definition: docsh5.cxx:404
void WriteSourceDataTo(ScDPObject &rDest) const
Definition: dpobject.cxx:464
SCSIZE Query(SCTAB nTab, const ScQueryParam &rQueryParam, bool bKeepSub)
Definition: documen3.cxx:1462
OUString aDBName
Definition: global.hxx:455
std::unique_ptr< ContentProperties > pData
static weld::Window * GetActiveDialogParent()
Definition: docsh.cxx:2950
SCCOL nDestCol
Definition: sortparam.hxx:57
bool bIncludeComments
Definition: sortparam.hxx:51
SC_DLLPUBLIC void GetSortParam(ScSortParam &rSortParam) const
Definition: dbdata.cxx:386
SC_DLLPUBLIC void SetAnonymousDBData(SCTAB nTab, std::unique_ptr< ScDBData > pDBData)
Definition: document.cxx:318
void MarkRange(const ScRange &rRange, bool bSetCursor=true, bool bContinue=false)
Definition: tabview3.cxx:1685
SC_DLLPUBLIC void SetDrawPageSize(SCTAB nTab)
Definition: documen9.cxx:195
SC_DLLPUBLIC bool Intersects(const ScRange &rRange) const
Definition: address.cxx:1558
SC_DLLPUBLIC bool GetReferenceGroups(const ScDPObject &rDPObj, const ScDPDimensionSaveData **pGroups) const
Definition: dpobject.cxx:3522
sal_uIntPtr sal_uLong
SC_DLLPUBLIC void CompileHybridFormula()
Call this immediately after updating named ranges.
Definition: document10.cxx:315
#define STR_DB_LOCAL_NONAME
Definition: globalnames.hxx:12
void InvalidateData()
Definition: dpobject.cxx:784
SC_DLLPUBLIC ScRangeName * GetRangeName(SCTAB nTab) const
Definition: documen3.cxx:168
sal_Int64 n
SC_DLLPUBLIC ScDPCollection * GetDPCollection()
Definition: documen3.cxx:365
ViewShellDocId GetDocId() const override
bool DoImport(SCTAB nTab, const ScImportParam &rParam, const svx::ODataAccessDescriptor *pDescriptor)
Definition: dbdocimp.cxx:121
void RefreshPivotTables(const ScRange &rSource)
Definition: docsh5.cxx:472
void RemoveAll()
Definition: olinetab.cxx:716
SC_DLLPUBLIC const ScDBData * GetDBAtArea(SCTAB nTab, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2) const
Definition: documen3.cxx:338
void SetAllowMove(bool bSet)
Definition: dpobject.cxx:381
ScAddress aEnd
Definition: address.hxx:500
bool bDoSort
presort
bool GetSortRefUpdate() const
Definition: inputopt.hxx:59
bool HasSubTotalParam() const
Definition: dbdata.cxx:527
ScDBData * GetDBData(const ScRange &rMarked, ScGetDBMode eMode, ScGetDBSelection eSel)
Definition: docsh5.cxx:114
bool DoSubTotals(SCTAB nTab, ScSubTotalParam &rParam)
Definition: documen3.cxx:777
SC_DLLPUBLIC void Fill(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, ScProgress *pProgress, const ScMarkData &rMark, sal_uLong nFillCount, FillDir eFillDir=FILL_TO_BOTTOM, FillCmd eFillCmd=FILL_LINEAR, FillDateCmd eFillDateCmd=FILL_DAY, double nStepValue=1.0, double nMaxValue=1E307)
Definition: documen3.cxx:1153
SC_DLLPUBLIC bool HasAttrib(SCCOL nCol1, SCROW nRow1, SCTAB nTab1, SCCOL nCol2, SCROW nRow2, SCTAB nTab2, HasAttrFlags nMask) const
Definition: document.cxx:5165
ScDPObject * GetByName(std::u16string_view rName) const
Definition: dpobject.cxx:3691
bool has(const ScDBData *p) const
Definition: dbdata.cxx:1269
bool IsDoSize() const
Definition: dbdata.hxx:135
static void notifyAllViewsSheetGeomInvalidation(const SfxViewShell *pForViewShell, bool bColumns, bool bRows, bool bSizes, bool bHidden, bool bFiltered, bool bGroups, SCTAB nCurrentTabIndex)
Emits a LOK_CALLBACK_INVALIDATE_SHEET_GEOMETRY for all views whose current tab is equal to nCurrentTa...
Definition: tabvwshc.cxx:559
SfxApplication * SfxGetpApp()
Internal use only (d&d undo): do not delete caption objects of cell notes.
bool UpdatePivotTable(ScDPObject &rDPObj, bool bRecord, bool bApi)
Definition: dbdocfun.cxx:1556
void Sort(SCTAB nTab, const ScSortParam &rSortParam, bool bKeepQuery, bool bUpdateRefs, ScProgress *pProgress, sc::ReorderParam *pUndo)
Sort a range of data.
Definition: documen3.cxx:1426
virtual SfxUndoManager * GetUndoManager() override
Definition: docsh.cxx:2806
RET_NO
OUString CreateNewName() const
Create a new name that's not yet used by any existing data pilot objects.
Definition: dpobject.cxx:3702
SCROW nRow2
Definition: sortparam.hxx:45
RET_YES
bool RepeatDB(const OUString &rDBName, bool bApi, bool bIsUnnamed, SCTAB aTab=0)
Definition: dbdocfun.cxx:283
void RefreshPivotTables(const ScDPObject *pDPObj, bool bApi)
Reload the referenced pivot cache, and refresh all pivot tables that reference the cache...
Definition: dbdocfun.cxx:1630
const ScRange & GetOutRange() const
Definition: dpobject.cxx:409
SC_DLLPUBLIC SCROW MaxRow() const
Definition: document.hxx:871
size_t SCSIZE
size_t typedef to be able to find places where code was changed from USHORT to size_t and is used to ...
Definition: address.hxx:44
sal_Int32 SCCOLROW
a type capable of holding either SCCOL or SCROW
Definition: types.hxx:23
SC_DLLPUBLIC SCTAB GetTableCount() const
Definition: document.cxx:313
AnonDBs & getAnonDBs()
Definition: dbdata.hxx:317
bool empty() const
Definition: rangenam.cxx:802
int nCount
static SfxViewShell * GetNext(const SfxViewShell &rPrev, bool bOnlyVisible=true, const std::function< bool(const SfxViewShell *)> &isViewShell=nullptr)
SC_DLLPUBLIC SCSIZE GetEntryCount() const
Definition: queryparam.cxx:119
void CopyToDocument(SCCOL nCol1, SCROW nRow1, SCTAB nTab1, SCCOL nCol2, SCROW nRow2, SCTAB nTab2, InsertDeleteFlags nFlags, bool bMarked, ScDocument &rDestDoc, const ScMarkData *pMarks=nullptr, bool bColRowFlags=true)
Definition: document.cxx:2067
oslFileHandle & pOut
void push_back(const ScRange &rRange)
Definition: rangelst.cxx:1142
SC_DLLPUBLIC const ScQueryEntry & GetEntry(SCSIZE n) const
Definition: queryparam.cxx:124
void UpdateScriptTypes(const ScAddress &rPos, SCCOL nColSize, SCROW nRowSize)
Definition: document10.cxx:333
Walk through all cells in an area.
Definition: dociter.hxx:207
bool SyncAllDimensionMembers()
Remove in the save data entries for members that don't exist anymore.
Definition: dpobject.cxx:973
SCTAB Tab() const
Definition: address.hxx:270
SC_DLLPUBLIC void SetQueryParam(const ScQueryParam &rQueryParam)
Definition: dbdata.cxx:422
bool ReloadGroupsInCache(const ScDPObject *pDPObj, o3tl::sorted_vector< ScDPObject * > &rRefs)
Definition: dpobject.cxx:3434
void SetRow(SCROW nRowP)
Definition: address.hxx:274
SC_DLLPUBLIC const ScRange & GetSourceRange() const
Get the range that contains the source data.
Definition: dpshttab.cxx:229
bool DeleteDBRange(const OUString &rName)
Definition: dbdocfun.cxx:118
bool bIncludeGraphicObjects
Definition: sortparam.hxx:52
void Output(const ScAddress &rPos)
Definition: dpobject.cxx:887
void SetCol(SCCOL nColP)
Definition: address.hxx:278
ScViewData & GetViewData()
Definition: tabview.hxx:333
ScChangeTrack * GetChangeTrack() const
Definition: document.hxx:2392
void GetRange(SCCOLROW &rStart, SCCOLROW &rEnd) const
Definition: olinetab.cxx:569
create "untitled" (if necessary)
Definition: global.hxx:392
SCCOL nCol1
Definition: sortparam.hxx:42
void SetName(const OUString &rNew)
Definition: dpobject.cxx:489
void SetArea(SCTAB nTab, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2)
Definition: dbdata.cxx:322
const char * GetMessageId() const
Definition: editable.cxx:152
void CalcSaveFilteredCount(SCSIZE nNonFilteredRowCount)
Definition: dbdata.cxx:926
OUString aStatement
Definition: global.hxx:456
SC_DLLPUBLIC ScDrawLayer * GetDrawLayer()
Definition: document.hxx:1057
SC_DLLPUBLIC SCCOL MaxCol() const
Definition: document.hxx:870
void RepeatDB(bool bRecord=true)
Definition: dbfunc3.cxx:2114
bool ShrinkToUsedDataArea(bool &o_bShrunk, SCTAB nTab, SCCOL &rStartCol, SCROW &rStartRow, SCCOL &rEndCol, SCROW &rEndRow, bool bColumnsOnly, bool bStickyTopRow=false, bool bStickyLeftCol=false, bool bConsiderCellNotes=false, bool bConsiderCellDrawObjects=false) const
Shrink a range to only include used data area.
Definition: document.cxx:1062
virtual void AddUndoAction(std::unique_ptr< SfxUndoAction > pAction, bool bTryMerg=false)
void InvalidatePageBreaks(SCTAB nTab)
Definition: document.cxx:6201
void SetDBCollection(std::unique_ptr< ScDBCollection > pNewDBCollection, bool bRemoveAutoFilter=false)
Definition: documen3.cxx:275
bool IsImportingXML() const
Definition: document.hxx:2137
void DBAreaDeleted(SCTAB nTab, SCCOL nX1, SCROW nY1, SCCOL nX2)
Definition: docsh5.cxx:103
SC_DLLPUBLIC void SetDimensionData(const ScDPDimensionSaveData *pNew)
Definition: dpsave.cxx:1202
int i
bool HasUniformRowHeight(SCTAB nTab, SCROW nRow1, SCROW nRow2) const
Definition: document10.cxx:342
void UpdateFromSortParam(const ScSortParam &rSortParam)
Remember some more settings of ScSortParam, only to be called at anonymous DB ranges as it at least o...
Definition: dbdata.cxx:404
bool empty() const
Definition: dbdata.cxx:1497
bool RenameDBRange(const OUString &rOld, const OUString &rNew)
Definition: dbdocfun.cxx:154
void invalidateByIndex(index_type nIndex)
Definition: viewdata.cxx:158
std::unique_ptr< ScDocument, o3tl::default_delete< ScDocument > > ScDocumentUniquePtr
Definition: document.hxx:2613
const ScOutlineArray & GetRowArray() const
Definition: olinetab.hxx:160
sal_Int16 SCCOL
Definition: types.hxx:21
const ScOutlineArray & GetColArray() const
Definition: olinetab.hxx:158
bool DataPilotUpdate(ScDPObject *pOldObj, const ScDPObject *pNewObj, bool bRecord, bool bApi, bool bAllowMove=false)
Definition: dbdocfun.cxx:1261
void OnLOKShowHideColRow(bool bColumns, SCCOLROW nStartRow)
Definition: dbfunc3.cxx:2279
#define SC_MOD()
Definition: scmod.hxx:249
bool HasSortParam() const
Definition: dbdata.cxx:520
void SetSaveData(const ScDPSaveData &rData)
Definition: dpobject.cxx:386
SC_DLLPUBLIC void SetAdvancedQuerySource(const ScRange *pSource)
Definition: dbdata.cxx:431
ScSheetLimits & GetSheetLimits() const
Definition: document.hxx:872
const ScStyleSheet * GetStyleSheet() const
Definition: patattr.hxx:126
const OUString & GetName() const
Definition: dpobject.hxx:166
size_t size() const
Definition: rangelst.hxx:89
bool bNative
Definition: global.hxx:457
void IncRow(SCROW nDelta=1)
Definition: address.hxx:299
void SelectOneTable(SCTAB nTab)
Definition: markdata.cxx:189
OUString ScResId(const char *pId)
Definition: scdll.cxx:89
const OUString & GetName() const
Definition: dbdata.hxx:121
void GetImportParam(ScImportParam &rImportParam) const
Definition: dbdata.cxx:465
bool IsKeepFmt() const
Definition: dbdata.hxx:137
SC_DLLPUBLIC void ApplyPatternAreaTab(SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow, SCTAB nTab, const ScPatternAttr &rAttr)
Definition: document.cxx:4777
void removeByName(const OUString &rName)
Definition: chartlis.cxx:395
ScDPSaveData * GetSaveData() const
Definition: dpobject.hxx:140
void BroadcastUno(const SfxHint &rHint)
Definition: documen3.cxx:949
SC_DLLPUBLIC ScDPObject * InsertNewTable(std::unique_ptr< ScDPObject > pDPObj)
Definition: dpobject.cxx:3730
void SetSubTotalCellsDirty(const ScRange &rDirtyRange)
Definition: document.cxx:6410
bool IsEditable() const
Definition: editable.hxx:83
bool IsBlockEmpty(SCTAB nTab, SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow, bool bIgnoreNotes=false) const
Definition: document.cxx:5282
bool IsEditable() const
Definition: docsh5.cxx:95
bool In(const ScAddress &) const
is Address& in Range?
Definition: address.hxx:732
const SCTAB MAXTAB
Definition: address.hxx:70
static SfxViewShell * GetFirst(bool bOnlyVisible=true, const std::function< bool(const SfxViewShell *)> &isViewShell=nullptr)
void PostPaint(SCCOL nStartCol, SCROW nStartRow, SCTAB nStartTab, SCCOL nEndCol, SCROW nEndRow, SCTAB nEndTab, PaintPartFlags nPart, sal_uInt16 nExtFlags=0)
Definition: docsh3.cxx:100
void GetArea(SCTAB &rTab, SCCOL &rCol1, SCROW &rRow1, SCCOL &rCol2, SCROW &rRow2) const
Definition: dbdata.cxx:300
void SetHeader(bool bHasH)
Definition: dbdata.hxx:130
void CompileDBFormula()
Definition: documen4.cxx:557
SCCOL Col() const
Definition: address.hxx:266
void GetSubTotalParam(ScSubTotalParam &rSubTotalParam) const
Definition: dbdata.cxx:448
const char * ReloadCache(const ScDPObject *pDPObj, o3tl::sorted_vector< ScDPObject * > &rRefs)
Definition: dpobject.cxx:3370
ScDBData * findByUpperName(const OUString &rName)
Definition: dbdata.cxx:1147
void RemoveSubTotals(SCTAB nTab, ScSubTotalParam &rParam)
Definition: documen3.cxx:771
SC_DLLPUBLIC bool Query(SCTAB nTab, const ScQueryParam &rQueryParam, const ScRange *pAdvSource, bool bRecord, bool bApi)
Definition: dbdocfun.cxx:646
top left cell of area
OUString getDataSource() const
ScDocShell & rDocShell
Definition: dbdocfun.hxx:48
bool bReplace
replace existing results
bool ValidColRow(SCCOL nCol, SCROW nRow) const
Definition: document.hxx:875
std::vector< SdrOle2Obj * > getAllPivotChartsConnectedTo(std::u16string_view sPivotTableName, ScDocShell *pDocShell)
Definition: ChartTools.cxx:142
Stores global named database ranges.
Definition: dbdata.hxx:234
Behave as if the range corresponding to a ScDBData area was selected, for API use.
sal_Int32 SCROW
Definition: types.hxx:17
bool RemovePivotTable(ScDPObject &rDPObj, bool bRecord, bool bApi)
Definition: dbdocfun.cxx:1363
void erase(const iterator &itr)
Definition: dbdata.cxx:1183
SC_DLLPUBLIC bool Sort(SCTAB nTab, const ScSortParam &rSortParam, bool bRecord, bool bPaint, bool bApi)
Definition: dbdocfun.cxx:466
void SetDirty(const ScRange &, bool bIncludeEmptyCells)
Definition: document.cxx:3848
bool ValidRow(SCROW nRow) const
Definition: document.hxx:874
bool bInplace
Definition: sortparam.hxx:55
void DoSubTotals(SCTAB nTab, const ScSubTotalParam &rParam, bool bRecord, bool bApi)
Definition: dbdocfun.cxx:1002
bool bHasHeader
Definition: sortparam.hxx:47
SC_DLLPUBLIC bool HasTable(const ScDPObject *pDPObj) const
Definition: dpobject.cxx:3741
sal_uInt8 nType
Definition: global.hxx:459
const OUString & GetUpperName() const
Definition: dbdata.hxx:122
unsigned char sal_uInt8
void ErrorMessage(const char *pGlobStrId)
Definition: docsh5.cxx:70
sal_uInt16 GetSortKeyCount() const
Definition: sortparam.hxx:78
SC_DLLPUBLIC bool RemoveFlagsTab(SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow, SCTAB nTab, ScMF nFlags)
Definition: document.cxx:5009
void ModifyAllDBData(const ScDBCollection &rNewColl, const std::vector< ScRange > &rDelAreaList)
Definition: dbdocfun.cxx:245
const ScSheetSourceDesc * GetSheetDesc() const
Definition: dpobject.hxx:155
SC_DLLPUBLIC ScOutlineTable * GetOutlineTable(SCTAB nTab, bool bCreate=false)
Definition: documen3.cxx:736
static SC_DLLPUBLIC const CharClass * getCharClassPtr()
Definition: global.cxx:1009
SC_DLLPUBLIC ScChartListenerCollection * GetChartListenerCollection() const
Definition: document.hxx:2143
const ScDocument & GetDocument() const
Definition: docsh.hxx:216
SC_DLLPUBLIC void PreprocessDBDataUpdate()
Definition: document10.cxx:303
SC_DLLPUBLIC void GetQueryParam(ScQueryParam &rQueryParam) const
Definition: dbdata.cxx:409
bool TestRemoveSubTotals(SCTAB nTab, const ScSubTotalParam &rParam)
Definition: documen3.cxx:766
bool bImport
Definition: global.hxx:454
SC_DLLPUBLIC bool HasHiddenRows(SCROW nStartRow, SCROW nEndRow, SCTAB nTab) const
Definition: document.cxx:4428
NamedDBs & getNamedDBs()
Definition: dbdata.hxx:314
static bool isAnyEditViewInRange(const SfxViewShell *pForViewShell, bool bColumns, SCCOLROW nStart, SCCOLROW nEnd)
Definition: tabvwshc.cxx:534
void MoveToDest()
Definition: sortparam.cxx:225
iterator findByUpperName2(const OUString &rName)
Definition: dbdata.cxx:1154
void SetDocumentModified()
Definition: docsh.cxx:3159
void UpdateImport(const OUString &rTarget, const svx::ODataAccessDescriptor &rDescriptor)
Definition: dbdocfun.cxx:1691
void MoveToDest()
Definition: queryparam.cxx:398
void SetSubTotalParam(const ScSubTotalParam &rSubTotalParam)
Definition: dbdata.cxx:460
SfxObjectShell * GetDocumentShell() const
Definition: document.hxx:1056
void ModifyDBData(const ScDBData &rNewData)
Definition: dbdocfun.cxx:201
SC_DLLPUBLIC bool GetAdvancedQuerySource(ScRange &rSource) const
Definition: dbdata.cxx:442
SCROW nDestRow
Definition: sortparam.hxx:58
bool IsUndoEnabled() const
Definition: document.hxx:1530
ScDocFunc & GetDocFunc()
Definition: docsh.hxx:218
ScTabViewShell * GetBestViewShell(bool bOnlyVisible=true)
Definition: docsh4.cxx:2565
bool MoveBlock(const ScRange &rSource, const ScAddress &rDestPos, bool bCut, bool bRecord, bool bPaint, bool bApi)
Definition: docfunc.cxx:2845
ScPositionHelper & GetLOKHeightHelper()
Definition: viewdata.hxx:410
const ScDBData * GetDBAtCursor(SCCOL nCol, SCROW nRow, SCTAB nTab, ScDBDataPortion ePortion) const
Definition: documen3.cxx:322
bool bIncludePattern
Definition: sortparam.hxx:54
PaintPartFlags
Definition: global.hxx:118
void RefreshPivotTableGroups(ScDPObject *pDPObj)
Refresh the group dimensions of all pivot tables referencing the same cache.
Definition: dbdocfun.cxx:1648
SC_DLLPUBLIC void DeleteAreaTab(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, SCTAB nTab, InsertDeleteFlags nDelFlag)
Definition: document.cxx:1946
bool AddDBRange(const OUString &rName, const ScRange &rRange)
Definition: dbdocfun.cxx:65
ScRange GetNewOutputRange(bool &rOverflow)
Definition: dpobject.cxx:873
This class contains authoritative information on the internal reference used as the data source for d...
Definition: dpshttab.hxx:38
static weld::MessageDialog * CreateMessageDialog(weld::Widget *pParent, VclMessageType eMessageType, VclButtonsType eButtonType, const OUString &rPrimaryMessage, bool bMobile=false)
Create before modifications of the document and destroy thereafter.
Definition: docsh.hxx:451
SC_DLLPUBLIC void GetCellType(SCCOL nCol, SCROW nRow, SCTAB nTab, CellType &rCellType) const
Definition: document.cxx:3738
sal_Int16 SCTAB
Definition: types.hxx:22
void FreeTable(const ScDPObject *pDPObj)
Definition: dpobject.cxx:3715
bool CreatePivotTable(const ScDPObject &rDPObj, bool bRecord, bool bApi)
Definition: dbdocfun.cxx:1445
SCTAB nDestTab
Definition: sortparam.hxx:56
typedef void(CALLTYPE *GetFuncDataPtr)(sal_uInt16 &nNo