update dev300-m58
[ooovba.git] / sc / source / core / tool / chartarr.cxx
blob59519577a043f309f3a1aaaeb777ea5a02d7b563
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: chartarr.cxx,v $
10 * $Revision: 1.24.32.3 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sc.hxx"
36 // INCLUDE ---------------------------------------------------------------
38 #include "scitems.hxx"
39 #include <svtools/intitem.hxx>
40 #include <svtools/zforlist.hxx>
41 #include <float.h> // DBL_MIN
43 #include "chartarr.hxx"
44 #include "document.hxx"
45 #include "rechead.hxx"
46 #include "globstr.hrc"
47 #include "cell.hxx"
48 #include "docoptio.hxx"
50 #include <vector>
52 using ::std::vector;
54 // -----------------------------------------------------------------------
56 ScMemChart::ScMemChart(short nCols, short nRows)
58 nRowCnt = nRows;
59 nColCnt = nCols;
60 pData = new double[nColCnt * nRowCnt];
62 if (pData)
64 double *pFill = pData;
66 for (short i = 0; i < nColCnt; i++)
67 for (short j = 0; j < nRowCnt; j++)
68 *(pFill ++) = 0.0;
71 pColText = new String[nColCnt];
72 pRowText = new String[nRowCnt];
75 ScMemChart::~ScMemChart()
77 delete[] pRowText;
78 delete[] pColText;
79 delete[] pData;
82 // -----------------------------------------------------------------------
84 ScChartArray::ScChartArray( ScDocument* pDoc, SCTAB nTab,
85 SCCOL nStartColP, SCROW nStartRowP, SCCOL nEndColP, SCROW nEndRowP,
86 const String& rChartName ) :
87 aName( rChartName ),
88 pDocument( pDoc ),
89 aPositioner(pDoc, nTab, nStartColP, nStartRowP, nEndColP, nEndRowP),
90 bValid( TRUE )
94 ScChartArray::ScChartArray( ScDocument* pDoc, const ScRangeListRef& rRangeList,
95 const String& rChartName ) :
96 aName( rChartName ),
97 pDocument( pDoc ),
98 aPositioner(pDoc, rRangeList),
99 bValid( TRUE )
103 ScChartArray::ScChartArray( const ScChartArray& rArr ) :
104 ScDataObject(),
105 aName(rArr.aName),
106 pDocument(rArr.pDocument),
107 aPositioner(rArr.aPositioner),
108 bValid(rArr.bValid)
112 ScChartArray::~ScChartArray()
116 ScDataObject* ScChartArray::Clone() const
118 return new ScChartArray(*this);
121 BOOL ScChartArray::operator==(const ScChartArray& rCmp) const
123 return aPositioner == rCmp.aPositioner
124 && aName == rCmp.aName;
127 #ifdef _MSC_VER
128 #pragma optimize("",off)
129 #endif
131 ScMemChart* ScChartArray::CreateMemChart()
133 ScRangeListRef aRangeListRef(GetRangeList());
134 ULONG nCount = aRangeListRef->Count();
135 if ( nCount > 1 )
136 return CreateMemChartMulti();
137 else if ( nCount == 1 )
139 ScRange* pR = aRangeListRef->First();
140 if ( pR->aStart.Tab() != pR->aEnd.Tab() )
141 return CreateMemChartMulti();
142 else
143 return CreateMemChartSingle();
145 else
146 return CreateMemChartMulti(); // kann 0 Range besser ab als Single
149 ScMemChart* ScChartArray::CreateMemChartSingle()
151 SCSIZE nCol;
152 SCSIZE nRow;
155 // wirkliche Groesse (ohne versteckte Zeilen/Spalten)
158 SCCOL nColAdd = HasRowHeaders() ? 1 : 0;
159 SCROW nRowAdd = HasColHeaders() ? 1 : 0;
161 SCCOL nCol1;
162 SCROW nRow1;
163 SCTAB nTab1;
164 SCCOL nCol2;
165 SCROW nRow2;
166 SCTAB nTab2;
167 ScRangeListRef aRangeListRef(GetRangeList());
168 aRangeListRef->First()->GetVars( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 );
170 SCCOL nStrCol = nCol1; // fuer Beschriftung merken
171 SCROW nStrRow = nRow1;
172 // Skip hidden columns.
173 // TODO: make use of last column value once implemented.
174 SCCOL nLastCol = -1;
175 while (pDocument->ColHidden(nCol1, nTab1, nLastCol))
176 ++nCol1;
178 // Skip hidden rows.
179 SCROW nLastRow = -1;
180 if (pDocument->RowHidden(nRow1, nTab1, nLastRow))
181 nRow1 = nLastRow + 1;
183 // falls alles hidden ist, bleibt die Beschriftung am Anfang
184 if ( nCol1 <= nCol2 )
186 nStrCol = nCol1;
187 nCol1 = sal::static_int_cast<SCCOL>( nCol1 + nColAdd );
189 if ( nRow1 <= nRow2 )
191 nStrRow = nRow1;
192 nRow1 = sal::static_int_cast<SCROW>( nRow1 + nRowAdd );
195 SCSIZE nTotalCols = ( nCol1 <= nCol2 ? nCol2 - nCol1 + 1 : 0 );
196 vector<SCCOL> aCols;
197 aCols.reserve(nTotalCols);
198 for (SCSIZE i=0; i<nTotalCols; i++)
200 SCCOL nThisCol = sal::static_int_cast<SCCOL>(nCol1+i);
201 if (!pDocument->ColHidden(nThisCol, nTab1, nLastCol))
202 aCols.push_back(nThisCol);
204 SCSIZE nColCount = aCols.size();
206 SCSIZE nTotalRows = ( nRow1 <= nRow2 ? nRow2 - nRow1 + 1 : 0 );
207 vector<SCROW> aRows;
208 aRows.reserve(nTotalRows);
209 if (nRow1 <= nRow2)
211 // Get all visible rows between nRow1 and nRow2.
212 SCROW nThisRow = nRow1;
213 while (nThisRow <= nRow2)
215 if (pDocument->RowHidden(nThisRow, nTab1, nLastRow))
216 nThisRow = nLastRow;
217 else
218 aRows.push_back(nThisRow);
219 ++nThisRow;
222 SCSIZE nRowCount = aRows.size();
224 // May happen at least with more than 32k rows.
225 if (nColCount > SHRT_MAX || nRowCount > SHRT_MAX)
227 nColCount = 0;
228 nRowCount = 0;
231 BOOL bValidData = TRUE;
232 if ( !nColCount )
234 bValidData = FALSE;
235 nColCount = 1;
236 aCols.push_back(nStrCol);
238 if ( !nRowCount )
240 bValidData = FALSE;
241 nRowCount = 1;
242 aRows.push_back(nStrRow);
246 // Daten
249 ScMemChart* pMemChart = new ScMemChart(
250 static_cast<short>(nColCount), static_cast<short>(nRowCount) );
251 if (pMemChart)
253 // SvNumberFormatter* pFormatter = pDocument->GetFormatTable();
254 // pMemChart->SetNumberFormatter( pFormatter );
255 if ( bValidData )
257 BOOL bCalcAsShown = pDocument->GetDocOptions().IsCalcAsShown();
258 ScBaseCell* pCell;
259 for (nCol=0; nCol<nColCount; nCol++)
261 for (nRow=0; nRow<nRowCount; nRow++)
263 double nVal = DBL_MIN; // Hack fuer Chart, um leere Zellen zu erkennen
265 pDocument->GetCell( aCols[nCol], aRows[nRow], nTab1, pCell );
266 if (pCell)
268 CellType eType = pCell->GetCellType();
269 if (eType == CELLTYPE_VALUE)
271 nVal = ((ScValueCell*)pCell)->GetValue();
272 if ( bCalcAsShown && nVal != 0.0 )
274 sal_uInt32 nFormat;
275 pDocument->GetNumberFormat( aCols[nCol],
276 aRows[nRow], nTab1, nFormat );
277 nVal = pDocument->RoundValueAsShown( nVal, nFormat );
280 else if (eType == CELLTYPE_FORMULA)
282 ScFormulaCell* pFCell = (ScFormulaCell*)pCell;
283 if ( (pFCell->GetErrCode() == 0) && pFCell->IsValue() )
284 nVal = pFCell->GetValue();
287 pMemChart->SetData(static_cast<short>(nCol), static_cast<short>(nRow), nVal);
291 else
293 //! Flag, dass Daten ungueltig ??
295 for (nCol=0; nCol<nColCount; nCol++)
296 for (nRow=0; nRow<nRowCount; nRow++)
297 pMemChart->SetData( static_cast<short>(nCol), static_cast<short>(nRow), DBL_MIN );
301 // Spalten-Header
304 for (nCol=0; nCol<nColCount; nCol++)
306 String aString, aColStr;
307 if (HasColHeaders())
308 pDocument->GetString( aCols[nCol], nStrRow, nTab1, aString );
309 if ( !aString.Len() )
311 aString = ScGlobal::GetRscString(STR_COLUMN);
312 aString += ' ';
313 // aString += String::CreateFromInt32( pCols[nCol]+1 );
314 ScAddress aPos( aCols[ nCol ], 0, 0 );
315 aPos.Format( aColStr, SCA_VALID_COL, NULL );
316 aString += aColStr;
318 pMemChart->SetColText( static_cast<short>(nCol), aString);
320 // ULONG nNumberAttr = (nTotalRows ? pDocument->GetNumberFormat(
321 // ScAddress( pCols[nCol], nRow1, nTab1)) : 0);
322 // pMemChart->SetNumFormatIdCol( static_cast<long>(nCol), nNumberAttr );
326 // Zeilen-Header
329 for (nRow=0; nRow<nRowCount; nRow++)
331 String aString;
332 if (HasRowHeaders())
334 ScAddress aAddr( nStrCol, aRows[nRow], nTab1 );
335 pDocument->GetString( nStrCol, aRows[nRow], nTab1, aString );
337 if ( !aString.Len() )
339 aString = ScGlobal::GetRscString(STR_ROW);
340 aString += ' ';
341 aString += String::CreateFromInt32( aRows[nRow]+1 );
343 pMemChart->SetRowText( static_cast<short>(nRow), aString);
345 // ULONG nNumberAttr = (nTotalCols ? pDocument->GetNumberFormat(
346 // ScAddress( nCol1, pRows[nRow], nTab1)) : 0);
347 // pMemChart->SetNumFormatIdRow( static_cast<long>(nRow), nNumberAttr );
351 // Titel
354 // pMemChart->SetMainTitle(ScGlobal::GetRscString(STR_CHART_MAINTITLE));
355 // pMemChart->SetSubTitle(ScGlobal::GetRscString(STR_CHART_SUBTITLE));
356 // pMemChart->SetXAxisTitle(ScGlobal::GetRscString(STR_CHART_XTITLE));
357 // pMemChart->SetYAxisTitle(ScGlobal::GetRscString(STR_CHART_YTITLE));
358 // pMemChart->SetZAxisTitle(ScGlobal::GetRscString(STR_CHART_ZTITLE));
361 // Zahlen-Typ
364 // ULONG nNumberAttr = (nTotalCols && nTotalRows ?
365 // pDocument->GetNumberFormat( ScAddress( nCol1, nRow1, nTab1)) :
366 // 0);
367 // if (pFormatter)
368 // pMemChart->SetDataType(pFormatter->GetType( nNumberAttr ));
371 // Parameter-Strings
374 // SetExtraStrings( *pMemChart );
377 return pMemChart;
380 ScMemChart* ScChartArray::CreateMemChartMulti()
382 SCSIZE nColCount = GetPositionMap()->GetColCount();
383 SCSIZE nRowCount = GetPositionMap()->GetRowCount();
385 SCSIZE nCol = 0;
386 SCSIZE nRow = 0;
388 // May happen at least with more than 32k rows.
389 if (nColCount > SHRT_MAX || nRowCount > SHRT_MAX)
391 nColCount = 0;
392 nRowCount = 0;
395 BOOL bValidData = TRUE;
396 if ( !nColCount )
398 bValidData = FALSE;
399 nColCount = 1;
401 if ( !nRowCount )
403 bValidData = FALSE;
404 nRowCount = 1;
408 // Daten
411 ScMemChart* pMemChart = new ScMemChart(
412 static_cast<short>(nColCount), static_cast<short>(nRowCount) );
413 if (pMemChart)
415 // pMemChart->SetNumberFormatter( pDocument->GetFormatTable() );
416 BOOL bCalcAsShown = pDocument->GetDocOptions().IsCalcAsShown();
417 ULONG nIndex = 0;
418 if (bValidData)
420 for ( nCol = 0; nCol < nColCount; nCol++ )
422 for ( nRow = 0; nRow < nRowCount; nRow++, nIndex++ )
424 double nVal = DBL_MIN; // Hack fuer Chart, um leere Zellen zu erkennen
425 const ScAddress* pPos = GetPositionMap()->GetPosition( nIndex );
426 if ( pPos )
427 { // sonst: Luecke
428 ScBaseCell* pCell = pDocument->GetCell( *pPos );
429 if (pCell)
431 CellType eType = pCell->GetCellType();
432 if (eType == CELLTYPE_VALUE)
434 nVal = ((ScValueCell*)pCell)->GetValue();
435 if ( bCalcAsShown && nVal != 0.0 )
437 ULONG nFormat = pDocument->GetNumberFormat( *pPos );
438 nVal = pDocument->RoundValueAsShown( nVal, nFormat );
441 else if (eType == CELLTYPE_FORMULA)
443 ScFormulaCell* pFCell = (ScFormulaCell*)pCell;
444 if ( (pFCell->GetErrCode() == 0) && pFCell->IsValue() )
445 nVal = pFCell->GetValue();
449 pMemChart->SetData(static_cast<short>(nCol), static_cast<short>(nRow), nVal);
453 else
455 for ( nRow = 0; nRow < nRowCount; nRow++, nIndex++ )
457 double nVal = DBL_MIN; // Hack fuer Chart, um leere Zellen zu erkennen
458 const ScAddress* pPos = GetPositionMap()->GetPosition( nIndex );
459 if ( pPos )
460 { // sonst: Luecke
461 ScBaseCell* pCell = pDocument->GetCell( *pPos );
462 if (pCell)
464 CellType eType = pCell->GetCellType();
465 if (eType == CELLTYPE_VALUE)
467 nVal = ((ScValueCell*)pCell)->GetValue();
468 if ( bCalcAsShown && nVal != 0.0 )
470 ULONG nFormat = pDocument->GetNumberFormat( *pPos );
471 nVal = pDocument->RoundValueAsShown( nVal, nFormat );
474 else if (eType == CELLTYPE_FORMULA)
476 ScFormulaCell* pFCell = (ScFormulaCell*)pCell;
477 if ( (pFCell->GetErrCode() == 0) && pFCell->IsValue() )
478 nVal = pFCell->GetValue();
482 pMemChart->SetData(static_cast<short>(nCol), static_cast<short>(nRow), nVal);
486 //2do: Beschriftung bei Luecken
489 // Spalten-Header
492 SCCOL nPosCol = 0;
493 for ( nCol = 0; nCol < nColCount; nCol++ )
495 String aString, aColStr;
496 const ScAddress* pPos = GetPositionMap()->GetColHeaderPosition( static_cast<SCCOL>(nCol) );
497 if ( HasColHeaders() && pPos )
498 pDocument->GetString(
499 pPos->Col(), pPos->Row(), pPos->Tab(), aString );
500 if ( !aString.Len() )
502 aString = ScGlobal::GetRscString(STR_COLUMN);
503 aString += ' ';
504 if ( pPos )
505 nPosCol = pPos->Col() + 1;
506 else
507 nPosCol++;
508 ScAddress aPos( nPosCol - 1, 0, 0 );
509 aPos.Format( aColStr, SCA_VALID_COL, NULL );
510 // aString += String::CreateFromInt32( nPosCol );
511 aString += aColStr;
513 pMemChart->SetColText( static_cast<short>(nCol), aString);
515 // ULONG nNumberAttr = 0;
516 // pPos = GetPositionMap()->GetPosition( nCol, 0 );
517 // if ( pPos )
518 // nNumberAttr = pDocument->GetNumberFormat( *pPos );
519 // pMemChart->SetNumFormatIdCol( static_cast<long>(nCol), nNumberAttr );
523 // Zeilen-Header
526 SCROW nPosRow = 0;
527 for ( nRow = 0; nRow < nRowCount; nRow++ )
529 String aString;
530 const ScAddress* pPos = GetPositionMap()->GetRowHeaderPosition( nRow );
531 if ( HasRowHeaders() && pPos )
533 pDocument->GetString(
534 pPos->Col(), pPos->Row(), pPos->Tab(), aString );
536 if ( !aString.Len() )
538 aString = ScGlobal::GetRscString(STR_ROW);
539 aString += ' ';
540 if ( pPos )
541 nPosRow = pPos->Row() + 1;
542 else
543 nPosRow++;
544 aString += String::CreateFromInt32( nPosRow );
546 pMemChart->SetRowText( static_cast<short>(nRow), aString);
548 // ULONG nNumberAttr = 0;
549 // pPos = GetPositionMap()->GetPosition( 0, nRow );
550 // if ( pPos )
551 // nNumberAttr = pDocument->GetNumberFormat( *pPos );
552 // pMemChart->SetNumFormatIdRow( static_cast<long>(nRow), nNumberAttr );
556 // Titel
559 // pMemChart->SetMainTitle(ScGlobal::GetRscString(STR_CHART_MAINTITLE));
560 // pMemChart->SetSubTitle(ScGlobal::GetRscString(STR_CHART_SUBTITLE));
561 // pMemChart->SetXAxisTitle(ScGlobal::GetRscString(STR_CHART_XTITLE));
562 // pMemChart->SetYAxisTitle(ScGlobal::GetRscString(STR_CHART_YTITLE));
563 // pMemChart->SetZAxisTitle(ScGlobal::GetRscString(STR_CHART_ZTITLE));
566 // Zahlen-Typ
569 // SvNumberFormatter* pFormatter = pDocument->GetFormatTable();
570 // if (pFormatter)
571 // {
572 // ULONG nIndex = 0;
573 // ULONG nCount = GetPositionMap()->GetCount();
574 // const ScAddress* pPos;
575 // do
576 // {
577 // pPos = GetPositionMap()->GetPosition( nIndex );
578 // } while ( !pPos && ++nIndex < nCount );
579 // ULONG nFormat = ( pPos ? pDocument->GetNumberFormat( *pPos ) : 0 );
580 // pMemChart->SetDataType( pFormatter->GetType( nFormat ) );
581 // }
584 // Parameter-Strings
587 // SetExtraStrings( *pMemChart );
590 return pMemChart;
593 #ifdef _MSC_VER
594 #pragma optimize("",on)
595 #endif
599 // Collection
602 ScDataObject* ScChartCollection::Clone() const
604 return new ScChartCollection(*this);
607 BOOL ScChartCollection::operator==(const ScChartCollection& rCmp) const
609 if (nCount != rCmp.nCount)
610 return FALSE;
612 for (USHORT i=0; i<nCount; i++)
613 if (!((*(const ScChartArray*)pItems[i]) == (*(const ScChartArray*)rCmp.pItems[i])))
614 return FALSE;
616 return TRUE;