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