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