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 .
22 #include <chartarr.hxx>
23 #include <cellvalue.hxx>
24 #include <document.hxx>
25 #include <globstr.hrc>
26 #include <scresid.hxx>
27 #include <formulacell.hxx>
28 #include <docoptio.hxx>
30 #include <formula/errorcodes.hxx>
37 ScMemChart::ScMemChart(SCCOL nCols
, SCROW nRows
)
41 pData
.reset( new double[nColCnt
* nRowCnt
] );
43 memset( pData
.get(), 0.0, nColCnt
* nRowCnt
);
45 pColText
.reset( new OUString
[nColCnt
] );
46 pRowText
.reset( new OUString
[nRowCnt
] );
49 ScMemChart::~ScMemChart()
53 ScChartArray::ScChartArray(
54 ScDocument
& rDoc
, const ScRangeListRef
& rRangeList
) :
56 aPositioner(rDoc
, rRangeList
) {}
58 std::unique_ptr
<ScMemChart
> ScChartArray::CreateMemChart()
60 ScRangeListRef
aRangeListRef(GetRangeList());
61 size_t nCount
= aRangeListRef
->size();
63 return CreateMemChartMulti();
64 else if ( nCount
== 1 )
66 const ScRange
& rR
= aRangeListRef
->front();
67 if ( rR
.aStart
.Tab() != rR
.aEnd
.Tab() )
68 return CreateMemChartMulti();
70 return CreateMemChartSingle();
73 return CreateMemChartMulti(); // Can handle 0 range better than Single
78 double getCellValue( ScDocument
& rDoc
, const ScAddress
& rPos
, double fDefault
, bool bCalcAsShown
)
80 double fRet
= fDefault
;
82 ScRefCellValue
aCell(rDoc
, rPos
);
83 switch (aCell
.getType())
87 fRet
= aCell
.getValue();
88 if (bCalcAsShown
&& fRet
!= 0.0)
90 sal_uInt32 nFormat
= rDoc
.GetNumberFormat(rPos
);
91 fRet
= rDoc
.RoundValueAsShown(fRet
, nFormat
);
95 case CELLTYPE_FORMULA
:
97 ScFormulaCell
* pFCell
= aCell
.getFormula();
98 if (pFCell
&& pFCell
->GetErrCode() == FormulaError::NONE
&& pFCell
->IsValue())
99 fRet
= pFCell
->GetValue();
110 std::unique_ptr
<ScMemChart
> ScChartArray::CreateMemChartSingle()
115 // real size (without hidden rows/columns)
117 SCCOL nColAdd
= HasRowHeaders() ? 1 : 0;
118 SCROW nRowAdd
= HasColHeaders() ? 1 : 0;
126 ScRangeListRef
aRangeListRef(GetRangeList());
127 aRangeListRef
->front().GetVars( nCol1
, nRow1
, nTab1
, nCol2
, nRow2
, nTab2
);
129 SCCOL nStrCol
= nCol1
; // remember for labeling
130 SCROW nStrRow
= nRow1
;
131 // Skip hidden columns.
132 // TODO: make use of last column value once implemented.
134 while (rDocument
.ColHidden(nCol1
, nTab1
, nullptr, &nLastCol
))
139 if (rDocument
.RowHidden(nRow1
, nTab1
, nullptr, &nLastRow
))
140 nRow1
= nLastRow
+ 1;
142 // if everything is hidden then the label remains at the beginning
143 if ( nCol1
<= nCol2
)
146 nCol1
= sal::static_int_cast
<SCCOL
>( nCol1
+ nColAdd
);
148 if ( nRow1
<= nRow2
)
151 nRow1
= sal::static_int_cast
<SCROW
>( nRow1
+ nRowAdd
);
154 SCSIZE nTotalCols
= ( nCol1
<= nCol2
? nCol2
- nCol1
+ 1 : 0 );
156 aCols
.reserve(nTotalCols
);
157 for (SCSIZE i
=0; i
<nTotalCols
; i
++)
159 SCCOL nThisCol
= sal::static_int_cast
<SCCOL
>(nCol1
+i
);
160 if (!rDocument
.ColHidden(nThisCol
, nTab1
, nullptr, &nLastCol
))
161 aCols
.push_back(nThisCol
);
163 SCSIZE nColCount
= aCols
.size();
165 SCSIZE nTotalRows
= ( nRow1
<= nRow2
? nRow2
- nRow1
+ 1 : 0 );
167 aRows
.reserve(nTotalRows
);
170 // Get all visible rows between nRow1 and nRow2.
171 SCROW nThisRow
= nRow1
;
172 while (nThisRow
<= nRow2
)
174 if (rDocument
.RowHidden(nThisRow
, nTab1
, nullptr, &nLastRow
))
177 aRows
.push_back(nThisRow
);
181 SCSIZE nRowCount
= aRows
.size();
183 // May happen at least with more than 32k rows.
184 if (nColCount
> SHRT_MAX
|| nRowCount
> SHRT_MAX
)
190 bool bValidData
= true;
195 aCols
.push_back(nStrCol
);
201 aRows
.push_back(nStrRow
);
205 std::unique_ptr
<ScMemChart
> pMemChart(new ScMemChart( nColCount
, nRowCount
));
209 bool bCalcAsShown
= rDocument
.GetDocOptions().IsCalcAsShown();
210 for (nCol
=0; nCol
<nColCount
; nCol
++)
212 for (nRow
=0; nRow
<nRowCount
; nRow
++)
214 // DBL_MIN is a Hack for Chart to recognize empty cells.
215 ScAddress
aPos(aCols
[nCol
], aRows
[nRow
], nTab1
);
216 double nVal
= getCellValue(rDocument
, aPos
, DBL_MIN
, bCalcAsShown
);
217 pMemChart
->SetData(nCol
, nRow
, nVal
);
223 // Flag marking data as invalid?
224 for (nCol
=0; nCol
<nColCount
; nCol
++)
225 for (nRow
=0; nRow
<nRowCount
; nRow
++)
226 pMemChart
->SetData( nCol
, nRow
, DBL_MIN
);
231 for (nCol
=0; nCol
<nColCount
; nCol
++)
235 aString
= rDocument
.GetString(aCols
[nCol
], nStrRow
, nTab1
);
236 if (aString
.isEmpty())
238 ScAddress
aPos( aCols
[ nCol
], 0, 0 );
239 aString
= ScResId(STR_COLUMN
) + " " +
240 aPos
.Format(ScRefFlags::COL_VALID
);
242 pMemChart
->SetColText( nCol
, aString
);
247 for (nRow
=0; nRow
<nRowCount
; nRow
++)
252 aString
= rDocument
.GetString(nStrCol
, aRows
[nRow
], nTab1
);
254 if (aString
.isEmpty())
256 aString
= ScResId(STR_ROW
) + " " +
257 OUString::number(static_cast<sal_Int32
>(aRows
[nRow
]+1));
259 pMemChart
->SetRowText( nRow
, aString
);
265 std::unique_ptr
<ScMemChart
> ScChartArray::CreateMemChartMulti()
267 SCSIZE nColCount
= GetPositionMap()->GetColCount();
268 SCSIZE nRowCount
= GetPositionMap()->GetRowCount();
270 // May happen at least with more than 32k rows.
271 if (nColCount
> SHRT_MAX
|| nRowCount
> SHRT_MAX
)
277 bool bValidData
= true;
290 std::unique_ptr
<ScMemChart
> pMemChart(new ScMemChart( nColCount
, nRowCount
));
294 bool bCalcAsShown
= rDocument
.GetDocOptions().IsCalcAsShown();
295 sal_uLong nIndex
= 0;
298 for ( nCol
= 0; nCol
< nColCount
; nCol
++ )
300 for ( nRow
= 0; nRow
< nRowCount
; nRow
++, nIndex
++ )
302 double nVal
= DBL_MIN
; // Hack for Chart to recognize empty cells
303 const ScAddress
* pPos
= GetPositionMap()->GetPosition( nIndex
);
306 nVal
= getCellValue(rDocument
, *pPos
, DBL_MIN
, bCalcAsShown
);
308 pMemChart
->SetData(nCol
, nRow
, nVal
);
314 for ( nRow
= 0; nRow
< nRowCount
; nRow
++, nIndex
++ )
316 double nVal
= DBL_MIN
; // Hack for Chart to recognize empty cells
317 const ScAddress
* pPos
= GetPositionMap()->GetPosition( nIndex
);
320 nVal
= getCellValue(rDocument
, *pPos
, DBL_MIN
, bCalcAsShown
);
322 pMemChart
->SetData(nCol
, nRow
, nVal
);
326 //TODO: Label when gaps
331 for ( nCol
= 0; nCol
< nColCount
; nCol
++ )
334 const ScAddress
* pPos
= GetPositionMap()->GetColHeaderPosition( static_cast<SCCOL
>(nCol
) );
335 if ( HasColHeaders() && pPos
)
336 aString
= rDocument
.GetString(pPos
->Col(), pPos
->Row(), pPos
->Tab());
338 if (aString
.isEmpty())
341 nPosCol
= pPos
->Col() + 1;
344 ScAddress
aPos( nPosCol
- 1, 0, 0 );
345 aString
= ScResId(STR_COLUMN
) + " " + aPos
.Format(ScRefFlags::COL_VALID
);
347 pMemChart
->SetColText( nCol
, aString
);
353 for ( nRow
= 0; nRow
< nRowCount
; nRow
++ )
356 const ScAddress
* pPos
= GetPositionMap()->GetRowHeaderPosition( nRow
);
357 if ( HasRowHeaders() && pPos
)
358 aString
= rDocument
.GetString(pPos
->Col(), pPos
->Row(), pPos
->Tab());
360 if (aString
.isEmpty())
363 nPosRow
= pPos
->Row() + 1;
366 aString
= ScResId(STR_ROW
) + " " + OUString::number(static_cast<sal_Int32
>(nPosRow
));
368 pMemChart
->SetRowText( nRow
, aString
);
374 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */