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>
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
63using namespace ::com::sun::star;
64
65bool 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 )
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
118bool ScDBDocFunc::DeleteDBRange(const OUString& rName)
119{
120 bool bDone = false;
122 ScDBCollection* pDocColl = rDoc.GetDBCollection();
123 bool bUndo = rDoc.IsUndoEnabled();
124
125 ScDBCollection::NamedDBs& rDBs = pDocColl->getNamedDBs();
126 auto const iter = rDBs.findByUpperName2(ScGlobal::getCharClass().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
136 rDBs.erase(iter);
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
154bool ScDBDocFunc::RenameDBRange( const OUString& rOld, const OUString& rNew )
155{
156 bool bDone = false;
158 ScDBCollection* pDocColl = rDoc.GetDBCollection();
159 bool bUndo = rDoc.IsUndoEnabled();
160 ScDBCollection::NamedDBs& rDBs = pDocColl->getNamedDBs();
161 auto const iterOld = rDBs.findByUpperName2(ScGlobal::getCharClass().uppercase(rOld));
162 const ScDBData* pNew = rDBs.findByUpperName(ScGlobal::getCharClass().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
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
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
201void ScDBDocFunc::ModifyDBData( const ScDBData& rNewData )
202{
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
245void ScDBDocFunc::ModifyAllDBData( const ScDBCollection& rNewColl, const std::vector<ScRange>& rDelAreaList )
246{
247 ScDocShellModificator aModificator(rDocShell);
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
268 rDoc.SetDBCollection( std::unique_ptr<ScDBCollection>(new ScDBCollection( rNewColl )) );
270 pOldColl = nullptr;
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
283bool ScDBDocFunc::RepeatDB( const OUString& rDBName, bool bApi, bool bIsUnnamed, SCTAB aTab )
284{
286
287 bool bDone = false;
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::getCharClass().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
466bool ScDBDocFunc::Sort( SCTAB nTab, const ScSortParam& rSortParam,
467 bool bRecord, bool bPaint, bool bApi )
468{
469 ScDocShellModificator aModificator( rDocShell );
470
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 const ScInputOptions aInputOption = SC_MOD()->GetInputOptions();
526 const bool bUpdateRefs = aInputOption.GetSortRefUpdate();
527
528 // Adjust aLocalParam cols/rows to used data area. Keep sticky top row or
529 // column (depending on direction) in any case, not just if it has headers,
530 // so empty leading cells will be sorted to the end.
531 // aLocalParam.nCol/Row will encompass data content only, extras in
532 // aLocalParam.aDataAreaExtras.
533 bool bShrunk = false;
534 aLocalParam.aDataAreaExtras.resetArea();
535 rDoc.ShrinkToUsedDataArea(bShrunk, nTab, aLocalParam.nCol1, aLocalParam.nRow1,
536 aLocalParam.nCol2, aLocalParam.nRow2, false, aLocalParam.bByRow,
537 !aLocalParam.bByRow,
538 (aLocalParam.aDataAreaExtras.anyExtrasWanted() ?
539 &aLocalParam.aDataAreaExtras : nullptr));
540
541 SCROW nStartRow = aLocalParam.nRow1;
542 if (aLocalParam.bByRow && aLocalParam.bHasHeader && nStartRow < aLocalParam.nRow2)
543 ++nStartRow;
544
545 SCCOL nOverallCol1 = aLocalParam.nCol1;
546 SCROW nOverallRow1 = aLocalParam.nRow1;
547 SCCOL nOverallCol2 = aLocalParam.nCol2;
548 SCROW nOverallRow2 = aLocalParam.nRow2;
549 if (aLocalParam.aDataAreaExtras.anyExtrasWanted())
550 {
551 // Trailing empty excess columns/rows are excluded from being sorted,
552 // they stick at the end. Clip them.
553 const ScDataAreaExtras::Clip eClip = (aLocalParam.bByRow ?
555 aLocalParam.aDataAreaExtras.GetOverallRange( nOverallCol1, nOverallRow1, nOverallCol2, nOverallRow2, eClip);
556 // Make it permanent.
557 aLocalParam.aDataAreaExtras.SetOverallRange( nOverallCol1, nOverallRow1, nOverallCol2, nOverallRow2);
558
559 if (bUpdateRefs)
560 {
561 // With update references the entire range needs to be handled as
562 // one entity for references pointing within to be moved along,
563 // even when there's no data content. For huge ranges we may be
564 // DOOMed then.
565 aLocalParam.nCol1 = nOverallCol1;
566 aLocalParam.nRow1 = nOverallRow1;
567 aLocalParam.nCol2 = nOverallCol2;
568 aLocalParam.nRow2 = nOverallRow2;
569 }
570 }
571
572 if (aLocalParam.aDataAreaExtras.mbCellFormats
573 && rDoc.HasAttrib( nOverallCol1, nStartRow, nTab, nOverallCol2, nOverallRow2, nTab,
575 {
576 // Merge attributes would be mixed up during sorting.
577 if (!bApi)
578 rDocShell.ErrorMessage(STR_SORT_ERR_MERGED);
579 return false;
580 }
581
582 // execute
583
585
586 // Calculate the script types for all cells in the sort range beforehand.
587 // This will speed up the row height adjustment that takes place after the
588 // sort.
590 ScAddress(aLocalParam.nCol1,nStartRow,nTab),
591 aLocalParam.nCol2-aLocalParam.nCol1+1,
592 aLocalParam.nRow2-nStartRow+1);
593
594 // No point adjusting row heights after the sort when all rows have the same height.
595 bool bUniformRowHeight = rDoc.HasUniformRowHeight(nTab, nStartRow, nOverallRow2);
596
597 bool bRepeatQuery = false; // repeat existing filter?
598 ScQueryParam aQueryParam;
599 pDBData->GetQueryParam( aQueryParam );
600 if ( aQueryParam.GetEntry(0).bDoQuery )
601 bRepeatQuery = true;
602
603 sc::ReorderParam aUndoParam;
604
605 // don't call ScDocument::Sort with an empty SortParam (may be empty here if bCopy is set)
606 if (aLocalParam.GetSortKeyCount() && aLocalParam.maKeyState[0].bDoSort)
607 {
608 ScProgress aProgress(&rDocShell, ScResId(STR_PROGRESS_SORTING), 0, true);
609 if (!bRepeatQuery)
610 bRepeatQuery = rDoc.HasHiddenRows(aLocalParam.nRow1, aLocalParam.nRow2, nTab);
611 rDoc.Sort(nTab, aLocalParam, bRepeatQuery, bUpdateRefs, &aProgress, &aUndoParam);
612 }
613
614 if (bRecord)
615 {
616 // Set up an undo object.
618 std::make_unique<sc::UndoSort>(&rDocShell, aUndoParam));
619 }
620
621 pDBData->SetSortParam(rSortParam);
622 // Remember additional settings on anonymous database ranges.
623 if (pDBData == rDoc.GetAnonymousDBData( nTab) || rDoc.GetDBCollection()->getAnonDBs().has( pDBData))
624 pDBData->UpdateFromSortParam( rSortParam);
625
627 {
628 SfxViewShell* pSomeViewForThisDoc = rDocShell.GetBestViewShell(false);
629 SfxViewShell* pViewShell = SfxViewShell::GetFirst();
630 while (pViewShell)
631 {
632 ScTabViewShell* pTabViewShell = dynamic_cast<ScTabViewShell*>(pViewShell);
633 if (pTabViewShell && pTabViewShell->GetDocId() == pSomeViewForThisDoc->GetDocId())
634 {
635 if (ScPositionHelper* pPosHelper = pTabViewShell->GetViewData().GetLOKHeightHelper(nTab))
636 pPosHelper->invalidateByIndex(nStartRow);
637 }
638 pViewShell = SfxViewShell::GetNext(*pViewShell);
639 }
640
642 pSomeViewForThisDoc, false /* bColumns */, true /* bRows */, true /* bSizes*/,
643 true /* bHidden */, true /* bFiltered */, true /* bGroups */, nTab);
644 }
645
646 if (nStartRow <= aLocalParam.nRow2)
647 {
648 ScRange aDirtyRange(
649 aLocalParam.nCol1, nStartRow, nTab,
650 aLocalParam.nCol2, aLocalParam.nRow2, nTab);
651 rDoc.SetDirty( aDirtyRange, true );
652 }
653
654 if (bPaint)
655 {
657 SCCOL nStartX = nOverallCol1;
658 SCROW nStartY = nOverallRow1;
659 SCCOL nEndX = nOverallCol2;
660 SCROW nEndY = nOverallRow2;
661 if ( bRepeatQuery )
662 {
663 nPaint |= PaintPartFlags::Left;
664 nStartX = 0;
665 nEndX = rDoc.MaxCol();
666 }
667 rDocShell.PostPaint(ScRange(nStartX, nStartY, nTab, nEndX, nEndY, nTab), nPaint);
668 }
669
670 if (!bUniformRowHeight && nStartRow <= nOverallRow2)
671 rDocShell.AdjustRowHeight(nStartRow, nOverallRow2, nTab);
672
673 aModificator.SetDocumentModified();
674
675 return true;
676}
677
678bool ScDBDocFunc::Query( SCTAB nTab, const ScQueryParam& rQueryParam,
679 const ScRange* pAdvSource, bool bRecord, bool bApi )
680{
681 ScDocShellModificator aModificator( rDocShell );
682
684
686 if (pViewSh && ScTabViewShell::isAnyEditViewInRange(pViewSh, /*bColumns*/ false, rQueryParam.nRow1, rQueryParam.nRow2))
687 {
688 return false;
689 }
690
691 if (bRecord && !rDoc.IsUndoEnabled())
692 bRecord = false;
693 ScDBData* pDBData = rDoc.GetDBAtArea( nTab, rQueryParam.nCol1, rQueryParam.nRow1,
694 rQueryParam.nCol2, rQueryParam.nRow2 );
695 if (!pDBData)
696 {
697 OSL_FAIL( "Query: no DBData" );
698 return false;
699 }
700
701 // Change from Inplace to non-Inplace, only then cancel Inplace:
702 // (only if "Persistent" is selected in the dialog)
703
704 if ( !rQueryParam.bInplace && pDBData->HasQueryParam() && rQueryParam.bDestPers )
705 {
706 ScQueryParam aOldQuery;
707 pDBData->GetQueryParam(aOldQuery);
708 if (aOldQuery.bInplace)
709 {
710 // cancel old filtering
711
712 SCSIZE nEC = aOldQuery.GetEntryCount();
713 for (SCSIZE i=0; i<nEC; i++)
714 aOldQuery.GetEntry(i).bDoQuery = false;
715 aOldQuery.bDuplicate = true;
716 Query( nTab, aOldQuery, nullptr, bRecord, bApi );
717 }
718 }
719
720 ScQueryParam aLocalParam( rQueryParam ); // for Paint / destination range
721 bool bCopy = !rQueryParam.bInplace; // copied in Table::Query
722 ScDBData* pDestData = nullptr; // range to be copied to
723 bool bDoSize = false; // adjust destination size (insert/delete)
724 SCCOL nFormulaCols = 0; // only at bDoSize
725 bool bKeepFmt = false;
726 ScRange aOldDest;
727 ScRange aDestTotal;
728 if ( bCopy && rQueryParam.nDestCol == rQueryParam.nCol1 &&
729 rQueryParam.nDestRow == rQueryParam.nRow1 && rQueryParam.nDestTab == nTab )
730 bCopy = false;
731 SCTAB nDestTab = nTab;
732 if ( bCopy )
733 {
734 aLocalParam.MoveToDest();
735 nDestTab = rQueryParam.nDestTab;
736 if ( !rDoc.ValidColRow( aLocalParam.nCol2, aLocalParam.nRow2 ) )
737 {
738 if (!bApi)
739 rDocShell.ErrorMessage(STR_PASTE_FULL);
740 return false;
741 }
742
743 ScEditableTester aTester( rDoc, nDestTab, aLocalParam.nCol1,aLocalParam.nRow1,
744 aLocalParam.nCol2,aLocalParam.nRow2);
745 if (!aTester.IsEditable())
746 {
747 if (!bApi)
749 return false;
750 }
751
752 pDestData = rDoc.GetDBAtCursor( rQueryParam.nDestCol, rQueryParam.nDestRow,
753 rQueryParam.nDestTab, ScDBDataPortion::TOP_LEFT );
754 if (pDestData)
755 {
756 pDestData->GetArea( aOldDest );
757 aDestTotal=ScRange( rQueryParam.nDestCol,
758 rQueryParam.nDestRow,
759 nDestTab,
760 rQueryParam.nDestCol + rQueryParam.nCol2 - rQueryParam.nCol1,
761 rQueryParam.nDestRow + rQueryParam.nRow2 - rQueryParam.nRow1,
762 nDestTab );
763
764 bDoSize = pDestData->IsDoSize();
765 // test if formulas need to be filled in (nFormulaCols):
766 if ( bDoSize && aOldDest.aEnd.Col() == aDestTotal.aEnd.Col() )
767 {
768 SCCOL nTestCol = aOldDest.aEnd.Col() + 1; // next to the range
769 SCROW nTestRow = rQueryParam.nDestRow +
770 ( aLocalParam.bHasHeader ? 1 : 0 );
771 while ( nTestCol <= rDoc.MaxCol() &&
772 rDoc.GetCellType(ScAddress( nTestCol, nTestRow, nTab )) == CELLTYPE_FORMULA )
773 {
774 ++nTestCol;
775 ++nFormulaCols;
776 }
777 }
778
779 bKeepFmt = pDestData->IsKeepFmt();
780 if ( bDoSize && !rDoc.CanFitBlock( aOldDest, aDestTotal ) )
781 {
782 if (!bApi)
783 rDocShell.ErrorMessage(STR_MSSG_DOSUBTOTALS_2); // cannot insert rows
784 return false;
785 }
786 }
787 }
788
789 // execute
790
792
793 bool bKeepSub = false; // repeat existing partial results?
794 if (rQueryParam.GetEntry(0).bDoQuery) // not at cancellation
795 {
796 ScSubTotalParam aSubTotalParam;
797 pDBData->GetSubTotalParam( aSubTotalParam ); // partial results exist?
798
799 if ( aSubTotalParam.bGroupActive[0] && !aSubTotalParam.bRemoveOnly )
800 bKeepSub = true;
801 }
802
803 ScDocumentUniquePtr pUndoDoc;
804 std::unique_ptr<ScDBCollection> pUndoDB;
805 const ScRange* pOld = nullptr;
806
807 if ( bRecord )
808 {
809 pUndoDoc.reset(new ScDocument( SCDOCMODE_UNDO ));
810 if (bCopy)
811 {
812 pUndoDoc->InitUndo( rDoc, nDestTab, nDestTab, false, true );
813 rDoc.CopyToDocument(aLocalParam.nCol1, aLocalParam.nRow1, nDestTab,
814 aLocalParam.nCol2, aLocalParam.nRow2, nDestTab,
815 InsertDeleteFlags::ALL, false, *pUndoDoc);
816 // secure attributes in case they were copied along
817
818 if (pDestData)
819 {
820 rDoc.CopyToDocument(aOldDest, InsertDeleteFlags::ALL, false, *pUndoDoc);
821 pOld = &aOldDest;
822 }
823 }
824 else
825 {
826 pUndoDoc->InitUndo( rDoc, nTab, nTab, false, true );
827 rDoc.CopyToDocument(0, rQueryParam.nRow1, nTab, rDoc.MaxCol(), rQueryParam.nRow2, nTab,
828 InsertDeleteFlags::NONE, false, *pUndoDoc);
829 }
830
831 ScDBCollection* pDocDB = rDoc.GetDBCollection();
832 if (!pDocDB->empty())
833 pUndoDB.reset(new ScDBCollection( *pDocDB ));
834
835 rDoc.BeginDrawUndo();
836 }
837
838 std::unique_ptr<ScDocument> pAttribDoc;
839 ScRange aAttribRange;
840 if (pDestData) // delete destination range
841 {
842 if ( bKeepFmt )
843 {
844 // smaller of the end columns, header+1 row
845 aAttribRange = aOldDest;
846 if ( aAttribRange.aEnd.Col() > aDestTotal.aEnd.Col() )
847 aAttribRange.aEnd.SetCol( aDestTotal.aEnd.Col() );
848 aAttribRange.aEnd.SetRow( aAttribRange.aStart.Row() +
849 ( aLocalParam.bHasHeader ? 1 : 0 ) );
850
851 // also for filled-in formulas
852 aAttribRange.aEnd.SetCol( aAttribRange.aEnd.Col() + nFormulaCols );
853
854 pAttribDoc.reset(new ScDocument( SCDOCMODE_UNDO ));
855 pAttribDoc->InitUndo( rDoc, nDestTab, nDestTab, false, true );
856 rDoc.CopyToDocument(aAttribRange, InsertDeleteFlags::ATTRIB, false, *pAttribDoc);
857 }
858
859 if ( bDoSize )
860 rDoc.FitBlock( aOldDest, aDestTotal );
861 else
862 rDoc.DeleteAreaTab(aOldDest, InsertDeleteFlags::ALL); // simply delete
863 }
864
865 // execute filtering on the document
866 SCSIZE nCount = rDoc.Query( nTab, rQueryParam, bKeepSub );
867 pDBData->CalcSaveFilteredCount( nCount );
868 if (bCopy)
869 {
870 aLocalParam.nRow2 = aLocalParam.nRow1 + nCount;
871 if (!aLocalParam.bHasHeader && nCount > 0)
872 --aLocalParam.nRow2;
873
874 if ( bDoSize )
875 {
876 // adjust to the real result range
877 // (this here is always a reduction)
878
879 ScRange aNewDest( aLocalParam.nCol1, aLocalParam.nRow1, nDestTab,
880 aLocalParam.nCol2, aLocalParam.nRow2, nDestTab );
881 rDoc.FitBlock( aDestTotal, aNewDest, false ); // sal_False - don't delete
882
883 if ( nFormulaCols > 0 )
884 {
885 // fill in formulas
887
888 ScRange aNewForm( aLocalParam.nCol2+1, aLocalParam.nRow1, nDestTab,
889 aLocalParam.nCol2+nFormulaCols, aLocalParam.nRow2, nDestTab );
890 ScRange aOldForm = aNewForm;
891 aOldForm.aEnd.SetRow( aOldDest.aEnd.Row() );
892 rDoc.FitBlock( aOldForm, aNewForm, false );
893
894 ScMarkData aMark(rDoc.GetSheetLimits());
895 aMark.SelectOneTable(nDestTab);
896 SCROW nFStartY = aLocalParam.nRow1 + ( aLocalParam.bHasHeader ? 1 : 0 );
897
898 sal_uLong nProgCount = nFormulaCols;
899 nProgCount *= aLocalParam.nRow2 - nFStartY;
900 ScProgress aProgress( rDoc.GetDocumentShell(),
901 ScResId(STR_FILL_SERIES_PROGRESS), nProgCount, true );
902
903 rDoc.Fill( aLocalParam.nCol2+1, nFStartY,
904 aLocalParam.nCol2+nFormulaCols, nFStartY, &aProgress, aMark,
905 aLocalParam.nRow2 - nFStartY,
907 }
908 }
909
910 if ( pAttribDoc ) // copy back the memorized attributes
911 {
912 // Header
913 if (aLocalParam.bHasHeader)
914 {
915 ScRange aHdrRange = aAttribRange;
916 aHdrRange.aEnd.SetRow( aHdrRange.aStart.Row() );
917 pAttribDoc->CopyToDocument(aHdrRange, InsertDeleteFlags::ATTRIB, false, rDoc);
918 }
919
920 // Data
921 SCCOL nAttrEndCol = aAttribRange.aEnd.Col();
922 SCROW nAttrRow = aAttribRange.aStart.Row() + ( aLocalParam.bHasHeader ? 1 : 0 );
923 for (SCCOL nCol = aAttribRange.aStart.Col(); nCol<=nAttrEndCol; nCol++)
924 {
925 const ScPatternAttr* pSrcPattern = pAttribDoc->GetPattern(
926 nCol, nAttrRow, nDestTab );
927 OSL_ENSURE(pSrcPattern,"Pattern is 0");
928 if (pSrcPattern)
929 {
930 rDoc.ApplyPatternAreaTab( nCol, nAttrRow, nCol, aLocalParam.nRow2,
931 nDestTab, *pSrcPattern );
932 const ScStyleSheet* pStyle = pSrcPattern->GetStyleSheet();
933 if (pStyle)
934 rDoc.ApplyStyleAreaTab( nCol, nAttrRow, nCol, aLocalParam.nRow2,
935 nDestTab, *pStyle );
936 }
937 }
938 }
939 }
940
941 // saving: Inplace always, otherwise depending on setting
942 // old Inplace-Filter may have already been removed
943
944 bool bSave = rQueryParam.bInplace || rQueryParam.bDestPers;
945 if (bSave) // memorize
946 {
947 pDBData->SetQueryParam( rQueryParam );
948 pDBData->SetHeader( rQueryParam.bHasHeader );
949 pDBData->SetAdvancedQuerySource( pAdvSource ); // after SetQueryParam
950 }
951
952 if (bCopy) // memorize new DB range
953 {
954 // Selection is done afterwards from outside (dbfunc).
955 // Currently through the DB area at the destination position,
956 // so a range must be created there in any case.
957
958 ScDBData* pNewData;
959 if (pDestData)
960 pNewData = pDestData; // range exists -> adjust (always!)
961 else // create range
962 pNewData = rDocShell.GetDBData(
963 ScRange( aLocalParam.nCol1, aLocalParam.nRow1, nDestTab,
964 aLocalParam.nCol2, aLocalParam.nRow2, nDestTab ),
966
967 if (pNewData)
968 {
969 pNewData->SetArea( nDestTab, aLocalParam.nCol1, aLocalParam.nRow1,
970 aLocalParam.nCol2, aLocalParam.nRow2 );
971
972 // query parameter is no longer set at the destination, only leads to confusion
973 // and mistakes with the query parameter at the source range (#37187#)
974 }
975 else
976 {
977 OSL_FAIL("Target are not available");
978 }
979 }
980
981 if (!bCopy)
982 {
983 rDoc.InvalidatePageBreaks(nTab);
984 rDoc.UpdatePageBreaks( nTab );
985 }
986
987 // #i23299# Subtotal functions depend on cell's filtered states.
988 ScRange aDirtyRange(0 , aLocalParam.nRow1, nDestTab, rDoc.MaxCol(), aLocalParam.nRow2, nDestTab);
989 rDoc.SetSubTotalCellsDirty(aDirtyRange);
990
991 if ( bRecord )
992 {
993 // create undo action after executing, because of drawing layer undo
995 std::make_unique<ScUndoQuery>( &rDocShell, nTab, rQueryParam, std::move(pUndoDoc), std::move(pUndoDB),
996 pOld, bDoSize, pAdvSource ) );
997 }
998
999 if ( pViewSh )
1000 {
1001 // could there be horizontal autofilter ?
1002 // maybe it would be better to set bColumns to !rQueryParam.bByRow ?
1003 // anyway at the beginning the value of bByRow is 'false'
1004 // then after the first sort action it becomes 'true'
1005 pViewSh->OnLOKShowHideColRow(/*bColumns*/ false, rQueryParam.nRow1 - 1);
1006 }
1007
1008 if (bCopy)
1009 {
1010 SCCOL nEndX = aLocalParam.nCol2;
1011 SCROW nEndY = aLocalParam.nRow2;
1012 if (pDestData)
1013 {
1014 if ( aOldDest.aEnd.Col() > nEndX )
1015 nEndX = aOldDest.aEnd.Col();
1016 if ( aOldDest.aEnd.Row() > nEndY )
1017 nEndY = aOldDest.aEnd.Row();
1018 }
1019 if (bDoSize)
1020 nEndY = rDoc.MaxRow();
1021
1022 // remove AutoFilter button flags
1023 rDocShell.DBAreaDeleted(nDestTab, aLocalParam.nCol1, aLocalParam.nRow1, aLocalParam.nCol2);
1024
1026 ScRange(aLocalParam.nCol1, aLocalParam.nRow1, nDestTab, nEndX, nEndY, nDestTab),
1028 }
1029 else
1031 ScRange(0, rQueryParam.nRow1, nTab, rDoc.MaxCol(), rDoc.MaxRow(), nTab),
1033 aModificator.SetDocumentModified();
1034
1035 return true;
1036}
1037
1039 bool bRecord, bool bApi )
1040{
1042 // then stays outside:
1043 // - mark new range (from DBData)
1044 // - SelectionChanged (?)
1045
1046 bool bDo = !rParam.bRemoveOnly; // sal_False = only delete
1047
1049 if (bRecord && !rDoc.IsUndoEnabled())
1050 bRecord = false;
1051 ScDBData* pDBData = rDoc.GetDBAtArea( nTab, rParam.nCol1, rParam.nRow1,
1052 rParam.nCol2, rParam.nRow2 );
1053 if (!pDBData)
1054 {
1055 OSL_FAIL( "SubTotals: no DBData" );
1056 return;
1057 }
1058
1059 ScEditableTester aTester( rDoc, nTab, 0,rParam.nRow1+1, rDoc.MaxCol(),rDoc.MaxRow() );
1060 if (!aTester.IsEditable())
1061 {
1062 if (!bApi)
1064 return;
1065 }
1066
1067 if (rDoc.HasAttrib( rParam.nCol1, rParam.nRow1+1, nTab,
1068 rParam.nCol2, rParam.nRow2, nTab, HasAttrFlags::Merged | HasAttrFlags::Overlapped ))
1069 {
1070 if (!bApi)
1071 rDocShell.ErrorMessage(STR_MSSG_INSERTCELLS_0); // don't insert into merged
1072 return;
1073 }
1074
1075 bool bOk = true;
1076 if (rParam.bReplace)
1077 {
1078 if (rDoc.TestRemoveSubTotals( nTab, rParam ))
1079 {
1080 std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(ScDocShell::GetActiveDialogParent(),
1081 VclMessageType::Question,
1082 VclButtonsType::YesNo, ScResId(STR_MSSG_DOSUBTOTALS_1))); // "Delete Data?"
1083 xBox->set_title(ScResId(STR_MSSG_DOSUBTOTALS_0)); // "StarCalc"
1084 bOk = xBox->run() == RET_YES;
1085 }
1086 }
1087
1088 if (!bOk)
1089 return;
1090
1092 ScDocShellModificator aModificator( rDocShell );
1093
1094 ScSubTotalParam aNewParam( rParam ); // end of range is being changed
1095 ScDocumentUniquePtr pUndoDoc;
1096 std::unique_ptr<ScOutlineTable> pUndoTab;
1097 std::unique_ptr<ScRangeName> pUndoRange;
1098 std::unique_ptr<ScDBCollection> pUndoDB;
1099
1100 if (bRecord) // secure old data
1101 {
1102 bool bOldFilter = bDo && rParam.bDoSort;
1103
1104 SCTAB nTabCount = rDoc.GetTableCount();
1105 pUndoDoc.reset(new ScDocument( SCDOCMODE_UNDO ));
1106 ScOutlineTable* pTable = rDoc.GetOutlineTable( nTab );
1107 if (pTable)
1108 {
1109 pUndoTab.reset(new ScOutlineTable( *pTable ));
1110
1111 // column/row state
1112 SCCOLROW nOutStartCol, nOutEndCol;
1113 SCCOLROW nOutStartRow, nOutEndRow;
1114 pTable->GetColArray().GetRange( nOutStartCol, nOutEndCol );
1115 pTable->GetRowArray().GetRange( nOutStartRow, nOutEndRow );
1116
1117 pUndoDoc->InitUndo( rDoc, nTab, nTab, true, true );
1118 rDoc.CopyToDocument(static_cast<SCCOL>(nOutStartCol), 0, nTab, static_cast<SCCOL>(nOutEndCol), rDoc.MaxRow(), nTab, InsertDeleteFlags::NONE, false, *pUndoDoc);
1119 rDoc.CopyToDocument(0, nOutStartRow, nTab, rDoc.MaxCol(), nOutEndRow, nTab, InsertDeleteFlags::NONE, false, *pUndoDoc);
1120 }
1121 else
1122 pUndoDoc->InitUndo( rDoc, nTab, nTab, false, bOldFilter );
1123
1124 // secure data range - incl. filtering result
1125 rDoc.CopyToDocument(0, rParam.nRow1+1,nTab, rDoc.MaxCol(),rParam.nRow2,nTab,
1126 InsertDeleteFlags::ALL, false, *pUndoDoc);
1127
1128 // all formulas because of references
1129 rDoc.CopyToDocument(0, 0, 0, rDoc.MaxCol(),rDoc.MaxRow(),nTabCount-1,
1130 InsertDeleteFlags::FORMULA, false, *pUndoDoc);
1131
1132 // ranges of DB and other
1133 ScRangeName* pDocRange = rDoc.GetRangeName();
1134 if (!pDocRange->empty())
1135 pUndoRange.reset(new ScRangeName( *pDocRange ));
1136 ScDBCollection* pDocDB = rDoc.GetDBCollection();
1137 if (!pDocDB->empty())
1138 pUndoDB.reset(new ScDBCollection( *pDocDB ));
1139 }
1140
1141// rDoc.SetOutlineTable( nTab, NULL );
1142 ScOutlineTable* pOut = rDoc.GetOutlineTable( nTab );
1143 if (pOut)
1144 pOut->GetRowArray().RemoveAll(); // only delete row outlines
1145
1146 if (rParam.bReplace)
1147 rDoc.RemoveSubTotals( nTab, aNewParam );
1148 bool bSuccess = true;
1149 if (bDo)
1150 {
1151 // sort
1152 if ( rParam.bDoSort )
1153 {
1154 pDBData->SetArea( nTab, aNewParam.nCol1,aNewParam.nRow1, aNewParam.nCol2,aNewParam.nRow2 );
1155
1156 // set partial result field to before the sorting
1157 // (Duplicates are omitted, so can be called again)
1158
1159 ScSortParam aOldSort;
1160 pDBData->GetSortParam( aOldSort );
1161 ScSortParam aSortParam( aNewParam, aOldSort );
1162 Sort( nTab, aSortParam, false, false, bApi );
1163 }
1164
1165 bSuccess = rDoc.DoSubTotals( nTab, aNewParam );
1166 rDoc.SetDrawPageSize(nTab);
1167 }
1168 ScRange aDirtyRange( aNewParam.nCol1, aNewParam.nRow1, nTab,
1169 aNewParam.nCol2, aNewParam.nRow2, nTab );
1170 rDoc.SetDirty( aDirtyRange, true );
1171
1172 if (bRecord)
1173 {
1174// ScDBData* pUndoDBData = pDBData ? new ScDBData( *pDBData ) : NULL;
1176 std::make_unique<ScUndoSubTotals>( &rDocShell, nTab,
1177 rParam, aNewParam.nRow2,
1178 std::move(pUndoDoc), std::move(pUndoTab), // pUndoDBData,
1179 std::move(pUndoRange), std::move(pUndoDB) ) );
1180 }
1181
1182 if (!bSuccess)
1183 {
1184 // "Cannot insert rows"
1185 if (!bApi)
1186 rDocShell.ErrorMessage(STR_MSSG_DOSUBTOTALS_2);
1187 }
1188
1189 // memorize
1190 pDBData->SetSubTotalParam( aNewParam );
1191 pDBData->SetArea( nTab, aNewParam.nCol1,aNewParam.nRow1, aNewParam.nCol2,aNewParam.nRow2 );
1192 rDoc.CompileDBFormula();
1193
1194 rDocShell.PostPaint(ScRange(0, 0, nTab, rDoc.MaxCol(),rDoc.MaxRow(),nTab),
1196 aModificator.SetDocumentModified();
1197}
1198
1199namespace {
1200
1201bool lcl_EmptyExcept( ScDocument& rDoc, const ScRange& rRange, const ScRange& rExcept )
1202{
1203 ScCellIterator aIter( rDoc, rRange );
1204 for (bool bHasCell = aIter.first(); bHasCell; bHasCell = aIter.next())
1205 {
1206 if (!aIter.isEmpty()) // real content?
1207 {
1208 if (!rExcept.Contains(aIter.GetPos()))
1209 return false; // cell found
1210 }
1211 }
1212
1213 return true; // nothing found - empty
1214}
1215
1216bool isEditable(ScDocShell& rDocShell, const ScRangeList& rRanges, bool bApi)
1217{
1218 ScDocument& rDoc = rDocShell.GetDocument();
1219 if (!rDocShell.IsEditable() || rDoc.GetChangeTrack())
1220 {
1221 // not recorded -> disallow
1222 if (!bApi)
1223 rDocShell.ErrorMessage(STR_PROTECTIONERR);
1224
1225 return false;
1226 }
1227
1228 for (size_t i = 0, n = rRanges.size(); i < n; ++i)
1229 {
1230 const ScRange & r = rRanges[i];
1231 ScEditableTester aTester(rDoc, r);
1232 if (!aTester.IsEditable())
1233 {
1234 if (!bApi)
1235 rDocShell.ErrorMessage(aTester.GetMessageId());
1236
1237 return false;
1238 }
1239 }
1240
1241 return true;
1242}
1243
1244void createUndoDoc(ScDocumentUniquePtr& pUndoDoc, ScDocument& rDoc, const ScRange& rRange)
1245{
1246 SCTAB nTab = rRange.aStart.Tab();
1247 pUndoDoc.reset(new ScDocument(SCDOCMODE_UNDO));
1248 pUndoDoc->InitUndo(rDoc, nTab, nTab);
1249 rDoc.CopyToDocument(rRange, InsertDeleteFlags::ALL, false, *pUndoDoc);
1250}
1251
1252bool checkNewOutputRange(ScDPObject& rDPObj, ScDocShell& rDocShell, ScRange& rNewOut, bool bApi)
1253{
1254 ScDocument& rDoc = rDocShell.GetDocument();
1255
1256 bool bOverflow = false;
1257 rNewOut = rDPObj.GetNewOutputRange(bOverflow);
1258
1259 // Test for overlap with source data range.
1260 // TODO: Check with other pivot tables as well.
1261 const ScSheetSourceDesc* pSheetDesc = rDPObj.GetSheetDesc();
1262 if (pSheetDesc && pSheetDesc->GetSourceRange().Intersects(rNewOut))
1263 {
1264 // New output range intersteps with the source data. Move it up to
1265 // where the old range is and see if that works.
1266 ScRange aOldRange = rDPObj.GetOutRange();
1267 SCROW nDiff = aOldRange.aStart.Row() - rNewOut.aStart.Row();
1268 rNewOut.aStart.SetRow(aOldRange.aStart.Row());
1269 rNewOut.aEnd.IncRow(nDiff);
1270 if (!rDoc.ValidRow(rNewOut.aStart.Row()) || !rDoc.ValidRow(rNewOut.aEnd.Row()))
1271 bOverflow = true;
1272 }
1273
1274 if (bOverflow)
1275 {
1276 if (!bApi)
1277 rDocShell.ErrorMessage(STR_PIVOT_ERROR);
1278
1279 return false;
1280 }
1281
1282 ScEditableTester aTester(rDoc, rNewOut);
1283 if (!aTester.IsEditable())
1284 {
1285 // destination area isn't editable
1286 if (!bApi)
1287 rDocShell.ErrorMessage(aTester.GetMessageId());
1288
1289 return false;
1290 }
1291
1292 return true;
1293}
1294
1295}
1296
1298 bool bRecord, bool bApi, bool bAllowMove )
1299{
1300 if (!pOldObj)
1301 {
1302 if (!pNewObj)
1303 return false;
1304
1305 return CreatePivotTable(*pNewObj, bRecord, bApi);
1306 }
1307
1308 if (!pNewObj)
1309 return RemovePivotTable(*pOldObj, bRecord, bApi);
1310
1311 if (pOldObj == pNewObj)
1312 return UpdatePivotTable(*pOldObj, bRecord, bApi);
1313
1314 OSL_ASSERT(pOldObj && pNewObj && pOldObj != pNewObj);
1315
1316 ScDocShellModificator aModificator( rDocShell );
1318
1319 ScRangeList aRanges;
1320 aRanges.push_back(pOldObj->GetOutRange());
1321 aRanges.push_back(pNewObj->GetOutRange().aStart); // at least one cell in the output position must be editable.
1322 if (!isEditable(rDocShell, aRanges, bApi))
1323 return false;
1324
1325 ScDocumentUniquePtr pOldUndoDoc;
1326 ScDocumentUniquePtr pNewUndoDoc;
1327
1328 ScDPObject aUndoDPObj(*pOldObj); // for undo or revert on failure
1329
1331 if (bRecord && !rDoc.IsUndoEnabled())
1332 bRecord = false;
1333
1334 if (bRecord)
1335 createUndoDoc(pOldUndoDoc, rDoc, pOldObj->GetOutRange());
1336
1337 pNewObj->WriteSourceDataTo(*pOldObj); // copy source data
1338
1339 ScDPSaveData* pData = pNewObj->GetSaveData();
1340 OSL_ENSURE( pData, "no SaveData from living DPObject" );
1341 if (pData)
1342 pOldObj->SetSaveData(*pData); // copy SaveData
1343
1344 pOldObj->SetAllowMove(bAllowMove);
1345 pOldObj->ReloadGroupTableData();
1346 pOldObj->SyncAllDimensionMembers();
1347 pOldObj->InvalidateData(); // before getting the new output area
1348
1349 // make sure the table has a name (not set by dialog)
1350 if (pOldObj->GetName().isEmpty())
1351 pOldObj->SetName( rDoc.GetDPCollection()->CreateNewName() );
1352
1353 ScRange aNewOut;
1354 if (!checkNewOutputRange(*pOldObj, rDocShell, aNewOut, bApi))
1355 {
1356 *pOldObj = aUndoDPObj;
1357 return false;
1358 }
1359
1360 // test if new output area is empty except for old area
1361 if (!bApi)
1362 {
1363 // OutRange of pOldObj (pDestObj) is still old area
1364 if (!lcl_EmptyExcept(rDoc, aNewOut, pOldObj->GetOutRange()))
1365 {
1366 std::unique_ptr<weld::MessageDialog> xQueryBox(Application::CreateMessageDialog(ScDocShell::GetActiveDialogParent(),
1367 VclMessageType::Question, VclButtonsType::YesNo,
1368 ScResId(STR_PIVOT_NOTEMPTY)));
1369 xQueryBox->set_default_response(RET_YES);
1370 if (xQueryBox->run() == RET_NO)
1371 {
1373 *pOldObj = aUndoDPObj;
1374 return false;
1375 }
1376 }
1377 }
1378
1379 if (bRecord)
1380 createUndoDoc(pNewUndoDoc, rDoc, aNewOut);
1381
1382 pOldObj->Output(aNewOut.aStart);
1384
1385 if (bRecord)
1386 {
1388 std::make_unique<ScUndoDataPilot>(
1389 &rDocShell, std::move(pOldUndoDoc), std::move(pNewUndoDoc), &aUndoDPObj, pOldObj, bAllowMove));
1390 }
1391
1392 // notify API objects
1393 rDoc.BroadcastUno( ScDataPilotModifiedHint(pOldObj->GetName()) );
1394 aModificator.SetDocumentModified();
1395
1396 return true;
1397}
1398
1399bool ScDBDocFunc::RemovePivotTable(const ScDPObject& rDPObj, bool bRecord, bool bApi)
1400{
1401 ScDocShellModificator aModificator(rDocShell);
1403
1404 if (!isEditable(rDocShell, rDPObj.GetOutRange(), bApi))
1405 return false;
1406
1408
1409 if (!bApi)
1410 {
1411 // If we come from GUI - ask to delete the associated pivot charts too...
1412 std::vector<SdrOle2Obj*> aListOfObjects =
1414
1415 ScDrawLayer* pModel = rDoc.GetDrawLayer();
1416
1417 if (pModel && !aListOfObjects.empty())
1418 {
1419 std::unique_ptr<weld::MessageDialog> xQueryBox(Application::CreateMessageDialog(ScDocShell::GetActiveDialogParent(),
1420 VclMessageType::Question, VclButtonsType::YesNo,
1421 ScResId(STR_PIVOT_REMOVE_PIVOTCHART)));
1422 xQueryBox->set_default_response(RET_YES);
1423 if (xQueryBox->run() == RET_NO)
1424 {
1425 return false;
1426 }
1427 else
1428 {
1429 for (SdrOle2Obj* pChartObject : aListOfObjects)
1430 {
1431 rDoc.GetChartListenerCollection()->removeByName(pChartObject->GetName());
1432 pModel->AddUndo(std::make_unique<SdrUndoDelObj>(*pChartObject));
1433 pChartObject->getSdrPageFromSdrObject()->RemoveObject(pChartObject->GetOrdNum());
1434 }
1435 }
1436 }
1437 }
1438
1439 ScDocumentUniquePtr pOldUndoDoc;
1440 std::unique_ptr<ScDPObject> pUndoDPObj;
1441
1442 if (bRecord)
1443 pUndoDPObj.reset(new ScDPObject(rDPObj)); // copy old settings for undo
1444
1445 if (bRecord && !rDoc.IsUndoEnabled())
1446 bRecord = false;
1447
1448 // delete table
1449
1450 ScRange aRange = rDPObj.GetOutRange();
1451 SCTAB nTab = aRange.aStart.Tab();
1452
1453 if (bRecord)
1454 createUndoDoc(pOldUndoDoc, rDoc, aRange);
1455
1456 rDoc.DeleteAreaTab( aRange.aStart.Col(), aRange.aStart.Row(),
1457 aRange.aEnd.Col(), aRange.aEnd.Row(),
1458 nTab, InsertDeleteFlags::ALL );
1459 rDoc.RemoveFlagsTab( aRange.aStart.Col(), aRange.aStart.Row(),
1460 aRange.aEnd.Col(), aRange.aEnd.Row(),
1461 nTab, ScMF::Auto );
1462
1463 rDoc.GetDPCollection()->FreeTable(&rDPObj); // object is deleted here
1464
1467
1468 if (bRecord)
1469 {
1471 std::make_unique<ScUndoDataPilot>(
1472 &rDocShell, std::move(pOldUndoDoc), nullptr, pUndoDPObj.get(), nullptr, false));
1473
1474 // pUndoDPObj is copied
1475 }
1476
1477 aModificator.SetDocumentModified();
1478 return true;
1479}
1480
1481bool ScDBDocFunc::CreatePivotTable(const ScDPObject& rDPObj, bool bRecord, bool bApi)
1482{
1483 ScDocShellModificator aModificator(rDocShell);
1485
1486 // At least one cell in the output range should be editable. Check in advance.
1487 if (!isEditable(rDocShell, ScRange(rDPObj.GetOutRange().aStart), bApi))
1488 return false;
1489
1490 ScDocumentUniquePtr pNewUndoDoc;
1491
1493 if (bRecord && !rDoc.IsUndoEnabled())
1494 bRecord = false;
1495
1496 // output range must be set at pNewObj
1497 std::unique_ptr<ScDPObject> pDestObj(new ScDPObject(rDPObj));
1498
1499 ScDPObject& rDestObj = *pDestObj;
1500
1501 // #i94570# When changing the output position in the dialog, a new table is created
1502 // with the settings from the old table, including the name.
1503 // So we have to check for duplicate names here (before inserting).
1504 if (rDoc.GetDPCollection()->GetByName(rDestObj.GetName()))
1505 rDestObj.SetName(OUString()); // ignore the invalid name, create a new name below
1506
1507 // Synchronize groups between linked tables
1508 {
1509 const ScDPDimensionSaveData* pGroups = nullptr;
1510 bool bRefFound = rDoc.GetDPCollection()->GetReferenceGroups(rDestObj, &pGroups);
1511 if (bRefFound)
1512 {
1513 ScDPSaveData* pSaveData = rDestObj.GetSaveData();
1514 if (pSaveData)
1515 pSaveData->SetDimensionData(pGroups);
1516 }
1517 }
1518
1519 rDoc.GetDPCollection()->InsertNewTable(std::move(pDestObj));
1520
1521 rDestObj.ReloadGroupTableData();
1522 rDestObj.SyncAllDimensionMembers();
1523 rDestObj.InvalidateData(); // before getting the new output area
1524
1525 // make sure the table has a name (not set by dialog)
1526 if (rDestObj.GetName().isEmpty())
1527 rDestObj.SetName(rDoc.GetDPCollection()->CreateNewName());
1528
1529 bool bOverflow = false;
1530 ScRange aNewOut = rDestObj.GetNewOutputRange(bOverflow);
1531
1532 if (bOverflow)
1533 {
1534 if (!bApi)
1535 rDocShell.ErrorMessage(STR_PIVOT_ERROR);
1536
1537 return false;
1538 }
1539
1540 {
1541 ScEditableTester aTester(rDoc, aNewOut);
1542 if (!aTester.IsEditable())
1543 {
1544 // destination area isn't editable
1545 if (!bApi)
1547
1548 return false;
1549 }
1550 }
1551
1552 // test if new output area is empty except for old area
1553 if (!bApi)
1554 {
1555 bool bEmpty = rDoc.IsBlockEmpty(
1556 aNewOut.aStart.Col(), aNewOut.aStart.Row(),
1557 aNewOut.aEnd.Col(), aNewOut.aEnd.Row(), aNewOut.aStart.Tab() );
1558
1559 if (!bEmpty)
1560 {
1561 std::unique_ptr<weld::MessageDialog> xQueryBox(Application::CreateMessageDialog(ScDocShell::GetActiveDialogParent(),
1562 VclMessageType::Question, VclButtonsType::YesNo,
1563 ScResId(STR_PIVOT_NOTEMPTY)));
1564 xQueryBox->set_default_response(RET_YES);
1565 if (xQueryBox->run() == RET_NO)
1566 {
1568 return false;
1569 }
1570 }
1571 }
1572
1573 if (bRecord)
1574 createUndoDoc(pNewUndoDoc, rDoc, aNewOut);
1575
1576 rDestObj.Output(aNewOut.aStart);
1578
1579 if (bRecord)
1580 {
1582 std::make_unique<ScUndoDataPilot>(&rDocShell, nullptr, std::move(pNewUndoDoc), nullptr, &rDestObj, false));
1583 }
1584
1585 // notify API objects
1587 aModificator.SetDocumentModified();
1588
1589 return true;
1590}
1591
1592bool ScDBDocFunc::UpdatePivotTable(ScDPObject& rDPObj, bool bRecord, bool bApi)
1593{
1594 ScDocShellModificator aModificator( rDocShell );
1596
1597 if (!isEditable(rDocShell, rDPObj.GetOutRange(), bApi))
1598 return false;
1599
1600 ScDocumentUniquePtr pOldUndoDoc;
1601 ScDocumentUniquePtr pNewUndoDoc;
1602
1603 ScDPObject aUndoDPObj(rDPObj); // For undo or revert on failure.
1604
1606 if (bRecord && !rDoc.IsUndoEnabled())
1607 bRecord = false;
1608
1609 if (bRecord)
1610 createUndoDoc(pOldUndoDoc, rDoc, rDPObj.GetOutRange());
1611
1612 rDPObj.SetAllowMove(false);
1613 rDPObj.ReloadGroupTableData();
1614 if (!rDPObj.SyncAllDimensionMembers())
1615 return false;
1616
1617 rDPObj.InvalidateData(); // before getting the new output area
1618
1619 // make sure the table has a name (not set by dialog)
1620 if (rDPObj.GetName().isEmpty())
1621 rDPObj.SetName( rDoc.GetDPCollection()->CreateNewName() );
1622
1623 ScRange aNewOut;
1624 if (!checkNewOutputRange(rDPObj, rDocShell, aNewOut, bApi))
1625 {
1626 rDPObj = aUndoDPObj;
1627 return false;
1628 }
1629
1630 // test if new output area is empty except for old area
1631 if (!bApi)
1632 {
1633 if (!lcl_EmptyExcept(rDoc, aNewOut, rDPObj.GetOutRange()))
1634 {
1635 std::unique_ptr<weld::MessageDialog> xQueryBox(Application::CreateMessageDialog(ScDocShell::GetActiveDialogParent(),
1636 VclMessageType::Question, VclButtonsType::YesNo,
1637 ScResId(STR_PIVOT_NOTEMPTY)));
1638 xQueryBox->set_default_response(RET_YES);
1639 if (xQueryBox->run() == RET_NO)
1640 {
1641 rDPObj = aUndoDPObj;
1642 return false;
1643 }
1644 }
1645 }
1646
1647 if (bRecord)
1648 createUndoDoc(pNewUndoDoc, rDoc, aNewOut);
1649
1650 rDPObj.Output(aNewOut.aStart);
1652
1653 if (bRecord)
1654 {
1656 std::make_unique<ScUndoDataPilot>(
1657 &rDocShell, std::move(pOldUndoDoc), std::move(pNewUndoDoc), &aUndoDPObj, &rDPObj, false));
1658 }
1659
1660 // notify API objects
1662 aModificator.SetDocumentModified();
1663 return true;
1664}
1665
1666void ScDBDocFunc::RefreshPivotTables(const ScDPObject* pDPObj, bool bApi)
1667{
1669 if (!pDPs)
1670 return;
1671
1673 TranslateId pErrId = pDPs->ReloadCache(pDPObj, aRefs);
1674 if (pErrId)
1675 return;
1676
1677 for (ScDPObject* pObj : aRefs)
1678 {
1679 // This action is intentionally not undoable since it modifies cache.
1680 UpdatePivotTable(*pObj, false, bApi);
1681 }
1682}
1683
1685{
1686 if (!pDPObj)
1687 return;
1688
1690 if (!pDPs)
1691 return;
1692
1693 ScDPSaveData* pSaveData = pDPObj->GetSaveData();
1694 if (!pSaveData)
1695 return;
1696
1697 if (!pDPs->HasTable(pDPObj))
1698 {
1699 // This table is under construction so no need for a whole update (UpdatePivotTable()).
1700 pDPObj->ReloadGroupTableData();
1701 return;
1702 }
1703
1704 // Update all linked tables, if this table is part of the cache (ScDPCollection)
1706 if (!pDPs->ReloadGroupsInCache(pDPObj, aRefs))
1707 return;
1708
1709 // We allow pDimData being NULL.
1710 const ScDPDimensionSaveData* pDimData = pSaveData->GetExistingDimensionData();
1711 for (ScDPObject* pObj : aRefs)
1712 {
1713 if (pObj != pDPObj)
1714 {
1715 pSaveData = pObj->GetSaveData();
1716 if (pSaveData)
1717 pSaveData->SetDimensionData(pDimData);
1718 }
1719
1720 // This action is intentionally not undoable since it modifies cache.
1721 UpdatePivotTable(*pObj, false, false);
1722 }
1723}
1724
1725// database import
1726
1727void ScDBDocFunc::UpdateImport( const OUString& rTarget, const svx::ODataAccessDescriptor& rDescriptor )
1728{
1729 // rTarget is the name of a database range
1730
1732 ScDBCollection& rDBColl = *rDoc.GetDBCollection();
1734 if (!pData)
1735 {
1736 std::unique_ptr<weld::MessageDialog> xInfoBox(Application::CreateMessageDialog(ScDocShell::GetActiveDialogParent(),
1737 VclMessageType::Info, VclButtonsType::Ok,
1738 ScResId(STR_TARGETNOTFOUND)));
1739 xInfoBox->run();
1740 return;
1741 }
1742
1743 SCTAB nTab;
1744 SCCOL nDummyCol;
1745 SCROW nDummyRow;
1746 pData->GetArea( nTab, nDummyCol,nDummyRow,nDummyCol,nDummyRow );
1747
1748 ScImportParam aImportParam;
1749 pData->GetImportParam( aImportParam );
1750
1751 OUString sDBName;
1752 OUString sDBTable;
1753 sal_Int32 nCommandType = 0;
1754 sDBName = rDescriptor.getDataSource();
1755 rDescriptor[svx::DataAccessDescriptorProperty::Command] >>= sDBTable;
1756 rDescriptor[svx::DataAccessDescriptorProperty::CommandType] >>= nCommandType;
1757
1758 aImportParam.aDBName = sDBName;
1759 aImportParam.bSql = ( nCommandType == sdb::CommandType::COMMAND );
1760 aImportParam.aStatement = sDBTable;
1761 aImportParam.bNative = false;
1762 aImportParam.nType = static_cast<sal_uInt8>( ( nCommandType == sdb::CommandType::QUERY ) ? ScDbQuery : ScDbTable );
1763 aImportParam.bImport = true;
1764
1765 bool bContinue = DoImport( nTab, aImportParam, &rDescriptor );
1766
1767 // repeat DB operations
1768
1770 if (!pViewSh)
1771 return;
1772
1773 ScRange aRange;
1774 pData->GetArea(aRange);
1775 pViewSh->MarkRange(aRange); // select
1776
1777 if ( bContinue ) // error at import -> abort
1778 {
1779 // internal operations, if some are saved
1780
1781 if ( pData->HasQueryParam() || pData->HasSortParam() || pData->HasSubTotalParam() )
1782 pViewSh->RepeatDB();
1783
1784 // pivot tables which have the range as source data
1785
1787 }
1788}
1789
1790/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
const SCTAB MAXTAB
Definition: address.hxx:70
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
SfxApplication * SfxGetpApp()
static weld::MessageDialog * CreateMessageDialog(weld::Widget *pParent, VclMessageType eMessageType, VclButtonsType eButtonType, const OUString &rPrimaryMessage, const ILibreOfficeKitNotifier *pNotifier=nullptr)
SCTAB Tab() const
Definition: address.hxx:283
void SetCol(SCCOL nColP)
Definition: address.hxx:291
SCROW Row() const
Definition: address.hxx:274
void SetRow(SCROW nRowP)
Definition: address.hxx:287
void IncRow(SCROW nDelta=1)
Definition: address.hxx:312
SCCOL Col() const
Definition: address.hxx:279
Walk through all cells in an area.
Definition: dociter.hxx:206
void removeByName(const OUString &rName)
Definition: chartlis.cxx:396
bool has(const ScDBData *p) const
Definition: dbdata.cxx:1354
Stores global named database ranges.
Definition: dbdata.hxx:243
iterator erase(const iterator &itr)
Definition: dbdata.cxx:1263
bool insert(std::unique_ptr< ScDBData > p)
Takes ownership of p and attempts to insert it into the collection.
Definition: dbdata.cxx:1240
iterator findByUpperName2(const OUString &rName)
Definition: dbdata.cxx:1228
ScDBData * findByUpperName(const OUString &rName)
Definition: dbdata.cxx:1221
NamedDBs & getNamedDBs()
Definition: dbdata.hxx:324
bool empty() const
Definition: dbdata.cxx:1634
AnonDBs & getAnonDBs()
Definition: dbdata.hxx:327
bool IsDoSize() const
Definition: dbdata.hxx:142
SC_DLLPUBLIC bool HasQueryParam() const
Definition: dbdata.cxx:522
const OUString & GetName() const
Definition: dbdata.hxx:127
void GetArea(SCTAB &rTab, SCCOL &rCol1, SCROW &rRow1, SCCOL &rCol2, SCROW &rRow2) const
Definition: dbdata.cxx:298
SC_DLLPUBLIC bool GetAdvancedQuerySource(ScRange &rSource) const
Definition: dbdata.cxx:455
void CalcSaveFilteredCount(SCSIZE nNonFilteredRowCount)
Definition: dbdata.cxx:973
const OUString & GetUpperName() const
Definition: dbdata.hxx:128
void SetSubTotalParam(const ScSubTotalParam &rSubTotalParam)
Definition: dbdata.cxx:473
SC_DLLPUBLIC void SetAdvancedQuerySource(const ScRange *pSource)
Definition: dbdata.cxx:444
SC_DLLPUBLIC void GetSortParam(ScSortParam &rSortParam) const
Definition: dbdata.cxx:399
void SetHeader(bool bHasH)
Definition: dbdata.hxx:137
SC_DLLPUBLIC void SetSortParam(const ScSortParam &rSortParam)
Definition: dbdata.cxx:411
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:417
SC_DLLPUBLIC void GetQueryParam(ScQueryParam &rQueryParam) const
Definition: dbdata.cxx:422
bool IsKeepFmt() const
Definition: dbdata.hxx:144
SC_DLLPUBLIC void SetQueryParam(const ScQueryParam &rQueryParam)
Definition: dbdata.cxx:435
void GetSubTotalParam(ScSubTotalParam &rSubTotalParam) const
Definition: dbdata.cxx:461
void SetArea(SCTAB nTab, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2)
Definition: dbdata.cxx:320
bool RenameDBRange(const OUString &rOld, const OUString &rNew)
Definition: dbdocfun.cxx:154
bool RemovePivotTable(const ScDPObject &rDPObj, bool bRecord, bool bApi)
Definition: dbdocfun.cxx:1399
bool AddDBRange(const OUString &rName, const ScRange &rRange)
Definition: dbdocfun.cxx:65
void ModifyDBData(const ScDBData &rNewData)
Definition: dbdocfun.cxx:201
void RefreshPivotTables(const ScDPObject *pDPObj, bool bApi)
Reload the referenced pivot cache, and refresh all pivot tables that reference the cache.
Definition: dbdocfun.cxx:1666
bool UpdatePivotTable(ScDPObject &rDPObj, bool bRecord, bool bApi)
Definition: dbdocfun.cxx:1592
SC_DLLPUBLIC bool Sort(SCTAB nTab, const ScSortParam &rSortParam, bool bRecord, bool bPaint, bool bApi)
Definition: dbdocfun.cxx:466
ScDocShell & rDocShell
Definition: dbdocfun.hxx:48
SC_DLLPUBLIC bool Query(SCTAB nTab, const ScQueryParam &rQueryParam, const ScRange *pAdvSource, bool bRecord, bool bApi)
Definition: dbdocfun.cxx:678
bool DeleteDBRange(const OUString &rName)
Definition: dbdocfun.cxx:118
void DoSubTotals(SCTAB nTab, const ScSubTotalParam &rParam, bool bRecord, bool bApi)
Definition: dbdocfun.cxx:1038
void UpdateImport(const OUString &rTarget, const svx::ODataAccessDescriptor &rDescriptor)
Definition: dbdocfun.cxx:1727
bool RepeatDB(const OUString &rDBName, bool bApi, bool bIsUnnamed, SCTAB aTab=0)
Definition: dbdocfun.cxx:283
bool DoImport(SCTAB nTab, const ScImportParam &rParam, const svx::ODataAccessDescriptor *pDescriptor)
Definition: dbdocimp.cxx:121
bool DataPilotUpdate(ScDPObject *pOldObj, const ScDPObject *pNewObj, bool bRecord, bool bApi, bool bAllowMove=false)
Definition: dbdocfun.cxx:1297
void RefreshPivotTableGroups(ScDPObject *pDPObj)
Refresh the group dimensions of all pivot tables referencing the same cache.
Definition: dbdocfun.cxx:1684
bool CreatePivotTable(const ScDPObject &rDPObj, bool bRecord, bool bApi)
Definition: dbdocfun.cxx:1481
void ModifyAllDBData(const ScDBCollection &rNewColl, const std::vector< ScRange > &rDelAreaList)
Definition: dbdocfun.cxx:245
void OnLOKShowHideColRow(bool bColumns, SCCOLROW nStartRow)
Definition: dbfunc3.cxx:2278
void RepeatDB(bool bRecord=true)
Definition: dbfunc3.cxx:2113
SC_DLLPUBLIC ScDPObject * InsertNewTable(std::unique_ptr< ScDPObject > pDPObj)
Definition: dpobject.cxx:3771
void FreeTable(const ScDPObject *pDPObj)
Definition: dpobject.cxx:3756
ScDPObject * GetByName(std::u16string_view rName) const
Definition: dpobject.cxx:3732
TranslateId ReloadCache(const ScDPObject *pDPObj, o3tl::sorted_vector< ScDPObject * > &rRefs)
Definition: dpobject.cxx:3411
OUString CreateNewName() const
Create a new name that's not yet used by any existing data pilot objects.
Definition: dpobject.cxx:3743
SC_DLLPUBLIC bool GetReferenceGroups(const ScDPObject &rDPObj, const ScDPDimensionSaveData **pGroups) const
Definition: dpobject.cxx:3563
bool ReloadGroupsInCache(const ScDPObject *pDPObj, o3tl::sorted_vector< ScDPObject * > &rRefs)
Definition: dpobject.cxx:3475
SC_DLLPUBLIC bool HasTable(const ScDPObject *pDPObj) const
Definition: dpobject.cxx:3782
This class has to do with handling exclusively grouped dimensions? TODO: Find out what this class doe...
Definition: dpdimsave.hxx:164
const ScRange & GetOutRange() const
Definition: dpobject.cxx:410
bool SyncAllDimensionMembers()
Remove in the save data entries for members that don't exist anymore.
Definition: dpobject.cxx:974
void InvalidateData()
Definition: dpobject.cxx:785
void SetName(const OUString &rNew)
Definition: dpobject.cxx:490
ScRange GetNewOutputRange(bool &rOverflow)
Definition: dpobject.cxx:874
void SetSaveData(const ScDPSaveData &rData)
Definition: dpobject.cxx:387
void SetAllowMove(bool bSet)
Definition: dpobject.cxx:382
void Output(const ScAddress &rPos)
Definition: dpobject.cxx:888
const ScSheetSourceDesc * GetSheetDesc() const
Definition: dpobject.hxx:156
void ReloadGroupTableData()
Definition: dpobject.cxx:810
ScDPSaveData * GetSaveData() const
Definition: dpobject.hxx:141
const OUString & GetName() const
Definition: dpobject.hxx:167
void WriteSourceDataTo(ScDPObject &rDest) const
Definition: dpobject.cxx:465
const ScDPDimensionSaveData * GetExistingDimensionData() const
Definition: dpsave.hxx:353
SC_DLLPUBLIC void SetDimensionData(const ScDPDimensionSaveData *pNew)
Definition: dpsave.cxx:1211
bool MoveBlock(const ScRange &rSource, const ScAddress &rDestPos, bool bCut, bool bRecord, bool bPaint, bool bApi)
Definition: docfunc.cxx:2852
Create before modifications of the document and destroy thereafter.
Definition: docsh.hxx:455
void SetDocumentModified()
Definition: docsh.cxx:3315
static weld::Window * GetActiveDialogParent()
Definition: docsh.cxx:3112
void PostPaintGridAll()
Definition: docsh3.cxx:183
void ErrorMessage(TranslateId pGlobStrId)
Definition: docsh5.cxx:71
const ScDocument & GetDocument() const
Definition: docsh.hxx:219
ScTabViewShell * GetBestViewShell(bool bOnlyVisible=true)
Definition: docsh4.cxx:2623
ScDBData * GetDBData(const ScRange &rMarked, ScGetDBMode eMode, ScGetDBSelection eSel)
Definition: docsh5.cxx:115
void PostPaint(SCCOL nStartCol, SCROW nStartRow, SCTAB nStartTab, SCCOL nEndCol, SCROW nEndRow, SCTAB nEndTab, PaintPartFlags nPart, sal_uInt16 nExtFlags=0)
Definition: docsh3.cxx:101
void DBAreaDeleted(SCTAB nTab, SCCOL nX1, SCROW nY1, SCCOL nX2)
Definition: docsh5.cxx:104
bool AdjustRowHeight(SCROW nStartRow, SCROW nEndRow, SCTAB nTab)
merge with docfunc
Definition: docsh5.cxx:405
virtual SfxUndoManager * GetUndoManager() override
Definition: docsh.cxx:2968
bool IsEditable() const
Definition: docsh5.cxx:96
ScDocFunc & GetDocFunc()
Definition: docsh.hxx:221
void RefreshPivotTables(const ScRange &rSource)
Definition: docsh5.cxx:482
SC_DLLPUBLIC bool RemoveFlagsTab(SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow, SCTAB nTab, ScMF nFlags)
Definition: document.cxx:4980
ScSheetLimits & GetSheetLimits() const
Definition: document.hxx:898
bool ValidRow(SCROW nRow) const
Definition: document.hxx:900
void UpdatePageBreaks(SCTAB nTab, const ScRange *pUserArea=nullptr)
Definition: document.cxx:6210
SC_DLLPUBLIC void Fill(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, ScProgress *pProgress, const ScMarkData &rMark, sal_uInt64 nFillCount, FillDir eFillDir=FILL_TO_BOTTOM, FillCmd eFillCmd=FILL_LINEAR, FillDateCmd eFillDateCmd=FILL_DAY, double nStepValue=1.0, double nMaxValue=1E307)
Definition: documen3.cxx:1156
void BeginDrawUndo()
Definition: documen9.cxx:61
SC_DLLPUBLIC void CompileHybridFormula()
Call this immediately after updating named ranges.
Definition: document10.cxx:319
void RemoveSubTotals(SCTAB nTab, ScSubTotalParam &rParam)
Definition: documen3.cxx:773
void InvalidatePageBreaks(SCTAB nTab)
Definition: document.cxx:6204
SC_DLLPUBLIC SCCOL MaxCol() const
Definition: document.hxx:892
const ScDBData * GetDBAtCursor(SCCOL nCol, SCROW nRow, SCTAB nTab, ScDBDataPortion ePortion) const
Definition: documen3.cxx:322
bool HasUniformRowHeight(SCTAB nTab, SCROW nRow1, SCROW nRow2) const
Definition: document10.cxx:346
SC_DLLPUBLIC void ApplyPatternAreaTab(SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow, SCTAB nTab, const ScPatternAttr &rAttr)
Definition: document.cxx:4770
SC_DLLPUBLIC SCROW MaxRow() const
Definition: document.hxx:893
SC_DLLPUBLIC ScChartListenerCollection * GetChartListenerCollection() const
Definition: document.hxx:2233
bool DoSubTotals(SCTAB nTab, ScSubTotalParam &rParam)
Definition: documen3.cxx:779
SC_DLLPUBLIC const ScDBData * GetDBAtArea(SCTAB nTab, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2) const
Definition: documen3.cxx:338
SC_DLLPUBLIC void PreprocessDBDataUpdate()
Definition: document10.cxx:307
bool ShrinkToUsedDataArea(bool &o_bShrunk, SCTAB nTab, SCCOL &rStartCol, SCROW &rStartRow, SCCOL &rEndCol, SCROW &rEndRow, bool bColumnsOnly, bool bStickyTopRow=false, bool bStickyLeftCol=false, ScDataAreaExtras *pDataAreaExtras=nullptr) const
Shrink a range to only include used data area.
Definition: document.cxx:1049
void SetSubTotalCellsDirty(const ScRange &rDirtyRange)
Definition: document.cxx:6412
SC_DLLPUBLIC void SetDrawPageSize(SCTAB nTab)
Definition: documen9.cxx:203
SC_DLLPUBLIC ScDrawLayer * GetDrawLayer()
Definition: document.hxx:1084
SC_DLLPUBLIC bool HasAttrib(SCCOL nCol1, SCROW nRow1, SCTAB nTab1, SCCOL nCol2, SCROW nRow2, SCTAB nTab2, HasAttrFlags nMask) const
Definition: document.cxx:5161
void UpdateScriptTypes(const ScAddress &rPos, SCCOL nColSize, SCROW nRowSize)
Definition: document10.cxx:337
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:2041
SC_DLLPUBLIC ScDBCollection * GetDBCollection() const
Definition: document.hxx:827
void FitBlock(const ScRange &rOld, const ScRange &rNew, bool bClear=true)
Definition: document.cxx:1827
SfxObjectShell * GetDocumentShell() const
Definition: document.hxx:1083
SC_DLLPUBLIC ScOutlineTable * GetOutlineTable(SCTAB nTab, bool bCreate=false)
Definition: documen3.cxx:737
SCSIZE Query(SCTAB nTab, const ScQueryParam &rQueryParam, bool bKeepSub)
Definition: documen3.cxx:1468
bool TestRemoveSubTotals(SCTAB nTab, const ScSubTotalParam &rParam)
Definition: documen3.cxx:767
SC_DLLPUBLIC ScRangeName * GetRangeName(SCTAB nTab) const
Definition: documen3.cxx:171
SC_DLLPUBLIC bool HasHiddenRows(SCROW nStartRow, SCROW nEndRow, SCTAB nTab) const
Definition: document.cxx:4423
SC_DLLPUBLIC void DeleteAreaTab(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, SCTAB nTab, InsertDeleteFlags nDelFlag)
Definition: document.cxx:1920
void SetDBCollection(std::unique_ptr< ScDBCollection > pNewDBCollection, bool bRemoveAutoFilter=false)
Definition: documen3.cxx:275
ScChangeTrack * GetChangeTrack() const
Definition: document.hxx:2494
SC_DLLPUBLIC CellType GetCellType(SCCOL nCol, SCROW nRow, SCTAB nTab) const
Definition: document.cxx:3736
bool IsBlockEmpty(SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow, SCTAB nTab) const
Definition: document.cxx:5288
void CompileDBFormula()
Definition: documen4.cxx:554
SC_DLLPUBLIC ScDBData * GetAnonymousDBData(SCTAB nTab)
Definition: document.cxx:290
SC_DLLPUBLIC void ApplyStyleAreaTab(SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow, SCTAB nTab, const ScStyleSheet &rStyle)
Definition: document.cxx:4823
bool IsUndoEnabled() const
Definition: document.hxx:1595
void SetDirty(const ScRange &, bool bIncludeEmptyCells)
Definition: document.cxx:3841
bool CanFitBlock(const ScRange &rOld, const ScRange &rNew)
Definition: document.cxx:1796
SC_DLLPUBLIC ScDPCollection * GetDPCollection()
Definition: documen3.cxx:365
void Sort(SCTAB nTab, const ScSortParam &rSortParam, bool bKeepQuery, bool bUpdateRefs, ScProgress *pProgress, sc::ReorderParam *pUndo)
Sort a range of data.
Definition: documen3.cxx:1433
SC_DLLPUBLIC void SetAnonymousDBData(SCTAB nTab, std::unique_ptr< ScDBData > pDBData)
Definition: document.cxx:302
bool IsImportingXML() const
Definition: document.hxx:2227
void BroadcastUno(const SfxHint &rHint)
Definition: documen3.cxx:952
SC_DLLPUBLIC SCTAB GetTableCount() const
Definition: document.cxx:297
bool ValidColRow(SCCOL nCol, SCROW nRow) const
Definition: document.hxx:901
bool IsEditable() const
Definition: editable.hxx:84
TranslateId GetMessageId() const
Definition: editable.cxx:152
static SC_DLLPUBLIC const CharClass & getCharClass()
Definition: global.cxx:1064
bool GetSortRefUpdate() const
Definition: inputopt.hxx:57
todo: It should be possible to have MarkArrays for each table, in order to enable "search all" across...
Definition: markdata.hxx:43
void SelectOneTable(SCTAB nTab)
Definition: markdata.cxx:174
void GetRange(SCCOLROW &rStart, SCCOLROW &rEnd) const
Definition: olinetab.cxx:555
const ScOutlineArray & GetColArray() const
Definition: olinetab.hxx:158
const ScOutlineArray & GetRowArray() const
Definition: olinetab.hxx:160
const ScStyleSheet * GetStyleSheet() const
Definition: patattr.hxx:165
void push_back(const ScRange &rRange)
Definition: rangelst.cxx:1137
size_t size() const
Definition: rangelst.hxx:89
bool empty() const
Definition: rangenam.hxx:249
ScAddress aEnd
Definition: address.hxx:498
bool Intersects(const ScRange &rRange) const
Definition: address.hxx:734
bool Contains(const ScAddress &) const
is Address& fully in Range?
Definition: address.hxx:718
ScAddress aStart
Definition: address.hxx:497
This class contains authoritative information on the internal reference used as the data source for d...
Definition: dpshttab.hxx:40
SC_DLLPUBLIC const ScRange & GetSourceRange() const
Get the range that contains the source data.
Definition: dpshttab.cxx:230
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:593
static bool isAnyEditViewInRange(const SfxViewShell *pForViewShell, bool bColumns, SCCOLROW nStart, SCCOLROW nEnd)
Definition: tabvwshc.cxx:568
void MarkRange(const ScRange &rRange, bool bSetCursor=true, bool bContinue=false)
Definition: tabview3.cxx:1708
ScViewData & GetViewData()
Definition: tabview.hxx:344
ScPositionHelper & GetLOKHeightHelper()
Definition: viewdata.hxx:411
void AddUndo(std::unique_ptr< SdrUndoAction > pUndo)
virtual void AddUndoAction(std::unique_ptr< SfxUndoAction > pAction, bool bTryMerg=false)
ViewShellDocId GetDocId() const override
static SAL_WARN_UNUSED_RESULT SfxViewShell * GetNext(const SfxViewShell &rPrev, bool bOnlyVisible=true, const std::function< bool(const SfxViewShell *)> &isViewShell=nullptr)
static SAL_WARN_UNUSED_RESULT SfxViewShell * GetFirst(bool bOnlyVisible=true, const std::function< bool(const SfxViewShell *)> &isViewShell=nullptr)
OUString getDataSource() const
int nCount
@ TOP_LEFT
top left cell of area
std::unique_ptr< ScDocument, o3tl::default_delete< ScDocument > > ScDocumentUniquePtr
Definition: document.hxx:2720
@ SCDOCMODE_UNDO
Definition: document.hxx:258
FilterGroup & rTarget
@ CELLTYPE_FORMULA
Definition: global.hxx:276
@ ATTRIB
Internal use only (d&d undo): do not delete caption objects of cell notes.
@ FORMULA
Cell notes.
@ ForceMark
Behave as if the range corresponding to a ScDBData area was selected, for API use.
PaintPartFlags
Definition: global.hxx:109
@ ScDbQuery
Definition: global.hxx:421
@ ScDbTable
Definition: global.hxx:420
@ SC_DB_MAKE
create "untitled" (if necessary)
Definition: global.hxx:383
@ FILL_SIMPLE
Definition: global.hxx:318
@ FILL_TO_BOTTOM
Definition: global.hxx:310
constexpr OUStringLiteral STR_DB_LOCAL_NONAME
Definition: globalnames.hxx:14
std::unique_ptr< sal_Int32[]> pData
int i
std::vector< SdrOle2Obj * > getAllPivotChartsConnectedTo(std::u16string_view sPivotTableName, ScDocShell *pDocShell)
Definition: ChartTools.cxx:142
OUString ScResId(TranslateId aId)
Definition: scdll.cxx:90
#define SC_MOD()
Definition: scmod.hxx:247
sal_uIntPtr sal_uLong
bool mbCellFormats
If TRUE, consider the presence of cell formats.
Definition: sortparam.hxx:59
void GetOverallRange(SCCOL &nCol1, SCROW &nRow1, SCCOL &nCol2, SCROW &nRow2, Clip eClip=Clip::None) const
Obtain the overall range if area extras are larger.
Definition: sortparam.hxx:84
void SetOverallRange(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2)
Set the overall range.
Definition: sortparam.hxx:103
bool anyExtrasWanted() const
Definition: sortparam.hxx:65
OUString aStatement
Definition: global.hxx:447
sal_uInt8 nType
Definition: global.hxx:450
OUString aDBName
Definition: global.hxx:446
bool bNative
Definition: global.hxx:448
bool bImport
Definition: global.hxx:445
SC_DLLPUBLIC const ScQueryEntry & GetEntry(SCSIZE n) const
Definition: queryparam.cxx:116
SC_DLLPUBLIC SCSIZE GetEntryCount() const
Definition: queryparam.cxx:111
void MoveToDest()
Definition: queryparam.cxx:398
SCTAB nDestTab
Definition: sortparam.hxx:126
SCROW nDestRow
Definition: sortparam.hxx:128
SCCOL nDestCol
Definition: sortparam.hxx:127
::std::vector< ScSortKeyState > maKeyState
Definition: sortparam.hxx:130
void MoveToDest()
Definition: sortparam.cxx:234
bool bHasHeader
Definition: sortparam.hxx:120
ScDataAreaExtras aDataAreaExtras
Definition: sortparam.hxx:118
sal_uInt16 GetSortKeyCount() const
Definition: sortparam.hxx:148
bool bGroupActive[MAXSUBTOTAL]
active groups
bool bDoSort
presort
SCCOL nCol1
selected area
bool bReplace
replace existing results
unsigned char sal_uInt8
sal_Int32 SCCOLROW
a type capable of holding either SCCOL or SCROW
Definition: types.hxx:23
sal_Int16 SCTAB
Definition: types.hxx:22
sal_Int16 SCCOL
Definition: types.hxx:21
sal_Int32 SCROW
Definition: types.hxx:17
RET_NO
RET_YES
oslFileHandle & pOut
@ QUERY
Definition: xmldpimp.hxx:44