1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
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"
48 #include "docoptio.hxx"
54 // -----------------------------------------------------------------------
56 ScMemChart::ScMemChart(short nCols
, short nRows
)
60 pData
= new double[nColCnt
* nRowCnt
];
64 double *pFill
= pData
;
66 for (short i
= 0; i
< nColCnt
; i
++)
67 for (short j
= 0; j
< nRowCnt
; j
++)
71 pColText
= new String
[nColCnt
];
72 pRowText
= new String
[nRowCnt
];
75 ScMemChart::~ScMemChart()
82 // -----------------------------------------------------------------------
84 ScChartArray::ScChartArray( ScDocument
* pDoc
, SCTAB nTab
,
85 SCCOL nStartColP
, SCROW nStartRowP
, SCCOL nEndColP
, SCROW nEndRowP
,
86 const String
& rChartName
) :
89 aPositioner(pDoc
, nTab
, nStartColP
, nStartRowP
, nEndColP
, nEndRowP
),
94 ScChartArray::ScChartArray( ScDocument
* pDoc
, const ScRangeListRef
& rRangeList
,
95 const String
& rChartName
) :
98 aPositioner(pDoc
, rRangeList
),
103 ScChartArray::ScChartArray( const ScChartArray
& rArr
) :
106 pDocument(rArr
.pDocument
),
107 aPositioner(rArr
.aPositioner
),
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
;
128 #pragma optimize("",off)
131 ScMemChart
* ScChartArray::CreateMemChart()
133 ScRangeListRef
aRangeListRef(GetRangeList());
134 ULONG nCount
= aRangeListRef
->Count();
136 return CreateMemChartMulti();
137 else if ( nCount
== 1 )
139 ScRange
* pR
= aRangeListRef
->First();
140 if ( pR
->aStart
.Tab() != pR
->aEnd
.Tab() )
141 return CreateMemChartMulti();
143 return CreateMemChartSingle();
146 return CreateMemChartMulti(); // kann 0 Range besser ab als Single
149 ScMemChart
* ScChartArray::CreateMemChartSingle()
155 // wirkliche Groesse (ohne versteckte Zeilen/Spalten)
158 SCCOL nColAdd
= HasRowHeaders() ? 1 : 0;
159 SCROW nRowAdd
= HasColHeaders() ? 1 : 0;
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.
175 while (pDocument
->ColHidden(nCol1
, nTab1
, nLastCol
))
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
)
187 nCol1
= sal::static_int_cast
<SCCOL
>( nCol1
+ nColAdd
);
189 if ( nRow1
<= nRow2
)
192 nRow1
= sal::static_int_cast
<SCROW
>( nRow1
+ nRowAdd
);
195 SCSIZE nTotalCols
= ( nCol1
<= nCol2
? nCol2
- nCol1
+ 1 : 0 );
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 );
208 aRows
.reserve(nTotalRows
);
211 // Get all visible rows between nRow1 and nRow2.
212 SCROW nThisRow
= nRow1
;
213 while (nThisRow
<= nRow2
)
215 if (pDocument
->RowHidden(nThisRow
, nTab1
, nLastRow
))
218 aRows
.push_back(nThisRow
);
222 SCSIZE nRowCount
= aRows
.size();
224 // May happen at least with more than 32k rows.
225 if (nColCount
> SHRT_MAX
|| nRowCount
> SHRT_MAX
)
231 BOOL bValidData
= TRUE
;
236 aCols
.push_back(nStrCol
);
242 aRows
.push_back(nStrRow
);
249 ScMemChart
* pMemChart
= new ScMemChart(
250 static_cast<short>(nColCount
), static_cast<short>(nRowCount
) );
253 // SvNumberFormatter* pFormatter = pDocument->GetFormatTable();
254 // pMemChart->SetNumberFormatter( pFormatter );
257 BOOL bCalcAsShown
= pDocument
->GetDocOptions().IsCalcAsShown();
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
);
268 CellType eType
= pCell
->GetCellType();
269 if (eType
== CELLTYPE_VALUE
)
271 nVal
= ((ScValueCell
*)pCell
)->GetValue();
272 if ( bCalcAsShown
&& nVal
!= 0.0 )
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
);
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
);
304 for (nCol
=0; nCol
<nColCount
; nCol
++)
306 String aString
, aColStr
;
308 pDocument
->GetString( aCols
[nCol
], nStrRow
, nTab1
, aString
);
309 if ( !aString
.Len() )
311 aString
= ScGlobal::GetRscString(STR_COLUMN
);
313 // aString += String::CreateFromInt32( pCols[nCol]+1 );
314 ScAddress
aPos( aCols
[ nCol
], 0, 0 );
315 aPos
.Format( aColStr
, SCA_VALID_COL
, NULL
);
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 );
329 for (nRow
=0; nRow
<nRowCount
; nRow
++)
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
);
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 );
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));
364 // ULONG nNumberAttr = (nTotalCols && nTotalRows ?
365 // pDocument->GetNumberFormat( ScAddress( nCol1, nRow1, nTab1)) :
368 // pMemChart->SetDataType(pFormatter->GetType( nNumberAttr ));
374 // SetExtraStrings( *pMemChart );
380 ScMemChart
* ScChartArray::CreateMemChartMulti()
382 SCSIZE nColCount
= GetPositionMap()->GetColCount();
383 SCSIZE nRowCount
= GetPositionMap()->GetRowCount();
388 // May happen at least with more than 32k rows.
389 if (nColCount
> SHRT_MAX
|| nRowCount
> SHRT_MAX
)
395 BOOL bValidData
= TRUE
;
411 ScMemChart
* pMemChart
= new ScMemChart(
412 static_cast<short>(nColCount
), static_cast<short>(nRowCount
) );
415 // pMemChart->SetNumberFormatter( pDocument->GetFormatTable() );
416 BOOL bCalcAsShown
= pDocument
->GetDocOptions().IsCalcAsShown();
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
);
428 ScBaseCell
* pCell
= pDocument
->GetCell( *pPos
);
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
);
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
);
461 ScBaseCell
* pCell
= pDocument
->GetCell( *pPos
);
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
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
);
505 nPosCol
= pPos
->Col() + 1;
508 ScAddress
aPos( nPosCol
- 1, 0, 0 );
509 aPos
.Format( aColStr
, SCA_VALID_COL
, NULL
);
510 // aString += String::CreateFromInt32( nPosCol );
513 pMemChart
->SetColText( static_cast<short>(nCol
), aString
);
515 // ULONG nNumberAttr = 0;
516 // pPos = GetPositionMap()->GetPosition( nCol, 0 );
518 // nNumberAttr = pDocument->GetNumberFormat( *pPos );
519 // pMemChart->SetNumFormatIdCol( static_cast<long>(nCol), nNumberAttr );
527 for ( nRow
= 0; nRow
< nRowCount
; nRow
++ )
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
);
541 nPosRow
= pPos
->Row() + 1;
544 aString
+= String::CreateFromInt32( nPosRow
);
546 pMemChart
->SetRowText( static_cast<short>(nRow
), aString
);
548 // ULONG nNumberAttr = 0;
549 // pPos = GetPositionMap()->GetPosition( 0, nRow );
551 // nNumberAttr = pDocument->GetNumberFormat( *pPos );
552 // pMemChart->SetNumFormatIdRow( static_cast<long>(nRow), nNumberAttr );
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));
569 // SvNumberFormatter* pFormatter = pDocument->GetFormatTable();
573 // ULONG nCount = GetPositionMap()->GetCount();
574 // const ScAddress* pPos;
577 // pPos = GetPositionMap()->GetPosition( nIndex );
578 // } while ( !pPos && ++nIndex < nCount );
579 // ULONG nFormat = ( pPos ? pDocument->GetNumberFormat( *pPos ) : 0 );
580 // pMemChart->SetDataType( pFormatter->GetType( nFormat ) );
587 // SetExtraStrings( *pMemChart );
594 #pragma optimize("",on)
602 ScDataObject
* ScChartCollection::Clone() const
604 return new ScChartCollection(*this);
607 BOOL
ScChartCollection::operator==(const ScChartCollection
& rCmp
) const
609 if (nCount
!= rCmp
.nCount
)
612 for (USHORT i
=0; i
<nCount
; i
++)
613 if (!((*(const ScChartArray
*)pItems
[i
]) == (*(const ScChartArray
*)rCmp
.pItems
[i
])))