merge the formfield patch from ooo-build
[ooovba.git] / sc / source / core / tool / rangeseq.cxx
blobc32a658cec0dc6d3e9c524aef018c94be9669037
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: rangeseq.cxx,v $
10 * $Revision: 1.9 $
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 <svtools/zforlist.hxx>
37 #include <rtl/math.hxx>
38 #include <tools/debug.hxx>
40 #include <com/sun/star/uno/Any.hxx>
41 #include <com/sun/star/uno/Sequence.hxx>
43 #include "rangeseq.hxx"
44 #include "document.hxx"
45 #include "scmatrix.hxx"
46 #include "cell.hxx"
48 using namespace com::sun::star;
50 //------------------------------------------------------------------------
52 long lcl_DoubleToLong( double fVal )
54 double fInt = (fVal >= 0.0) ? ::rtl::math::approxFloor( fVal ) :
55 ::rtl::math::approxCeil( fVal );
56 if ( fInt >= LONG_MIN && fInt <= LONG_MAX )
57 return (long)fInt;
58 else
59 return 0; // out of range
62 BOOL ScRangeToSequence::FillLongArray( uno::Any& rAny, ScDocument* pDoc, const ScRange& rRange )
64 SCTAB nTab = rRange.aStart.Tab();
65 SCCOL nStartCol = rRange.aStart.Col();
66 SCROW nStartRow = rRange.aStart.Row();
67 long nColCount = rRange.aEnd.Col() + 1 - rRange.aStart.Col();
68 long nRowCount = rRange.aEnd.Row() + 1 - rRange.aStart.Row();
70 uno::Sequence< uno::Sequence<INT32> > aRowSeq( nRowCount );
71 uno::Sequence<INT32>* pRowAry = aRowSeq.getArray();
72 for (long nRow = 0; nRow < nRowCount; nRow++)
74 uno::Sequence<INT32> aColSeq( nColCount );
75 INT32* pColAry = aColSeq.getArray();
76 for (long nCol = 0; nCol < nColCount; nCol++)
77 pColAry[nCol] = lcl_DoubleToLong( pDoc->GetValue(
78 ScAddress( (SCCOL)(nStartCol+nCol), (SCROW)(nStartRow+nRow), nTab ) ) );
80 pRowAry[nRow] = aColSeq;
83 rAny <<= aRowSeq;
84 return TRUE; //! check for errors
88 BOOL ScRangeToSequence::FillLongArray( uno::Any& rAny, const ScMatrix* pMatrix )
90 if (!pMatrix)
91 return FALSE;
93 SCSIZE nColCount;
94 SCSIZE nRowCount;
95 pMatrix->GetDimensions( nColCount, nRowCount );
97 uno::Sequence< uno::Sequence<INT32> > aRowSeq( static_cast<sal_Int32>(nRowCount) );
98 uno::Sequence<INT32>* pRowAry = aRowSeq.getArray();
99 for (SCSIZE nRow = 0; nRow < nRowCount; nRow++)
101 uno::Sequence<INT32> aColSeq( static_cast<sal_Int32>(nColCount) );
102 INT32* pColAry = aColSeq.getArray();
103 for (SCSIZE nCol = 0; nCol < nColCount; nCol++)
104 if ( pMatrix->IsString( nCol, nRow ) )
105 pColAry[nCol] = 0;
106 else
107 pColAry[nCol] = lcl_DoubleToLong( pMatrix->GetDouble( nCol, nRow ) );
109 pRowAry[nRow] = aColSeq;
112 rAny <<= aRowSeq;
113 return TRUE;
116 //------------------------------------------------------------------------
118 BOOL ScRangeToSequence::FillDoubleArray( uno::Any& rAny, ScDocument* pDoc, const ScRange& rRange )
120 SCTAB nTab = rRange.aStart.Tab();
121 SCCOL nStartCol = rRange.aStart.Col();
122 SCROW nStartRow = rRange.aStart.Row();
123 long nColCount = rRange.aEnd.Col() + 1 - rRange.aStart.Col();
124 long nRowCount = rRange.aEnd.Row() + 1 - rRange.aStart.Row();
126 uno::Sequence< uno::Sequence<double> > aRowSeq( nRowCount );
127 uno::Sequence<double>* pRowAry = aRowSeq.getArray();
128 for (long nRow = 0; nRow < nRowCount; nRow++)
130 uno::Sequence<double> aColSeq( nColCount );
131 double* pColAry = aColSeq.getArray();
132 for (long nCol = 0; nCol < nColCount; nCol++)
133 pColAry[nCol] = pDoc->GetValue(
134 ScAddress( (SCCOL)(nStartCol+nCol), (SCROW)(nStartRow+nRow), nTab ) );
136 pRowAry[nRow] = aColSeq;
139 rAny <<= aRowSeq;
140 return TRUE; //! check for errors
144 BOOL ScRangeToSequence::FillDoubleArray( uno::Any& rAny, const ScMatrix* pMatrix )
146 if (!pMatrix)
147 return FALSE;
149 SCSIZE nColCount;
150 SCSIZE nRowCount;
151 pMatrix->GetDimensions( nColCount, nRowCount );
153 uno::Sequence< uno::Sequence<double> > aRowSeq( static_cast<sal_Int32>(nRowCount) );
154 uno::Sequence<double>* pRowAry = aRowSeq.getArray();
155 for (SCSIZE nRow = 0; nRow < nRowCount; nRow++)
157 uno::Sequence<double> aColSeq( static_cast<sal_Int32>(nColCount) );
158 double* pColAry = aColSeq.getArray();
159 for (SCSIZE nCol = 0; nCol < nColCount; nCol++)
160 if ( pMatrix->IsString( nCol, nRow ) )
161 pColAry[nCol] = 0.0;
162 else
163 pColAry[nCol] = pMatrix->GetDouble( nCol, nRow );
165 pRowAry[nRow] = aColSeq;
168 rAny <<= aRowSeq;
169 return TRUE;
172 //------------------------------------------------------------------------
174 BOOL ScRangeToSequence::FillStringArray( uno::Any& rAny, ScDocument* pDoc, const ScRange& rRange )
176 SCTAB nTab = rRange.aStart.Tab();
177 SCCOL nStartCol = rRange.aStart.Col();
178 SCROW nStartRow = rRange.aStart.Row();
179 long nColCount = rRange.aEnd.Col() + 1 - rRange.aStart.Col();
180 long nRowCount = rRange.aEnd.Row() + 1 - rRange.aStart.Row();
182 String aDocStr;
184 uno::Sequence< uno::Sequence<rtl::OUString> > aRowSeq( nRowCount );
185 uno::Sequence<rtl::OUString>* pRowAry = aRowSeq.getArray();
186 for (long nRow = 0; nRow < nRowCount; nRow++)
188 uno::Sequence<rtl::OUString> aColSeq( nColCount );
189 rtl::OUString* pColAry = aColSeq.getArray();
190 for (long nCol = 0; nCol < nColCount; nCol++)
192 pDoc->GetString( (SCCOL)(nStartCol+nCol), (SCROW)(nStartRow+nRow), nTab, aDocStr );
193 pColAry[nCol] = rtl::OUString( aDocStr );
195 pRowAry[nRow] = aColSeq;
198 rAny <<= aRowSeq;
199 return TRUE; //! check for errors
203 BOOL ScRangeToSequence::FillStringArray( uno::Any& rAny, const ScMatrix* pMatrix,
204 SvNumberFormatter* pFormatter )
206 if (!pMatrix)
207 return FALSE;
209 SCSIZE nColCount;
210 SCSIZE nRowCount;
211 pMatrix->GetDimensions( nColCount, nRowCount );
213 uno::Sequence< uno::Sequence<rtl::OUString> > aRowSeq( static_cast<sal_Int32>(nRowCount) );
214 uno::Sequence<rtl::OUString>* pRowAry = aRowSeq.getArray();
215 for (SCSIZE nRow = 0; nRow < nRowCount; nRow++)
217 uno::Sequence<rtl::OUString> aColSeq( static_cast<sal_Int32>(nColCount) );
218 rtl::OUString* pColAry = aColSeq.getArray();
219 for (SCSIZE nCol = 0; nCol < nColCount; nCol++)
221 String aStr;
222 if ( pMatrix->IsString( nCol, nRow ) )
224 if ( !pMatrix->IsEmpty( nCol, nRow ) )
225 aStr = pMatrix->GetString( nCol, nRow );
227 else if ( pFormatter )
229 double fVal = pMatrix->GetDouble( nCol, nRow );
230 Color* pColor;
231 pFormatter->GetOutputString( fVal, 0, aStr, &pColor );
233 pColAry[nCol] = rtl::OUString( aStr );
236 pRowAry[nRow] = aColSeq;
239 rAny <<= aRowSeq;
240 return TRUE;
243 //------------------------------------------------------------------------
245 double lcl_GetValueFromCell( ScBaseCell& rCell )
247 //! ScBaseCell member function?
249 CellType eType = rCell.GetCellType();
250 if ( eType == CELLTYPE_VALUE )
251 return ((ScValueCell&)rCell).GetValue();
252 else if ( eType == CELLTYPE_FORMULA )
253 return ((ScFormulaCell&)rCell).GetValue(); // called only if result is value
255 DBG_ERROR( "GetValueFromCell: wrong type" );
256 return 0;
259 BOOL ScRangeToSequence::FillMixedArray( uno::Any& rAny, ScDocument* pDoc, const ScRange& rRange,
260 BOOL bAllowNV )
262 SCTAB nTab = rRange.aStart.Tab();
263 SCCOL nStartCol = rRange.aStart.Col();
264 SCROW nStartRow = rRange.aStart.Row();
265 long nColCount = rRange.aEnd.Col() + 1 - rRange.aStart.Col();
266 long nRowCount = rRange.aEnd.Row() + 1 - rRange.aStart.Row();
268 String aDocStr;
269 BOOL bHasErrors = FALSE;
271 uno::Sequence< uno::Sequence<uno::Any> > aRowSeq( nRowCount );
272 uno::Sequence<uno::Any>* pRowAry = aRowSeq.getArray();
273 for (long nRow = 0; nRow < nRowCount; nRow++)
275 uno::Sequence<uno::Any> aColSeq( nColCount );
276 uno::Any* pColAry = aColSeq.getArray();
277 for (long nCol = 0; nCol < nColCount; nCol++)
279 uno::Any& rElement = pColAry[nCol];
281 ScAddress aPos( (SCCOL)(nStartCol+nCol), (SCROW)(nStartRow+nRow), nTab );
282 ScBaseCell* pCell = pDoc->GetCell( aPos );
283 if ( pCell )
285 if ( pCell->GetCellType() == CELLTYPE_FORMULA &&
286 ((ScFormulaCell*)pCell)->GetErrCode() != 0 )
288 // if NV is allowed, leave empty for errors
289 bHasErrors = TRUE;
291 else if ( pCell->HasValueData() )
292 rElement <<= (double) lcl_GetValueFromCell( *pCell );
293 else
294 rElement <<= rtl::OUString( pCell->GetStringData() );
296 else
297 rElement <<= rtl::OUString(); // empty: empty string
299 pRowAry[nRow] = aColSeq;
302 rAny <<= aRowSeq;
303 return bAllowNV || !bHasErrors;
307 BOOL ScRangeToSequence::FillMixedArray( uno::Any& rAny, const ScMatrix* pMatrix, bool bDataTypes )
309 if (!pMatrix)
310 return FALSE;
312 SCSIZE nColCount;
313 SCSIZE nRowCount;
314 pMatrix->GetDimensions( nColCount, nRowCount );
316 uno::Sequence< uno::Sequence<uno::Any> > aRowSeq( static_cast<sal_Int32>(nRowCount) );
317 uno::Sequence<uno::Any>* pRowAry = aRowSeq.getArray();
318 for (SCSIZE nRow = 0; nRow < nRowCount; nRow++)
320 uno::Sequence<uno::Any> aColSeq( static_cast<sal_Int32>(nColCount) );
321 uno::Any* pColAry = aColSeq.getArray();
322 for (SCSIZE nCol = 0; nCol < nColCount; nCol++)
324 if ( pMatrix->IsString( nCol, nRow ) )
326 String aStr;
327 if ( !pMatrix->IsEmpty( nCol, nRow ) )
328 aStr = pMatrix->GetString( nCol, nRow );
329 pColAry[nCol] <<= rtl::OUString( aStr );
331 else
333 double fVal = pMatrix->GetDouble( nCol, nRow );
334 if (bDataTypes && pMatrix->IsBoolean( nCol, nRow ))
335 pColAry[nCol] <<= (fVal ? true : false);
336 else
337 pColAry[nCol] <<= fVal;
341 pRowAry[nRow] = aColSeq;
344 rAny <<= aRowSeq;
345 return TRUE;
348 //------------------------------------------------------------------------
350 // static
351 bool ScApiTypeConversion::ConvertAnyToDouble( double & o_fVal,
352 com::sun::star::uno::TypeClass & o_eClass,
353 const com::sun::star::uno::Any & rAny )
355 bool bRet = false;
356 o_eClass = rAny.getValueTypeClass();
357 switch (o_eClass)
359 //! extract integer values
360 case uno::TypeClass_ENUM:
361 case uno::TypeClass_BOOLEAN:
362 case uno::TypeClass_CHAR:
363 case uno::TypeClass_BYTE:
364 case uno::TypeClass_SHORT:
365 case uno::TypeClass_UNSIGNED_SHORT:
366 case uno::TypeClass_LONG:
367 case uno::TypeClass_UNSIGNED_LONG:
368 case uno::TypeClass_FLOAT:
369 case uno::TypeClass_DOUBLE:
370 rAny >>= o_fVal;
371 bRet = true;
372 break;
373 default:
374 ; // nothing, avoid warning
376 if (!bRet)
377 o_fVal = 0.0;
378 return bRet;
381 //------------------------------------------------------------------------
383 // static
384 ScMatrixRef ScSequenceToMatrix::CreateMixedMatrix( const com::sun::star::uno::Any & rAny )
386 ScMatrixRef xMatrix;
387 uno::Sequence< uno::Sequence< uno::Any > > aSequence;
388 if ( rAny >>= aSequence )
390 sal_Int32 nRowCount = aSequence.getLength();
391 const uno::Sequence<uno::Any>* pRowArr = aSequence.getConstArray();
392 sal_Int32 nMaxColCount = 0;
393 sal_Int32 nCol, nRow;
394 for (nRow=0; nRow<nRowCount; nRow++)
396 sal_Int32 nTmp = pRowArr[nRow].getLength();
397 if ( nTmp > nMaxColCount )
398 nMaxColCount = nTmp;
400 if ( nMaxColCount && nRowCount )
402 rtl::OUString aUStr;
403 xMatrix = new ScMatrix(
404 static_cast<SCSIZE>(nMaxColCount),
405 static_cast<SCSIZE>(nRowCount) );
406 ScMatrix* pMatrix = xMatrix;
407 SCSIZE nCols, nRows;
408 pMatrix->GetDimensions( nCols, nRows);
409 if (nCols != static_cast<SCSIZE>(nMaxColCount) || nRows != static_cast<SCSIZE>(nRowCount))
411 DBG_ERRORFILE( "ScSequenceToMatrix::CreateMixedMatrix: matrix exceeded max size, returning NULL matrix");
412 return NULL;
414 for (nRow=0; nRow<nRowCount; nRow++)
416 sal_Int32 nColCount = pRowArr[nRow].getLength();
417 const uno::Any* pColArr = pRowArr[nRow].getConstArray();
418 for (nCol=0; nCol<nColCount; nCol++)
420 double fVal;
421 uno::TypeClass eClass;
422 if (ScApiTypeConversion::ConvertAnyToDouble( fVal, eClass, pColArr[nCol]))
424 if (eClass == uno::TypeClass_BOOLEAN)
425 pMatrix->PutBoolean( (fVal ? true : false),
426 static_cast<SCSIZE>(nCol),
427 static_cast<SCSIZE>(nRow) );
428 else
429 pMatrix->PutDouble( fVal,
430 static_cast<SCSIZE>(nCol),
431 static_cast<SCSIZE>(nRow) );
433 else
435 // Try string, else use empty as last resort.
437 //Reflection* pRefl = pColArr[nCol].getReflection();
438 //if ( pRefl->equals( *OUString_getReflection() ) )
439 if ( pColArr[nCol] >>= aUStr )
440 pMatrix->PutString( String( aUStr ),
441 static_cast<SCSIZE>(nCol),
442 static_cast<SCSIZE>(nRow) );
443 else
444 pMatrix->PutEmpty(
445 static_cast<SCSIZE>(nCol),
446 static_cast<SCSIZE>(nRow) );
449 for (nCol=nColCount; nCol<nMaxColCount; nCol++)
451 pMatrix->PutEmpty(
452 static_cast<SCSIZE>(nCol),
453 static_cast<SCSIZE>(nRow) );
458 return xMatrix;
462 //------------------------------------------------------------------------
464 BOOL ScByteSequenceToString::GetString( String& rString, const uno::Any& rAny,
465 sal_uInt16 nEncoding )
467 uno::Sequence<sal_Int8> aSeq;
468 if ( rAny >>= aSeq )
470 rString = String( (const sal_Char*)aSeq.getConstArray(),
471 (xub_StrLen)aSeq.getLength(), nEncoding );
472 rString.EraseTrailingChars( (sal_Unicode) 0 );
473 return TRUE;
475 return FALSE;
478 //------------------------------------------------------------------------