/src/libreoffice/sc/source/ui/docshell/docsh5.cxx
Line | Count | Source |
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 <memory> |
21 | | #include <sal/config.h> |
22 | | |
23 | | #include <cassert> |
24 | | |
25 | | #include <osl/diagnose.h> |
26 | | #include <vcl/svapp.hxx> |
27 | | #include <vcl/vclenum.hxx> |
28 | | #include <vcl/weld/MessageDialog.hxx> |
29 | | #include <vcl/weld/weld.hxx> |
30 | | #include <sfx2/app.hxx> |
31 | | #include <sfx2/bindings.hxx> |
32 | | #include <unotools/charclass.hxx> |
33 | | |
34 | | #include <com/sun/star/script/vba/XVBACompatibility.hpp> |
35 | | |
36 | | #include <dociter.hxx> |
37 | | #include <docsh.hxx> |
38 | | #include <global.hxx> |
39 | | #include <globstr.hrc> |
40 | | #include <scresid.hxx> |
41 | | #include <globalnames.hxx> |
42 | | #include <undodat.hxx> |
43 | | #include <undotab.hxx> |
44 | | #include <undoblk.hxx> |
45 | | #include <dpobject.hxx> |
46 | | #include <dpshttab.hxx> |
47 | | #include <dbdocfun.hxx> |
48 | | #include <consoli.hxx> |
49 | | #include <dbdata.hxx> |
50 | | #include <progress.hxx> |
51 | | #include <olinetab.hxx> |
52 | | #include <patattr.hxx> |
53 | | #include <attrib.hxx> |
54 | | #include <docpool.hxx> |
55 | | #include <uiitems.hxx> |
56 | | #include <sc.hrc> |
57 | | #include <sizedev.hxx> |
58 | | #include <clipparam.hxx> |
59 | | #include <rowheightcontext.hxx> |
60 | | #include <refupdatecontext.hxx> |
61 | | |
62 | | using com::sun::star::script::XLibraryContainer; |
63 | | using com::sun::star::script::vba::XVBACompatibility; |
64 | | using com::sun::star::container::XNameContainer; |
65 | | using com::sun::star::uno::Reference; |
66 | | using com::sun::star::uno::UNO_QUERY; |
67 | | |
68 | | // former viewfunc/dbfunc methods |
69 | | |
70 | | void ScDocShell::ErrorMessage(TranslateId pGlobStrId) |
71 | 0 | { |
72 | | //! StopMarking at the (active) view? |
73 | |
|
74 | 0 | weld::Window* pParent = GetActiveDialogParent(); |
75 | 0 | weld::WaitObject aWaitOff( pParent ); |
76 | 0 | bool bFocus = pParent && pParent->has_focus(); |
77 | |
|
78 | 0 | if (pGlobStrId && pGlobStrId == STR_PROTECTIONERR) |
79 | 0 | { |
80 | 0 | if (IsReadOnly()) |
81 | 0 | { |
82 | 0 | pGlobStrId = STR_READONLYERR; |
83 | 0 | } |
84 | 0 | } |
85 | |
|
86 | 0 | std::unique_ptr<weld::MessageDialog> xInfoBox(Application::CreateMessageDialog(pParent, |
87 | 0 | VclMessageType::Info, VclButtonsType::Ok, |
88 | 0 | ScResId(pGlobStrId))); |
89 | 0 | xInfoBox->run(); |
90 | |
|
91 | 0 | if (bFocus) |
92 | 0 | pParent->grab_focus(); |
93 | 0 | } |
94 | | |
95 | | bool ScDocShell::IsEditable() const |
96 | 20.3k | { |
97 | | // import into read-only document is possible - must be extended if other filters use api |
98 | | // #i108547# MSOOXML filter uses "IsChangeReadOnlyEnabled" property |
99 | | |
100 | 20.3k | return !IsReadOnly() || m_pDocument->IsImportingXML() || m_pDocument->IsChangeReadOnlyEnabled(); |
101 | 20.3k | } |
102 | | |
103 | | void ScDocShell::DBAreaDeleted( SCTAB nTab, SCCOL nX1, SCROW nY1, SCCOL nX2 ) |
104 | 0 | { |
105 | 0 | ScDocShellModificator aModificator( *this ); |
106 | | // the auto-filter is in the first row of the area |
107 | 0 | m_pDocument->RemoveFlagsTab( nX1, nY1, nX2, nY1, nTab, ScMF::Auto ); |
108 | 0 | PostPaint( nX1, nY1, nTab, nX2, nY1, nTab, PaintPartFlags::Grid ); |
109 | | // No SetDocumentModified, as the unnamed database range might have to be restored later. |
110 | | // The UNO hint is broadcast directly instead, to keep UNO objects in valid state. |
111 | 0 | m_pDocument->BroadcastUno( SfxHint( SfxHintId::DataChanged ) ); |
112 | 0 | } |
113 | | |
114 | | ScDBData* ScDocShell::GetDBData( const ScRange& rMarked, ScGetDBMode eMode, ScGetDBSelection eSel ) |
115 | 0 | { |
116 | 0 | SCCOL nCol = rMarked.aStart.Col(); |
117 | 0 | SCROW nRow = rMarked.aStart.Row(); |
118 | 0 | SCTAB nTab = rMarked.aStart.Tab(); |
119 | |
|
120 | 0 | SCCOL nStartCol = nCol; |
121 | 0 | SCROW nStartRow = nRow; |
122 | 0 | SCTAB nStartTab = nTab; |
123 | 0 | SCCOL nEndCol = rMarked.aEnd.Col(); |
124 | 0 | SCROW nEndRow = rMarked.aEnd.Row(); |
125 | | // Not simply GetDBAtCursor: The continuous data range for "unnamed" (GetDataArea) may be |
126 | | // located next to the cursor; so a named DB range needs to be searched for there as well. |
127 | 0 | ScDBCollection* pColl = m_pDocument->GetDBCollection(); |
128 | 0 | ScDBData* pData = m_pDocument->GetDBAtArea( nTab, nStartCol, nStartRow, nEndCol, nEndRow ); |
129 | 0 | if (!pData) |
130 | 0 | pData = pColl->GetDBNearCursor(nCol, nRow, nTab ); |
131 | |
|
132 | 0 | bool bSelected = ( eSel == ScGetDBSelection::ForceMark || |
133 | 0 | (rMarked.aStart != rMarked.aEnd && eSel != ScGetDBSelection::RowDown) ); |
134 | 0 | bool bOnlyDown = (!bSelected && eSel == ScGetDBSelection::RowDown && rMarked.aStart.Row() == rMarked.aEnd.Row()); |
135 | |
|
136 | 0 | bool bUseThis = false; |
137 | 0 | if (pData) |
138 | 0 | { |
139 | | // take range, if nothing else is marked |
140 | |
|
141 | 0 | SCTAB nDummy; |
142 | 0 | SCCOL nOldCol1; |
143 | 0 | SCROW nOldRow1; |
144 | 0 | SCCOL nOldCol2; |
145 | 0 | SCROW nOldRow2; |
146 | 0 | pData->GetArea( nDummy, nOldCol1,nOldRow1, nOldCol2,nOldRow2 ); |
147 | 0 | bool bIsNoName = ( pData->GetName() == STR_DB_LOCAL_NONAME ); |
148 | |
|
149 | 0 | if (!bSelected) |
150 | 0 | { |
151 | 0 | bUseThis = true; |
152 | 0 | if ( bIsNoName && (eMode == SC_DB_MAKE || eMode == SC_DB_AUTOFILTER) ) |
153 | 0 | { |
154 | | // If nothing marked or only one row marked, adapt |
155 | | // "unnamed" to contiguous area. |
156 | 0 | nStartCol = nCol; |
157 | 0 | nStartRow = nRow; |
158 | 0 | if (bOnlyDown) |
159 | 0 | { |
160 | 0 | nEndCol = rMarked.aEnd.Col(); |
161 | 0 | nEndRow = rMarked.aEnd.Row(); |
162 | 0 | } |
163 | 0 | else |
164 | 0 | { |
165 | 0 | nEndCol = nStartCol; |
166 | 0 | nEndRow = nStartRow; |
167 | 0 | } |
168 | 0 | m_pDocument->GetDataArea( nTab, nStartCol, nStartRow, nEndCol, nEndRow, false, bOnlyDown ); |
169 | 0 | if ( nOldCol1 != nStartCol || nOldCol2 != nEndCol || nOldRow1 != nStartRow ) |
170 | 0 | bUseThis = false; // doesn't fit at all |
171 | 0 | else if ( nOldRow2 != nEndRow ) |
172 | 0 | { |
173 | | // extend range to new end row |
174 | 0 | pData->SetArea( nTab, nOldCol1,nOldRow1, nOldCol2,nEndRow ); |
175 | 0 | } |
176 | 0 | } |
177 | 0 | } |
178 | 0 | else |
179 | 0 | { |
180 | 0 | if ( nOldCol1 == nStartCol && nOldRow1 == nStartRow && |
181 | 0 | nOldCol2 == nEndCol && nOldRow2 == nEndRow ) // marked precisely? |
182 | 0 | bUseThis = true; |
183 | 0 | else |
184 | 0 | bUseThis = false; // always take marking (Bug 11964) |
185 | 0 | } |
186 | | |
187 | | // never take "unnamed" for import |
188 | |
|
189 | 0 | if ( bUseThis && eMode == SC_DB_IMPORT && bIsNoName ) |
190 | 0 | bUseThis = false; |
191 | 0 | } |
192 | |
|
193 | 0 | if ( bUseThis ) |
194 | 0 | { |
195 | 0 | pData->GetArea( nStartTab, nStartCol,nStartRow, nEndCol,nEndRow ); |
196 | 0 | } |
197 | | // tdf#168478 - use the previously found range rather than returning an empty one |
198 | 0 | else if ( eMode != SC_DB_OLD ) |
199 | 0 | { |
200 | 0 | if ( !bSelected ) |
201 | 0 | { // continuous range |
202 | 0 | nStartCol = nCol; |
203 | 0 | nStartRow = nRow; |
204 | 0 | if (bOnlyDown) |
205 | 0 | { |
206 | 0 | nEndCol = rMarked.aEnd.Col(); |
207 | 0 | nEndRow = rMarked.aEnd.Row(); |
208 | 0 | } |
209 | 0 | else |
210 | 0 | { |
211 | 0 | nEndCol = nStartCol; |
212 | 0 | nEndRow = nStartRow; |
213 | 0 | } |
214 | 0 | m_pDocument->GetDataArea( nTab, nStartCol, nStartRow, nEndCol, nEndRow, false, bOnlyDown ); |
215 | 0 | } |
216 | |
|
217 | 0 | bool bHasHeader = m_pDocument->HasColHeader( nStartCol,nStartRow, nEndCol,nEndRow, nTab ); |
218 | |
|
219 | 0 | ScDBData* pNoNameData = m_pDocument->GetAnonymousDBData(nTab); |
220 | 0 | if ( eMode != SC_DB_IMPORT && pNoNameData) |
221 | 0 | { |
222 | | // Do not reset AutoFilter range during temporary operations on |
223 | | // other ranges, use the document global temporary anonymous range |
224 | | // instead. But, if AutoFilter is to be toggled then do use the |
225 | | // sheet-local DB range. |
226 | 0 | bool bSheetLocal = true; |
227 | 0 | if (eMode != SC_DB_AUTOFILTER && pNoNameData->HasAutoFilter()) |
228 | 0 | { |
229 | 0 | bSheetLocal = false; |
230 | 0 | pNoNameData = m_pDocument->GetAnonymousDBData(); |
231 | 0 | if (!pNoNameData) |
232 | 0 | { |
233 | 0 | m_pDocument->SetAnonymousDBData( std::unique_ptr<ScDBData>(new ScDBData( STR_DB_LOCAL_NONAME, |
234 | 0 | nTab, nStartCol, nStartRow, nEndCol, nEndRow, true, bHasHeader) ) ); |
235 | 0 | pNoNameData = m_pDocument->GetAnonymousDBData(); |
236 | 0 | } |
237 | | // ScDocShell::CancelAutoDBRange() would restore the |
238 | | // sheet-local anonymous DBData from pOldAutoDBRange, unset so |
239 | | // that won't happen with data of a previous sheet-local |
240 | | // DBData. |
241 | 0 | m_pOldAutoDBRange.reset(); |
242 | 0 | } |
243 | 0 | else if (!m_pOldAutoDBRange) |
244 | 0 | { |
245 | | // store the old unnamed database range with its settings for undo |
246 | | // (store at the first change, get the state before all changes) |
247 | 0 | m_pOldAutoDBRange.reset( new ScDBData( *pNoNameData ) ); |
248 | 0 | } |
249 | 0 | else if (m_pOldAutoDBRange->GetTab() != pNoNameData->GetTab()) |
250 | 0 | { |
251 | | // Different sheet-local unnamed DB range than the previous one. |
252 | 0 | *m_pOldAutoDBRange = *pNoNameData; |
253 | 0 | } |
254 | |
|
255 | 0 | SCCOL nOldX1; // take old range away cleanly |
256 | 0 | SCROW nOldY1; //! (UNDO ???) |
257 | 0 | SCCOL nOldX2; |
258 | 0 | SCROW nOldY2; |
259 | 0 | SCTAB nOldTab; |
260 | 0 | pNoNameData->GetArea( nOldTab, nOldX1, nOldY1, nOldX2, nOldY2 ); |
261 | | |
262 | | // If previously bHasHeader was set and the new range starts on the |
263 | | // same row and intersects the old column range, then don't reset |
264 | | // bHasHeader but assume that the new range still has headers, just |
265 | | // some are empty or numeric. |
266 | 0 | if (!bHasHeader && pNoNameData->HasHeader() && nTab == nOldTab && nStartRow == nOldY1 && |
267 | 0 | nStartCol <= nOldY2 && nOldY1 <= nEndCol) |
268 | 0 | bHasHeader = true; |
269 | | |
270 | | // Remove AutoFilter button flags only for sheet-local DB range, |
271 | | // not if a temporary is used. |
272 | 0 | if (bSheetLocal) |
273 | 0 | DBAreaDeleted( nOldTab, nOldX1, nOldY1, nOldX2 ); |
274 | |
|
275 | 0 | pNoNameData->SetSortParam( ScSortParam() ); // reset parameter |
276 | 0 | pNoNameData->SetQueryParam( ScQueryParam() ); |
277 | 0 | pNoNameData->SetSubTotalParam( ScSubTotalParam() ); |
278 | |
|
279 | 0 | pNoNameData->SetArea( nTab, nStartCol,nStartRow, nEndCol,nEndRow ); // set anew |
280 | 0 | pNoNameData->SetByRow( true ); |
281 | 0 | pNoNameData->SetHeader( bHasHeader ); |
282 | 0 | pNoNameData->SetAutoFilter( false ); |
283 | 0 | } |
284 | 0 | else |
285 | 0 | { |
286 | 0 | std::unique_ptr<ScDBCollection> pUndoColl; |
287 | |
|
288 | 0 | if (eMode==SC_DB_IMPORT) |
289 | 0 | { |
290 | 0 | m_pDocument->PreprocessDBDataUpdate(); |
291 | 0 | pUndoColl.reset( new ScDBCollection( *pColl ) ); // Undo for import range |
292 | |
|
293 | 0 | OUString aImport = ScResId( STR_DBNAME_IMPORT ); |
294 | 0 | tools::Long nCount = 0; |
295 | 0 | const ScDBData* pDummy = nullptr; |
296 | 0 | ScDBCollection::NamedDBs& rDBs = pColl->getNamedDBs(); |
297 | 0 | OUString aNewName; |
298 | 0 | do |
299 | 0 | { |
300 | 0 | ++nCount; |
301 | 0 | aNewName = aImport + OUString::number( nCount ); |
302 | 0 | pDummy = rDBs.findByUpperName(ScGlobal::getCharClass().uppercase(aNewName)); |
303 | 0 | } |
304 | 0 | while (pDummy); |
305 | 0 | pNoNameData = new ScDBData( aNewName, nTab, |
306 | 0 | nStartCol,nStartRow, nEndCol,nEndRow, |
307 | 0 | true, bHasHeader ); |
308 | 0 | bool ins = rDBs.insert(std::unique_ptr<ScDBData>(pNoNameData)); |
309 | 0 | assert(ins); (void)ins; |
310 | 0 | } |
311 | 0 | else |
312 | 0 | { |
313 | 0 | pNoNameData = new ScDBData(STR_DB_LOCAL_NONAME, nTab, |
314 | 0 | nStartCol,nStartRow, nEndCol,nEndRow, |
315 | 0 | true, bHasHeader ); |
316 | 0 | m_pDocument->SetAnonymousDBData(nTab, std::unique_ptr<ScDBData>(pNoNameData)); |
317 | 0 | } |
318 | |
|
319 | 0 | if ( pUndoColl ) |
320 | 0 | { |
321 | 0 | m_pDocument->CompileHybridFormula(); |
322 | |
|
323 | 0 | GetUndoManager()->AddUndoAction( std::make_unique<ScUndoDBData>( *this, u""_ustr, |
324 | 0 | std::move(pUndoColl), pNoNameData ? pNoNameData->GetName() : u""_ustr, |
325 | 0 | std::make_unique<ScDBCollection>( *pColl ) ) ); |
326 | 0 | } |
327 | | |
328 | | // no longer needed to register new range at the Sba |
329 | | |
330 | | // announce "Import1", etc., at the Navigator |
331 | 0 | if (eMode==SC_DB_IMPORT) |
332 | 0 | SfxGetpApp()->Broadcast( SfxHint( SfxHintId::ScDbAreasChanged ) ); |
333 | 0 | } |
334 | 0 | pData = pNoNameData; |
335 | 0 | } |
336 | |
|
337 | 0 | return pData; |
338 | 0 | } |
339 | | |
340 | | ScDBData* ScDocShell::GetAnonymousDBData(const ScRange& rRange) |
341 | 0 | { |
342 | 0 | ScDBCollection* pColl = m_pDocument->GetDBCollection(); |
343 | 0 | if (!pColl) |
344 | 0 | return nullptr; |
345 | | |
346 | 0 | ScDBData* pData = pColl->getAnonDBs().getByRange(rRange); |
347 | 0 | if (!pData) |
348 | 0 | return nullptr; |
349 | | |
350 | 0 | if (!pData->HasHeader()) |
351 | 0 | { |
352 | 0 | bool bHasHeader = m_pDocument->HasColHeader( |
353 | 0 | rRange.aStart.Col(), rRange.aStart.Row(), rRange.aEnd.Col(), rRange.aEnd.Row(), rRange.aStart.Tab()); |
354 | 0 | pData->SetHeader(bHasHeader); |
355 | 0 | } |
356 | |
|
357 | 0 | return pData; |
358 | 0 | } |
359 | | |
360 | | std::unique_ptr<ScDBData> ScDocShell::GetOldAutoDBRange() |
361 | 0 | { |
362 | 0 | return std::move(m_pOldAutoDBRange); |
363 | 0 | } |
364 | | |
365 | | void ScDocShell::CancelAutoDBRange() |
366 | 0 | { |
367 | | // called when dialog is cancelled |
368 | | //moggi:TODO |
369 | 0 | if ( !m_pOldAutoDBRange ) |
370 | 0 | return; |
371 | | |
372 | 0 | SCTAB nTab = GetCurTab(); |
373 | 0 | ScDBData* pDBData = m_pDocument->GetAnonymousDBData(nTab); |
374 | 0 | if ( pDBData ) |
375 | 0 | { |
376 | 0 | SCCOL nRangeX1; |
377 | 0 | SCROW nRangeY1; |
378 | 0 | SCCOL nRangeX2; |
379 | 0 | SCROW nRangeY2; |
380 | 0 | SCTAB nRangeTab; |
381 | 0 | pDBData->GetArea( nRangeTab, nRangeX1, nRangeY1, nRangeX2, nRangeY2 ); |
382 | 0 | DBAreaDeleted( nRangeTab, nRangeX1, nRangeY1, nRangeX2 ); |
383 | |
|
384 | 0 | *pDBData = *m_pOldAutoDBRange; // restore old settings |
385 | |
|
386 | 0 | if ( m_pOldAutoDBRange->HasAutoFilter() ) |
387 | 0 | { |
388 | | // restore AutoFilter buttons |
389 | 0 | m_pOldAutoDBRange->GetArea( nRangeTab, nRangeX1, nRangeY1, nRangeX2, nRangeY2 ); |
390 | 0 | m_pDocument->ApplyFlagsTab( nRangeX1, nRangeY1, nRangeX2, nRangeY1, nRangeTab, ScMF::Auto ); |
391 | 0 | PostPaint( nRangeX1, nRangeY1, nRangeTab, nRangeX2, nRangeY1, nRangeTab, PaintPartFlags::Grid ); |
392 | 0 | } |
393 | 0 | } |
394 | |
|
395 | 0 | m_pOldAutoDBRange.reset(); |
396 | 0 | } |
397 | | |
398 | | // adjust height |
399 | | //! merge with docfunc |
400 | | |
401 | | bool ScDocShell::AdjustRowHeight( SCROW nStartRow, SCROW nEndRow, SCTAB nTab ) |
402 | 0 | { |
403 | 0 | ScSizeDeviceProvider aProv(*this); |
404 | 0 | double fZoom(1.0); |
405 | 0 | sc::RowHeightContext aCxt(m_pDocument->MaxRow(), aProv.GetPPTX(), aProv.GetPPTY(), fZoom, fZoom, aProv.GetDevice()); |
406 | 0 | bool bChange = m_pDocument->SetOptimalHeight(aCxt, nStartRow,nEndRow, nTab, true); |
407 | |
|
408 | 0 | if (bChange) |
409 | 0 | { |
410 | | // tdf#76183: recalculate objects' positions |
411 | 0 | m_pDocument->SetDrawPageSize(nTab); |
412 | |
|
413 | 0 | PostPaint( 0,nStartRow,nTab, m_pDocument->MaxCol(),m_pDocument->MaxRow(),nTab, PaintPartFlags::Grid|PaintPartFlags::Left ); |
414 | 0 | } |
415 | |
|
416 | 0 | return bChange; |
417 | 0 | } |
418 | | |
419 | | void ScDocShell::UpdateAllRowHeights( const ScMarkData* pTabMark ) |
420 | 0 | { |
421 | | // update automatic row heights |
422 | |
|
423 | 0 | ScSizeDeviceProvider aProv(*this); |
424 | 0 | double fZoom(1.0); |
425 | 0 | sc::RowHeightContext aCxt(m_pDocument->MaxRow(), aProv.GetPPTX(), aProv.GetPPTY(), fZoom, fZoom, aProv.GetDevice()); |
426 | 0 | m_pDocument->UpdateAllRowHeights(aCxt, pTabMark); |
427 | 0 | } |
428 | | |
429 | | void ScDocShell::UpdateAllRowHeights(const bool bOnlyUsedRows) |
430 | 4.00k | { |
431 | | // update automatic row heights on all sheets using the newer ScDocRowHeightUpdater |
432 | 4.00k | ScSizeDeviceProvider aProv(*this); |
433 | 4.00k | ScDocRowHeightUpdater aUpdater(*m_pDocument, aProv.GetDevice(), aProv.GetPPTX(), |
434 | 4.00k | aProv.GetPPTY(), nullptr); |
435 | 4.00k | aUpdater.update(bOnlyUsedRows); |
436 | 4.00k | } |
437 | | |
438 | | void ScDocShell::UpdatePendingRowHeights( SCTAB nUpdateTab, bool bBefore ) |
439 | 43.0k | { |
440 | 43.0k | bool bIsUndoEnabled = m_pDocument->IsUndoEnabled(); |
441 | 43.0k | m_pDocument->EnableUndo( false ); |
442 | 43.0k | m_pDocument->LockStreamValid( true ); // ignore draw page size (but not formula results) |
443 | 43.0k | if ( bBefore ) // check all sheets up to nUpdateTab |
444 | 0 | { |
445 | 0 | SCTAB nTabCount = m_pDocument->GetTableCount(); |
446 | 0 | if ( nUpdateTab >= nTabCount ) |
447 | 0 | nUpdateTab = nTabCount-1; // nUpdateTab is inclusive |
448 | |
|
449 | 0 | ScMarkData aUpdateSheets(m_pDocument->GetSheetLimits()); |
450 | 0 | SCTAB nTab; |
451 | 0 | for (nTab=0; nTab<=nUpdateTab; ++nTab) |
452 | 0 | if ( m_pDocument->IsPendingRowHeights( nTab ) ) |
453 | 0 | aUpdateSheets.SelectTable( nTab, true ); |
454 | |
|
455 | 0 | if (aUpdateSheets.GetSelectCount()) |
456 | 0 | UpdateAllRowHeights(&aUpdateSheets); // update with a single progress bar |
457 | |
|
458 | 0 | for (nTab=0; nTab<=nUpdateTab; ++nTab) |
459 | 0 | if ( aUpdateSheets.GetTableSelect( nTab ) ) |
460 | 0 | { |
461 | 0 | m_pDocument->UpdatePageBreaks( nTab ); |
462 | 0 | m_pDocument->SetPendingRowHeights( nTab, false ); |
463 | 0 | } |
464 | 0 | } |
465 | 43.0k | else // only nUpdateTab |
466 | 43.0k | { |
467 | 43.0k | if ( m_pDocument->IsPendingRowHeights( nUpdateTab ) ) |
468 | 0 | { |
469 | 0 | AdjustRowHeight( 0, m_pDocument->MaxRow(), nUpdateTab ); |
470 | 0 | m_pDocument->UpdatePageBreaks( nUpdateTab ); |
471 | 0 | m_pDocument->SetPendingRowHeights( nUpdateTab, false ); |
472 | 0 | } |
473 | 43.0k | } |
474 | 43.0k | m_pDocument->LockStreamValid( false ); |
475 | 43.0k | m_pDocument->EnableUndo( bIsUndoEnabled ); |
476 | 43.0k | } |
477 | | |
478 | | void ScDocShell::RefreshPivotTables( const ScRange& rSource ) |
479 | 0 | { |
480 | 0 | ScDPCollection* pColl = m_pDocument->GetDPCollection(); |
481 | 0 | if (!pColl) |
482 | 0 | return; |
483 | | |
484 | 0 | ScDBDocFunc aFunc(*this); |
485 | 0 | for (size_t i = 0, n = pColl->GetCount(); i < n; ++i) |
486 | 0 | { |
487 | 0 | ScDPObject& rOld = (*pColl)[i]; |
488 | |
|
489 | 0 | const ScSheetSourceDesc* pSheetDesc = rOld.GetSheetDesc(); |
490 | 0 | if (pSheetDesc && pSheetDesc->GetSourceRange().Intersects(rSource)) |
491 | 0 | aFunc.UpdatePivotTable(rOld, true, false); |
492 | 0 | } |
493 | 0 | } |
494 | | |
495 | | static OUString lcl_GetAreaName( ScDocument* pDoc, const ScArea* pArea ) |
496 | 0 | { |
497 | 0 | ScDBData* pData = pDoc->GetDBAtArea( pArea->nTab, pArea->nColStart, pArea->nRowStart, |
498 | 0 | pArea->nColEnd, pArea->nRowEnd ); |
499 | 0 | if (pData) |
500 | 0 | return pData->GetName(); |
501 | | |
502 | 0 | OUString aName; |
503 | 0 | pDoc->GetName( pArea->nTab, aName ); |
504 | 0 | return aName; |
505 | 0 | } |
506 | | |
507 | | static ScDBData* getUndoData(const ScDBData* pDestData) |
508 | 0 | { |
509 | 0 | if (!pDestData) |
510 | 0 | return nullptr; |
511 | 0 | return new ScDBData(*pDestData); |
512 | 0 | } |
513 | | |
514 | | void ScDocShell::DoConsolidate( const ScConsolidateParam& rParam, bool bRecord ) |
515 | 0 | { |
516 | 0 | ScConsData aData; |
517 | |
|
518 | 0 | sal_uInt16 nPos; |
519 | 0 | SCCOL nColSize = 0; |
520 | 0 | SCROW nRowSize = 0; |
521 | 0 | bool bErr = false; |
522 | 0 | for (nPos=0; nPos<rParam.nDataAreaCount; nPos++) |
523 | 0 | { |
524 | 0 | ScArea const & rArea = rParam.pDataAreas[nPos]; |
525 | 0 | nColSize = std::max( nColSize, SCCOL( rArea.nColEnd - rArea.nColStart + 1 ) ); |
526 | 0 | nRowSize = std::max( nRowSize, SCROW( rArea.nRowEnd - rArea.nRowStart + 1 ) ); |
527 | | |
528 | | // test if source data were moved |
529 | 0 | if (rParam.bReferenceData) |
530 | 0 | if (rArea.nTab == rParam.nTab && rArea.nRowEnd >= rParam.nRow) |
531 | 0 | bErr = true; |
532 | 0 | } |
533 | |
|
534 | 0 | if (bErr) |
535 | 0 | { |
536 | 0 | std::unique_ptr<weld::MessageDialog> xInfoBox(Application::CreateMessageDialog(GetActiveDialogParent(), |
537 | 0 | VclMessageType::Info, VclButtonsType::Ok, |
538 | 0 | ScResId(STR_CONSOLIDATE_ERR1))); |
539 | 0 | xInfoBox->run(); |
540 | 0 | return; |
541 | 0 | } |
542 | | |
543 | | // execute |
544 | | |
545 | 0 | weld::WaitObject aWait( GetActiveDialogParent() ); |
546 | 0 | ScDocShellModificator aModificator( *this ); |
547 | |
|
548 | 0 | ScRange aOldDest; |
549 | 0 | ScDBData* pDestData = m_pDocument->GetDBAtCursor( rParam.nCol, rParam.nRow, rParam.nTab, ScDBDataPortion::TOP_LEFT ); |
550 | 0 | if (pDestData) |
551 | 0 | pDestData->GetArea(aOldDest); |
552 | |
|
553 | 0 | aData.SetSize( nColSize, nRowSize ); |
554 | 0 | aData.SetFlags( rParam.eFunction, rParam.bByCol, rParam.bByRow, rParam.bReferenceData ); |
555 | 0 | if ( rParam.bByCol || rParam.bByRow ) |
556 | 0 | for (nPos=0; nPos<rParam.nDataAreaCount; nPos++) |
557 | 0 | { |
558 | 0 | ScArea const & rArea = rParam.pDataAreas[nPos]; |
559 | 0 | aData.AddFields( m_pDocument.get(), rArea.nTab, rArea.nColStart, rArea.nRowStart, |
560 | 0 | rArea.nColEnd, rArea.nRowEnd ); |
561 | 0 | } |
562 | 0 | aData.DoneFields(); |
563 | 0 | for (nPos=0; nPos<rParam.nDataAreaCount; nPos++) |
564 | 0 | { |
565 | 0 | ScArea const & rArea = rParam.pDataAreas[nPos]; |
566 | 0 | aData.AddData( m_pDocument.get(), rArea.nTab, rArea.nColStart, rArea.nRowStart, |
567 | 0 | rArea.nColEnd, rArea.nRowEnd ); |
568 | 0 | aData.AddName( lcl_GetAreaName(m_pDocument.get(), &rArea) ); |
569 | 0 | } |
570 | |
|
571 | 0 | aData.GetSize( nColSize, nRowSize ); |
572 | 0 | if (bRecord && nColSize > 0 && nRowSize > 0) |
573 | 0 | { |
574 | 0 | std::unique_ptr<ScDBData> pUndoData(getUndoData(pDestData)); |
575 | |
|
576 | 0 | SCTAB nDestTab = rParam.nTab; |
577 | 0 | ScArea aDestArea( rParam.nTab, rParam.nCol, rParam.nRow, |
578 | 0 | rParam.nCol+nColSize-1, rParam.nRow+nRowSize-1 ); |
579 | 0 | if (rParam.bByCol) ++aDestArea.nColEnd; |
580 | 0 | if (rParam.bByRow) ++aDestArea.nRowEnd; |
581 | |
|
582 | 0 | if (rParam.bReferenceData) |
583 | 0 | { |
584 | 0 | SCTAB nTabCount = m_pDocument->GetTableCount(); |
585 | 0 | SCROW nInsertCount = aData.GetInsertCount(); |
586 | | |
587 | | // old outlines |
588 | 0 | ScOutlineTable* pTable = m_pDocument->GetOutlineTable( nDestTab ); |
589 | 0 | std::unique_ptr<ScOutlineTable> pUndoTab(pTable ? new ScOutlineTable( *pTable ) : nullptr); |
590 | |
|
591 | 0 | ScDocumentUniquePtr pUndoDoc(new ScDocument( SCDOCMODE_UNDO )); |
592 | 0 | pUndoDoc->InitUndo( *m_pDocument, 0, nTabCount-1, false, true ); |
593 | | |
594 | | // row state |
595 | 0 | m_pDocument->CopyToDocument(0, 0, nDestTab, m_pDocument->MaxCol(), m_pDocument->MaxRow(), nDestTab, |
596 | 0 | InsertDeleteFlags::NONE, false, *pUndoDoc); |
597 | | |
598 | | // all formulas |
599 | 0 | m_pDocument->CopyToDocument(0, 0, 0, m_pDocument->MaxCol(), m_pDocument->MaxRow(), nTabCount-1, |
600 | 0 | InsertDeleteFlags::FORMULA, false, *pUndoDoc); |
601 | | |
602 | | // complete output rows |
603 | 0 | m_pDocument->CopyToDocument(0, aDestArea.nRowStart, nDestTab, |
604 | 0 | m_pDocument->MaxCol(),aDestArea.nRowEnd, nDestTab, |
605 | 0 | InsertDeleteFlags::ALL, false, *pUndoDoc); |
606 | | |
607 | | // old output range |
608 | 0 | if (pDestData) |
609 | 0 | m_pDocument->CopyToDocument(aOldDest, InsertDeleteFlags::ALL, false, *pUndoDoc); |
610 | |
|
611 | 0 | GetUndoManager()->AddUndoAction( |
612 | 0 | std::make_unique<ScUndoConsolidate>( *this, aDestArea, rParam, std::move(pUndoDoc), |
613 | 0 | true, nInsertCount, std::move(pUndoTab), std::move(pUndoData) ) ); |
614 | 0 | } |
615 | 0 | else |
616 | 0 | { |
617 | 0 | ScDocumentUniquePtr pUndoDoc(new ScDocument( SCDOCMODE_UNDO )); |
618 | 0 | pUndoDoc->InitUndo( *m_pDocument, aDestArea.nTab, aDestArea.nTab ); |
619 | |
|
620 | 0 | m_pDocument->CopyToDocument(aDestArea.nColStart, aDestArea.nRowStart, aDestArea.nTab, |
621 | 0 | aDestArea.nColEnd, aDestArea.nRowEnd, aDestArea.nTab, |
622 | 0 | InsertDeleteFlags::ALL, false, *pUndoDoc); |
623 | | |
624 | | // old output range |
625 | 0 | if (pDestData) |
626 | 0 | m_pDocument->CopyToDocument(aOldDest, InsertDeleteFlags::ALL, false, *pUndoDoc); |
627 | |
|
628 | 0 | GetUndoManager()->AddUndoAction( |
629 | 0 | std::make_unique<ScUndoConsolidate>( *this, aDestArea, rParam, std::move(pUndoDoc), |
630 | 0 | false, 0, nullptr, std::move(pUndoData) ) ); |
631 | 0 | } |
632 | 0 | } |
633 | |
|
634 | 0 | if (pDestData) // delete / adjust destination range |
635 | 0 | { |
636 | 0 | m_pDocument->DeleteAreaTab(aOldDest, InsertDeleteFlags::CONTENTS); |
637 | 0 | pDestData->SetArea( rParam.nTab, rParam.nCol, rParam.nRow, |
638 | 0 | rParam.nCol + nColSize - 1, rParam.nRow + nRowSize - 1 ); |
639 | 0 | pDestData->SetHeader( rParam.bByRow ); |
640 | 0 | } |
641 | |
|
642 | 0 | aData.OutputToDocument( *m_pDocument, rParam.nCol, rParam.nRow, rParam.nTab ); |
643 | |
|
644 | 0 | SCCOL nPaintStartCol = rParam.nCol; |
645 | 0 | SCROW nPaintStartRow = rParam.nRow; |
646 | 0 | SCCOL nPaintEndCol = nPaintStartCol + nColSize - 1; |
647 | 0 | SCROW nPaintEndRow = nPaintStartRow + nRowSize - 1; |
648 | 0 | PaintPartFlags nPaintFlags = PaintPartFlags::Grid; |
649 | 0 | if (rParam.bByCol) |
650 | 0 | ++nPaintEndRow; |
651 | 0 | if (rParam.bByRow) |
652 | 0 | ++nPaintEndCol; |
653 | 0 | if (rParam.bReferenceData) |
654 | 0 | { |
655 | 0 | nPaintStartCol = 0; |
656 | 0 | nPaintEndCol = m_pDocument->MaxCol(); |
657 | 0 | nPaintEndRow = m_pDocument->MaxRow(); |
658 | 0 | nPaintFlags |= PaintPartFlags::Left | PaintPartFlags::Size; |
659 | 0 | } |
660 | 0 | if (pDestData) |
661 | 0 | { |
662 | 0 | if ( aOldDest.aEnd.Col() > nPaintEndCol ) |
663 | 0 | nPaintEndCol = aOldDest.aEnd.Col(); |
664 | 0 | if ( aOldDest.aEnd.Row() > nPaintEndRow ) |
665 | 0 | nPaintEndRow = aOldDest.aEnd.Row(); |
666 | 0 | } |
667 | 0 | PostPaint( nPaintStartCol, nPaintStartRow, rParam.nTab, |
668 | 0 | nPaintEndCol, nPaintEndRow, rParam.nTab, nPaintFlags ); |
669 | 0 | aModificator.SetDocumentModified(); |
670 | 0 | } |
671 | | |
672 | | void ScDocShell::UseScenario( SCTAB nTab, const OUString& rName, bool bRecord ) |
673 | 0 | { |
674 | 0 | if (!m_pDocument->IsScenario(nTab)) |
675 | 0 | { |
676 | 0 | SCTAB nTabCount = m_pDocument->GetTableCount(); |
677 | 0 | SCTAB nSrcTab = SCTAB_MAX; |
678 | 0 | SCTAB nEndTab = nTab; |
679 | 0 | OUString aCompare; |
680 | 0 | while ( nEndTab+1 < nTabCount && m_pDocument->IsScenario(nEndTab+1) ) |
681 | 0 | { |
682 | 0 | ++nEndTab; |
683 | 0 | if (nSrcTab > MAXTAB) // still searching for the scenario? |
684 | 0 | { |
685 | 0 | m_pDocument->GetName( nEndTab, aCompare ); |
686 | 0 | if (aCompare == rName) |
687 | 0 | nSrcTab = nEndTab; // found |
688 | 0 | } |
689 | 0 | } |
690 | 0 | if (ValidTab(nSrcTab)) |
691 | 0 | { |
692 | 0 | if ( m_pDocument->TestCopyScenario( nSrcTab, nTab ) ) // test cell protection |
693 | 0 | { |
694 | 0 | ScDocShellModificator aModificator( *this ); |
695 | 0 | ScMarkData aScenMark(m_pDocument->GetSheetLimits()); |
696 | 0 | m_pDocument->MarkScenario( nSrcTab, nTab, aScenMark ); |
697 | 0 | const ScRange& aMultiRange = aScenMark.GetMultiMarkArea(); |
698 | 0 | SCCOL nStartCol = aMultiRange.aStart.Col(); |
699 | 0 | SCROW nStartRow = aMultiRange.aStart.Row(); |
700 | 0 | SCCOL nEndCol = aMultiRange.aEnd.Col(); |
701 | 0 | SCROW nEndRow = aMultiRange.aEnd.Row(); |
702 | |
|
703 | 0 | if (bRecord) |
704 | 0 | { |
705 | 0 | ScDocumentUniquePtr pUndoDoc(new ScDocument( SCDOCMODE_UNDO )); |
706 | 0 | pUndoDoc->InitUndo( *m_pDocument, nTab,nEndTab ); // also all scenarios |
707 | | // shown table: |
708 | 0 | m_pDocument->CopyToDocument(nStartCol, nStartRow, nTab, |
709 | 0 | nEndCol, nEndRow, nTab, InsertDeleteFlags::ALL, |
710 | 0 | true, *pUndoDoc, &aScenMark); |
711 | | // scenarios |
712 | 0 | for (SCTAB i=nTab+1; i<=nEndTab; i++) |
713 | 0 | { |
714 | 0 | pUndoDoc->SetScenario( i, true ); |
715 | 0 | OUString aComment; |
716 | 0 | Color aColor; |
717 | 0 | ScScenarioFlags nScenFlags; |
718 | 0 | m_pDocument->GetScenarioData( i, aComment, aColor, nScenFlags ); |
719 | 0 | pUndoDoc->SetScenarioData( i, aComment, aColor, nScenFlags ); |
720 | 0 | bool bActive = m_pDocument->IsActiveScenario( i ); |
721 | 0 | pUndoDoc->SetActiveScenario( i, bActive ); |
722 | | // At copy-back scenarios also contents |
723 | 0 | if ( nScenFlags & ScScenarioFlags::TwoWay ) |
724 | 0 | m_pDocument->CopyToDocument(0, 0, i, m_pDocument->MaxCol(), m_pDocument->MaxRow(), i, |
725 | 0 | InsertDeleteFlags::ALL, false, *pUndoDoc ); |
726 | 0 | } |
727 | |
|
728 | 0 | GetUndoManager()->AddUndoAction( |
729 | 0 | std::make_unique<ScUndoUseScenario>( *this, aScenMark, |
730 | 0 | ScArea( nTab,nStartCol,nStartRow,nEndCol,nEndRow ), |
731 | 0 | std::move(pUndoDoc), rName ) ); |
732 | 0 | } |
733 | |
|
734 | 0 | m_pDocument->CopyScenario( nSrcTab, nTab ); |
735 | |
|
736 | 0 | sc::SetFormulaDirtyContext aCxt; |
737 | 0 | m_pDocument->SetAllFormulasDirty(aCxt); |
738 | | |
739 | | // paint all, because the active scenario may be modified in other ranges; |
740 | | //! only if there are visible frames? |
741 | 0 | PostPaint( 0,0,nTab, m_pDocument->MaxCol(),m_pDocument->MaxRow(),nTab, PaintPartFlags::Grid ); |
742 | 0 | aModificator.SetDocumentModified(); |
743 | 0 | } |
744 | 0 | else |
745 | 0 | { |
746 | 0 | std::unique_ptr<weld::MessageDialog> xInfoBox(Application::CreateMessageDialog(GetActiveDialogParent(), |
747 | 0 | VclMessageType::Info, VclButtonsType::Ok, |
748 | 0 | ScResId(STR_PROTECTIONERR))); |
749 | 0 | xInfoBox->run(); |
750 | 0 | } |
751 | 0 | } |
752 | 0 | else |
753 | 0 | { |
754 | 0 | std::unique_ptr<weld::MessageDialog> xInfoBox(Application::CreateMessageDialog(GetActiveDialogParent(), |
755 | 0 | VclMessageType::Info, VclButtonsType::Ok, |
756 | 0 | ScResId(STR_SCENARIO_NOTFOUND))); |
757 | 0 | xInfoBox->run(); |
758 | 0 | } |
759 | 0 | } |
760 | 0 | else |
761 | 0 | { |
762 | 0 | OSL_FAIL( "UseScenario on Scenario-Sheet" ); |
763 | 0 | } |
764 | 0 | } |
765 | | |
766 | | void ScDocShell::ModifyScenario( SCTAB nTab, const OUString& rName, const OUString& rComment, |
767 | | const Color& rColor, ScScenarioFlags nFlags ) |
768 | 80 | { |
769 | | // Undo |
770 | 80 | OUString aOldName; |
771 | 80 | m_pDocument->GetName( nTab, aOldName ); |
772 | 80 | OUString aOldComment; |
773 | 80 | Color aOldColor; |
774 | 80 | ScScenarioFlags nOldFlags; |
775 | 80 | m_pDocument->GetScenarioData( nTab, aOldComment, aOldColor, nOldFlags ); |
776 | 80 | GetUndoManager()->AddUndoAction( |
777 | 80 | std::make_unique<ScUndoScenarioFlags>(*this, nTab, |
778 | 80 | aOldName, rName, aOldComment, rComment, |
779 | 80 | aOldColor, rColor, nOldFlags, nFlags) ); |
780 | | |
781 | | // execute |
782 | 80 | ScDocShellModificator aModificator( *this ); |
783 | 80 | m_pDocument->RenameTab( nTab, rName ); |
784 | 80 | m_pDocument->SetScenarioData( nTab, rComment, rColor, nFlags ); |
785 | 80 | PostPaintGridAll(); |
786 | 80 | aModificator.SetDocumentModified(); |
787 | | |
788 | 80 | if (aOldName != rName) |
789 | 0 | SfxGetpApp()->Broadcast( SfxHint( SfxHintId::ScTablesChanged ) ); |
790 | | |
791 | 80 | SfxBindings* pBindings = GetViewBindings(); |
792 | 80 | if (pBindings) |
793 | 0 | pBindings->Invalidate( SID_SELECT_SCENARIO ); |
794 | 80 | } |
795 | | |
796 | | SCTAB ScDocShell::MakeScenario( SCTAB nTab, const OUString& rName, const OUString& rComment, |
797 | | const Color& rColor, ScScenarioFlags nFlags, |
798 | | ScMarkData& rMark, bool bRecord ) |
799 | 20 | { |
800 | 20 | rMark.MarkToMulti(); |
801 | 20 | if (rMark.IsMultiMarked()) |
802 | 20 | { |
803 | 20 | SCTAB nNewTab = nTab + 1; |
804 | 30 | while (m_pDocument->IsScenario(nNewTab)) |
805 | 10 | ++nNewTab; |
806 | | |
807 | 20 | bool bCopyAll = ( (nFlags & ScScenarioFlags::CopyAll) != ScScenarioFlags::NONE ); |
808 | 20 | const ScMarkData* pCopyMark = nullptr; |
809 | 20 | if (!bCopyAll) |
810 | 20 | pCopyMark = &rMark; |
811 | | |
812 | 20 | ScDocShellModificator aModificator( *this ); |
813 | | |
814 | 20 | if (bRecord) |
815 | 20 | m_pDocument->BeginDrawUndo(); // drawing layer must do its own undo actions |
816 | | |
817 | 20 | if (m_pDocument->CopyTab( nTab, nNewTab, pCopyMark )) |
818 | 20 | { |
819 | 20 | if (bRecord) |
820 | 20 | { |
821 | 20 | GetUndoManager()->AddUndoAction( |
822 | 20 | std::make_unique<ScUndoMakeScenario>( *this, nTab, nNewTab, |
823 | 20 | rName, rComment, rColor, nFlags, rMark )); |
824 | 20 | } |
825 | | |
826 | 20 | m_pDocument->RenameTab( nNewTab, rName); |
827 | 20 | m_pDocument->SetScenario( nNewTab, true ); |
828 | 20 | m_pDocument->SetScenarioData( nNewTab, rComment, rColor, nFlags ); |
829 | | |
830 | 20 | ScMarkData aDestMark = rMark; |
831 | 20 | aDestMark.SelectOneTable( nNewTab ); |
832 | | |
833 | | //! test for filter / buttons / merging |
834 | | |
835 | 20 | ScPatternAttr aProtPattern(m_pDocument->getCellAttributeHelper()); |
836 | 20 | aProtPattern.ItemSetPut(ScProtectionAttr(true)); |
837 | 20 | m_pDocument->ApplyPatternAreaTab( 0,0, m_pDocument->MaxCol(),m_pDocument->MaxRow(), nNewTab, aProtPattern ); |
838 | | |
839 | 20 | ScPatternAttr aPattern(m_pDocument->getCellAttributeHelper()); |
840 | 20 | aPattern.ItemSetPut(ScMergeFlagAttr(ScMF::Scenario)); |
841 | 20 | aPattern.ItemSetPut(ScProtectionAttr(true)); |
842 | 20 | m_pDocument->ApplySelectionPattern( aPattern, aDestMark ); |
843 | | |
844 | 20 | if (!bCopyAll) |
845 | 20 | m_pDocument->SetVisible( nNewTab, false ); |
846 | | |
847 | | // this is the active scenario, then |
848 | 20 | m_pDocument->CopyScenario( nNewTab, nTab, true ); // sal_True - don't copy anything from scenario |
849 | | |
850 | 20 | if (nFlags & ScScenarioFlags::ShowFrame) |
851 | 20 | PostPaint( 0,0,nTab, m_pDocument->MaxCol(),m_pDocument->MaxRow(),nTab, PaintPartFlags::Grid ); // paint frames |
852 | 20 | PostPaintExtras(); // table tab |
853 | 20 | aModificator.SetDocumentModified(); |
854 | | |
855 | | // A scenario tab is like a hidden sheet, broadcasting also |
856 | | // notifies ScTabViewShell to add an ScViewData::maTabData entry. |
857 | 20 | Broadcast( ScTablesHint( SC_TAB_INSERTED, nNewTab )); |
858 | 20 | SfxGetpApp()->Broadcast( SfxHint( SfxHintId::ScTablesChanged ) ); |
859 | | |
860 | 20 | return nNewTab; |
861 | 20 | } |
862 | 20 | } |
863 | 0 | return nTab; |
864 | 20 | } |
865 | | |
866 | | bool ScDocShell::TransferTab( ScDocShell& rSrcDocShell, SCTAB nSrcPos, |
867 | | SCTAB nDestPos, bool bInsertNew, |
868 | | bool bNotifyAndPaint ) |
869 | 0 | { |
870 | 0 | ScDocument& rSrcDoc = rSrcDocShell.GetDocument(); |
871 | | |
872 | | // set the transferred area to the copyparam to make adjusting formulas possible |
873 | 0 | ScClipParam aParam; |
874 | 0 | ScRange aRange(0, 0, nSrcPos, m_pDocument->MaxCol(), m_pDocument->MaxRow(), nSrcPos); |
875 | 0 | aParam.maRanges.push_back(aRange); |
876 | 0 | rSrcDoc.SetClipParam(aParam); |
877 | |
|
878 | 0 | bool bValid = m_pDocument->TransferTab( rSrcDoc, nSrcPos, nDestPos, |
879 | 0 | bInsertNew ); // no insert |
880 | | |
881 | | // TransferTab doesn't copy drawing objects with bInsertNew=FALSE |
882 | 0 | if ( bValid && !bInsertNew) |
883 | 0 | m_pDocument->TransferDrawPage( rSrcDoc, nSrcPos, nDestPos ); |
884 | |
|
885 | 0 | if(bValid && rSrcDoc.IsScenario( nSrcPos )) |
886 | 0 | { |
887 | 0 | OUString aComment; |
888 | 0 | Color aColor; |
889 | 0 | ScScenarioFlags nFlags; |
890 | |
|
891 | 0 | rSrcDoc.GetScenarioData( nSrcPos, aComment,aColor, nFlags); |
892 | 0 | m_pDocument->SetScenario(nDestPos,true); |
893 | 0 | m_pDocument->SetScenarioData(nDestPos,aComment,aColor,nFlags); |
894 | 0 | bool bActive = rSrcDoc.IsActiveScenario(nSrcPos); |
895 | 0 | m_pDocument->SetActiveScenario(nDestPos, bActive ); |
896 | |
|
897 | 0 | bool bVisible = rSrcDoc.IsVisible(nSrcPos); |
898 | 0 | m_pDocument->SetVisible(nDestPos,bVisible ); |
899 | |
|
900 | 0 | } |
901 | |
|
902 | 0 | if ( bValid && rSrcDoc.IsTabProtected( nSrcPos ) ) |
903 | 0 | m_pDocument->SetTabProtection(nDestPos, rSrcDoc.GetTabProtection(nSrcPos)); |
904 | 0 | if ( bNotifyAndPaint ) |
905 | 0 | { |
906 | 0 | Broadcast( ScTablesHint( SC_TAB_INSERTED, nDestPos ) ); |
907 | 0 | PostPaintExtras(); |
908 | 0 | PostPaintGridAll(); |
909 | 0 | } |
910 | 0 | return bValid; |
911 | 0 | } |
912 | | |
913 | | bool ScDocShell::MoveTable( SCTAB nSrcTab, SCTAB nDestTab, bool bCopy, bool bRecord ) |
914 | 0 | { |
915 | 0 | ScDocShellModificator aModificator( *this ); |
916 | | |
917 | | // #i92477# be consistent with ScDocFunc::InsertTable: any index past the last sheet means "append" |
918 | | // #i101139# nDestTab must be the target position, not APPEND (for CopyTabProtection etc.) |
919 | 0 | if ( nDestTab >= m_pDocument->GetTableCount() ) |
920 | 0 | nDestTab = m_pDocument->GetTableCount(); |
921 | |
|
922 | 0 | if (bCopy) |
923 | 0 | { |
924 | 0 | if (bRecord) |
925 | 0 | m_pDocument->BeginDrawUndo(); // drawing layer must do its own undo actions |
926 | |
|
927 | 0 | OUString sSrcCodeName; |
928 | 0 | m_pDocument->GetCodeName( nSrcTab, sSrcCodeName ); |
929 | 0 | if (!m_pDocument->CopyTab( nSrcTab, nDestTab )) |
930 | 0 | { |
931 | | //! EndDrawUndo? |
932 | 0 | return false; |
933 | 0 | } |
934 | 0 | else |
935 | 0 | { |
936 | 0 | SCTAB nAdjSource = nSrcTab; |
937 | 0 | if ( nDestTab <= nSrcTab ) |
938 | 0 | ++nAdjSource; // new position of source table after CopyTab |
939 | |
|
940 | 0 | if ( m_pDocument->IsTabProtected( nAdjSource ) ) |
941 | 0 | m_pDocument->CopyTabProtection(nAdjSource, nDestTab); |
942 | |
|
943 | 0 | if (bRecord) |
944 | 0 | { |
945 | 0 | std::unique_ptr<std::vector<SCTAB>> pSrcList(new std::vector<SCTAB>(1, nSrcTab)); |
946 | 0 | std::unique_ptr<std::vector<SCTAB>> pDestList(new std::vector<SCTAB>(1, nDestTab)); |
947 | 0 | GetUndoManager()->AddUndoAction( |
948 | 0 | std::make_unique<ScUndoCopyTab>(*this, std::move(pSrcList), std::move(pDestList))); |
949 | 0 | } |
950 | |
|
951 | 0 | bool bVbaEnabled = m_pDocument->IsInVBAMode(); |
952 | 0 | if ( bVbaEnabled ) |
953 | 0 | { |
954 | 0 | OUString aLibName( u"Standard"_ustr ); |
955 | 0 | Reference< XLibraryContainer > xLibContainer = GetBasicContainer(); |
956 | 0 | Reference< XVBACompatibility > xVBACompat( xLibContainer, UNO_QUERY ); |
957 | |
|
958 | 0 | if ( xVBACompat.is() ) |
959 | 0 | { |
960 | 0 | aLibName = xVBACompat->getProjectName(); |
961 | 0 | } |
962 | |
|
963 | 0 | SCTAB nTabToUse = nDestTab; |
964 | 0 | if ( nDestTab == SC_TAB_APPEND ) |
965 | 0 | nTabToUse = m_pDocument->GetMaxTableNumber() - 1; |
966 | 0 | OUString sSource; |
967 | 0 | try |
968 | 0 | { |
969 | 0 | Reference< XNameContainer > xLib; |
970 | 0 | if( xLibContainer.is() ) |
971 | 0 | { |
972 | 0 | css::uno::Any aLibAny = xLibContainer->getByName( aLibName ); |
973 | 0 | aLibAny >>= xLib; |
974 | 0 | } |
975 | 0 | if( xLib.is() ) |
976 | 0 | { |
977 | 0 | xLib->getByName( sSrcCodeName ) >>= sSource; |
978 | 0 | } |
979 | 0 | } |
980 | 0 | catch ( const css::uno::Exception& ) |
981 | 0 | { |
982 | 0 | } |
983 | 0 | VBA_InsertModule( *m_pDocument, nTabToUse, sSource ); |
984 | 0 | } |
985 | 0 | } |
986 | 0 | Broadcast( ScTablesHint( SC_TAB_COPIED, nSrcTab, nDestTab ) ); |
987 | 0 | } |
988 | 0 | else |
989 | 0 | { |
990 | 0 | if ( m_pDocument->GetChangeTrack() ) |
991 | 0 | return false; |
992 | | |
993 | 0 | if ( nSrcTab == nDestTab ) |
994 | 0 | { |
995 | | //! allow only for api calls? |
996 | 0 | return true; // nothing to do, but valid |
997 | 0 | } |
998 | | |
999 | 0 | std::optional<ScProgress> pProgress(std::in_place, this, ScResId(STR_UNDO_MOVE_TAB), |
1000 | 0 | m_pDocument->GetCodeCount(), true); |
1001 | 0 | bool bDone = m_pDocument->MoveTab( nSrcTab, nDestTab, &*pProgress ); |
1002 | 0 | pProgress.reset(); |
1003 | 0 | if (!bDone) |
1004 | 0 | { |
1005 | 0 | return false; |
1006 | 0 | } |
1007 | 0 | else if (bRecord) |
1008 | 0 | { |
1009 | 0 | std::unique_ptr<std::vector<SCTAB>> pSrcList(new std::vector<SCTAB>(1, nSrcTab)); |
1010 | 0 | std::unique_ptr<std::vector<SCTAB>> pDestList(new std::vector<SCTAB>(1, nDestTab)); |
1011 | 0 | GetUndoManager()->AddUndoAction( |
1012 | 0 | std::make_unique<ScUndoMoveTab>(*this, std::move(pSrcList), std::move(pDestList))); |
1013 | 0 | } |
1014 | | |
1015 | 0 | Broadcast( ScTablesHint( SC_TAB_MOVED, nSrcTab, nDestTab ) ); |
1016 | 0 | } |
1017 | | |
1018 | 0 | PostPaintGridAll(); |
1019 | 0 | PostPaintExtras(); |
1020 | 0 | aModificator.SetDocumentModified(); |
1021 | 0 | SfxGetpApp()->Broadcast( SfxHint( SfxHintId::ScTablesChanged ) ); |
1022 | |
|
1023 | 0 | return true; |
1024 | 0 | } |
1025 | | |
1026 | | IMPL_LINK( ScDocShell, RefreshDBDataHdl, Timer*, pRefreshTimer, void ) |
1027 | 0 | { |
1028 | 0 | ScDBDocFunc aFunc(*this); |
1029 | |
|
1030 | 0 | ScDBData* pDBData = static_cast<ScDBData*>(pRefreshTimer); |
1031 | 0 | ScImportParam aImportParam; |
1032 | 0 | pDBData->GetImportParam( aImportParam ); |
1033 | 0 | if (aImportParam.bImport && !pDBData->HasImportSelection()) |
1034 | 0 | { |
1035 | 0 | ScRange aRange; |
1036 | 0 | pDBData->GetArea( aRange ); |
1037 | 0 | bool bContinue = aFunc.DoImport( aRange.aStart.Tab(), aImportParam, nullptr ); //! Api-Flag as parameter |
1038 | | // internal operations (sort, query, subtotal) only if no error |
1039 | 0 | if (bContinue) |
1040 | 0 | { |
1041 | 0 | aFunc.RepeatDB( pDBData->GetName(), true, true ); |
1042 | 0 | RefreshPivotTables(aRange); |
1043 | 0 | } |
1044 | 0 | } |
1045 | 0 | } |
1046 | | |
1047 | | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |