Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : : *
6 : : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
12 : : * OpenOffice.org is free software: you can redistribute it and/or modify
13 : : * it under the terms of the GNU Lesser General Public License version 3
14 : : * only, as published by the Free Software Foundation.
15 : : *
16 : : * OpenOffice.org is distributed in the hope that it will be useful,
17 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : : * GNU Lesser General Public License version 3 for more details
20 : : * (a copy is included in the LICENSE file that accompanied this code).
21 : : *
22 : : * You should have received a copy of the GNU Lesser General Public License
23 : : * version 3 along with OpenOffice.org. If not, see
24 : : * <http://www.openoffice.org/license.html>
25 : : * for a copy of the LGPLv3 License.
26 : : *
27 : : ************************************************************************/
28 : :
29 : : #include <sfx2/app.hxx>
30 : : #include <vcl/msgbox.hxx>
31 : : #include <vcl/waitobj.hxx>
32 : : #include <svx/dataaccessdescriptor.hxx>
33 : :
34 : : #include <com/sun/star/sdb/CommandType.hpp>
35 : :
36 : : #include "dbdocfun.hxx"
37 : : #include "sc.hrc"
38 : : #include "dbdata.hxx"
39 : : #include "undodat.hxx"
40 : : #include "docsh.hxx"
41 : : #include "docfunc.hxx"
42 : : #include "globstr.hrc"
43 : : #include "globalnames.hxx"
44 : : #include "tabvwsh.hxx"
45 : : #include "patattr.hxx"
46 : : #include "rangenam.hxx"
47 : : #include "olinetab.hxx"
48 : : #include "dpobject.hxx"
49 : : #include "dpsave.hxx"
50 : : #include "dociter.hxx" // for lcl_EmptyExcept
51 : : #include "cell.hxx" // for lcl_EmptyExcept
52 : : #include "editable.hxx"
53 : : #include "attrib.hxx"
54 : : #include "drwlayer.hxx"
55 : : #include "dpshttab.hxx"
56 : : #include "hints.hxx"
57 : : #include "queryentry.hxx"
58 : : #include "markdata.hxx"
59 : : #include "progress.hxx"
60 : :
61 : : #include <set>
62 : :
63 : : using namespace ::com::sun::star;
64 : :
65 : : // -----------------------------------------------------------------
66 : :
67 : 3 : bool ScDBDocFunc::AddDBRange( const ::rtl::OUString& rName, const ScRange& rRange, sal_Bool /* bApi */ )
68 : : {
69 : :
70 [ + - ]: 3 : ScDocShellModificator aModificator( rDocShell );
71 : :
72 : 3 : ScDocument* pDoc = rDocShell.GetDocument();
73 [ + - ]: 3 : ScDBCollection* pDocColl = pDoc->GetDBCollection();
74 : 3 : sal_Bool bUndo (pDoc->IsUndoEnabled());
75 : :
76 : 3 : ScDBCollection* pUndoColl = NULL;
77 [ + - ]: 3 : if (bUndo)
78 [ + - ][ + - ]: 3 : pUndoColl = new ScDBCollection( *pDocColl );
79 : :
80 : 3 : ScDBData* pNew = new ScDBData( rName, rRange.aStart.Tab(),
81 : 3 : rRange.aStart.Col(), rRange.aStart.Row(),
82 [ + - ][ + - ]: 3 : rRange.aEnd.Col(), rRange.aEnd.Row() );
83 : :
84 : : // #i55926# While loading XML, formula cells only have a single string token,
85 : : // so CompileDBFormula would never find any name (index) tokens, and would
86 : : // unnecessarily loop through all cells.
87 : 3 : bool bCompile = !pDoc->IsImportingXML();
88 : : bool bOk;
89 [ + - ]: 3 : if ( bCompile )
90 [ + - ]: 3 : pDoc->CompileDBFormula( sal_True ); // CreateFormulaString
91 [ - + ]: 3 : if ( rName == STR_DB_LOCAL_NONAME )
92 : : {
93 [ # # ]: 0 : pDoc->SetAnonymousDBData(rRange.aStart.Tab() , pNew);
94 : 0 : bOk = true;
95 : : }
96 : : else
97 : : {
98 [ + - ][ + - ]: 3 : bOk = pDocColl->getNamedDBs().insert(pNew);
99 : : }
100 [ + - ]: 3 : if ( bCompile )
101 [ + - ]: 3 : pDoc->CompileDBFormula( false ); // CompileFormulaString
102 : :
103 [ - + ]: 3 : if (!bOk)
104 : : {
105 [ # # ][ # # ]: 0 : delete pNew;
106 [ # # ][ # # ]: 0 : delete pUndoColl;
107 : 0 : return false;
108 : : }
109 : :
110 [ + - ]: 3 : if (bUndo)
111 : : {
112 [ + - ][ + - ]: 3 : ScDBCollection* pRedoColl = new ScDBCollection( *pDocColl );
113 [ + - ]: 3 : rDocShell.GetUndoManager()->AddUndoAction(
114 [ + - ][ + - ]: 3 : new ScUndoDBData( &rDocShell, pUndoColl, pRedoColl ) );
[ + - ]
115 : : }
116 : :
117 [ + - ]: 3 : aModificator.SetDocumentModified();
118 [ + - ][ + - ]: 3 : SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_DBAREAS_CHANGED ) );
[ + - ][ + - ]
119 [ + - ]: 3 : return true;
120 : : }
121 : :
122 : 0 : bool ScDBDocFunc::DeleteDBRange(const ::rtl::OUString& rName)
123 : : {
124 : 0 : bool bDone = false;
125 : 0 : ScDocument* pDoc = rDocShell.GetDocument();
126 : 0 : ScDBCollection* pDocColl = pDoc->GetDBCollection();
127 : 0 : bool bUndo = pDoc->IsUndoEnabled();
128 : :
129 : 0 : ScDBCollection::NamedDBs& rDBs = pDocColl->getNamedDBs();
130 : 0 : const ScDBData* p = rDBs.findByName(rName);
131 [ # # ]: 0 : if (p)
132 : : {
133 [ # # ]: 0 : ScDocShellModificator aModificator( rDocShell );
134 : :
135 : 0 : ScDBCollection* pUndoColl = NULL;
136 [ # # ]: 0 : if (bUndo)
137 [ # # ][ # # ]: 0 : pUndoColl = new ScDBCollection( *pDocColl );
138 : :
139 [ # # ]: 0 : pDoc->CompileDBFormula( true ); // CreateFormulaString
140 [ # # ]: 0 : rDBs.erase(*p);
141 [ # # ]: 0 : pDoc->CompileDBFormula( false ); // CompileFormulaString
142 : :
143 [ # # ]: 0 : if (bUndo)
144 : : {
145 [ # # ][ # # ]: 0 : ScDBCollection* pRedoColl = new ScDBCollection( *pDocColl );
146 [ # # ]: 0 : rDocShell.GetUndoManager()->AddUndoAction(
147 [ # # ][ # # ]: 0 : new ScUndoDBData( &rDocShell, pUndoColl, pRedoColl ) );
[ # # ]
148 : : }
149 : :
150 [ # # ]: 0 : aModificator.SetDocumentModified();
151 [ # # ][ # # ]: 0 : SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_DBAREAS_CHANGED ) );
[ # # ][ # # ]
152 [ # # ]: 0 : bDone = true;
153 : : }
154 : :
155 : 0 : return bDone;
156 : : }
157 : :
158 : 2 : bool ScDBDocFunc::RenameDBRange( const String& rOld, const String& rNew )
159 : : {
160 : 2 : bool bDone = false;
161 : 2 : ScDocument* pDoc = rDocShell.GetDocument();
162 : 2 : ScDBCollection* pDocColl = pDoc->GetDBCollection();
163 : 2 : bool bUndo = pDoc->IsUndoEnabled();
164 : 2 : ScDBCollection::NamedDBs& rDBs = pDocColl->getNamedDBs();
165 [ + - ]: 2 : const ScDBData* pOld = rDBs.findByName(rOld);
166 [ + - ]: 2 : const ScDBData* pNew = rDBs.findByName(rNew);
167 [ + - ][ + - ]: 2 : if (pOld && !pNew)
168 : : {
169 [ + - ]: 2 : ScDocShellModificator aModificator( rDocShell );
170 : :
171 [ + - ][ + - ]: 2 : ScDBData* pNewData = new ScDBData(rNew, *pOld);
[ + - ]
172 : :
173 [ + - ][ + - ]: 2 : ScDBCollection* pUndoColl = new ScDBCollection( *pDocColl );
174 : :
175 [ + - ]: 2 : pDoc->CompileDBFormula(true); // CreateFormulaString
176 [ + - ]: 2 : rDBs.erase(*pOld);
177 [ + - ]: 2 : bool bInserted = rDBs.insert(pNewData);
178 [ - + ]: 2 : if (!bInserted) // Fehler -> alten Zustand wiederherstellen
179 [ # # ]: 0 : pDoc->SetDBCollection(pUndoColl); // gehoert dann dem Dokument
180 : : //
181 [ + - ]: 2 : pDoc->CompileDBFormula( false ); // CompileFormulaString
182 : :
183 [ + - ]: 2 : if (bInserted) // Einfuegen hat geklappt
184 : : {
185 [ + - ]: 2 : if (bUndo)
186 : : {
187 [ + - ][ + - ]: 2 : ScDBCollection* pRedoColl = new ScDBCollection( *pDocColl );
188 [ + - ]: 2 : rDocShell.GetUndoManager()->AddUndoAction(
189 [ + - ][ + - ]: 2 : new ScUndoDBData( &rDocShell, pUndoColl, pRedoColl ) );
[ + - ]
190 : : }
191 : : else
192 [ # # ][ # # ]: 0 : delete pUndoColl;
193 : :
194 [ + - ]: 2 : aModificator.SetDocumentModified();
195 [ + - ][ + - ]: 2 : SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_DBAREAS_CHANGED ) );
[ + - ][ + - ]
196 : 2 : bDone = true;
197 [ + - ]: 2 : }
198 : : }
199 : :
200 : 2 : return bDone;
201 : : }
202 : :
203 : 48 : bool ScDBDocFunc::ModifyDBData( const ScDBData& rNewData )
204 : : {
205 : 48 : bool bDone = false;
206 : 48 : ScDocument* pDoc = rDocShell.GetDocument();
207 : 48 : ScDBCollection* pDocColl = pDoc->GetDBCollection();
208 : 48 : bool bUndo = pDoc->IsUndoEnabled();
209 : :
210 : 48 : ScDBData* pData = NULL;
211 [ + + ]: 48 : if (rNewData.GetName().equalsAsciiL(RTL_CONSTASCII_STRINGPARAM(STR_DB_LOCAL_NONAME)))
212 : : {
213 : 24 : ScRange aRange;
214 [ + - ]: 24 : rNewData.GetArea(aRange);
215 : 24 : SCTAB nTab = aRange.aStart.Tab();
216 [ + - ]: 24 : pData = pDoc->GetAnonymousDBData(nTab);
217 : : }
218 : : else
219 : 24 : pData = pDocColl->getNamedDBs().findByName(rNewData.GetName());
220 : :
221 [ + - ]: 48 : if (pData)
222 : : {
223 [ + - ]: 48 : ScDocShellModificator aModificator( rDocShell );
224 : 48 : ScRange aOldRange, aNewRange;
225 [ + - ]: 48 : pData->GetArea(aOldRange);
226 [ + - ]: 48 : rNewData.GetArea(aNewRange);
227 : 48 : bool bAreaChanged = ( aOldRange != aNewRange ); // dann muss neu compiliert werden
228 : :
229 : 48 : ScDBCollection* pUndoColl = NULL;
230 [ + + ]: 48 : if (bUndo)
231 [ + - ][ + - ]: 24 : pUndoColl = new ScDBCollection( *pDocColl );
232 : :
233 [ + - ]: 48 : *pData = rNewData;
234 [ + + ]: 48 : if (bAreaChanged)
235 [ + - ]: 2 : pDoc->CompileDBFormula();
236 : :
237 [ + + ]: 48 : if (bUndo)
238 : : {
239 [ + - ][ + - ]: 24 : ScDBCollection* pRedoColl = new ScDBCollection( *pDocColl );
240 [ + - ]: 24 : rDocShell.GetUndoManager()->AddUndoAction(
241 [ + - ][ + - ]: 24 : new ScUndoDBData( &rDocShell, pUndoColl, pRedoColl ) );
[ + - ]
242 : : }
243 : :
244 [ + - ]: 48 : aModificator.SetDocumentModified();
245 [ + - ]: 48 : bDone = true;
246 : : }
247 : :
248 : 48 : return bDone;
249 : : }
250 : :
251 : : // -----------------------------------------------------------------
252 : :
253 : 2 : bool ScDBDocFunc::RepeatDB( const ::rtl::OUString& rDBName, bool bRecord, bool bApi, bool bIsUnnamed, SCTAB aTab )
254 : : {
255 : : //! auch fuer ScDBFunc::RepeatDB benutzen!
256 : :
257 : 2 : bool bDone = false;
258 : 2 : ScDocument* pDoc = rDocShell.GetDocument();
259 [ - + ][ - + ]: 2 : if (bRecord && !pDoc->IsUndoEnabled())
[ + - ]
260 : 0 : bRecord = false;
261 : 2 : ScDBData* pDBData = NULL;
262 [ - + ]: 2 : if (bIsUnnamed)
263 : : {
264 : 0 : pDBData = pDoc->GetAnonymousDBData( aTab );
265 : : }
266 : : else
267 : : {
268 : 2 : ScDBCollection* pColl = pDoc->GetDBCollection();
269 [ + - ]: 2 : if (pColl)
270 : 2 : pDBData = pColl->getNamedDBs().findByName(rDBName);
271 : : }
272 : :
273 [ + - ]: 2 : if ( pDBData )
274 : : {
275 [ + - ]: 2 : ScQueryParam aQueryParam;
276 [ + - ]: 2 : pDBData->GetQueryParam( aQueryParam );
277 [ + - ]: 2 : sal_Bool bQuery = aQueryParam.GetEntry(0).bDoQuery;
278 : :
279 [ + - ]: 2 : ScSortParam aSortParam;
280 [ + - ]: 2 : pDBData->GetSortParam( aSortParam );
281 : 2 : sal_Bool bSort = aSortParam.maKeyState[0].bDoSort;
282 : :
283 [ + - ]: 2 : ScSubTotalParam aSubTotalParam;
284 [ + - ]: 2 : pDBData->GetSubTotalParam( aSubTotalParam );
285 [ - + ][ # # ]: 2 : sal_Bool bSubTotal = aSubTotalParam.bGroupActive[0] && !aSubTotalParam.bRemoveOnly;
286 : :
287 [ - + ][ # # ]: 2 : if ( bQuery || bSort || bSubTotal )
[ # # ]
288 : : {
289 : 2 : sal_Bool bQuerySize = false;
290 : 2 : ScRange aOldQuery;
291 : 2 : ScRange aNewQuery;
292 [ - + ][ + - ]: 2 : if (bQuery && !aQueryParam.bInplace)
293 : : {
294 : : ScDBData* pDest = pDoc->GetDBAtCursor( aQueryParam.nDestCol, aQueryParam.nDestRow,
295 [ # # ]: 0 : aQueryParam.nDestTab, sal_True );
296 [ # # ][ # # ]: 0 : if (pDest && pDest->IsDoSize())
[ # # ]
297 : : {
298 [ # # ]: 0 : pDest->GetArea( aOldQuery );
299 : 0 : bQuerySize = sal_True;
300 : : }
301 : : }
302 : :
303 : : SCTAB nTab;
304 : : SCCOL nStartCol;
305 : : SCROW nStartRow;
306 : : SCCOL nEndCol;
307 : : SCROW nEndRow;
308 [ + - ]: 2 : pDBData->GetArea( nTab, nStartCol, nStartRow, nEndCol, nEndRow );
309 : :
310 : : //! Undo nur benoetigte Daten ?
311 : :
312 : 2 : ScDocument* pUndoDoc = NULL;
313 : 2 : ScOutlineTable* pUndoTab = NULL;
314 : 2 : ScRangeName* pUndoRange = NULL;
315 : 2 : ScDBCollection* pUndoDB = NULL;
316 : :
317 [ + - ]: 2 : if (bRecord)
318 : : {
319 [ + - ]: 2 : SCTAB nTabCount = pDoc->GetTableCount();
320 [ + - ][ + - ]: 2 : pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
321 [ + - ]: 2 : ScOutlineTable* pTable = pDoc->GetOutlineTable( nTab );
322 [ - + ]: 2 : if (pTable)
323 : : {
324 [ # # ][ # # ]: 0 : pUndoTab = new ScOutlineTable( *pTable );
325 : :
326 : : // column/row state
327 : : SCCOLROW nOutStartCol, nOutEndCol;
328 : : SCCOLROW nOutStartRow, nOutEndRow;
329 [ # # ]: 0 : pTable->GetColArray()->GetRange( nOutStartCol, nOutEndCol );
330 [ # # ]: 0 : pTable->GetRowArray()->GetRange( nOutStartRow, nOutEndRow );
331 : :
332 [ # # ]: 0 : pUndoDoc->InitUndo( pDoc, nTab, nTab, sal_True, sal_True );
333 : : pDoc->CopyToDocument( static_cast<SCCOL>(nOutStartCol), 0,
334 : : nTab, static_cast<SCCOL>(nOutEndCol), MAXROW, nTab,
335 [ # # ]: 0 : IDF_NONE, false, pUndoDoc );
336 : : pDoc->CopyToDocument( 0, static_cast<SCROW>(nOutStartRow),
337 : : nTab, MAXCOL, static_cast<SCROW>(nOutEndRow), nTab,
338 [ # # ]: 0 : IDF_NONE, false, pUndoDoc );
339 : : }
340 : : else
341 [ + - ]: 2 : pUndoDoc->InitUndo( pDoc, nTab, nTab, false, sal_True );
342 : :
343 : : // Datenbereich sichern - incl. Filter-Ergebnis
344 [ + - ]: 2 : pDoc->CopyToDocument( 0,nStartRow,nTab, MAXCOL,nEndRow,nTab, IDF_ALL, false, pUndoDoc );
345 : :
346 : : // alle Formeln wegen Referenzen
347 [ + - ]: 2 : pDoc->CopyToDocument( 0,0,0, MAXCOL,MAXROW,nTabCount-1, IDF_FORMULA, false, pUndoDoc );
348 : :
349 : : // DB- und andere Bereiche
350 [ + - ]: 2 : ScRangeName* pDocRange = pDoc->GetRangeName();
351 [ + - ][ - + ]: 2 : if (!pDocRange->empty())
352 [ # # ][ # # ]: 0 : pUndoRange = new ScRangeName( *pDocRange );
353 [ + - ]: 2 : ScDBCollection* pDocDB = pDoc->GetDBCollection();
354 [ + - ][ + - ]: 2 : if (!pDocDB->empty())
355 [ + - ][ + - ]: 2 : pUndoDB = new ScDBCollection( *pDocDB );
356 : : }
357 : :
358 [ - + ][ # # ]: 2 : if (bSort && bSubTotal)
359 : : {
360 : : // Sortieren ohne SubTotals
361 : :
362 : 0 : aSubTotalParam.bRemoveOnly = sal_True; // wird unten wieder zurueckgesetzt
363 [ # # ]: 0 : DoSubTotals( nTab, aSubTotalParam, NULL, false, bApi );
364 : : }
365 : :
366 [ - + ]: 2 : if (bSort)
367 : : {
368 [ # # ]: 0 : pDBData->GetSortParam( aSortParam ); // Bereich kann sich geaendert haben
369 [ # # ]: 0 : Sort( nTab, aSortParam, false, false, bApi );
370 : : }
371 [ + - ]: 2 : if (bQuery)
372 : : {
373 [ + - ]: 2 : pDBData->GetQueryParam( aQueryParam ); // Bereich kann sich geaendert haben
374 : 2 : ScRange aAdvSource;
375 [ - + ][ + - ]: 2 : if (pDBData->GetAdvancedQuerySource(aAdvSource))
376 [ # # ]: 0 : Query( nTab, aQueryParam, &aAdvSource, false, bApi );
377 : : else
378 [ + - ]: 2 : Query( nTab, aQueryParam, NULL, false, bApi );
379 : :
380 : : // bei nicht-inplace kann die Tabelle umgestellt worden sein
381 : : // if ( !aQueryParam.bInplace && aQueryParam.nDestTab != nTab )
382 : : // SetTabNo( nTab );
383 : : }
384 [ - + ]: 2 : if (bSubTotal)
385 : : {
386 [ # # ]: 0 : pDBData->GetSubTotalParam( aSubTotalParam ); // Bereich kann sich geaendert haben
387 : 0 : aSubTotalParam.bRemoveOnly = false;
388 [ # # ]: 0 : DoSubTotals( nTab, aSubTotalParam, NULL, false, bApi );
389 : : }
390 : :
391 [ + - ]: 2 : if (bRecord)
392 : : {
393 : : SCTAB nDummyTab;
394 : : SCCOL nDummyCol;
395 : : SCROW nDummyRow;
396 : : SCROW nNewEndRow;
397 [ + - ]: 2 : pDBData->GetArea( nDummyTab, nDummyCol,nDummyRow, nDummyCol,nNewEndRow );
398 : :
399 : 2 : const ScRange* pOld = NULL;
400 : 2 : const ScRange* pNew = NULL;
401 [ - + ]: 2 : if (bQuerySize)
402 : : {
403 : : ScDBData* pDest = pDoc->GetDBAtCursor( aQueryParam.nDestCol, aQueryParam.nDestRow,
404 [ # # ]: 0 : aQueryParam.nDestTab, sal_True );
405 [ # # ]: 0 : if (pDest)
406 : : {
407 [ # # ]: 0 : pDest->GetArea( aNewQuery );
408 : 0 : pOld = &aOldQuery;
409 : 0 : pNew = &aNewQuery;
410 : : }
411 : : }
412 : :
413 [ + - ]: 2 : rDocShell.GetUndoManager()->AddUndoAction(
414 : : new ScUndoRepeatDB( &rDocShell, nTab,
415 : : nStartCol, nStartRow, nEndCol, nEndRow,
416 : : nNewEndRow,
417 : : //nCurX, nCurY,
418 : : nStartCol, nStartRow,
419 : : pUndoDoc, pUndoTab,
420 : : pUndoRange, pUndoDB,
421 [ + - ][ + - ]: 2 : pOld, pNew ) );
[ + - ]
422 : : }
423 : :
424 : : rDocShell.PostPaint(ScRange(0, 0, nTab, MAXCOL, MAXROW, nTab),
425 [ + - ][ + - ]: 2 : PAINT_GRID | PAINT_LEFT | PAINT_TOP | PAINT_SIZE);
[ + - ]
426 : 2 : bDone = sal_True;
427 : : }
428 [ # # ]: 0 : else if (!bApi) // "Keine Operationen auszufuehren"
429 [ # # ][ + - ]: 2 : rDocShell.ErrorMessage(STR_MSSG_REPEATDB_0);
[ + - ]
430 : : }
431 : :
432 : 2 : return bDone;
433 : : }
434 : :
435 : : // -----------------------------------------------------------------
436 : :
437 : 10 : sal_Bool ScDBDocFunc::Sort( SCTAB nTab, const ScSortParam& rSortParam,
438 : : sal_Bool bRecord, sal_Bool bPaint, sal_Bool bApi )
439 : : {
440 [ + - ]: 10 : ScDocShellModificator aModificator( rDocShell );
441 : :
442 : 10 : ScDocument* pDoc = rDocShell.GetDocument();
443 [ - + ][ - + ]: 10 : if (bRecord && !pDoc->IsUndoEnabled())
[ + + ]
444 : 0 : bRecord = false;
445 : 10 : SCTAB nSrcTab = nTab;
446 [ + - ]: 10 : ScDrawLayer* pDrawLayer = pDoc->GetDrawLayer();
447 : :
448 : : ScDBData* pDBData = pDoc->GetDBAtArea( nTab, rSortParam.nCol1, rSortParam.nRow1,
449 [ + - ]: 10 : rSortParam.nCol2, rSortParam.nRow2 );
450 [ - + ]: 10 : if (!pDBData)
451 : : {
452 : : OSL_FAIL( "Sort: keine DBData" );
453 : 0 : return false;
454 : : }
455 : :
456 : 10 : ScDBData* pDestData = NULL;
457 : 10 : ScRange aOldDest;
458 : 10 : sal_Bool bCopy = !rSortParam.bInplace;
459 [ # # ][ # # ]: 10 : if ( bCopy && rSortParam.nDestCol == rSortParam.nCol1 &&
[ # # ][ - + ]
460 : : rSortParam.nDestRow == rSortParam.nRow1 && rSortParam.nDestTab == nTab )
461 : 0 : bCopy = false;
462 [ + - ]: 10 : ScSortParam aLocalParam( rSortParam );
463 [ - + ]: 10 : if ( bCopy )
464 : : {
465 [ # # ]: 0 : aLocalParam.MoveToDest();
466 [ # # ]: 0 : if ( !ValidColRow( aLocalParam.nCol2, aLocalParam.nRow2 ) )
467 : : {
468 [ # # ]: 0 : if (!bApi)
469 [ # # ]: 0 : rDocShell.ErrorMessage(STR_PASTE_FULL);
470 : 0 : return false;
471 : : }
472 : :
473 : 0 : nTab = rSortParam.nDestTab;
474 : : pDestData = pDoc->GetDBAtCursor( rSortParam.nDestCol, rSortParam.nDestRow,
475 [ # # ]: 0 : rSortParam.nDestTab, sal_True );
476 [ # # ]: 0 : if (pDestData)
477 [ # # ]: 0 : pDestData->GetArea(aOldDest);
478 : : }
479 : :
480 : : ScEditableTester aTester( pDoc, nTab, aLocalParam.nCol1,aLocalParam.nRow1,
481 [ + - ]: 10 : aLocalParam.nCol2,aLocalParam.nRow2 );
482 [ - + ]: 10 : if (!aTester.IsEditable())
483 : : {
484 [ # # ]: 0 : if (!bApi)
485 [ # # ][ # # ]: 0 : rDocShell.ErrorMessage(aTester.GetMessageId());
486 : 0 : return false;
487 : : }
488 : :
489 [ + + ][ - + ]: 18 : if ( aLocalParam.bIncludePattern && pDoc->HasAttrib(
[ - + ]
490 : : aLocalParam.nCol1, aLocalParam.nRow1, nTab,
491 : : aLocalParam.nCol2, aLocalParam.nRow2, nTab,
492 [ + - ]: 8 : HASATTR_MERGED | HASATTR_OVERLAPPED ) )
493 : : {
494 : : // Merge-Attribute wuerden beim Sortieren durcheinanderkommen
495 [ # # ]: 0 : if (!bApi)
496 [ # # ]: 0 : rDocShell.ErrorMessage(STR_SORT_ERR_MERGED);
497 : 0 : return false;
498 : : }
499 : :
500 : :
501 : : // ausfuehren
502 : :
503 [ + - ][ + - ]: 10 : WaitObject aWait( rDocShell.GetActiveDialogParent() );
504 : :
505 : 10 : sal_Bool bRepeatQuery = false; // bestehenden Filter wiederholen?
506 [ + - ]: 10 : ScQueryParam aQueryParam;
507 [ + - ]: 10 : pDBData->GetQueryParam( aQueryParam );
508 [ + - ][ - + ]: 10 : if ( aQueryParam.GetEntry(0).bDoQuery )
509 : 0 : bRepeatQuery = sal_True;
510 : :
511 [ - + ][ # # ]: 10 : if (bRepeatQuery && bCopy)
512 : : {
513 [ # # ][ # # ]: 0 : if ( aQueryParam.bInplace ||
[ # # ][ # # ]
514 : : aQueryParam.nDestCol != rSortParam.nDestCol ||
515 : : aQueryParam.nDestRow != rSortParam.nDestRow ||
516 : : aQueryParam.nDestTab != rSortParam.nDestTab ) // Query auf selben Zielbereich?
517 : 0 : bRepeatQuery = false;
518 : : }
519 : :
520 : 10 : ScUndoSort* pUndoAction = 0;
521 [ + + ]: 10 : if ( bRecord )
522 : : {
523 : : // Referenzen ausserhalb des Bereichs werden nicht veraendert !
524 : :
525 [ + - ][ + - ]: 8 : ScDocument* pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
526 : : // Zeilenhoehen immer (wegen automatischer Anpassung)
527 : : //! auf ScBlockUndo umstellen
528 [ + - ]: 8 : pUndoDoc->InitUndo( pDoc, nTab, nTab, false, sal_True );
529 : :
530 : : /* #i59745# Do not copy note captions to undo document. All existing
531 : : caption objects will be repositioned while sorting which is tracked
532 : : in drawing undo. When undo is executed, the old positions will be
533 : : restored, and the cells with the old notes (which still refer to the
534 : : existing captions) will be copied back into the source document. */
535 : : pDoc->CopyToDocument( aLocalParam.nCol1, aLocalParam.nRow1, nTab,
536 : : aLocalParam.nCol2, aLocalParam.nRow2, nTab,
537 [ + - ]: 8 : IDF_ALL|IDF_NOCAPTIONS, false, pUndoDoc );
538 : :
539 : 8 : const ScRange* pR = 0;
540 [ - + ]: 8 : if (pDestData)
541 : : {
542 : : /* #i59745# Do not copy note captions from destination range to
543 : : undo document. All existing caption objects will be removed
544 : : which is tracked in drawing undo. When undo is executed, the
545 : : caption objects are reinserted with drawing undo, and the cells
546 : : with the old notes (which still refer to the existing captions)
547 : : will be copied back into the source document. */
548 [ # # ]: 0 : pDoc->CopyToDocument( aOldDest, IDF_ALL|IDF_NOCAPTIONS, false, pUndoDoc );
549 : 0 : pR = &aOldDest;
550 : : }
551 : :
552 : : // Zeilenhoehen immer (wegen automatischer Anpassung)
553 : : //! auf ScBlockUndo umstellen
554 : : // if (bRepeatQuery)
555 : : pDoc->CopyToDocument( 0, aLocalParam.nRow1, nTab, MAXCOL, aLocalParam.nRow2, nTab,
556 [ + - ]: 8 : IDF_NONE, false, pUndoDoc );
557 : :
558 : 8 : ScDBCollection* pUndoDB = NULL;
559 [ + - ]: 8 : ScDBCollection* pDocDB = pDoc->GetDBCollection();
560 [ + - ][ - + ]: 8 : if (!pDocDB->empty())
561 [ # # ][ # # ]: 0 : pUndoDB = new ScDBCollection( *pDocDB );
562 : :
563 [ + - ][ + - ]: 8 : pUndoAction = new ScUndoSort( &rDocShell, nTab, rSortParam, bRepeatQuery, pUndoDoc, pUndoDB, pR );
564 [ + - ][ + - ]: 8 : rDocShell.GetUndoManager()->AddUndoAction( pUndoAction );
565 : :
566 : : // #i59745# collect all drawing undo actions affecting cell note captions
567 [ + - ]: 8 : if( pDrawLayer )
568 [ + - ]: 8 : pDrawLayer->BeginCalcUndo();
569 : : }
570 : :
571 [ - + ]: 10 : if ( bCopy )
572 : : {
573 [ # # ]: 0 : if (pDestData)
574 [ # # ]: 0 : pDoc->DeleteAreaTab(aOldDest, IDF_CONTENTS); // Zielbereich vorher loeschen
575 : :
576 : : ScRange aSource( rSortParam.nCol1,rSortParam.nRow1,nSrcTab,
577 : 0 : rSortParam.nCol2,rSortParam.nRow2,nSrcTab );
578 : 0 : ScAddress aDest( rSortParam.nDestCol, rSortParam.nDestRow, rSortParam.nDestTab );
579 : :
580 [ # # ]: 0 : rDocShell.GetDocFunc().MoveBlock( aSource, aDest, false, false, false, sal_True );
581 : : }
582 : :
583 : : // don't call ScDocument::Sort with an empty SortParam (may be empty here if bCopy is set)
584 [ + - ][ + - ]: 10 : if (aLocalParam.GetSortKeyCount() && aLocalParam.maKeyState[0].bDoSort)
[ + - ]
585 [ + - ]: 10 : pDoc->Sort( nTab, aLocalParam, bRepeatQuery );
586 : :
587 : 10 : sal_Bool bSave = sal_True;
588 [ - + ]: 10 : if (bCopy)
589 : : {
590 [ # # ]: 0 : ScSortParam aOldSortParam;
591 [ # # ]: 0 : pDBData->GetSortParam( aOldSortParam );
592 [ # # # # ]: 0 : if (aOldSortParam.GetSortKeyCount() &&
[ # # ][ # # ]
593 : 0 : aOldSortParam.maKeyState[0].bDoSort && aOldSortParam.bInplace)
594 : : {
595 : 0 : bSave = false;
596 : 0 : aOldSortParam.nDestCol = rSortParam.nDestCol;
597 : 0 : aOldSortParam.nDestRow = rSortParam.nDestRow;
598 : 0 : aOldSortParam.nDestTab = rSortParam.nDestTab;
599 [ # # ]: 0 : pDBData->SetSortParam( aOldSortParam ); // dann nur DestPos merken
600 [ # # ]: 0 : }
601 : : }
602 [ + - ]: 10 : if (bSave) // Parameter merken
603 : : {
604 [ + - ]: 10 : pDBData->SetSortParam( rSortParam );
605 : 10 : pDBData->SetHeader( rSortParam.bHasHeader ); //! ???
606 : 10 : pDBData->SetByRow( rSortParam.bByRow ); //! ???
607 : : }
608 : :
609 [ - + ]: 10 : if (bCopy) // neuen DB-Bereich merken
610 : : {
611 : : // Tabelle umschalten von aussen (View)
612 : : //! SetCursor ??!?!
613 : :
614 : : ScRange aDestPos( aLocalParam.nCol1, aLocalParam.nRow1, nTab,
615 : 0 : aLocalParam.nCol2, aLocalParam.nRow2, nTab );
616 : : ScDBData* pNewData;
617 [ # # ]: 0 : if (pDestData)
618 : 0 : pNewData = pDestData; // Bereich vorhanden -> anpassen
619 : : else // Bereich ab Cursor/Markierung wird angelegt
620 [ # # ]: 0 : pNewData = rDocShell.GetDBData(aDestPos, SC_DB_MAKE, SC_DBSEL_FORCE_MARK );
621 [ # # ]: 0 : if (pNewData)
622 : : {
623 : : pNewData->SetArea( nTab,
624 : : aLocalParam.nCol1,aLocalParam.nRow1,
625 [ # # ]: 0 : aLocalParam.nCol2,aLocalParam.nRow2 );
626 [ # # ]: 0 : pNewData->SetSortParam( aLocalParam );
627 : 0 : pNewData->SetHeader( aLocalParam.bHasHeader ); //! ???
628 : 0 : pNewData->SetByRow( aLocalParam.bByRow );
629 : : }
630 : : else
631 : : {
632 : : OSL_FAIL("Zielbereich nicht da");
633 : : }
634 : : }
635 : :
636 : : ScRange aDirtyRange( aLocalParam.nCol1, aLocalParam.nRow1, nTab,
637 : 10 : aLocalParam.nCol2, aLocalParam.nRow2, nTab );
638 [ + - ]: 10 : pDoc->SetDirty( aDirtyRange );
639 : :
640 [ + + ]: 10 : if (bPaint)
641 : : {
642 : 8 : sal_uInt16 nPaint = PAINT_GRID;
643 : 8 : SCCOL nStartX = aLocalParam.nCol1;
644 : 8 : SCROW nStartY = aLocalParam.nRow1;
645 : 8 : SCCOL nEndX = aLocalParam.nCol2;
646 : 8 : SCROW nEndY = aLocalParam.nRow2;
647 [ - + ]: 8 : if ( bRepeatQuery )
648 : : {
649 : 0 : nPaint |= PAINT_LEFT;
650 : 0 : nStartX = 0;
651 : 0 : nEndX = MAXCOL;
652 : : }
653 [ - + ]: 8 : if (pDestData)
654 : : {
655 [ # # ]: 0 : if ( nEndX < aOldDest.aEnd.Col() )
656 : 0 : nEndX = aOldDest.aEnd.Col();
657 [ # # ]: 0 : if ( nEndY < aOldDest.aEnd.Row() )
658 : 0 : nEndY = aOldDest.aEnd.Row();
659 : : }
660 [ + - ][ + - ]: 8 : rDocShell.PostPaint(ScRange(nStartX, nStartY, nTab, nEndX, nEndY, nTab), nPaint);
[ + - ]
661 : : }
662 : :
663 : : // AdjustRowHeight( aLocalParam.nRow1, aLocalParam.nRow2, bPaint );
664 [ + - ]: 10 : rDocShell.AdjustRowHeight( aLocalParam.nRow1, aLocalParam.nRow2, nTab );
665 : :
666 : : // #i59745# set collected drawing undo actions at sorting undo action
667 [ + + ][ + - ]: 10 : if( pUndoAction && pDrawLayer )
668 [ + - ][ + - ]: 8 : pUndoAction->SetDrawUndoAction( pDrawLayer->GetCalcUndo() );
669 : :
670 [ + - ]: 10 : aModificator.SetDocumentModified();
671 : :
672 [ + - ][ + - ]: 10 : return sal_True;
[ + - ][ + - ]
673 : : }
674 : :
675 : : // -----------------------------------------------------------------
676 : :
677 : 4 : sal_Bool ScDBDocFunc::Query( SCTAB nTab, const ScQueryParam& rQueryParam,
678 : : const ScRange* pAdvSource, sal_Bool bRecord, sal_Bool bApi )
679 : : {
680 [ + - ]: 4 : ScDocShellModificator aModificator( rDocShell );
681 : :
682 : 4 : ScDocument* pDoc = rDocShell.GetDocument();
683 [ - + ][ - + ]: 4 : if (bRecord && !pDoc->IsUndoEnabled())
[ + + ]
684 : 0 : bRecord = false;
685 : : ScDBData* pDBData = pDoc->GetDBAtArea( nTab, rQueryParam.nCol1, rQueryParam.nRow1,
686 [ + - ]: 4 : rQueryParam.nCol2, rQueryParam.nRow2 );
687 [ - + ]: 4 : if (!pDBData)
688 : : {
689 : : OSL_FAIL( "Query: keine DBData" );
690 : 0 : return false;
691 : : }
692 : :
693 : : // Wechsel von Inplace auf nicht-Inplace, dann erst Inplace aufheben:
694 : : // (nur, wenn im Dialog "Persistent" ausgewaehlt ist)
695 : :
696 [ - + ][ # # ]: 4 : if ( !rQueryParam.bInplace && pDBData->HasQueryParam() && rQueryParam.bDestPers )
[ # # ][ # # ]
[ - + ]
697 : : {
698 [ # # ]: 0 : ScQueryParam aOldQuery;
699 [ # # ]: 0 : pDBData->GetQueryParam(aOldQuery);
700 [ # # ]: 0 : if (aOldQuery.bInplace)
701 : : {
702 : : // alte Filterung aufheben
703 : :
704 [ # # ]: 0 : SCSIZE nEC = aOldQuery.GetEntryCount();
705 [ # # ]: 0 : for (SCSIZE i=0; i<nEC; i++)
706 [ # # ]: 0 : aOldQuery.GetEntry(i).bDoQuery = false;
707 : 0 : aOldQuery.bDuplicate = sal_True;
708 [ # # ]: 0 : Query( nTab, aOldQuery, NULL, bRecord, bApi );
709 [ # # ]: 0 : }
710 : : }
711 : :
712 [ + - ]: 4 : ScQueryParam aLocalParam( rQueryParam ); // fuer Paint / Zielbereich
713 : 4 : sal_Bool bCopy = !rQueryParam.bInplace; // kopiert wird in Table::Query
714 : 4 : ScDBData* pDestData = NULL; // Bereich, in den kopiert wird
715 : 4 : sal_Bool bDoSize = false; // Zielgroesse anpassen (einf./loeschen)
716 : 4 : SCCOL nFormulaCols = 0; // nur bei bDoSize
717 : 4 : sal_Bool bKeepFmt = false;
718 : 4 : ScRange aOldDest;
719 : 4 : ScRange aDestTotal;
720 [ # # ][ # # ]: 4 : if ( bCopy && rQueryParam.nDestCol == rQueryParam.nCol1 &&
[ # # ][ - + ]
721 : : rQueryParam.nDestRow == rQueryParam.nRow1 && rQueryParam.nDestTab == nTab )
722 : 0 : bCopy = false;
723 : 4 : SCTAB nDestTab = nTab;
724 [ - + ]: 4 : if ( bCopy )
725 : : {
726 [ # # ]: 0 : aLocalParam.MoveToDest();
727 : 0 : nDestTab = rQueryParam.nDestTab;
728 [ # # ]: 0 : if ( !ValidColRow( aLocalParam.nCol2, aLocalParam.nRow2 ) )
729 : : {
730 [ # # ]: 0 : if (!bApi)
731 [ # # ]: 0 : rDocShell.ErrorMessage(STR_PASTE_FULL);
732 : 0 : return false;
733 : : }
734 : :
735 : : ScEditableTester aTester( pDoc, nDestTab, aLocalParam.nCol1,aLocalParam.nRow1,
736 [ # # ]: 0 : aLocalParam.nCol2,aLocalParam.nRow2);
737 [ # # ]: 0 : if (!aTester.IsEditable())
738 : : {
739 [ # # ]: 0 : if (!bApi)
740 [ # # ][ # # ]: 0 : rDocShell.ErrorMessage(aTester.GetMessageId());
741 : 0 : return false;
742 : : }
743 : :
744 : : pDestData = pDoc->GetDBAtCursor( rQueryParam.nDestCol, rQueryParam.nDestRow,
745 [ # # ]: 0 : rQueryParam.nDestTab, sal_True );
746 [ # # ]: 0 : if (pDestData)
747 : : {
748 [ # # ]: 0 : pDestData->GetArea( aOldDest );
749 : : aDestTotal=ScRange( rQueryParam.nDestCol,
750 : : rQueryParam.nDestRow,
751 : : nDestTab,
752 : : rQueryParam.nDestCol + rQueryParam.nCol2 - rQueryParam.nCol1,
753 : : rQueryParam.nDestRow + rQueryParam.nRow2 - rQueryParam.nRow1,
754 : 0 : nDestTab );
755 : :
756 : 0 : bDoSize = pDestData->IsDoSize();
757 : : // Test, ob Formeln aufgefuellt werden muessen (nFormulaCols):
758 [ # # ][ # # ]: 0 : if ( bDoSize && aOldDest.aEnd.Col() == aDestTotal.aEnd.Col() )
[ # # ]
759 : : {
760 : 0 : SCCOL nTestCol = aOldDest.aEnd.Col() + 1; // neben dem Bereich
761 : : SCROW nTestRow = rQueryParam.nDestRow +
762 [ # # ]: 0 : ( aLocalParam.bHasHeader ? 1 : 0 );
763 [ # # ][ # # ]: 0 : while ( nTestCol <= MAXCOL &&
[ # # ]
764 [ # # ][ # # ]: 0 : pDoc->GetCellType(ScAddress( nTestCol, nTestRow, nTab )) == CELLTYPE_FORMULA )
[ # # ]
765 : 0 : ++nTestCol, ++nFormulaCols;
766 : : }
767 : :
768 : 0 : bKeepFmt = pDestData->IsKeepFmt();
769 [ # # ][ # # ]: 0 : if ( bDoSize && !pDoc->CanFitBlock( aOldDest, aDestTotal ) )
[ # # ][ # # ]
770 : : {
771 [ # # ]: 0 : if (!bApi)
772 [ # # ]: 0 : rDocShell.ErrorMessage(STR_MSSG_DOSUBTOTALS_2); // kann keine Zeilen einfuegen
773 : 0 : return false;
774 : : }
775 [ # # ]: 0 : }
776 : : }
777 : :
778 : : // ausfuehren
779 : :
780 [ + - ][ + - ]: 4 : WaitObject aWait( rDocShell.GetActiveDialogParent() );
781 : :
782 : 4 : sal_Bool bKeepSub = false; // bestehende Teilergebnisse wiederholen?
783 [ + - ]: 4 : ScSubTotalParam aSubTotalParam;
784 [ + - ][ + - ]: 4 : if (rQueryParam.GetEntry(0).bDoQuery) // nicht beim Aufheben
785 : : {
786 [ + - ]: 4 : pDBData->GetSubTotalParam( aSubTotalParam ); // Teilergebnisse vorhanden?
787 : :
788 [ - + ][ # # ]: 4 : if ( aSubTotalParam.bGroupActive[0] && !aSubTotalParam.bRemoveOnly )
789 : 0 : bKeepSub = sal_True;
790 : : }
791 : :
792 : 4 : ScDocument* pUndoDoc = NULL;
793 : 4 : ScDBCollection* pUndoDB = NULL;
794 : 4 : const ScRange* pOld = NULL;
795 : :
796 [ + + ]: 4 : if ( bRecord )
797 : : {
798 [ + - ][ + - ]: 2 : pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
799 [ - + ]: 2 : if (bCopy)
800 : : {
801 [ # # ]: 0 : pUndoDoc->InitUndo( pDoc, nDestTab, nDestTab, false, sal_True );
802 : : pDoc->CopyToDocument( aLocalParam.nCol1, aLocalParam.nRow1, nDestTab,
803 : : aLocalParam.nCol2, aLocalParam.nRow2, nDestTab,
804 [ # # ]: 0 : IDF_ALL, false, pUndoDoc );
805 : : // Attribute sichern, falls beim Filtern mitkopiert
806 : :
807 [ # # ]: 0 : if (pDestData)
808 : : {
809 [ # # ]: 0 : pDoc->CopyToDocument( aOldDest, IDF_ALL, false, pUndoDoc );
810 : 0 : pOld = &aOldDest;
811 : : }
812 : : }
813 : : else
814 : : {
815 [ + - ]: 2 : pUndoDoc->InitUndo( pDoc, nTab, nTab, false, sal_True );
816 : : pDoc->CopyToDocument( 0, rQueryParam.nRow1, nTab, MAXCOL, rQueryParam.nRow2, nTab,
817 [ + - ]: 2 : IDF_NONE, false, pUndoDoc );
818 : : }
819 : :
820 [ + - ]: 2 : ScDBCollection* pDocDB = pDoc->GetDBCollection();
821 [ + - ][ - + ]: 2 : if (!pDocDB->empty())
822 [ # # ][ # # ]: 0 : pUndoDB = new ScDBCollection( *pDocDB );
823 : :
824 [ + - ]: 2 : pDoc->BeginDrawUndo();
825 : : }
826 : :
827 : 4 : ScDocument* pAttribDoc = NULL;
828 : 4 : ScRange aAttribRange;
829 [ - + ]: 4 : if (pDestData) // Zielbereich loeschen
830 : : {
831 [ # # ]: 0 : if ( bKeepFmt )
832 : : {
833 : : // kleinere der End-Spalten, Header+1 Zeile
834 : 0 : aAttribRange = aOldDest;
835 [ # # ]: 0 : if ( aAttribRange.aEnd.Col() > aDestTotal.aEnd.Col() )
836 : 0 : aAttribRange.aEnd.SetCol( aDestTotal.aEnd.Col() );
837 : 0 : aAttribRange.aEnd.SetRow( aAttribRange.aStart.Row() +
838 [ # # ]: 0 : ( aLocalParam.bHasHeader ? 1 : 0 ) );
839 : :
840 : : // auch fuer aufgefuellte Formeln
841 : 0 : aAttribRange.aEnd.SetCol( aAttribRange.aEnd.Col() + nFormulaCols );
842 : :
843 [ # # ][ # # ]: 0 : pAttribDoc = new ScDocument( SCDOCMODE_UNDO );
844 [ # # ]: 0 : pAttribDoc->InitUndo( pDoc, nDestTab, nDestTab, false, sal_True );
845 [ # # ]: 0 : pDoc->CopyToDocument( aAttribRange, IDF_ATTRIB, false, pAttribDoc );
846 : : }
847 : :
848 [ # # ]: 0 : if ( bDoSize )
849 [ # # ]: 0 : pDoc->FitBlock( aOldDest, aDestTotal );
850 : : else
851 [ # # ]: 0 : pDoc->DeleteAreaTab(aOldDest, IDF_ALL); // einfach loeschen
852 : : }
853 : :
854 : : // Filtern am Dokument ausfuehren
855 [ + - ]: 4 : SCSIZE nCount = pDoc->Query( nTab, rQueryParam, bKeepSub );
856 [ - + ]: 4 : if (bCopy)
857 : : {
858 : 0 : aLocalParam.nRow2 = aLocalParam.nRow1 + nCount;
859 [ # # ][ # # ]: 0 : if (!aLocalParam.bHasHeader && nCount > 0)
860 : 0 : --aLocalParam.nRow2;
861 : :
862 [ # # ]: 0 : if ( bDoSize )
863 : : {
864 : : // auf wirklichen Ergebnis-Bereich anpassen
865 : : // (das hier ist immer eine Verkleinerung)
866 : :
867 : : ScRange aNewDest( aLocalParam.nCol1, aLocalParam.nRow1, nDestTab,
868 : 0 : aLocalParam.nCol2, aLocalParam.nRow2, nDestTab );
869 [ # # ]: 0 : pDoc->FitBlock( aDestTotal, aNewDest, false ); // sal_False - nicht loeschen
870 : :
871 [ # # ]: 0 : if ( nFormulaCols > 0 )
872 : : {
873 : : // Formeln ausfuellen
874 : : //! Undo (Query und Repeat) !!!
875 : :
876 : : ScRange aNewForm( aLocalParam.nCol2+1, aLocalParam.nRow1, nDestTab,
877 : 0 : aLocalParam.nCol2+nFormulaCols, aLocalParam.nRow2, nDestTab );
878 : 0 : ScRange aOldForm = aNewForm;
879 : 0 : aOldForm.aEnd.SetRow( aOldDest.aEnd.Row() );
880 [ # # ]: 0 : pDoc->FitBlock( aOldForm, aNewForm, false );
881 : :
882 [ # # ]: 0 : ScMarkData aMark;
883 [ # # ]: 0 : aMark.SelectOneTable(nDestTab);
884 [ # # ]: 0 : SCROW nFStartY = aLocalParam.nRow1 + ( aLocalParam.bHasHeader ? 1 : 0 );
885 : :
886 : 0 : sal_uLong nProgCount = nFormulaCols;
887 : 0 : nProgCount *= aLocalParam.nRow2 - nFStartY;
888 : : ScProgress aProgress( pDoc->GetDocumentShell(),
889 [ # # ][ # # ]: 0 : ScGlobal::GetRscString(STR_FILL_SERIES_PROGRESS), nProgCount );
890 : :
891 : : pDoc->Fill( aLocalParam.nCol2+1, nFStartY,
892 : : aLocalParam.nCol2+nFormulaCols, nFStartY, &aProgress, aMark,
893 : : aLocalParam.nRow2 - nFStartY,
894 [ # # ][ # # ]: 0 : FILL_TO_BOTTOM, FILL_SIMPLE );
[ # # ]
895 : : }
896 : : }
897 : :
898 [ # # ]: 0 : if ( pAttribDoc ) // gemerkte Attribute zurueckkopieren
899 : : {
900 : : // Header
901 [ # # ]: 0 : if (aLocalParam.bHasHeader)
902 : : {
903 : 0 : ScRange aHdrRange = aAttribRange;
904 : 0 : aHdrRange.aEnd.SetRow( aHdrRange.aStart.Row() );
905 [ # # ]: 0 : pAttribDoc->CopyToDocument( aHdrRange, IDF_ATTRIB, false, pDoc );
906 : : }
907 : :
908 : : // Daten
909 : 0 : SCCOL nAttrEndCol = aAttribRange.aEnd.Col();
910 [ # # ]: 0 : SCROW nAttrRow = aAttribRange.aStart.Row() + ( aLocalParam.bHasHeader ? 1 : 0 );
911 [ # # ]: 0 : for (SCCOL nCol = aAttribRange.aStart.Col(); nCol<=nAttrEndCol; nCol++)
912 : : {
913 : : const ScPatternAttr* pSrcPattern = pAttribDoc->GetPattern(
914 [ # # ]: 0 : nCol, nAttrRow, nDestTab );
915 : : OSL_ENSURE(pSrcPattern,"Pattern ist 0");
916 [ # # ]: 0 : if (pSrcPattern)
917 : : {
918 : : pDoc->ApplyPatternAreaTab( nCol, nAttrRow, nCol, aLocalParam.nRow2,
919 [ # # ]: 0 : nDestTab, *pSrcPattern );
920 : 0 : const ScStyleSheet* pStyle = pSrcPattern->GetStyleSheet();
921 [ # # ]: 0 : if (pStyle)
922 : : pDoc->ApplyStyleAreaTab( nCol, nAttrRow, nCol, aLocalParam.nRow2,
923 [ # # ]: 0 : nDestTab, *pStyle );
924 : : }
925 : : }
926 : :
927 [ # # ][ # # ]: 0 : delete pAttribDoc;
928 : : }
929 : : }
930 : :
931 : : // speichern: Inplace immer, sonst je nach Einstellung
932 : : // alter Inplace-Filter ist ggf. schon aufgehoben
933 : :
934 [ - + ][ # # ]: 4 : sal_Bool bSave = rQueryParam.bInplace || rQueryParam.bDestPers;
935 [ + - ]: 4 : if (bSave) // merken
936 : : {
937 [ + - ]: 4 : pDBData->SetQueryParam( rQueryParam );
938 : 4 : pDBData->SetHeader( rQueryParam.bHasHeader ); //! ???
939 [ + - ]: 4 : pDBData->SetAdvancedQuerySource( pAdvSource ); // after SetQueryParam
940 : : }
941 : :
942 [ - + ]: 4 : if (bCopy) // neuen DB-Bereich merken
943 : : {
944 : : // selektieren wird hinterher von aussen (dbfunc)
945 : : // momentan ueber DB-Bereich an der Zielposition, darum muss dort
946 : : // auf jeden Fall ein Bereich angelegt werden.
947 : :
948 : : ScDBData* pNewData;
949 [ # # ]: 0 : if (pDestData)
950 : 0 : pNewData = pDestData; // Bereich vorhanden -> anpassen (immer!)
951 : : else // Bereich anlegen
952 : : pNewData = rDocShell.GetDBData(
953 : : ScRange( aLocalParam.nCol1, aLocalParam.nRow1, nDestTab,
954 : : aLocalParam.nCol2, aLocalParam.nRow2, nDestTab ),
955 [ # # ]: 0 : SC_DB_MAKE, SC_DBSEL_FORCE_MARK );
956 : :
957 [ # # ]: 0 : if (pNewData)
958 : : {
959 : : pNewData->SetArea( nDestTab, aLocalParam.nCol1, aLocalParam.nRow1,
960 [ # # ]: 0 : aLocalParam.nCol2, aLocalParam.nRow2 );
961 : :
962 : : // Query-Param wird am Ziel nicht mehr eingestellt, fuehrt nur zu Verwirrung
963 : : // und Verwechslung mit dem Query-Param am Quellbereich (#37187#)
964 : : }
965 : : else
966 : : {
967 : : OSL_FAIL("Zielbereich nicht da");
968 : : }
969 : : }
970 : :
971 [ + - ]: 4 : if (!bCopy)
972 : : {
973 [ + - ]: 4 : pDoc->InvalidatePageBreaks(nTab);
974 [ + - ]: 4 : pDoc->UpdatePageBreaks( nTab );
975 : : }
976 : :
977 : : // #i23299# Subtotal functions depend on cell's filtered states.
978 : 4 : ScRange aDirtyRange(0 , aLocalParam.nRow1, nDestTab, MAXCOL, aLocalParam.nRow2, nDestTab);
979 [ + - ]: 4 : pDoc->SetSubTotalCellsDirty(aDirtyRange);
980 : :
981 [ + + ]: 4 : if ( bRecord )
982 : : {
983 : : // create undo action after executing, because of drawing layer undo
984 [ + - ]: 2 : rDocShell.GetUndoManager()->AddUndoAction(
985 : : new ScUndoQuery( &rDocShell, nTab, rQueryParam, pUndoDoc, pUndoDB,
986 [ + - ][ + - ]: 2 : pOld, bDoSize, pAdvSource ) );
[ + - ]
987 : : }
988 : :
989 : :
990 [ - + ]: 4 : if (bCopy)
991 : : {
992 : 0 : SCCOL nEndX = aLocalParam.nCol2;
993 : 0 : SCROW nEndY = aLocalParam.nRow2;
994 [ # # ]: 0 : if (pDestData)
995 : : {
996 [ # # ]: 0 : if ( aOldDest.aEnd.Col() > nEndX )
997 : 0 : nEndX = aOldDest.aEnd.Col();
998 [ # # ]: 0 : if ( aOldDest.aEnd.Row() > nEndY )
999 : 0 : nEndY = aOldDest.aEnd.Row();
1000 : : }
1001 [ # # ]: 0 : if (bDoSize)
1002 : 0 : nEndY = MAXROW;
1003 : : rDocShell.PostPaint(
1004 : : ScRange(aLocalParam.nCol1, aLocalParam.nRow1, nDestTab, nEndX, nEndY, nDestTab),
1005 [ # # ][ # # ]: 0 : PAINT_GRID);
[ # # ]
1006 : : }
1007 : : else
1008 : : rDocShell.PostPaint(
1009 : : ScRange(0, rQueryParam.nRow1, nTab, MAXCOL, MAXROW, nTab),
1010 [ + - ][ + - ]: 4 : PAINT_GRID | PAINT_LEFT);
[ + - ]
1011 [ + - ]: 4 : aModificator.SetDocumentModified();
1012 : :
1013 [ + - ][ + - ]: 4 : return sal_True;
[ + - ]
1014 : : }
1015 : :
1016 : : // -----------------------------------------------------------------
1017 : :
1018 : 4 : sal_Bool ScDBDocFunc::DoSubTotals( SCTAB nTab, const ScSubTotalParam& rParam,
1019 : : const ScSortParam* pForceNewSort, sal_Bool bRecord, sal_Bool bApi )
1020 : : {
1021 : : //! auch fuer ScDBFunc::DoSubTotals benutzen!
1022 : : // dann bleibt aussen:
1023 : : // - neuen Bereich (aus DBData) markieren
1024 : : // - SelectionChanged (?)
1025 : :
1026 : 4 : sal_Bool bDo = !rParam.bRemoveOnly; // sal_False = nur loeschen
1027 : 4 : sal_Bool bRet = false;
1028 : :
1029 : 4 : ScDocument* pDoc = rDocShell.GetDocument();
1030 [ - + ][ - + ]: 4 : if (bRecord && !pDoc->IsUndoEnabled())
[ + - ]
1031 : 0 : bRecord = false;
1032 : : ScDBData* pDBData = pDoc->GetDBAtArea( nTab, rParam.nCol1, rParam.nRow1,
1033 [ + - ]: 4 : rParam.nCol2, rParam.nRow2 );
1034 [ - + ]: 4 : if (!pDBData)
1035 : : {
1036 : : OSL_FAIL( "SubTotals: keine DBData" );
1037 : 0 : return false;
1038 : : }
1039 : :
1040 [ + - ]: 4 : ScEditableTester aTester( pDoc, nTab, 0,rParam.nRow1+1, MAXCOL,MAXROW );
1041 [ - + ]: 4 : if (!aTester.IsEditable())
1042 : : {
1043 [ # # ]: 0 : if (!bApi)
1044 [ # # ][ # # ]: 0 : rDocShell.ErrorMessage(aTester.GetMessageId());
1045 : 0 : return false;
1046 : : }
1047 : :
1048 [ + - ][ - + ]: 4 : if (pDoc->HasAttrib( rParam.nCol1, rParam.nRow1+1, nTab,
1049 : 4 : rParam.nCol2, rParam.nRow2, nTab, HASATTR_MERGED | HASATTR_OVERLAPPED ))
1050 : : {
1051 [ # # ]: 0 : if (!bApi)
1052 [ # # ]: 0 : rDocShell.ErrorMessage(STR_MSSG_INSERTCELLS_0); // nicht in zusammengefasste einfuegen
1053 : 0 : return false;
1054 : : }
1055 : :
1056 : 4 : sal_Bool bOk = true;
1057 [ + - ]: 4 : if (rParam.bReplace)
1058 [ + - ][ - + ]: 4 : if (pDoc->TestRemoveSubTotals( nTab, rParam ))
1059 : : {
1060 : : bOk = ( MessBox( rDocShell.GetActiveDialogParent(), WinBits(WB_YES_NO | WB_DEF_YES),
1061 : : // "StarCalc" "Daten loeschen?"
1062 [ # # ]: 0 : ScGlobal::GetRscString( STR_MSSG_DOSUBTOTALS_0 ),
1063 [ # # ][ # # ]: 0 : ScGlobal::GetRscString( STR_MSSG_DOSUBTOTALS_1 ) ).Execute()
[ # # ][ # # ]
[ # # ]
1064 : 0 : == RET_YES );
1065 : : }
1066 : :
1067 [ + - ]: 4 : if (bOk)
1068 : : {
1069 [ + - ][ + - ]: 4 : WaitObject aWait( rDocShell.GetActiveDialogParent() );
1070 [ + - ]: 4 : ScDocShellModificator aModificator( rDocShell );
1071 : :
1072 [ + - ]: 4 : ScSubTotalParam aNewParam( rParam ); // Bereichsende wird veraendert
1073 : 4 : ScDocument* pUndoDoc = NULL;
1074 : 4 : ScOutlineTable* pUndoTab = NULL;
1075 : 4 : ScRangeName* pUndoRange = NULL;
1076 : 4 : ScDBCollection* pUndoDB = NULL;
1077 : :
1078 [ + - ]: 4 : if (bRecord) // alte Daten sichern
1079 : : {
1080 [ + + ][ + - ]: 4 : sal_Bool bOldFilter = bDo && rParam.bDoSort;
1081 : :
1082 [ + - ]: 4 : SCTAB nTabCount = pDoc->GetTableCount();
1083 [ + - ][ + - ]: 4 : pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
1084 [ + - ]: 4 : ScOutlineTable* pTable = pDoc->GetOutlineTable( nTab );
1085 [ + + ]: 4 : if (pTable)
1086 : : {
1087 [ + - ][ + - ]: 2 : pUndoTab = new ScOutlineTable( *pTable );
1088 : :
1089 : : // column/row state
1090 : : SCCOLROW nOutStartCol, nOutEndCol;
1091 : : SCCOLROW nOutStartRow, nOutEndRow;
1092 [ + - ]: 2 : pTable->GetColArray()->GetRange( nOutStartCol, nOutEndCol );
1093 [ + - ]: 2 : pTable->GetRowArray()->GetRange( nOutStartRow, nOutEndRow );
1094 : :
1095 [ + - ]: 2 : pUndoDoc->InitUndo( pDoc, nTab, nTab, sal_True, sal_True );
1096 [ + - ]: 2 : pDoc->CopyToDocument( static_cast<SCCOL>(nOutStartCol), 0, nTab, static_cast<SCCOL>(nOutEndCol), MAXROW, nTab, IDF_NONE, false, pUndoDoc );
1097 [ + - ]: 2 : pDoc->CopyToDocument( 0, nOutStartRow, nTab, MAXCOL, nOutEndRow, nTab, IDF_NONE, false, pUndoDoc );
1098 : : }
1099 : : else
1100 [ + - ]: 2 : pUndoDoc->InitUndo( pDoc, nTab, nTab, false, bOldFilter );
1101 : :
1102 : : // Datenbereich sichern - incl. Filter-Ergebnis
1103 : : pDoc->CopyToDocument( 0,rParam.nRow1+1,nTab, MAXCOL,rParam.nRow2,nTab,
1104 [ + - ]: 4 : IDF_ALL, false, pUndoDoc );
1105 : :
1106 : : // alle Formeln wegen Referenzen
1107 : : pDoc->CopyToDocument( 0,0,0, MAXCOL,MAXROW,nTabCount-1,
1108 [ + - ]: 4 : IDF_FORMULA, false, pUndoDoc );
1109 : :
1110 : : // DB- und andere Bereiche
1111 [ + - ]: 4 : ScRangeName* pDocRange = pDoc->GetRangeName();
1112 [ + - ][ - + ]: 4 : if (!pDocRange->empty())
1113 [ # # ][ # # ]: 0 : pUndoRange = new ScRangeName( *pDocRange );
1114 [ + - ]: 4 : ScDBCollection* pDocDB = pDoc->GetDBCollection();
1115 [ + - ][ - + ]: 4 : if (!pDocDB->empty())
1116 [ # # ][ # # ]: 0 : pUndoDB = new ScDBCollection( *pDocDB );
1117 : : }
1118 : :
1119 : : // pDoc->SetOutlineTable( nTab, NULL );
1120 [ + - ]: 4 : ScOutlineTable* pOut = pDoc->GetOutlineTable( nTab );
1121 [ + + ]: 4 : if (pOut)
1122 [ + - ]: 2 : pOut->GetRowArray()->RemoveAll(); // nur Zeilen-Outlines loeschen
1123 : :
1124 [ + - ]: 4 : if (rParam.bReplace)
1125 [ + - ]: 4 : pDoc->RemoveSubTotals( nTab, aNewParam );
1126 : 4 : sal_Bool bSuccess = sal_True;
1127 [ + + ]: 4 : if (bDo)
1128 : : {
1129 : : // Sortieren
1130 [ - + ][ # # ]: 2 : if ( rParam.bDoSort || pForceNewSort )
1131 : : {
1132 [ + - ]: 2 : pDBData->SetArea( nTab, aNewParam.nCol1,aNewParam.nRow1, aNewParam.nCol2,aNewParam.nRow2 );
1133 : :
1134 : : // Teilergebnis-Felder vor die Sortierung setzen
1135 : : // (doppelte werden weggelassen, kann darum auch wieder aufgerufen werden)
1136 : :
1137 [ + - ]: 2 : ScSortParam aOldSort;
1138 [ + - ]: 2 : pDBData->GetSortParam( aOldSort );
1139 [ + - ][ + - ]: 2 : ScSortParam aSortParam( aNewParam, pForceNewSort ? *pForceNewSort : aOldSort );
1140 [ + - ][ + - ]: 2 : Sort( nTab, aSortParam, false, false, bApi );
[ + - ]
1141 : : }
1142 : :
1143 [ + - ]: 2 : pDoc->InitializeNoteCaptions(nTab);
1144 [ + - ]: 2 : bSuccess = pDoc->DoSubTotals( nTab, aNewParam );
1145 [ + - ]: 2 : pDoc->SetDrawPageSize(nTab);
1146 : : }
1147 : : ScRange aDirtyRange( aNewParam.nCol1, aNewParam.nRow1, nTab,
1148 : 4 : aNewParam.nCol2, aNewParam.nRow2, nTab );
1149 [ + - ]: 4 : pDoc->SetDirty( aDirtyRange );
1150 : :
1151 [ + - ]: 4 : if (bRecord)
1152 : : {
1153 : : // ScDBData* pUndoDBData = pDBData ? new ScDBData( *pDBData ) : NULL;
1154 [ + - ]: 4 : rDocShell.GetUndoManager()->AddUndoAction(
1155 : : new ScUndoSubTotals( &rDocShell, nTab,
1156 : : rParam, aNewParam.nRow2,
1157 : : pUndoDoc, pUndoTab, // pUndoDBData,
1158 [ + - ][ + - ]: 4 : pUndoRange, pUndoDB ) );
[ + - ]
1159 : : }
1160 : :
1161 [ - + ]: 4 : if (!bSuccess)
1162 : : {
1163 : : // "Kann keine Zeilen einfuegen"
1164 [ # # ]: 0 : if (!bApi)
1165 [ # # ]: 0 : rDocShell.ErrorMessage(STR_MSSG_DOSUBTOTALS_2);
1166 : : }
1167 : :
1168 : : // merken
1169 [ + - ]: 4 : pDBData->SetSubTotalParam( aNewParam );
1170 [ + - ]: 4 : pDBData->SetArea( nTab, aNewParam.nCol1,aNewParam.nRow1, aNewParam.nCol2,aNewParam.nRow2 );
1171 [ + - ]: 4 : pDoc->CompileDBFormula();
1172 : :
1173 : : rDocShell.PostPaint(ScRange(0, 0, nTab, MAXCOL,MAXROW,nTab),
1174 [ + - ][ + - ]: 4 : PAINT_GRID | PAINT_LEFT | PAINT_TOP | PAINT_SIZE);
[ + - ]
1175 [ + - ]: 4 : aModificator.SetDocumentModified();
1176 : :
1177 [ + - ][ + - ]: 4 : bRet = bSuccess;
1178 : : }
1179 : 4 : return bRet;
1180 : : }
1181 : :
1182 : : //==================================================================
1183 : :
1184 : 5 : sal_Bool lcl_EmptyExcept( ScDocument* pDoc, const ScRange& rRange, const ScRange& rExcept )
1185 : : {
1186 [ + - ]: 5 : ScCellIterator aIter( pDoc, rRange );
1187 [ + - ]: 5 : ScBaseCell* pCell = aIter.GetFirst();
1188 [ + + ]: 163 : while (pCell)
1189 : : {
1190 [ + - ][ + - ]: 158 : if ( !pCell->IsBlank() ) // real content?
1191 : : {
1192 [ - + ]: 158 : if ( !rExcept.In( ScAddress( aIter.GetCol(), aIter.GetRow(), aIter.GetTab() ) ) )
1193 : 0 : return false; // cell found
1194 : : }
1195 [ + - ]: 158 : pCell = aIter.GetNext();
1196 : : }
1197 : :
1198 : 5 : return sal_True; // nothing found - empty
1199 : : }
1200 : :
1201 : 75 : bool ScDBDocFunc::DataPilotUpdate( ScDPObject* pOldObj, const ScDPObject* pNewObj,
1202 : : bool bRecord, bool bApi, bool bAllowMove )
1203 : : {
1204 [ + - ]: 75 : ScDocShellModificator aModificator( rDocShell );
1205 [ + - ][ + - ]: 75 : WaitObject aWait( rDocShell.GetActiveDialogParent() );
1206 : :
1207 : 75 : bool bDone = false;
1208 : 75 : bool bUndoSelf = false;
1209 : 75 : sal_uInt16 nErrId = 0;
1210 : :
1211 : 75 : ScDocument* pOldUndoDoc = NULL;
1212 : 75 : ScDocument* pNewUndoDoc = NULL;
1213 : 75 : ScDPObject* pUndoDPObj = NULL;
1214 [ + + ][ + + ]: 75 : if ( bRecord && pOldObj )
1215 [ + - ][ + - ]: 43 : pUndoDPObj = new ScDPObject( *pOldObj ); // copy old settings for undo
1216 : :
1217 : 75 : ScDocument* pDoc = rDocShell.GetDocument();
1218 [ - + ][ - + ]: 75 : if (bRecord && !pDoc->IsUndoEnabled())
[ + + ]
1219 : 0 : bRecord = false;
1220 [ + - ][ + - ]: 75 : if ( !rDocShell.IsEditable() || pDoc->GetChangeTrack() )
[ - + ][ - + ]
1221 : : {
1222 : : // not recorded -> disallow
1223 : : //! different error messages?
1224 : :
1225 : 0 : nErrId = STR_PROTECTIONERR;
1226 : : }
1227 [ + + ][ + - ]: 75 : if ( pOldObj && !nErrId )
1228 : : {
1229 : 56 : ScRange aOldOut = pOldObj->GetOutRange();
1230 [ + - ]: 56 : ScEditableTester aTester( pDoc, aOldOut );
1231 [ - + ]: 56 : if ( !aTester.IsEditable() )
1232 [ # # ]: 56 : nErrId = aTester.GetMessageId();
1233 : : }
1234 [ + + ][ + - ]: 75 : if ( pNewObj && !nErrId )
1235 : : {
1236 : : // at least one cell at the output position must be editable
1237 : : // -> check in advance
1238 : : // (start of output range in pNewObj is valid)
1239 : :
1240 : 74 : ScRange aNewStart( pNewObj->GetOutRange().aStart );
1241 [ + - ]: 74 : ScEditableTester aTester( pDoc, aNewStart );
1242 [ - + ]: 74 : if ( !aTester.IsEditable() )
1243 [ # # ]: 74 : nErrId = aTester.GetMessageId();
1244 : : }
1245 : :
1246 : 75 : ScDPObject* pDestObj = NULL;
1247 [ + - ]: 75 : if ( !nErrId )
1248 : : {
1249 [ + + ][ + + ]: 75 : if ( pOldObj && !pNewObj )
1250 : : {
1251 : : // delete table
1252 : :
1253 : 1 : ScRange aRange = pOldObj->GetOutRange();
1254 : 1 : SCTAB nTab = aRange.aStart.Tab();
1255 : :
1256 [ + - ]: 1 : if ( bRecord )
1257 : : {
1258 [ + - ][ + - ]: 1 : pOldUndoDoc = new ScDocument( SCDOCMODE_UNDO );
1259 [ + - ]: 1 : pOldUndoDoc->InitUndo( pDoc, nTab, nTab );
1260 [ + - ]: 1 : pDoc->CopyToDocument( aRange, IDF_ALL, false, pOldUndoDoc );
1261 : : }
1262 : :
1263 : 1 : pDoc->DeleteAreaTab( aRange.aStart.Col(), aRange.aStart.Row(),
1264 : 1 : aRange.aEnd.Col(), aRange.aEnd.Row(),
1265 [ + - ]: 3 : nTab, IDF_ALL );
1266 : 1 : pDoc->RemoveFlagsTab( aRange.aStart.Col(), aRange.aStart.Row(),
1267 : 1 : aRange.aEnd.Col(), aRange.aEnd.Row(),
1268 [ + - ]: 3 : nTab, SC_MF_AUTO );
1269 : :
1270 [ + - ][ + - ]: 1 : pDoc->GetDPCollection()->FreeTable( pOldObj ); // object is deleted here
1271 : :
1272 [ + - ]: 1 : rDocShell.PostPaintGridAll(); //! only necessary parts
1273 [ + - ][ + - ]: 1 : rDocShell.PostPaint(aRange, PAINT_GRID);
[ + - ]
1274 : 1 : bDone = true;
1275 : : }
1276 [ + - ]: 74 : else if ( pNewObj )
1277 : : {
1278 [ + + ]: 74 : if ( pOldObj )
1279 : : {
1280 [ + + ]: 55 : if ( bRecord )
1281 : : {
1282 : 42 : ScRange aRange = pOldObj->GetOutRange();
1283 : 42 : SCTAB nTab = aRange.aStart.Tab();
1284 [ + - ][ + - ]: 42 : pOldUndoDoc = new ScDocument( SCDOCMODE_UNDO );
1285 [ + - ]: 42 : pOldUndoDoc->InitUndo( pDoc, nTab, nTab );
1286 [ + - ]: 42 : pDoc->CopyToDocument( aRange, IDF_ALL, false, pOldUndoDoc );
1287 : : }
1288 : :
1289 [ - + ]: 55 : if ( pNewObj == pOldObj )
1290 : : {
1291 : : // refresh only - no settings modified
1292 : : }
1293 : : else
1294 : : {
1295 [ # # ]: 0 : pNewObj->WriteSourceDataTo( *pOldObj ); // copy source data
1296 : :
1297 : 0 : ScDPSaveData* pData = pNewObj->GetSaveData();
1298 : : OSL_ENSURE( pData, "no SaveData from living DPObject" );
1299 [ # # ]: 0 : if ( pData )
1300 [ # # ]: 0 : pOldObj->SetSaveData( *pData ); // copy SaveData
1301 : : }
1302 : :
1303 : 55 : pDestObj = pOldObj;
1304 [ + - ]: 55 : pDestObj->SetAllowMove( bAllowMove );
1305 : : }
1306 : : else
1307 : : {
1308 : : // output range must be set at pNewObj
1309 : :
1310 [ + - ][ + - ]: 19 : pDestObj = new ScDPObject( *pNewObj );
1311 : :
1312 : : // #i94570# When changing the output position in the dialog, a new table is created
1313 : : // with the settings from the old table, including the name.
1314 : : // So we have to check for duplicate names here (before inserting).
1315 [ + - ][ + - ]: 19 : if ( pDoc->GetDPCollection()->GetByName(pDestObj->GetName()) )
[ - + ]
1316 [ # # ][ # # ]: 0 : pDestObj->SetName( String() ); // ignore the invalid name, create a new name below
[ # # ][ # # ]
1317 : :
1318 [ + - ]: 19 : pDestObj->SetAlive(sal_True);
1319 [ + - ][ + - ]: 19 : if ( !pDoc->GetDPCollection()->InsertNewTable(pDestObj) )
[ - + ]
1320 : : {
1321 : : OSL_FAIL("cannot insert DPObject");
1322 [ # # ][ # # ]: 0 : DELETEZ( pDestObj );
1323 : : }
1324 : : }
1325 [ + - ]: 74 : if ( pDestObj )
1326 : : {
1327 [ + - ]: 74 : pDestObj->ReloadGroupTableData();
1328 [ + - ]: 74 : pDestObj->InvalidateData(); // before getting the new output area
1329 : :
1330 : : // make sure the table has a name (not set by dialog)
1331 [ - + ]: 74 : if (pDestObj->GetName().isEmpty())
1332 [ # # ][ # # ]: 0 : pDestObj->SetName( pDoc->GetDPCollection()->CreateNewName() );
[ # # ]
1333 : :
1334 : 74 : bool bOverflow = false;
1335 [ + - ]: 74 : ScRange aNewOut = pDestObj->GetNewOutputRange( bOverflow );
1336 : :
1337 : : //! test for overlap with other data pilot tables
1338 [ + + ]: 74 : if( pOldObj )
1339 : : {
1340 : 55 : const ScSheetSourceDesc* pSheetDesc = pOldObj->GetSheetDesc();
1341 [ + - ][ + - ]: 55 : if( pSheetDesc && pSheetDesc->GetSourceRange().Intersects( aNewOut ) )
[ - + ][ - + ]
[ + - ]
1342 : : {
1343 : 0 : ScRange aOldRange = pOldObj->GetOutRange();
1344 : 0 : SCsROW nDiff = aOldRange.aStart.Row()-aNewOut.aStart.Row();
1345 : 0 : aNewOut.aStart.SetRow( aOldRange.aStart.Row() );
1346 : 0 : aNewOut.aEnd.SetRow( aNewOut.aEnd.Row()+nDiff );
1347 [ # # ][ # # ]: 0 : if( !ValidRow( aNewOut.aStart.Row() ) || !ValidRow( aNewOut.aEnd.Row() ) )
[ # # ]
1348 : 0 : bOverflow = sal_True;
1349 : : }
1350 : : }
1351 : :
1352 [ - + ]: 74 : if ( bOverflow )
1353 : : {
1354 : : // like with STR_PROTECTIONERR, use undo to reverse everything
1355 : : OSL_ENSURE( bRecord, "DataPilotUpdate: can't undo" );
1356 : 0 : bUndoSelf = true;
1357 : 0 : nErrId = STR_PIVOT_ERROR;
1358 : : }
1359 : : else
1360 : : {
1361 [ + - ]: 74 : ScEditableTester aTester( pDoc, aNewOut );
1362 [ - + ]: 74 : if ( !aTester.IsEditable() )
1363 : : {
1364 : : // destination area isn't editable
1365 : : //! reverse everything done so far, don't proceed
1366 : :
1367 : : // quick solution: proceed to end, use undo action
1368 : : // to reverse everything:
1369 : : OSL_ENSURE( bRecord, "DataPilotUpdate: can't undo" );
1370 : 0 : bUndoSelf = sal_True;
1371 [ # # ]: 0 : nErrId = aTester.GetMessageId();
1372 : 74 : }
1373 : : }
1374 : :
1375 : : // test if new output area is empty except for old area
1376 [ + + ]: 74 : if ( !bApi )
1377 : : {
1378 : : bool bEmpty;
1379 [ + - ]: 5 : if ( pOldObj ) // OutRange of pOldObj (pDestObj) is still old area
1380 [ + - ]: 5 : bEmpty = lcl_EmptyExcept( pDoc, aNewOut, pOldObj->GetOutRange() );
1381 : : else
1382 : 0 : bEmpty = pDoc->IsBlockEmpty( aNewOut.aStart.Tab(),
1383 : 0 : aNewOut.aStart.Col(), aNewOut.aStart.Row(),
1384 [ # # ]: 0 : aNewOut.aEnd.Col(), aNewOut.aEnd.Row() );
1385 : :
1386 [ - + ]: 5 : if ( !bEmpty )
1387 : : {
1388 : : QueryBox aBox( rDocShell.GetActiveDialogParent(), WinBits(WB_YES_NO | WB_DEF_YES),
1389 [ # # ][ # # ]: 0 : ScGlobal::GetRscString(STR_PIVOT_NOTEMPTY) );
[ # # ]
1390 [ # # ][ # # ]: 0 : if (aBox.Execute() == RET_NO)
1391 : : {
1392 : : //! like above (not editable), use undo to reverse everything
1393 : : OSL_ENSURE( bRecord, "DataPilotUpdate: can't undo" );
1394 : 0 : bUndoSelf = true;
1395 [ # # ]: 0 : }
1396 : : }
1397 : : }
1398 : :
1399 [ + + ]: 74 : if ( bRecord )
1400 : : {
1401 : 61 : SCTAB nTab = aNewOut.aStart.Tab();
1402 [ + - ][ + - ]: 61 : pNewUndoDoc = new ScDocument( SCDOCMODE_UNDO );
1403 [ + - ]: 61 : pNewUndoDoc->InitUndo( pDoc, nTab, nTab );
1404 [ + - ]: 61 : pDoc->CopyToDocument( aNewOut, IDF_ALL, false, pNewUndoDoc );
1405 : : }
1406 : :
1407 [ + - ]: 74 : pDestObj->Output( aNewOut.aStart );
1408 : :
1409 [ + - ]: 74 : rDocShell.PostPaintGridAll(); //! only necessary parts
1410 : 75 : bDone = true;
1411 : : }
1412 : : }
1413 : : // else nothing (no old, no new)
1414 : : }
1415 : :
1416 [ + + ][ + - ]: 75 : if ( bRecord && bDone )
1417 : : {
1418 : : SfxUndoAction* pAction = new ScUndoDataPilot( &rDocShell,
1419 [ + - ][ + - ]: 62 : pOldUndoDoc, pNewUndoDoc, pUndoDPObj, pDestObj, bAllowMove );
1420 : 62 : pOldUndoDoc = NULL;
1421 : 62 : pNewUndoDoc = NULL; // pointers are used in undo action
1422 : : // pUndoDPObj is copied
1423 : :
1424 [ - + ]: 62 : if (bUndoSelf)
1425 : : {
1426 : : // use undo action to restore original state
1427 : : //! prevent setting the document modified? (ScDocShellModificator)
1428 : :
1429 [ # # ]: 0 : pAction->Undo();
1430 [ # # ][ # # ]: 0 : delete pAction;
1431 : 0 : bDone = false;
1432 : : }
1433 : : else
1434 [ + - ][ + - ]: 62 : rDocShell.GetUndoManager()->AddUndoAction( pAction );
1435 : : }
1436 : :
1437 [ - + ][ # # ]: 75 : delete pOldUndoDoc; // if not used for undo
1438 [ - + ][ # # ]: 75 : delete pNewUndoDoc;
1439 [ + + ][ + - ]: 75 : delete pUndoDPObj;
1440 : :
1441 [ + - ]: 75 : if (bDone)
1442 : : {
1443 : : // notify API objects
1444 [ + + ]: 75 : if (pDestObj)
1445 [ + - ][ + - ]: 74 : pDoc->BroadcastUno( ScDataPilotModifiedHint( pDestObj->GetName() ) );
[ + - ][ + - ]
[ + - ]
1446 [ + - ]: 75 : aModificator.SetDocumentModified();
1447 : : }
1448 : :
1449 [ - + ][ # # ]: 75 : if ( nErrId && !bApi )
1450 [ # # ]: 0 : rDocShell.ErrorMessage( nErrId );
1451 : :
1452 [ + - ][ + - ]: 75 : return bDone;
1453 : : }
1454 : :
1455 : 4 : sal_uLong ScDBDocFunc::RefreshPivotTables(ScDPObject* pDPObj, bool bApi)
1456 : : {
1457 [ + - ]: 4 : ScDPCollection* pDPs = rDocShell.GetDocument()->GetDPCollection();
1458 [ - + ]: 4 : if (!pDPs)
1459 : 0 : return 0;
1460 : :
1461 [ + - ]: 4 : std::set<ScDPObject*> aRefs;
1462 [ + - ]: 4 : sal_uLong nErrId = pDPs->ReloadCache(pDPObj, aRefs);
1463 [ - + ]: 4 : if (nErrId)
1464 : 0 : return nErrId;
1465 : :
1466 : 4 : std::set<ScDPObject*>::iterator it = aRefs.begin(), itEnd = aRefs.end();
1467 [ + - ][ + - ]: 12 : for (; it != itEnd; ++it)
[ + + ]
1468 : : {
1469 [ + - ]: 8 : ScDPObject* pObj = *it;
1470 [ + - ]: 8 : pObj->SyncAllDimensionMembers();
1471 : :
1472 : : // This action is intentionally not undoable since it modifies cache.
1473 [ + - ]: 8 : DataPilotUpdate(pObj, pObj, false, bApi);
1474 : : }
1475 : :
1476 : 4 : return 0;
1477 : : }
1478 : :
1479 : 5 : void ScDBDocFunc::RefreshPivotTableGroups(ScDPObject* pDPObj)
1480 : : {
1481 [ + - ]: 5 : if (!pDPObj)
1482 : : return;
1483 : :
1484 [ + - ]: 5 : ScDPCollection* pDPs = rDocShell.GetDocument()->GetDPCollection();
1485 [ + - ]: 5 : if (!pDPs)
1486 : : return;
1487 : :
1488 : 5 : ScDPSaveData* pSaveData = pDPObj->GetSaveData();
1489 [ + - ]: 5 : if (!pSaveData)
1490 : : return;
1491 : :
1492 [ + - ]: 5 : std::set<ScDPObject*> aRefs;
1493 [ + - ][ - + ]: 5 : if (!pDPs->ReloadGroupsInCache(pDPObj, aRefs))
1494 : : return;
1495 : :
1496 : : // We allow pDimData being NULL.
1497 : 5 : const ScDPDimensionSaveData* pDimData = pSaveData->GetExistingDimensionData();
1498 : 5 : std::set<ScDPObject*>::iterator it = aRefs.begin(), itEnd = aRefs.end();
1499 [ + - ][ + - ]: 10 : for (; it != itEnd; ++it)
[ + + ]
1500 : : {
1501 [ + - ]: 5 : ScDPObject* pObj = *it;
1502 [ - + ]: 5 : if (pObj != pDPObj)
1503 : : {
1504 : 0 : pSaveData = pObj->GetSaveData();
1505 [ # # ]: 0 : if (pSaveData)
1506 [ # # ]: 0 : pSaveData->SetDimensionData(pDimData);
1507 : : }
1508 : :
1509 : : // This action is intentionally not undoable since it modifies cache.
1510 [ + - ]: 5 : DataPilotUpdate(pObj, pObj, false, false);
1511 [ + - ]: 5 : }
1512 : : }
1513 : :
1514 : : //==================================================================
1515 : : //
1516 : : // database import
1517 : :
1518 : 0 : void ScDBDocFunc::UpdateImport( const String& rTarget, const svx::ODataAccessDescriptor& rDescriptor )
1519 : : {
1520 : : // rTarget is the name of a database range
1521 : :
1522 : 0 : ScDocument* pDoc = rDocShell.GetDocument();
1523 [ # # ]: 0 : ScDBCollection& rDBColl = *pDoc->GetDBCollection();
1524 [ # # ][ # # ]: 0 : const ScDBData* pData = rDBColl.getNamedDBs().findByName(rTarget);
[ # # ]
1525 [ # # ]: 0 : if (!pData)
1526 : : {
1527 : : InfoBox aInfoBox(rDocShell.GetActiveDialogParent(),
1528 [ # # ][ # # ]: 0 : ScGlobal::GetRscString( STR_TARGETNOTFOUND ) );
[ # # ]
1529 [ # # ]: 0 : aInfoBox.Execute();
1530 [ # # ]: 0 : return;
1531 : : }
1532 : :
1533 : : SCTAB nTab;
1534 : : SCCOL nDummyCol;
1535 : : SCROW nDummyRow;
1536 [ # # ]: 0 : pData->GetArea( nTab, nDummyCol,nDummyRow,nDummyCol,nDummyRow );
1537 : :
1538 [ # # ]: 0 : ScImportParam aImportParam;
1539 [ # # ]: 0 : pData->GetImportParam( aImportParam );
1540 : :
1541 : 0 : rtl::OUString sDBName;
1542 : 0 : rtl::OUString sDBTable;
1543 : 0 : sal_Int32 nCommandType = 0;
1544 [ # # ]: 0 : rDescriptor[svx::daDataSource] >>= sDBName;
1545 [ # # ]: 0 : rDescriptor[svx::daCommand] >>= sDBTable;
1546 [ # # ]: 0 : rDescriptor[svx::daCommandType] >>= nCommandType;
1547 : :
1548 : 0 : aImportParam.aDBName = sDBName;
1549 : 0 : aImportParam.bSql = ( nCommandType == sdb::CommandType::COMMAND );
1550 : 0 : aImportParam.aStatement = sDBTable;
1551 : 0 : aImportParam.bNative = false;
1552 [ # # ]: 0 : aImportParam.nType = static_cast<sal_uInt8>( ( nCommandType == sdb::CommandType::QUERY ) ? ScDbQuery : ScDbTable );
1553 : 0 : aImportParam.bImport = true;
1554 : :
1555 [ # # ]: 0 : bool bContinue = DoImport( nTab, aImportParam, &rDescriptor, true );
1556 : :
1557 : : // DB-Operationen wiederholen
1558 : :
1559 [ # # ]: 0 : ScTabViewShell* pViewSh = rDocShell.GetBestViewShell();
1560 [ # # ]: 0 : if (pViewSh)
1561 : : {
1562 : 0 : ScRange aRange;
1563 [ # # ]: 0 : pData->GetArea(aRange);
1564 [ # # ]: 0 : pViewSh->MarkRange(aRange); // selektieren
1565 : :
1566 [ # # ]: 0 : if ( bContinue ) // Fehler beim Import -> Abbruch
1567 : : {
1568 : : // interne Operationen, wenn welche gespeichert
1569 : :
1570 [ # # ][ # # ]: 0 : if ( pData->HasQueryParam() || pData->HasSortParam() || pData->HasSubTotalParam() )
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1571 [ # # ]: 0 : pViewSh->RepeatDB();
1572 : :
1573 : : // Pivottabellen die den Bereich als Quelldaten haben
1574 : :
1575 [ # # ]: 0 : rDocShell.RefreshPivotTables(aRange);
1576 : : }
1577 [ # # ]: 0 : }
1578 [ + - ][ + - ]: 153 : }
1579 : :
1580 : :
1581 : :
1582 : :
1583 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|