diff options
Diffstat (limited to 'sc/source/core/tool/consoli.cxx')
-rw-r--r-- | sc/source/core/tool/consoli.cxx | 858 |
1 files changed, 858 insertions, 0 deletions
diff --git a/sc/source/core/tool/consoli.cxx b/sc/source/core/tool/consoli.cxx new file mode 100644 index 000000000000..addd92082cfd --- /dev/null +++ b/sc/source/core/tool/consoli.cxx @@ -0,0 +1,858 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" + + + +// INCLUDE --------------------------------------------------------------- + +#include <tools/debug.hxx> + +#include "consoli.hxx" +#include "document.hxx" +#include "olinetab.hxx" +#include "globstr.hrc" +#include "subtotal.hxx" +#include "formula/errorcodes.hxx" +#include "cell.hxx" + +#include <math.h> +#include <string.h> + +#define SC_CONS_NOTFOUND -1 + +// STATIC DATA ----------------------------------------------------------- + +/* Strings bei Gelegenheit ganz raus... +static USHORT nFuncRes[] = { // Reihenfolge wie bei enum ScSubTotalFunc + 0, // none + STR_PIVOTFUNC_AVG, + STR_PIVOTFUNC_COUNT, + STR_PIVOTFUNC_COUNT2, + STR_PIVOTFUNC_MAX, + STR_PIVOTFUNC_MIN, + STR_PIVOTFUNC_PROD, + STR_PIVOTFUNC_STDDEV, + STR_PIVOTFUNC_STDDEV2, + STR_PIVOTFUNC_SUM, + STR_PIVOTFUNC_VAR, + STR_PIVOTFUNC_VAR2 }; +*/ + +static OpCode eOpCodeTable[] = { // Reihenfolge wie bei enum ScSubTotalFunc + ocBad, // none + ocAverage, + ocCount, + ocCount2, + ocMax, + ocMin, + ocProduct, + ocStDev, + ocStDevP, + ocSum, + ocVar, + ocVarP }; + +// ----------------------------------------------------------------------- + +void ScReferenceList::AddEntry( SCCOL nCol, SCROW nRow, SCTAB nTab ) +{ + ScReferenceEntry* pOldData = pData; + pData = new ScReferenceEntry[ nFullSize+1 ]; + if (pOldData) + { + memmove( pData, pOldData, nCount * sizeof(ScReferenceEntry) ); + delete[] pOldData; + } + while (nCount < nFullSize) + { + pData[nCount].nCol = SC_CONS_NOTFOUND; + pData[nCount].nRow = SC_CONS_NOTFOUND; + pData[nCount].nTab = SC_CONS_NOTFOUND; + ++nCount; + } + pData[nCount].nCol = nCol; + pData[nCount].nRow = nRow; + pData[nCount].nTab = nTab; + ++nCount; + nFullSize = nCount; +} + +template< typename T > +void lcl_AddString( String**& pData, T& nCount, const String& rInsert ) +{ + String** pOldData = pData; + pData = new String*[ nCount+1 ]; + if (pOldData) + { + memmove( pData, pOldData, nCount * sizeof(String*) ); + delete[] pOldData; + } + pData[nCount] = new String(rInsert); + ++nCount; +} + +// ----------------------------------------------------------------------- + +ScConsData::ScConsData() : + eFunction(SUBTOTAL_FUNC_SUM), + bReference(FALSE), + bColByName(FALSE), + bRowByName(FALSE), + bSubTitles(FALSE), + nColCount(0), + nRowCount(0), + ppUsed(NULL), + ppSum(NULL), + ppCount(NULL), + ppSumSqr(NULL), + ppRefs(NULL), + ppColHeaders(NULL), + ppRowHeaders(NULL), + nDataCount(0), + nTitleCount(0), + ppTitles(NULL), + ppTitlePos(NULL), + bCornerUsed(FALSE) +{ +} + +ScConsData::~ScConsData() +{ + DeleteData(); +} + + +#define DELETEARR(ppArray,nCount) \ +{ \ + ULONG i; \ + if (ppArray) \ + for(i=0; i<nCount; i++) \ + delete[] ppArray[i]; \ + delete[] ppArray; \ + ppArray = NULL; \ +} + +#define DELETESTR(ppArray,nCount) \ +{ \ + ULONG i; \ + if (ppArray) \ + for(i=0; i<nCount; i++) \ + delete ppArray[i]; \ + delete[] ppArray; \ + ppArray = NULL; \ +} + +void ScConsData::DeleteData() +{ + if (ppRefs) + { + for (SCSIZE i=0; i<nColCount; i++) + { + for (SCSIZE j=0; j<nRowCount; j++) + if (ppUsed[i][j]) + ppRefs[i][j].Clear(); + delete[] ppRefs[i]; + } + delete[] ppRefs; + ppRefs = NULL; + } + +// DELETEARR( ppData1, nColCount ); +// DELETEARR( ppData2, nColCount ); + DELETEARR( ppCount, nColCount ); + DELETEARR( ppSum, nColCount ); + DELETEARR( ppSumSqr,nColCount ); + DELETEARR( ppUsed, nColCount ); // erst nach ppRefs !!! + DELETEARR( ppTitlePos, nRowCount ); + DELETESTR( ppColHeaders, nColCount ); + DELETESTR( ppRowHeaders, nRowCount ); + DELETESTR( ppTitles, nTitleCount ); + nTitleCount = 0; + nDataCount = 0; + + if (bColByName) nColCount = 0; // sonst stimmt ppColHeaders nicht + if (bRowByName) nRowCount = 0; + + bCornerUsed = FALSE; + aCornerText.Erase(); +} + +#undef DELETEARR +#undef DELETESTR + +void ScConsData::InitData( BOOL bDelete ) +{ + if (bDelete) + DeleteData(); + + if (bReference && nColCount && !ppRefs) + { + ppRefs = new ScReferenceList*[nColCount]; + for (SCSIZE i=0; i<nColCount; i++) + ppRefs[i] = new ScReferenceList[nRowCount]; + } + else if (nColCount && !ppCount) + { + ppCount = new double*[nColCount]; + ppSum = new double*[nColCount]; + ppSumSqr = new double*[nColCount]; + for (SCSIZE i=0; i<nColCount; i++) + { + ppCount[i] = new double[nRowCount]; + ppSum[i] = new double[nRowCount]; + ppSumSqr[i] = new double[nRowCount]; + } + } + + if (nColCount && !ppUsed) + { + ppUsed = new BOOL*[nColCount]; + for (SCSIZE i=0; i<nColCount; i++) + { + ppUsed[i] = new BOOL[nRowCount]; + memset( ppUsed[i], 0, nRowCount * sizeof(BOOL) ); + } + } + + if (nRowCount && nDataCount && !ppTitlePos) + { + ppTitlePos = new SCSIZE*[nRowCount]; + for (SCSIZE i=0; i<nRowCount; i++) + { + ppTitlePos[i] = new SCSIZE[nDataCount]; + memset( ppTitlePos[i], 0, nDataCount * sizeof(SCSIZE) ); //! unnoetig ? + } + } + + // CornerText: einzelner String +} + +void ScConsData::DoneFields() +{ + InitData(FALSE); +} + +void ScConsData::SetSize( SCCOL nCols, SCROW nRows ) +{ + DeleteData(); + nColCount = static_cast<SCSIZE>(nCols); + nRowCount = static_cast<SCSIZE>(nRows); +} + +void ScConsData::GetSize( SCCOL& rCols, SCROW& rRows ) const +{ + rCols = static_cast<SCCOL>(nColCount); + rRows = static_cast<SCROW>(nRowCount); +} + +void ScConsData::SetFlags( ScSubTotalFunc eFunc, BOOL bColName, BOOL bRowName, BOOL bRef ) +{ + DeleteData(); + bReference = bRef; + bColByName = bColName; + if (bColName) nColCount = 0; + bRowByName = bRowName; + if (bRowName) nRowCount = 0; + eFunction = eFunc; +} + +void ScConsData::AddFields( ScDocument* pSrcDoc, SCTAB nTab, + SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2 ) +{ + ++nDataCount; + + String aTitle; + + SCCOL nStartCol = nCol1; + SCROW nStartRow = nRow1; + if (bColByName) ++nStartRow; + if (bRowByName) ++nStartCol; + + if (bColByName) + { + for (SCCOL nCol=nStartCol; nCol<=nCol2; nCol++) + { + pSrcDoc->GetString( nCol, nRow1, nTab, aTitle ); + if (aTitle.Len()) + { + BOOL bFound = FALSE; + for (SCSIZE i=0; i<nColCount && !bFound; i++) + if ( *ppColHeaders[i] == aTitle ) + bFound = TRUE; + if (!bFound) + lcl_AddString( ppColHeaders, nColCount, aTitle ); + } + } + } + + if (bRowByName) + { + for (SCROW nRow=nStartRow; nRow<=nRow2; nRow++) + { + pSrcDoc->GetString( nCol1, nRow, nTab, aTitle ); + if (aTitle.Len()) + { + BOOL bFound = FALSE; + for (SCSIZE i=0; i<nRowCount && !bFound; i++) + if ( *ppRowHeaders[i] == aTitle ) + bFound = TRUE; + if (!bFound) + lcl_AddString( ppRowHeaders, nRowCount, aTitle ); + } + } + } +} + +void ScConsData::AddName( const String& rName ) +{ + SCSIZE nArrX; + SCSIZE nArrY; + + if (bReference) + { + lcl_AddString( ppTitles, nTitleCount, rName ); + + for (nArrY=0; nArrY<nRowCount; nArrY++) + { + // Daten auf gleiche Laenge bringen + + SCSIZE nMax = 0; + for (nArrX=0; nArrX<nColCount; nArrX++) + if (ppUsed[nArrX][nArrY]) + nMax = Max( nMax, ppRefs[nArrX][nArrY].GetCount() ); + + for (nArrX=0; nArrX<nColCount; nArrX++) + { + if (!ppUsed[nArrX][nArrY]) + { + ppUsed[nArrX][nArrY] = TRUE; + ppRefs[nArrX][nArrY].Init(); + } + ppRefs[nArrX][nArrY].SetFullSize(nMax); + } + + // Positionen eintragen + + if (ppTitlePos) + if (nTitleCount < nDataCount) + ppTitlePos[nArrY][nTitleCount] = nMax; + } + } +} + + // rCount < 0 <=> Fehler aufgetreten + +void lcl_UpdateArray( ScSubTotalFunc eFunc, + double& rCount, double& rSum, double& rSumSqr, double nVal ) +{ + if (rCount < 0.0) + return; + switch (eFunc) + { + case SUBTOTAL_FUNC_SUM: + if (!SubTotal::SafePlus(rSum, nVal)) + rCount = -MAXDOUBLE; + break; + case SUBTOTAL_FUNC_PROD: + if (!SubTotal::SafeMult(rSum, nVal)) + rCount = -MAXDOUBLE; + break; + case SUBTOTAL_FUNC_CNT: + case SUBTOTAL_FUNC_CNT2: + rCount += 1.0; + break; + case SUBTOTAL_FUNC_AVE: + if (!SubTotal::SafePlus(rSum, nVal)) + rCount = -MAXDOUBLE; + else + rCount += 1.0; + break; + case SUBTOTAL_FUNC_MAX: + if (nVal > rSum) + rSum = nVal; + break; + case SUBTOTAL_FUNC_MIN: + if (nVal < rSum) + rSum = nVal; + break; + case SUBTOTAL_FUNC_STD: + case SUBTOTAL_FUNC_STDP: + case SUBTOTAL_FUNC_VAR: + case SUBTOTAL_FUNC_VARP: + { + BOOL bOk = SubTotal::SafePlus(rSum, nVal); + bOk = bOk && SubTotal::SafeMult(nVal, nVal); + bOk = bOk && SubTotal::SafePlus(rSumSqr, nVal); + if (!bOk) + rCount = -MAXDOUBLE; + else + rCount += 1.0; + break; + } + default: + { + // added to avoid warnings + } + } +} + +void lcl_InitArray( ScSubTotalFunc eFunc, + double& rCount, double& rSum, double& rSumSqr, double nVal ) +{ + rCount = 1.0; + switch (eFunc) + { + case SUBTOTAL_FUNC_SUM: + case SUBTOTAL_FUNC_MAX: + case SUBTOTAL_FUNC_MIN: + case SUBTOTAL_FUNC_PROD: + case SUBTOTAL_FUNC_AVE: + rSum = nVal; + break; + case SUBTOTAL_FUNC_STD: + case SUBTOTAL_FUNC_STDP: + case SUBTOTAL_FUNC_VAR: + case SUBTOTAL_FUNC_VARP: + { + rSum = nVal; + BOOL bOk = SubTotal::SafeMult(nVal, nVal); + if (bOk) + rSumSqr = nVal; + else + rCount = -MAXDOUBLE; + } + break; + default: + break; + } +} + +double lcl_CalcData( ScSubTotalFunc eFunc, + double fCount, double fSum, double fSumSqr) +{ + if (fCount < 0.0) + return 0.0; + double fVal = 0.0; + switch (eFunc) + { + case SUBTOTAL_FUNC_CNT: + case SUBTOTAL_FUNC_CNT2: + fVal = fCount; + break; + case SUBTOTAL_FUNC_SUM: + case SUBTOTAL_FUNC_MAX: + case SUBTOTAL_FUNC_MIN: + case SUBTOTAL_FUNC_PROD: + fVal = fSum; + break; + case SUBTOTAL_FUNC_AVE: + if (fCount > 0.0) + fVal = fSum / fCount; + else + fCount = -MAXDOUBLE; + break; + case SUBTOTAL_FUNC_STD: + { + if (fCount > 1 && SubTotal::SafeMult(fSum, fSum)) + fVal = sqrt((fSumSqr - fSum/fCount)/(fCount-1.0)); + else + fCount = -MAXDOUBLE; + } + break; + case SUBTOTAL_FUNC_STDP: + { + if (fCount > 0 && SubTotal::SafeMult(fSum, fSum)) + fVal = sqrt((fSumSqr - fSum/fCount)/fCount); + else + fCount = -MAXDOUBLE; + } + break; + case SUBTOTAL_FUNC_VAR: + { + if (fCount > 1 && SubTotal::SafeMult(fSum, fSum)) + fVal = (fSumSqr - fSum/fCount)/(fCount-1.0); + else + fCount = -MAXDOUBLE; + } + break; + case SUBTOTAL_FUNC_VARP: + { + if (fCount > 0 && SubTotal::SafeMult(fSum, fSum)) + fVal = (fSumSqr - fSum/fCount)/fCount; + else + fCount = -MAXDOUBLE; + } + break; + default: + { + DBG_ERROR("unbekannte Funktion bei Consoli::CalcData"); + fCount = -MAXDOUBLE; + } + break; + } + return fVal; +} + +void ScConsData::AddData( ScDocument* pSrcDoc, SCTAB nTab, + SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2 ) +{ + PutInOrder(nCol1,nCol2); + PutInOrder(nRow1,nRow2); + if ( nCol2 >= sal::static_int_cast<SCCOL>(nCol1 + nColCount) && !bColByName ) + { + DBG_ASSERT(0,"Bereich zu gross"); + nCol2 = sal::static_int_cast<SCCOL>( nCol1 + nColCount - 1 ); + } + if ( nRow2 >= sal::static_int_cast<SCROW>(nRow1 + nRowCount) && !bRowByName ) + { + DBG_ASSERT(0,"Bereich zu gross"); + nRow2 = sal::static_int_cast<SCROW>( nRow1 + nRowCount - 1 ); + } + + SCCOL nCol; + SCROW nRow; + + // Ecke links oben + + if ( bColByName && bRowByName ) + { + String aThisCorner; + pSrcDoc->GetString(nCol1,nRow1,nTab,aThisCorner); + if (bCornerUsed) + { + if (aCornerText != aThisCorner) + aCornerText.Erase(); + } + else + { + aCornerText = aThisCorner; + bCornerUsed = TRUE; + } + } + + // Titel suchen + + SCCOL nStartCol = nCol1; + SCROW nStartRow = nRow1; + if (bColByName) ++nStartRow; + if (bRowByName) ++nStartCol; + String aTitle; + SCCOL* pDestCols = NULL; + SCROW* pDestRows = NULL; + if (bColByName) + { + pDestCols = new SCCOL[nCol2-nStartCol+1]; + for (nCol=nStartCol; nCol<=nCol2; nCol++) + { + pSrcDoc->GetString(nCol,nRow1,nTab,aTitle); + SCCOL nPos = SC_CONS_NOTFOUND; + if (aTitle.Len()) + { + BOOL bFound = FALSE; + for (SCSIZE i=0; i<nColCount && !bFound; i++) + if ( *ppColHeaders[i] == aTitle ) + { + nPos = static_cast<SCCOL>(i); + bFound = TRUE; + } + DBG_ASSERT(bFound, "Spalte nicht gefunden"); + } + pDestCols[nCol-nStartCol] = nPos; + } + } + if (bRowByName) + { + pDestRows = new SCROW[nRow2-nStartRow+1]; + for (nRow=nStartRow; nRow<=nRow2; nRow++) + { + pSrcDoc->GetString(nCol1,nRow,nTab,aTitle); + SCROW nPos = SC_CONS_NOTFOUND; + if (aTitle.Len()) + { + BOOL bFound = FALSE; + for (SCSIZE i=0; i<nRowCount && !bFound; i++) + if ( *ppRowHeaders[i] == aTitle ) + { + nPos = static_cast<SCROW>(i); + bFound = TRUE; + } + DBG_ASSERT(bFound, "Zeile nicht gefunden"); + } + pDestRows[nRow-nStartRow] = nPos; + } + } + nCol1 = nStartCol; + nRow1 = nStartRow; + + // Daten + + BOOL bAnyCell = ( eFunction == SUBTOTAL_FUNC_CNT2 ); + for (nCol=nCol1; nCol<=nCol2; nCol++) + { + SCCOL nArrX = nCol-nCol1; + if (bColByName) nArrX = pDestCols[nArrX]; + if (nArrX != SC_CONS_NOTFOUND) + { + for (nRow=nRow1; nRow<=nRow2; nRow++) + { + SCROW nArrY = nRow-nRow1; + if (bRowByName) nArrY = pDestRows[nArrY]; + if ( nArrY != SC_CONS_NOTFOUND && ( + bAnyCell ? pSrcDoc->HasData( nCol, nRow, nTab ) + : pSrcDoc->HasValueData( nCol, nRow, nTab ) ) ) + { + if (bReference) + { + if (ppUsed[nArrX][nArrY]) + ppRefs[nArrX][nArrY].AddEntry( nCol, nRow, nTab ); + else + { + ppUsed[nArrX][nArrY] = TRUE; + ppRefs[nArrX][nArrY].Init(); + ppRefs[nArrX][nArrY].AddEntry( nCol, nRow, nTab ); + } + } + else + { + double nVal; + pSrcDoc->GetValue( nCol, nRow, nTab, nVal ); + if (ppUsed[nArrX][nArrY]) + lcl_UpdateArray( eFunction, ppCount[nArrX][nArrY], + ppSum[nArrX][nArrY], ppSumSqr[nArrX][nArrY], + nVal); + else + { + ppUsed[nArrX][nArrY] = TRUE; + lcl_InitArray( eFunction, ppCount[nArrX][nArrY], + ppSum[nArrX][nArrY], + ppSumSqr[nArrX][nArrY], nVal ); + } + } + } + } + } + } + + delete[] pDestCols; + delete[] pDestRows; +} + +// vorher testen, wieviele Zeilen eingefuegt werden (fuer Undo) + +SCROW ScConsData::GetInsertCount() const +{ + SCROW nInsert = 0; + SCSIZE nArrX; + SCSIZE nArrY; + if ( ppRefs && ppUsed ) + { + for (nArrY=0; nArrY<nRowCount; nArrY++) + { + SCSIZE nNeeded = 0; + for (nArrX=0; nArrX<nColCount; nArrX++) + if (ppUsed[nArrX][nArrY]) + nNeeded = Max( nNeeded, ppRefs[nArrX][nArrY].GetCount() ); + + nInsert += nNeeded; + } + } + return nInsert; +} + +// fertige Daten ins Dokument schreiben +//! optimieren nach Spalten? + +void ScConsData::OutputToDocument( ScDocument* pDestDoc, SCCOL nCol, SCROW nRow, SCTAB nTab ) +{ + OpCode eOpCode = eOpCodeTable[eFunction]; + + SCSIZE nArrX; + SCSIZE nArrY; + + // Ecke links oben + + if ( bColByName && bRowByName && aCornerText.Len() ) + pDestDoc->SetString( nCol, nRow, nTab, aCornerText ); + + // Titel + + SCCOL nStartCol = nCol; + SCROW nStartRow = nRow; + if (bColByName) ++nStartRow; + if (bRowByName) ++nStartCol; + + if (bColByName) + for (SCSIZE i=0; i<nColCount; i++) + pDestDoc->SetString( sal::static_int_cast<SCCOL>(nStartCol+i), nRow, nTab, *ppColHeaders[i] ); + if (bRowByName) + for (SCSIZE j=0; j<nRowCount; j++) + pDestDoc->SetString( nCol, sal::static_int_cast<SCROW>(nStartRow+j), nTab, *ppRowHeaders[j] ); + + nCol = nStartCol; + nRow = nStartRow; + + // Daten + + if ( ppCount && ppUsed ) // Werte direkt einfuegen + { + for (nArrX=0; nArrX<nColCount; nArrX++) + for (nArrY=0; nArrY<nRowCount; nArrY++) + if (ppUsed[nArrX][nArrY]) + { + double fVal = lcl_CalcData( eFunction, ppCount[nArrX][nArrY], + ppSum[nArrX][nArrY], + ppSumSqr[nArrX][nArrY]); + if (ppCount[nArrX][nArrY] < 0.0) + pDestDoc->SetError( sal::static_int_cast<SCCOL>(nCol+nArrX), + sal::static_int_cast<SCROW>(nRow+nArrY), nTab, errNoValue ); + else + pDestDoc->SetValue( sal::static_int_cast<SCCOL>(nCol+nArrX), + sal::static_int_cast<SCROW>(nRow+nArrY), nTab, fVal ); + } + } + + if ( ppRefs && ppUsed ) // Referenzen einfuegen + { + //! unterscheiden, ob nach Kategorien aufgeteilt + String aString; + + ScSingleRefData aSRef; // Daten fuer Referenz-Formelzellen + aSRef.InitFlags(); + aSRef.SetFlag3D(TRUE); + + ScComplexRefData aCRef; // Daten fuer Summen-Zellen + aCRef.InitFlags(); + aCRef.Ref1.SetColRel(TRUE); aCRef.Ref1.SetRowRel(TRUE); aCRef.Ref1.SetTabRel(TRUE); + aCRef.Ref2.SetColRel(TRUE); aCRef.Ref2.SetRowRel(TRUE); aCRef.Ref2.SetTabRel(TRUE); + + for (nArrY=0; nArrY<nRowCount; nArrY++) + { + SCSIZE nNeeded = 0; + for (nArrX=0; nArrX<nColCount; nArrX++) + if (ppUsed[nArrX][nArrY]) + nNeeded = Max( nNeeded, ppRefs[nArrX][nArrY].GetCount() ); + + if (nNeeded) + { + pDestDoc->InsertRow( 0,nTab, MAXCOL,nTab, nRow+nArrY, nNeeded ); + + for (nArrX=0; nArrX<nColCount; nArrX++) + if (ppUsed[nArrX][nArrY]) + { + ScReferenceList& rList = ppRefs[nArrX][nArrY]; + SCSIZE nCount = rList.GetCount(); + if (nCount) + { + for (SCSIZE nPos=0; nPos<nCount; nPos++) + { + ScReferenceEntry aRef = rList.GetEntry(nPos); + if (aRef.nTab != SC_CONS_NOTFOUND) + { + // Referenz einfuegen (absolut, 3d) + + aSRef.nCol = aRef.nCol; + aSRef.nRow = aRef.nRow; + aSRef.nTab = aRef.nTab; + + ScTokenArray aRefArr; + aRefArr.AddSingleReference(aSRef); + aRefArr.AddOpCode(ocStop); + ScAddress aDest( sal::static_int_cast<SCCOL>(nCol+nArrX), + sal::static_int_cast<SCROW>(nRow+nArrY+nPos), nTab ); + ScBaseCell* pCell = new ScFormulaCell( pDestDoc, aDest, &aRefArr ); + pDestDoc->PutCell( aDest.Col(), aDest.Row(), aDest.Tab(), pCell ); + } + } + + // Summe einfuegen (relativ, nicht 3d) + + ScAddress aDest( sal::static_int_cast<SCCOL>(nCol+nArrX), + sal::static_int_cast<SCROW>(nRow+nArrY+nNeeded), nTab ); + + aCRef.Ref1.nTab = aCRef.Ref2.nTab = nTab; + aCRef.Ref1.nCol = aCRef.Ref2.nCol = sal::static_int_cast<SCsCOL>( nCol+nArrX ); + aCRef.Ref1.nRow = nRow+nArrY; + aCRef.Ref2.nRow = nRow+nArrY+nNeeded-1; + aCRef.CalcRelFromAbs( aDest ); + + ScTokenArray aArr; + aArr.AddOpCode(eOpCode); // ausgewaehlte Funktion + aArr.AddOpCode(ocOpen); + aArr.AddDoubleReference(aCRef); + aArr.AddOpCode(ocClose); + aArr.AddOpCode(ocStop); + ScBaseCell* pCell = new ScFormulaCell( pDestDoc, aDest, &aArr ); + pDestDoc->PutCell( aDest.Col(), aDest.Row(), aDest.Tab(), pCell ); + } + } + + // Gliederung einfuegen + + ScOutlineArray* pOutArr = pDestDoc->GetOutlineTable( nTab, TRUE )->GetRowArray(); + SCROW nOutStart = nRow+nArrY; + SCROW nOutEnd = nRow+nArrY+nNeeded-1; + BOOL bSize = FALSE; + pOutArr->Insert( nOutStart, nOutEnd, bSize ); + for (SCROW nOutRow=nOutStart; nOutRow<=nOutEnd; nOutRow++) + pDestDoc->ShowRow( nOutRow, nTab, FALSE ); + pDestDoc->UpdateOutlineRow( nOutStart, nOutEnd, nTab, FALSE ); + + // Zwischentitel + + if (ppTitlePos && ppTitles && ppRowHeaders) + { + String aDelim( RTL_CONSTASCII_USTRINGPARAM(" / ") ); + for (SCSIZE nPos=0; nPos<nDataCount; nPos++) + { + SCSIZE nTPos = ppTitlePos[nArrY][nPos]; + BOOL bDo = TRUE; + if (nPos+1<nDataCount) + if (ppTitlePos[nArrY][nPos+1] == nTPos) + bDo = FALSE; // leer + if ( bDo && nTPos < nNeeded ) + { + aString = *ppRowHeaders[nArrY]; + aString += aDelim; + aString += *ppTitles[nPos]; + pDestDoc->SetString( nCol-1, nRow+nArrY+nTPos, nTab, aString ); + } + } + } + + nRow += nNeeded; + } + } + } +} + + + + + |