summaryrefslogtreecommitdiff
path: root/sc/source/core/tool/consoli.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'sc/source/core/tool/consoli.cxx')
-rw-r--r--sc/source/core/tool/consoli.cxx858
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;
+ }
+ }
+ }
+}
+
+
+
+
+