/************************************************************** * * 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 "scitems.hxx" #include #include #include // DBL_MIN #include "chartarr.hxx" #include "document.hxx" #include "rechead.hxx" #include "globstr.hrc" #include "cell.hxx" #include "docoptio.hxx" #include 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( sal_True ) { } ScChartArray::ScChartArray( ScDocument* pDoc, const ScRangeListRef& rRangeList, const String& rChartName ) : aName( rChartName ), pDocument( pDoc ), aPositioner(pDoc, rRangeList), bValid( sal_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); } sal_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()); sal_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( nCol1 + nColAdd ); } if ( nRow1 <= nRow2 ) { nStrRow = nRow1; nRow1 = sal::static_int_cast( nRow1 + nRowAdd ); } SCSIZE nTotalCols = ( nCol1 <= nCol2 ? nCol2 - nCol1 + 1 : 0 ); vector aCols; aCols.reserve(nTotalCols); for (SCSIZE i=0; i(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 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; } sal_Bool bValidData = sal_True; if ( !nColCount ) { bValidData = sal_False; nColCount = 1; aCols.push_back(nStrCol); } if ( !nRowCount ) { bValidData = sal_False; nRowCount = 1; aRows.push_back(nStrRow); } // // Daten // ScMemChart* pMemChart = new ScMemChart( static_cast(nColCount), static_cast(nRowCount) ); if (pMemChart) { // SvNumberFormatter* pFormatter = pDocument->GetFormatTable(); // pMemChart->SetNumberFormatter( pFormatter ); if ( bValidData ) { sal_Bool bCalcAsShown = pDocument->GetDocOptions().IsCalcAsShown(); ScBaseCell* pCell; for (nCol=0; nColGetCell( 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(nCol), static_cast(nRow), nVal); } } } else { //! Flag, dass Daten ungueltig ?? for (nCol=0; nColSetData( static_cast(nCol), static_cast(nRow), DBL_MIN ); } // // Spalten-Header // for (nCol=0; nColGetString( 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(nCol), aString); // sal_uLong nNumberAttr = (nTotalRows ? pDocument->GetNumberFormat( // ScAddress( pCols[nCol], nRow1, nTab1)) : 0); // pMemChart->SetNumFormatIdCol( static_cast(nCol), nNumberAttr ); } // // Zeilen-Header // for (nRow=0; nRowGetString( nStrCol, aRows[nRow], nTab1, aString ); } if ( !aString.Len() ) { aString = ScGlobal::GetRscString(STR_ROW); aString += ' '; aString += String::CreateFromInt32( aRows[nRow]+1 ); } pMemChart->SetRowText( static_cast(nRow), aString); // sal_uLong nNumberAttr = (nTotalCols ? pDocument->GetNumberFormat( // ScAddress( nCol1, pRows[nRow], nTab1)) : 0); // pMemChart->SetNumFormatIdRow( static_cast(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 // // sal_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; } sal_Bool bValidData = sal_True; if ( !nColCount ) { bValidData = sal_False; nColCount = 1; } if ( !nRowCount ) { bValidData = sal_False; nRowCount = 1; } // // Daten // ScMemChart* pMemChart = new ScMemChart( static_cast(nColCount), static_cast(nRowCount) ); if (pMemChart) { // pMemChart->SetNumberFormatter( pDocument->GetFormatTable() ); sal_Bool bCalcAsShown = pDocument->GetDocOptions().IsCalcAsShown(); sal_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 ) { sal_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(nCol), static_cast(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 ) { sal_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(nCol), static_cast(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(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(nCol), aString); // sal_uLong nNumberAttr = 0; // pPos = GetPositionMap()->GetPosition( nCol, 0 ); // if ( pPos ) // nNumberAttr = pDocument->GetNumberFormat( *pPos ); // pMemChart->SetNumFormatIdCol( static_cast(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(nRow), aString); // sal_uLong nNumberAttr = 0; // pPos = GetPositionMap()->GetPosition( 0, nRow ); // if ( pPos ) // nNumberAttr = pDocument->GetNumberFormat( *pPos ); // pMemChart->SetNumFormatIdRow( static_cast(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) // { // sal_uLong nIndex = 0; // sal_uLong nCount = GetPositionMap()->GetCount(); // const ScAddress* pPos; // do // { // pPos = GetPositionMap()->GetPosition( nIndex ); // } while ( !pPos && ++nIndex < nCount ); // sal_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); } sal_Bool ScChartCollection::operator==(const ScChartCollection& rCmp) const { if (nCount != rCmp.nCount) return sal_False; for (sal_uInt16 i=0; i