1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
21 #include <sal/config.h>
25 #include <osl/diagnose.h>
26 #include <vcl/svapp.hxx>
27 #include <vcl/weld.hxx>
28 #include <sfx2/app.hxx>
29 #include <sfx2/bindings.hxx>
30 #include <unotools/charclass.hxx>
32 #include <com/sun/star/script/vba/XVBACompatibility.hpp>
34 #include <dociter.hxx>
37 #include <globstr.hrc>
38 #include <scresid.hxx>
39 #include <globalnames.hxx>
40 #include <undodat.hxx>
41 #include <undotab.hxx>
42 #include <undoblk.hxx>
43 #include <dpobject.hxx>
44 #include <dpshttab.hxx>
45 #include <dbdocfun.hxx>
46 #include <consoli.hxx>
48 #include <progress.hxx>
49 #include <olinetab.hxx>
50 #include <patattr.hxx>
52 #include <docpool.hxx>
53 #include <uiitems.hxx>
55 #include <sizedev.hxx>
56 #include <clipparam.hxx>
57 #include <rowheightcontext.hxx>
58 #include <refupdatecontext.hxx>
60 using com::sun::star::script::XLibraryContainer
;
61 using com::sun::star::script::vba::XVBACompatibility
;
62 using com::sun::star::container::XNameContainer
;
63 using com::sun::star::uno::Reference
;
64 using com::sun::star::uno::UNO_QUERY
;
66 using ::std::unique_ptr
;
69 // former viewfunc/dbfunc methods
71 void ScDocShell::ErrorMessage(TranslateId pGlobStrId
)
73 //! StopMarking at the (active) view?
75 weld::Window
* pParent
= GetActiveDialogParent();
76 weld::WaitObject
aWaitOff( pParent
);
77 bool bFocus
= pParent
&& pParent
->has_focus();
79 if (pGlobStrId
&& pGlobStrId
== STR_PROTECTIONERR
)
83 pGlobStrId
= STR_READONLYERR
;
87 std::unique_ptr
<weld::MessageDialog
> xInfoBox(Application::CreateMessageDialog(pParent
,
88 VclMessageType::Info
, VclButtonsType::Ok
,
89 ScResId(pGlobStrId
)));
93 pParent
->grab_focus();
96 bool ScDocShell::IsEditable() const
98 // import into read-only document is possible - must be extended if other filters use api
99 // #i108547# MSOOXML filter uses "IsChangeReadOnlyEnabled" property
101 return !IsReadOnly() || m_pDocument
->IsImportingXML() || m_pDocument
->IsChangeReadOnlyEnabled();
104 void ScDocShell::DBAreaDeleted( SCTAB nTab
, SCCOL nX1
, SCROW nY1
, SCCOL nX2
)
106 ScDocShellModificator
aModificator( *this );
107 // the auto-filter is in the first row of the area
108 m_pDocument
->RemoveFlagsTab( nX1
, nY1
, nX2
, nY1
, nTab
, ScMF::Auto
);
109 PostPaint( nX1
, nY1
, nTab
, nX2
, nY1
, nTab
, PaintPartFlags::Grid
);
110 // No SetDocumentModified, as the unnamed database range might have to be restored later.
111 // The UNO hint is broadcast directly instead, to keep UNO objects in valid state.
112 m_pDocument
->BroadcastUno( SfxHint( SfxHintId::DataChanged
) );
115 ScDBData
* ScDocShell::GetDBData( const ScRange
& rMarked
, ScGetDBMode eMode
, ScGetDBSelection eSel
)
117 SCCOL nCol
= rMarked
.aStart
.Col();
118 SCROW nRow
= rMarked
.aStart
.Row();
119 SCTAB nTab
= rMarked
.aStart
.Tab();
121 SCCOL nStartCol
= nCol
;
122 SCROW nStartRow
= nRow
;
123 SCTAB nStartTab
= nTab
;
124 SCCOL nEndCol
= rMarked
.aEnd
.Col();
125 SCROW nEndRow
= rMarked
.aEnd
.Row();
126 // Not simply GetDBAtCursor: The continuous data range for "unnamed" (GetDataArea) may be
127 // located next to the cursor; so a named DB range needs to be searched for there as well.
128 ScDBCollection
* pColl
= m_pDocument
->GetDBCollection();
129 ScDBData
* pData
= m_pDocument
->GetDBAtArea( nTab
, nStartCol
, nStartRow
, nEndCol
, nEndRow
);
131 pData
= pColl
->GetDBNearCursor(nCol
, nRow
, nTab
);
133 bool bSelected
= ( eSel
== ScGetDBSelection::ForceMark
||
134 (rMarked
.aStart
!= rMarked
.aEnd
&& eSel
!= ScGetDBSelection::RowDown
) );
135 bool bOnlyDown
= (!bSelected
&& eSel
== ScGetDBSelection::RowDown
&& rMarked
.aStart
.Row() == rMarked
.aEnd
.Row());
137 bool bUseThis
= false;
140 // take range, if nothing else is marked
147 pData
->GetArea( nDummy
, nOldCol1
,nOldRow1
, nOldCol2
,nOldRow2
);
148 bool bIsNoName
= ( pData
->GetName() == STR_DB_LOCAL_NONAME
);
153 if ( bIsNoName
&& (eMode
== SC_DB_MAKE
|| eMode
== SC_DB_AUTOFILTER
) )
155 // If nothing marked or only one row marked, adapt
156 // "unnamed" to contiguous area.
161 nEndCol
= rMarked
.aEnd
.Col();
162 nEndRow
= rMarked
.aEnd
.Row();
169 m_pDocument
->GetDataArea( nTab
, nStartCol
, nStartRow
, nEndCol
, nEndRow
, false, bOnlyDown
);
170 if ( nOldCol1
!= nStartCol
|| nOldCol2
!= nEndCol
|| nOldRow1
!= nStartRow
)
171 bUseThis
= false; // doesn't fit at all
172 else if ( nOldRow2
!= nEndRow
)
174 // extend range to new end row
175 pData
->SetArea( nTab
, nOldCol1
,nOldRow1
, nOldCol2
,nEndRow
);
181 if ( nOldCol1
== nStartCol
&& nOldRow1
== nStartRow
&&
182 nOldCol2
== nEndCol
&& nOldRow2
== nEndRow
) // marked precisely?
185 bUseThis
= false; // always take marking (Bug 11964)
188 // never take "unnamed" for import
190 if ( bUseThis
&& eMode
== SC_DB_IMPORT
&& bIsNoName
)
196 pData
->GetArea( nStartTab
, nStartCol
,nStartRow
, nEndCol
,nEndRow
);
198 else if ( eMode
== SC_DB_OLD
)
200 pData
= nullptr; // nothing found
205 { // continuous range
210 nEndCol
= rMarked
.aEnd
.Col();
211 nEndRow
= rMarked
.aEnd
.Row();
218 m_pDocument
->GetDataArea( nTab
, nStartCol
, nStartRow
, nEndCol
, nEndRow
, false, bOnlyDown
);
221 bool bHasHeader
= m_pDocument
->HasColHeader( nStartCol
,nStartRow
, nEndCol
,nEndRow
, nTab
);
223 ScDBData
* pNoNameData
= m_pDocument
->GetAnonymousDBData(nTab
);
224 if ( eMode
!= SC_DB_IMPORT
&& pNoNameData
)
226 // Do not reset AutoFilter range during temporary operations on
227 // other ranges, use the document global temporary anonymous range
228 // instead. But, if AutoFilter is to be toggled then do use the
229 // sheet-local DB range.
230 bool bSheetLocal
= true;
231 if (eMode
!= SC_DB_AUTOFILTER
&& pNoNameData
->HasAutoFilter())
234 pNoNameData
= m_pDocument
->GetAnonymousDBData();
237 m_pDocument
->SetAnonymousDBData( std::unique_ptr
<ScDBData
>(new ScDBData( STR_DB_LOCAL_NONAME
,
238 nTab
, nStartCol
, nStartRow
, nEndCol
, nEndRow
, true, bHasHeader
) ) );
239 pNoNameData
= m_pDocument
->GetAnonymousDBData();
241 // ScDocShell::CancelAutoDBRange() would restore the
242 // sheet-local anonymous DBData from pOldAutoDBRange, unset so
243 // that won't happen with data of a previous sheet-local
245 m_pOldAutoDBRange
.reset();
247 else if (!m_pOldAutoDBRange
)
249 // store the old unnamed database range with its settings for undo
250 // (store at the first change, get the state before all changes)
251 m_pOldAutoDBRange
.reset( new ScDBData( *pNoNameData
) );
253 else if (m_pOldAutoDBRange
->GetTab() != pNoNameData
->GetTab())
255 // Different sheet-local unnamed DB range than the previous one.
256 *m_pOldAutoDBRange
= *pNoNameData
;
259 SCCOL nOldX1
; // take old range away cleanly
260 SCROW nOldY1
; //! (UNDO ???)
264 pNoNameData
->GetArea( nOldTab
, nOldX1
, nOldY1
, nOldX2
, nOldY2
);
266 // If previously bHasHeader was set and the new range starts on the
267 // same row and intersects the old column range, then don't reset
268 // bHasHeader but assume that the new range still has headers, just
269 // some are empty or numeric.
270 if (!bHasHeader
&& pNoNameData
->HasHeader() && nTab
== nOldTab
&& nStartRow
== nOldY1
&&
271 nStartCol
<= nOldY2
&& nOldY1
<= nEndCol
)
274 // Remove AutoFilter button flags only for sheet-local DB range,
275 // not if a temporary is used.
277 DBAreaDeleted( nOldTab
, nOldX1
, nOldY1
, nOldX2
);
279 pNoNameData
->SetSortParam( ScSortParam() ); // reset parameter
280 pNoNameData
->SetQueryParam( ScQueryParam() );
281 pNoNameData
->SetSubTotalParam( ScSubTotalParam() );
283 pNoNameData
->SetArea( nTab
, nStartCol
,nStartRow
, nEndCol
,nEndRow
); // set anew
284 pNoNameData
->SetByRow( true );
285 pNoNameData
->SetHeader( bHasHeader
);
286 pNoNameData
->SetAutoFilter( false );
290 std::unique_ptr
<ScDBCollection
> pUndoColl
;
292 if (eMode
==SC_DB_IMPORT
)
294 m_pDocument
->PreprocessDBDataUpdate();
295 pUndoColl
.reset( new ScDBCollection( *pColl
) ); // Undo for import range
297 OUString aImport
= ScResId( STR_DBNAME_IMPORT
);
298 tools::Long nCount
= 0;
299 const ScDBData
* pDummy
= nullptr;
300 ScDBCollection::NamedDBs
& rDBs
= pColl
->getNamedDBs();
305 aNewName
= aImport
+ OUString::number( nCount
);
306 pDummy
= rDBs
.findByUpperName(ScGlobal::getCharClass().uppercase(aNewName
));
309 pNoNameData
= new ScDBData( aNewName
, nTab
,
310 nStartCol
,nStartRow
, nEndCol
,nEndRow
,
312 bool ins
= rDBs
.insert(std::unique_ptr
<ScDBData
>(pNoNameData
));
313 assert(ins
); (void)ins
;
317 pNoNameData
= new ScDBData(STR_DB_LOCAL_NONAME
, nTab
,
318 nStartCol
,nStartRow
, nEndCol
,nEndRow
,
320 m_pDocument
->SetAnonymousDBData(nTab
, std::unique_ptr
<ScDBData
>(pNoNameData
));
325 m_pDocument
->CompileHybridFormula();
327 GetUndoManager()->AddUndoAction( std::make_unique
<ScUndoDBData
>( this,
328 std::move(pUndoColl
),
329 std::make_unique
<ScDBCollection
>( *pColl
) ) );
332 // no longer needed to register new range at the Sba
334 // announce "Import1", etc., at the Navigator
335 if (eMode
==SC_DB_IMPORT
)
336 SfxGetpApp()->Broadcast( SfxHint( SfxHintId::ScDbAreasChanged
) );
344 ScDBData
* ScDocShell::GetAnonymousDBData(const ScRange
& rRange
)
346 ScDBCollection
* pColl
= m_pDocument
->GetDBCollection();
350 ScDBData
* pData
= pColl
->getAnonDBs().getByRange(rRange
);
354 if (!pData
->HasHeader())
356 bool bHasHeader
= m_pDocument
->HasColHeader(
357 rRange
.aStart
.Col(), rRange
.aStart
.Row(), rRange
.aEnd
.Col(), rRange
.aEnd
.Row(), rRange
.aStart
.Tab());
358 pData
->SetHeader(bHasHeader
);
364 std::unique_ptr
<ScDBData
> ScDocShell::GetOldAutoDBRange()
366 return std::move(m_pOldAutoDBRange
);
369 void ScDocShell::CancelAutoDBRange()
371 // called when dialog is cancelled
373 if ( !m_pOldAutoDBRange
)
376 SCTAB nTab
= GetCurTab();
377 ScDBData
* pDBData
= m_pDocument
->GetAnonymousDBData(nTab
);
385 pDBData
->GetArea( nRangeTab
, nRangeX1
, nRangeY1
, nRangeX2
, nRangeY2
);
386 DBAreaDeleted( nRangeTab
, nRangeX1
, nRangeY1
, nRangeX2
);
388 *pDBData
= *m_pOldAutoDBRange
; // restore old settings
390 if ( m_pOldAutoDBRange
->HasAutoFilter() )
392 // restore AutoFilter buttons
393 m_pOldAutoDBRange
->GetArea( nRangeTab
, nRangeX1
, nRangeY1
, nRangeX2
, nRangeY2
);
394 m_pDocument
->ApplyFlagsTab( nRangeX1
, nRangeY1
, nRangeX2
, nRangeY1
, nRangeTab
, ScMF::Auto
);
395 PostPaint( nRangeX1
, nRangeY1
, nRangeTab
, nRangeX2
, nRangeY1
, nRangeTab
, PaintPartFlags::Grid
);
399 m_pOldAutoDBRange
.reset();
403 //! merge with docfunc
405 bool ScDocShell::AdjustRowHeight( SCROW nStartRow
, SCROW nEndRow
, SCTAB nTab
)
407 ScSizeDeviceProvider
aProv(this);
409 sc::RowHeightContext
aCxt(m_pDocument
->MaxRow(), aProv
.GetPPTX(), aProv
.GetPPTY(), aZoom
, aZoom
, aProv
.GetDevice());
410 bool bChange
= m_pDocument
->SetOptimalHeight(aCxt
, nStartRow
,nEndRow
, nTab
, true);
414 // tdf#76183: recalculate objects' positions
415 m_pDocument
->SetDrawPageSize(nTab
);
417 PostPaint( 0,nStartRow
,nTab
, m_pDocument
->MaxCol(),m_pDocument
->MaxRow(),nTab
, PaintPartFlags::Grid
|PaintPartFlags::Left
);
423 void ScDocShell::UpdateAllRowHeights( const ScMarkData
* pTabMark
)
425 // update automatic row heights
427 ScSizeDeviceProvider
aProv(this);
429 sc::RowHeightContext
aCxt(m_pDocument
->MaxRow(), aProv
.GetPPTX(), aProv
.GetPPTY(), aZoom
, aZoom
, aProv
.GetDevice());
430 m_pDocument
->UpdateAllRowHeights(aCxt
, pTabMark
);
433 void ScDocShell::UpdateAllRowHeights(const bool bOnlyUsedRows
)
435 // update automatic row heights on all sheets using the newer ScDocRowHeightUpdater
436 ScSizeDeviceProvider
aProv(this);
437 ScDocRowHeightUpdater
aUpdater(*m_pDocument
, aProv
.GetDevice(), aProv
.GetPPTX(),
438 aProv
.GetPPTY(), nullptr);
439 aUpdater
.update(bOnlyUsedRows
);
442 void ScDocShell::UpdatePendingRowHeights( SCTAB nUpdateTab
, bool bBefore
)
444 bool bIsUndoEnabled
= m_pDocument
->IsUndoEnabled();
445 m_pDocument
->EnableUndo( false );
446 m_pDocument
->LockStreamValid( true ); // ignore draw page size (but not formula results)
447 if ( bBefore
) // check all sheets up to nUpdateTab
449 SCTAB nTabCount
= m_pDocument
->GetTableCount();
450 if ( nUpdateTab
>= nTabCount
)
451 nUpdateTab
= nTabCount
-1; // nUpdateTab is inclusive
453 ScMarkData
aUpdateSheets(m_pDocument
->GetSheetLimits());
455 for (nTab
=0; nTab
<=nUpdateTab
; ++nTab
)
456 if ( m_pDocument
->IsPendingRowHeights( nTab
) )
457 aUpdateSheets
.SelectTable( nTab
, true );
459 if (aUpdateSheets
.GetSelectCount())
460 UpdateAllRowHeights(&aUpdateSheets
); // update with a single progress bar
462 for (nTab
=0; nTab
<=nUpdateTab
; ++nTab
)
463 if ( aUpdateSheets
.GetTableSelect( nTab
) )
465 m_pDocument
->UpdatePageBreaks( nTab
);
466 m_pDocument
->SetPendingRowHeights( nTab
, false );
469 else // only nUpdateTab
471 if ( m_pDocument
->IsPendingRowHeights( nUpdateTab
) )
473 AdjustRowHeight( 0, m_pDocument
->MaxRow(), nUpdateTab
);
474 m_pDocument
->UpdatePageBreaks( nUpdateTab
);
475 m_pDocument
->SetPendingRowHeights( nUpdateTab
, false );
478 m_pDocument
->LockStreamValid( false );
479 m_pDocument
->EnableUndo( bIsUndoEnabled
);
482 void ScDocShell::RefreshPivotTables( const ScRange
& rSource
)
484 ScDPCollection
* pColl
= m_pDocument
->GetDPCollection();
488 ScDBDocFunc
aFunc(*this);
489 for (size_t i
= 0, n
= pColl
->GetCount(); i
< n
; ++i
)
491 ScDPObject
& rOld
= (*pColl
)[i
];
493 const ScSheetSourceDesc
* pSheetDesc
= rOld
.GetSheetDesc();
494 if (pSheetDesc
&& pSheetDesc
->GetSourceRange().Intersects(rSource
))
495 aFunc
.UpdatePivotTable(rOld
, true, false);
499 static OUString
lcl_GetAreaName( ScDocument
* pDoc
, const ScArea
* pArea
)
501 ScDBData
* pData
= pDoc
->GetDBAtArea( pArea
->nTab
, pArea
->nColStart
, pArea
->nRowStart
,
502 pArea
->nColEnd
, pArea
->nRowEnd
);
504 return pData
->GetName();
507 pDoc
->GetName( pArea
->nTab
, aName
);
511 static ScDBData
* getUndoData(ScDBData
* pDestData
)
515 return new ScDBData(*pDestData
);
518 void ScDocShell::DoConsolidate( const ScConsolidateParam
& rParam
, bool bRecord
)
526 for (nPos
=0; nPos
<rParam
.nDataAreaCount
; nPos
++)
528 ScArea
const & rArea
= rParam
.pDataAreas
[nPos
];
529 nColSize
= std::max( nColSize
, SCCOL( rArea
.nColEnd
- rArea
.nColStart
+ 1 ) );
530 nRowSize
= std::max( nRowSize
, SCROW( rArea
.nRowEnd
- rArea
.nRowStart
+ 1 ) );
532 // test if source data were moved
533 if (rParam
.bReferenceData
)
534 if (rArea
.nTab
== rParam
.nTab
&& rArea
.nRowEnd
>= rParam
.nRow
)
540 std::unique_ptr
<weld::MessageDialog
> xInfoBox(Application::CreateMessageDialog(GetActiveDialogParent(),
541 VclMessageType::Info
, VclButtonsType::Ok
,
542 ScResId(STR_CONSOLIDATE_ERR1
)));
549 weld::WaitObject
aWait( GetActiveDialogParent() );
550 ScDocShellModificator
aModificator( *this );
553 ScDBData
* pDestData
= m_pDocument
->GetDBAtCursor( rParam
.nCol
, rParam
.nRow
, rParam
.nTab
, ScDBDataPortion::TOP_LEFT
);
555 pDestData
->GetArea(aOldDest
);
557 aData
.SetSize( nColSize
, nRowSize
);
558 aData
.SetFlags( rParam
.eFunction
, rParam
.bByCol
, rParam
.bByRow
, rParam
.bReferenceData
);
559 if ( rParam
.bByCol
|| rParam
.bByRow
)
560 for (nPos
=0; nPos
<rParam
.nDataAreaCount
; nPos
++)
562 ScArea
const & rArea
= rParam
.pDataAreas
[nPos
];
563 aData
.AddFields( m_pDocument
.get(), rArea
.nTab
, rArea
.nColStart
, rArea
.nRowStart
,
564 rArea
.nColEnd
, rArea
.nRowEnd
);
567 for (nPos
=0; nPos
<rParam
.nDataAreaCount
; nPos
++)
569 ScArea
const & rArea
= rParam
.pDataAreas
[nPos
];
570 aData
.AddData( m_pDocument
.get(), rArea
.nTab
, rArea
.nColStart
, rArea
.nRowStart
,
571 rArea
.nColEnd
, rArea
.nRowEnd
);
572 aData
.AddName( lcl_GetAreaName(m_pDocument
.get(), &rArea
) );
575 aData
.GetSize( nColSize
, nRowSize
);
576 if (bRecord
&& nColSize
> 0 && nRowSize
> 0)
578 std::unique_ptr
<ScDBData
> pUndoData(getUndoData(pDestData
));
580 SCTAB nDestTab
= rParam
.nTab
;
581 ScArea
aDestArea( rParam
.nTab
, rParam
.nCol
, rParam
.nRow
,
582 rParam
.nCol
+nColSize
-1, rParam
.nRow
+nRowSize
-1 );
583 if (rParam
.bByCol
) ++aDestArea
.nColEnd
;
584 if (rParam
.bByRow
) ++aDestArea
.nRowEnd
;
586 if (rParam
.bReferenceData
)
588 SCTAB nTabCount
= m_pDocument
->GetTableCount();
589 SCROW nInsertCount
= aData
.GetInsertCount();
592 ScOutlineTable
* pTable
= m_pDocument
->GetOutlineTable( nDestTab
);
593 std::unique_ptr
<ScOutlineTable
> pUndoTab(pTable
? new ScOutlineTable( *pTable
) : nullptr);
595 ScDocumentUniquePtr
pUndoDoc(new ScDocument( SCDOCMODE_UNDO
));
596 pUndoDoc
->InitUndo( *m_pDocument
, 0, nTabCount
-1, false, true );
599 m_pDocument
->CopyToDocument(0, 0, nDestTab
, m_pDocument
->MaxCol(), m_pDocument
->MaxRow(), nDestTab
,
600 InsertDeleteFlags::NONE
, false, *pUndoDoc
);
603 m_pDocument
->CopyToDocument(0, 0, 0, m_pDocument
->MaxCol(), m_pDocument
->MaxRow(), nTabCount
-1,
604 InsertDeleteFlags::FORMULA
, false, *pUndoDoc
);
606 // complete output rows
607 m_pDocument
->CopyToDocument(0, aDestArea
.nRowStart
, nDestTab
,
608 m_pDocument
->MaxCol(),aDestArea
.nRowEnd
, nDestTab
,
609 InsertDeleteFlags::ALL
, false, *pUndoDoc
);
613 m_pDocument
->CopyToDocument(aOldDest
, InsertDeleteFlags::ALL
, false, *pUndoDoc
);
615 GetUndoManager()->AddUndoAction(
616 std::make_unique
<ScUndoConsolidate
>( this, aDestArea
, rParam
, std::move(pUndoDoc
),
617 true, nInsertCount
, std::move(pUndoTab
), std::move(pUndoData
) ) );
621 ScDocumentUniquePtr
pUndoDoc(new ScDocument( SCDOCMODE_UNDO
));
622 pUndoDoc
->InitUndo( *m_pDocument
, aDestArea
.nTab
, aDestArea
.nTab
);
624 m_pDocument
->CopyToDocument(aDestArea
.nColStart
, aDestArea
.nRowStart
, aDestArea
.nTab
,
625 aDestArea
.nColEnd
, aDestArea
.nRowEnd
, aDestArea
.nTab
,
626 InsertDeleteFlags::ALL
, false, *pUndoDoc
);
630 m_pDocument
->CopyToDocument(aOldDest
, InsertDeleteFlags::ALL
, false, *pUndoDoc
);
632 GetUndoManager()->AddUndoAction(
633 std::make_unique
<ScUndoConsolidate
>( this, aDestArea
, rParam
, std::move(pUndoDoc
),
634 false, 0, nullptr, std::move(pUndoData
) ) );
638 if (pDestData
) // delete / adjust destination range
640 m_pDocument
->DeleteAreaTab(aOldDest
, InsertDeleteFlags::CONTENTS
);
641 pDestData
->SetArea( rParam
.nTab
, rParam
.nCol
, rParam
.nRow
,
642 rParam
.nCol
+ nColSize
- 1, rParam
.nRow
+ nRowSize
- 1 );
643 pDestData
->SetHeader( rParam
.bByRow
);
646 aData
.OutputToDocument( *m_pDocument
, rParam
.nCol
, rParam
.nRow
, rParam
.nTab
);
648 SCCOL nPaintStartCol
= rParam
.nCol
;
649 SCROW nPaintStartRow
= rParam
.nRow
;
650 SCCOL nPaintEndCol
= nPaintStartCol
+ nColSize
- 1;
651 SCROW nPaintEndRow
= nPaintStartRow
+ nRowSize
- 1;
652 PaintPartFlags nPaintFlags
= PaintPartFlags::Grid
;
657 if (rParam
.bReferenceData
)
660 nPaintEndCol
= m_pDocument
->MaxCol();
661 nPaintEndRow
= m_pDocument
->MaxRow();
662 nPaintFlags
|= PaintPartFlags::Left
| PaintPartFlags::Size
;
666 if ( aOldDest
.aEnd
.Col() > nPaintEndCol
)
667 nPaintEndCol
= aOldDest
.aEnd
.Col();
668 if ( aOldDest
.aEnd
.Row() > nPaintEndRow
)
669 nPaintEndRow
= aOldDest
.aEnd
.Row();
671 PostPaint( nPaintStartCol
, nPaintStartRow
, rParam
.nTab
,
672 nPaintEndCol
, nPaintEndRow
, rParam
.nTab
, nPaintFlags
);
673 aModificator
.SetDocumentModified();
676 void ScDocShell::UseScenario( SCTAB nTab
, const OUString
& rName
, bool bRecord
)
678 if (!m_pDocument
->IsScenario(nTab
))
680 SCTAB nTabCount
= m_pDocument
->GetTableCount();
681 SCTAB nSrcTab
= SCTAB_MAX
;
682 SCTAB nEndTab
= nTab
;
684 while ( nEndTab
+1 < nTabCount
&& m_pDocument
->IsScenario(nEndTab
+1) )
687 if (nSrcTab
> MAXTAB
) // still searching for the scenario?
689 m_pDocument
->GetName( nEndTab
, aCompare
);
690 if (aCompare
== rName
)
691 nSrcTab
= nEndTab
; // found
694 if (ValidTab(nSrcTab
))
696 if ( m_pDocument
->TestCopyScenario( nSrcTab
, nTab
) ) // test cell protection
698 ScDocShellModificator
aModificator( *this );
699 ScMarkData
aScenMark(m_pDocument
->GetSheetLimits());
700 m_pDocument
->MarkScenario( nSrcTab
, nTab
, aScenMark
);
701 const ScRange
& aMultiRange
= aScenMark
.GetMultiMarkArea();
702 SCCOL nStartCol
= aMultiRange
.aStart
.Col();
703 SCROW nStartRow
= aMultiRange
.aStart
.Row();
704 SCCOL nEndCol
= aMultiRange
.aEnd
.Col();
705 SCROW nEndRow
= aMultiRange
.aEnd
.Row();
709 ScDocumentUniquePtr
pUndoDoc(new ScDocument( SCDOCMODE_UNDO
));
710 pUndoDoc
->InitUndo( *m_pDocument
, nTab
,nEndTab
); // also all scenarios
712 m_pDocument
->CopyToDocument(nStartCol
, nStartRow
, nTab
,
713 nEndCol
, nEndRow
, nTab
, InsertDeleteFlags::ALL
,
714 true, *pUndoDoc
, &aScenMark
);
716 for (SCTAB i
=nTab
+1; i
<=nEndTab
; i
++)
718 pUndoDoc
->SetScenario( i
, true );
721 ScScenarioFlags nScenFlags
;
722 m_pDocument
->GetScenarioData( i
, aComment
, aColor
, nScenFlags
);
723 pUndoDoc
->SetScenarioData( i
, aComment
, aColor
, nScenFlags
);
724 bool bActive
= m_pDocument
->IsActiveScenario( i
);
725 pUndoDoc
->SetActiveScenario( i
, bActive
);
726 // At copy-back scenarios also contents
727 if ( nScenFlags
& ScScenarioFlags::TwoWay
)
728 m_pDocument
->CopyToDocument(0, 0, i
, m_pDocument
->MaxCol(), m_pDocument
->MaxRow(), i
,
729 InsertDeleteFlags::ALL
, false, *pUndoDoc
);
732 GetUndoManager()->AddUndoAction(
733 std::make_unique
<ScUndoUseScenario
>( this, aScenMark
,
734 ScArea( nTab
,nStartCol
,nStartRow
,nEndCol
,nEndRow
),
735 std::move(pUndoDoc
), rName
) );
738 m_pDocument
->CopyScenario( nSrcTab
, nTab
);
740 sc::SetFormulaDirtyContext aCxt
;
741 m_pDocument
->SetAllFormulasDirty(aCxt
);
743 // paint all, because the active scenario may be modified in other ranges;
744 //! only if there are visible frames?
745 PostPaint( 0,0,nTab
, m_pDocument
->MaxCol(),m_pDocument
->MaxRow(),nTab
, PaintPartFlags::Grid
);
746 aModificator
.SetDocumentModified();
750 std::unique_ptr
<weld::MessageDialog
> xInfoBox(Application::CreateMessageDialog(GetActiveDialogParent(),
751 VclMessageType::Info
, VclButtonsType::Ok
,
752 ScResId(STR_PROTECTIONERR
)));
758 std::unique_ptr
<weld::MessageDialog
> xInfoBox(Application::CreateMessageDialog(GetActiveDialogParent(),
759 VclMessageType::Info
, VclButtonsType::Ok
,
760 ScResId(STR_SCENARIO_NOTFOUND
)));
766 OSL_FAIL( "UseScenario on Scenario-Sheet" );
770 void ScDocShell::ModifyScenario( SCTAB nTab
, const OUString
& rName
, const OUString
& rComment
,
771 const Color
& rColor
, ScScenarioFlags nFlags
)
775 m_pDocument
->GetName( nTab
, aOldName
);
776 OUString aOldComment
;
778 ScScenarioFlags nOldFlags
;
779 m_pDocument
->GetScenarioData( nTab
, aOldComment
, aOldColor
, nOldFlags
);
780 GetUndoManager()->AddUndoAction(
781 std::make_unique
<ScUndoScenarioFlags
>(this, nTab
,
782 aOldName
, rName
, aOldComment
, rComment
,
783 aOldColor
, rColor
, nOldFlags
, nFlags
) );
786 ScDocShellModificator
aModificator( *this );
787 m_pDocument
->RenameTab( nTab
, rName
);
788 m_pDocument
->SetScenarioData( nTab
, rComment
, rColor
, nFlags
);
790 aModificator
.SetDocumentModified();
792 if (aOldName
!= rName
)
793 SfxGetpApp()->Broadcast( SfxHint( SfxHintId::ScTablesChanged
) );
795 SfxBindings
* pBindings
= GetViewBindings();
797 pBindings
->Invalidate( SID_SELECT_SCENARIO
);
800 SCTAB
ScDocShell::MakeScenario( SCTAB nTab
, const OUString
& rName
, const OUString
& rComment
,
801 const Color
& rColor
, ScScenarioFlags nFlags
,
802 ScMarkData
& rMark
, bool bRecord
)
805 if (rMark
.IsMultiMarked())
807 SCTAB nNewTab
= nTab
+ 1;
808 while (m_pDocument
->IsScenario(nNewTab
))
811 bool bCopyAll
= ( (nFlags
& ScScenarioFlags::CopyAll
) != ScScenarioFlags::NONE
);
812 const ScMarkData
* pCopyMark
= nullptr;
816 ScDocShellModificator
aModificator( *this );
819 m_pDocument
->BeginDrawUndo(); // drawing layer must do its own undo actions
821 if (m_pDocument
->CopyTab( nTab
, nNewTab
, pCopyMark
))
825 GetUndoManager()->AddUndoAction(
826 std::make_unique
<ScUndoMakeScenario
>( this, nTab
, nNewTab
,
827 rName
, rComment
, rColor
, nFlags
, rMark
));
830 m_pDocument
->RenameTab( nNewTab
, rName
);
831 m_pDocument
->SetScenario( nNewTab
, true );
832 m_pDocument
->SetScenarioData( nNewTab
, rComment
, rColor
, nFlags
);
834 ScMarkData aDestMark
= rMark
;
835 aDestMark
.SelectOneTable( nNewTab
);
837 //! test for filter / buttons / merging
839 ScPatternAttr
aProtPattern(m_pDocument
->getCellAttributeHelper());
840 aProtPattern
.GetItemSet().Put( ScProtectionAttr( true ) );
841 m_pDocument
->ApplyPatternAreaTab( 0,0, m_pDocument
->MaxCol(),m_pDocument
->MaxRow(), nNewTab
, aProtPattern
);
843 ScPatternAttr
aPattern(m_pDocument
->getCellAttributeHelper());
844 aPattern
.GetItemSet().Put( ScMergeFlagAttr( ScMF::Scenario
) );
845 aPattern
.GetItemSet().Put( ScProtectionAttr( true ) );
846 m_pDocument
->ApplySelectionPattern( aPattern
, aDestMark
);
849 m_pDocument
->SetVisible( nNewTab
, false );
851 // this is the active scenario, then
852 m_pDocument
->CopyScenario( nNewTab
, nTab
, true ); // sal_True - don't copy anything from scenario
854 if (nFlags
& ScScenarioFlags::ShowFrame
)
855 PostPaint( 0,0,nTab
, m_pDocument
->MaxCol(),m_pDocument
->MaxRow(),nTab
, PaintPartFlags::Grid
); // paint frames
856 PostPaintExtras(); // table tab
857 aModificator
.SetDocumentModified();
859 // A scenario tab is like a hidden sheet, broadcasting also
860 // notifies ScTabViewShell to add an ScViewData::maTabData entry.
861 Broadcast( ScTablesHint( SC_TAB_INSERTED
, nNewTab
));
862 SfxGetpApp()->Broadcast( SfxHint( SfxHintId::ScTablesChanged
) );
870 bool ScDocShell::TransferTab( ScDocShell
& rSrcDocShell
, SCTAB nSrcPos
,
871 SCTAB nDestPos
, bool bInsertNew
,
872 bool bNotifyAndPaint
)
874 ScDocument
& rSrcDoc
= rSrcDocShell
.GetDocument();
876 // set the transferred area to the copyparam to make adjusting formulas possible
878 ScRange
aRange(0, 0, nSrcPos
, m_pDocument
->MaxCol(), m_pDocument
->MaxRow(), nSrcPos
);
879 aParam
.maRanges
.push_back(aRange
);
880 rSrcDoc
.SetClipParam(aParam
);
882 bool bValid
= m_pDocument
->TransferTab( rSrcDoc
, nSrcPos
, nDestPos
,
883 bInsertNew
); // no insert
885 // TransferTab doesn't copy drawing objects with bInsertNew=FALSE
886 if ( bValid
&& !bInsertNew
)
887 m_pDocument
->TransferDrawPage( rSrcDoc
, nSrcPos
, nDestPos
);
889 if(bValid
&& rSrcDoc
.IsScenario( nSrcPos
))
893 ScScenarioFlags nFlags
;
895 rSrcDoc
.GetScenarioData( nSrcPos
, aComment
,aColor
, nFlags
);
896 m_pDocument
->SetScenario(nDestPos
,true);
897 m_pDocument
->SetScenarioData(nDestPos
,aComment
,aColor
,nFlags
);
898 bool bActive
= rSrcDoc
.IsActiveScenario(nSrcPos
);
899 m_pDocument
->SetActiveScenario(nDestPos
, bActive
);
901 bool bVisible
= rSrcDoc
.IsVisible(nSrcPos
);
902 m_pDocument
->SetVisible(nDestPos
,bVisible
);
906 if ( bValid
&& rSrcDoc
.IsTabProtected( nSrcPos
) )
907 m_pDocument
->SetTabProtection(nDestPos
, rSrcDoc
.GetTabProtection(nSrcPos
));
908 if ( bNotifyAndPaint
)
910 Broadcast( ScTablesHint( SC_TAB_INSERTED
, nDestPos
) );
917 bool ScDocShell::MoveTable( SCTAB nSrcTab
, SCTAB nDestTab
, bool bCopy
, bool bRecord
)
919 ScDocShellModificator
aModificator( *this );
921 // #i92477# be consistent with ScDocFunc::InsertTable: any index past the last sheet means "append"
922 // #i101139# nDestTab must be the target position, not APPEND (for CopyTabProtection etc.)
923 if ( nDestTab
>= m_pDocument
->GetTableCount() )
924 nDestTab
= m_pDocument
->GetTableCount();
929 m_pDocument
->BeginDrawUndo(); // drawing layer must do its own undo actions
931 OUString sSrcCodeName
;
932 m_pDocument
->GetCodeName( nSrcTab
, sSrcCodeName
);
933 if (!m_pDocument
->CopyTab( nSrcTab
, nDestTab
))
940 SCTAB nAdjSource
= nSrcTab
;
941 if ( nDestTab
<= nSrcTab
)
942 ++nAdjSource
; // new position of source table after CopyTab
944 if ( m_pDocument
->IsTabProtected( nAdjSource
) )
945 m_pDocument
->CopyTabProtection(nAdjSource
, nDestTab
);
949 unique_ptr
< vector
<SCTAB
> > pSrcList(new vector
<SCTAB
>(1, nSrcTab
));
950 unique_ptr
< vector
<SCTAB
> > pDestList(new vector
<SCTAB
>(1, nDestTab
));
951 GetUndoManager()->AddUndoAction(
952 std::make_unique
<ScUndoCopyTab
>(this, std::move(pSrcList
), std::move(pDestList
)));
955 bool bVbaEnabled
= m_pDocument
->IsInVBAMode();
958 OUString
aLibName( u
"Standard"_ustr
);
959 Reference
< XLibraryContainer
> xLibContainer
= GetBasicContainer();
960 Reference
< XVBACompatibility
> xVBACompat( xLibContainer
, UNO_QUERY
);
962 if ( xVBACompat
.is() )
964 aLibName
= xVBACompat
->getProjectName();
967 SCTAB nTabToUse
= nDestTab
;
968 if ( nDestTab
== SC_TAB_APPEND
)
969 nTabToUse
= m_pDocument
->GetMaxTableNumber() - 1;
973 Reference
< XNameContainer
> xLib
;
974 if( xLibContainer
.is() )
976 css::uno::Any aLibAny
= xLibContainer
->getByName( aLibName
);
981 xLib
->getByName( sSrcCodeName
) >>= sSource
;
984 catch ( const css::uno::Exception
& )
987 VBA_InsertModule( *m_pDocument
, nTabToUse
, sSource
);
990 Broadcast( ScTablesHint( SC_TAB_COPIED
, nSrcTab
, nDestTab
) );
994 if ( m_pDocument
->GetChangeTrack() )
997 if ( nSrcTab
<nDestTab
&& nDestTab
!=SC_TAB_APPEND
)
1000 if ( nSrcTab
== nDestTab
)
1002 //! allow only for api calls?
1003 return true; // nothing to do, but valid
1006 std::optional
<ScProgress
> pProgress(std::in_place
, this, ScResId(STR_UNDO_MOVE_TAB
),
1007 m_pDocument
->GetCodeCount(), true);
1008 bool bDone
= m_pDocument
->MoveTab( nSrcTab
, nDestTab
, &*pProgress
);
1016 unique_ptr
< vector
<SCTAB
> > pSrcList(new vector
<SCTAB
>(1, nSrcTab
));
1017 unique_ptr
< vector
<SCTAB
> > pDestList(new vector
<SCTAB
>(1, nDestTab
));
1018 GetUndoManager()->AddUndoAction(
1019 std::make_unique
<ScUndoMoveTab
>(this, std::move(pSrcList
), std::move(pDestList
)));
1022 Broadcast( ScTablesHint( SC_TAB_MOVED
, nSrcTab
, nDestTab
) );
1027 aModificator
.SetDocumentModified();
1028 SfxGetpApp()->Broadcast( SfxHint( SfxHintId::ScTablesChanged
) );
1033 IMPL_LINK( ScDocShell
, RefreshDBDataHdl
, Timer
*, pRefreshTimer
, void )
1035 ScDBDocFunc
aFunc(*this);
1037 ScDBData
* pDBData
= static_cast<ScDBData
*>(pRefreshTimer
);
1038 ScImportParam aImportParam
;
1039 pDBData
->GetImportParam( aImportParam
);
1040 if (aImportParam
.bImport
&& !pDBData
->HasImportSelection())
1043 pDBData
->GetArea( aRange
);
1044 bool bContinue
= aFunc
.DoImport( aRange
.aStart
.Tab(), aImportParam
, nullptr ); //! Api-Flag as parameter
1045 // internal operations (sort, query, subtotal) only if no error
1048 aFunc
.RepeatDB( pDBData
->GetName(), true, true );
1049 RefreshPivotTables(aRange
);
1054 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */