merge the formfield patch from ooo-build
[ooovba.git] / sc / source / core / tool / consoli.cxx
blob026160ba7563399c60c84c3fd2ea0a94367657c5
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: consoli.cxx,v $
10 * $Revision: 1.8 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sc.hxx"
36 // INCLUDE ---------------------------------------------------------------
38 #include <tools/debug.hxx>
40 #include "consoli.hxx"
41 #include "document.hxx"
42 #include "olinetab.hxx"
43 #include "globstr.hrc"
44 #include "subtotal.hxx"
45 #include "formula/errorcodes.hxx"
46 #include "cell.hxx"
48 #include <math.h>
49 #include <string.h>
51 #define SC_CONS_NOTFOUND -1
53 // STATIC DATA -----------------------------------------------------------
55 /* Strings bei Gelegenheit ganz raus...
56 static USHORT nFuncRes[] = { // Reihenfolge wie bei enum ScSubTotalFunc
57 0, // none
58 STR_PIVOTFUNC_AVG,
59 STR_PIVOTFUNC_COUNT,
60 STR_PIVOTFUNC_COUNT2,
61 STR_PIVOTFUNC_MAX,
62 STR_PIVOTFUNC_MIN,
63 STR_PIVOTFUNC_PROD,
64 STR_PIVOTFUNC_STDDEV,
65 STR_PIVOTFUNC_STDDEV2,
66 STR_PIVOTFUNC_SUM,
67 STR_PIVOTFUNC_VAR,
68 STR_PIVOTFUNC_VAR2 };
71 static OpCode eOpCodeTable[] = { // Reihenfolge wie bei enum ScSubTotalFunc
72 ocBad, // none
73 ocAverage,
74 ocCount,
75 ocCount2,
76 ocMax,
77 ocMin,
78 ocProduct,
79 ocStDev,
80 ocStDevP,
81 ocSum,
82 ocVar,
83 ocVarP };
85 // -----------------------------------------------------------------------
87 void ScReferenceList::AddEntry( SCCOL nCol, SCROW nRow, SCTAB nTab )
89 ScReferenceEntry* pOldData = pData;
90 pData = new ScReferenceEntry[ nFullSize+1 ];
91 if (pOldData)
93 memmove( pData, pOldData, nCount * sizeof(ScReferenceEntry) );
94 delete[] pOldData;
96 while (nCount < nFullSize)
98 pData[nCount].nCol = SC_CONS_NOTFOUND;
99 pData[nCount].nRow = SC_CONS_NOTFOUND;
100 pData[nCount].nTab = SC_CONS_NOTFOUND;
101 ++nCount;
103 pData[nCount].nCol = nCol;
104 pData[nCount].nRow = nRow;
105 pData[nCount].nTab = nTab;
106 ++nCount;
107 nFullSize = nCount;
110 template< typename T >
111 void lcl_AddString( String**& pData, T& nCount, const String& rInsert )
113 String** pOldData = pData;
114 pData = new String*[ nCount+1 ];
115 if (pOldData)
117 memmove( pData, pOldData, nCount * sizeof(String*) );
118 delete[] pOldData;
120 pData[nCount] = new String(rInsert);
121 ++nCount;
124 // -----------------------------------------------------------------------
126 ScConsData::ScConsData() :
127 eFunction(SUBTOTAL_FUNC_SUM),
128 bReference(FALSE),
129 bColByName(FALSE),
130 bRowByName(FALSE),
131 bSubTitles(FALSE),
132 nColCount(0),
133 nRowCount(0),
134 ppUsed(NULL),
135 ppSum(NULL),
136 ppCount(NULL),
137 ppSumSqr(NULL),
138 ppRefs(NULL),
139 ppColHeaders(NULL),
140 ppRowHeaders(NULL),
141 nDataCount(0),
142 nTitleCount(0),
143 ppTitles(NULL),
144 ppTitlePos(NULL),
145 bCornerUsed(FALSE)
149 ScConsData::~ScConsData()
151 DeleteData();
155 #define DELETEARR(ppArray,nCount) \
157 ULONG i; \
158 if (ppArray) \
159 for(i=0; i<nCount; i++) \
160 delete[] ppArray[i]; \
161 delete[] ppArray; \
162 ppArray = NULL; \
165 #define DELETESTR(ppArray,nCount) \
167 ULONG i; \
168 if (ppArray) \
169 for(i=0; i<nCount; i++) \
170 delete ppArray[i]; \
171 delete[] ppArray; \
172 ppArray = NULL; \
175 void ScConsData::DeleteData()
177 if (ppRefs)
179 for (SCSIZE i=0; i<nColCount; i++)
181 for (SCSIZE j=0; j<nRowCount; j++)
182 if (ppUsed[i][j])
183 ppRefs[i][j].Clear();
184 delete[] ppRefs[i];
186 delete[] ppRefs;
187 ppRefs = NULL;
190 // DELETEARR( ppData1, nColCount );
191 // DELETEARR( ppData2, nColCount );
192 DELETEARR( ppCount, nColCount );
193 DELETEARR( ppSum, nColCount );
194 DELETEARR( ppSumSqr,nColCount );
195 DELETEARR( ppUsed, nColCount ); // erst nach ppRefs !!!
196 DELETEARR( ppTitlePos, nRowCount );
197 DELETESTR( ppColHeaders, nColCount );
198 DELETESTR( ppRowHeaders, nRowCount );
199 DELETESTR( ppTitles, nTitleCount );
200 nTitleCount = 0;
201 nDataCount = 0;
203 if (bColByName) nColCount = 0; // sonst stimmt ppColHeaders nicht
204 if (bRowByName) nRowCount = 0;
206 bCornerUsed = FALSE;
207 aCornerText.Erase();
210 #undef DELETEARR
211 #undef DELETESTR
213 void ScConsData::InitData( BOOL bDelete )
215 if (bDelete)
216 DeleteData();
218 if (bReference && nColCount && !ppRefs)
220 ppRefs = new ScReferenceList*[nColCount];
221 for (SCSIZE i=0; i<nColCount; i++)
222 ppRefs[i] = new ScReferenceList[nRowCount];
224 else if (nColCount && !ppCount)
226 ppCount = new double*[nColCount];
227 ppSum = new double*[nColCount];
228 ppSumSqr = new double*[nColCount];
229 for (SCSIZE i=0; i<nColCount; i++)
231 ppCount[i] = new double[nRowCount];
232 ppSum[i] = new double[nRowCount];
233 ppSumSqr[i] = new double[nRowCount];
237 if (nColCount && !ppUsed)
239 ppUsed = new BOOL*[nColCount];
240 for (SCSIZE i=0; i<nColCount; i++)
242 ppUsed[i] = new BOOL[nRowCount];
243 memset( ppUsed[i], 0, nRowCount * sizeof(BOOL) );
247 if (nRowCount && nDataCount && !ppTitlePos)
249 ppTitlePos = new SCSIZE*[nRowCount];
250 for (SCSIZE i=0; i<nRowCount; i++)
252 ppTitlePos[i] = new SCSIZE[nDataCount];
253 memset( ppTitlePos[i], 0, nDataCount * sizeof(SCSIZE) ); //! unnoetig ?
257 // CornerText: einzelner String
260 void ScConsData::DoneFields()
262 InitData(FALSE);
265 void ScConsData::SetSize( SCCOL nCols, SCROW nRows )
267 DeleteData();
268 nColCount = static_cast<SCSIZE>(nCols);
269 nRowCount = static_cast<SCSIZE>(nRows);
272 void ScConsData::GetSize( SCCOL& rCols, SCROW& rRows ) const
274 rCols = static_cast<SCCOL>(nColCount);
275 rRows = static_cast<SCROW>(nRowCount);
278 void ScConsData::SetFlags( ScSubTotalFunc eFunc, BOOL bColName, BOOL bRowName, BOOL bRef )
280 DeleteData();
281 bReference = bRef;
282 bColByName = bColName;
283 if (bColName) nColCount = 0;
284 bRowByName = bRowName;
285 if (bRowName) nRowCount = 0;
286 eFunction = eFunc;
289 void ScConsData::AddFields( ScDocument* pSrcDoc, SCTAB nTab,
290 SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2 )
292 ++nDataCount;
294 String aTitle;
296 SCCOL nStartCol = nCol1;
297 SCROW nStartRow = nRow1;
298 if (bColByName) ++nStartRow;
299 if (bRowByName) ++nStartCol;
301 if (bColByName)
303 for (SCCOL nCol=nStartCol; nCol<=nCol2; nCol++)
305 pSrcDoc->GetString( nCol, nRow1, nTab, aTitle );
306 if (aTitle.Len())
308 BOOL bFound = FALSE;
309 for (SCSIZE i=0; i<nColCount && !bFound; i++)
310 if ( *ppColHeaders[i] == aTitle )
311 bFound = TRUE;
312 if (!bFound)
313 lcl_AddString( ppColHeaders, nColCount, aTitle );
318 if (bRowByName)
320 for (SCROW nRow=nStartRow; nRow<=nRow2; nRow++)
322 pSrcDoc->GetString( nCol1, nRow, nTab, aTitle );
323 if (aTitle.Len())
325 BOOL bFound = FALSE;
326 for (SCSIZE i=0; i<nRowCount && !bFound; i++)
327 if ( *ppRowHeaders[i] == aTitle )
328 bFound = TRUE;
329 if (!bFound)
330 lcl_AddString( ppRowHeaders, nRowCount, aTitle );
336 void ScConsData::AddName( const String& rName )
338 SCSIZE nArrX;
339 SCSIZE nArrY;
341 if (bReference)
343 lcl_AddString( ppTitles, nTitleCount, rName );
345 for (nArrY=0; nArrY<nRowCount; nArrY++)
347 // Daten auf gleiche Laenge bringen
349 SCSIZE nMax = 0;
350 for (nArrX=0; nArrX<nColCount; nArrX++)
351 if (ppUsed[nArrX][nArrY])
352 nMax = Max( nMax, ppRefs[nArrX][nArrY].GetCount() );
354 for (nArrX=0; nArrX<nColCount; nArrX++)
356 if (!ppUsed[nArrX][nArrY])
358 ppUsed[nArrX][nArrY] = TRUE;
359 ppRefs[nArrX][nArrY].Init();
361 ppRefs[nArrX][nArrY].SetFullSize(nMax);
364 // Positionen eintragen
366 if (ppTitlePos)
367 if (nTitleCount < nDataCount)
368 ppTitlePos[nArrY][nTitleCount] = nMax;
373 // rCount < 0 <=> Fehler aufgetreten
375 void lcl_UpdateArray( ScSubTotalFunc eFunc,
376 double& rCount, double& rSum, double& rSumSqr, double nVal )
378 if (rCount < 0.0)
379 return;
380 switch (eFunc)
382 case SUBTOTAL_FUNC_SUM:
383 if (!SubTotal::SafePlus(rSum, nVal))
384 rCount = -MAXDOUBLE;
385 break;
386 case SUBTOTAL_FUNC_PROD:
387 if (!SubTotal::SafeMult(rSum, nVal))
388 rCount = -MAXDOUBLE;
389 break;
390 case SUBTOTAL_FUNC_CNT:
391 case SUBTOTAL_FUNC_CNT2:
392 rCount += 1.0;
393 break;
394 case SUBTOTAL_FUNC_AVE:
395 if (!SubTotal::SafePlus(rSum, nVal))
396 rCount = -MAXDOUBLE;
397 else
398 rCount += 1.0;
399 break;
400 case SUBTOTAL_FUNC_MAX:
401 if (nVal > rSum)
402 rSum = nVal;
403 break;
404 case SUBTOTAL_FUNC_MIN:
405 if (nVal < rSum)
406 rSum = nVal;
407 break;
408 case SUBTOTAL_FUNC_STD:
409 case SUBTOTAL_FUNC_STDP:
410 case SUBTOTAL_FUNC_VAR:
411 case SUBTOTAL_FUNC_VARP:
413 BOOL bOk = SubTotal::SafePlus(rSum, nVal);
414 bOk = bOk && SubTotal::SafeMult(nVal, nVal);
415 bOk = bOk && SubTotal::SafePlus(rSumSqr, nVal);
416 if (!bOk)
417 rCount = -MAXDOUBLE;
418 else
419 rCount += 1.0;
420 break;
422 default:
424 // added to avoid warnings
429 void lcl_InitArray( ScSubTotalFunc eFunc,
430 double& rCount, double& rSum, double& rSumSqr, double nVal )
432 rCount = 1.0;
433 switch (eFunc)
435 case SUBTOTAL_FUNC_SUM:
436 case SUBTOTAL_FUNC_MAX:
437 case SUBTOTAL_FUNC_MIN:
438 case SUBTOTAL_FUNC_PROD:
439 case SUBTOTAL_FUNC_AVE:
440 rSum = nVal;
441 break;
442 case SUBTOTAL_FUNC_STD:
443 case SUBTOTAL_FUNC_STDP:
444 case SUBTOTAL_FUNC_VAR:
445 case SUBTOTAL_FUNC_VARP:
447 rSum = nVal;
448 BOOL bOk = SubTotal::SafeMult(nVal, nVal);
449 if (bOk)
450 rSumSqr = nVal;
451 else
452 rCount = -MAXDOUBLE;
454 break;
455 default:
456 break;
460 double lcl_CalcData( ScSubTotalFunc eFunc,
461 double fCount, double fSum, double fSumSqr)
463 if (fCount < 0.0)
464 return 0.0;
465 double fVal = 0.0;
466 switch (eFunc)
468 case SUBTOTAL_FUNC_CNT:
469 case SUBTOTAL_FUNC_CNT2:
470 fVal = fCount;
471 break;
472 case SUBTOTAL_FUNC_SUM:
473 case SUBTOTAL_FUNC_MAX:
474 case SUBTOTAL_FUNC_MIN:
475 case SUBTOTAL_FUNC_PROD:
476 fVal = fSum;
477 break;
478 case SUBTOTAL_FUNC_AVE:
479 if (fCount > 0.0)
480 fVal = fSum / fCount;
481 else
482 fCount = -MAXDOUBLE;
483 break;
484 case SUBTOTAL_FUNC_STD:
486 if (fCount > 1 && SubTotal::SafeMult(fSum, fSum))
487 fVal = sqrt((fSumSqr - fSum/fCount)/(fCount-1.0));
488 else
489 fCount = -MAXDOUBLE;
491 break;
492 case SUBTOTAL_FUNC_STDP:
494 if (fCount > 0 && SubTotal::SafeMult(fSum, fSum))
495 fVal = sqrt((fSumSqr - fSum/fCount)/fCount);
496 else
497 fCount = -MAXDOUBLE;
499 break;
500 case SUBTOTAL_FUNC_VAR:
502 if (fCount > 1 && SubTotal::SafeMult(fSum, fSum))
503 fVal = (fSumSqr - fSum/fCount)/(fCount-1.0);
504 else
505 fCount = -MAXDOUBLE;
507 break;
508 case SUBTOTAL_FUNC_VARP:
510 if (fCount > 0 && SubTotal::SafeMult(fSum, fSum))
511 fVal = (fSumSqr - fSum/fCount)/fCount;
512 else
513 fCount = -MAXDOUBLE;
515 break;
516 default:
518 DBG_ERROR("unbekannte Funktion bei Consoli::CalcData");
519 fCount = -MAXDOUBLE;
521 break;
523 return fVal;
526 void ScConsData::AddData( ScDocument* pSrcDoc, SCTAB nTab,
527 SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2 )
529 PutInOrder(nCol1,nCol2);
530 PutInOrder(nRow1,nRow2);
531 if ( nCol2 >= sal::static_int_cast<SCCOL>(nCol1 + nColCount) && !bColByName )
533 DBG_ASSERT(0,"Bereich zu gross");
534 nCol2 = sal::static_int_cast<SCCOL>( nCol1 + nColCount - 1 );
536 if ( nRow2 >= sal::static_int_cast<SCROW>(nRow1 + nRowCount) && !bRowByName )
538 DBG_ASSERT(0,"Bereich zu gross");
539 nRow2 = sal::static_int_cast<SCROW>( nRow1 + nRowCount - 1 );
542 SCCOL nCol;
543 SCROW nRow;
545 // Ecke links oben
547 if ( bColByName && bRowByName )
549 String aThisCorner;
550 pSrcDoc->GetString(nCol1,nRow1,nTab,aThisCorner);
551 if (bCornerUsed)
553 if (aCornerText != aThisCorner)
554 aCornerText.Erase();
556 else
558 aCornerText = aThisCorner;
559 bCornerUsed = TRUE;
563 // Titel suchen
565 SCCOL nStartCol = nCol1;
566 SCROW nStartRow = nRow1;
567 if (bColByName) ++nStartRow;
568 if (bRowByName) ++nStartCol;
569 String aTitle;
570 SCCOL* pDestCols = NULL;
571 SCROW* pDestRows = NULL;
572 if (bColByName)
574 pDestCols = new SCCOL[nCol2-nStartCol+1];
575 for (nCol=nStartCol; nCol<=nCol2; nCol++)
577 pSrcDoc->GetString(nCol,nRow1,nTab,aTitle);
578 SCCOL nPos = SC_CONS_NOTFOUND;
579 if (aTitle.Len())
581 BOOL bFound = FALSE;
582 for (SCSIZE i=0; i<nColCount && !bFound; i++)
583 if ( *ppColHeaders[i] == aTitle )
585 nPos = static_cast<SCCOL>(i);
586 bFound = TRUE;
588 DBG_ASSERT(bFound, "Spalte nicht gefunden");
590 pDestCols[nCol-nStartCol] = nPos;
593 if (bRowByName)
595 pDestRows = new SCROW[nRow2-nStartRow+1];
596 for (nRow=nStartRow; nRow<=nRow2; nRow++)
598 pSrcDoc->GetString(nCol1,nRow,nTab,aTitle);
599 SCROW nPos = SC_CONS_NOTFOUND;
600 if (aTitle.Len())
602 BOOL bFound = FALSE;
603 for (SCSIZE i=0; i<nRowCount && !bFound; i++)
604 if ( *ppRowHeaders[i] == aTitle )
606 nPos = static_cast<SCROW>(i);
607 bFound = TRUE;
609 DBG_ASSERT(bFound, "Zeile nicht gefunden");
611 pDestRows[nRow-nStartRow] = nPos;
614 nCol1 = nStartCol;
615 nRow1 = nStartRow;
617 // Daten
619 BOOL bAnyCell = ( eFunction == SUBTOTAL_FUNC_CNT2 );
620 for (nCol=nCol1; nCol<=nCol2; nCol++)
622 SCCOL nArrX = nCol-nCol1;
623 if (bColByName) nArrX = pDestCols[nArrX];
624 if (nArrX != SC_CONS_NOTFOUND)
626 for (nRow=nRow1; nRow<=nRow2; nRow++)
628 SCROW nArrY = nRow-nRow1;
629 if (bRowByName) nArrY = pDestRows[nArrY];
630 if ( nArrY != SC_CONS_NOTFOUND && (
631 bAnyCell ? pSrcDoc->HasData( nCol, nRow, nTab )
632 : pSrcDoc->HasValueData( nCol, nRow, nTab ) ) )
634 if (bReference)
636 if (ppUsed[nArrX][nArrY])
637 ppRefs[nArrX][nArrY].AddEntry( nCol, nRow, nTab );
638 else
640 ppUsed[nArrX][nArrY] = TRUE;
641 ppRefs[nArrX][nArrY].Init();
642 ppRefs[nArrX][nArrY].AddEntry( nCol, nRow, nTab );
645 else
647 double nVal;
648 pSrcDoc->GetValue( nCol, nRow, nTab, nVal );
649 if (ppUsed[nArrX][nArrY])
650 lcl_UpdateArray( eFunction, ppCount[nArrX][nArrY],
651 ppSum[nArrX][nArrY], ppSumSqr[nArrX][nArrY],
652 nVal);
653 else
655 ppUsed[nArrX][nArrY] = TRUE;
656 lcl_InitArray( eFunction, ppCount[nArrX][nArrY],
657 ppSum[nArrX][nArrY],
658 ppSumSqr[nArrX][nArrY], nVal );
666 delete[] pDestCols;
667 delete[] pDestRows;
670 // vorher testen, wieviele Zeilen eingefuegt werden (fuer Undo)
672 SCROW ScConsData::GetInsertCount() const
674 SCROW nInsert = 0;
675 SCSIZE nArrX;
676 SCSIZE nArrY;
677 if ( ppRefs && ppUsed )
679 for (nArrY=0; nArrY<nRowCount; nArrY++)
681 SCSIZE nNeeded = 0;
682 for (nArrX=0; nArrX<nColCount; nArrX++)
683 if (ppUsed[nArrX][nArrY])
684 nNeeded = Max( nNeeded, ppRefs[nArrX][nArrY].GetCount() );
686 nInsert += nNeeded;
689 return nInsert;
692 // fertige Daten ins Dokument schreiben
693 //! optimieren nach Spalten?
695 void ScConsData::OutputToDocument( ScDocument* pDestDoc, SCCOL nCol, SCROW nRow, SCTAB nTab )
697 OpCode eOpCode = eOpCodeTable[eFunction];
699 SCSIZE nArrX;
700 SCSIZE nArrY;
702 // Ecke links oben
704 if ( bColByName && bRowByName && aCornerText.Len() )
705 pDestDoc->SetString( nCol, nRow, nTab, aCornerText );
707 // Titel
709 SCCOL nStartCol = nCol;
710 SCROW nStartRow = nRow;
711 if (bColByName) ++nStartRow;
712 if (bRowByName) ++nStartCol;
714 if (bColByName)
715 for (SCSIZE i=0; i<nColCount; i++)
716 pDestDoc->SetString( sal::static_int_cast<SCCOL>(nStartCol+i), nRow, nTab, *ppColHeaders[i] );
717 if (bRowByName)
718 for (SCSIZE j=0; j<nRowCount; j++)
719 pDestDoc->SetString( nCol, sal::static_int_cast<SCROW>(nStartRow+j), nTab, *ppRowHeaders[j] );
721 nCol = nStartCol;
722 nRow = nStartRow;
724 // Daten
726 if ( ppCount && ppUsed ) // Werte direkt einfuegen
728 for (nArrX=0; nArrX<nColCount; nArrX++)
729 for (nArrY=0; nArrY<nRowCount; nArrY++)
730 if (ppUsed[nArrX][nArrY])
732 double fVal = lcl_CalcData( eFunction, ppCount[nArrX][nArrY],
733 ppSum[nArrX][nArrY],
734 ppSumSqr[nArrX][nArrY]);
735 if (ppCount[nArrX][nArrY] < 0.0)
736 pDestDoc->SetError( sal::static_int_cast<SCCOL>(nCol+nArrX),
737 sal::static_int_cast<SCROW>(nRow+nArrY), nTab, errNoValue );
738 else
739 pDestDoc->SetValue( sal::static_int_cast<SCCOL>(nCol+nArrX),
740 sal::static_int_cast<SCROW>(nRow+nArrY), nTab, fVal );
744 if ( ppRefs && ppUsed ) // Referenzen einfuegen
746 //! unterscheiden, ob nach Kategorien aufgeteilt
747 String aString;
749 ScSingleRefData aSRef; // Daten fuer Referenz-Formelzellen
750 aSRef.InitFlags();
751 aSRef.SetFlag3D(TRUE);
753 ScComplexRefData aCRef; // Daten fuer Summen-Zellen
754 aCRef.InitFlags();
755 aCRef.Ref1.SetColRel(TRUE); aCRef.Ref1.SetRowRel(TRUE); aCRef.Ref1.SetTabRel(TRUE);
756 aCRef.Ref2.SetColRel(TRUE); aCRef.Ref2.SetRowRel(TRUE); aCRef.Ref2.SetTabRel(TRUE);
758 for (nArrY=0; nArrY<nRowCount; nArrY++)
760 SCSIZE nNeeded = 0;
761 for (nArrX=0; nArrX<nColCount; nArrX++)
762 if (ppUsed[nArrX][nArrY])
763 nNeeded = Max( nNeeded, ppRefs[nArrX][nArrY].GetCount() );
765 if (nNeeded)
767 pDestDoc->InsertRow( 0,nTab, MAXCOL,nTab, nRow+nArrY, nNeeded );
769 for (nArrX=0; nArrX<nColCount; nArrX++)
770 if (ppUsed[nArrX][nArrY])
772 ScReferenceList& rList = ppRefs[nArrX][nArrY];
773 SCSIZE nCount = rList.GetCount();
774 if (nCount)
776 for (SCSIZE nPos=0; nPos<nCount; nPos++)
778 ScReferenceEntry aRef = rList.GetEntry(nPos);
779 if (aRef.nTab != SC_CONS_NOTFOUND)
781 // Referenz einfuegen (absolut, 3d)
783 aSRef.nCol = aRef.nCol;
784 aSRef.nRow = aRef.nRow;
785 aSRef.nTab = aRef.nTab;
787 ScTokenArray aRefArr;
788 aRefArr.AddSingleReference(aSRef);
789 aRefArr.AddOpCode(ocStop);
790 ScAddress aDest( sal::static_int_cast<SCCOL>(nCol+nArrX),
791 sal::static_int_cast<SCROW>(nRow+nArrY+nPos), nTab );
792 ScBaseCell* pCell = new ScFormulaCell( pDestDoc, aDest, &aRefArr );
793 pDestDoc->PutCell( aDest.Col(), aDest.Row(), aDest.Tab(), pCell );
797 // Summe einfuegen (relativ, nicht 3d)
799 ScAddress aDest( sal::static_int_cast<SCCOL>(nCol+nArrX),
800 sal::static_int_cast<SCROW>(nRow+nArrY+nNeeded), nTab );
802 aCRef.Ref1.nTab = aCRef.Ref2.nTab = nTab;
803 aCRef.Ref1.nCol = aCRef.Ref2.nCol = sal::static_int_cast<SCsCOL>( nCol+nArrX );
804 aCRef.Ref1.nRow = nRow+nArrY;
805 aCRef.Ref2.nRow = nRow+nArrY+nNeeded-1;
806 aCRef.CalcRelFromAbs( aDest );
808 ScTokenArray aArr;
809 aArr.AddOpCode(eOpCode); // ausgewaehlte Funktion
810 aArr.AddOpCode(ocOpen);
811 aArr.AddDoubleReference(aCRef);
812 aArr.AddOpCode(ocClose);
813 aArr.AddOpCode(ocStop);
814 ScBaseCell* pCell = new ScFormulaCell( pDestDoc, aDest, &aArr );
815 pDestDoc->PutCell( aDest.Col(), aDest.Row(), aDest.Tab(), pCell );
819 // Gliederung einfuegen
821 ScOutlineArray* pOutArr = pDestDoc->GetOutlineTable( nTab, TRUE )->GetRowArray();
822 SCROW nOutStart = nRow+nArrY;
823 SCROW nOutEnd = nRow+nArrY+nNeeded-1;
824 BOOL bSize = FALSE;
825 pOutArr->Insert( nOutStart, nOutEnd, bSize );
826 for (SCROW nOutRow=nOutStart; nOutRow<=nOutEnd; nOutRow++)
827 pDestDoc->ShowRow( nOutRow, nTab, FALSE );
828 pDestDoc->UpdateOutlineRow( nOutStart, nOutEnd, nTab, FALSE );
830 // Zwischentitel
832 if (ppTitlePos && ppTitles && ppRowHeaders)
834 String aDelim( RTL_CONSTASCII_USTRINGPARAM(" / ") );
835 for (SCSIZE nPos=0; nPos<nDataCount; nPos++)
837 SCSIZE nTPos = ppTitlePos[nArrY][nPos];
838 BOOL bDo = TRUE;
839 if (nPos+1<nDataCount)
840 if (ppTitlePos[nArrY][nPos+1] == nTPos)
841 bDo = FALSE; // leer
842 if ( bDo && nTPos < nNeeded )
844 aString = *ppRowHeaders[nArrY];
845 aString += aDelim;
846 aString += *ppTitles[nPos];
847 pDestDoc->SetString( nCol-1, nRow+nArrY+nTPos, nTab, aString );
852 nRow += nNeeded;