| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the 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 sal_uInt16 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(sal_False), |
| bColByName(sal_False), |
| bRowByName(sal_False), |
| bSubTitles(sal_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(sal_False) |
| { |
| } |
| |
| ScConsData::~ScConsData() |
| { |
| DeleteData(); |
| } |
| |
| |
| #define DELETEARR(ppArray,nCount) \ |
| { \ |
| sal_uLong i; \ |
| if (ppArray) \ |
| for(i=0; i<nCount; i++) \ |
| delete[] ppArray[i]; \ |
| delete[] ppArray; \ |
| ppArray = NULL; \ |
| } |
| |
| #define DELETESTR(ppArray,nCount) \ |
| { \ |
| sal_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 = sal_False; |
| aCornerText.Erase(); |
| } |
| |
| #undef DELETEARR |
| #undef DELETESTR |
| |
| void ScConsData::InitData( sal_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 sal_Bool*[nColCount]; |
| for (SCSIZE i=0; i<nColCount; i++) |
| { |
| ppUsed[i] = new sal_Bool[nRowCount]; |
| memset( ppUsed[i], 0, nRowCount * sizeof(sal_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(sal_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, sal_Bool bColName, sal_Bool bRowName, sal_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()) |
| { |
| sal_Bool bFound = sal_False; |
| for (SCSIZE i=0; i<nColCount && !bFound; i++) |
| if ( *ppColHeaders[i] == aTitle ) |
| bFound = sal_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()) |
| { |
| sal_Bool bFound = sal_False; |
| for (SCSIZE i=0; i<nRowCount && !bFound; i++) |
| if ( *ppRowHeaders[i] == aTitle ) |
| bFound = sal_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] = sal_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: |
| { |
| sal_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; |
| sal_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 = sal_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()) |
| { |
| sal_Bool bFound = sal_False; |
| for (SCSIZE i=0; i<nColCount && !bFound; i++) |
| if ( *ppColHeaders[i] == aTitle ) |
| { |
| nPos = static_cast<SCCOL>(i); |
| bFound = sal_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()) |
| { |
| sal_Bool bFound = sal_False; |
| for (SCSIZE i=0; i<nRowCount && !bFound; i++) |
| if ( *ppRowHeaders[i] == aTitle ) |
| { |
| nPos = static_cast<SCROW>(i); |
| bFound = sal_True; |
| } |
| DBG_ASSERT(bFound, "Zeile nicht gefunden"); |
| } |
| pDestRows[nRow-nStartRow] = nPos; |
| } |
| } |
| nCol1 = nStartCol; |
| nRow1 = nStartRow; |
| |
| // Daten |
| |
| sal_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] = sal_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] = sal_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(sal_True); |
| |
| ScComplexRefData aCRef; // Daten fuer Summen-Zellen |
| aCRef.InitFlags(); |
| aCRef.Ref1.SetColRel(sal_True); aCRef.Ref1.SetRowRel(sal_True); aCRef.Ref1.SetTabRel(sal_True); |
| aCRef.Ref2.SetColRel(sal_True); aCRef.Ref2.SetRowRel(sal_True); aCRef.Ref2.SetTabRel(sal_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, sal_True )->GetRowArray(); |
| SCROW nOutStart = nRow+nArrY; |
| SCROW nOutEnd = nRow+nArrY+nNeeded-1; |
| sal_Bool bSize = sal_False; |
| pOutArr->Insert( nOutStart, nOutEnd, bSize ); |
| for (SCROW nOutRow=nOutStart; nOutRow<=nOutEnd; nOutRow++) |
| pDestDoc->ShowRow( nOutRow, nTab, sal_False ); |
| pDestDoc->UpdateOutlineRow( nOutStart, nOutEnd, nTab, sal_False ); |
| |
| // Zwischentitel |
| |
| if (ppTitlePos && ppTitles && ppRowHeaders) |
| { |
| String aDelim( RTL_CONSTASCII_USTRINGPARAM(" / ") ); |
| for (SCSIZE nPos=0; nPos<nDataCount; nPos++) |
| { |
| SCSIZE nTPos = ppTitlePos[nArrY][nPos]; |
| sal_Bool bDo = sal_True; |
| if (nPos+1<nDataCount) |
| if (ppTitlePos[nArrY][nPos+1] == nTPos) |
| bDo = sal_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; |
| } |
| } |
| } |
| } |
| |
| |
| |
| |
| |