LibreOffice Module sc (master) 1
chartarr.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
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 .
18 */
19
20#include <float.h>
21
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>
29
31
32#include <memory>
33#include <vector>
34
35using ::std::vector;
36
38{
39 nRowCnt = nRows;
40 nColCnt = nCols;
41 pData.reset( new double[nColCnt * nRowCnt] );
42
43 memset( pData.get(), 0.0, nColCnt * nRowCnt );
44
45 pColText.reset( new OUString[nColCnt] );
46 pRowText.reset( new OUString[nRowCnt] );
47}
48
50{
51}
52
54 ScDocument& rDoc, const ScRangeListRef& rRangeList ) :
55 rDocument( rDoc ),
56 aPositioner(rDoc, rRangeList) {}
57
58std::unique_ptr<ScMemChart> ScChartArray::CreateMemChart()
59{
60 ScRangeListRef aRangeListRef(GetRangeList());
61 size_t nCount = aRangeListRef->size();
62 if ( nCount > 1 )
63 return CreateMemChartMulti();
64 else if ( nCount == 1 )
65 {
66 const ScRange & rR = aRangeListRef->front();
67 if ( rR.aStart.Tab() != rR.aEnd.Tab() )
68 return CreateMemChartMulti();
69 else
70 return CreateMemChartSingle();
71 }
72 else
73 return CreateMemChartMulti(); // Can handle 0 range better than Single
74}
75
76namespace {
77
78double getCellValue( ScDocument& rDoc, const ScAddress& rPos, double fDefault, bool bCalcAsShown )
79{
80 double fRet = fDefault;
81
82 ScRefCellValue aCell(rDoc, rPos);
83 switch (aCell.getType())
84 {
85 case CELLTYPE_VALUE:
86 {
87 fRet = aCell.getValue();
88 if (bCalcAsShown && fRet != 0.0)
89 {
90 sal_uInt32 nFormat = rDoc.GetNumberFormat(rPos);
91 fRet = rDoc.RoundValueAsShown(fRet, nFormat);
92 }
93 }
94 break;
96 {
97 ScFormulaCell* pFCell = aCell.getFormula();
98 if (pFCell && pFCell->GetErrCode() == FormulaError::NONE && pFCell->IsValue())
99 fRet = pFCell->GetValue();
100 }
101 break;
102 default:
103 ;
104 }
105 return fRet;
106}
107
108}
109
110std::unique_ptr<ScMemChart> ScChartArray::CreateMemChartSingle()
111{
112 SCSIZE nCol;
113 SCSIZE nRow;
114
115 // real size (without hidden rows/columns)
116
117 SCCOL nColAdd = HasRowHeaders() ? 1 : 0;
118 SCROW nRowAdd = HasColHeaders() ? 1 : 0;
119
120 SCCOL nCol1;
121 SCROW nRow1;
122 SCTAB nTab1;
123 SCCOL nCol2;
124 SCROW nRow2;
125 SCTAB nTab2;
126 ScRangeListRef aRangeListRef(GetRangeList());
127 aRangeListRef->front().GetVars( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 );
128
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.
133 SCCOL nLastCol = -1;
134 while (rDocument.ColHidden(nCol1, nTab1, nullptr, &nLastCol))
135 ++nCol1;
136
137 // Skip hidden rows.
138 SCROW nLastRow = -1;
139 if (rDocument.RowHidden(nRow1, nTab1, nullptr, &nLastRow))
140 nRow1 = nLastRow + 1;
141
142 // if everything is hidden then the label remains at the beginning
143 if ( nCol1 <= nCol2 )
144 {
145 nStrCol = nCol1;
146 nCol1 = sal::static_int_cast<SCCOL>( nCol1 + nColAdd );
147 }
148 if ( nRow1 <= nRow2 )
149 {
150 nStrRow = nRow1;
151 nRow1 = sal::static_int_cast<SCROW>( nRow1 + nRowAdd );
152 }
153
154 SCSIZE nTotalCols = ( nCol1 <= nCol2 ? nCol2 - nCol1 + 1 : 0 );
155 vector<SCCOL> aCols;
156 aCols.reserve(nTotalCols);
157 for (SCSIZE i=0; i<nTotalCols; i++)
158 {
159 SCCOL nThisCol = sal::static_int_cast<SCCOL>(nCol1+i);
160 if (!rDocument.ColHidden(nThisCol, nTab1, nullptr, &nLastCol))
161 aCols.push_back(nThisCol);
162 }
163 SCSIZE nColCount = aCols.size();
164
165 SCSIZE nTotalRows = ( nRow1 <= nRow2 ? nRow2 - nRow1 + 1 : 0 );
166 vector<SCROW> aRows;
167 aRows.reserve(nTotalRows);
168 if (nRow1 <= nRow2)
169 {
170 // Get all visible rows between nRow1 and nRow2.
171 SCROW nThisRow = nRow1;
172 while (nThisRow <= nRow2)
173 {
174 if (rDocument.RowHidden(nThisRow, nTab1, nullptr, &nLastRow))
175 nThisRow = nLastRow;
176 else
177 aRows.push_back(nThisRow);
178 ++nThisRow;
179 }
180 }
181 SCSIZE nRowCount = aRows.size();
182
183 // May happen at least with more than 32k rows.
184 if (nColCount > SHRT_MAX || nRowCount > SHRT_MAX)
185 {
186 nColCount = 0;
187 nRowCount = 0;
188 }
189
190 bool bValidData = true;
191 if ( !nColCount )
192 {
193 bValidData = false;
194 nColCount = 1;
195 aCols.push_back(nStrCol);
196 }
197 if ( !nRowCount )
198 {
199 bValidData = false;
200 nRowCount = 1;
201 aRows.push_back(nStrRow);
202 }
203
204 // Data
205 std::unique_ptr<ScMemChart> pMemChart(new ScMemChart( nColCount, nRowCount ));
206
207 if ( bValidData )
208 {
209 bool bCalcAsShown = rDocument.GetDocOptions().IsCalcAsShown();
210 for (nCol=0; nCol<nColCount; nCol++)
211 {
212 for (nRow=0; nRow<nRowCount; nRow++)
213 {
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);
218 }
219 }
220 }
221 else
222 {
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 );
227 }
228
229 // Column Header
230
231 for (nCol=0; nCol<nColCount; nCol++)
232 {
233 OUString aString;
234 if (HasColHeaders())
235 aString = rDocument.GetString(aCols[nCol], nStrRow, nTab1);
236 if (aString.isEmpty())
237 {
238 ScAddress aPos( aCols[ nCol ], 0, 0 );
239 aString = ScResId(STR_COLUMN) + " " +
241 }
242 pMemChart->SetColText( nCol, aString);
243 }
244
245 // Row Header
246
247 for (nRow=0; nRow<nRowCount; nRow++)
248 {
249 OUString aString;
250 if (HasRowHeaders())
251 {
252 aString = rDocument.GetString(nStrCol, aRows[nRow], nTab1);
253 }
254 if (aString.isEmpty())
255 {
256 OUStringBuffer aBuf;
257 aBuf.append(ScResId(STR_ROW));
258 aBuf.append(' ');
259 aBuf.append(static_cast<sal_Int32>(aRows[nRow]+1));
260 aString = aBuf.makeStringAndClear();
261 }
262 pMemChart->SetRowText( nRow, aString);
263 }
264
265 return pMemChart;
266}
267
268std::unique_ptr<ScMemChart> ScChartArray::CreateMemChartMulti()
269{
270 SCSIZE nColCount = GetPositionMap()->GetColCount();
271 SCSIZE nRowCount = GetPositionMap()->GetRowCount();
272
273 // May happen at least with more than 32k rows.
274 if (nColCount > SHRT_MAX || nRowCount > SHRT_MAX)
275 {
276 nColCount = 0;
277 nRowCount = 0;
278 }
279
280 bool bValidData = true;
281 if ( !nColCount )
282 {
283 bValidData = false;
284 nColCount = 1;
285 }
286 if ( !nRowCount )
287 {
288 bValidData = false;
289 nRowCount = 1;
290 }
291
292 // Data
293 std::unique_ptr<ScMemChart> pMemChart(new ScMemChart( nColCount, nRowCount ));
294
295 SCSIZE nCol = 0;
296 SCSIZE nRow = 0;
297 bool bCalcAsShown = rDocument.GetDocOptions().IsCalcAsShown();
298 sal_uLong nIndex = 0;
299 if (bValidData)
300 {
301 for ( nCol = 0; nCol < nColCount; nCol++ )
302 {
303 for ( nRow = 0; nRow < nRowCount; nRow++, nIndex++ )
304 {
305 double nVal = DBL_MIN; // Hack for Chart to recognize empty cells
306 const ScAddress* pPos = GetPositionMap()->GetPosition( nIndex );
307 if (pPos)
308 // otherwise: Gap
309 nVal = getCellValue(rDocument, *pPos, DBL_MIN, bCalcAsShown);
310
311 pMemChart->SetData(nCol, nRow, nVal);
312 }
313 }
314 }
315 else
316 {
317 for ( nRow = 0; nRow < nRowCount; nRow++, nIndex++ )
318 {
319 double nVal = DBL_MIN; // Hack for Chart to recognize empty cells
320 const ScAddress* pPos = GetPositionMap()->GetPosition( nIndex );
321 if (pPos)
322 // otherwise: Gap
323 nVal = getCellValue(rDocument, *pPos, DBL_MIN, bCalcAsShown);
324
325 pMemChart->SetData(nCol, nRow, nVal);
326 }
327 }
328
329 //TODO: Label when gaps
330
331 // Column header
332
333 SCCOL nPosCol = 0;
334 for ( nCol = 0; nCol < nColCount; nCol++ )
335 {
336 OUString aString;
337 const ScAddress* pPos = GetPositionMap()->GetColHeaderPosition( static_cast<SCCOL>(nCol) );
338 if ( HasColHeaders() && pPos )
339 aString = rDocument.GetString(pPos->Col(), pPos->Row(), pPos->Tab());
340
341 if (aString.isEmpty())
342 {
343 if ( pPos )
344 nPosCol = pPos->Col() + 1;
345 else
346 nPosCol++;
347 ScAddress aPos( nPosCol - 1, 0, 0 );
348 aString = ScResId(STR_COLUMN) + " " + aPos.Format(ScRefFlags::COL_VALID);
349 }
350 pMemChart->SetColText( nCol, aString);
351 }
352
353 // Row header
354
355 SCROW nPosRow = 0;
356 for ( nRow = 0; nRow < nRowCount; nRow++ )
357 {
358 OUString aString;
359 const ScAddress* pPos = GetPositionMap()->GetRowHeaderPosition( nRow );
360 if ( HasRowHeaders() && pPos )
361 aString = rDocument.GetString(pPos->Col(), pPos->Row(), pPos->Tab());
362
363 if (aString.isEmpty())
364 {
365 if ( pPos )
366 nPosRow = pPos->Row() + 1;
367 else
368 nPosRow++;
369 aString = ScResId(STR_ROW) + " " + OUString::number(static_cast<sal_Int32>(nPosRow));
370 }
371 pMemChart->SetRowText( nRow, aString);
372 }
373
374 return pMemChart;
375}
376
377/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
size_t SCSIZE
size_t typedef to be able to find places where code was changed from USHORT to size_t and is used to ...
Definition: address.hxx:44
SCTAB Tab() const
Definition: address.hxx:283
SC_DLLPUBLIC void Format(OStringBuffer &r, ScRefFlags nFlags, const ScDocument *pDocument=nullptr, const Details &rDetails=detailsOOOa1) const
Definition: address.cxx:2074
SCROW Row() const
Definition: address.hxx:274
SCCOL Col() const
Definition: address.hxx:279
const ScRangeListRef & GetRangeList() const
Definition: chartarr.hxx:72
const ScChartPositionMap * GetPositionMap()
Definition: chartarr.hxx:73
ScChartArray(ScDocument &rDoc, const ScRangeListRef &rRangeList)
Definition: chartarr.cxx:53
bool HasRowHeaders() const
Definition: chartarr.hxx:77
bool HasColHeaders() const
Definition: chartarr.hxx:76
std::unique_ptr< ScMemChart > CreateMemChartMulti()
Definition: chartarr.cxx:268
std::unique_ptr< ScMemChart > CreateMemChartSingle()
Definition: chartarr.cxx:110
std::unique_ptr< ScMemChart > CreateMemChart()
Definition: chartarr.cxx:58
ScDocument & rDocument
Definition: chartarr.hxx:62
const ScAddress * GetRowHeaderPosition(SCROW nChartRow) const
Definition: chartpos.hxx:84
const ScAddress * GetColHeaderPosition(SCCOL nChartCol) const
Definition: chartpos.hxx:78
const ScAddress * GetPosition(sal_uInt64 nIndex) const
Definition: chartpos.hxx:64
SCROW GetRowCount() const
Definition: chartpos.hxx:56
SCCOL GetColCount() const
deletes all ScAddress*
Definition: chartpos.hxx:55
bool IsCalcAsShown() const
Definition: docoptio.hxx:81
SC_DLLPUBLIC sal_uInt32 GetNumberFormat(SCCOL nCol, SCROW nRow, SCTAB nTab) const
Definition: document.cxx:3686
SC_DLLPUBLIC double RoundValueAsShown(double fVal, sal_uInt32 nFormat, const ScInterpreterContext *pContext=nullptr) const
Definition: documen4.cxx:634
SC_DLLPUBLIC bool RowHidden(SCROW nRow, SCTAB nTab, SCROW *pFirstRow=nullptr, SCROW *pLastRow=nullptr) const
Definition: document.cxx:4493
SC_DLLPUBLIC bool ColHidden(SCCOL nCol, SCTAB nTab, SCCOL *pFirstCol=nullptr, SCCOL *pLastCol=nullptr) const
Definition: document.cxx:4509
SC_DLLPUBLIC OUString GetString(SCCOL nCol, SCROW nRow, SCTAB nTab, const ScInterpreterContext *pContext=nullptr) const
Definition: document.cxx:3545
SC_DLLPUBLIC const ScDocOptions & GetDocOptions() const
Definition: documen3.cxx:1952
double GetValue()
FormulaError GetErrCode()
SCCOL nColCnt
Definition: chartarr.hxx:36
std::unique_ptr< double[]> pData
Definition: chartarr.hxx:37
ScMemChart(const ScMemChart &rMemChart)=delete
SCROW nRowCnt
Definition: chartarr.hxx:35
std::unique_ptr< OUString[]> pColText
Definition: chartarr.hxx:38
std::unique_ptr< OUString[]> pRowText
Definition: chartarr.hxx:39
ScAddress aEnd
Definition: address.hxx:498
ScAddress aStart
Definition: address.hxx:497
int nCount
@ CELLTYPE_FORMULA
Definition: global.hxx:275
@ CELLTYPE_VALUE
Definition: global.hxx:273
sal_Int32 nIndex
aBuf
int i
OUString ScResId(TranslateId aId)
Definition: scdll.cxx:90
sal_uIntPtr sal_uLong
This is very similar to ScCellValue, except that it references the original value instead of copying ...
Definition: cellvalue.hxx:108
sal_Int16 SCTAB
Definition: types.hxx:22
sal_Int16 SCCOL
Definition: types.hxx:21
sal_Int32 SCROW
Definition: types.hxx:17