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 "consoli.hxx"
30 : : #include "document.hxx"
31 : : #include "olinetab.hxx"
32 : : #include "globstr.hrc"
33 : : #include "subtotal.hxx"
34 : : #include "formula/errorcodes.hxx"
35 : : #include "cell.hxx"
36 : :
37 : : #include <math.h>
38 : : #include <string.h>
39 : :
40 : : #define SC_CONS_NOTFOUND -1
41 : :
42 : : // STATIC DATA -----------------------------------------------------------
43 : :
44 : : static OpCode eOpCodeTable[] = { // Reihenfolge wie bei enum ScSubTotalFunc
45 : : ocBad, // none
46 : : ocAverage,
47 : : ocCount,
48 : : ocCount2,
49 : : ocMax,
50 : : ocMin,
51 : : ocProduct,
52 : : ocStDev,
53 : : ocStDevP,
54 : : ocSum,
55 : : ocVar,
56 : : ocVarP };
57 : :
58 : : // -----------------------------------------------------------------------
59 : :
60 : 0 : void ScReferenceList::AddEntry( SCCOL nCol, SCROW nRow, SCTAB nTab )
61 : : {
62 : 0 : ScReferenceEntry* pOldData = pData;
63 : 0 : pData = new ScReferenceEntry[ nFullSize+1 ];
64 [ # # ]: 0 : if (pOldData)
65 : : {
66 : 0 : memmove( pData, pOldData, nCount * sizeof(ScReferenceEntry) );
67 [ # # ]: 0 : delete[] pOldData;
68 : : }
69 [ # # ]: 0 : while (nCount < nFullSize)
70 : : {
71 : 0 : pData[nCount].nCol = SC_CONS_NOTFOUND;
72 : 0 : pData[nCount].nRow = SC_CONS_NOTFOUND;
73 : 0 : pData[nCount].nTab = SC_CONS_NOTFOUND;
74 : 0 : ++nCount;
75 : : }
76 : 0 : pData[nCount].nCol = nCol;
77 : 0 : pData[nCount].nRow = nRow;
78 : 0 : pData[nCount].nTab = nTab;
79 : 0 : ++nCount;
80 : 0 : nFullSize = nCount;
81 : 0 : }
82 : :
83 : : template< typename T >
84 : 0 : void lcl_AddString( String**& pData, T& nCount, const String& rInsert )
85 : : {
86 : 0 : String** pOldData = pData;
87 : 0 : pData = new String*[ nCount+1 ];
88 [ # # ]: 0 : if (pOldData)
89 : : {
90 : 0 : memmove( pData, pOldData, nCount * sizeof(String*) );
91 [ # # ]: 0 : delete[] pOldData;
92 : : }
93 [ # # ]: 0 : pData[nCount] = new String(rInsert);
94 : 0 : ++nCount;
95 : 0 : }
96 : :
97 : : // -----------------------------------------------------------------------
98 : :
99 : 1 : ScConsData::ScConsData() :
100 : : eFunction(SUBTOTAL_FUNC_SUM),
101 : : bReference(false),
102 : : bColByName(false),
103 : : bRowByName(false),
104 : : bSubTitles(false),
105 : : nColCount(0),
106 : : nRowCount(0),
107 : : ppUsed(NULL),
108 : : ppSum(NULL),
109 : : ppCount(NULL),
110 : : ppSumSqr(NULL),
111 : : ppRefs(NULL),
112 : : ppColHeaders(NULL),
113 : : ppRowHeaders(NULL),
114 : : nDataCount(0),
115 : : nTitleCount(0),
116 : : ppTitles(NULL),
117 : : ppTitlePos(NULL),
118 : 1 : bCornerUsed(false)
119 : : {
120 : 1 : }
121 : :
122 : 1 : ScConsData::~ScConsData()
123 : : {
124 [ + - ]: 1 : DeleteData();
125 : 1 : }
126 : :
127 : :
128 : : #define DELETEARR(ppArray,nCount) \
129 : : { \
130 : : sal_uLong i; \
131 : : if (ppArray) \
132 : : for(i=0; i<nCount; i++) \
133 : : delete[] ppArray[i]; \
134 : : delete[] ppArray; \
135 : : ppArray = NULL; \
136 : : }
137 : :
138 : : #define DELETESTR(ppArray,nCount) \
139 : : { \
140 : : sal_uLong i; \
141 : : if (ppArray) \
142 : : for(i=0; i<nCount; i++) \
143 : : delete ppArray[i]; \
144 : : delete[] ppArray; \
145 : : ppArray = NULL; \
146 : : }
147 : :
148 : 3 : void ScConsData::DeleteData()
149 : : {
150 [ - + ]: 3 : if (ppRefs)
151 : : {
152 [ # # ]: 0 : for (SCSIZE i=0; i<nColCount; i++)
153 : : {
154 [ # # ]: 0 : for (SCSIZE j=0; j<nRowCount; j++)
155 [ # # ]: 0 : if (ppUsed[i][j])
156 : 0 : ppRefs[i][j].Clear();
157 [ # # ]: 0 : delete[] ppRefs[i];
158 : : }
159 [ # # ]: 0 : delete[] ppRefs;
160 : 0 : ppRefs = NULL;
161 : : }
162 : :
163 [ - + ][ # # ]: 3 : DELETEARR( ppCount, nColCount );
[ # # ][ - + ]
164 [ - + ][ # # ]: 3 : DELETEARR( ppSum, nColCount );
[ # # ][ - + ]
165 [ - + ][ # # ]: 3 : DELETEARR( ppSumSqr,nColCount );
[ # # ][ - + ]
166 [ - + ][ # # ]: 3 : DELETEARR( ppUsed, nColCount ); // erst nach ppRefs !!!
[ # # ][ - + ]
167 [ - + ][ # # ]: 3 : DELETEARR( ppTitlePos, nRowCount );
[ # # ][ - + ]
168 [ - + ][ # # ]: 3 : DELETESTR( ppColHeaders, nColCount );
[ # # ][ - + ]
169 [ - + ][ # # ]: 3 : DELETESTR( ppRowHeaders, nRowCount );
[ # # ][ - + ]
170 [ - + ][ # # ]: 3 : DELETESTR( ppTitles, nTitleCount );
[ # # ][ - + ]
171 : 3 : nTitleCount = 0;
172 : 3 : nDataCount = 0;
173 : :
174 [ - + ]: 3 : if (bColByName) nColCount = 0; // sonst stimmt ppColHeaders nicht
175 [ - + ]: 3 : if (bRowByName) nRowCount = 0;
176 : :
177 : 3 : bCornerUsed = false;
178 : 3 : aCornerText.Erase();
179 : 3 : }
180 : :
181 : : #undef DELETEARR
182 : : #undef DELETESTR
183 : :
184 : 1 : void ScConsData::InitData( sal_Bool bDelete )
185 : : {
186 [ - + ]: 1 : if (bDelete)
187 : 0 : DeleteData();
188 : :
189 [ - + ][ # # ]: 1 : if (bReference && nColCount && !ppRefs)
[ # # ]
190 : : {
191 : 0 : ppRefs = new ScReferenceList*[nColCount];
192 [ # # ]: 0 : for (SCSIZE i=0; i<nColCount; i++)
193 : 0 : ppRefs[i] = new ScReferenceList[nRowCount];
194 : : }
195 [ - + ][ # # ]: 1 : else if (nColCount && !ppCount)
196 : : {
197 : 0 : ppCount = new double*[nColCount];
198 : 0 : ppSum = new double*[nColCount];
199 : 0 : ppSumSqr = new double*[nColCount];
200 [ # # ]: 0 : for (SCSIZE i=0; i<nColCount; i++)
201 : : {
202 : 0 : ppCount[i] = new double[nRowCount];
203 : 0 : ppSum[i] = new double[nRowCount];
204 : 0 : ppSumSqr[i] = new double[nRowCount];
205 : : }
206 : : }
207 : :
208 [ - + ][ # # ]: 1 : if (nColCount && !ppUsed)
209 : : {
210 : 0 : ppUsed = new sal_Bool*[nColCount];
211 [ # # ]: 0 : for (SCSIZE i=0; i<nColCount; i++)
212 : : {
213 : 0 : ppUsed[i] = new sal_Bool[nRowCount];
214 : 0 : memset( ppUsed[i], 0, nRowCount * sizeof(sal_Bool) );
215 : : }
216 : : }
217 : :
218 [ - + ][ # # ]: 1 : if (nRowCount && nDataCount && !ppTitlePos)
[ # # ]
219 : : {
220 : 0 : ppTitlePos = new SCSIZE*[nRowCount];
221 [ # # ]: 0 : for (SCSIZE i=0; i<nRowCount; i++)
222 : : {
223 : 0 : ppTitlePos[i] = new SCSIZE[nDataCount];
224 : 0 : memset( ppTitlePos[i], 0, nDataCount * sizeof(SCSIZE) ); //! unnoetig ?
225 : : }
226 : : }
227 : :
228 : : // CornerText: einzelner String
229 : 1 : }
230 : :
231 : 1 : void ScConsData::DoneFields()
232 : : {
233 : 1 : InitData(false);
234 : 1 : }
235 : :
236 : 1 : void ScConsData::SetSize( SCCOL nCols, SCROW nRows )
237 : : {
238 : 1 : DeleteData();
239 : 1 : nColCount = static_cast<SCSIZE>(nCols);
240 : 1 : nRowCount = static_cast<SCSIZE>(nRows);
241 : 1 : }
242 : :
243 : 1 : void ScConsData::GetSize( SCCOL& rCols, SCROW& rRows ) const
244 : : {
245 : 1 : rCols = static_cast<SCCOL>(nColCount);
246 : 1 : rRows = static_cast<SCROW>(nRowCount);
247 : 1 : }
248 : :
249 : 1 : void ScConsData::SetFlags( ScSubTotalFunc eFunc, sal_Bool bColName, sal_Bool bRowName, sal_Bool bRef )
250 : : {
251 : 1 : DeleteData();
252 : 1 : bReference = bRef;
253 : 1 : bColByName = bColName;
254 [ - + ]: 1 : if (bColName) nColCount = 0;
255 : 1 : bRowByName = bRowName;
256 [ - + ]: 1 : if (bRowName) nRowCount = 0;
257 : 1 : eFunction = eFunc;
258 : 1 : }
259 : :
260 : 0 : void ScConsData::AddFields( ScDocument* pSrcDoc, SCTAB nTab,
261 : : SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2 )
262 : : {
263 : 0 : ++nDataCount;
264 : :
265 [ # # ]: 0 : String aTitle;
266 : :
267 : 0 : SCCOL nStartCol = nCol1;
268 : 0 : SCROW nStartRow = nRow1;
269 [ # # ]: 0 : if (bColByName) ++nStartRow;
270 [ # # ]: 0 : if (bRowByName) ++nStartCol;
271 : :
272 [ # # ]: 0 : if (bColByName)
273 : : {
274 [ # # ]: 0 : for (SCCOL nCol=nStartCol; nCol<=nCol2; nCol++)
275 : : {
276 [ # # ]: 0 : pSrcDoc->GetString( nCol, nRow1, nTab, aTitle );
277 [ # # ]: 0 : if (aTitle.Len())
278 : : {
279 : 0 : sal_Bool bFound = false;
280 [ # # ][ # # ]: 0 : for (SCSIZE i=0; i<nColCount && !bFound; i++)
[ # # ]
281 [ # # ][ # # ]: 0 : if ( *ppColHeaders[i] == aTitle )
282 : 0 : bFound = sal_True;
283 [ # # ]: 0 : if (!bFound)
284 [ # # ]: 0 : lcl_AddString( ppColHeaders, nColCount, aTitle );
285 : : }
286 : : }
287 : : }
288 : :
289 [ # # ]: 0 : if (bRowByName)
290 : : {
291 [ # # ]: 0 : for (SCROW nRow=nStartRow; nRow<=nRow2; nRow++)
292 : : {
293 [ # # ]: 0 : pSrcDoc->GetString( nCol1, nRow, nTab, aTitle );
294 [ # # ]: 0 : if (aTitle.Len())
295 : : {
296 : 0 : sal_Bool bFound = false;
297 [ # # ][ # # ]: 0 : for (SCSIZE i=0; i<nRowCount && !bFound; i++)
[ # # ]
298 [ # # ][ # # ]: 0 : if ( *ppRowHeaders[i] == aTitle )
299 : 0 : bFound = sal_True;
300 [ # # ]: 0 : if (!bFound)
301 [ # # ]: 0 : lcl_AddString( ppRowHeaders, nRowCount, aTitle );
302 : : }
303 : : }
304 [ # # ]: 0 : }
305 : 0 : }
306 : :
307 : 0 : void ScConsData::AddName( const String& rName )
308 : : {
309 : : SCSIZE nArrX;
310 : : SCSIZE nArrY;
311 : :
312 [ # # ]: 0 : if (bReference)
313 : : {
314 : 0 : lcl_AddString( ppTitles, nTitleCount, rName );
315 : :
316 [ # # ]: 0 : for (nArrY=0; nArrY<nRowCount; nArrY++)
317 : : {
318 : : // Daten auf gleiche Laenge bringen
319 : :
320 : 0 : SCSIZE nMax = 0;
321 [ # # ]: 0 : for (nArrX=0; nArrX<nColCount; nArrX++)
322 [ # # ]: 0 : if (ppUsed[nArrX][nArrY])
323 : 0 : nMax = Max( nMax, ppRefs[nArrX][nArrY].GetCount() );
324 : :
325 [ # # ]: 0 : for (nArrX=0; nArrX<nColCount; nArrX++)
326 : : {
327 [ # # ]: 0 : if (!ppUsed[nArrX][nArrY])
328 : : {
329 : 0 : ppUsed[nArrX][nArrY] = sal_True;
330 : 0 : ppRefs[nArrX][nArrY].Init();
331 : : }
332 : 0 : ppRefs[nArrX][nArrY].SetFullSize(nMax);
333 : : }
334 : :
335 : : // Positionen eintragen
336 : :
337 [ # # ]: 0 : if (ppTitlePos)
338 [ # # ]: 0 : if (nTitleCount < nDataCount)
339 : 0 : ppTitlePos[nArrY][nTitleCount] = nMax;
340 : : }
341 : : }
342 : 0 : }
343 : :
344 : : // rCount < 0 <=> Fehler aufgetreten
345 : :
346 : 0 : void lcl_UpdateArray( ScSubTotalFunc eFunc,
347 : : double& rCount, double& rSum, double& rSumSqr, double nVal )
348 : : {
349 [ # # ]: 0 : if (rCount < 0.0)
350 : 0 : return;
351 [ # # # # : 0 : switch (eFunc)
# # # # ]
352 : : {
353 : : case SUBTOTAL_FUNC_SUM:
354 [ # # ]: 0 : if (!SubTotal::SafePlus(rSum, nVal))
355 : 0 : rCount = -MAXDOUBLE;
356 : 0 : break;
357 : : case SUBTOTAL_FUNC_PROD:
358 [ # # ]: 0 : if (!SubTotal::SafeMult(rSum, nVal))
359 : 0 : rCount = -MAXDOUBLE;
360 : 0 : break;
361 : : case SUBTOTAL_FUNC_CNT:
362 : : case SUBTOTAL_FUNC_CNT2:
363 : 0 : rCount += 1.0;
364 : 0 : break;
365 : : case SUBTOTAL_FUNC_AVE:
366 [ # # ]: 0 : if (!SubTotal::SafePlus(rSum, nVal))
367 : 0 : rCount = -MAXDOUBLE;
368 : : else
369 : 0 : rCount += 1.0;
370 : 0 : break;
371 : : case SUBTOTAL_FUNC_MAX:
372 [ # # ]: 0 : if (nVal > rSum)
373 : 0 : rSum = nVal;
374 : 0 : break;
375 : : case SUBTOTAL_FUNC_MIN:
376 [ # # ]: 0 : if (nVal < rSum)
377 : 0 : rSum = nVal;
378 : 0 : break;
379 : : case SUBTOTAL_FUNC_STD:
380 : : case SUBTOTAL_FUNC_STDP:
381 : : case SUBTOTAL_FUNC_VAR:
382 : : case SUBTOTAL_FUNC_VARP:
383 : : {
384 : 0 : sal_Bool bOk = SubTotal::SafePlus(rSum, nVal);
385 [ # # ][ # # ]: 0 : bOk = bOk && SubTotal::SafeMult(nVal, nVal);
386 [ # # ][ # # ]: 0 : bOk = bOk && SubTotal::SafePlus(rSumSqr, nVal);
387 [ # # ]: 0 : if (!bOk)
388 : 0 : rCount = -MAXDOUBLE;
389 : : else
390 : 0 : rCount += 1.0;
391 : 0 : break;
392 : : }
393 : : default:
394 : : {
395 : : // added to avoid warnings
396 : : }
397 : : }
398 : : }
399 : :
400 : 0 : void lcl_InitArray( ScSubTotalFunc eFunc,
401 : : double& rCount, double& rSum, double& rSumSqr, double nVal )
402 : : {
403 : 0 : rCount = 1.0;
404 [ # # # ]: 0 : switch (eFunc)
405 : : {
406 : : case SUBTOTAL_FUNC_SUM:
407 : : case SUBTOTAL_FUNC_MAX:
408 : : case SUBTOTAL_FUNC_MIN:
409 : : case SUBTOTAL_FUNC_PROD:
410 : : case SUBTOTAL_FUNC_AVE:
411 : 0 : rSum = nVal;
412 : 0 : break;
413 : : case SUBTOTAL_FUNC_STD:
414 : : case SUBTOTAL_FUNC_STDP:
415 : : case SUBTOTAL_FUNC_VAR:
416 : : case SUBTOTAL_FUNC_VARP:
417 : : {
418 : 0 : rSum = nVal;
419 : 0 : sal_Bool bOk = SubTotal::SafeMult(nVal, nVal);
420 [ # # ]: 0 : if (bOk)
421 : 0 : rSumSqr = nVal;
422 : : else
423 : 0 : rCount = -MAXDOUBLE;
424 : : }
425 : 0 : break;
426 : : default:
427 : 0 : break;
428 : : }
429 : 0 : }
430 : :
431 : 0 : double lcl_CalcData( ScSubTotalFunc eFunc,
432 : : double fCount, double fSum, double fSumSqr)
433 : : {
434 [ # # ]: 0 : if (fCount < 0.0)
435 : 0 : return 0.0;
436 : 0 : double fVal = 0.0;
437 [ # # # # : 0 : switch (eFunc)
# # # # ]
438 : : {
439 : : case SUBTOTAL_FUNC_CNT:
440 : : case SUBTOTAL_FUNC_CNT2:
441 : 0 : fVal = fCount;
442 : 0 : break;
443 : : case SUBTOTAL_FUNC_SUM:
444 : : case SUBTOTAL_FUNC_MAX:
445 : : case SUBTOTAL_FUNC_MIN:
446 : : case SUBTOTAL_FUNC_PROD:
447 : 0 : fVal = fSum;
448 : 0 : break;
449 : : case SUBTOTAL_FUNC_AVE:
450 [ # # ]: 0 : if (fCount > 0.0)
451 : 0 : fVal = fSum / fCount;
452 : : else
453 : 0 : fCount = -MAXDOUBLE;
454 : 0 : break;
455 : : case SUBTOTAL_FUNC_STD:
456 : : {
457 [ # # ][ # # ]: 0 : if (fCount > 1 && SubTotal::SafeMult(fSum, fSum))
[ # # ]
458 : 0 : fVal = sqrt((fSumSqr - fSum/fCount)/(fCount-1.0));
459 : : else
460 : 0 : fCount = -MAXDOUBLE;
461 : : }
462 : 0 : break;
463 : : case SUBTOTAL_FUNC_STDP:
464 : : {
465 [ # # ][ # # ]: 0 : if (fCount > 0 && SubTotal::SafeMult(fSum, fSum))
[ # # ]
466 : 0 : fVal = sqrt((fSumSqr - fSum/fCount)/fCount);
467 : : else
468 : 0 : fCount = -MAXDOUBLE;
469 : : }
470 : 0 : break;
471 : : case SUBTOTAL_FUNC_VAR:
472 : : {
473 [ # # ][ # # ]: 0 : if (fCount > 1 && SubTotal::SafeMult(fSum, fSum))
[ # # ]
474 : 0 : fVal = (fSumSqr - fSum/fCount)/(fCount-1.0);
475 : : else
476 : 0 : fCount = -MAXDOUBLE;
477 : : }
478 : 0 : break;
479 : : case SUBTOTAL_FUNC_VARP:
480 : : {
481 [ # # ][ # # ]: 0 : if (fCount > 0 && SubTotal::SafeMult(fSum, fSum))
[ # # ]
482 : 0 : fVal = (fSumSqr - fSum/fCount)/fCount;
483 : : else
484 : 0 : fCount = -MAXDOUBLE;
485 : : }
486 : 0 : break;
487 : : default:
488 : : {
489 : : OSL_FAIL("unbekannte Funktion bei Consoli::CalcData");
490 : 0 : fCount = -MAXDOUBLE;
491 : : }
492 : 0 : break;
493 : : }
494 : 0 : return fVal;
495 : : }
496 : :
497 : 0 : void ScConsData::AddData( ScDocument* pSrcDoc, SCTAB nTab,
498 : : SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2 )
499 : : {
500 : 0 : PutInOrder(nCol1,nCol2);
501 : 0 : PutInOrder(nRow1,nRow2);
502 [ # # ][ # # ]: 0 : if ( nCol2 >= sal::static_int_cast<SCCOL>(nCol1 + nColCount) && !bColByName )
[ # # ]
503 : : {
504 : : OSL_FAIL("Bereich zu gross");
505 : 0 : nCol2 = sal::static_int_cast<SCCOL>( nCol1 + nColCount - 1 );
506 : : }
507 [ # # ][ # # ]: 0 : if ( nRow2 >= sal::static_int_cast<SCROW>(nRow1 + nRowCount) && !bRowByName )
[ # # ]
508 : : {
509 : : OSL_FAIL("Bereich zu gross");
510 : 0 : nRow2 = sal::static_int_cast<SCROW>( nRow1 + nRowCount - 1 );
511 : : }
512 : :
513 : : SCCOL nCol;
514 : : SCROW nRow;
515 : :
516 : : // Ecke links oben
517 : :
518 [ # # ][ # # ]: 0 : if ( bColByName && bRowByName )
519 : : {
520 [ # # ]: 0 : String aThisCorner;
521 [ # # ]: 0 : pSrcDoc->GetString(nCol1,nRow1,nTab,aThisCorner);
522 [ # # ]: 0 : if (bCornerUsed)
523 : : {
524 [ # # ][ # # ]: 0 : if (aCornerText != aThisCorner)
525 [ # # ]: 0 : aCornerText.Erase();
526 : : }
527 : : else
528 : : {
529 [ # # ]: 0 : aCornerText = aThisCorner;
530 : 0 : bCornerUsed = sal_True;
531 [ # # ]: 0 : }
532 : : }
533 : :
534 : : // Titel suchen
535 : :
536 : 0 : SCCOL nStartCol = nCol1;
537 : 0 : SCROW nStartRow = nRow1;
538 [ # # ]: 0 : if (bColByName) ++nStartRow;
539 [ # # ]: 0 : if (bRowByName) ++nStartCol;
540 [ # # ]: 0 : String aTitle;
541 : 0 : SCCOL* pDestCols = NULL;
542 : 0 : SCROW* pDestRows = NULL;
543 [ # # ]: 0 : if (bColByName)
544 : : {
545 [ # # ]: 0 : pDestCols = new SCCOL[nCol2-nStartCol+1];
546 [ # # ]: 0 : for (nCol=nStartCol; nCol<=nCol2; nCol++)
547 : : {
548 [ # # ]: 0 : pSrcDoc->GetString(nCol,nRow1,nTab,aTitle);
549 : 0 : SCCOL nPos = SC_CONS_NOTFOUND;
550 [ # # ]: 0 : if (aTitle.Len())
551 : : {
552 : 0 : sal_Bool bFound = false;
553 [ # # ][ # # ]: 0 : for (SCSIZE i=0; i<nColCount && !bFound; i++)
[ # # ]
554 [ # # ][ # # ]: 0 : if ( *ppColHeaders[i] == aTitle )
555 : : {
556 : 0 : nPos = static_cast<SCCOL>(i);
557 : 0 : bFound = sal_True;
558 : : }
559 : : OSL_ENSURE(bFound, "Spalte nicht gefunden");
560 : : }
561 : 0 : pDestCols[nCol-nStartCol] = nPos;
562 : : }
563 : : }
564 [ # # ]: 0 : if (bRowByName)
565 : : {
566 [ # # ]: 0 : pDestRows = new SCROW[nRow2-nStartRow+1];
567 [ # # ]: 0 : for (nRow=nStartRow; nRow<=nRow2; nRow++)
568 : : {
569 [ # # ]: 0 : pSrcDoc->GetString(nCol1,nRow,nTab,aTitle);
570 : 0 : SCROW nPos = SC_CONS_NOTFOUND;
571 [ # # ]: 0 : if (aTitle.Len())
572 : : {
573 : 0 : sal_Bool bFound = false;
574 [ # # ][ # # ]: 0 : for (SCSIZE i=0; i<nRowCount && !bFound; i++)
[ # # ]
575 [ # # ][ # # ]: 0 : if ( *ppRowHeaders[i] == aTitle )
576 : : {
577 : 0 : nPos = static_cast<SCROW>(i);
578 : 0 : bFound = sal_True;
579 : : }
580 : : OSL_ENSURE(bFound, "Zeile nicht gefunden");
581 : : }
582 : 0 : pDestRows[nRow-nStartRow] = nPos;
583 : : }
584 : : }
585 : 0 : nCol1 = nStartCol;
586 : 0 : nRow1 = nStartRow;
587 : :
588 : : // Daten
589 : :
590 : 0 : sal_Bool bAnyCell = ( eFunction == SUBTOTAL_FUNC_CNT2 );
591 [ # # ]: 0 : for (nCol=nCol1; nCol<=nCol2; nCol++)
592 : : {
593 : 0 : SCCOL nArrX = nCol-nCol1;
594 [ # # ]: 0 : if (bColByName) nArrX = pDestCols[nArrX];
595 [ # # ]: 0 : if (nArrX != SC_CONS_NOTFOUND)
596 : : {
597 [ # # ]: 0 : for (nRow=nRow1; nRow<=nRow2; nRow++)
598 : : {
599 : 0 : SCROW nArrY = nRow-nRow1;
600 [ # # ]: 0 : if (bRowByName) nArrY = pDestRows[nArrY];
601 [ # # ][ # # ]: 0 : if ( nArrY != SC_CONS_NOTFOUND && (
[ # # ][ # # ]
[ # # ]
602 [ # # ]: 0 : bAnyCell ? pSrcDoc->HasData( nCol, nRow, nTab )
603 [ # # ]: 0 : : pSrcDoc->HasValueData( nCol, nRow, nTab ) ) )
604 : : {
605 [ # # ]: 0 : if (bReference)
606 : : {
607 [ # # ]: 0 : if (ppUsed[nArrX][nArrY])
608 [ # # ]: 0 : ppRefs[nArrX][nArrY].AddEntry( nCol, nRow, nTab );
609 : : else
610 : : {
611 : 0 : ppUsed[nArrX][nArrY] = sal_True;
612 : 0 : ppRefs[nArrX][nArrY].Init();
613 [ # # ]: 0 : ppRefs[nArrX][nArrY].AddEntry( nCol, nRow, nTab );
614 : : }
615 : : }
616 : : else
617 : : {
618 : : double nVal;
619 [ # # ]: 0 : pSrcDoc->GetValue( nCol, nRow, nTab, nVal );
620 [ # # ]: 0 : if (ppUsed[nArrX][nArrY])
621 : 0 : lcl_UpdateArray( eFunction, ppCount[nArrX][nArrY],
622 : 0 : ppSum[nArrX][nArrY], ppSumSqr[nArrX][nArrY],
623 [ # # ]: 0 : nVal);
624 : : else
625 : : {
626 : 0 : ppUsed[nArrX][nArrY] = sal_True;
627 : 0 : lcl_InitArray( eFunction, ppCount[nArrX][nArrY],
628 : 0 : ppSum[nArrX][nArrY],
629 [ # # ]: 0 : ppSumSqr[nArrX][nArrY], nVal );
630 : : }
631 : : }
632 : : }
633 : : }
634 : : }
635 : : }
636 : :
637 [ # # ]: 0 : delete[] pDestCols;
638 [ # # ][ # # ]: 0 : delete[] pDestRows;
639 : 0 : }
640 : :
641 : : // vorher testen, wieviele Zeilen eingefuegt werden (fuer Undo)
642 : :
643 : 0 : SCROW ScConsData::GetInsertCount() const
644 : : {
645 : 0 : SCROW nInsert = 0;
646 : : SCSIZE nArrX;
647 : : SCSIZE nArrY;
648 [ # # ][ # # ]: 0 : if ( ppRefs && ppUsed )
649 : : {
650 [ # # ]: 0 : for (nArrY=0; nArrY<nRowCount; nArrY++)
651 : : {
652 : 0 : SCSIZE nNeeded = 0;
653 [ # # ]: 0 : for (nArrX=0; nArrX<nColCount; nArrX++)
654 [ # # ]: 0 : if (ppUsed[nArrX][nArrY])
655 : 0 : nNeeded = Max( nNeeded, ppRefs[nArrX][nArrY].GetCount() );
656 : :
657 : 0 : nInsert += nNeeded;
658 : : }
659 : : }
660 : 0 : return nInsert;
661 : : }
662 : :
663 : : // fertige Daten ins Dokument schreiben
664 : : //! optimieren nach Spalten?
665 : :
666 : 1 : void ScConsData::OutputToDocument( ScDocument* pDestDoc, SCCOL nCol, SCROW nRow, SCTAB nTab )
667 : : {
668 : 1 : OpCode eOpCode = eOpCodeTable[eFunction];
669 : :
670 : : SCSIZE nArrX;
671 : : SCSIZE nArrY;
672 : :
673 : : // Ecke links oben
674 : :
675 [ - + ][ # # ]: 1 : if ( bColByName && bRowByName && aCornerText.Len() )
[ # # ][ - + ]
676 [ # # ]: 0 : pDestDoc->SetString( nCol, nRow, nTab, aCornerText );
677 : :
678 : : // Titel
679 : :
680 : 1 : SCCOL nStartCol = nCol;
681 : 1 : SCROW nStartRow = nRow;
682 [ - + ]: 1 : if (bColByName) ++nStartRow;
683 [ - + ]: 1 : if (bRowByName) ++nStartCol;
684 : :
685 [ - + ]: 1 : if (bColByName)
686 [ # # ]: 0 : for (SCSIZE i=0; i<nColCount; i++)
687 [ # # ]: 0 : pDestDoc->SetString( sal::static_int_cast<SCCOL>(nStartCol+i), nRow, nTab, *ppColHeaders[i] );
688 [ - + ]: 1 : if (bRowByName)
689 [ # # ]: 0 : for (SCSIZE j=0; j<nRowCount; j++)
690 [ # # ]: 0 : pDestDoc->SetString( nCol, sal::static_int_cast<SCROW>(nStartRow+j), nTab, *ppRowHeaders[j] );
691 : :
692 : 1 : nCol = nStartCol;
693 : 1 : nRow = nStartRow;
694 : :
695 : : // Daten
696 : :
697 [ - + ][ # # ]: 1 : if ( ppCount && ppUsed ) // Werte direkt einfuegen
698 : : {
699 [ # # ]: 0 : for (nArrX=0; nArrX<nColCount; nArrX++)
700 [ # # ]: 0 : for (nArrY=0; nArrY<nRowCount; nArrY++)
701 [ # # ]: 0 : if (ppUsed[nArrX][nArrY])
702 : : {
703 : 0 : double fVal = lcl_CalcData( eFunction, ppCount[nArrX][nArrY],
704 : 0 : ppSum[nArrX][nArrY],
705 [ # # ]: 0 : ppSumSqr[nArrX][nArrY]);
706 [ # # ]: 0 : if (ppCount[nArrX][nArrY] < 0.0)
707 : 0 : pDestDoc->SetError( sal::static_int_cast<SCCOL>(nCol+nArrX),
708 [ # # ]: 0 : sal::static_int_cast<SCROW>(nRow+nArrY), nTab, errNoValue );
709 : : else
710 : 0 : pDestDoc->SetValue( sal::static_int_cast<SCCOL>(nCol+nArrX),
711 [ # # ]: 0 : sal::static_int_cast<SCROW>(nRow+nArrY), nTab, fVal );
712 : : }
713 : : }
714 : :
715 [ - + ][ # # ]: 1 : if ( ppRefs && ppUsed ) // Referenzen einfuegen
716 : : {
717 : : //! unterscheiden, ob nach Kategorien aufgeteilt
718 [ # # ]: 0 : String aString;
719 : :
720 : : ScSingleRefData aSRef; // Daten fuer Referenz-Formelzellen
721 : 0 : aSRef.InitFlags();
722 : 0 : aSRef.SetFlag3D(sal_True);
723 : :
724 : : ScComplexRefData aCRef; // Daten fuer Summen-Zellen
725 : 0 : aCRef.InitFlags();
726 : 0 : aCRef.Ref1.SetColRel(sal_True); aCRef.Ref1.SetRowRel(sal_True); aCRef.Ref1.SetTabRel(sal_True);
727 : 0 : aCRef.Ref2.SetColRel(sal_True); aCRef.Ref2.SetRowRel(sal_True); aCRef.Ref2.SetTabRel(sal_True);
728 : :
729 [ # # ]: 0 : for (nArrY=0; nArrY<nRowCount; nArrY++)
730 : : {
731 : 0 : SCSIZE nNeeded = 0;
732 [ # # ]: 0 : for (nArrX=0; nArrX<nColCount; nArrX++)
733 [ # # ]: 0 : if (ppUsed[nArrX][nArrY])
734 : 0 : nNeeded = Max( nNeeded, ppRefs[nArrX][nArrY].GetCount() );
735 : :
736 [ # # ]: 0 : if (nNeeded)
737 : : {
738 [ # # ]: 0 : pDestDoc->InsertRow( 0,nTab, MAXCOL,nTab, nRow+nArrY, nNeeded );
739 : :
740 [ # # ]: 0 : for (nArrX=0; nArrX<nColCount; nArrX++)
741 [ # # ]: 0 : if (ppUsed[nArrX][nArrY])
742 : : {
743 : 0 : ScReferenceList& rList = ppRefs[nArrX][nArrY];
744 : 0 : SCSIZE nCount = rList.GetCount();
745 [ # # ]: 0 : if (nCount)
746 : : {
747 [ # # ]: 0 : for (SCSIZE nPos=0; nPos<nCount; nPos++)
748 : : {
749 : 0 : ScReferenceEntry aRef = rList.GetEntry(nPos);
750 [ # # ]: 0 : if (aRef.nTab != SC_CONS_NOTFOUND)
751 : : {
752 : : // Referenz einfuegen (absolut, 3d)
753 : :
754 : 0 : aSRef.nCol = aRef.nCol;
755 : 0 : aSRef.nRow = aRef.nRow;
756 : 0 : aSRef.nTab = aRef.nTab;
757 : :
758 [ # # ]: 0 : ScTokenArray aRefArr;
759 [ # # ]: 0 : aRefArr.AddSingleReference(aSRef);
760 [ # # ]: 0 : aRefArr.AddOpCode(ocStop);
761 : 0 : ScAddress aDest( sal::static_int_cast<SCCOL>(nCol+nArrX),
762 : 0 : sal::static_int_cast<SCROW>(nRow+nArrY+nPos), nTab );
763 [ # # ][ # # ]: 0 : ScBaseCell* pCell = new ScFormulaCell( pDestDoc, aDest, &aRefArr );
[ # # ]
764 [ # # ][ # # ]: 0 : pDestDoc->PutCell( aDest.Col(), aDest.Row(), aDest.Tab(), pCell );
765 : : }
766 : : }
767 : :
768 : : // Summe einfuegen (relativ, nicht 3d)
769 : :
770 : 0 : ScAddress aDest( sal::static_int_cast<SCCOL>(nCol+nArrX),
771 : 0 : sal::static_int_cast<SCROW>(nRow+nArrY+nNeeded), nTab );
772 : :
773 : 0 : aCRef.Ref1.nTab = aCRef.Ref2.nTab = nTab;
774 : 0 : aCRef.Ref1.nCol = aCRef.Ref2.nCol = sal::static_int_cast<SCsCOL>( nCol+nArrX );
775 : 0 : aCRef.Ref1.nRow = nRow+nArrY;
776 : 0 : aCRef.Ref2.nRow = nRow+nArrY+nNeeded-1;
777 [ # # ]: 0 : aCRef.CalcRelFromAbs( aDest );
778 : :
779 [ # # ]: 0 : ScTokenArray aArr;
780 [ # # ]: 0 : aArr.AddOpCode(eOpCode); // ausgewaehlte Funktion
781 [ # # ]: 0 : aArr.AddOpCode(ocOpen);
782 [ # # ]: 0 : aArr.AddDoubleReference(aCRef);
783 [ # # ]: 0 : aArr.AddOpCode(ocClose);
784 [ # # ]: 0 : aArr.AddOpCode(ocStop);
785 [ # # ][ # # ]: 0 : ScBaseCell* pCell = new ScFormulaCell( pDestDoc, aDest, &aArr );
[ # # ]
786 [ # # ][ # # ]: 0 : pDestDoc->PutCell( aDest.Col(), aDest.Row(), aDest.Tab(), pCell );
787 : : }
788 : : }
789 : :
790 : : // Gliederung einfuegen
791 : :
792 [ # # ]: 0 : ScOutlineArray* pOutArr = pDestDoc->GetOutlineTable( nTab, sal_True )->GetRowArray();
793 : 0 : SCROW nOutStart = nRow+nArrY;
794 : 0 : SCROW nOutEnd = nRow+nArrY+nNeeded-1;
795 : 0 : bool bSize = false;
796 [ # # ]: 0 : pOutArr->Insert( nOutStart, nOutEnd, bSize );
797 [ # # ]: 0 : pDestDoc->InitializeNoteCaptions(nTab);
798 [ # # ]: 0 : for (SCROW nOutRow=nOutStart; nOutRow<=nOutEnd; nOutRow++)
799 [ # # ]: 0 : pDestDoc->ShowRow( nOutRow, nTab, false );
800 [ # # ]: 0 : pDestDoc->SetDrawPageSize(nTab);
801 [ # # ]: 0 : pDestDoc->UpdateOutlineRow( nOutStart, nOutEnd, nTab, false );
802 : :
803 : : // Zwischentitel
804 : :
805 [ # # ][ # # ]: 0 : if (ppTitlePos && ppTitles && ppRowHeaders)
[ # # ]
806 : : {
807 [ # # ]: 0 : String aDelim( RTL_CONSTASCII_USTRINGPARAM(" / ") );
808 [ # # ]: 0 : for (SCSIZE nPos=0; nPos<nDataCount; nPos++)
809 : : {
810 : 0 : SCSIZE nTPos = ppTitlePos[nArrY][nPos];
811 : 0 : sal_Bool bDo = sal_True;
812 [ # # ]: 0 : if (nPos+1<nDataCount)
813 [ # # ]: 0 : if (ppTitlePos[nArrY][nPos+1] == nTPos)
814 : 0 : bDo = false; // leer
815 [ # # ][ # # ]: 0 : if ( bDo && nTPos < nNeeded )
816 : : {
817 [ # # ]: 0 : aString = *ppRowHeaders[nArrY];
818 [ # # ]: 0 : aString += aDelim;
819 [ # # ]: 0 : aString += *ppTitles[nPos];
820 [ # # ][ # # ]: 0 : pDestDoc->SetString( nCol-1, nRow+nArrY+nTPos, nTab, aString );
821 : : }
822 [ # # ]: 0 : }
823 : : }
824 : :
825 : 0 : nRow += nNeeded;
826 : : }
827 [ # # ]: 0 : }
828 : : }
829 : 1 : }
830 : :
831 : :
832 : :
833 : :
834 : :
835 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|