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 : #include <osl/diagnose.h>
29 :
30 : #include <math.h>
31 : #include <string.h>
32 : #include <boost/scoped_array.hpp>
33 :
34 : #define SC_CONS_NOTFOUND -1
35 :
36 : // STATIC DATA
37 : static const OpCode eOpCodeTable[] = { // order as for enum ScSubTotalFunc
38 : ocBad, // none
39 : ocAverage,
40 : ocCount,
41 : ocCount2,
42 : ocMax,
43 : ocMin,
44 : ocProduct,
45 : ocStDev,
46 : ocStDevP,
47 : ocSum,
48 : ocVar,
49 : ocVarP };
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( ::std::vector<OUString>& rData, T& nCount, const OUString& rInsert )
76 : {
77 0 : rData.push_back( rInsert);
78 0 : ++nCount;
79 0 : }
80 :
81 1 : ScConsData::ScConsData() :
82 : eFunction(SUBTOTAL_FUNC_SUM),
83 : bReference(false),
84 : bColByName(false),
85 : bRowByName(false),
86 : nColCount(0),
87 : nRowCount(0),
88 : ppUsed(NULL),
89 : ppSum(NULL),
90 : ppCount(NULL),
91 : ppSumSqr(NULL),
92 : ppRefs(NULL),
93 : nDataCount(0),
94 : ppTitlePos(NULL),
95 1 : bCornerUsed(false)
96 : {
97 1 : }
98 :
99 2 : ScConsData::~ScConsData()
100 : {
101 1 : DeleteData();
102 1 : }
103 :
104 : #define DELETEARR(ppArray,nCount) \
105 : { \
106 : sal_uLong i; \
107 : if (ppArray) \
108 : for(i=0; i<nCount; i++) \
109 : delete[] ppArray[i]; \
110 : delete[] ppArray; \
111 : ppArray = NULL; \
112 : }
113 :
114 3 : void ScConsData::DeleteData()
115 : {
116 3 : if (ppRefs)
117 : {
118 0 : for (SCSIZE i=0; i<nColCount; i++)
119 : {
120 0 : for (SCSIZE j=0; j<nRowCount; j++)
121 0 : if (ppUsed[i][j])
122 0 : ppRefs[i][j].Clear();
123 0 : delete[] ppRefs[i];
124 : }
125 0 : delete[] ppRefs;
126 0 : ppRefs = NULL;
127 : }
128 :
129 3 : DELETEARR( ppCount, nColCount );
130 3 : DELETEARR( ppSum, nColCount );
131 3 : DELETEARR( ppSumSqr,nColCount );
132 3 : DELETEARR( ppUsed, nColCount ); // only after ppRefs !!!
133 3 : DELETEARR( ppTitlePos, nRowCount );
134 3 : ::std::vector<OUString>().swap( maColHeaders);
135 3 : ::std::vector<OUString>().swap( maRowHeaders);
136 3 : ::std::vector<OUString>().swap( maTitles);
137 3 : nDataCount = 0;
138 :
139 3 : if (bColByName) nColCount = 0; // otherwise maColHeaders is wrong
140 3 : if (bRowByName) nRowCount = 0;
141 :
142 3 : bCornerUsed = false;
143 3 : aCornerText.clear();
144 3 : }
145 :
146 : #undef DELETEARR
147 : #undef DELETESTR
148 :
149 1 : void ScConsData::InitData()
150 : {
151 1 : if (bReference && nColCount && !ppRefs)
152 : {
153 0 : ppRefs = new ScReferenceList*[nColCount];
154 0 : for (SCSIZE i=0; i<nColCount; i++)
155 0 : ppRefs[i] = new ScReferenceList[nRowCount];
156 : }
157 1 : else if (nColCount && !ppCount)
158 : {
159 0 : ppCount = new double*[nColCount];
160 0 : ppSum = new double*[nColCount];
161 0 : ppSumSqr = new double*[nColCount];
162 0 : for (SCSIZE i=0; i<nColCount; i++)
163 : {
164 0 : ppCount[i] = new double[nRowCount];
165 0 : ppSum[i] = new double[nRowCount];
166 0 : ppSumSqr[i] = new double[nRowCount];
167 : }
168 : }
169 :
170 1 : if (nColCount && !ppUsed)
171 : {
172 0 : ppUsed = new bool*[nColCount];
173 0 : for (SCSIZE i=0; i<nColCount; i++)
174 : {
175 0 : ppUsed[i] = new bool[nRowCount];
176 0 : memset( ppUsed[i], 0, nRowCount * sizeof(bool) );
177 : }
178 : }
179 :
180 1 : if (nRowCount && nDataCount && !ppTitlePos)
181 : {
182 0 : ppTitlePos = new SCSIZE*[nRowCount];
183 0 : for (SCSIZE i=0; i<nRowCount; i++)
184 : {
185 0 : ppTitlePos[i] = new SCSIZE[nDataCount];
186 0 : memset( ppTitlePos[i], 0, nDataCount * sizeof(SCSIZE) ); //TODO: not necessary ?
187 : }
188 : }
189 :
190 : // CornerText: single String
191 1 : }
192 :
193 1 : void ScConsData::DoneFields()
194 : {
195 1 : InitData();
196 1 : }
197 :
198 1 : void ScConsData::SetSize( SCCOL nCols, SCROW nRows )
199 : {
200 1 : DeleteData();
201 1 : nColCount = static_cast<SCSIZE>(nCols);
202 1 : nRowCount = static_cast<SCSIZE>(nRows);
203 1 : }
204 :
205 1 : void ScConsData::GetSize( SCCOL& rCols, SCROW& rRows ) const
206 : {
207 1 : rCols = static_cast<SCCOL>(nColCount);
208 1 : rRows = static_cast<SCROW>(nRowCount);
209 1 : }
210 :
211 1 : void ScConsData::SetFlags( ScSubTotalFunc eFunc, bool bColName, bool bRowName, bool bRef )
212 : {
213 1 : DeleteData();
214 1 : bReference = bRef;
215 1 : bColByName = bColName;
216 1 : if (bColName) nColCount = 0;
217 1 : bRowByName = bRowName;
218 1 : if (bRowName) nRowCount = 0;
219 1 : eFunction = eFunc;
220 1 : }
221 :
222 0 : void ScConsData::AddFields( ScDocument* pSrcDoc, SCTAB nTab,
223 : SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2 )
224 : {
225 0 : ++nDataCount;
226 :
227 0 : OUString aTitle;
228 :
229 0 : SCCOL nStartCol = nCol1;
230 0 : SCROW nStartRow = nRow1;
231 0 : if (bColByName) ++nStartRow;
232 0 : if (bRowByName) ++nStartCol;
233 :
234 0 : if (bColByName)
235 : {
236 0 : for (SCCOL nCol=nStartCol; nCol<=nCol2; nCol++)
237 : {
238 0 : aTitle = pSrcDoc->GetString(nCol, nRow1, nTab);
239 0 : if (!aTitle.isEmpty())
240 : {
241 0 : bool bFound = false;
242 0 : for (SCSIZE i=0; i<nColCount && !bFound; i++)
243 0 : if ( maColHeaders[i] == aTitle )
244 0 : bFound = true;
245 0 : if (!bFound)
246 0 : lcl_AddString( maColHeaders, nColCount, aTitle );
247 : }
248 : }
249 : }
250 :
251 0 : if (bRowByName)
252 : {
253 0 : for (SCROW nRow=nStartRow; nRow<=nRow2; nRow++)
254 : {
255 0 : aTitle = pSrcDoc->GetString(nCol1, nRow, nTab);
256 0 : if (!aTitle.isEmpty())
257 : {
258 0 : bool bFound = false;
259 0 : for (SCSIZE i=0; i<nRowCount && !bFound; i++)
260 0 : if ( maRowHeaders[i] == aTitle )
261 0 : bFound = true;
262 0 : if (!bFound)
263 0 : lcl_AddString( maRowHeaders, nRowCount, aTitle );
264 : }
265 : }
266 0 : }
267 0 : }
268 :
269 0 : void ScConsData::AddName( const OUString& rName )
270 : {
271 : SCSIZE nArrX;
272 : SCSIZE nArrY;
273 :
274 0 : if (bReference)
275 : {
276 0 : maTitles.push_back( rName);
277 0 : size_t nTitleCount = maTitles.size();
278 :
279 0 : for (nArrY=0; nArrY<nRowCount; nArrY++)
280 : {
281 : // set all data to same length
282 :
283 0 : SCSIZE nMax = 0;
284 0 : for (nArrX=0; nArrX<nColCount; nArrX++)
285 0 : if (ppUsed[nArrX][nArrY])
286 0 : nMax = std::max( nMax, ppRefs[nArrX][nArrY].GetCount() );
287 :
288 0 : for (nArrX=0; nArrX<nColCount; nArrX++)
289 : {
290 0 : if (!ppUsed[nArrX][nArrY])
291 : {
292 0 : ppUsed[nArrX][nArrY] = true;
293 0 : ppRefs[nArrX][nArrY].Init();
294 : }
295 0 : ppRefs[nArrX][nArrY].SetFullSize(nMax);
296 : }
297 :
298 : // store positions
299 :
300 0 : if (ppTitlePos)
301 0 : if (nTitleCount < nDataCount)
302 0 : ppTitlePos[nArrY][nTitleCount] = nMax;
303 : }
304 : }
305 0 : }
306 :
307 : // rCount < 0 <=> error
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 : // left top corner
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.clear();
487 : }
488 : else
489 : {
490 0 : aCornerText = aThisCorner;
491 0 : bCornerUsed = true;
492 0 : }
493 : }
494 :
495 : // search title
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 : // data
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 : // check before, how many rows to insert (for 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 : // store completed data to document
622 : //TODO: optimize on columns?
623 :
624 1 : void ScConsData::OutputToDocument( ScDocument* pDestDoc, SCCOL nCol, SCROW nRow, SCTAB nTab )
625 : {
626 1 : OpCode eOpCode = eOpCodeTable[eFunction];
627 :
628 : SCSIZE nArrX;
629 : SCSIZE nArrY;
630 :
631 : // left top corner
632 :
633 1 : if ( bColByName && bRowByName && !aCornerText.isEmpty() )
634 0 : pDestDoc->SetString( nCol, nRow, nTab, aCornerText );
635 :
636 : // title
637 :
638 1 : SCCOL nStartCol = nCol;
639 1 : SCROW nStartRow = nRow;
640 1 : if (bColByName) ++nStartRow;
641 1 : if (bRowByName) ++nStartCol;
642 :
643 1 : 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 1 : 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 1 : nCol = nStartCol;
651 1 : nRow = nStartRow;
652 :
653 : // data
654 :
655 1 : if ( ppCount && ppUsed ) // insert values directly
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 1 : if ( ppRefs && ppUsed ) // insert Reference
674 : {
675 : //TODO: differentiate, if split into categories
676 0 : OUString aString;
677 :
678 : ScSingleRefData aSRef; // data for Referece formula cells
679 0 : aSRef.InitFlags(); // this reference is absolute at all times
680 0 : aSRef.SetFlag3D(true);
681 :
682 : ScComplexRefData aCRef; // data for Sum cells
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 : // insert reference (absolute, 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 : // insert sum (relativ, not 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); // selected function
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 : // insert outline
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 : // sub title
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; // empty
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 157 : }
783 :
784 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|