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,
531  !aLocalParam.bByRow, aLocalParam.bIncludeComments,
532  aLocalParam.bIncludeGraphicObjects, aLocalParam.bIncludePattern);
533 
534  SCROW nStartRow = aLocalParam.nRow1;
535  if (aLocalParam.bByRow && aLocalParam.bHasHeader && nStartRow < aLocalParam.nRow2)
536  ++nStartRow;
537 
538  if ( aLocalParam.bIncludePattern && rDoc.HasAttrib(
539  aLocalParam.nCol1, nStartRow , nTab,
540  aLocalParam.nCol2, aLocalParam.nRow2, nTab,
542  {
543  // merge attributes would be mixed up during sorting
544  if (!bApi)
545  rDocShell.ErrorMessage(STR_SORT_ERR_MERGED);
546  return false;
547  }
548 
549  // execute
550 
552 
553  // Calculate the script types for all cells in the sort range beforehand.
554  // This will speed up the row height adjustment that takes place after the
555  // sort.
556  rDoc.UpdateScriptTypes(
557  ScAddress(aLocalParam.nCol1,nStartRow,nTab),
558  aLocalParam.nCol2-aLocalParam.nCol1+1,
559  aLocalParam.nRow2-nStartRow+1);
560 
561  // No point adjusting row heights after the sort when all rows have the same height.
562  bool bUniformRowHeight =
563  rDoc.HasUniformRowHeight(nTab, nStartRow, aLocalParam.nRow2);
564 
565  bool bRepeatQuery = false; // repeat existing filter?
566  ScQueryParam aQueryParam;
567  pDBData->GetQueryParam( aQueryParam );
568  if ( aQueryParam.GetEntry(0).bDoQuery )
569  bRepeatQuery = true;
570 
571  sc::ReorderParam aUndoParam;
572 
573  // don't call ScDocument::Sort with an empty SortParam (may be empty here if bCopy is set)
574  if (aLocalParam.GetSortKeyCount() && aLocalParam.maKeyState[0].bDoSort)
575  {
576  ScInputOptions aInputOption = SC_MOD()->GetInputOptions();
577  bool bUpdateRefs = aInputOption.GetSortRefUpdate();
578  ScProgress aProgress(&rDocShell, ScResId(STR_PROGRESS_SORTING), 0, true);
579  if (!bRepeatQuery)
580  bRepeatQuery = rDoc.HasHiddenRows(aLocalParam.nRow1, aLocalParam.nRow2, nTab);
581  rDoc.Sort(nTab, aLocalParam, bRepeatQuery, bUpdateRefs, &aProgress, &aUndoParam);
582  }
583 
584  if (bRecord)
585  {
586  // Set up an undo object.
588  std::make_unique<sc::UndoSort>(&rDocShell, aUndoParam));
589  }
590 
591  pDBData->SetSortParam(rSortParam);
592  // Remember additional settings on anonymous database ranges.
593  if (pDBData == rDoc.GetAnonymousDBData( nTab) || rDoc.GetDBCollection()->getAnonDBs().has( pDBData))
594  pDBData->UpdateFromSortParam( rSortParam);
595 
597  {
598  SfxViewShell* pSomeViewForThisDoc = rDocShell.GetBestViewShell(false);
599  SfxViewShell* pViewShell = SfxViewShell::GetFirst();
600  while (pViewShell)
601  {
602  ScTabViewShell* pTabViewShell = dynamic_cast<ScTabViewShell*>(pViewShell);
603  if (pTabViewShell && pTabViewShell->GetDocId() == pSomeViewForThisDoc->GetDocId())
604  {
605  pTabViewShell->GetViewData().GetLOKHeightHelper(nTab)->invalidateByIndex(nStartRow);
606  }
607  pViewShell = SfxViewShell::GetNext(*pViewShell);
608  }
609 
611  pSomeViewForThisDoc, false /* bColumns */, true /* bRows */, true /* bSizes*/,
612  true /* bHidden */, true /* bFiltered */, true /* bGroups */, nTab);
613  }
614 
615  if (nStartRow <= aLocalParam.nRow2)
616  {
617  ScRange aDirtyRange(
618  aLocalParam.nCol1, nStartRow, nTab,
619  aLocalParam.nCol2, aLocalParam.nRow2, nTab);
620  rDoc.SetDirty( aDirtyRange, true );
621  }
622 
623  if (bPaint)
624  {
626  SCCOL nStartX = aLocalParam.nCol1;
627  SCROW nStartY = aLocalParam.nRow1;
628  SCCOL nEndX = aLocalParam.nCol2;
629  SCROW nEndY = aLocalParam.nRow2;
630  if ( bRepeatQuery )
631  {
632  nPaint |= PaintPartFlags::Left;
633  nStartX = 0;
634  nEndX = rDoc.MaxCol();
635  }
636  rDocShell.PostPaint(ScRange(nStartX, nStartY, nTab, nEndX, nEndY, nTab), nPaint);
637  }
638 
639  if (!bUniformRowHeight && nStartRow <= aLocalParam.nRow2)
640  rDocShell.AdjustRowHeight(nStartRow, aLocalParam.nRow2, nTab);
641 
642  aModificator.SetDocumentModified();
643 
644  return true;
645 }
646 
647 bool ScDBDocFunc::Query( SCTAB nTab, const ScQueryParam& rQueryParam,
648  const ScRange* pAdvSource, bool bRecord, bool bApi )
649 {
650  ScDocShellModificator aModificator( rDocShell );
651 
652  ScDocument& rDoc = rDocShell.GetDocument();
653 
655  if (pViewSh && ScTabViewShell::isAnyEditViewInRange(pViewSh, /*bColumns*/ false, rQueryParam.nRow1, rQueryParam.nRow2))
656  {
657  return false;
658  }
659 
660  if (bRecord && !rDoc.IsUndoEnabled())
661  bRecord = false;
662  ScDBData* pDBData = rDoc.GetDBAtArea( nTab, rQueryParam.nCol1, rQueryParam.nRow1,
663  rQueryParam.nCol2, rQueryParam.nRow2 );
664  if (!pDBData)
665  {
666  OSL_FAIL( "Query: no DBData" );
667  return false;
668  }
669 
670  // Change from Inplace to non-Inplace, only then cancel Inplace:
671  // (only if "Persistent" is selected in the dialog)
672 
673  if ( !rQueryParam.bInplace && pDBData->HasQueryParam() && rQueryParam.bDestPers )
674  {
675  ScQueryParam aOldQuery;
676  pDBData->GetQueryParam(aOldQuery);
677  if (aOldQuery.bInplace)
678  {
679  // cancel old filtering
680 
681  SCSIZE nEC = aOldQuery.GetEntryCount();
682  for (SCSIZE i=0; i<nEC; i++)
683  aOldQuery.GetEntry(i).bDoQuery = false;
684  aOldQuery.bDuplicate = true;
685  Query( nTab, aOldQuery, nullptr, bRecord, bApi );
686  }
687  }
688 
689  ScQueryParam aLocalParam( rQueryParam ); // for Paint / destination range
690  bool bCopy = !rQueryParam.bInplace; // copied in Table::Query
691  ScDBData* pDestData = nullptr; // range to be copied to
692  bool bDoSize = false; // adjust destination size (insert/delete)
693  SCCOL nFormulaCols = 0; // only at bDoSize
694  bool bKeepFmt = false;
695  ScRange aOldDest;
696  ScRange aDestTotal;
697  if ( bCopy && rQueryParam.nDestCol == rQueryParam.nCol1 &&
698  rQueryParam.nDestRow == rQueryParam.nRow1 && rQueryParam.nDestTab == nTab )
699  bCopy = false;
700  SCTAB nDestTab = nTab;
701  if ( bCopy )
702  {
703  aLocalParam.MoveToDest();
704  nDestTab = rQueryParam.nDestTab;
705  if ( !rDoc.ValidColRow( aLocalParam.nCol2, aLocalParam.nRow2 ) )
706  {
707  if (!bApi)
708  rDocShell.ErrorMessage(STR_PASTE_FULL);
709  return false;
710  }
711 
712  ScEditableTester aTester( rDoc, nDestTab, aLocalParam.nCol1,aLocalParam.nRow1,
713  aLocalParam.nCol2,aLocalParam.nRow2);
714  if (!aTester.IsEditable())
715  {
716  if (!bApi)
718  return false;
719  }
720 
721  pDestData = rDoc.GetDBAtCursor( rQueryParam.nDestCol, rQueryParam.nDestRow,
722  rQueryParam.nDestTab, ScDBDataPortion::TOP_LEFT );
723  if (pDestData)
724  {
725  pDestData->GetArea( aOldDest );
726  aDestTotal=ScRange( rQueryParam.nDestCol,
727  rQueryParam.nDestRow,
728  nDestTab,
729  rQueryParam.nDestCol + rQueryParam.nCol2 - rQueryParam.nCol1,
730  rQueryParam.nDestRow + rQueryParam.nRow2 - rQueryParam.nRow1,
731  nDestTab );
732 
733  bDoSize = pDestData->IsDoSize();
734  // test if formulas need to be filled in (nFormulaCols):
735  if ( bDoSize && aOldDest.aEnd.Col() == aDestTotal.aEnd.Col() )
736  {
737  SCCOL nTestCol = aOldDest.aEnd.Col() + 1; // next to the range
738  SCROW nTestRow = rQueryParam.nDestRow +
739  ( aLocalParam.bHasHeader ? 1 : 0 );
740  while ( nTestCol <= rDoc.MaxCol() &&
741  rDoc.GetCellType(ScAddress( nTestCol, nTestRow, nTab )) == CELLTYPE_FORMULA )
742  {
743  ++nTestCol;
744  ++nFormulaCols;
745  }
746  }
747 
748  bKeepFmt = pDestData->IsKeepFmt();
749  if ( bDoSize && !rDoc.CanFitBlock( aOldDest, aDestTotal ) )
750  {
751  if (!bApi)
752  rDocShell.ErrorMessage(STR_MSSG_DOSUBTOTALS_2); // cannot insert rows
753  return false;
754  }
755  }
756  }
757 
758  // execute
759 
761 
762  bool bKeepSub = false; // repeat existing partial results?
763  if (rQueryParam.GetEntry(0).bDoQuery) // not at cancellation
764  {
765  ScSubTotalParam aSubTotalParam;
766  pDBData->GetSubTotalParam( aSubTotalParam ); // partial results exist?
767 
768  if ( aSubTotalParam.bGroupActive[0] && !aSubTotalParam.bRemoveOnly )
769  bKeepSub = true;
770  }
771 
772  ScDocumentUniquePtr pUndoDoc;
773  std::unique_ptr<ScDBCollection> pUndoDB;
774  const ScRange* pOld = nullptr;
775 
776  if ( bRecord )
777  {
778  pUndoDoc.reset(new ScDocument( SCDOCMODE_UNDO ));
779  if (bCopy)
780  {
781  pUndoDoc->InitUndo( rDoc, nDestTab, nDestTab, false, true );
782  rDoc.CopyToDocument(aLocalParam.nCol1, aLocalParam.nRow1, nDestTab,
783  aLocalParam.nCol2, aLocalParam.nRow2, nDestTab,
784  InsertDeleteFlags::ALL, false, *pUndoDoc);
785  // secure attributes in case they were copied along
786 
787  if (pDestData)
788  {
789  rDoc.CopyToDocument(aOldDest, InsertDeleteFlags::ALL, false, *pUndoDoc);
790  pOld = &aOldDest;
791  }
792  }
793  else
794  {
795  pUndoDoc->InitUndo( rDoc, nTab, nTab, false, true );
796  rDoc.CopyToDocument(0, rQueryParam.nRow1, nTab, rDoc.MaxCol(), rQueryParam.nRow2, nTab,
797  InsertDeleteFlags::NONE, false, *pUndoDoc);
798  }
799 
800  ScDBCollection* pDocDB = rDoc.GetDBCollection();
801  if (!pDocDB->empty())
802  pUndoDB.reset(new ScDBCollection( *pDocDB ));
803 
804  rDoc.BeginDrawUndo();
805  }
806 
807  std::unique_ptr<ScDocument> pAttribDoc;
808  ScRange aAttribRange;
809  if (pDestData) // delete destination range
810  {
811  if ( bKeepFmt )
812  {
813  // smaller of the end columns, header+1 row
814  aAttribRange = aOldDest;
815  if ( aAttribRange.aEnd.Col() > aDestTotal.aEnd.Col() )
816  aAttribRange.aEnd.SetCol( aDestTotal.aEnd.Col() );
817  aAttribRange.aEnd.SetRow( aAttribRange.aStart.Row() +
818  ( aLocalParam.bHasHeader ? 1 : 0 ) );
819 
820  // also for filled-in formulas
821  aAttribRange.aEnd.SetCol( aAttribRange.aEnd.Col() + nFormulaCols );
822 
823  pAttribDoc.reset(new ScDocument( SCDOCMODE_UNDO ));
824  pAttribDoc->InitUndo( rDoc, nDestTab, nDestTab, false, true );
825  rDoc.CopyToDocument(aAttribRange, InsertDeleteFlags::ATTRIB, false, *pAttribDoc);
826  }
827 
828  if ( bDoSize )
829  rDoc.FitBlock( aOldDest, aDestTotal );
830  else
831  rDoc.DeleteAreaTab(aOldDest, InsertDeleteFlags::ALL); // simply delete
832  }
833 
834  // execute filtering on the document
835  SCSIZE nCount = rDoc.Query( nTab, rQueryParam, bKeepSub );
836  pDBData->CalcSaveFilteredCount( nCount );
837  if (bCopy)
838  {
839  aLocalParam.nRow2 = aLocalParam.nRow1 + nCount;
840  if (!aLocalParam.bHasHeader && nCount > 0)
841  --aLocalParam.nRow2;
842 
843  if ( bDoSize )
844  {
845  // adjust to the real result range
846  // (this here is always a reduction)
847 
848  ScRange aNewDest( aLocalParam.nCol1, aLocalParam.nRow1, nDestTab,
849  aLocalParam.nCol2, aLocalParam.nRow2, nDestTab );
850  rDoc.FitBlock( aDestTotal, aNewDest, false ); // sal_False - don't delete
851 
852  if ( nFormulaCols > 0 )
853  {
854  // fill in formulas
856 
857  ScRange aNewForm( aLocalParam.nCol2+1, aLocalParam.nRow1, nDestTab,
858  aLocalParam.nCol2+nFormulaCols, aLocalParam.nRow2, nDestTab );
859  ScRange aOldForm = aNewForm;
860  aOldForm.aEnd.SetRow( aOldDest.aEnd.Row() );
861  rDoc.FitBlock( aOldForm, aNewForm, false );
862 
863  ScMarkData aMark(rDoc.GetSheetLimits());
864  aMark.SelectOneTable(nDestTab);
865  SCROW nFStartY = aLocalParam.nRow1 + ( aLocalParam.bHasHeader ? 1 : 0 );
866 
867  sal_uLong nProgCount = nFormulaCols;
868  nProgCount *= aLocalParam.nRow2 - nFStartY;
869  ScProgress aProgress( rDoc.GetDocumentShell(),
870  ScResId(STR_FILL_SERIES_PROGRESS), nProgCount, true );
871 
872  rDoc.Fill( aLocalParam.nCol2+1, nFStartY,
873  aLocalParam.nCol2+nFormulaCols, nFStartY, &aProgress, aMark,
874  aLocalParam.nRow2 - nFStartY,
876  }
877  }
878 
879  if ( pAttribDoc ) // copy back the memorized attributes
880  {
881  // Header
882  if (aLocalParam.bHasHeader)
883  {
884  ScRange aHdrRange = aAttribRange;
885  aHdrRange.aEnd.SetRow( aHdrRange.aStart.Row() );
886  pAttribDoc->CopyToDocument(aHdrRange, InsertDeleteFlags::ATTRIB, false, rDoc);
887  }
888 
889  // Data
890  SCCOL nAttrEndCol = aAttribRange.aEnd.Col();
891  SCROW nAttrRow = aAttribRange.aStart.Row() + ( aLocalParam.bHasHeader ? 1 : 0 );
892  for (SCCOL nCol = aAttribRange.aStart.Col(); nCol<=nAttrEndCol; nCol++)
893  {
894  const ScPatternAttr* pSrcPattern = pAttribDoc->GetPattern(
895  nCol, nAttrRow, nDestTab );
896  OSL_ENSURE(pSrcPattern,"Pattern is 0");
897  if (pSrcPattern)
898  {
899  rDoc.ApplyPatternAreaTab( nCol, nAttrRow, nCol, aLocalParam.nRow2,
900  nDestTab, *pSrcPattern );
901  const ScStyleSheet* pStyle = pSrcPattern->GetStyleSheet();
902  if (pStyle)
903  rDoc.ApplyStyleAreaTab( nCol, nAttrRow, nCol, aLocalParam.nRow2,
904  nDestTab, *pStyle );
905  }
906  }
907  }
908  }
909 
910  // saving: Inplace always, otherwise depending on setting
911  // old Inplace-Filter may have already been removed
912 
913  bool bSave = rQueryParam.bInplace || rQueryParam.bDestPers;
914  if (bSave) // memorize
915  {
916  pDBData->SetQueryParam( rQueryParam );
917  pDBData->SetHeader( rQueryParam.bHasHeader );
918  pDBData->SetAdvancedQuerySource( pAdvSource ); // after SetQueryParam
919  }
920 
921  if (bCopy) // memorize new DB range
922  {
923  // Selection is done afterwards from outside (dbfunc).
924  // Currently through the DB area at the destination position,
925  // so a range must be created there in any case.
926 
927  ScDBData* pNewData;
928  if (pDestData)
929  pNewData = pDestData; // range exists -> adjust (always!)
930  else // create range
931  pNewData = rDocShell.GetDBData(
932  ScRange( aLocalParam.nCol1, aLocalParam.nRow1, nDestTab,
933  aLocalParam.nCol2, aLocalParam.nRow2, nDestTab ),
935 
936  if (pNewData)
937  {
938  pNewData->SetArea( nDestTab, aLocalParam.nCol1, aLocalParam.nRow1,
939  aLocalParam.nCol2, aLocalParam.nRow2 );
940 
941  // query parameter is no longer set at the destination, only leads to confusion
942  // and mistakes with the query parameter at the source range (#37187#)
943  }
944  else
945  {
946  OSL_FAIL("Target are not available");
947  }
948  }
949 
950  if (!bCopy)
951  {
952  rDoc.InvalidatePageBreaks(nTab);
953  rDoc.UpdatePageBreaks( nTab );
954  }
955 
956  // #i23299# Subtotal functions depend on cell's filtered states.
957  ScRange aDirtyRange(0 , aLocalParam.nRow1, nDestTab, rDoc.MaxCol(), aLocalParam.nRow2, nDestTab);
958  rDoc.SetSubTotalCellsDirty(aDirtyRange);
959 
960  if ( bRecord )
961  {
962  // create undo action after executing, because of drawing layer undo
964  std::make_unique<ScUndoQuery>( &rDocShell, nTab, rQueryParam, std::move(pUndoDoc), std::move(pUndoDB),
965  pOld, bDoSize, pAdvSource ) );
966  }
967 
968  if ( pViewSh )
969  {
970  // could there be horizontal autofilter ?
971  // maybe it would be better to set bColumns to !rQueryParam.bByRow ?
972  // anyway at the beginning the value of bByRow is 'false'
973  // then after the first sort action it becomes 'true'
974  pViewSh->OnLOKShowHideColRow(/*bColumns*/ false, rQueryParam.nRow1 - 1);
975  }
976 
977  if (bCopy)
978  {
979  SCCOL nEndX = aLocalParam.nCol2;
980  SCROW nEndY = aLocalParam.nRow2;
981  if (pDestData)
982  {
983  if ( aOldDest.aEnd.Col() > nEndX )
984  nEndX = aOldDest.aEnd.Col();
985  if ( aOldDest.aEnd.Row() > nEndY )
986  nEndY = aOldDest.aEnd.Row();
987  }
988  if (bDoSize)
989  nEndY = rDoc.MaxRow();
991  ScRange(aLocalParam.nCol1, aLocalParam.nRow1, nDestTab, nEndX, nEndY, nDestTab),
993  }
994  else
996  ScRange(0, rQueryParam.nRow1, nTab, rDoc.MaxCol(), rDoc.MaxRow(), nTab),
998  aModificator.SetDocumentModified();
999 
1000  return true;
1001 }
1002 
1004  bool bRecord, bool bApi )
1005 {
1007  // then stays outside:
1008  // - mark new range (from DBData)
1009  // - SelectionChanged (?)
1010 
1011  bool bDo = !rParam.bRemoveOnly; // sal_False = only delete
1012 
1013  ScDocument& rDoc = rDocShell.GetDocument();
1014  if (bRecord && !rDoc.IsUndoEnabled())
1015  bRecord = false;
1016  ScDBData* pDBData = rDoc.GetDBAtArea( nTab, rParam.nCol1, rParam.nRow1,
1017  rParam.nCol2, rParam.nRow2 );
1018  if (!pDBData)
1019  {
1020  OSL_FAIL( "SubTotals: no DBData" );
1021  return;
1022  }
1023 
1024  ScEditableTester aTester( rDoc, nTab, 0,rParam.nRow1+1, rDoc.MaxCol(),rDoc.MaxRow() );
1025  if (!aTester.IsEditable())
1026  {
1027  if (!bApi)
1028  rDocShell.ErrorMessage(aTester.GetMessageId());
1029  return;
1030  }
1031 
1032  if (rDoc.HasAttrib( rParam.nCol1, rParam.nRow1+1, nTab,
1033  rParam.nCol2, rParam.nRow2, nTab, HasAttrFlags::Merged | HasAttrFlags::Overlapped ))
1034  {
1035  if (!bApi)
1036  rDocShell.ErrorMessage(STR_MSSG_INSERTCELLS_0); // don't insert into merged
1037  return;
1038  }
1039 
1040  bool bOk = true;
1041  if (rParam.bReplace)
1042  {
1043  if (rDoc.TestRemoveSubTotals( nTab, rParam ))
1044  {
1045  std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(ScDocShell::GetActiveDialogParent(),
1046  VclMessageType::Question,
1047  VclButtonsType::YesNo, ScResId(STR_MSSG_DOSUBTOTALS_1))); // "Delete Data?"
1048  xBox->set_title(ScResId(STR_MSSG_DOSUBTOTALS_0)); // "StarCalc"
1049  bOk = xBox->run() == RET_YES;
1050  }
1051  }
1052 
1053  if (!bOk)
1054  return;
1055 
1057  ScDocShellModificator aModificator( rDocShell );
1058 
1059  ScSubTotalParam aNewParam( rParam ); // end of range is being changed
1060  ScDocumentUniquePtr pUndoDoc;
1061  std::unique_ptr<ScOutlineTable> pUndoTab;
1062  std::unique_ptr<ScRangeName> pUndoRange;
1063  std::unique_ptr<ScDBCollection> pUndoDB;
1064 
1065  if (bRecord) // secure old data
1066  {
1067  bool bOldFilter = bDo && rParam.bDoSort;
1068 
1069  SCTAB nTabCount = rDoc.GetTableCount();
1070  pUndoDoc.reset(new ScDocument( SCDOCMODE_UNDO ));
1071  ScOutlineTable* pTable = rDoc.GetOutlineTable( nTab );
1072  if (pTable)
1073  {
1074  pUndoTab.reset(new ScOutlineTable( *pTable ));
1075 
1076  // column/row state
1077  SCCOLROW nOutStartCol, nOutEndCol;
1078  SCCOLROW nOutStartRow, nOutEndRow;
1079  pTable->GetColArray().GetRange( nOutStartCol, nOutEndCol );
1080  pTable->GetRowArray().GetRange( nOutStartRow, nOutEndRow );
1081 
1082  pUndoDoc->InitUndo( rDoc, nTab, nTab, true, true );
1083  rDoc.CopyToDocument(static_cast<SCCOL>(nOutStartCol), 0, nTab, static_cast<SCCOL>(nOutEndCol), rDoc.MaxRow(), nTab, InsertDeleteFlags::NONE, false, *pUndoDoc);
1084  rDoc.CopyToDocument(0, nOutStartRow, nTab, rDoc.MaxCol(), nOutEndRow, nTab, InsertDeleteFlags::NONE, false, *pUndoDoc);
1085  }
1086  else
1087  pUndoDoc->InitUndo( rDoc, nTab, nTab, false, bOldFilter );
1088 
1089  // secure data range - incl. filtering result
1090  rDoc.CopyToDocument(0, rParam.nRow1+1,nTab, rDoc.MaxCol(),rParam.nRow2,nTab,
1091  InsertDeleteFlags::ALL, false, *pUndoDoc);
1092 
1093  // all formulas because of references
1094  rDoc.CopyToDocument(0, 0, 0, rDoc.MaxCol(),rDoc.MaxRow(),nTabCount-1,
1095  InsertDeleteFlags::FORMULA, false, *pUndoDoc);
1096 
1097  // ranges of DB and other
1098  ScRangeName* pDocRange = rDoc.GetRangeName();
1099  if (!pDocRange->empty())
1100  pUndoRange.reset(new ScRangeName( *pDocRange ));
1101  ScDBCollection* pDocDB = rDoc.GetDBCollection();
1102  if (!pDocDB->empty())
1103  pUndoDB.reset(new ScDBCollection( *pDocDB ));
1104  }
1105 
1106 // rDoc.SetOutlineTable( nTab, NULL );
1107  ScOutlineTable* pOut = rDoc.GetOutlineTable( nTab );
1108  if (pOut)
1109  pOut->GetRowArray().RemoveAll(); // only delete row outlines
1110 
1111  if (rParam.bReplace)
1112  rDoc.RemoveSubTotals( nTab, aNewParam );
1113  bool bSuccess = true;
1114  if (bDo)
1115  {
1116  // sort
1117  if ( rParam.bDoSort )
1118  {
1119  pDBData->SetArea( nTab, aNewParam.nCol1,aNewParam.nRow1, aNewParam.nCol2,aNewParam.nRow2 );
1120 
1121  // set partial result field to before the sorting
1122  // (Duplicates are omitted, so can be called again)
1123 
1124  ScSortParam aOldSort;
1125  pDBData->GetSortParam( aOldSort );
1126  ScSortParam aSortParam( aNewParam, aOldSort );
1127  Sort( nTab, aSortParam, false, false, bApi );
1128  }
1129 
1130  bSuccess = rDoc.DoSubTotals( nTab, aNewParam );
1131  rDoc.SetDrawPageSize(nTab);
1132  }
1133  ScRange aDirtyRange( aNewParam.nCol1, aNewParam.nRow1, nTab,
1134  aNewParam.nCol2, aNewParam.nRow2, nTab );
1135  rDoc.SetDirty( aDirtyRange, true );
1136 
1137  if (bRecord)
1138  {
1139 // ScDBData* pUndoDBData = pDBData ? new ScDBData( *pDBData ) : NULL;
1141  std::make_unique<ScUndoSubTotals>( &rDocShell, nTab,
1142  rParam, aNewParam.nRow2,
1143  std::move(pUndoDoc), std::move(pUndoTab), // pUndoDBData,
1144  std::move(pUndoRange), std::move(pUndoDB) ) );
1145  }
1146 
1147  if (!bSuccess)
1148  {
1149  // "Cannot insert rows"
1150  if (!bApi)
1151  rDocShell.ErrorMessage(STR_MSSG_DOSUBTOTALS_2);
1152  }
1153 
1154  // memorize
1155  pDBData->SetSubTotalParam( aNewParam );
1156  pDBData->SetArea( nTab, aNewParam.nCol1,aNewParam.nRow1, aNewParam.nCol2,aNewParam.nRow2 );
1157  rDoc.CompileDBFormula();
1158 
1159  rDocShell.PostPaint(ScRange(0, 0, nTab, rDoc.MaxCol(),rDoc.MaxRow(),nTab),
1161  aModificator.SetDocumentModified();
1162 }
1163 
1164 namespace {
1165 
1166 bool lcl_EmptyExcept( ScDocument& rDoc, const ScRange& rRange, const ScRange& rExcept )
1167 {
1168  ScCellIterator aIter( rDoc, rRange );
1169  for (bool bHasCell = aIter.first(); bHasCell; bHasCell = aIter.next())
1170  {
1171  if (!aIter.isEmpty()) // real content?
1172  {
1173  if (!rExcept.In(aIter.GetPos()))
1174  return false; // cell found
1175  }
1176  }
1177 
1178  return true; // nothing found - empty
1179 }
1180 
1181 bool isEditable(ScDocShell& rDocShell, const ScRangeList& rRanges, bool bApi)
1182 {
1183  ScDocument& rDoc = rDocShell.GetDocument();
1184  if (!rDocShell.IsEditable() || rDoc.GetChangeTrack())
1185  {
1186  // not recorded -> disallow
1187  if (!bApi)
1188  rDocShell.ErrorMessage(STR_PROTECTIONERR);
1189 
1190  return false;
1191  }
1192 
1193  for (size_t i = 0, n = rRanges.size(); i < n; ++i)
1194  {
1195  const ScRange & r = rRanges[i];
1196  ScEditableTester aTester(rDoc, r);
1197  if (!aTester.IsEditable())
1198  {
1199  if (!bApi)
1200  rDocShell.ErrorMessage(aTester.GetMessageId());
1201 
1202  return false;
1203  }
1204  }
1205 
1206  return true;
1207 }
1208 
1209 void createUndoDoc(ScDocumentUniquePtr& pUndoDoc, ScDocument& rDoc, const ScRange& rRange)
1210 {
1211  SCTAB nTab = rRange.aStart.Tab();
1212  pUndoDoc.reset(new ScDocument(SCDOCMODE_UNDO));
1213  pUndoDoc->InitUndo(rDoc, nTab, nTab);
1214  rDoc.CopyToDocument(rRange, InsertDeleteFlags::ALL, false, *pUndoDoc);
1215 }
1216 
1217 bool checkNewOutputRange(ScDPObject& rDPObj, ScDocShell& rDocShell, ScRange& rNewOut, bool bApi)
1218 {
1219  ScDocument& rDoc = rDocShell.GetDocument();
1220 
1221  bool bOverflow = false;
1222  rNewOut = rDPObj.GetNewOutputRange(bOverflow);
1223 
1224  // Test for overlap with source data range.
1225  // TODO: Check with other pivot tables as well.
1226  const ScSheetSourceDesc* pSheetDesc = rDPObj.GetSheetDesc();
1227  if (pSheetDesc && pSheetDesc->GetSourceRange().Intersects(rNewOut))
1228  {
1229  // New output range intersteps with the source data. Move it up to
1230  // where the old range is and see if that works.
1231  ScRange aOldRange = rDPObj.GetOutRange();
1232  SCROW nDiff = aOldRange.aStart.Row() - rNewOut.aStart.Row();
1233  rNewOut.aStart.SetRow(aOldRange.aStart.Row());
1234  rNewOut.aEnd.IncRow(nDiff);
1235  if (!rDoc.ValidRow(rNewOut.aStart.Row()) || !rDoc.ValidRow(rNewOut.aEnd.Row()))
1236  bOverflow = true;
1237  }
1238 
1239  if (bOverflow)
1240  {
1241  if (!bApi)
1242  rDocShell.ErrorMessage(STR_PIVOT_ERROR);
1243 
1244  return false;
1245  }
1246 
1247  ScEditableTester aTester(rDoc, rNewOut);
1248  if (!aTester.IsEditable())
1249  {
1250  // destination area isn't editable
1251  if (!bApi)
1252  rDocShell.ErrorMessage(aTester.GetMessageId());
1253 
1254  return false;
1255  }
1256 
1257  return true;
1258 }
1259 
1260 }
1261 
1262 bool ScDBDocFunc::DataPilotUpdate( ScDPObject* pOldObj, const ScDPObject* pNewObj,
1263  bool bRecord, bool bApi, bool bAllowMove )
1264 {
1265  if (!pOldObj)
1266  {
1267  if (!pNewObj)
1268  return false;
1269 
1270  return CreatePivotTable(*pNewObj, bRecord, bApi);
1271  }
1272 
1273  if (!pNewObj)
1274  return RemovePivotTable(*pOldObj, bRecord, bApi);
1275 
1276  if (pOldObj == pNewObj)
1277  return UpdatePivotTable(*pOldObj, bRecord, bApi);
1278 
1279  OSL_ASSERT(pOldObj && pNewObj && pOldObj != pNewObj);
1280 
1281  ScDocShellModificator aModificator( rDocShell );
1283 
1284  ScRangeList aRanges;
1285  aRanges.push_back(pOldObj->GetOutRange());
1286  aRanges.push_back(pNewObj->GetOutRange().aStart); // at least one cell in the output position must be editable.
1287  if (!isEditable(rDocShell, aRanges, bApi))
1288  return false;
1289 
1290  ScDocumentUniquePtr pOldUndoDoc;
1291  ScDocumentUniquePtr pNewUndoDoc;
1292 
1293  ScDPObject aUndoDPObj(*pOldObj); // for undo or revert on failure
1294 
1295  ScDocument& rDoc = rDocShell.GetDocument();
1296  if (bRecord && !rDoc.IsUndoEnabled())
1297  bRecord = false;
1298 
1299  if (bRecord)
1300  createUndoDoc(pOldUndoDoc, rDoc, pOldObj->GetOutRange());
1301 
1302  pNewObj->WriteSourceDataTo(*pOldObj); // copy source data
1303 
1304  ScDPSaveData* pData = pNewObj->GetSaveData();
1305  OSL_ENSURE( pData, "no SaveData from living DPObject" );
1306  if (pData)
1307  pOldObj->SetSaveData(*pData); // copy SaveData
1308 
1309  pOldObj->SetAllowMove(bAllowMove);
1310  pOldObj->ReloadGroupTableData();
1311  pOldObj->SyncAllDimensionMembers();
1312  pOldObj->InvalidateData(); // before getting the new output area
1313 
1314  // make sure the table has a name (not set by dialog)
1315  if (pOldObj->GetName().isEmpty())
1316  pOldObj->SetName( rDoc.GetDPCollection()->CreateNewName() );
1317 
1318  ScRange aNewOut;
1319  if (!checkNewOutputRange(*pOldObj, rDocShell, aNewOut, bApi))
1320  {
1321  *pOldObj = aUndoDPObj;
1322  return false;
1323  }
1324 
1325  // test if new output area is empty except for old area
1326  if (!bApi)
1327  {
1328  // OutRange of pOldObj (pDestObj) is still old area
1329  if (!lcl_EmptyExcept(rDoc, aNewOut, pOldObj->GetOutRange()))
1330  {
1331  std::unique_ptr<weld::MessageDialog> xQueryBox(Application::CreateMessageDialog(ScDocShell::GetActiveDialogParent(),
1332  VclMessageType::Question, VclButtonsType::YesNo,
1333  ScResId(STR_PIVOT_NOTEMPTY)));
1334  xQueryBox->set_default_response(RET_YES);
1335  if (xQueryBox->run() == RET_NO)
1336  {
1338  *pOldObj = aUndoDPObj;
1339  return false;
1340  }
1341  }
1342  }
1343 
1344  if (bRecord)
1345  createUndoDoc(pNewUndoDoc, rDoc, aNewOut);
1346 
1347  pOldObj->Output(aNewOut.aStart);
1348  rDocShell.PostPaintGridAll();
1349 
1350  if (bRecord)
1351  {
1352  rDocShell.GetUndoManager()->AddUndoAction(
1353  std::make_unique<ScUndoDataPilot>(
1354  &rDocShell, std::move(pOldUndoDoc), std::move(pNewUndoDoc), &aUndoDPObj, pOldObj, bAllowMove));
1355  }
1356 
1357  // notify API objects
1358  rDoc.BroadcastUno( ScDataPilotModifiedHint(pOldObj->GetName()) );
1359  aModificator.SetDocumentModified();
1360 
1361  return true;
1362 }
1363 
1364 bool ScDBDocFunc::RemovePivotTable(ScDPObject& rDPObj, bool bRecord, bool bApi)
1365 {
1366  ScDocShellModificator aModificator(rDocShell);
1368 
1369  if (!isEditable(rDocShell, rDPObj.GetOutRange(), bApi))
1370  return false;
1371 
1372  ScDocument& rDoc = rDocShell.GetDocument();
1373 
1374  if (!bApi)
1375  {
1376  // If we come from GUI - ask to delete the associated pivot charts too...
1377  std::vector<SdrOle2Obj*> aListOfObjects =
1379 
1380  ScDrawLayer* pModel = rDoc.GetDrawLayer();
1381 
1382  if (pModel && !aListOfObjects.empty())
1383  {
1384  std::unique_ptr<weld::MessageDialog> xQueryBox(Application::CreateMessageDialog(ScDocShell::GetActiveDialogParent(),
1385  VclMessageType::Question, VclButtonsType::YesNo,
1386  ScResId(STR_PIVOT_REMOVE_PIVOTCHART)));
1387  xQueryBox->set_default_response(RET_YES);
1388  if (xQueryBox->run() == RET_NO)
1389  {
1390  return false;
1391  }
1392  else
1393  {
1394  for (SdrOle2Obj* pChartObject : aListOfObjects)
1395  {
1396  rDoc.GetChartListenerCollection()->removeByName(pChartObject->GetName());
1397  pModel->AddUndo(std::make_unique<SdrUndoDelObj>(*pChartObject));
1398  pChartObject->getSdrPageFromSdrObject()->RemoveObject(pChartObject->GetOrdNum());
1399  }
1400  }
1401  }
1402  }
1403 
1404  ScDocumentUniquePtr pOldUndoDoc;
1405  std::unique_ptr<ScDPObject> pUndoDPObj;
1406 
1407  if (bRecord)
1408  pUndoDPObj.reset(new ScDPObject(rDPObj)); // copy old settings for undo
1409 
1410  if (bRecord && !rDoc.IsUndoEnabled())
1411  bRecord = false;
1412 
1413  // delete table
1414 
1415  ScRange aRange = rDPObj.GetOutRange();
1416  SCTAB nTab = aRange.aStart.Tab();
1417 
1418  if (bRecord)
1419  createUndoDoc(pOldUndoDoc, rDoc, aRange);
1420 
1421  rDoc.DeleteAreaTab( aRange.aStart.Col(), aRange.aStart.Row(),
1422  aRange.aEnd.Col(), aRange.aEnd.Row(),
1423  nTab, InsertDeleteFlags::ALL );
1424  rDoc.RemoveFlagsTab( aRange.aStart.Col(), aRange.aStart.Row(),
1425  aRange.aEnd.Col(), aRange.aEnd.Row(),
1426  nTab, ScMF::Auto );
1427 
1428  rDoc.GetDPCollection()->FreeTable(&rDPObj); // object is deleted here
1429 
1430  rDocShell.PostPaintGridAll();
1431  rDocShell.PostPaint(aRange, PaintPartFlags::Grid);
1432 
1433  if (bRecord)
1434  {
1435  rDocShell.GetUndoManager()->AddUndoAction(
1436  std::make_unique<ScUndoDataPilot>(
1437  &rDocShell, std::move(pOldUndoDoc), nullptr, pUndoDPObj.get(), nullptr, false));
1438 
1439  // pUndoDPObj is copied
1440  }
1441 
1442  aModificator.SetDocumentModified();
1443  return true;
1444 }
1445 
1446 bool ScDBDocFunc::CreatePivotTable(const ScDPObject& rDPObj, bool bRecord, bool bApi)
1447 {
1448  ScDocShellModificator aModificator(rDocShell);
1450 
1451  // At least one cell in the output range should be editable. Check in advance.
1452  if (!isEditable(rDocShell, ScRange(rDPObj.GetOutRange().aStart), bApi))
1453  return false;
1454 
1455  ScDocumentUniquePtr pNewUndoDoc;
1456 
1457  ScDocument& rDoc = rDocShell.GetDocument();
1458  if (bRecord && !rDoc.IsUndoEnabled())
1459  bRecord = false;
1460 
1461  // output range must be set at pNewObj
1462  std::unique_ptr<ScDPObject> pDestObj(new ScDPObject(rDPObj));
1463 
1464  ScDPObject& rDestObj = *pDestObj;
1465 
1466  // #i94570# When changing the output position in the dialog, a new table is created
1467  // with the settings from the old table, including the name.
1468  // So we have to check for duplicate names here (before inserting).
1469  if (rDoc.GetDPCollection()->GetByName(rDestObj.GetName()))
1470  rDestObj.SetName(OUString()); // ignore the invalid name, create a new name below
1471 
1472  // Synchronize groups between linked tables
1473  {
1474  const ScDPDimensionSaveData* pGroups = nullptr;
1475  bool bRefFound = rDoc.GetDPCollection()->GetReferenceGroups(rDestObj, &pGroups);
1476  if (bRefFound)
1477  {
1478  ScDPSaveData* pSaveData = rDestObj.GetSaveData();
1479  if (pSaveData)
1480  pSaveData->SetDimensionData(pGroups);
1481  }
1482  }
1483 
1484  rDoc.GetDPCollection()->InsertNewTable(std::move(pDestObj));
1485 
1486  rDestObj.ReloadGroupTableData();
1487  rDestObj.SyncAllDimensionMembers();
1488  rDestObj.InvalidateData(); // before getting the new output area
1489 
1490  // make sure the table has a name (not set by dialog)
1491  if (rDestObj.GetName().isEmpty())
1492  rDestObj.SetName(rDoc.GetDPCollection()->CreateNewName());
1493 
1494  bool bOverflow = false;
1495  ScRange aNewOut = rDestObj.GetNewOutputRange(bOverflow);
1496 
1497  if (bOverflow)
1498  {
1499  if (!bApi)
1500  rDocShell.ErrorMessage(STR_PIVOT_ERROR);
1501 
1502  return false;
1503  }
1504 
1505  {
1506  ScEditableTester aTester(rDoc, aNewOut);
1507  if (!aTester.IsEditable())
1508  {
1509  // destination area isn't editable
1510  if (!bApi)
1511  rDocShell.ErrorMessage(aTester.GetMessageId());
1512 
1513  return false;
1514  }
1515  }
1516 
1517  // test if new output area is empty except for old area
1518  if (!bApi)
1519  {
1520  bool bEmpty = rDoc.IsBlockEmpty(
1521  aNewOut.aStart.Tab(), aNewOut.aStart.Col(), aNewOut.aStart.Row(),
1522  aNewOut.aEnd.Col(), aNewOut.aEnd.Row());
1523 
1524  if (!bEmpty)
1525  {
1526  std::unique_ptr<weld::MessageDialog> xQueryBox(Application::CreateMessageDialog(ScDocShell::GetActiveDialogParent(),
1527  VclMessageType::Question, VclButtonsType::YesNo,
1528  ScResId(STR_PIVOT_NOTEMPTY)));
1529  xQueryBox->set_default_response(RET_YES);
1530  if (xQueryBox->run() == RET_NO)
1531  {
1533  return false;
1534  }
1535  }
1536  }
1537 
1538  if (bRecord)
1539  createUndoDoc(pNewUndoDoc, rDoc, aNewOut);
1540 
1541  rDestObj.Output(aNewOut.aStart);
1542  rDocShell.PostPaintGridAll();
1543 
1544  if (bRecord)
1545  {
1546  rDocShell.GetUndoManager()->AddUndoAction(
1547  std::make_unique<ScUndoDataPilot>(&rDocShell, nullptr, std::move(pNewUndoDoc), nullptr, &rDestObj, false));
1548  }
1549 
1550  // notify API objects
1551  rDoc.BroadcastUno(ScDataPilotModifiedHint(rDestObj.GetName()));
1552  aModificator.SetDocumentModified();
1553 
1554  return true;
1555 }
1556 
1557 bool ScDBDocFunc::UpdatePivotTable(ScDPObject& rDPObj, bool bRecord, bool bApi)
1558 {
1559  ScDocShellModificator aModificator( rDocShell );
1561 
1562  if (!isEditable(rDocShell, rDPObj.GetOutRange(), bApi))
1563  return false;
1564 
1565  ScDocumentUniquePtr pOldUndoDoc;
1566  ScDocumentUniquePtr pNewUndoDoc;
1567 
1568  ScDPObject aUndoDPObj(rDPObj); // For undo or revert on failure.
1569 
1570  ScDocument& rDoc = rDocShell.GetDocument();
1571  if (bRecord && !rDoc.IsUndoEnabled())
1572  bRecord = false;
1573 
1574  if (bRecord)
1575  createUndoDoc(pOldUndoDoc, rDoc, rDPObj.GetOutRange());
1576 
1577  rDPObj.SetAllowMove(false);
1578  rDPObj.ReloadGroupTableData();
1579  if (!rDPObj.SyncAllDimensionMembers())
1580  return false;
1581 
1582  rDPObj.InvalidateData(); // before getting the new output area
1583 
1584  // make sure the table has a name (not set by dialog)
1585  if (rDPObj.GetName().isEmpty())
1586  rDPObj.SetName( rDoc.GetDPCollection()->CreateNewName() );
1587 
1588  ScRange aNewOut;
1589  if (!checkNewOutputRange(rDPObj, rDocShell, aNewOut, bApi))
1590  {
1591  rDPObj = aUndoDPObj;
1592  return false;
1593  }
1594 
1595  // test if new output area is empty except for old area
1596  if (!bApi)
1597  {
1598  if (!lcl_EmptyExcept(rDoc, aNewOut, rDPObj.GetOutRange()))
1599  {
1600  std::unique_ptr<weld::MessageDialog> xQueryBox(Application::CreateMessageDialog(ScDocShell::GetActiveDialogParent(),
1601  VclMessageType::Question, VclButtonsType::YesNo,
1602  ScResId(STR_PIVOT_NOTEMPTY)));
1603  xQueryBox->set_default_response(RET_YES);
1604  if (xQueryBox->run() == RET_NO)
1605  {
1606  rDPObj = aUndoDPObj;
1607  return false;
1608  }
1609  }
1610  }
1611 
1612  if (bRecord)
1613  createUndoDoc(pNewUndoDoc, rDoc, aNewOut);
1614 
1615  rDPObj.Output(aNewOut.aStart);
1616  rDocShell.PostPaintGridAll();
1617 
1618  if (bRecord)
1619  {
1620  rDocShell.GetUndoManager()->AddUndoAction(
1621  std::make_unique<ScUndoDataPilot>(
1622  &rDocShell, std::move(pOldUndoDoc), std::move(pNewUndoDoc), &aUndoDPObj, &rDPObj, false));
1623  }
1624 
1625  // notify API objects
1626  rDoc.BroadcastUno( ScDataPilotModifiedHint(rDPObj.GetName()) );
1627  aModificator.SetDocumentModified();
1628  return true;
1629 }
1630 
1631 void ScDBDocFunc::RefreshPivotTables(const ScDPObject* pDPObj, bool bApi)
1632 {
1633  ScDPCollection* pDPs = rDocShell.GetDocument().GetDPCollection();
1634  if (!pDPs)
1635  return;
1636 
1638  const char* pErrId = pDPs->ReloadCache(pDPObj, aRefs);
1639  if (pErrId)
1640  return;
1641 
1642  for (ScDPObject* pObj : aRefs)
1643  {
1644  // This action is intentionally not undoable since it modifies cache.
1645  UpdatePivotTable(*pObj, false, bApi);
1646  }
1647 }
1648 
1650 {
1651  if (!pDPObj)
1652  return;
1653 
1654  ScDPCollection* pDPs = rDocShell.GetDocument().GetDPCollection();
1655  if (!pDPs)
1656  return;
1657 
1658  ScDPSaveData* pSaveData = pDPObj->GetSaveData();
1659  if (!pSaveData)
1660  return;
1661 
1662  if (!pDPs->HasTable(pDPObj))
1663  {
1664  // This table is under construction so no need for a whole update (UpdatePivotTable()).
1665  pDPObj->ReloadGroupTableData();
1666  return;
1667  }
1668 
1669  // Update all linked tables, if this table is part of the cache (ScDPCollection)
1671  if (!pDPs->ReloadGroupsInCache(pDPObj, aRefs))
1672  return;
1673 
1674  // We allow pDimData being NULL.
1675  const ScDPDimensionSaveData* pDimData = pSaveData->GetExistingDimensionData();
1676  for (ScDPObject* pObj : aRefs)
1677  {
1678  if (pObj != pDPObj)
1679  {
1680  pSaveData = pObj->GetSaveData();
1681  if (pSaveData)
1682  pSaveData->SetDimensionData(pDimData);
1683  }
1684 
1685  // This action is intentionally not undoable since it modifies cache.
1686  UpdatePivotTable(*pObj, false, false);
1687  }
1688 }
1689 
1690 // database import
1691 
1692 void ScDBDocFunc::UpdateImport( const OUString& rTarget, const svx::ODataAccessDescriptor& rDescriptor )
1693 {
1694  // rTarget is the name of a database range
1695 
1696  ScDocument& rDoc = rDocShell.GetDocument();
1697  ScDBCollection& rDBColl = *rDoc.GetDBCollection();
1698  const ScDBData* pData = rDBColl.getNamedDBs().findByUpperName(ScGlobal::getCharClassPtr()->uppercase(rTarget));
1699  if (!pData)
1700  {
1701  std::unique_ptr<weld::MessageDialog> xInfoBox(Application::CreateMessageDialog(ScDocShell::GetActiveDialogParent(),
1702  VclMessageType::Info, VclButtonsType::Ok,
1703  ScResId(STR_TARGETNOTFOUND)));
1704  xInfoBox->run();
1705  return;
1706  }
1707 
1708  SCTAB nTab;
1709  SCCOL nDummyCol;
1710  SCROW nDummyRow;
1711  pData->GetArea( nTab, nDummyCol,nDummyRow,nDummyCol,nDummyRow );
1712 
1713  ScImportParam aImportParam;
1714  pData->GetImportParam( aImportParam );
1715 
1716  OUString sDBName;
1717  OUString sDBTable;
1718  sal_Int32 nCommandType = 0;
1719  sDBName = rDescriptor.getDataSource();
1720  rDescriptor[svx::DataAccessDescriptorProperty::Command] >>= sDBTable;
1721  rDescriptor[svx::DataAccessDescriptorProperty::CommandType] >>= nCommandType;
1722 
1723  aImportParam.aDBName = sDBName;
1724  aImportParam.bSql = ( nCommandType == sdb::CommandType::COMMAND );
1725  aImportParam.aStatement = sDBTable;
1726  aImportParam.bNative = false;
1727  aImportParam.nType = static_cast<sal_uInt8>( ( nCommandType == sdb::CommandType::QUERY ) ? ScDbQuery : ScDbTable );
1728  aImportParam.bImport = true;
1729 
1730  bool bContinue = DoImport( nTab, aImportParam, &rDescriptor );
1731 
1732  // repeat DB operations
1733 
1734  ScTabViewShell* pViewSh = rDocShell.GetBestViewShell();
1735  if (!pViewSh)
1736  return;
1737 
1738  ScRange aRange;
1739  pData->GetArea(aRange);
1740  pViewSh->MarkRange(aRange); // select
1741 
1742  if ( bContinue ) // error at import -> abort
1743  {
1744  // internal operations, if some are saved
1745 
1746  if ( pData->HasQueryParam() || pData->HasSortParam() || pData->HasSubTotalParam() )
1747  pViewSh->RepeatDB();
1748 
1749  // pivot tables which have the range as source data
1750 
1751  rDocShell.RefreshPivotTables(aRange);
1752  }
1753 }
1754 
1755 /* 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:1805
void UpdatePageBreaks(SCTAB nTab, const ScRange *pUserArea=nullptr)
Definition: document.cxx:6247
bool insert(std::unique_ptr< ScDBData > p)
Takes ownership of p and attempts to insert it into the collection.
Definition: dbdata.cxx:1180
SC_DLLPUBLIC void ApplyStyleAreaTab(SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow, SCTAB nTab, const ScStyleSheet &rStyle)
Definition: document.cxx:4882
void ReloadGroupTableData()
Definition: dpobject.cxx:809
void FitBlock(const ScRange &rOld, const ScRange &rNew, bool bClear=true)
Definition: document.cxx:1836
SC_DLLPUBLIC bool HasQueryParam() const
Definition: dbdata.cxx:524
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:413
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:401
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:1687
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:702
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:542
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:5205
ScDPObject * GetByName(std::u16string_view rName) const
Definition: dpobject.cxx:3691
bool has(const ScDBData *p) const
Definition: dbdata.cxx:1289
bool IsDoSize() const
Definition: dbdata.hxx:136
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:560
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:1557
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:1631
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:318
bool empty() const
Definition: rangenam.cxx:804
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:2050
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:437
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:2403
void GetRange(SCCOLROW &rStart, SCCOLROW &rEnd) const
Definition: olinetab.cxx:555
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:946
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
virtual void AddUndoAction(std::unique_ptr< SfxUndoAction > pAction, bool bTryMerg=false)
void InvalidatePageBreaks(SCTAB nTab)
Definition: document.cxx:6241
void SetDBCollection(std::unique_ptr< ScDBCollection > pNewDBCollection, bool bRemoveAutoFilter=false)
Definition: documen3.cxx:275
bool IsImportingXML() const
Definition: document.hxx:2148
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:419
bool empty() const
Definition: dbdata.cxx:1517
bool RenameDBRange(const OUString &rOld, const OUString &rNew)
Definition: dbdocfun.cxx:154
void invalidateByIndex(index_type nIndex)
Definition: viewdata.cxx:160
std::unique_ptr< ScDocument, o3tl::default_delete< ScDocument > > ScDocumentUniquePtr
Definition: document.hxx:2620
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:1262
void OnLOKShowHideColRow(bool bColumns, SCCOLROW nStartRow)
Definition: dbfunc3.cxx:2279
#define SC_MOD()
Definition: scmod.hxx:250
bool HasSortParam() const
Definition: dbdata.cxx:535
void SetSaveData(const ScDPSaveData &rData)
Definition: dpobject.cxx:386
SC_DLLPUBLIC void SetAdvancedQuerySource(const ScRange *pSource)
Definition: dbdata.cxx:446
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
const OUString & GetName() const
Definition: dbdata.hxx:121
void GetImportParam(ScImportParam &rImportParam) const
Definition: dbdata.cxx:480
bool IsKeepFmt() const
Definition: dbdata.hxx:138
SC_DLLPUBLIC void ApplyPatternAreaTab(SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow, SCTAB nTab, const ScPatternAttr &rAttr)
Definition: document.cxx:4817
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:6450
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:5322
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:131
void CompileDBFormula()
Definition: documen4.cxx:557
SCCOL Col() const
Definition: address.hxx:266
void GetSubTotalParam(ScSubTotalParam &rSubTotalParam) const
Definition: dbdata.cxx:463
const char * ReloadCache(const ScDPObject *pDPObj, o3tl::sorted_vector< ScDPObject * > &rRefs)
Definition: dpobject.cxx:3370
ScDBData * findByUpperName(const OUString &rName)
Definition: dbdata.cxx:1167
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:647
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:235
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:1364
void erase(const iterator &itr)
Definition: dbdata.cxx:1203
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:3888
bool ValidRow(SCROW nRow) const
Definition: document.hxx:874
OUString ScResId(std::string_view aId)
Definition: scdll.cxx:89
bool bInplace
Definition: sortparam.hxx:55
void DoSubTotals(SCTAB nTab, const ScSubTotalParam &rParam, bool bRecord, bool bApi)
Definition: dbdocfun.cxx:1003
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:5049
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:2154
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:424
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:4468
NamedDBs & getNamedDBs()
Definition: dbdata.hxx:315
static bool isAnyEditViewInRange(const SfxViewShell *pForViewShell, bool bColumns, SCCOLROW nStart, SCCOLROW nEnd)
Definition: tabvwshc.cxx:535
void MoveToDest()
Definition: sortparam.cxx:225
iterator findByUpperName2(const OUString &rName)
Definition: dbdata.cxx:1174
void SetDocumentModified()
Definition: docsh.cxx:3159
void UpdateImport(const OUString &rTarget, const svx::ODataAccessDescriptor &rDescriptor)
Definition: dbdocfun.cxx:1692
void MoveToDest()
Definition: queryparam.cxx:398
void SetSubTotalParam(const ScSubTotalParam &rSubTotalParam)
Definition: dbdata.cxx:475
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:457
SCROW nDestRow
Definition: sortparam.hxx:58
bool IsUndoEnabled() const
Definition: document.hxx:1534
ScDocFunc & GetDocFunc()
Definition: docsh.hxx:218
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, bool bConsiderCellFormats=false) const
Shrink a range to only include used data area.
Definition: document.cxx:1062
ScTabViewShell * GetBestViewShell(bool bOnlyVisible=true)
Definition: docsh4.cxx:2574
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:1649
SC_DLLPUBLIC void DeleteAreaTab(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, SCTAB nTab, InsertDeleteFlags nDelFlag)
Definition: document.cxx:1929
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:3778
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:1446
SCTAB nDestTab
Definition: sortparam.hxx:56
typedef void(CALLTYPE *GetFuncDataPtr)(sal_uInt16 &nNo