summaryrefslogtreecommitdiff
path: root/sc/source/core/tool/chartarr.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'sc/source/core/tool/chartarr.cxx')
-rw-r--r--sc/source/core/tool/chartarr.cxx615
1 files changed, 615 insertions, 0 deletions
diff --git a/sc/source/core/tool/chartarr.cxx b/sc/source/core/tool/chartarr.cxx
new file mode 100644
index 000000000000..573763141b18
--- /dev/null
+++ b/sc/source/core/tool/chartarr.cxx
@@ -0,0 +1,615 @@
+/*************************************************************************
+ *
+ * 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 "scitems.hxx"
+#include <svl/intitem.hxx>
+#include <svl/zforlist.hxx>
+#include <float.h> // DBL_MIN
+
+#include "chartarr.hxx"
+#include "document.hxx"
+#include "rechead.hxx"
+#include "globstr.hrc"
+#include "cell.hxx"
+#include "docoptio.hxx"
+
+#include <vector>
+
+using ::std::vector;
+
+// -----------------------------------------------------------------------
+
+ScMemChart::ScMemChart(short nCols, short nRows)
+{
+ nRowCnt = nRows;
+ nColCnt = nCols;
+ pData = new double[nColCnt * nRowCnt];
+
+ if (pData)
+ {
+ double *pFill = pData;
+
+ for (short i = 0; i < nColCnt; i++)
+ for (short j = 0; j < nRowCnt; j++)
+ *(pFill ++) = 0.0;
+ }
+
+ pColText = new String[nColCnt];
+ pRowText = new String[nRowCnt];
+}
+
+ScMemChart::~ScMemChart()
+{
+ delete[] pRowText;
+ delete[] pColText;
+ delete[] pData;
+}
+
+// -----------------------------------------------------------------------
+
+ScChartArray::ScChartArray( ScDocument* pDoc, SCTAB nTab,
+ SCCOL nStartColP, SCROW nStartRowP, SCCOL nEndColP, SCROW nEndRowP,
+ const String& rChartName ) :
+ aName( rChartName ),
+ pDocument( pDoc ),
+ aPositioner(pDoc, nTab, nStartColP, nStartRowP, nEndColP, nEndRowP),
+ bValid( TRUE )
+{
+}
+
+ScChartArray::ScChartArray( ScDocument* pDoc, const ScRangeListRef& rRangeList,
+ const String& rChartName ) :
+ aName( rChartName ),
+ pDocument( pDoc ),
+ aPositioner(pDoc, rRangeList),
+ bValid( TRUE )
+{
+}
+
+ScChartArray::ScChartArray( const ScChartArray& rArr ) :
+ ScDataObject(),
+ aName(rArr.aName),
+ pDocument(rArr.pDocument),
+ aPositioner(rArr.aPositioner),
+ bValid(rArr.bValid)
+{
+}
+
+ScChartArray::~ScChartArray()
+{
+}
+
+ScDataObject* ScChartArray::Clone() const
+{
+ return new ScChartArray(*this);
+}
+
+BOOL ScChartArray::operator==(const ScChartArray& rCmp) const
+{
+ return aPositioner == rCmp.aPositioner
+ && aName == rCmp.aName;
+}
+
+#ifdef _MSC_VER
+#pragma optimize("",off)
+#endif
+
+ScMemChart* ScChartArray::CreateMemChart()
+{
+ ScRangeListRef aRangeListRef(GetRangeList());
+ ULONG nCount = aRangeListRef->Count();
+ if ( nCount > 1 )
+ return CreateMemChartMulti();
+ else if ( nCount == 1 )
+ {
+ ScRange* pR = aRangeListRef->First();
+ if ( pR->aStart.Tab() != pR->aEnd.Tab() )
+ return CreateMemChartMulti();
+ else
+ return CreateMemChartSingle();
+ }
+ else
+ return CreateMemChartMulti(); // kann 0 Range besser ab als Single
+}
+
+ScMemChart* ScChartArray::CreateMemChartSingle()
+{
+ SCSIZE nCol;
+ SCSIZE nRow;
+
+ //
+ // wirkliche Groesse (ohne versteckte Zeilen/Spalten)
+ //
+
+ SCCOL nColAdd = HasRowHeaders() ? 1 : 0;
+ SCROW nRowAdd = HasColHeaders() ? 1 : 0;
+
+ SCCOL nCol1;
+ SCROW nRow1;
+ SCTAB nTab1;
+ SCCOL nCol2;
+ SCROW nRow2;
+ SCTAB nTab2;
+ ScRangeListRef aRangeListRef(GetRangeList());
+ aRangeListRef->First()->GetVars( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 );
+
+ SCCOL nStrCol = nCol1; // fuer Beschriftung merken
+ SCROW nStrRow = nRow1;
+ // Skip hidden columns.
+ // TODO: make use of last column value once implemented.
+ SCCOL nLastCol = -1;
+ while (pDocument->ColHidden(nCol1, nTab1, nLastCol))
+ ++nCol1;
+
+ // Skip hidden rows.
+ SCROW nLastRow = -1;
+ if (pDocument->RowHidden(nRow1, nTab1, nLastRow))
+ nRow1 = nLastRow + 1;
+
+ // falls alles hidden ist, bleibt die Beschriftung am Anfang
+ if ( nCol1 <= nCol2 )
+ {
+ nStrCol = nCol1;
+ nCol1 = sal::static_int_cast<SCCOL>( nCol1 + nColAdd );
+ }
+ if ( nRow1 <= nRow2 )
+ {
+ nStrRow = nRow1;
+ nRow1 = sal::static_int_cast<SCROW>( nRow1 + nRowAdd );
+ }
+
+ SCSIZE nTotalCols = ( nCol1 <= nCol2 ? nCol2 - nCol1 + 1 : 0 );
+ vector<SCCOL> aCols;
+ aCols.reserve(nTotalCols);
+ for (SCSIZE i=0; i<nTotalCols; i++)
+ {
+ SCCOL nThisCol = sal::static_int_cast<SCCOL>(nCol1+i);
+ if (!pDocument->ColHidden(nThisCol, nTab1, nLastCol))
+ aCols.push_back(nThisCol);
+ }
+ SCSIZE nColCount = aCols.size();
+
+ SCSIZE nTotalRows = ( nRow1 <= nRow2 ? nRow2 - nRow1 + 1 : 0 );
+ vector<SCROW> aRows;
+ aRows.reserve(nTotalRows);
+ if (nRow1 <= nRow2)
+ {
+ // Get all visible rows between nRow1 and nRow2.
+ SCROW nThisRow = nRow1;
+ while (nThisRow <= nRow2)
+ {
+ if (pDocument->RowHidden(nThisRow, nTab1, nLastRow))
+ nThisRow = nLastRow;
+ else
+ aRows.push_back(nThisRow);
+ ++nThisRow;
+ }
+ }
+ SCSIZE nRowCount = aRows.size();
+
+ // May happen at least with more than 32k rows.
+ if (nColCount > SHRT_MAX || nRowCount > SHRT_MAX)
+ {
+ nColCount = 0;
+ nRowCount = 0;
+ }
+
+ BOOL bValidData = TRUE;
+ if ( !nColCount )
+ {
+ bValidData = FALSE;
+ nColCount = 1;
+ aCols.push_back(nStrCol);
+ }
+ if ( !nRowCount )
+ {
+ bValidData = FALSE;
+ nRowCount = 1;
+ aRows.push_back(nStrRow);
+ }
+
+ //
+ // Daten
+ //
+
+ ScMemChart* pMemChart = new ScMemChart(
+ static_cast<short>(nColCount), static_cast<short>(nRowCount) );
+ if (pMemChart)
+ {
+// SvNumberFormatter* pFormatter = pDocument->GetFormatTable();
+// pMemChart->SetNumberFormatter( pFormatter );
+ if ( bValidData )
+ {
+ BOOL bCalcAsShown = pDocument->GetDocOptions().IsCalcAsShown();
+ ScBaseCell* pCell;
+ for (nCol=0; nCol<nColCount; nCol++)
+ {
+ for (nRow=0; nRow<nRowCount; nRow++)
+ {
+ double nVal = DBL_MIN; // Hack fuer Chart, um leere Zellen zu erkennen
+
+ pDocument->GetCell( aCols[nCol], aRows[nRow], nTab1, pCell );
+ if (pCell)
+ {
+ CellType eType = pCell->GetCellType();
+ if (eType == CELLTYPE_VALUE)
+ {
+ nVal = ((ScValueCell*)pCell)->GetValue();
+ if ( bCalcAsShown && nVal != 0.0 )
+ {
+ sal_uInt32 nFormat;
+ pDocument->GetNumberFormat( aCols[nCol],
+ aRows[nRow], nTab1, nFormat );
+ nVal = pDocument->RoundValueAsShown( nVal, nFormat );
+ }
+ }
+ else if (eType == CELLTYPE_FORMULA)
+ {
+ ScFormulaCell* pFCell = (ScFormulaCell*)pCell;
+ if ( (pFCell->GetErrCode() == 0) && pFCell->IsValue() )
+ nVal = pFCell->GetValue();
+ }
+ }
+ pMemChart->SetData(static_cast<short>(nCol), static_cast<short>(nRow), nVal);
+ }
+ }
+ }
+ else
+ {
+ //! Flag, dass Daten ungueltig ??
+
+ for (nCol=0; nCol<nColCount; nCol++)
+ for (nRow=0; nRow<nRowCount; nRow++)
+ pMemChart->SetData( static_cast<short>(nCol), static_cast<short>(nRow), DBL_MIN );
+ }
+
+ //
+ // Spalten-Header
+ //
+
+ for (nCol=0; nCol<nColCount; nCol++)
+ {
+ String aString, aColStr;
+ if (HasColHeaders())
+ pDocument->GetString( aCols[nCol], nStrRow, nTab1, aString );
+ if ( !aString.Len() )
+ {
+ aString = ScGlobal::GetRscString(STR_COLUMN);
+ aString += ' ';
+// aString += String::CreateFromInt32( pCols[nCol]+1 );
+ ScAddress aPos( aCols[ nCol ], 0, 0 );
+ aPos.Format( aColStr, SCA_VALID_COL, NULL );
+ aString += aColStr;
+ }
+ pMemChart->SetColText( static_cast<short>(nCol), aString);
+
+// ULONG nNumberAttr = (nTotalRows ? pDocument->GetNumberFormat(
+// ScAddress( pCols[nCol], nRow1, nTab1)) : 0);
+// pMemChart->SetNumFormatIdCol( static_cast<long>(nCol), nNumberAttr );
+ }
+
+ //
+ // Zeilen-Header
+ //
+
+ for (nRow=0; nRow<nRowCount; nRow++)
+ {
+ String aString;
+ if (HasRowHeaders())
+ {
+ ScAddress aAddr( nStrCol, aRows[nRow], nTab1 );
+ pDocument->GetString( nStrCol, aRows[nRow], nTab1, aString );
+ }
+ if ( !aString.Len() )
+ {
+ aString = ScGlobal::GetRscString(STR_ROW);
+ aString += ' ';
+ aString += String::CreateFromInt32( aRows[nRow]+1 );
+ }
+ pMemChart->SetRowText( static_cast<short>(nRow), aString);
+
+// ULONG nNumberAttr = (nTotalCols ? pDocument->GetNumberFormat(
+// ScAddress( nCol1, pRows[nRow], nTab1)) : 0);
+// pMemChart->SetNumFormatIdRow( static_cast<long>(nRow), nNumberAttr );
+ }
+
+ //
+ // Titel
+ //
+
+// pMemChart->SetMainTitle(ScGlobal::GetRscString(STR_CHART_MAINTITLE));
+// pMemChart->SetSubTitle(ScGlobal::GetRscString(STR_CHART_SUBTITLE));
+// pMemChart->SetXAxisTitle(ScGlobal::GetRscString(STR_CHART_XTITLE));
+// pMemChart->SetYAxisTitle(ScGlobal::GetRscString(STR_CHART_YTITLE));
+// pMemChart->SetZAxisTitle(ScGlobal::GetRscString(STR_CHART_ZTITLE));
+
+ //
+ // Zahlen-Typ
+ //
+
+// ULONG nNumberAttr = (nTotalCols && nTotalRows ?
+// pDocument->GetNumberFormat( ScAddress( nCol1, nRow1, nTab1)) :
+// 0);
+// if (pFormatter)
+// pMemChart->SetDataType(pFormatter->GetType( nNumberAttr ));
+
+ //
+ // Parameter-Strings
+ //
+
+// SetExtraStrings( *pMemChart );
+ }
+
+ return pMemChart;
+}
+
+ScMemChart* ScChartArray::CreateMemChartMulti()
+{
+ SCSIZE nColCount = GetPositionMap()->GetColCount();
+ SCSIZE nRowCount = GetPositionMap()->GetRowCount();
+
+ SCSIZE nCol = 0;
+ SCSIZE nRow = 0;
+
+ // May happen at least with more than 32k rows.
+ if (nColCount > SHRT_MAX || nRowCount > SHRT_MAX)
+ {
+ nColCount = 0;
+ nRowCount = 0;
+ }
+
+ BOOL bValidData = TRUE;
+ if ( !nColCount )
+ {
+ bValidData = FALSE;
+ nColCount = 1;
+ }
+ if ( !nRowCount )
+ {
+ bValidData = FALSE;
+ nRowCount = 1;
+ }
+
+ //
+ // Daten
+ //
+
+ ScMemChart* pMemChart = new ScMemChart(
+ static_cast<short>(nColCount), static_cast<short>(nRowCount) );
+ if (pMemChart)
+ {
+// pMemChart->SetNumberFormatter( pDocument->GetFormatTable() );
+ BOOL bCalcAsShown = pDocument->GetDocOptions().IsCalcAsShown();
+ ULONG nIndex = 0;
+ if (bValidData)
+ {
+ for ( nCol = 0; nCol < nColCount; nCol++ )
+ {
+ for ( nRow = 0; nRow < nRowCount; nRow++, nIndex++ )
+ {
+ double nVal = DBL_MIN; // Hack fuer Chart, um leere Zellen zu erkennen
+ const ScAddress* pPos = GetPositionMap()->GetPosition( nIndex );
+ if ( pPos )
+ { // sonst: Luecke
+ ScBaseCell* pCell = pDocument->GetCell( *pPos );
+ if (pCell)
+ {
+ CellType eType = pCell->GetCellType();
+ if (eType == CELLTYPE_VALUE)
+ {
+ nVal = ((ScValueCell*)pCell)->GetValue();
+ if ( bCalcAsShown && nVal != 0.0 )
+ {
+ ULONG nFormat = pDocument->GetNumberFormat( *pPos );
+ nVal = pDocument->RoundValueAsShown( nVal, nFormat );
+ }
+ }
+ else if (eType == CELLTYPE_FORMULA)
+ {
+ ScFormulaCell* pFCell = (ScFormulaCell*)pCell;
+ if ( (pFCell->GetErrCode() == 0) && pFCell->IsValue() )
+ nVal = pFCell->GetValue();
+ }
+ }
+ }
+ pMemChart->SetData(static_cast<short>(nCol), static_cast<short>(nRow), nVal);
+ }
+ }
+ }
+ else
+ {
+ for ( nRow = 0; nRow < nRowCount; nRow++, nIndex++ )
+ {
+ double nVal = DBL_MIN; // Hack fuer Chart, um leere Zellen zu erkennen
+ const ScAddress* pPos = GetPositionMap()->GetPosition( nIndex );
+ if ( pPos )
+ { // sonst: Luecke
+ ScBaseCell* pCell = pDocument->GetCell( *pPos );
+ if (pCell)
+ {
+ CellType eType = pCell->GetCellType();
+ if (eType == CELLTYPE_VALUE)
+ {
+ nVal = ((ScValueCell*)pCell)->GetValue();
+ if ( bCalcAsShown && nVal != 0.0 )
+ {
+ ULONG nFormat = pDocument->GetNumberFormat( *pPos );
+ nVal = pDocument->RoundValueAsShown( nVal, nFormat );
+ }
+ }
+ else if (eType == CELLTYPE_FORMULA)
+ {
+ ScFormulaCell* pFCell = (ScFormulaCell*)pCell;
+ if ( (pFCell->GetErrCode() == 0) && pFCell->IsValue() )
+ nVal = pFCell->GetValue();
+ }
+ }
+ }
+ pMemChart->SetData(static_cast<short>(nCol), static_cast<short>(nRow), nVal);
+ }
+ }
+
+//2do: Beschriftung bei Luecken
+
+ //
+ // Spalten-Header
+ //
+
+ SCCOL nPosCol = 0;
+ for ( nCol = 0; nCol < nColCount; nCol++ )
+ {
+ String aString, aColStr;
+ const ScAddress* pPos = GetPositionMap()->GetColHeaderPosition( static_cast<SCCOL>(nCol) );
+ if ( HasColHeaders() && pPos )
+ pDocument->GetString(
+ pPos->Col(), pPos->Row(), pPos->Tab(), aString );
+ if ( !aString.Len() )
+ {
+ aString = ScGlobal::GetRscString(STR_COLUMN);
+ aString += ' ';
+ if ( pPos )
+ nPosCol = pPos->Col() + 1;
+ else
+ nPosCol++;
+ ScAddress aPos( nPosCol - 1, 0, 0 );
+ aPos.Format( aColStr, SCA_VALID_COL, NULL );
+// aString += String::CreateFromInt32( nPosCol );
+ aString += aColStr;
+ }
+ pMemChart->SetColText( static_cast<short>(nCol), aString);
+
+// ULONG nNumberAttr = 0;
+// pPos = GetPositionMap()->GetPosition( nCol, 0 );
+// if ( pPos )
+// nNumberAttr = pDocument->GetNumberFormat( *pPos );
+// pMemChart->SetNumFormatIdCol( static_cast<long>(nCol), nNumberAttr );
+ }
+
+ //
+ // Zeilen-Header
+ //
+
+ SCROW nPosRow = 0;
+ for ( nRow = 0; nRow < nRowCount; nRow++ )
+ {
+ String aString;
+ const ScAddress* pPos = GetPositionMap()->GetRowHeaderPosition( nRow );
+ if ( HasRowHeaders() && pPos )
+ {
+ pDocument->GetString(
+ pPos->Col(), pPos->Row(), pPos->Tab(), aString );
+ }
+ if ( !aString.Len() )
+ {
+ aString = ScGlobal::GetRscString(STR_ROW);
+ aString += ' ';
+ if ( pPos )
+ nPosRow = pPos->Row() + 1;
+ else
+ nPosRow++;
+ aString += String::CreateFromInt32( nPosRow );
+ }
+ pMemChart->SetRowText( static_cast<short>(nRow), aString);
+
+// ULONG nNumberAttr = 0;
+// pPos = GetPositionMap()->GetPosition( 0, nRow );
+// if ( pPos )
+// nNumberAttr = pDocument->GetNumberFormat( *pPos );
+// pMemChart->SetNumFormatIdRow( static_cast<long>(nRow), nNumberAttr );
+ }
+
+ //
+ // Titel
+ //
+
+// pMemChart->SetMainTitle(ScGlobal::GetRscString(STR_CHART_MAINTITLE));
+// pMemChart->SetSubTitle(ScGlobal::GetRscString(STR_CHART_SUBTITLE));
+// pMemChart->SetXAxisTitle(ScGlobal::GetRscString(STR_CHART_XTITLE));
+// pMemChart->SetYAxisTitle(ScGlobal::GetRscString(STR_CHART_YTITLE));
+// pMemChart->SetZAxisTitle(ScGlobal::GetRscString(STR_CHART_ZTITLE));
+
+ //
+ // Zahlen-Typ
+ //
+
+// SvNumberFormatter* pFormatter = pDocument->GetFormatTable();
+// if (pFormatter)
+// {
+// ULONG nIndex = 0;
+// ULONG nCount = GetPositionMap()->GetCount();
+// const ScAddress* pPos;
+// do
+// {
+// pPos = GetPositionMap()->GetPosition( nIndex );
+// } while ( !pPos && ++nIndex < nCount );
+// ULONG nFormat = ( pPos ? pDocument->GetNumberFormat( *pPos ) : 0 );
+// pMemChart->SetDataType( pFormatter->GetType( nFormat ) );
+// }
+
+ //
+ // Parameter-Strings
+ //
+
+// SetExtraStrings( *pMemChart );
+ }
+
+ return pMemChart;
+}
+
+#ifdef _MSC_VER
+#pragma optimize("",on)
+#endif
+
+
+//
+// Collection
+//
+
+ScDataObject* ScChartCollection::Clone() const
+{
+ return new ScChartCollection(*this);
+}
+
+BOOL ScChartCollection::operator==(const ScChartCollection& rCmp) const
+{
+ if (nCount != rCmp.nCount)
+ return FALSE;
+
+ for (USHORT i=0; i<nCount; i++)
+ if (!((*(const ScChartArray*)pItems[i]) == (*(const ScChartArray*)rCmp.pItems[i])))
+ return FALSE;
+
+ return TRUE;
+}
+