1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include "scitems.hxx"
21 #include <svl/intitem.hxx>
22 #include <svl/zforlist.hxx>
25 #include "chartarr.hxx"
26 #include "document.hxx"
27 #include "rechead.hxx"
28 #include "globstr.hrc"
29 #include "formulacell.hxx"
30 #include "docoptio.hxx"
36 ScMemChart::ScMemChart(short nCols
, short nRows
)
40 pData
= new double[nColCnt
* nRowCnt
];
44 double *pFill
= pData
;
46 for (short i
= 0; i
< nColCnt
; i
++)
47 for (short j
= 0; j
< nRowCnt
; j
++)
51 pColText
= new OUString
[nColCnt
];
52 pRowText
= new OUString
[nRowCnt
];
55 ScMemChart::~ScMemChart()
62 ScChartArray::ScChartArray( ScDocument
* pDoc
, SCTAB nTab
,
63 SCCOL nStartColP
, SCROW nStartRowP
, SCCOL nEndColP
, SCROW nEndRowP
,
64 const OUString
& rChartName
) :
67 aPositioner(pDoc
, nTab
, nStartColP
, nStartRowP
, nEndColP
, nEndRowP
),
72 ScChartArray::ScChartArray(
73 ScDocument
* pDoc
, const ScRangeListRef
& rRangeList
, const OUString
& rChartName
) :
76 aPositioner(pDoc
, rRangeList
),
79 ScChartArray::ScChartArray( const ScChartArray
& rArr
) :
81 pDocument(rArr
.pDocument
),
82 aPositioner(rArr
.aPositioner
),
83 bValid(rArr
.bValid
) {}
85 ScChartArray::~ScChartArray() {}
87 bool ScChartArray::operator==(const ScChartArray
& rCmp
) const
89 return aPositioner
== rCmp
.aPositioner
90 && aName
== rCmp
.aName
;
93 ScMemChart
* ScChartArray::CreateMemChart()
95 ScRangeListRef
aRangeListRef(GetRangeList());
96 size_t nCount
= aRangeListRef
->size();
98 return CreateMemChartMulti();
99 else if ( nCount
== 1 )
101 ScRange
* pR
= aRangeListRef
->front();
102 if ( pR
->aStart
.Tab() != pR
->aEnd
.Tab() )
103 return CreateMemChartMulti();
105 return CreateMemChartSingle();
108 return CreateMemChartMulti(); // Can handle 0 range better than Single
113 double getCellValue( ScDocument
& rDoc
, const ScAddress
& rPos
, double fDefault
, bool bCalcAsShown
)
115 double fRet
= fDefault
;
117 CellType eType
= rDoc
.GetCellType(rPos
);
122 fRet
= rDoc
.GetValue(rPos
);
123 if (bCalcAsShown
&& fRet
!= 0.0)
125 sal_uInt32 nFormat
= rDoc
.GetNumberFormat(rPos
);
126 fRet
= rDoc
.RoundValueAsShown(fRet
, nFormat
);
130 case CELLTYPE_FORMULA
:
132 ScFormulaCell
* pFCell
= rDoc
.GetFormulaCell(rPos
);
133 if (!pFCell
->GetErrCode() && pFCell
->IsValue())
134 fRet
= pFCell
->GetValue();
145 ScMemChart
* ScChartArray::CreateMemChartSingle()
151 // real size (without hidden rows/columns)
154 SCCOL nColAdd
= HasRowHeaders() ? 1 : 0;
155 SCROW nRowAdd
= HasColHeaders() ? 1 : 0;
163 ScRangeListRef
aRangeListRef(GetRangeList());
164 aRangeListRef
->front()->GetVars( nCol1
, nRow1
, nTab1
, nCol2
, nRow2
, nTab2
);
166 SCCOL nStrCol
= nCol1
; // remember for labeling
167 SCROW nStrRow
= nRow1
;
168 // Skip hidden columns.
169 // TODO: make use of last column value once implemented.
171 while (pDocument
->ColHidden(nCol1
, nTab1
, NULL
, &nLastCol
))
176 if (pDocument
->RowHidden(nRow1
, nTab1
, NULL
, &nLastRow
))
177 nRow1
= nLastRow
+ 1;
179 // if everything is hidden then the label remains at the beginning
180 if ( nCol1
<= nCol2
)
183 nCol1
= sal::static_int_cast
<SCCOL
>( nCol1
+ nColAdd
);
185 if ( nRow1
<= nRow2
)
188 nRow1
= sal::static_int_cast
<SCROW
>( nRow1
+ nRowAdd
);
191 SCSIZE nTotalCols
= ( nCol1
<= nCol2
? nCol2
- nCol1
+ 1 : 0 );
193 aCols
.reserve(nTotalCols
);
194 for (SCSIZE i
=0; i
<nTotalCols
; i
++)
196 SCCOL nThisCol
= sal::static_int_cast
<SCCOL
>(nCol1
+i
);
197 if (!pDocument
->ColHidden(nThisCol
, nTab1
, NULL
, &nLastCol
))
198 aCols
.push_back(nThisCol
);
200 SCSIZE nColCount
= aCols
.size();
202 SCSIZE nTotalRows
= ( nRow1
<= nRow2
? nRow2
- nRow1
+ 1 : 0 );
204 aRows
.reserve(nTotalRows
);
207 // Get all visible rows between nRow1 and nRow2.
208 SCROW nThisRow
= nRow1
;
209 while (nThisRow
<= nRow2
)
211 if (pDocument
->RowHidden(nThisRow
, nTab1
, NULL
, &nLastRow
))
214 aRows
.push_back(nThisRow
);
218 SCSIZE nRowCount
= aRows
.size();
220 // May happen at least with more than 32k rows.
221 if (nColCount
> SHRT_MAX
|| nRowCount
> SHRT_MAX
)
227 bool bValidData
= true;
232 aCols
.push_back(nStrCol
);
238 aRows
.push_back(nStrRow
);
245 ScMemChart
* pMemChart
= new ScMemChart(
246 static_cast<short>(nColCount
), static_cast<short>(nRowCount
) );
251 bool bCalcAsShown
= pDocument
->GetDocOptions().IsCalcAsShown();
252 for (nCol
=0; nCol
<nColCount
; nCol
++)
254 for (nRow
=0; nRow
<nRowCount
; nRow
++)
256 // DBL_MIN is a Hack for Chart to recognize empty cells.
257 ScAddress
aPos(aCols
[nCol
], aRows
[nRow
], nTab1
);
258 double nVal
= getCellValue(*pDocument
, aPos
, DBL_MIN
, bCalcAsShown
);
259 pMemChart
->SetData(static_cast<short>(nCol
), static_cast<short>(nRow
), nVal
);
265 // Flag marking data as invalid?
266 for (nCol
=0; nCol
<nColCount
; nCol
++)
267 for (nRow
=0; nRow
<nRowCount
; nRow
++)
268 pMemChart
->SetData( static_cast<short>(nCol
), static_cast<short>(nRow
), DBL_MIN
);
274 for (nCol
=0; nCol
<nColCount
; nCol
++)
278 aString
= pDocument
->GetString(aCols
[nCol
], nStrRow
, nTab1
);
279 if (aString
.isEmpty())
282 aBuf
.append(ScGlobal::GetRscString(STR_COLUMN
));
285 ScAddress
aPos( aCols
[ nCol
], 0, 0 );
286 aBuf
.append(aPos
.Format(SCA_VALID_COL
, NULL
));
288 aString
= aBuf
.makeStringAndClear();
290 pMemChart
->SetColText( static_cast<short>(nCol
), aString
);
296 for (nRow
=0; nRow
<nRowCount
; nRow
++)
301 ScAddress
aAddr( nStrCol
, aRows
[nRow
], nTab1
);
302 aString
= pDocument
->GetString(nStrCol
, aRows
[nRow
], nTab1
);
304 if (aString
.isEmpty())
307 aBuf
.append(ScGlobal::GetRscString(STR_ROW
));
309 aBuf
.append(static_cast<sal_Int32
>(aRows
[nRow
]+1));
310 aString
= aBuf
.makeStringAndClear();
312 pMemChart
->SetRowText( static_cast<short>(nRow
), aString
);
319 ScMemChart
* ScChartArray::CreateMemChartMulti()
321 SCSIZE nColCount
= GetPositionMap()->GetColCount();
322 SCSIZE nRowCount
= GetPositionMap()->GetRowCount();
324 // May happen at least with more than 32k rows.
325 if (nColCount
> SHRT_MAX
|| nRowCount
> SHRT_MAX
)
331 bool bValidData
= true;
347 ScMemChart
* pMemChart
= new ScMemChart(
348 static_cast<short>(nColCount
), static_cast<short>(nRowCount
) );
353 bool bCalcAsShown
= pDocument
->GetDocOptions().IsCalcAsShown();
354 sal_uLong nIndex
= 0;
357 for ( nCol
= 0; nCol
< nColCount
; nCol
++ )
359 for ( nRow
= 0; nRow
< nRowCount
; nRow
++, nIndex
++ )
361 double nVal
= DBL_MIN
; // Hack for Chart to recognize empty cells
362 const ScAddress
* pPos
= GetPositionMap()->GetPosition( nIndex
);
365 nVal
= getCellValue(*pDocument
, *pPos
, DBL_MIN
, bCalcAsShown
);
367 pMemChart
->SetData(static_cast<short>(nCol
), static_cast<short>(nRow
), nVal
);
373 for ( nRow
= 0; nRow
< nRowCount
; nRow
++, nIndex
++ )
375 double nVal
= DBL_MIN
; // Hack for Chart to recognize empty cells
376 const ScAddress
* pPos
= GetPositionMap()->GetPosition( nIndex
);
379 nVal
= getCellValue(*pDocument
, *pPos
, DBL_MIN
, bCalcAsShown
);
381 pMemChart
->SetData(static_cast<short>(nCol
), static_cast<short>(nRow
), nVal
);
385 //TODO: Label when gaps
392 for ( nCol
= 0; nCol
< nColCount
; nCol
++ )
395 const ScAddress
* pPos
= GetPositionMap()->GetColHeaderPosition( static_cast<SCCOL
>(nCol
) );
396 if ( HasColHeaders() && pPos
)
397 aString
= pDocument
->GetString(pPos
->Col(), pPos
->Row(), pPos
->Tab());
399 if (aString
.isEmpty())
401 OUStringBuffer
aBuf(ScGlobal::GetRscString(STR_COLUMN
));
404 nPosCol
= pPos
->Col() + 1;
407 ScAddress
aPos( nPosCol
- 1, 0, 0 );
408 aBuf
.append(aPos
.Format(SCA_VALID_COL
, NULL
));
409 aString
= aBuf
.makeStringAndClear();
411 pMemChart
->SetColText( static_cast<short>(nCol
), aString
);
419 for ( nRow
= 0; nRow
< nRowCount
; nRow
++ )
422 const ScAddress
* pPos
= GetPositionMap()->GetRowHeaderPosition( nRow
);
423 if ( HasRowHeaders() && pPos
)
424 aString
= pDocument
->GetString(pPos
->Col(), pPos
->Row(), pPos
->Tab());
426 if (aString
.isEmpty())
428 OUStringBuffer
aBuf(ScGlobal::GetRscString(STR_ROW
));
431 nPosRow
= pPos
->Row() + 1;
434 aBuf
.append(static_cast<sal_Int32
>(nPosRow
));
435 aString
= aBuf
.makeStringAndClear();
437 pMemChart
->SetRowText( static_cast<short>(nRow
), aString
);
444 ScChartCollection::ScChartCollection() {}
445 ScChartCollection::ScChartCollection(const ScChartCollection
& r
) :
448 void ScChartCollection::push_back(ScChartArray
* p
)
453 void ScChartCollection::clear()
458 size_t ScChartCollection::size() const
460 return maData
.size();
463 bool ScChartCollection::empty() const
465 return maData
.empty();
468 ScChartArray
* ScChartCollection::operator[](size_t nIndex
)
470 if (maData
.size() <= nIndex
)
472 return &maData
[nIndex
];
475 const ScChartArray
* ScChartCollection::operator[](size_t nIndex
) const
477 if (maData
.size() <= nIndex
)
479 return &maData
[nIndex
];
482 bool ScChartCollection::operator==(const ScChartCollection
& rCmp
) const
484 return maData
== rCmp
.maData
;
487 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */