Stop leaking all ScPostIt instances.
[LibreOffice.git] / sc / source / core / tool / consoli.cxx
blob3dbe8f923fc14ae35fbbf80c428d67679115c7bd
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
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"
29 #include <math.h>
30 #include <string.h>
32 #define SC_CONS_NOTFOUND -1
34 // STATIC DATA
35 static const 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 };
49 void ScReferenceList::AddEntry( SCCOL nCol, SCROW nRow, SCTAB nTab )
51 ScReferenceEntry* pOldData = pData;
52 pData = new ScReferenceEntry[ nFullSize+1 ];
53 if (pOldData)
55 memcpy( pData, pOldData, nCount * sizeof(ScReferenceEntry) );
56 delete[] pOldData;
58 while (nCount < nFullSize)
60 pData[nCount].nCol = SC_CONS_NOTFOUND;
61 pData[nCount].nRow = SC_CONS_NOTFOUND;
62 pData[nCount].nTab = SC_CONS_NOTFOUND;
63 ++nCount;
65 pData[nCount].nCol = nCol;
66 pData[nCount].nRow = nRow;
67 pData[nCount].nTab = nTab;
68 ++nCount;
69 nFullSize = nCount;
72 template< typename T >
73 static void lcl_AddString( OUString*& pData, T& nCount, const OUString& rInsert )
75 OUString* pOldData = pData;
76 pData = new OUString[ nCount+1 ];
77 if (pOldData)
79 memcpy( pData, pOldData, nCount * sizeof(OUString) );
80 delete[] pOldData;
82 pData[nCount] = rInsert;
83 ++nCount;
86 ScConsData::ScConsData() :
87 eFunction(SUBTOTAL_FUNC_SUM),
88 bReference(false),
89 bColByName(false),
90 bRowByName(false),
91 nColCount(0),
92 nRowCount(0),
93 ppUsed(NULL),
94 ppSum(NULL),
95 ppCount(NULL),
96 ppSumSqr(NULL),
97 ppRefs(NULL),
98 mpColHeaders(NULL),
99 mpRowHeaders(NULL),
100 nDataCount(0),
101 nTitleCount(0),
102 mpTitles(NULL),
103 ppTitlePos(NULL),
104 bCornerUsed(false)
108 ScConsData::~ScConsData()
110 DeleteData();
113 #define DELETEARR(ppArray,nCount) \
115 sal_uLong i; \
116 if (ppArray) \
117 for(i=0; i<nCount; i++) \
118 delete[] ppArray[i]; \
119 delete[] ppArray; \
120 ppArray = NULL; \
123 void ScConsData::DeleteData()
125 if (ppRefs)
127 for (SCSIZE i=0; i<nColCount; i++)
129 for (SCSIZE j=0; j<nRowCount; j++)
130 if (ppUsed[i][j])
131 ppRefs[i][j].Clear();
132 delete[] ppRefs[i];
134 delete[] ppRefs;
135 ppRefs = NULL;
138 DELETEARR( ppCount, nColCount );
139 DELETEARR( ppSum, nColCount );
140 DELETEARR( ppSumSqr,nColCount );
141 DELETEARR( ppUsed, nColCount ); // erst nach ppRefs !!!
142 DELETEARR( ppTitlePos, nRowCount );
143 delete[] mpColHeaders;
144 mpColHeaders = NULL;
145 delete[] mpRowHeaders;
146 mpRowHeaders = NULL;
147 delete[] mpTitles;
148 mpTitles = NULL;
149 nTitleCount = 0;
150 nDataCount = 0;
152 if (bColByName) nColCount = 0; // sonst stimmt mpColHeaders nicht
153 if (bRowByName) nRowCount = 0;
155 bCornerUsed = false;
156 aCornerText = "";
159 #undef DELETEARR
160 #undef DELETESTR
162 void ScConsData::InitData( sal_Bool bDelete )
164 if (bDelete)
165 DeleteData();
167 if (bReference && nColCount && !ppRefs)
169 ppRefs = new ScReferenceList*[nColCount];
170 for (SCSIZE i=0; i<nColCount; i++)
171 ppRefs[i] = new ScReferenceList[nRowCount];
173 else if (nColCount && !ppCount)
175 ppCount = new double*[nColCount];
176 ppSum = new double*[nColCount];
177 ppSumSqr = new double*[nColCount];
178 for (SCSIZE i=0; i<nColCount; i++)
180 ppCount[i] = new double[nRowCount];
181 ppSum[i] = new double[nRowCount];
182 ppSumSqr[i] = new double[nRowCount];
186 if (nColCount && !ppUsed)
188 ppUsed = new sal_Bool*[nColCount];
189 for (SCSIZE i=0; i<nColCount; i++)
191 ppUsed[i] = new sal_Bool[nRowCount];
192 memset( ppUsed[i], 0, nRowCount * sizeof(sal_Bool) );
196 if (nRowCount && nDataCount && !ppTitlePos)
198 ppTitlePos = new SCSIZE*[nRowCount];
199 for (SCSIZE i=0; i<nRowCount; i++)
201 ppTitlePos[i] = new SCSIZE[nDataCount];
202 memset( ppTitlePos[i], 0, nDataCount * sizeof(SCSIZE) ); //! unnoetig ?
206 // CornerText: einzelner String
209 void ScConsData::DoneFields()
211 InitData(false);
214 void ScConsData::SetSize( SCCOL nCols, SCROW nRows )
216 DeleteData();
217 nColCount = static_cast<SCSIZE>(nCols);
218 nRowCount = static_cast<SCSIZE>(nRows);
221 void ScConsData::GetSize( SCCOL& rCols, SCROW& rRows ) const
223 rCols = static_cast<SCCOL>(nColCount);
224 rRows = static_cast<SCROW>(nRowCount);
227 void ScConsData::SetFlags( ScSubTotalFunc eFunc, sal_Bool bColName, sal_Bool bRowName, sal_Bool bRef )
229 DeleteData();
230 bReference = bRef;
231 bColByName = bColName;
232 if (bColName) nColCount = 0;
233 bRowByName = bRowName;
234 if (bRowName) nRowCount = 0;
235 eFunction = eFunc;
238 void ScConsData::AddFields( ScDocument* pSrcDoc, SCTAB nTab,
239 SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2 )
241 ++nDataCount;
243 OUString aTitle;
245 SCCOL nStartCol = nCol1;
246 SCROW nStartRow = nRow1;
247 if (bColByName) ++nStartRow;
248 if (bRowByName) ++nStartCol;
250 if (bColByName)
252 for (SCCOL nCol=nStartCol; nCol<=nCol2; nCol++)
254 aTitle = pSrcDoc->GetString(nCol, nRow1, nTab);
255 if (!aTitle.isEmpty())
257 bool bFound = false;
258 for (SCSIZE i=0; i<nColCount && !bFound; i++)
259 if ( mpColHeaders[i] == aTitle )
260 bFound = true;
261 if (!bFound)
262 lcl_AddString( mpColHeaders, nColCount, aTitle );
267 if (bRowByName)
269 for (SCROW nRow=nStartRow; nRow<=nRow2; nRow++)
271 aTitle = pSrcDoc->GetString(nCol1, nRow, nTab);
272 if (!aTitle.isEmpty())
274 bool bFound = false;
275 for (SCSIZE i=0; i<nRowCount && !bFound; i++)
276 if ( mpRowHeaders[i] == aTitle )
277 bFound = true;
278 if (!bFound)
279 lcl_AddString( mpRowHeaders, nRowCount, aTitle );
285 void ScConsData::AddName( const OUString& rName )
287 SCSIZE nArrX;
288 SCSIZE nArrY;
290 if (bReference)
292 lcl_AddString( mpTitles, nTitleCount, rName );
294 for (nArrY=0; nArrY<nRowCount; nArrY++)
296 // Daten auf gleiche Laenge bringen
298 SCSIZE nMax = 0;
299 for (nArrX=0; nArrX<nColCount; nArrX++)
300 if (ppUsed[nArrX][nArrY])
301 nMax = std::max( nMax, ppRefs[nArrX][nArrY].GetCount() );
303 for (nArrX=0; nArrX<nColCount; nArrX++)
305 if (!ppUsed[nArrX][nArrY])
307 ppUsed[nArrX][nArrY] = sal_True;
308 ppRefs[nArrX][nArrY].Init();
310 ppRefs[nArrX][nArrY].SetFullSize(nMax);
313 // Positionen eintragen
315 if (ppTitlePos)
316 if (nTitleCount < nDataCount)
317 ppTitlePos[nArrY][nTitleCount] = nMax;
322 // rCount < 0 <=> Fehler aufgetreten
324 static void lcl_UpdateArray( ScSubTotalFunc eFunc,
325 double& rCount, double& rSum, double& rSumSqr, double nVal )
327 if (rCount < 0.0)
328 return;
329 switch (eFunc)
331 case SUBTOTAL_FUNC_SUM:
332 if (!SubTotal::SafePlus(rSum, nVal))
333 rCount = -MAXDOUBLE;
334 break;
335 case SUBTOTAL_FUNC_PROD:
336 if (!SubTotal::SafeMult(rSum, nVal))
337 rCount = -MAXDOUBLE;
338 break;
339 case SUBTOTAL_FUNC_CNT:
340 case SUBTOTAL_FUNC_CNT2:
341 rCount += 1.0;
342 break;
343 case SUBTOTAL_FUNC_AVE:
344 if (!SubTotal::SafePlus(rSum, nVal))
345 rCount = -MAXDOUBLE;
346 else
347 rCount += 1.0;
348 break;
349 case SUBTOTAL_FUNC_MAX:
350 if (nVal > rSum)
351 rSum = nVal;
352 break;
353 case SUBTOTAL_FUNC_MIN:
354 if (nVal < rSum)
355 rSum = nVal;
356 break;
357 case SUBTOTAL_FUNC_STD:
358 case SUBTOTAL_FUNC_STDP:
359 case SUBTOTAL_FUNC_VAR:
360 case SUBTOTAL_FUNC_VARP:
362 sal_Bool bOk = SubTotal::SafePlus(rSum, nVal);
363 bOk = bOk && SubTotal::SafeMult(nVal, nVal);
364 bOk = bOk && SubTotal::SafePlus(rSumSqr, nVal);
365 if (!bOk)
366 rCount = -MAXDOUBLE;
367 else
368 rCount += 1.0;
369 break;
371 default:
373 // added to avoid warnings
378 static void lcl_InitArray( ScSubTotalFunc eFunc,
379 double& rCount, double& rSum, double& rSumSqr, double nVal )
381 rCount = 1.0;
382 switch (eFunc)
384 case SUBTOTAL_FUNC_SUM:
385 case SUBTOTAL_FUNC_MAX:
386 case SUBTOTAL_FUNC_MIN:
387 case SUBTOTAL_FUNC_PROD:
388 case SUBTOTAL_FUNC_AVE:
389 rSum = nVal;
390 break;
391 case SUBTOTAL_FUNC_STD:
392 case SUBTOTAL_FUNC_STDP:
393 case SUBTOTAL_FUNC_VAR:
394 case SUBTOTAL_FUNC_VARP:
396 rSum = nVal;
397 sal_Bool bOk = SubTotal::SafeMult(nVal, nVal);
398 if (bOk)
399 rSumSqr = nVal;
400 else
401 rCount = -MAXDOUBLE;
403 break;
404 default:
405 break;
409 static double lcl_CalcData( ScSubTotalFunc eFunc,
410 double& fCount, double fSum, double fSumSqr)
412 if (fCount < 0.0)
413 return 0.0;
414 double fVal = 0.0;
415 switch (eFunc)
417 case SUBTOTAL_FUNC_CNT:
418 case SUBTOTAL_FUNC_CNT2:
419 fVal = fCount;
420 break;
421 case SUBTOTAL_FUNC_SUM:
422 case SUBTOTAL_FUNC_MAX:
423 case SUBTOTAL_FUNC_MIN:
424 case SUBTOTAL_FUNC_PROD:
425 fVal = fSum;
426 break;
427 case SUBTOTAL_FUNC_AVE:
428 if (fCount > 0.0)
429 fVal = fSum / fCount;
430 else
431 fCount = -MAXDOUBLE;
432 break;
433 case SUBTOTAL_FUNC_STD:
435 if (fCount > 1 && SubTotal::SafeMult(fSum, fSum))
436 fVal = sqrt((fSumSqr - fSum/fCount)/(fCount-1.0));
437 else
438 fCount = -MAXDOUBLE;
440 break;
441 case SUBTOTAL_FUNC_STDP:
443 if (fCount > 0 && SubTotal::SafeMult(fSum, fSum))
444 fVal = sqrt((fSumSqr - fSum/fCount)/fCount);
445 else
446 fCount = -MAXDOUBLE;
448 break;
449 case SUBTOTAL_FUNC_VAR:
451 if (fCount > 1 && SubTotal::SafeMult(fSum, fSum))
452 fVal = (fSumSqr - fSum/fCount)/(fCount-1.0);
453 else
454 fCount = -MAXDOUBLE;
456 break;
457 case SUBTOTAL_FUNC_VARP:
459 if (fCount > 0 && SubTotal::SafeMult(fSum, fSum))
460 fVal = (fSumSqr - fSum/fCount)/fCount;
461 else
462 fCount = -MAXDOUBLE;
464 break;
465 default:
467 OSL_FAIL("Consoli::CalcData: unknown function");
468 fCount = -MAXDOUBLE;
470 break;
472 return fVal;
475 void ScConsData::AddData( ScDocument* pSrcDoc, SCTAB nTab,
476 SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2 )
478 PutInOrder(nCol1,nCol2);
479 PutInOrder(nRow1,nRow2);
480 if ( nCol2 >= sal::static_int_cast<SCCOL>(nCol1 + nColCount) && !bColByName )
482 OSL_FAIL("range too big");
483 nCol2 = sal::static_int_cast<SCCOL>( nCol1 + nColCount - 1 );
485 if ( nRow2 >= sal::static_int_cast<SCROW>(nRow1 + nRowCount) && !bRowByName )
487 OSL_FAIL("range too big");
488 nRow2 = sal::static_int_cast<SCROW>( nRow1 + nRowCount - 1 );
491 SCCOL nCol;
492 SCROW nRow;
494 // Ecke links oben
496 if ( bColByName && bRowByName )
498 OUString aThisCorner = pSrcDoc->GetString(nCol1, nRow1, nTab);
499 if (bCornerUsed)
501 if (aCornerText != aThisCorner)
502 aCornerText = "";
504 else
506 aCornerText = aThisCorner;
507 bCornerUsed = sal_True;
511 // Titel suchen
513 SCCOL nStartCol = nCol1;
514 SCROW nStartRow = nRow1;
515 if (bColByName) ++nStartRow;
516 if (bRowByName) ++nStartCol;
517 OUString aTitle;
518 SCCOL* pDestCols = NULL;
519 SCROW* pDestRows = NULL;
520 if (bColByName)
522 pDestCols = new SCCOL[nCol2-nStartCol+1];
523 for (nCol=nStartCol; nCol<=nCol2; nCol++)
525 aTitle = pSrcDoc->GetString(nCol, nRow1, nTab);
526 SCCOL nPos = SC_CONS_NOTFOUND;
527 if (!aTitle.isEmpty())
529 bool bFound = false;
530 for (SCSIZE i=0; i<nColCount && !bFound; i++)
531 if ( mpColHeaders[i] == aTitle )
533 nPos = static_cast<SCCOL>(i);
534 bFound = true;
536 OSL_ENSURE(bFound, "column not found");
538 pDestCols[nCol-nStartCol] = nPos;
541 if (bRowByName)
543 pDestRows = new SCROW[nRow2-nStartRow+1];
544 for (nRow=nStartRow; nRow<=nRow2; nRow++)
546 aTitle = pSrcDoc->GetString(nCol1, nRow, nTab);
547 SCROW nPos = SC_CONS_NOTFOUND;
548 if (!aTitle.isEmpty())
550 bool bFound = false;
551 for (SCSIZE i=0; i<nRowCount && !bFound; i++)
552 if ( mpRowHeaders[i] == aTitle )
554 nPos = static_cast<SCROW>(i);
555 bFound = true;
557 OSL_ENSURE(bFound, "row not found");
559 pDestRows[nRow-nStartRow] = nPos;
562 nCol1 = nStartCol;
563 nRow1 = nStartRow;
565 // Daten
567 bool bAnyCell = ( eFunction == SUBTOTAL_FUNC_CNT2 );
568 for (nCol=nCol1; nCol<=nCol2; nCol++)
570 SCCOL nArrX = nCol-nCol1;
571 if (bColByName) nArrX = pDestCols[nArrX];
572 if (nArrX != SC_CONS_NOTFOUND)
574 for (nRow=nRow1; nRow<=nRow2; nRow++)
576 SCROW nArrY = nRow-nRow1;
577 if (bRowByName) nArrY = pDestRows[nArrY];
578 if ( nArrY != SC_CONS_NOTFOUND && (
579 bAnyCell ? pSrcDoc->HasData( nCol, nRow, nTab )
580 : pSrcDoc->HasValueData( nCol, nRow, nTab ) ) )
582 if (bReference)
584 if (ppUsed[nArrX][nArrY])
585 ppRefs[nArrX][nArrY].AddEntry( nCol, nRow, nTab );
586 else
588 ppUsed[nArrX][nArrY] = sal_True;
589 ppRefs[nArrX][nArrY].Init();
590 ppRefs[nArrX][nArrY].AddEntry( nCol, nRow, nTab );
593 else
595 double nVal;
596 pSrcDoc->GetValue( nCol, nRow, nTab, nVal );
597 if (ppUsed[nArrX][nArrY])
598 lcl_UpdateArray( eFunction, ppCount[nArrX][nArrY],
599 ppSum[nArrX][nArrY], ppSumSqr[nArrX][nArrY],
600 nVal);
601 else
603 ppUsed[nArrX][nArrY] = sal_True;
604 lcl_InitArray( eFunction, ppCount[nArrX][nArrY],
605 ppSum[nArrX][nArrY],
606 ppSumSqr[nArrX][nArrY], nVal );
614 delete[] pDestCols;
615 delete[] pDestRows;
618 // vorher testen, wieviele Zeilen eingefuegt werden (fuer Undo)
620 SCROW ScConsData::GetInsertCount() const
622 SCROW nInsert = 0;
623 SCSIZE nArrX;
624 SCSIZE nArrY;
625 if ( ppRefs && ppUsed )
627 for (nArrY=0; nArrY<nRowCount; nArrY++)
629 SCSIZE nNeeded = 0;
630 for (nArrX=0; nArrX<nColCount; nArrX++)
631 if (ppUsed[nArrX][nArrY])
632 nNeeded = std::max( nNeeded, ppRefs[nArrX][nArrY].GetCount() );
634 nInsert += nNeeded;
637 return nInsert;
640 // fertige Daten ins Dokument schreiben
641 //! optimieren nach Spalten?
643 void ScConsData::OutputToDocument( ScDocument* pDestDoc, SCCOL nCol, SCROW nRow, SCTAB nTab )
645 OpCode eOpCode = eOpCodeTable[eFunction];
647 SCSIZE nArrX;
648 SCSIZE nArrY;
650 // Ecke links oben
652 if ( bColByName && bRowByName && !aCornerText.isEmpty() )
653 pDestDoc->SetString( nCol, nRow, nTab, aCornerText );
655 // Titel
657 SCCOL nStartCol = nCol;
658 SCROW nStartRow = nRow;
659 if (bColByName) ++nStartRow;
660 if (bRowByName) ++nStartCol;
662 if (bColByName)
663 for (SCSIZE i=0; i<nColCount; i++)
664 pDestDoc->SetString( sal::static_int_cast<SCCOL>(nStartCol+i), nRow, nTab, mpColHeaders[i] );
665 if (bRowByName)
666 for (SCSIZE j=0; j<nRowCount; j++)
667 pDestDoc->SetString( nCol, sal::static_int_cast<SCROW>(nStartRow+j), nTab, mpRowHeaders[j] );
669 nCol = nStartCol;
670 nRow = nStartRow;
672 // Daten
674 if ( ppCount && ppUsed ) // Werte direkt einfuegen
676 for (nArrX=0; nArrX<nColCount; nArrX++)
677 for (nArrY=0; nArrY<nRowCount; nArrY++)
678 if (ppUsed[nArrX][nArrY])
680 double fVal = lcl_CalcData( eFunction, ppCount[nArrX][nArrY],
681 ppSum[nArrX][nArrY],
682 ppSumSqr[nArrX][nArrY]);
683 if (ppCount[nArrX][nArrY] < 0.0)
684 pDestDoc->SetError( sal::static_int_cast<SCCOL>(nCol+nArrX),
685 sal::static_int_cast<SCROW>(nRow+nArrY), nTab, errNoValue );
686 else
687 pDestDoc->SetValue( sal::static_int_cast<SCCOL>(nCol+nArrX),
688 sal::static_int_cast<SCROW>(nRow+nArrY), nTab, fVal );
692 if ( ppRefs && ppUsed ) // Referenzen einfuegen
694 //! unterscheiden, ob nach Kategorien aufgeteilt
695 OUString aString;
697 ScSingleRefData aSRef; // Daten fuer Referenz-Formelzellen
698 aSRef.InitFlags(); // This reference is absolute at all times.
699 aSRef.SetFlag3D(true);
701 ScComplexRefData aCRef; // Daten fuer Summen-Zellen
702 aCRef.InitFlags();
703 aCRef.Ref1.SetColRel(sal_True); aCRef.Ref1.SetRowRel(sal_True); aCRef.Ref1.SetTabRel(sal_True);
704 aCRef.Ref2.SetColRel(sal_True); aCRef.Ref2.SetRowRel(sal_True); aCRef.Ref2.SetTabRel(sal_True);
706 for (nArrY=0; nArrY<nRowCount; nArrY++)
708 SCSIZE nNeeded = 0;
709 for (nArrX=0; nArrX<nColCount; nArrX++)
710 if (ppUsed[nArrX][nArrY])
711 nNeeded = std::max( nNeeded, ppRefs[nArrX][nArrY].GetCount() );
713 if (nNeeded)
715 pDestDoc->InsertRow( 0,nTab, MAXCOL,nTab, nRow+nArrY, nNeeded );
717 for (nArrX=0; nArrX<nColCount; nArrX++)
718 if (ppUsed[nArrX][nArrY])
720 ScReferenceList& rList = ppRefs[nArrX][nArrY];
721 SCSIZE nCount = rList.GetCount();
722 if (nCount)
724 for (SCSIZE nPos=0; nPos<nCount; nPos++)
726 ScReferenceEntry aRef = rList.GetEntry(nPos);
727 if (aRef.nTab != SC_CONS_NOTFOUND)
729 // Referenz einfuegen (absolut, 3d)
731 aSRef.SetAddress(ScAddress(aRef.nCol,aRef.nRow,aRef.nTab), ScAddress());
733 ScTokenArray aRefArr;
734 aRefArr.AddSingleReference(aSRef);
735 aRefArr.AddOpCode(ocStop);
736 ScAddress aDest( sal::static_int_cast<SCCOL>(nCol+nArrX),
737 sal::static_int_cast<SCROW>(nRow+nArrY+nPos), nTab );
738 ScFormulaCell* pCell = new ScFormulaCell(pDestDoc, aDest, aRefArr);
739 pDestDoc->SetFormulaCell(aDest, pCell);
743 // Summe einfuegen (relativ, nicht 3d)
745 ScAddress aDest( sal::static_int_cast<SCCOL>(nCol+nArrX),
746 sal::static_int_cast<SCROW>(nRow+nArrY+nNeeded), nTab );
748 ScRange aRange(sal::static_int_cast<SCCOL>(nCol+nArrX), nRow+nArrY, nTab);
749 aRange.aEnd.SetRow(nRow+nArrY+nNeeded-1);
750 aCRef.SetRange(aRange, aDest);
752 ScTokenArray aArr;
753 aArr.AddOpCode(eOpCode); // ausgewaehlte Funktion
754 aArr.AddOpCode(ocOpen);
755 aArr.AddDoubleReference(aCRef);
756 aArr.AddOpCode(ocClose);
757 aArr.AddOpCode(ocStop);
758 ScFormulaCell* pCell = new ScFormulaCell(pDestDoc, aDest, aArr);
759 pDestDoc->SetFormulaCell(aDest, pCell);
763 // Gliederung einfuegen
765 ScOutlineArray* pOutArr = pDestDoc->GetOutlineTable( nTab, sal_True )->GetRowArray();
766 SCROW nOutStart = nRow+nArrY;
767 SCROW nOutEnd = nRow+nArrY+nNeeded-1;
768 bool bSize = false;
769 pOutArr->Insert( nOutStart, nOutEnd, bSize );
770 for (SCROW nOutRow=nOutStart; nOutRow<=nOutEnd; nOutRow++)
771 pDestDoc->ShowRow( nOutRow, nTab, false );
772 pDestDoc->SetDrawPageSize(nTab);
773 pDestDoc->UpdateOutlineRow( nOutStart, nOutEnd, nTab, false );
775 // Zwischentitel
777 if (ppTitlePos && mpTitles && mpRowHeaders)
779 OUString aDelim( " / " );
780 for (SCSIZE nPos=0; nPos<nDataCount; nPos++)
782 SCSIZE nTPos = ppTitlePos[nArrY][nPos];
783 bool bDo = true;
784 if (nPos+1<nDataCount)
785 if (ppTitlePos[nArrY][nPos+1] == nTPos)
786 bDo = false; // leer
787 if ( bDo && nTPos < nNeeded )
789 aString = mpRowHeaders[nArrY];
790 aString += aDelim;
791 aString += mpTitles[nPos];
792 pDestDoc->SetString( nCol-1, nRow+nArrY+nTPos, nTab, aString );
797 nRow += nNeeded;
803 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */