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