1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: rangeseq.cxx,v $
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"
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
)
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
;
84 return TRUE
; //! check for errors
88 BOOL
ScRangeToSequence::FillLongArray( uno::Any
& rAny
, const ScMatrix
* pMatrix
)
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
) )
107 pColAry
[nCol
] = lcl_DoubleToLong( pMatrix
->GetDouble( nCol
, nRow
) );
109 pRowAry
[nRow
] = aColSeq
;
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
;
140 return TRUE
; //! check for errors
144 BOOL
ScRangeToSequence::FillDoubleArray( uno::Any
& rAny
, const ScMatrix
* pMatrix
)
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
) )
163 pColAry
[nCol
] = pMatrix
->GetDouble( nCol
, nRow
);
165 pRowAry
[nRow
] = aColSeq
;
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();
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
;
199 return TRUE
; //! check for errors
203 BOOL
ScRangeToSequence::FillStringArray( uno::Any
& rAny
, const ScMatrix
* pMatrix
,
204 SvNumberFormatter
* pFormatter
)
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
++)
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
);
231 pFormatter
->GetOutputString( fVal
, 0, aStr
, &pColor
);
233 pColAry
[nCol
] = rtl::OUString( aStr
);
236 pRowAry
[nRow
] = aColSeq
;
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" );
259 BOOL
ScRangeToSequence::FillMixedArray( uno::Any
& rAny
, ScDocument
* pDoc
, const ScRange
& rRange
,
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();
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
);
285 if ( pCell
->GetCellType() == CELLTYPE_FORMULA
&&
286 ((ScFormulaCell
*)pCell
)->GetErrCode() != 0 )
288 // if NV is allowed, leave empty for errors
291 else if ( pCell
->HasValueData() )
292 rElement
<<= (double) lcl_GetValueFromCell( *pCell
);
294 rElement
<<= rtl::OUString( pCell
->GetStringData() );
297 rElement
<<= rtl::OUString(); // empty: empty string
299 pRowAry
[nRow
] = aColSeq
;
303 return bAllowNV
|| !bHasErrors
;
307 BOOL
ScRangeToSequence::FillMixedArray( uno::Any
& rAny
, const ScMatrix
* pMatrix
, bool bDataTypes
)
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
) )
327 if ( !pMatrix
->IsEmpty( nCol
, nRow
) )
328 aStr
= pMatrix
->GetString( nCol
, nRow
);
329 pColAry
[nCol
] <<= rtl::OUString( aStr
);
333 double fVal
= pMatrix
->GetDouble( nCol
, nRow
);
334 if (bDataTypes
&& pMatrix
->IsBoolean( nCol
, nRow
))
335 pColAry
[nCol
] <<= (fVal
? true : false);
337 pColAry
[nCol
] <<= fVal
;
341 pRowAry
[nRow
] = aColSeq
;
348 //------------------------------------------------------------------------
351 bool ScApiTypeConversion::ConvertAnyToDouble( double & o_fVal
,
352 com::sun::star::uno::TypeClass
& o_eClass
,
353 const com::sun::star::uno::Any
& rAny
)
356 o_eClass
= rAny
.getValueTypeClass();
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
:
374 ; // nothing, avoid warning
381 //------------------------------------------------------------------------
384 ScMatrixRef
ScSequenceToMatrix::CreateMixedMatrix( const com::sun::star::uno::Any
& rAny
)
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
)
400 if ( nMaxColCount
&& nRowCount
)
403 xMatrix
= new ScMatrix(
404 static_cast<SCSIZE
>(nMaxColCount
),
405 static_cast<SCSIZE
>(nRowCount
) );
406 ScMatrix
* pMatrix
= xMatrix
;
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");
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
++)
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
) );
429 pMatrix
->PutDouble( fVal
,
430 static_cast<SCSIZE
>(nCol
),
431 static_cast<SCSIZE
>(nRow
) );
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
) );
445 static_cast<SCSIZE
>(nCol
),
446 static_cast<SCSIZE
>(nRow
) );
449 for (nCol
=nColCount
; nCol
<nMaxColCount
; nCol
++)
452 static_cast<SCSIZE
>(nCol
),
453 static_cast<SCSIZE
>(nRow
) );
462 //------------------------------------------------------------------------
464 BOOL
ScByteSequenceToString::GetString( String
& rString
, const uno::Any
& rAny
,
465 sal_uInt16 nEncoding
)
467 uno::Sequence
<sal_Int8
> aSeq
;
470 rString
= String( (const sal_Char
*)aSeq
.getConstArray(),
471 (xub_StrLen
)aSeq
.getLength(), nEncoding
);
472 rString
.EraseTrailingChars( (sal_Unicode
) 0 );
478 //------------------------------------------------------------------------