Stop leaking all ScPostIt instances.
[LibreOffice.git] / sc / source / core / tool / rangeseq.cxx
blobfcdd17ea11e7c5df7d3fca5ab354e90df74bd10e
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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 <svl/zforlist.hxx>
21 #include <rtl/math.hxx>
23 #include <com/sun/star/uno/Any.hxx>
24 #include <com/sun/star/uno/Sequence.hxx>
25 #include <comphelper/string.hxx>
26 #include "rangeseq.hxx"
27 #include "document.hxx"
28 #include "dociter.hxx"
29 #include "scmatrix.hxx"
30 #include "formulacell.hxx"
32 using namespace com::sun::star;
34 static bool lcl_HasErrors( ScDocument* pDoc, const ScRange& rRange )
36 // no need to look at empty cells - just use ScCellIterator
37 ScCellIterator aIter( pDoc, rRange );
38 for (bool bHas = aIter.first(); bHas; bHas = aIter.next())
40 if (aIter.getType() != CELLTYPE_FORMULA)
41 continue;
43 ScFormulaCell* pCell = aIter.getFormulaCell();
44 if (pCell->GetErrCode() != 0)
45 return true;
47 return false; // no error found
50 static long lcl_DoubleToLong( double fVal )
52 double fInt = (fVal >= 0.0) ? ::rtl::math::approxFloor( fVal ) :
53 ::rtl::math::approxCeil( fVal );
54 if ( fInt >= LONG_MIN && fInt <= LONG_MAX )
55 return (long)fInt;
56 else
57 return 0; // out of range
60 sal_Bool ScRangeToSequence::FillLongArray( uno::Any& rAny, ScDocument* pDoc, const ScRange& rRange )
62 SCTAB nTab = rRange.aStart.Tab();
63 SCCOL nStartCol = rRange.aStart.Col();
64 SCROW nStartRow = rRange.aStart.Row();
65 long nColCount = rRange.aEnd.Col() + 1 - rRange.aStart.Col();
66 long nRowCount = rRange.aEnd.Row() + 1 - rRange.aStart.Row();
68 uno::Sequence< uno::Sequence<sal_Int32> > aRowSeq( nRowCount );
69 uno::Sequence<sal_Int32>* pRowAry = aRowSeq.getArray();
70 for (long nRow = 0; nRow < nRowCount; nRow++)
72 uno::Sequence<sal_Int32> aColSeq( nColCount );
73 sal_Int32* pColAry = aColSeq.getArray();
74 for (long nCol = 0; nCol < nColCount; nCol++)
75 pColAry[nCol] = lcl_DoubleToLong( pDoc->GetValue(
76 ScAddress( (SCCOL)(nStartCol+nCol), (SCROW)(nStartRow+nRow), nTab ) ) );
78 pRowAry[nRow] = aColSeq;
81 rAny <<= aRowSeq;
82 return !lcl_HasErrors( pDoc, rRange );
85 sal_Bool ScRangeToSequence::FillLongArray( uno::Any& rAny, const ScMatrix* pMatrix )
87 if (!pMatrix)
88 return false;
90 SCSIZE nColCount;
91 SCSIZE nRowCount;
92 pMatrix->GetDimensions( nColCount, nRowCount );
94 uno::Sequence< uno::Sequence<sal_Int32> > aRowSeq( static_cast<sal_Int32>(nRowCount) );
95 uno::Sequence<sal_Int32>* pRowAry = aRowSeq.getArray();
96 for (SCSIZE nRow = 0; nRow < nRowCount; nRow++)
98 uno::Sequence<sal_Int32> aColSeq( static_cast<sal_Int32>(nColCount) );
99 sal_Int32* pColAry = aColSeq.getArray();
100 for (SCSIZE nCol = 0; nCol < nColCount; nCol++)
101 if ( pMatrix->IsString( nCol, nRow ) )
102 pColAry[nCol] = 0;
103 else
104 pColAry[nCol] = lcl_DoubleToLong( pMatrix->GetDouble( nCol, nRow ) );
106 pRowAry[nRow] = aColSeq;
109 rAny <<= aRowSeq;
110 return sal_True;
113 sal_Bool ScRangeToSequence::FillDoubleArray( uno::Any& rAny, ScDocument* pDoc, const ScRange& rRange )
115 SCTAB nTab = rRange.aStart.Tab();
116 SCCOL nStartCol = rRange.aStart.Col();
117 SCROW nStartRow = rRange.aStart.Row();
118 long nColCount = rRange.aEnd.Col() + 1 - rRange.aStart.Col();
119 long nRowCount = rRange.aEnd.Row() + 1 - rRange.aStart.Row();
121 uno::Sequence< uno::Sequence<double> > aRowSeq( nRowCount );
122 uno::Sequence<double>* pRowAry = aRowSeq.getArray();
123 for (long nRow = 0; nRow < nRowCount; nRow++)
125 uno::Sequence<double> aColSeq( nColCount );
126 double* pColAry = aColSeq.getArray();
127 for (long nCol = 0; nCol < nColCount; nCol++)
128 pColAry[nCol] = pDoc->GetValue(
129 ScAddress( (SCCOL)(nStartCol+nCol), (SCROW)(nStartRow+nRow), nTab ) );
131 pRowAry[nRow] = aColSeq;
134 rAny <<= aRowSeq;
135 return !lcl_HasErrors( pDoc, rRange );
138 sal_Bool ScRangeToSequence::FillDoubleArray( uno::Any& rAny, const ScMatrix* pMatrix )
140 if (!pMatrix)
141 return false;
143 SCSIZE nColCount;
144 SCSIZE nRowCount;
145 pMatrix->GetDimensions( nColCount, nRowCount );
147 uno::Sequence< uno::Sequence<double> > aRowSeq( static_cast<sal_Int32>(nRowCount) );
148 uno::Sequence<double>* pRowAry = aRowSeq.getArray();
149 for (SCSIZE nRow = 0; nRow < nRowCount; nRow++)
151 uno::Sequence<double> aColSeq( static_cast<sal_Int32>(nColCount) );
152 double* pColAry = aColSeq.getArray();
153 for (SCSIZE nCol = 0; nCol < nColCount; nCol++)
154 if ( pMatrix->IsString( nCol, nRow ) )
155 pColAry[nCol] = 0.0;
156 else
157 pColAry[nCol] = pMatrix->GetDouble( nCol, nRow );
159 pRowAry[nRow] = aColSeq;
162 rAny <<= aRowSeq;
163 return sal_True;
166 sal_Bool ScRangeToSequence::FillStringArray( uno::Any& rAny, ScDocument* pDoc, const ScRange& rRange )
168 SCTAB nTab = rRange.aStart.Tab();
169 SCCOL nStartCol = rRange.aStart.Col();
170 SCROW nStartRow = rRange.aStart.Row();
171 long nColCount = rRange.aEnd.Col() + 1 - rRange.aStart.Col();
172 long nRowCount = rRange.aEnd.Row() + 1 - rRange.aStart.Row();
174 bool bHasErrors = false;
176 uno::Sequence< uno::Sequence<OUString> > aRowSeq( nRowCount );
177 uno::Sequence<OUString>* pRowAry = aRowSeq.getArray();
178 for (long nRow = 0; nRow < nRowCount; nRow++)
180 uno::Sequence<OUString> aColSeq( nColCount );
181 OUString* pColAry = aColSeq.getArray();
182 for (long nCol = 0; nCol < nColCount; nCol++)
184 sal_uInt16 nErrCode = pDoc->GetStringForFormula(
185 ScAddress((SCCOL)(nStartCol+nCol), (SCROW)(nStartRow+nRow), nTab),
186 pColAry[nCol] );
187 if ( nErrCode != 0 )
188 bHasErrors = true;
190 pRowAry[nRow] = aColSeq;
193 rAny <<= aRowSeq;
194 return !bHasErrors;
197 sal_Bool ScRangeToSequence::FillStringArray( uno::Any& rAny, const ScMatrix* pMatrix,
198 SvNumberFormatter* pFormatter )
200 if (!pMatrix)
201 return false;
203 SCSIZE nColCount;
204 SCSIZE nRowCount;
205 pMatrix->GetDimensions( nColCount, nRowCount );
207 uno::Sequence< uno::Sequence<OUString> > aRowSeq( static_cast<sal_Int32>(nRowCount) );
208 uno::Sequence<OUString>* pRowAry = aRowSeq.getArray();
209 for (SCSIZE nRow = 0; nRow < nRowCount; nRow++)
211 uno::Sequence<OUString> aColSeq( static_cast<sal_Int32>(nColCount) );
212 OUString* pColAry = aColSeq.getArray();
213 for (SCSIZE nCol = 0; nCol < nColCount; nCol++)
215 OUString aStr;
216 if ( pMatrix->IsString( nCol, nRow ) )
218 if ( !pMatrix->IsEmpty( nCol, nRow ) )
219 aStr = pMatrix->GetString(nCol, nRow).getString();
221 else if ( pFormatter )
223 double fVal = pMatrix->GetDouble( nCol, nRow );
224 Color* pColor;
225 pFormatter->GetOutputString( fVal, 0, aStr, &pColor );
227 pColAry[nCol] = aStr;
230 pRowAry[nRow] = aColSeq;
233 rAny <<= aRowSeq;
234 return sal_True;
237 sal_Bool ScRangeToSequence::FillMixedArray( uno::Any& rAny, ScDocument* pDoc, const ScRange& rRange,
238 sal_Bool bAllowNV )
240 SCTAB nTab = rRange.aStart.Tab();
241 SCCOL nStartCol = rRange.aStart.Col();
242 SCROW nStartRow = rRange.aStart.Row();
243 long nColCount = rRange.aEnd.Col() + 1 - rRange.aStart.Col();
244 long nRowCount = rRange.aEnd.Row() + 1 - rRange.aStart.Row();
246 sal_Bool bHasErrors = false;
248 uno::Sequence< uno::Sequence<uno::Any> > aRowSeq( nRowCount );
249 uno::Sequence<uno::Any>* pRowAry = aRowSeq.getArray();
250 for (long nRow = 0; nRow < nRowCount; nRow++)
252 uno::Sequence<uno::Any> aColSeq( nColCount );
253 uno::Any* pColAry = aColSeq.getArray();
254 for (long nCol = 0; nCol < nColCount; nCol++)
256 uno::Any& rElement = pColAry[nCol];
258 ScAddress aPos( (SCCOL)(nStartCol+nCol), (SCROW)(nStartRow+nRow), nTab );
259 ScRefCellValue aCell;
260 aCell.assign(*pDoc, aPos);
262 if (aCell.isEmpty())
264 rElement <<= EMPTY_OUSTRING;
265 continue;
268 if (aCell.meType == CELLTYPE_FORMULA && aCell.mpFormula->GetErrCode() != 0)
270 // if NV is allowed, leave empty for errors
271 bHasErrors = true;
273 else if (aCell.hasNumeric())
274 rElement <<= aCell.getValue();
275 else
276 rElement <<= aCell.getString(pDoc);
278 pRowAry[nRow] = aColSeq;
281 rAny <<= aRowSeq;
282 return bAllowNV || !bHasErrors;
285 sal_Bool ScRangeToSequence::FillMixedArray( uno::Any& rAny, const ScMatrix* pMatrix, bool bDataTypes )
287 if (!pMatrix)
288 return false;
290 SCSIZE nColCount;
291 SCSIZE nRowCount;
292 pMatrix->GetDimensions( nColCount, nRowCount );
294 uno::Sequence< uno::Sequence<uno::Any> > aRowSeq( static_cast<sal_Int32>(nRowCount) );
295 uno::Sequence<uno::Any>* pRowAry = aRowSeq.getArray();
296 for (SCSIZE nRow = 0; nRow < nRowCount; nRow++)
298 uno::Sequence<uno::Any> aColSeq( static_cast<sal_Int32>(nColCount) );
299 uno::Any* pColAry = aColSeq.getArray();
300 for (SCSIZE nCol = 0; nCol < nColCount; nCol++)
302 if ( pMatrix->IsString( nCol, nRow ) )
304 OUString aStr;
305 if ( !pMatrix->IsEmpty( nCol, nRow ) )
306 aStr = pMatrix->GetString(nCol, nRow).getString();
307 pColAry[nCol] <<= aStr;
309 else
311 double fVal = pMatrix->GetDouble( nCol, nRow );
312 if (bDataTypes && pMatrix->IsBoolean( nCol, nRow ))
313 pColAry[nCol] <<= (fVal ? true : false);
314 else
315 pColAry[nCol] <<= fVal;
319 pRowAry[nRow] = aColSeq;
322 rAny <<= aRowSeq;
323 return sal_True;
326 bool ScApiTypeConversion::ConvertAnyToDouble( double & o_fVal,
327 com::sun::star::uno::TypeClass & o_eClass,
328 const com::sun::star::uno::Any & rAny )
330 bool bRet = false;
331 o_eClass = rAny.getValueTypeClass();
332 switch (o_eClass)
334 //! extract integer values
335 case uno::TypeClass_ENUM:
336 case uno::TypeClass_BOOLEAN:
337 case uno::TypeClass_CHAR:
338 case uno::TypeClass_BYTE:
339 case uno::TypeClass_SHORT:
340 case uno::TypeClass_UNSIGNED_SHORT:
341 case uno::TypeClass_LONG:
342 case uno::TypeClass_UNSIGNED_LONG:
343 case uno::TypeClass_FLOAT:
344 case uno::TypeClass_DOUBLE:
345 rAny >>= o_fVal;
346 bRet = true;
347 break;
348 default:
349 ; // nothing, avoid warning
351 if (!bRet)
352 o_fVal = 0.0;
353 return bRet;
356 ScMatrixRef ScSequenceToMatrix::CreateMixedMatrix( const com::sun::star::uno::Any & rAny )
358 ScMatrixRef xMatrix;
359 uno::Sequence< uno::Sequence< uno::Any > > aSequence;
360 if ( rAny >>= aSequence )
362 sal_Int32 nRowCount = aSequence.getLength();
363 const uno::Sequence<uno::Any>* pRowArr = aSequence.getConstArray();
364 sal_Int32 nMaxColCount = 0;
365 sal_Int32 nCol, nRow;
366 for (nRow=0; nRow<nRowCount; nRow++)
368 sal_Int32 nTmp = pRowArr[nRow].getLength();
369 if ( nTmp > nMaxColCount )
370 nMaxColCount = nTmp;
372 if ( nMaxColCount && nRowCount )
374 OUString aUStr;
375 xMatrix = new ScMatrix(
376 static_cast<SCSIZE>(nMaxColCount),
377 static_cast<SCSIZE>(nRowCount), 0.0);
378 SCSIZE nCols, nRows;
379 xMatrix->GetDimensions( nCols, nRows);
380 if (nCols != static_cast<SCSIZE>(nMaxColCount) || nRows != static_cast<SCSIZE>(nRowCount))
382 OSL_FAIL( "ScSequenceToMatrix::CreateMixedMatrix: matrix exceeded max size, returning NULL matrix");
383 return NULL;
385 for (nRow=0; nRow<nRowCount; nRow++)
387 sal_Int32 nColCount = pRowArr[nRow].getLength();
388 const uno::Any* pColArr = pRowArr[nRow].getConstArray();
389 for (nCol=0; nCol<nColCount; nCol++)
391 double fVal;
392 uno::TypeClass eClass;
393 if (ScApiTypeConversion::ConvertAnyToDouble( fVal, eClass, pColArr[nCol]))
395 if (eClass == uno::TypeClass_BOOLEAN)
396 xMatrix->PutBoolean( (fVal ? true : false),
397 static_cast<SCSIZE>(nCol),
398 static_cast<SCSIZE>(nRow) );
399 else
400 xMatrix->PutDouble( fVal,
401 static_cast<SCSIZE>(nCol),
402 static_cast<SCSIZE>(nRow) );
404 else
406 // Try string, else use empty as last resort.
408 if ( pColArr[nCol] >>= aUStr )
410 xMatrix->PutString(
411 svl::SharedString(aUStr), static_cast<SCSIZE>(nCol), static_cast<SCSIZE>(nRow));
413 else
414 xMatrix->PutEmpty(
415 static_cast<SCSIZE>(nCol),
416 static_cast<SCSIZE>(nRow) );
419 for (nCol=nColCount; nCol<nMaxColCount; nCol++)
421 xMatrix->PutEmpty(
422 static_cast<SCSIZE>(nCol),
423 static_cast<SCSIZE>(nRow) );
428 return xMatrix;
431 sal_Bool ScByteSequenceToString::GetString( OUString& rString, const uno::Any& rAny,
432 sal_uInt16 nEncoding )
434 uno::Sequence<sal_Int8> aSeq;
435 if ( rAny >>= aSeq )
437 rString = OUString( (const sal_Char*)aSeq.getConstArray(),
438 aSeq.getLength(), nEncoding );
439 rString = comphelper::string::stripEnd(rString, 0);
440 return sal_True;
442 return false;
445 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */