Line data Source code
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 <sal/config.h>
21 :
22 : #include <cassert>
23 :
24 : #include "scitems.hxx"
25 : #include <vcl/msgbox.hxx>
26 : #include <vcl/waitobj.hxx>
27 : #include <sfx2/app.hxx>
28 : #include <sfx2/bindings.hxx>
29 :
30 : #include <com/sun/star/script/vba/XVBACompatibility.hpp>
31 :
32 : #include "docsh.hxx"
33 : #include "global.hxx"
34 : #include "globstr.hrc"
35 : #include "globalnames.hxx"
36 : #include "undodat.hxx"
37 : #include "undotab.hxx"
38 : #include "undoblk.hxx"
39 : #include "dpobject.hxx"
40 : #include "dpshttab.hxx"
41 : #include "dbdocfun.hxx"
42 : #include "consoli.hxx"
43 : #include "dbdata.hxx"
44 : #include "progress.hxx"
45 : #include "olinetab.hxx"
46 : #include "patattr.hxx"
47 : #include "attrib.hxx"
48 : #include "docpool.hxx"
49 : #include "uiitems.hxx"
50 : #include "sc.hrc"
51 : #include "waitoff.hxx"
52 : #include "sizedev.hxx"
53 : #include "clipparam.hxx"
54 : #include <rowheightcontext.hxx>
55 : #include <refupdatecontext.hxx>
56 :
57 : // defined in docfunc.cxx
58 : void VBA_InsertModule( ScDocument& rDoc, SCTAB nTab, const OUString& sModuleName, const OUString& sModuleSource );
59 :
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;
65 :
66 : using ::std::auto_ptr;
67 : using ::std::vector;
68 :
69 :
70 : // former viewfunc/dbfunc methods
71 :
72 :
73 0 : void ScDocShell::ErrorMessage( sal_uInt16 nGlobStrId )
74 : {
75 : //! StopMarking an der (aktiven) View?
76 :
77 0 : Window* pParent = GetActiveDialogParent();
78 0 : ScWaitCursorOff aWaitOff( pParent );
79 0 : sal_Bool bFocus = pParent && pParent->HasFocus();
80 :
81 0 : if(nGlobStrId==STR_PROTECTIONERR)
82 : {
83 0 : if(IsReadOnly())
84 : {
85 0 : nGlobStrId=STR_READONLYERR;
86 : }
87 : }
88 :
89 0 : InfoBox aBox( pParent, ScGlobal::GetRscString( nGlobStrId ) );
90 0 : aBox.Execute();
91 0 : if (bFocus)
92 0 : pParent->GrabFocus();
93 0 : }
94 :
95 0 : bool ScDocShell::IsEditable() const
96 : {
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 0 : return !IsReadOnly() || aDocument.IsImportingXML() || aDocument.IsChangeReadOnlyEnabled();
101 : }
102 :
103 0 : void ScDocShell::DBAreaDeleted( SCTAB nTab, SCCOL nX1, SCROW nY1, SCCOL nX2, SCROW /* nY2 */ )
104 : {
105 0 : ScDocShellModificator aModificator( *this );
106 0 : aDocument.RemoveFlagsTab( nX1, nY1, nX2, nY1, nTab, SC_MF_AUTO );
107 0 : PostPaint( nX1, nY1, nTab, nX2, nY1, nTab, PAINT_GRID );
108 : // No SetDocumentModified, as the unnamed database range might have to be restored later.
109 : // The UNO hint is broadcast directly instead, to keep UNO objects in valid state.
110 0 : aDocument.BroadcastUno( SfxSimpleHint( SFX_HINT_DATACHANGED ) );
111 0 : }
112 :
113 0 : ScDBData* ScDocShell::GetDBData( const ScRange& rMarked, ScGetDBMode eMode, ScGetDBSelection eSel )
114 : {
115 0 : SCCOL nCol = rMarked.aStart.Col();
116 0 : SCROW nRow = rMarked.aStart.Row();
117 0 : SCTAB nTab = rMarked.aStart.Tab();
118 :
119 0 : SCCOL nStartCol = nCol;
120 0 : SCROW nStartRow = nRow;
121 0 : SCTAB nStartTab = nTab;
122 0 : SCCOL nEndCol = rMarked.aEnd.Col();
123 0 : SCROW nEndRow = rMarked.aEnd.Row();
124 0 : SCTAB nEndTab = rMarked.aEnd.Tab();
125 : // Nicht einfach GetDBAtCursor: Der zusammenhaengende Datenbereich
126 : // fuer "unbenannt" (GetDataArea) kann neben dem Cursor legen, also muss auch ein
127 : // benannter DB-Bereich dort gesucht werden.
128 0 : ScDBCollection* pColl = aDocument.GetDBCollection();
129 0 : ScDBData* pData = aDocument.GetDBAtArea( nTab, nStartCol, nStartRow, nEndCol, nEndRow );
130 0 : if (!pData && pColl)
131 0 : pData = pColl->GetDBNearCursor(nCol, nRow, nTab );
132 :
133 0 : sal_Bool bSelected = ( eSel == SC_DBSEL_FORCE_MARK ||
134 0 : (rMarked.aStart != rMarked.aEnd && eSel != SC_DBSEL_ROW_DOWN) );
135 0 : bool bOnlyDown = (!bSelected && eSel == SC_DBSEL_ROW_DOWN && rMarked.aStart.Row() == rMarked.aEnd.Row());
136 :
137 0 : sal_Bool bUseThis = false;
138 0 : if (pData)
139 : {
140 : // Bereich nehmen, wenn nichts anderes markiert
141 :
142 : SCTAB nDummy;
143 : SCCOL nOldCol1;
144 : SCROW nOldRow1;
145 : SCCOL nOldCol2;
146 : SCROW nOldRow2;
147 0 : pData->GetArea( nDummy, nOldCol1,nOldRow1, nOldCol2,nOldRow2 );
148 0 : sal_Bool bIsNoName = ( pData->GetName() == STR_DB_LOCAL_NONAME );
149 :
150 0 : if (!bSelected)
151 : {
152 0 : bUseThis = sal_True;
153 0 : if ( bIsNoName && eMode == SC_DB_MAKE )
154 : {
155 : // If nothing marked or only one row marked, adapt
156 : // "unbenannt"/"unnamed" to contiguous area.
157 0 : nStartCol = nCol;
158 0 : nStartRow = nRow;
159 0 : if (bOnlyDown)
160 : {
161 0 : nEndCol = rMarked.aEnd.Col();
162 0 : nEndRow = rMarked.aEnd.Row();
163 : }
164 : else
165 : {
166 0 : nEndCol = nStartCol;
167 0 : nEndRow = nStartRow;
168 : }
169 0 : aDocument.GetDataArea( nTab, nStartCol, nStartRow, nEndCol, nEndRow, false, bOnlyDown );
170 0 : if ( nOldCol1 != nStartCol || nOldCol2 != nEndCol || nOldRow1 != nStartRow )
171 0 : bUseThis = false; // passt gar nicht
172 0 : else if ( nOldRow2 != nEndRow )
173 : {
174 : // Bereich auf neue End-Zeile erweitern
175 0 : pData->SetArea( nTab, nOldCol1,nOldRow1, nOldCol2,nEndRow );
176 : }
177 : }
178 : }
179 : else
180 : {
181 0 : if ( nOldCol1 == nStartCol && nOldRow1 == nStartRow &&
182 0 : nOldCol2 == nEndCol && nOldRow2 == nEndRow ) // genau markiert?
183 0 : bUseThis = sal_True;
184 : else
185 0 : bUseThis = false; // immer Markierung nehmen (Bug 11964)
186 : }
187 :
188 : // fuer Import nie "unbenannt" nehmen
189 :
190 0 : if ( bUseThis && eMode == SC_DB_IMPORT && bIsNoName )
191 0 : bUseThis = false;
192 : }
193 :
194 0 : if ( bUseThis )
195 : {
196 0 : pData->GetArea( nStartTab, nStartCol,nStartRow, nEndCol,nEndRow );
197 0 : nEndTab = nStartTab;
198 : }
199 0 : else if ( eMode == SC_DB_OLD )
200 : {
201 0 : pData = NULL; // nichts gefunden
202 0 : nStartCol = nEndCol = nCol;
203 0 : nStartRow = nEndRow = nRow;
204 0 : nStartTab = nEndTab = nTab;
205 : }
206 : else
207 : {
208 0 : if ( !bSelected )
209 : { // zusammenhaengender Bereich
210 0 : nStartCol = nCol;
211 0 : nStartRow = nRow;
212 0 : if (bOnlyDown)
213 : {
214 0 : nEndCol = rMarked.aEnd.Col();
215 0 : nEndRow = rMarked.aEnd.Row();
216 : }
217 : else
218 : {
219 0 : nEndCol = nStartCol;
220 0 : nEndRow = nStartRow;
221 : }
222 0 : aDocument.GetDataArea( nTab, nStartCol, nStartRow, nEndCol, nEndRow, false, bOnlyDown );
223 : }
224 :
225 0 : sal_Bool bHasHeader = aDocument.HasColHeader( nStartCol,nStartRow, nEndCol,nEndRow, nTab );
226 :
227 0 : ScDBData* pNoNameData = aDocument.GetAnonymousDBData(nTab);
228 0 : if ( eMode != SC_DB_IMPORT && pNoNameData)
229 : {
230 :
231 0 : if ( !pOldAutoDBRange )
232 : {
233 : // store the old unnamed database range with its settings for undo
234 : // (store at the first change, get the state before all changes)
235 0 : pOldAutoDBRange = new ScDBData( *pNoNameData );
236 : }
237 :
238 : SCCOL nOldX1; // alten Bereich sauber wegnehmen
239 : SCROW nOldY1; //! (UNDO ???)
240 : SCCOL nOldX2;
241 : SCROW nOldY2;
242 : SCTAB nOldTab;
243 0 : pNoNameData->GetArea( nOldTab, nOldX1, nOldY1, nOldX2, nOldY2 );
244 0 : DBAreaDeleted( nOldTab, nOldX1, nOldY1, nOldX2, nOldY2 );
245 :
246 0 : pNoNameData->SetSortParam( ScSortParam() ); // Parameter zuruecksetzen
247 0 : pNoNameData->SetQueryParam( ScQueryParam() );
248 0 : pNoNameData->SetSubTotalParam( ScSubTotalParam() );
249 :
250 0 : pNoNameData->SetArea( nTab, nStartCol,nStartRow, nEndCol,nEndRow ); // neu setzen
251 0 : pNoNameData->SetByRow( true );
252 0 : pNoNameData->SetHeader( bHasHeader );
253 0 : pNoNameData->SetAutoFilter( false );
254 : }
255 : else
256 : {
257 0 : ScDBCollection* pUndoColl = NULL;
258 :
259 0 : OUString aNewName;
260 0 : if (eMode==SC_DB_IMPORT)
261 : {
262 0 : aDocument.CompileDBFormula( true ); // CreateFormulaString
263 0 : pUndoColl = new ScDBCollection( *pColl ); // Undo fuer Import1-Bereich
264 :
265 0 : OUString aImport = ScGlobal::GetRscString( STR_DBNAME_IMPORT );
266 0 : long nCount = 0;
267 0 : const ScDBData* pDummy = NULL;
268 0 : ScDBCollection::NamedDBs& rDBs = pColl->getNamedDBs();
269 0 : do
270 : {
271 0 : ++nCount;
272 0 : aNewName = aImport;
273 0 : aNewName += OUString::number( nCount );
274 0 : pDummy = rDBs.findByUpperName(ScGlobal::pCharClass->uppercase(aNewName));
275 : }
276 : while (pDummy);
277 : pNoNameData = new ScDBData( aNewName, nTab,
278 : nStartCol,nStartRow, nEndCol,nEndRow,
279 0 : true, bHasHeader );
280 0 : bool ins = rDBs.insert(pNoNameData);
281 0 : assert(ins); (void)ins;
282 : }
283 : else
284 : {
285 0 : aNewName = OUString(STR_DB_LOCAL_NONAME);
286 : pNoNameData = new ScDBData(aNewName , nTab,
287 : nStartCol,nStartRow, nEndCol,nEndRow,
288 0 : true, bHasHeader );
289 0 : aDocument.SetAnonymousDBData(nTab, pNoNameData);
290 : }
291 :
292 0 : if ( pUndoColl )
293 : {
294 0 : aDocument.CompileDBFormula( false ); // CompileFormulaString
295 :
296 0 : ScDBCollection* pRedoColl = new ScDBCollection( *pColl );
297 0 : GetUndoManager()->AddUndoAction( new ScUndoDBData( this, pUndoColl, pRedoColl ) );
298 : }
299 :
300 : // neuen Bereich am Sba anmelden nicht mehr noetig
301 :
302 : // "Import1" etc am Navigator bekanntmachen
303 0 : if (eMode==SC_DB_IMPORT)
304 0 : SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_DBAREAS_CHANGED ) );
305 : }
306 0 : pData = pNoNameData;
307 : }
308 :
309 0 : return pData;
310 : }
311 :
312 0 : ScDBData* ScDocShell::GetAnonymousDBData(const ScRange& rRange)
313 : {
314 : bool bHasHeader = aDocument.HasColHeader(
315 0 : rRange.aStart.Col(), rRange.aStart.Row(), rRange.aEnd.Col(), rRange.aEnd.Row(), rRange.aStart.Tab());
316 :
317 0 : ScDBCollection* pColl = aDocument.GetDBCollection();
318 0 : if (!pColl)
319 0 : return NULL;
320 :
321 0 : ScDBData* pData = pColl->getAnonDBs().getByRange(rRange);
322 0 : if (!pData)
323 0 : return NULL;
324 :
325 0 : pData->SetHeader(bHasHeader);
326 0 : return pData;
327 : }
328 :
329 0 : ScDBData* ScDocShell::GetOldAutoDBRange()
330 : {
331 0 : ScDBData* pRet = pOldAutoDBRange;
332 0 : pOldAutoDBRange = NULL;
333 0 : return pRet; // has to be deleted by caller!
334 : }
335 :
336 0 : void ScDocShell::CancelAutoDBRange()
337 : {
338 : // called when dialog is cancelled
339 : //moggi:TODO
340 0 : if ( pOldAutoDBRange )
341 : {
342 0 : SCTAB nTab = GetCurTab();
343 0 : ScDBData* pDBData = aDocument.GetAnonymousDBData(nTab);
344 0 : if ( pDBData )
345 : {
346 : SCCOL nRangeX1;
347 : SCROW nRangeY1;
348 : SCCOL nRangeX2;
349 : SCROW nRangeY2;
350 : SCTAB nRangeTab;
351 0 : pDBData->GetArea( nRangeTab, nRangeX1, nRangeY1, nRangeX2, nRangeY2 );
352 0 : DBAreaDeleted( nRangeTab, nRangeX1, nRangeY1, nRangeX2, nRangeY2 );
353 :
354 0 : *pDBData = *pOldAutoDBRange; // restore old settings
355 :
356 0 : if ( pOldAutoDBRange->HasAutoFilter() )
357 : {
358 : // restore AutoFilter buttons
359 0 : pOldAutoDBRange->GetArea( nRangeTab, nRangeX1, nRangeY1, nRangeX2, nRangeY2 );
360 0 : aDocument.ApplyFlagsTab( nRangeX1, nRangeY1, nRangeX2, nRangeY1, nRangeTab, SC_MF_AUTO );
361 0 : PostPaint( nRangeX1, nRangeY1, nRangeTab, nRangeX2, nRangeY1, nRangeTab, PAINT_GRID );
362 : }
363 : }
364 :
365 0 : delete pOldAutoDBRange;
366 0 : pOldAutoDBRange = NULL;
367 : }
368 0 : }
369 :
370 :
371 : // Hoehen anpassen
372 : //! mit docfunc zusammenfassen
373 :
374 0 : bool ScDocShell::AdjustRowHeight( SCROW nStartRow, SCROW nEndRow, SCTAB nTab )
375 : {
376 0 : ScSizeDeviceProvider aProv(this);
377 0 : Fraction aZoom(1,1);
378 0 : sc::RowHeightContext aCxt(aProv.GetPPTX(), aProv.GetPPTY(), aZoom, aZoom, aProv.GetDevice());
379 0 : bool bChange = aDocument.SetOptimalHeight(aCxt, nStartRow,nEndRow, nTab);
380 :
381 0 : if (bChange)
382 0 : PostPaint( 0,nStartRow,nTab, MAXCOL,MAXROW,nTab, PAINT_GRID|PAINT_LEFT );
383 :
384 0 : return bChange;
385 : }
386 :
387 0 : void ScDocShell::UpdateAllRowHeights( const ScMarkData* pTabMark )
388 : {
389 : // update automatic row heights
390 :
391 0 : ScSizeDeviceProvider aProv(this);
392 0 : Fraction aZoom(1,1);
393 0 : sc::RowHeightContext aCxt(aProv.GetPPTX(), aProv.GetPPTY(), aZoom, aZoom, aProv.GetDevice());
394 0 : aDocument.UpdateAllRowHeights(aCxt, pTabMark);
395 0 : }
396 :
397 0 : void ScDocShell::UpdatePendingRowHeights( SCTAB nUpdateTab, bool bBefore )
398 : {
399 0 : sal_Bool bIsUndoEnabled = aDocument.IsUndoEnabled();
400 0 : aDocument.EnableUndo( false );
401 0 : aDocument.LockStreamValid( true ); // ignore draw page size (but not formula results)
402 0 : if ( bBefore ) // check all sheets up to nUpdateTab
403 : {
404 0 : SCTAB nTabCount = aDocument.GetTableCount();
405 0 : if ( nUpdateTab >= nTabCount )
406 0 : nUpdateTab = nTabCount-1; // nUpdateTab is inclusive
407 :
408 0 : ScMarkData aUpdateSheets;
409 : SCTAB nTab;
410 0 : for (nTab=0; nTab<=nUpdateTab; ++nTab)
411 0 : if ( aDocument.IsPendingRowHeights( nTab ) )
412 0 : aUpdateSheets.SelectTable( nTab, true );
413 :
414 0 : if (aUpdateSheets.GetSelectCount())
415 0 : UpdateAllRowHeights(&aUpdateSheets); // update with a single progress bar
416 :
417 0 : for (nTab=0; nTab<=nUpdateTab; ++nTab)
418 0 : if ( aUpdateSheets.GetTableSelect( nTab ) )
419 : {
420 0 : aDocument.UpdatePageBreaks( nTab );
421 0 : aDocument.SetPendingRowHeights( nTab, false );
422 0 : }
423 : }
424 : else // only nUpdateTab
425 : {
426 0 : if ( aDocument.IsPendingRowHeights( nUpdateTab ) )
427 : {
428 0 : AdjustRowHeight( 0, MAXROW, nUpdateTab );
429 0 : aDocument.UpdatePageBreaks( nUpdateTab );
430 0 : aDocument.SetPendingRowHeights( nUpdateTab, false );
431 : }
432 : }
433 0 : aDocument.LockStreamValid( false );
434 0 : aDocument.EnableUndo( bIsUndoEnabled );
435 0 : }
436 :
437 0 : void ScDocShell::RefreshPivotTables( const ScRange& rSource )
438 : {
439 0 : ScDPCollection* pColl = aDocument.GetDPCollection();
440 0 : if (!pColl)
441 0 : return;
442 :
443 0 : ScDBDocFunc aFunc(*this);
444 0 : for (size_t i = 0, n = pColl->GetCount(); i < n; ++i)
445 : {
446 0 : ScDPObject* pOld = (*pColl)[i];
447 0 : if (!pOld)
448 0 : continue;
449 :
450 0 : const ScSheetSourceDesc* pSheetDesc = pOld->GetSheetDesc();
451 0 : if (pSheetDesc && pSheetDesc->GetSourceRange().Intersects(rSource))
452 0 : aFunc.UpdatePivotTable(*pOld, true, false);
453 0 : }
454 : }
455 :
456 0 : static OUString lcl_GetAreaName( ScDocument* pDoc, ScArea* pArea )
457 : {
458 0 : OUString aName;
459 0 : sal_Bool bOk = false;
460 : ScDBData* pData = pDoc->GetDBAtArea( pArea->nTab, pArea->nColStart, pArea->nRowStart,
461 0 : pArea->nColEnd, pArea->nRowEnd );
462 0 : if (pData)
463 : {
464 0 : aName = pData->GetName();
465 0 : bOk = sal_True;
466 : }
467 :
468 0 : if (!bOk)
469 0 : pDoc->GetName( pArea->nTab, aName );
470 :
471 0 : return aName;
472 : }
473 :
474 0 : void ScDocShell::DoConsolidate( const ScConsolidateParam& rParam, bool bRecord )
475 : {
476 0 : ScConsData aData;
477 :
478 : sal_uInt16 nPos;
479 0 : SCCOL nColSize = 0;
480 0 : SCROW nRowSize = 0;
481 0 : sal_Bool bErr = false;
482 0 : for (nPos=0; nPos<rParam.nDataAreaCount; nPos++)
483 : {
484 0 : ScArea* pArea = rParam.ppDataAreas[nPos];
485 0 : nColSize = std::max( nColSize, SCCOL( pArea->nColEnd - pArea->nColStart + 1 ) );
486 0 : nRowSize = std::max( nRowSize, SCROW( pArea->nRowEnd - pArea->nRowStart + 1 ) );
487 :
488 : // Test, ob Quelldaten verschoben wuerden
489 0 : if (rParam.bReferenceData)
490 0 : if (pArea->nTab == rParam.nTab && pArea->nRowEnd >= rParam.nRow)
491 0 : bErr = sal_True;
492 : }
493 :
494 0 : if (bErr)
495 : {
496 : InfoBox aBox( GetActiveDialogParent(),
497 0 : ScGlobal::GetRscString( STR_CONSOLIDATE_ERR1 ) );
498 0 : aBox.Execute();
499 0 : return;
500 : }
501 :
502 : // ausfuehren
503 :
504 0 : WaitObject aWait( GetActiveDialogParent() );
505 0 : ScDocShellModificator aModificator( *this );
506 :
507 0 : ScRange aOldDest;
508 0 : ScDBData* pDestData = aDocument.GetDBAtCursor( rParam.nCol, rParam.nRow, rParam.nTab, true );
509 0 : if (pDestData)
510 0 : pDestData->GetArea(aOldDest);
511 :
512 0 : aData.SetSize( nColSize, nRowSize );
513 0 : aData.SetFlags( rParam.eFunction, rParam.bByCol, rParam.bByRow, rParam.bReferenceData );
514 0 : if ( rParam.bByCol || rParam.bByRow )
515 0 : for (nPos=0; nPos<rParam.nDataAreaCount; nPos++)
516 : {
517 0 : ScArea* pArea = rParam.ppDataAreas[nPos];
518 : aData.AddFields( &aDocument, pArea->nTab, pArea->nColStart, pArea->nRowStart,
519 0 : pArea->nColEnd, pArea->nRowEnd );
520 : }
521 0 : aData.DoneFields();
522 0 : for (nPos=0; nPos<rParam.nDataAreaCount; nPos++)
523 : {
524 0 : ScArea* pArea = rParam.ppDataAreas[nPos];
525 : aData.AddData( &aDocument, pArea->nTab, pArea->nColStart, pArea->nRowStart,
526 0 : pArea->nColEnd, pArea->nRowEnd );
527 0 : aData.AddName( lcl_GetAreaName(&aDocument,pArea) );
528 : }
529 :
530 0 : aData.GetSize( nColSize, nRowSize );
531 0 : if (bRecord && nColSize > 0 && nRowSize > 0)
532 : {
533 0 : ScDBData* pUndoData = pDestData ? new ScDBData(*pDestData) : NULL;
534 :
535 0 : SCTAB nDestTab = rParam.nTab;
536 : ScArea aDestArea( rParam.nTab, rParam.nCol, rParam.nRow,
537 0 : rParam.nCol+nColSize-1, rParam.nRow+nRowSize-1 );
538 0 : if (rParam.bByCol) ++aDestArea.nColEnd;
539 0 : if (rParam.bByRow) ++aDestArea.nRowEnd;
540 :
541 0 : if (rParam.bReferenceData)
542 : {
543 0 : SCTAB nTabCount = aDocument.GetTableCount();
544 0 : SCROW nInsertCount = aData.GetInsertCount();
545 :
546 : // alte Outlines
547 0 : ScOutlineTable* pTable = aDocument.GetOutlineTable( nDestTab );
548 0 : ScOutlineTable* pUndoTab = pTable ? new ScOutlineTable( *pTable ) : NULL;
549 :
550 0 : ScDocument* pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
551 0 : pUndoDoc->InitUndo( &aDocument, 0, nTabCount-1, false, true );
552 :
553 : // Zeilenstatus
554 : aDocument.CopyToDocument( 0,0,nDestTab, MAXCOL,MAXROW,nDestTab,
555 0 : IDF_NONE, false, pUndoDoc );
556 :
557 : // alle Formeln
558 : aDocument.CopyToDocument( 0,0,0, MAXCOL,MAXROW,nTabCount-1,
559 0 : IDF_FORMULA, false, pUndoDoc );
560 :
561 : // komplette Ausgangszeilen
562 : aDocument.CopyToDocument( 0,aDestArea.nRowStart,nDestTab,
563 : MAXCOL,aDestArea.nRowEnd,nDestTab,
564 0 : IDF_ALL, false, pUndoDoc );
565 :
566 : // alten Ausgabebereich
567 0 : if (pDestData)
568 0 : aDocument.CopyToDocument( aOldDest, IDF_ALL, false, pUndoDoc );
569 :
570 0 : GetUndoManager()->AddUndoAction(
571 : new ScUndoConsolidate( this, aDestArea, rParam, pUndoDoc,
572 0 : true, nInsertCount, pUndoTab, pUndoData ) );
573 : }
574 : else
575 : {
576 0 : ScDocument* pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
577 0 : pUndoDoc->InitUndo( &aDocument, aDestArea.nTab, aDestArea.nTab );
578 :
579 : aDocument.CopyToDocument( aDestArea.nColStart, aDestArea.nRowStart, aDestArea.nTab,
580 : aDestArea.nColEnd, aDestArea.nRowEnd, aDestArea.nTab,
581 0 : IDF_ALL, false, pUndoDoc );
582 :
583 : // alten Ausgabebereich
584 0 : if (pDestData)
585 0 : aDocument.CopyToDocument( aOldDest, IDF_ALL, false, pUndoDoc );
586 :
587 0 : GetUndoManager()->AddUndoAction(
588 : new ScUndoConsolidate( this, aDestArea, rParam, pUndoDoc,
589 0 : false, 0, NULL, pUndoData ) );
590 : }
591 : }
592 :
593 0 : if (pDestData) // Zielbereich loeschen / anpassen
594 : {
595 0 : aDocument.DeleteAreaTab(aOldDest, IDF_CONTENTS);
596 : pDestData->SetArea( rParam.nTab, rParam.nCol, rParam.nRow,
597 0 : rParam.nCol + nColSize - 1, rParam.nRow + nRowSize - 1 );
598 0 : pDestData->SetHeader( rParam.bByRow );
599 : }
600 :
601 0 : aData.OutputToDocument( &aDocument, rParam.nCol, rParam.nRow, rParam.nTab );
602 :
603 0 : SCCOL nPaintStartCol = rParam.nCol;
604 0 : SCROW nPaintStartRow = rParam.nRow;
605 0 : SCCOL nPaintEndCol = nPaintStartCol + nColSize - 1;
606 0 : SCROW nPaintEndRow = nPaintStartRow + nRowSize - 1;
607 0 : sal_uInt16 nPaintFlags = PAINT_GRID;
608 0 : if (rParam.bByCol)
609 0 : ++nPaintEndRow;
610 0 : if (rParam.bByRow)
611 0 : ++nPaintEndCol;
612 0 : if (rParam.bReferenceData)
613 : {
614 0 : nPaintStartCol = 0;
615 0 : nPaintEndCol = MAXCOL;
616 0 : nPaintEndRow = MAXROW;
617 0 : nPaintFlags |= PAINT_LEFT | PAINT_SIZE;
618 : }
619 0 : if (pDestData)
620 : {
621 0 : if ( aOldDest.aEnd.Col() > nPaintEndCol )
622 0 : nPaintEndCol = aOldDest.aEnd.Col();
623 0 : if ( aOldDest.aEnd.Row() > nPaintEndRow )
624 0 : nPaintEndRow = aOldDest.aEnd.Row();
625 : }
626 : PostPaint( nPaintStartCol, nPaintStartRow, rParam.nTab,
627 0 : nPaintEndCol, nPaintEndRow, rParam.nTab, nPaintFlags );
628 0 : aModificator.SetDocumentModified();
629 : }
630 :
631 0 : void ScDocShell::UseScenario( SCTAB nTab, const OUString& rName, bool bRecord )
632 : {
633 0 : if (!aDocument.IsScenario(nTab))
634 : {
635 0 : SCTAB nTabCount = aDocument.GetTableCount();
636 0 : SCTAB nSrcTab = SCTAB_MAX;
637 0 : SCTAB nEndTab = nTab;
638 0 : OUString aCompare;
639 0 : while ( nEndTab+1 < nTabCount && aDocument.IsScenario(nEndTab+1) )
640 : {
641 0 : ++nEndTab;
642 0 : if (nSrcTab > MAXTAB) // noch auf der Suche nach dem Szenario?
643 : {
644 0 : aDocument.GetName( nEndTab, aCompare );
645 0 : if (aCompare.equals(rName))
646 0 : nSrcTab = nEndTab; // gefunden
647 : }
648 : }
649 0 : if (ValidTab(nSrcTab))
650 : {
651 0 : if ( aDocument.TestCopyScenario( nSrcTab, nTab ) ) // Zellschutz testen
652 : {
653 0 : ScDocShellModificator aModificator( *this );
654 0 : ScMarkData aScenMark;
655 0 : aDocument.MarkScenario( nSrcTab, nTab, aScenMark );
656 0 : ScRange aMultiRange;
657 0 : aScenMark.GetMultiMarkArea( aMultiRange );
658 0 : SCCOL nStartCol = aMultiRange.aStart.Col();
659 0 : SCROW nStartRow = aMultiRange.aStart.Row();
660 0 : SCCOL nEndCol = aMultiRange.aEnd.Col();
661 0 : SCROW nEndRow = aMultiRange.aEnd.Row();
662 :
663 0 : if (bRecord)
664 : {
665 0 : ScDocument* pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
666 0 : pUndoDoc->InitUndo( &aDocument, nTab,nEndTab ); // auch alle Szenarien
667 : // angezeigte Tabelle:
668 : aDocument.CopyToDocument( nStartCol,nStartRow,nTab,
669 0 : nEndCol,nEndRow,nTab, IDF_ALL,true, pUndoDoc, &aScenMark );
670 : // Szenarien
671 0 : for (SCTAB i=nTab+1; i<=nEndTab; i++)
672 : {
673 0 : pUndoDoc->SetScenario( i, true );
674 0 : OUString aComment;
675 0 : Color aColor;
676 : sal_uInt16 nScenFlags;
677 0 : aDocument.GetScenarioData( i, aComment, aColor, nScenFlags );
678 0 : pUndoDoc->SetScenarioData( i, aComment, aColor, nScenFlags );
679 0 : sal_Bool bActive = aDocument.IsActiveScenario( i );
680 0 : pUndoDoc->SetActiveScenario( i, bActive );
681 : // Bei Zurueckkopier-Szenarios auch Inhalte
682 0 : if ( nScenFlags & SC_SCENARIO_TWOWAY )
683 : aDocument.CopyToDocument( 0,0,i, MAXCOL,MAXROW,i,
684 0 : IDF_ALL,false, pUndoDoc );
685 0 : }
686 :
687 0 : GetUndoManager()->AddUndoAction(
688 : new ScUndoUseScenario( this, aScenMark,
689 : ScArea( nTab,nStartCol,nStartRow,nEndCol,nEndRow ),
690 0 : pUndoDoc, rName ) );
691 : }
692 :
693 0 : aDocument.CopyScenario( nSrcTab, nTab );
694 :
695 0 : sc::SetFormulaDirtyContext aCxt;
696 0 : aDocument.SetAllFormulasDirty(aCxt);
697 :
698 : // alles painten, weil in anderen Bereichen das aktive Szenario
699 : // geaendert sein kann
700 : //! nur, wenn sichtbare Rahmen vorhanden?
701 0 : PostPaint( 0,0,nTab, MAXCOL,MAXROW,nTab, PAINT_GRID );
702 0 : aModificator.SetDocumentModified();
703 : }
704 : else
705 : {
706 : InfoBox aBox(GetActiveDialogParent(),
707 0 : ScGlobal::GetRscString( STR_PROTECTIONERR ) );
708 0 : aBox.Execute();
709 : }
710 : }
711 : else
712 : {
713 : InfoBox aBox(GetActiveDialogParent(),
714 0 : ScGlobal::GetRscString( STR_SCENARIO_NOTFOUND ) );
715 0 : aBox.Execute();
716 0 : }
717 : }
718 : else
719 : {
720 : OSL_FAIL( "UseScenario auf Szenario-Blatt" );
721 : }
722 0 : }
723 :
724 0 : void ScDocShell::ModifyScenario( SCTAB nTab, const OUString& rName, const OUString& rComment,
725 : const Color& rColor, sal_uInt16 nFlags )
726 : {
727 : // Undo
728 0 : OUString aOldName;
729 0 : aDocument.GetName( nTab, aOldName );
730 0 : OUString aOldComment;
731 0 : Color aOldColor;
732 : sal_uInt16 nOldFlags;
733 0 : aDocument.GetScenarioData( nTab, aOldComment, aOldColor, nOldFlags );
734 0 : GetUndoManager()->AddUndoAction(
735 : new ScUndoScenarioFlags( this, nTab,
736 : aOldName, rName, aOldComment, rComment,
737 0 : aOldColor, rColor, nOldFlags, nFlags ) );
738 :
739 : // ausfuehren
740 0 : ScDocShellModificator aModificator( *this );
741 0 : aDocument.RenameTab( nTab, rName );
742 0 : aDocument.SetScenarioData( nTab, rComment, rColor, nFlags );
743 0 : PostPaintGridAll();
744 0 : aModificator.SetDocumentModified();
745 :
746 0 : if (!aOldName.equals(rName))
747 0 : SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_TABLES_CHANGED ) );
748 :
749 0 : SfxBindings* pBindings = GetViewBindings();
750 0 : if (pBindings)
751 0 : pBindings->Invalidate( SID_SELECT_SCENARIO );
752 0 : }
753 :
754 0 : SCTAB ScDocShell::MakeScenario( SCTAB nTab, const OUString& rName, const OUString& rComment,
755 : const Color& rColor, sal_uInt16 nFlags,
756 : ScMarkData& rMark, bool bRecord )
757 : {
758 0 : rMark.MarkToMulti();
759 0 : if (rMark.IsMultiMarked())
760 : {
761 0 : SCTAB nNewTab = nTab + 1;
762 0 : while (aDocument.IsScenario(nNewTab))
763 0 : ++nNewTab;
764 :
765 0 : sal_Bool bCopyAll = ( (nFlags & SC_SCENARIO_COPYALL) != 0 );
766 0 : const ScMarkData* pCopyMark = NULL;
767 0 : if (!bCopyAll)
768 0 : pCopyMark = &rMark;
769 :
770 0 : ScDocShellModificator aModificator( *this );
771 :
772 0 : if (bRecord)
773 0 : aDocument.BeginDrawUndo(); // drawing layer must do its own undo actions
774 :
775 0 : if (aDocument.CopyTab( nTab, nNewTab, pCopyMark ))
776 : {
777 0 : if (bRecord)
778 : {
779 0 : GetUndoManager()->AddUndoAction(
780 : new ScUndoMakeScenario( this, nTab, nNewTab,
781 0 : rName, rComment, rColor, nFlags, rMark ));
782 : }
783 :
784 0 : aDocument.RenameTab( nNewTab, rName, false ); // ohne Formel-Update
785 0 : aDocument.SetScenario( nNewTab, true );
786 0 : aDocument.SetScenarioData( nNewTab, rComment, rColor, nFlags );
787 :
788 0 : ScMarkData aDestMark = rMark;
789 0 : aDestMark.SelectOneTable( nNewTab );
790 :
791 : //! auf Filter / Buttons / Merging testen !
792 :
793 0 : ScPatternAttr aProtPattern( aDocument.GetPool() );
794 0 : aProtPattern.GetItemSet().Put( ScProtectionAttr( true ) );
795 0 : aDocument.ApplyPatternAreaTab( 0,0, MAXCOL,MAXROW, nNewTab, aProtPattern );
796 :
797 0 : ScPatternAttr aPattern( aDocument.GetPool() );
798 0 : aPattern.GetItemSet().Put( ScMergeFlagAttr( SC_MF_SCENARIO ) );
799 0 : aPattern.GetItemSet().Put( ScProtectionAttr( true ) );
800 0 : aDocument.ApplySelectionPattern( aPattern, aDestMark );
801 :
802 0 : if (!bCopyAll)
803 0 : aDocument.SetVisible( nNewTab, false );
804 :
805 : // dies ist dann das aktive Szenario
806 0 : aDocument.CopyScenario( nNewTab, nTab, true ); // sal_True - nicht aus Szenario kopieren
807 :
808 0 : if (nFlags & SC_SCENARIO_SHOWFRAME)
809 0 : PostPaint( 0,0,nTab, MAXCOL,MAXROW,nTab, PAINT_GRID ); // Rahmen painten
810 0 : PostPaintExtras(); // Tabellenreiter
811 0 : aModificator.SetDocumentModified();
812 :
813 0 : SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_TABLES_CHANGED ) );
814 :
815 0 : return nNewTab;
816 0 : }
817 : }
818 0 : return nTab;
819 : }
820 :
821 0 : sal_uLong ScDocShell::TransferTab( ScDocShell& rSrcDocShell, SCTAB nSrcPos,
822 : SCTAB nDestPos, bool bInsertNew,
823 : bool bNotifyAndPaint )
824 : {
825 0 : ScDocument* pSrcDoc = rSrcDocShell.GetDocument();
826 :
827 : // set the transferred area to the copyparam to make adjusting formulas possible
828 0 : ScClipParam aParam;
829 0 : ScRange aRange(0, 0, nSrcPos, MAXCOL, MAXROW, nSrcPos);
830 0 : aParam.maRanges.Append(aRange);
831 0 : pSrcDoc->SetClipParam(aParam);
832 :
833 : sal_uLong nErrVal = aDocument.TransferTab( pSrcDoc, nSrcPos, nDestPos,
834 0 : bInsertNew ); // no insert
835 :
836 : // TransferTab doesn't copy drawing objects with bInsertNew=FALSE
837 0 : if ( nErrVal > 0 && !bInsertNew)
838 0 : aDocument.TransferDrawPage( pSrcDoc, nSrcPos, nDestPos );
839 :
840 0 : if(nErrVal>0 && pSrcDoc->IsScenario( nSrcPos ))
841 : {
842 0 : OUString aComment;
843 0 : Color aColor;
844 : sal_uInt16 nFlags;
845 :
846 0 : pSrcDoc->GetScenarioData( nSrcPos, aComment,aColor, nFlags);
847 0 : aDocument.SetScenario(nDestPos,true);
848 0 : aDocument.SetScenarioData(nDestPos,aComment,aColor,nFlags);
849 0 : sal_Bool bActive = pSrcDoc->IsActiveScenario(nSrcPos);
850 0 : aDocument.SetActiveScenario(nDestPos, bActive );
851 :
852 0 : sal_Bool bVisible=pSrcDoc->IsVisible(nSrcPos);
853 0 : aDocument.SetVisible(nDestPos,bVisible );
854 :
855 : }
856 :
857 0 : if ( nErrVal > 0 && pSrcDoc->IsTabProtected( nSrcPos ) )
858 0 : aDocument.SetTabProtection(nDestPos, pSrcDoc->GetTabProtection(nSrcPos));
859 0 : if ( bNotifyAndPaint )
860 : {
861 0 : Broadcast( ScTablesHint( SC_TAB_INSERTED, nDestPos ) );
862 0 : PostPaintExtras();
863 0 : PostPaintGridAll();
864 : }
865 0 : return nErrVal;
866 : }
867 :
868 0 : bool ScDocShell::MoveTable( SCTAB nSrcTab, SCTAB nDestTab, bool bCopy, bool bRecord )
869 : {
870 0 : ScDocShellModificator aModificator( *this );
871 :
872 : // #i92477# be consistent with ScDocFunc::InsertTable: any index past the last sheet means "append"
873 : // #i101139# nDestTab must be the target position, not APPEND (for CopyTabProtection etc.)
874 0 : if ( nDestTab >= aDocument.GetTableCount() )
875 0 : nDestTab = aDocument.GetTableCount();
876 :
877 0 : if (bCopy)
878 : {
879 0 : if (bRecord)
880 0 : aDocument.BeginDrawUndo(); // drawing layer must do its own undo actions
881 :
882 0 : OUString sSrcCodeName;
883 0 : aDocument.GetCodeName( nSrcTab, sSrcCodeName );
884 0 : if (!aDocument.CopyTab( nSrcTab, nDestTab ))
885 : {
886 : //! EndDrawUndo?
887 0 : return false;
888 : }
889 : else
890 : {
891 0 : SCTAB nAdjSource = nSrcTab;
892 0 : if ( nDestTab <= nSrcTab )
893 0 : ++nAdjSource; // new position of source table after CopyTab
894 :
895 0 : if ( aDocument.IsTabProtected( nAdjSource ) )
896 0 : aDocument.CopyTabProtection(nAdjSource, nDestTab);
897 :
898 0 : if (bRecord)
899 : {
900 : SAL_WNODEPRECATED_DECLARATIONS_PUSH
901 0 : auto_ptr< vector<SCTAB> > pSrcList(new vector<SCTAB>(1, nSrcTab));
902 0 : auto_ptr< vector<SCTAB> > pDestList(new vector<SCTAB>(1, nDestTab));
903 : SAL_WNODEPRECATED_DECLARATIONS_POP
904 0 : GetUndoManager()->AddUndoAction(
905 0 : new ScUndoCopyTab(this, pSrcList.release(), pDestList.release()));
906 : }
907 :
908 0 : sal_Bool bVbaEnabled = aDocument.IsInVBAMode();
909 0 : if ( bVbaEnabled )
910 : {
911 0 : OUString aLibName( "Standard" );
912 0 : Reference< XLibraryContainer > xLibContainer = GetBasicContainer();
913 0 : Reference< XVBACompatibility > xVBACompat( xLibContainer, UNO_QUERY );
914 :
915 0 : if ( xVBACompat.is() )
916 : {
917 0 : aLibName = xVBACompat->getProjectName();
918 : }
919 :
920 0 : SCTAB nTabToUse = nDestTab;
921 0 : if ( nDestTab == SC_TAB_APPEND )
922 0 : nTabToUse = aDocument.GetMaxTableNumber() - 1;
923 0 : OUString sCodeName;
924 0 : OUString sSource;
925 : try
926 : {
927 0 : Reference< XNameContainer > xLib;
928 0 : if( xLibContainer.is() )
929 : {
930 0 : com::sun::star::uno::Any aLibAny = xLibContainer->getByName( aLibName );
931 0 : aLibAny >>= xLib;
932 : }
933 0 : if( xLib.is() )
934 : {
935 0 : xLib->getByName( sSrcCodeName ) >>= sSource;
936 0 : }
937 : }
938 0 : catch ( const com::sun::star::uno::Exception& )
939 : {
940 : }
941 0 : VBA_InsertModule( aDocument, nTabToUse, sCodeName, sSource );
942 : }
943 : }
944 0 : Broadcast( ScTablesHint( SC_TAB_COPIED, nSrcTab, nDestTab ) );
945 : }
946 : else
947 : {
948 0 : if ( aDocument.GetChangeTrack() )
949 0 : return false;
950 :
951 0 : if ( nSrcTab<nDestTab && nDestTab!=SC_TAB_APPEND )
952 0 : nDestTab--;
953 :
954 0 : if ( nSrcTab == nDestTab )
955 : {
956 : //! allow only for api calls?
957 0 : return true; // nothing to do, but valid
958 : }
959 :
960 : ScProgress* pProgress = new ScProgress(this, ScGlobal::GetRscString(STR_UNDO_MOVE_TAB),
961 0 : aDocument.GetCodeCount());
962 0 : bool bDone = aDocument.MoveTab( nSrcTab, nDestTab, pProgress );
963 0 : delete pProgress;
964 0 : if (!bDone)
965 : {
966 0 : return false;
967 : }
968 0 : else if (bRecord)
969 : {
970 : SAL_WNODEPRECATED_DECLARATIONS_PUSH
971 0 : auto_ptr< vector<SCTAB> > pSrcList(new vector<SCTAB>(1, nSrcTab));
972 0 : auto_ptr< vector<SCTAB> > pDestList(new vector<SCTAB>(1, nDestTab));
973 : SAL_WNODEPRECATED_DECLARATIONS_POP
974 0 : GetUndoManager()->AddUndoAction(
975 0 : new ScUndoMoveTab(this, pSrcList.release(), pDestList.release()));
976 : }
977 :
978 0 : Broadcast( ScTablesHint( SC_TAB_MOVED, nSrcTab, nDestTab ) );
979 : }
980 :
981 0 : PostPaintGridAll();
982 0 : PostPaintExtras();
983 0 : aModificator.SetDocumentModified();
984 0 : SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_TABLES_CHANGED ) );
985 :
986 0 : return true;
987 : }
988 :
989 :
990 0 : IMPL_LINK( ScDocShell, RefreshDBDataHdl, ScRefreshTimer*, pRefreshTimer )
991 : {
992 0 : ScDBDocFunc aFunc(*this);
993 :
994 0 : bool bContinue = true;
995 0 : ScDBData* pDBData = static_cast<ScDBData*>(pRefreshTimer);
996 0 : ScImportParam aImportParam;
997 0 : pDBData->GetImportParam( aImportParam );
998 0 : if (aImportParam.bImport && !pDBData->HasImportSelection())
999 : {
1000 0 : ScRange aRange;
1001 0 : pDBData->GetArea( aRange );
1002 0 : bContinue = aFunc.DoImport( aRange.aStart.Tab(), aImportParam, NULL, true, false ); //! Api-Flag as parameter
1003 : // internal operations (sort, query, subtotal) only if no error
1004 0 : if (bContinue)
1005 : {
1006 0 : aFunc.RepeatDB( pDBData->GetName(), true, true );
1007 0 : RefreshPivotTables(aRange);
1008 : }
1009 : }
1010 :
1011 0 : return long(bContinue);
1012 0 : }
1013 :
1014 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|