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