Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : : *
6 : : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
12 : : * OpenOffice.org is free software: you can redistribute it and/or modify
13 : : * it under the terms of the GNU Lesser General Public License version 3
14 : : * only, as published by the Free Software Foundation.
15 : : *
16 : : * OpenOffice.org is distributed in the hope that it will be useful,
17 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : : * GNU Lesser General Public License version 3 for more details
20 : : * (a copy is included in the LICENSE file that accompanied this code).
21 : : *
22 : : * You should have received a copy of the GNU Lesser General Public License
23 : : * version 3 along with OpenOffice.org. If not, see
24 : : * <http://www.openoffice.org/license.html>
25 : : * for a copy of the LGPLv3 License.
26 : : *
27 : : ************************************************************************/
28 : :
29 : : #include "scitems.hxx"
30 : : #include <editeng/langitem.hxx>
31 : : #include <editeng/justifyitem.hxx>
32 : : #include <svx/algitem.hxx>
33 : : #include <unotools/textsearch.hxx>
34 : : #include <svl/zforlist.hxx>
35 : : #include <svl/zformat.hxx>
36 : : #include <tools/urlobj.hxx>
37 : : #include <unotools/charclass.hxx>
38 : : #include <sfx2/docfile.hxx>
39 : : #include <sfx2/printer.hxx>
40 : : #include <unotools/collatorwrapper.hxx>
41 : : #include <unotools/transliterationwrapper.hxx>
42 : : #include <rtl/ustring.hxx>
43 : : #include <rtl/logfile.hxx>
44 : :
45 : : #include "interpre.hxx"
46 : : #include "patattr.hxx"
47 : : #include "global.hxx"
48 : : #include "document.hxx"
49 : : #include "dociter.hxx"
50 : : #include "cell.hxx"
51 : : #include "scmatrix.hxx"
52 : : #include "docoptio.hxx"
53 : : #include "globstr.hrc"
54 : : #include "attrib.hxx"
55 : : #include "jumpmatrix.hxx"
56 : :
57 : : #include <comphelper/processfactory.hxx>
58 : : #include <comphelper/string.hxx>
59 : :
60 : : #include <stdlib.h>
61 : : #include <string.h>
62 : : #include <math.h>
63 : : #include <vector>
64 : : #include <memory>
65 : : #include "cellkeytranslator.hxx"
66 : : #include "lookupcache.hxx"
67 : : #include "rangenam.hxx"
68 : : #include "rangeutl.hxx"
69 : : #include "compiler.hxx"
70 : : #include "externalrefmgr.hxx"
71 : : #include <basic/sbstar.hxx>
72 : : #include "doubleref.hxx"
73 : : #include "queryparam.hxx"
74 : : #include "queryentry.hxx"
75 : :
76 : : static const sal_uInt64 n2power48 = SAL_CONST_UINT64( 281474976710656); // 2^48
77 : :
78 : 51 : IMPL_FIXEDMEMPOOL_NEWDEL( ScTokenStack )
79 : 51 : IMPL_FIXEDMEMPOOL_NEWDEL( ScInterpreter )
80 : :
81 : 51 : ScCalcConfig ScInterpreter::maGlobalConfig;
82 : : ScTokenStack* ScInterpreter::pGlobalStack = NULL;
83 : : bool ScInterpreter::bGlobalStackInUse = false;
84 : :
85 : : using namespace formula;
86 : : using ::std::auto_ptr;
87 : : using ::rtl::OUString;
88 : :
89 : : struct ScCompare
90 : : {
91 : : double nVal[2];
92 : : String* pVal[2];
93 : : bool bVal[2];
94 : : bool bEmpty[2];
95 : 81 : ScCompare( String* p1, String* p2 )
96 : : {
97 : 81 : pVal[ 0 ] = p1;
98 : 81 : pVal[ 1 ] = p2;
99 : 81 : bEmpty[0] = false;
100 : 81 : bEmpty[1] = false;
101 : 81 : }
102 : : };
103 : :
104 : 0 : struct ScCompareOptions
105 : : {
106 : : ScQueryEntry aQueryEntry;
107 : : bool bRegEx;
108 : : bool bMatchWholeCell;
109 : : bool bIgnoreCase;
110 : :
111 : : ScCompareOptions( ScDocument* pDoc, const ScQueryEntry& rEntry, bool bReg );
112 : : private:
113 : : // Not implemented, prevent usage.
114 : : ScCompareOptions();
115 : : ScCompareOptions( const ScCompareOptions & );
116 : : ScCompareOptions& operator=( const ScCompareOptions & );
117 : : };
118 : :
119 : : //-----------------------------------------------------------------------------
120 : : // Functions
121 : : //-----------------------------------------------------------------------------
122 : :
123 : :
124 : 66 : void ScInterpreter::ScIfJump()
125 : : {
126 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScIfJump" );
127 : 66 : const short* pJump = pCur->GetJump();
128 : 66 : short nJumpCount = pJump[ 0 ];
129 : 66 : MatrixDoubleRefToMatrix();
130 [ - + ]: 66 : switch ( GetStackType() )
131 : : {
132 : : case svMatrix:
133 : : {
134 [ # # ]: 0 : ScMatrixRef pMat = PopMatrix();
135 [ # # ]: 0 : if ( !pMat )
136 [ # # ]: 0 : PushIllegalParameter();
137 : : else
138 : : {
139 : 0 : FormulaTokenRef xNew;
140 : 0 : ScTokenMatrixMap::const_iterator aMapIter;
141 : : // DoubleError handled by JumpMatrix
142 [ # # ]: 0 : pMat->SetErrorInterpreter( NULL);
143 : : SCSIZE nCols, nRows;
144 [ # # ]: 0 : pMat->GetDimensions( nCols, nRows );
145 [ # # ][ # # ]: 0 : if ( nCols == 0 || nRows == 0 )
146 [ # # ]: 0 : PushIllegalArgument();
147 [ # # # # ]: 0 : else if (pTokenMatrixMap && ((aMapIter = pTokenMatrixMap->find(
[ # # ]
148 [ # # ][ # # ]: 0 : pCur)) != pTokenMatrixMap->end()))
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # #
# # # # #
# # # ]
149 [ # # ]: 0 : xNew = (*aMapIter).second;
150 : : else
151 : : {
152 [ # # ][ # # ]: 0 : ScJumpMatrix* pJumpMat = new ScJumpMatrix( nCols, nRows );
153 [ # # ]: 0 : for ( SCSIZE nC=0; nC < nCols; ++nC )
154 : : {
155 [ # # ]: 0 : for ( SCSIZE nR=0; nR < nRows; ++nR )
156 : : {
157 : : double fVal;
158 : : bool bTrue;
159 [ # # ]: 0 : bool bIsValue = pMat->IsValue(nC, nR);
160 [ # # ]: 0 : if (bIsValue)
161 : : {
162 [ # # ]: 0 : fVal = pMat->GetDouble(nC, nR);
163 : 0 : bIsValue = ::rtl::math::isFinite(fVal);
164 [ # # ][ # # ]: 0 : bTrue = bIsValue && (fVal != 0.0);
165 [ # # ]: 0 : if (bTrue)
166 : 0 : fVal = 1.0;
167 : : }
168 : : else
169 : : {
170 : : // Treat empty and empty path as 0, but string
171 : : // as error.
172 [ # # ][ # # ]: 0 : bIsValue = (!pMat->IsString(nC, nR) || pMat->IsEmpty(nC, nR));
[ # # ][ # # ]
173 : 0 : bTrue = false;
174 [ # # ]: 0 : fVal = (bIsValue ? 0.0 : CreateDoubleError( errNoValue));
175 : : }
176 [ # # ]: 0 : if ( bTrue )
177 : : { // TRUE
178 [ # # ]: 0 : if( nJumpCount >= 2 )
179 : : { // THEN path
180 : : pJumpMat->SetJump( nC, nR, fVal,
181 : 0 : pJump[ 1 ],
182 : 0 : pJump[ nJumpCount ]);
183 : : }
184 : : else
185 : : { // no parameter given for THEN
186 : : pJumpMat->SetJump( nC, nR, fVal,
187 : 0 : pJump[ nJumpCount ],
188 : 0 : pJump[ nJumpCount ]);
189 : : }
190 : : }
191 : : else
192 : : { // FALSE
193 [ # # ][ # # ]: 0 : if( nJumpCount == 3 && bIsValue )
194 : : { // ELSE path
195 : : pJumpMat->SetJump( nC, nR, fVal,
196 : 0 : pJump[ 2 ],
197 : 0 : pJump[ nJumpCount ]);
198 : : }
199 : : else
200 : : { // no parameter given for ELSE,
201 : : // or DoubleError
202 : : pJumpMat->SetJump( nC, nR, fVal,
203 : 0 : pJump[ nJumpCount ],
204 : 0 : pJump[ nJumpCount ]);
205 : : }
206 : : }
207 : : }
208 : : }
209 [ # # ][ # # ]: 0 : xNew = new ScJumpMatrixToken( pJumpMat );
[ # # ]
210 [ # # ][ # # ]: 0 : GetTokenMatrixMap().insert( ScTokenMatrixMap::value_type(pCur, xNew));
[ # # ][ # # ]
211 : : }
212 [ # # ]: 0 : PushTempToken( xNew.get());
213 : : // set endpoint of path for main code line
214 [ # # ][ # # ]: 0 : aCode.Jump( pJump[ nJumpCount ], pJump[ nJumpCount ] );
215 [ # # ]: 0 : }
216 : : }
217 : 0 : break;
218 : : default:
219 : : {
220 [ + + ]: 66 : if ( GetBool() )
221 : : { // TRUE
222 [ + + ]: 42 : if( nJumpCount >= 2 )
223 : : { // THEN path
224 : 24 : aCode.Jump( pJump[ 1 ], pJump[ nJumpCount ] );
225 : : }
226 : : else
227 : : { // no parameter given for THEN
228 : 18 : nFuncFmtType = NUMBERFORMAT_LOGICAL;
229 : 18 : PushInt(1);
230 : 18 : aCode.Jump( pJump[ nJumpCount ], pJump[ nJumpCount ] );
231 : : }
232 : : }
233 : : else
234 : : { // FALSE
235 [ + + ]: 24 : if( nJumpCount == 3 )
236 : : { // ELSE path
237 : 21 : aCode.Jump( pJump[ 2 ], pJump[ nJumpCount ] );
238 : : }
239 : : else
240 : : { // no parameter given for ELSE
241 : 3 : nFuncFmtType = NUMBERFORMAT_LOGICAL;
242 : 3 : PushInt(0);
243 : 3 : aCode.Jump( pJump[ nJumpCount ], pJump[ nJumpCount ] );
244 : : }
245 : : }
246 : : }
247 : : }
248 : 66 : }
249 : :
250 : :
251 : 0 : void ScInterpreter::ScChoseJump()
252 : : {
253 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScChoseJump" );
254 : : // We have to set a jump, if there was none chosen because of an error set
255 : : // it to endpoint.
256 : 0 : bool bHaveJump = false;
257 : 0 : const short* pJump = pCur->GetJump();
258 : 0 : short nJumpCount = pJump[ 0 ];
259 : 0 : MatrixDoubleRefToMatrix();
260 [ # # ]: 0 : switch ( GetStackType() )
261 : : {
262 : : case svMatrix:
263 : : {
264 [ # # ]: 0 : ScMatrixRef pMat = PopMatrix();
265 [ # # ]: 0 : if ( !pMat )
266 [ # # ]: 0 : PushIllegalParameter();
267 : : else
268 : : {
269 : 0 : FormulaTokenRef xNew;
270 : 0 : ScTokenMatrixMap::const_iterator aMapIter;
271 : : // DoubleError handled by JumpMatrix
272 [ # # ]: 0 : pMat->SetErrorInterpreter( NULL);
273 : : SCSIZE nCols, nRows;
274 [ # # ]: 0 : pMat->GetDimensions( nCols, nRows );
275 [ # # ][ # # ]: 0 : if ( nCols == 0 || nRows == 0 )
276 [ # # ]: 0 : PushIllegalParameter();
277 [ # # # # ]: 0 : else if (pTokenMatrixMap && ((aMapIter = pTokenMatrixMap->find(
[ # # ]
278 [ # # ][ # # ]: 0 : pCur)) != pTokenMatrixMap->end()))
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # #
# # # # #
# # # ]
279 [ # # ]: 0 : xNew = (*aMapIter).second;
280 : : else
281 : : {
282 [ # # ][ # # ]: 0 : ScJumpMatrix* pJumpMat = new ScJumpMatrix( nCols, nRows );
283 [ # # ]: 0 : for ( SCSIZE nC=0; nC < nCols; ++nC )
284 : : {
285 [ # # ]: 0 : for ( SCSIZE nR=0; nR < nRows; ++nR )
286 : : {
287 : : double fVal;
288 [ # # ]: 0 : bool bIsValue = pMat->IsValue(nC, nR);
289 [ # # ]: 0 : if ( bIsValue )
290 : : {
291 [ # # ]: 0 : fVal = pMat->GetDouble(nC, nR);
292 : 0 : bIsValue = ::rtl::math::isFinite( fVal );
293 [ # # ]: 0 : if ( bIsValue )
294 : : {
295 : 0 : fVal = ::rtl::math::approxFloor( fVal);
296 [ # # ][ # # ]: 0 : if ( (fVal < 1) || (fVal >= nJumpCount))
297 : : {
298 : 0 : bIsValue = false;
299 : : fVal = CreateDoubleError(
300 : 0 : errIllegalArgument);
301 : : }
302 : : }
303 : : }
304 : : else
305 : : {
306 : 0 : fVal = CreateDoubleError( errNoValue);
307 : : }
308 [ # # ]: 0 : if ( bIsValue )
309 : : {
310 : : pJumpMat->SetJump( nC, nR, fVal,
311 : 0 : pJump[ (short)fVal ],
312 : 0 : pJump[ nJumpCount ]);
313 : : }
314 : : else
315 : : {
316 : : pJumpMat->SetJump( nC, nR, fVal,
317 : 0 : pJump[ nJumpCount ],
318 : 0 : pJump[ nJumpCount ]);
319 : : }
320 : : }
321 : : }
322 [ # # ][ # # ]: 0 : xNew = new ScJumpMatrixToken( pJumpMat );
[ # # ]
323 [ # # ]: 0 : GetTokenMatrixMap().insert( ScTokenMatrixMap::value_type(
324 [ # # ][ # # ]: 0 : pCur, xNew));
[ # # ]
325 : : }
326 [ # # ]: 0 : PushTempToken( xNew.get());
327 : : // set endpoint of path for main code line
328 [ # # ]: 0 : aCode.Jump( pJump[ nJumpCount ], pJump[ nJumpCount ] );
329 [ # # ]: 0 : bHaveJump = true;
330 [ # # ]: 0 : }
331 : : }
332 : 0 : break;
333 : : default:
334 : : {
335 : 0 : double nJumpIndex = ::rtl::math::approxFloor( GetDouble() );
336 [ # # ][ # # ]: 0 : if (!nGlobalError && (nJumpIndex >= 1) && (nJumpIndex < nJumpCount))
[ # # ]
337 : : {
338 : 0 : aCode.Jump( pJump[ (short) nJumpIndex ], pJump[ nJumpCount ] );
339 : 0 : bHaveJump = true;
340 : : }
341 : : else
342 : 0 : PushIllegalArgument();
343 : : }
344 : : }
345 [ # # ]: 0 : if (!bHaveJump)
346 : 0 : aCode.Jump( pJump[ nJumpCount ], pJump[ nJumpCount ] );
347 : 0 : }
348 : :
349 : 0 : void lcl_AdjustJumpMatrix( ScJumpMatrix* pJumpM, ScMatrixRef& pResMat, SCSIZE nParmCols, SCSIZE nParmRows )
350 : : {
351 : : SCSIZE nJumpCols, nJumpRows;
352 : : SCSIZE nResCols, nResRows;
353 : : SCSIZE nAdjustCols, nAdjustRows;
354 : 0 : pJumpM->GetDimensions( nJumpCols, nJumpRows );
355 : 0 : pJumpM->GetResMatDimensions( nResCols, nResRows );
356 [ # # ][ # # ]: 0 : if (( nJumpCols == 1 && nParmCols > nResCols ) ||
[ # # ][ # # ]
357 : : ( nJumpRows == 1 && nParmRows > nResRows ))
358 : : {
359 [ # # ][ # # ]: 0 : if ( nJumpCols == 1 && nJumpRows == 1 )
360 : : {
361 [ # # ]: 0 : nAdjustCols = nParmCols > nResCols ? nParmCols : nResCols;
362 [ # # ]: 0 : nAdjustRows = nParmRows > nResRows ? nParmRows : nResRows;
363 : : }
364 [ # # ]: 0 : else if ( nJumpCols == 1 )
365 : : {
366 : 0 : nAdjustCols = nParmCols;
367 : 0 : nAdjustRows = nResRows;
368 : : }
369 : : else
370 : : {
371 : 0 : nAdjustCols = nResCols;
372 : 0 : nAdjustRows = nParmRows;
373 : : }
374 [ # # ]: 0 : pJumpM->SetNewResMat( nAdjustCols, nAdjustRows );
375 [ # # ][ # # ]: 0 : pResMat = pJumpM->GetResultMatrix();
376 : : }
377 : 0 : }
378 : :
379 : 0 : bool ScInterpreter::JumpMatrix( short nStackLevel )
380 : : {
381 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::JumpMatrix" );
382 [ # # ]: 0 : pJumpMatrix = static_cast<ScToken*>(pStack[sp-nStackLevel])->GetJumpMatrix();
383 [ # # ]: 0 : ScMatrixRef pResMat = pJumpMatrix->GetResultMatrix();
384 : : SCSIZE nC, nR;
385 [ # # ]: 0 : if ( nStackLevel == 2 )
386 : : {
387 [ # # ]: 0 : if ( aCode.HasStacked() )
388 [ # # ]: 0 : aCode.Pop(); // pop what Jump() pushed
389 : : else
390 : : {
391 : : OSL_FAIL( "ScInterpreter::JumpMatrix: pop goes the weasel" );
392 : : }
393 : :
394 [ # # ]: 0 : if ( !pResMat )
395 : : {
396 [ # # ]: 0 : Pop();
397 : 0 : SetError( errUnknownStackVariable );
398 : : }
399 : : else
400 : : {
401 : 0 : pJumpMatrix->GetPos( nC, nR );
402 [ # # # # : 0 : switch ( GetStackType() )
# # # ]
[ # # ]
403 : : {
404 : : case svDouble:
405 : : {
406 [ # # ]: 0 : double fVal = GetDouble();
407 [ # # ]: 0 : if ( nGlobalError )
408 : : {
409 : 0 : fVal = CreateDoubleError( nGlobalError );
410 : 0 : nGlobalError = 0;
411 : : }
412 [ # # ]: 0 : pResMat->PutDouble( fVal, nC, nR );
413 : : }
414 : 0 : break;
415 : : case svString:
416 : : {
417 [ # # ]: 0 : const String& rStr = GetString();
418 [ # # ]: 0 : if ( nGlobalError )
419 : : {
420 : : pResMat->PutDouble( CreateDoubleError( nGlobalError),
421 [ # # ]: 0 : nC, nR);
422 : 0 : nGlobalError = 0;
423 : : }
424 : : else
425 [ # # ][ # # ]: 0 : pResMat->PutString( rStr, nC, nR );
426 : : }
427 : 0 : break;
428 : : case svSingleRef:
429 : : {
430 : 0 : ScAddress aAdr;
431 [ # # ]: 0 : PopSingleRef( aAdr );
432 [ # # ]: 0 : if ( nGlobalError )
433 : : {
434 : : pResMat->PutDouble( CreateDoubleError( nGlobalError),
435 [ # # ]: 0 : nC, nR);
436 : 0 : nGlobalError = 0;
437 : : }
438 : : else
439 : : {
440 [ # # ]: 0 : ScBaseCell* pCell = GetCell( aAdr );
441 [ # # ][ # # ]: 0 : if (HasCellEmptyData( pCell))
442 [ # # ]: 0 : pResMat->PutEmpty( nC, nR );
443 [ # # ][ # # ]: 0 : else if (HasCellValueData( pCell))
444 : : {
445 [ # # ]: 0 : double fVal = GetCellValue( aAdr, pCell);
446 [ # # ]: 0 : if ( nGlobalError )
447 : : {
448 : : fVal = CreateDoubleError(
449 : 0 : nGlobalError);
450 : 0 : nGlobalError = 0;
451 : : }
452 [ # # ]: 0 : pResMat->PutDouble( fVal, nC, nR );
453 : : }
454 : : else
455 : : {
456 [ # # ]: 0 : String aStr;
457 [ # # ]: 0 : GetCellString( aStr, pCell );
458 [ # # ]: 0 : if ( nGlobalError )
459 : : {
460 : : pResMat->PutDouble( CreateDoubleError(
461 [ # # ]: 0 : nGlobalError), nC, nR);
462 : 0 : nGlobalError = 0;
463 : : }
464 : : else
465 [ # # ][ # # ]: 0 : pResMat->PutString( aStr, nC, nR);
[ # # ]
466 : : }
467 : : }
468 : : }
469 : 0 : break;
470 : : case svDoubleRef:
471 : : { // upper left plus offset within matrix
472 : : double fVal;
473 : 0 : ScRange aRange;
474 [ # # ]: 0 : PopDoubleRef( aRange );
475 [ # # ]: 0 : if ( nGlobalError )
476 : : {
477 : 0 : fVal = CreateDoubleError( nGlobalError );
478 : 0 : nGlobalError = 0;
479 [ # # ]: 0 : pResMat->PutDouble( fVal, nC, nR );
480 : : }
481 : : else
482 : : {
483 : : // Do not modify the original range because we use it
484 : : // to adjust the size of the result matrix if necessary.
485 : 0 : ScAddress aAdr( aRange.aStart);
486 : 0 : sal_uLong nCol = (sal_uLong)aAdr.Col() + nC;
487 : 0 : sal_uLong nRow = (sal_uLong)aAdr.Row() + nR;
488 [ # # ][ # # : 0 : if ((nCol > static_cast<sal_uLong>(aRange.aEnd.Col()) &&
# # # # #
# ]
489 : 0 : aRange.aEnd.Col() != aRange.aStart.Col())
490 : 0 : || (nRow > static_cast<sal_uLong>(aRange.aEnd.Row()) &&
491 : 0 : aRange.aEnd.Row() != aRange.aStart.Row()))
492 : : {
493 : 0 : fVal = CreateDoubleError( NOTAVAILABLE );
494 [ # # ]: 0 : pResMat->PutDouble( fVal, nC, nR );
495 : : }
496 : : else
497 : : {
498 : : // Replicate column and/or row of a vector if it is
499 : : // one. Note that this could be a range reference
500 : : // that in fact consists of only one cell, e.g. A1:A1
501 [ # # ]: 0 : if (aRange.aEnd.Col() == aRange.aStart.Col())
502 : 0 : nCol = aRange.aStart.Col();
503 [ # # ]: 0 : if (aRange.aEnd.Row() == aRange.aStart.Row())
504 : 0 : nRow = aRange.aStart.Row();
505 : 0 : aAdr.SetCol( static_cast<SCCOL>(nCol) );
506 : 0 : aAdr.SetRow( static_cast<SCROW>(nRow) );
507 [ # # ]: 0 : ScBaseCell* pCell = GetCell( aAdr );
508 [ # # ][ # # ]: 0 : if (HasCellEmptyData( pCell))
509 [ # # ]: 0 : pResMat->PutEmpty( nC, nR );
510 [ # # ][ # # ]: 0 : else if (HasCellValueData( pCell))
511 : : {
512 [ # # ]: 0 : double fCellVal = GetCellValue( aAdr, pCell);
513 [ # # ]: 0 : if ( nGlobalError )
514 : : {
515 : : fCellVal = CreateDoubleError(
516 : 0 : nGlobalError);
517 : 0 : nGlobalError = 0;
518 : : }
519 [ # # ]: 0 : pResMat->PutDouble( fCellVal, nC, nR );
520 : : }
521 : : else
522 : : {
523 [ # # ]: 0 : String aStr;
524 [ # # ]: 0 : GetCellString( aStr, pCell );
525 [ # # ]: 0 : if ( nGlobalError )
526 : : {
527 : : pResMat->PutDouble( CreateDoubleError(
528 [ # # ]: 0 : nGlobalError), nC, nR);
529 : 0 : nGlobalError = 0;
530 : : }
531 : : else
532 [ # # ][ # # ]: 0 : pResMat->PutString( aStr, nC, nR );
[ # # ]
533 : : }
534 : : }
535 : 0 : SCSIZE nParmCols = aRange.aEnd.Col() - aRange.aStart.Col() + 1;
536 : 0 : SCSIZE nParmRows = aRange.aEnd.Row() - aRange.aStart.Row() + 1;
537 [ # # ]: 0 : lcl_AdjustJumpMatrix( pJumpMatrix, pResMat, nParmCols, nParmRows );
538 : : }
539 : : }
540 : 0 : break;
541 : : case svMatrix:
542 : : { // match matrix offsets
543 : : double fVal;
544 [ # # ]: 0 : ScMatrixRef pMat = PopMatrix();
545 [ # # ]: 0 : if ( nGlobalError )
546 : : {
547 : 0 : fVal = CreateDoubleError( nGlobalError );
548 : 0 : nGlobalError = 0;
549 [ # # ]: 0 : pResMat->PutDouble( fVal, nC, nR );
550 : : }
551 [ # # ]: 0 : else if ( !pMat )
552 : : {
553 : 0 : fVal = CreateDoubleError( errUnknownVariable );
554 [ # # ]: 0 : pResMat->PutDouble( fVal, nC, nR );
555 : : }
556 : : else
557 : : {
558 : : SCSIZE nCols, nRows;
559 [ # # ]: 0 : pMat->GetDimensions( nCols, nRows );
560 [ # # ][ # # ]: 0 : if ((nCols <= nC && nCols != 1) ||
[ # # ][ # # ]
561 : : (nRows <= nR && nRows != 1))
562 : : {
563 : 0 : fVal = CreateDoubleError( NOTAVAILABLE );
564 [ # # ]: 0 : pResMat->PutDouble( fVal, nC, nR );
565 : : }
566 : : else
567 : : {
568 [ # # ][ # # ]: 0 : if ( pMat->IsValue( nC, nR ) )
569 : : {
570 [ # # ]: 0 : fVal = pMat->GetDouble( nC, nR );
571 [ # # ]: 0 : pResMat->PutDouble( fVal, nC, nR );
572 : : }
573 [ # # ][ # # ]: 0 : else if ( pMat->IsEmpty( nC, nR ) )
574 [ # # ]: 0 : pResMat->PutEmpty( nC, nR );
575 : : else
576 : : {
577 [ # # ][ # # ]: 0 : const String& rStr = pMat->GetString( nC, nR );
578 [ # # ][ # # ]: 0 : pResMat->PutString( rStr, nC, nR );
[ # # ]
579 : : }
580 : : }
581 [ # # ]: 0 : lcl_AdjustJumpMatrix( pJumpMatrix, pResMat, nCols, nRows );
582 [ # # ]: 0 : }
583 : : }
584 : 0 : break;
585 : : case svError:
586 : : {
587 [ # # ]: 0 : PopError();
588 : 0 : double fVal = CreateDoubleError( nGlobalError);
589 : 0 : nGlobalError = 0;
590 [ # # ]: 0 : pResMat->PutDouble( fVal, nC, nR );
591 : : }
592 : 0 : break;
593 : : default:
594 : : {
595 [ # # ]: 0 : Pop();
596 : 0 : double fVal = CreateDoubleError( errIllegalArgument);
597 [ # # ]: 0 : pResMat->PutDouble( fVal, nC, nR );
598 : : }
599 : : }
600 : : }
601 : : }
602 : 0 : bool bCont = pJumpMatrix->Next( nC, nR );
603 [ # # ]: 0 : if ( bCont )
604 : : {
605 : : double fBool;
606 : : short nStart, nNext, nStop;
607 : 0 : pJumpMatrix->GetJump( nC, nR, fBool, nStart, nNext, nStop );
608 [ # # ][ # # ]: 0 : while ( bCont && nStart == nNext )
[ # # ]
609 : : { // push all results that have no jump path
610 [ # # ]: 0 : if ( pResMat )
611 : : {
612 : : // a false without path results in an empty path value
613 [ # # ]: 0 : if ( fBool == 0.0 )
614 [ # # ]: 0 : pResMat->PutEmptyPath( nC, nR );
615 : : else
616 [ # # ]: 0 : pResMat->PutDouble( fBool, nC, nR );
617 : : }
618 : 0 : bCont = pJumpMatrix->Next( nC, nR );
619 [ # # ]: 0 : if ( bCont )
620 : 0 : pJumpMatrix->GetJump( nC, nR, fBool, nStart, nNext, nStop );
621 : : }
622 [ # # ][ # # ]: 0 : if ( bCont && nStart != nNext )
623 : : {
624 : 0 : const ScTokenVec* pParams = pJumpMatrix->GetJumpParameters();
625 [ # # ]: 0 : if ( pParams )
626 : : {
627 [ # # # # ]: 0 : for ( ScTokenVec::const_iterator i = pParams->begin();
[ # # ]
628 : 0 : i != pParams->end(); ++i )
629 : : {
630 : : // This is not the current state of the interpreter, so
631 : : // push without error, and elements' errors are coded into
632 : : // double.
633 [ # # ][ # # ]: 0 : PushWithoutError( *(*i));
634 : : }
635 : : }
636 [ # # ]: 0 : aCode.Jump( nStart, nNext, nStop );
637 : : }
638 : : }
639 [ # # ]: 0 : if ( !bCont )
640 : : { // we're done with it, throw away jump matrix, keep result
641 : 0 : pJumpMatrix = NULL;
642 [ # # ]: 0 : Pop();
643 [ # # ]: 0 : PushMatrix( pResMat );
644 : : // Remove jump matrix from map and remember result matrix in case it
645 : : // could be reused in another path of the same condition.
646 [ # # ]: 0 : if (pTokenMatrixMap)
647 : : {
648 [ # # ][ # # ]: 0 : pTokenMatrixMap->erase( pCur);
649 : : pTokenMatrixMap->insert( ScTokenMatrixMap::value_type( pCur,
650 [ # # ][ # # ]: 0 : pStack[sp-1]));
[ # # ]
651 : : }
652 : 0 : return true;
653 : : }
654 [ # # ]: 0 : return false;
655 : : }
656 : :
657 : :
658 : 0 : ScCompareOptions::ScCompareOptions( ScDocument* pDoc, const ScQueryEntry& rEntry, bool bReg ) :
659 : : aQueryEntry(rEntry),
660 : : bRegEx(bReg),
661 [ # # ]: 0 : bMatchWholeCell(pDoc->GetDocOptions().IsMatchWholeCell()),
662 : 0 : bIgnoreCase(true)
663 : : {
664 [ # # ][ # # ]: 0 : bRegEx = (bRegEx && (aQueryEntry.eOp == SC_EQUAL || aQueryEntry.eOp == SC_NOT_EQUAL));
[ # # ]
665 : : // Interpreter functions usually are case insensitive, except the simple
666 : : // comparison operators, for which these options aren't used. Override in
667 : : // struct if needed.
668 : 0 : }
669 : :
670 : :
671 : 201 : double ScInterpreter::CompareFunc( const ScCompare& rComp, ScCompareOptions* pOptions )
672 : : {
673 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::CompareFunc" );
674 : : // Keep DoubleError if encountered
675 : : // #i40539# if bEmpty is set, bVal/nVal are uninitialized
676 [ + - ][ + + ]: 201 : if ( !rComp.bEmpty[0] && rComp.bVal[0] && !::rtl::math::isFinite( rComp.nVal[0]))
[ - + ][ - + ]
677 : 0 : return rComp.nVal[0];
678 [ + - ][ + + ]: 201 : if ( !rComp.bEmpty[1] && rComp.bVal[1] && !::rtl::math::isFinite( rComp.nVal[1]))
[ - + ][ - + ]
679 : 0 : return rComp.nVal[1];
680 : :
681 : 201 : double fRes = 0;
682 [ - + ]: 201 : if ( rComp.bEmpty[ 0 ] )
683 : : {
684 [ # # ]: 0 : if ( rComp.bEmpty[ 1 ] )
685 : : ; // empty cell == empty cell, fRes 0
686 [ # # ]: 0 : else if( rComp.bVal[ 1 ] )
687 : : {
688 [ # # ]: 0 : if ( !::rtl::math::approxEqual( rComp.nVal[ 1 ], 0.0 ) )
689 : : {
690 [ # # ]: 0 : if ( rComp.nVal[ 1 ] < 0.0 )
691 : 0 : fRes = 1; // empty cell > -x
692 : : else
693 : 0 : fRes = -1; // empty cell < x
694 : : }
695 : : // else: empty cell == 0.0
696 : : }
697 : : else
698 : : {
699 [ # # ]: 0 : if ( rComp.pVal[ 1 ]->Len() )
700 : 0 : fRes = -1; // empty cell < "..."
701 : : // else: empty cell == ""
702 : : }
703 : : }
704 [ - + ]: 201 : else if ( rComp.bEmpty[ 1 ] )
705 : : {
706 [ # # ]: 0 : if( rComp.bVal[ 0 ] )
707 : : {
708 [ # # ]: 0 : if ( !::rtl::math::approxEqual( rComp.nVal[ 0 ], 0.0 ) )
709 : : {
710 [ # # ]: 0 : if ( rComp.nVal[ 0 ] < 0.0 )
711 : 0 : fRes = -1; // -x < empty cell
712 : : else
713 : 0 : fRes = 1; // x > empty cell
714 : : }
715 : : // else: empty cell == 0.0
716 : : }
717 : : else
718 : : {
719 [ # # ]: 0 : if ( rComp.pVal[ 0 ]->Len() )
720 : 0 : fRes = 1; // "..." > empty cell
721 : : // else: "" == empty cell
722 : : }
723 : : }
724 [ + + ]: 201 : else if( rComp.bVal[ 0 ] )
725 : : {
726 [ + + ]: 105 : if( rComp.bVal[ 1 ] )
727 : : {
728 [ + + ]: 69 : if ( !::rtl::math::approxEqual( rComp.nVal[ 0 ], rComp.nVal[ 1 ] ) )
729 : : {
730 [ + + ]: 48 : if( rComp.nVal[ 0 ] - rComp.nVal[ 1 ] < 0 )
731 : 12 : fRes = -1;
732 : : else
733 : 36 : fRes = 1;
734 : : }
735 : : }
736 : : else
737 : 36 : fRes = -1; // number is less than string
738 : : }
739 [ + + ]: 96 : else if( rComp.bVal[ 1 ] )
740 : 36 : fRes = 1; // number is less than string
741 : : else
742 : : {
743 : : // Both strings.
744 [ - + ]: 60 : if (pOptions)
745 : : {
746 : : // All similar to Sctable::ValidQuery(), *rComp.pVal[1] actually
747 : : // is/must be identical to *rEntry.pStr, which is essential for
748 : : // regex to work through GetSearchTextPtr().
749 : 0 : ScQueryEntry& rEntry = pOptions->aQueryEntry;
750 : : OSL_ENSURE(rEntry.GetQueryItem().maString.equals(*rComp.pVal[1]), "ScInterpreter::CompareFunc: broken options");
751 [ # # ]: 0 : if (pOptions->bRegEx)
752 : : {
753 : 0 : xub_StrLen nStart = 0;
754 : 0 : xub_StrLen nStop = rComp.pVal[0]->Len();
755 : : bool bMatch = rEntry.GetSearchTextPtr(
756 : 0 : !pOptions->bIgnoreCase)->SearchFrwrd( *rComp.pVal[0],
757 [ # # ][ # # ]: 0 : &nStart, &nStop);
758 [ # # ][ # # ]: 0 : if (bMatch && pOptions->bMatchWholeCell && (nStart != 0 || nStop != rComp.pVal[0]->Len()))
[ # # ][ # # ]
[ # # ]
759 : 0 : bMatch = false; // RegEx must match entire string.
760 [ # # ]: 0 : fRes = (bMatch ? 0 : 1);
761 : : }
762 [ # # ][ # # ]: 0 : else if (rEntry.eOp == SC_EQUAL || rEntry.eOp == SC_NOT_EQUAL)
763 : : {
764 : : ::utl::TransliterationWrapper* pTransliteration =
765 : : (pOptions->bIgnoreCase ? ScGlobal::GetpTransliteration() :
766 [ # # ]: 0 : ScGlobal::GetCaseTransliteration());
767 : : bool bMatch;
768 [ # # ]: 0 : if (pOptions->bMatchWholeCell)
769 : 0 : bMatch = pTransliteration->isEqual( *rComp.pVal[0], *rComp.pVal[1]);
770 : : else
771 : : {
772 : : String aCell( pTransliteration->transliterate(
773 : 0 : *rComp.pVal[0], ScGlobal::eLnge, 0,
774 [ # # ]: 0 : rComp.pVal[0]->Len(), NULL));
775 : : String aQuer( pTransliteration->transliterate(
776 : 0 : *rComp.pVal[1], ScGlobal::eLnge, 0,
777 [ # # ]: 0 : rComp.pVal[1]->Len(), NULL));
778 [ # # ][ # # ]: 0 : bMatch = (aCell.Search( aQuer ) != STRING_NOTFOUND);
[ # # ]
779 : : }
780 [ # # ]: 0 : fRes = (bMatch ? 0 : 1);
781 : : }
782 [ # # ]: 0 : else if (pOptions->bIgnoreCase)
783 : : fRes = (double) ScGlobal::GetCollator()->compareString(
784 [ # # ][ # # ]: 0 : *rComp.pVal[ 0 ], *rComp.pVal[ 1 ] );
[ # # ]
785 : : else
786 : : fRes = (double) ScGlobal::GetCaseCollator()->compareString(
787 [ # # ][ # # ]: 0 : *rComp.pVal[ 0 ], *rComp.pVal[ 1 ] );
[ # # ]
788 : : }
789 [ - + ]: 60 : else if (pDok->GetDocOptions().IsIgnoreCase())
790 : : fRes = (double) ScGlobal::GetCollator()->compareString(
791 [ # # ][ # # ]: 0 : *rComp.pVal[ 0 ], *rComp.pVal[ 1 ] );
[ # # ]
792 : : else
793 : : fRes = (double) ScGlobal::GetCaseCollator()->compareString(
794 [ + - ][ + - ]: 60 : *rComp.pVal[ 0 ], *rComp.pVal[ 1 ] );
[ + - ]
795 : : }
796 : 201 : return fRes;
797 : : }
798 : :
799 : :
800 : 9 : double ScInterpreter::Compare()
801 : : {
802 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::Compare" );
803 [ + - ][ + - ]: 9 : String aVal1, aVal2;
804 : 9 : ScCompare aComp( &aVal1, &aVal2 );
805 [ + + ]: 27 : for( short i = 1; i >= 0; i-- )
806 : : {
807 [ + - ][ - + : 18 : switch ( GetRawStackType() )
- + - - ]
808 : : {
809 : : case svEmptyCell:
810 [ # # ]: 0 : Pop();
811 : 0 : aComp.bEmpty[ i ] = true;
812 : 0 : break;
813 : : case svMissing:
814 : : case svDouble:
815 [ + - ]: 9 : aComp.nVal[ i ] = GetDouble();
816 : 9 : aComp.bVal[ i ] = true;
817 : 9 : break;
818 : : case svString:
819 [ # # ][ # # ]: 0 : *aComp.pVal[ i ] = GetString();
820 : 0 : aComp.bVal[ i ] = false;
821 : 0 : break;
822 : : case svDoubleRef :
823 : : case svSingleRef :
824 : : {
825 : 9 : ScAddress aAdr;
826 [ + - ][ + - ]: 9 : if ( !PopDoubleRefOrSingleRef( aAdr ) )
827 : : break;
828 [ + - ]: 9 : ScBaseCell* pCell = GetCell( aAdr );
829 [ + - ][ - + ]: 9 : if (HasCellEmptyData( pCell))
830 : 0 : aComp.bEmpty[ i ] = true;
831 [ + - ][ - + ]: 9 : else if (HasCellStringData( pCell))
832 : : {
833 [ # # ]: 0 : GetCellString( *aComp.pVal[ i ], pCell);
834 : 0 : aComp.bVal[ i ] = false;
835 : : }
836 : : else
837 : : {
838 [ + - ]: 9 : aComp.nVal[ i ] = GetCellValue( aAdr, pCell );
839 : 9 : aComp.bVal[ i ] = true;
840 : : }
841 : : }
842 : 9 : break;
843 : : case svExternalSingleRef:
844 : : {
845 [ # # ]: 0 : ScMatrixRef pMat = GetMatrix();
846 [ # # ]: 0 : if (!pMat)
847 : : {
848 : 0 : SetError( errIllegalParameter);
849 : : break;
850 : : }
851 : :
852 : : SCSIZE nC, nR;
853 [ # # ]: 0 : pMat->GetDimensions(nC, nR);
854 [ # # ][ # # ]: 0 : if (!nC || !nR)
855 : : {
856 : 0 : SetError( errIllegalParameter);
857 : : break;
858 : : }
859 [ # # ][ # # ]: 0 : if (pMat->IsEmpty(0, 0))
860 : 0 : aComp.bEmpty[i] = true;
861 [ # # ][ # # ]: 0 : else if (pMat->IsString(0, 0))
862 : : {
863 [ # # ][ # # ]: 0 : *aComp.pVal[i] = pMat->GetString(0, 0);
864 : 0 : aComp.bVal[i] = false;
865 : : }
866 : : else
867 : : {
868 [ # # ]: 0 : aComp.nVal[i] = pMat->GetDouble(0, 0);
869 : 0 : aComp.bVal[i] = true;
870 [ # # ][ # # ]: 0 : }
871 : : }
872 : 0 : break;
873 : : case svExternalDoubleRef:
874 : : // TODO: Find out how to handle this...
875 : : default:
876 : 0 : SetError( errIllegalParameter);
877 : 0 : break;
878 : : }
879 : : }
880 [ - + ]: 9 : if( nGlobalError )
881 : 0 : return 0;
882 : 9 : nCurFmtType = nFuncFmtType = NUMBERFORMAT_LOGICAL;
883 [ + - ][ + - ]: 9 : return CompareFunc( aComp );
[ + - ]
884 : : }
885 : :
886 : :
887 : 72 : ScMatrixRef ScInterpreter::CompareMat( ScCompareOptions* pOptions )
888 : : {
889 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::CompareMat" );
890 [ + - ][ + - ]: 72 : String aVal1, aVal2;
891 : 72 : ScCompare aComp( &aVal1, &aVal2 );
892 [ + + ][ + - ]: 360 : ScMatrixRef pMat[2];
893 : 72 : ScAddress aAdr;
894 [ + + ]: 216 : for( short i = 1; i >= 0; i-- )
895 : : {
896 [ + - ][ - - : 144 : switch (GetRawStackType())
- + + - ]
897 : : {
898 : : case svEmptyCell:
899 [ # # ]: 0 : Pop();
900 : 0 : aComp.bEmpty[ i ] = true;
901 : 0 : break;
902 : : case svMissing:
903 : : case svDouble:
904 [ # # ]: 0 : aComp.nVal[ i ] = GetDouble();
905 : 0 : aComp.bVal[ i ] = true;
906 : 0 : break;
907 : : case svString:
908 [ # # ][ # # ]: 0 : *aComp.pVal[ i ] = GetString();
909 : 0 : aComp.bVal[ i ] = false;
910 : 0 : break;
911 : : case svSingleRef:
912 : : {
913 [ + - ]: 72 : PopSingleRef( aAdr );
914 [ + - ]: 72 : ScBaseCell* pCell = GetCell( aAdr );
915 [ + - ][ - + ]: 72 : if (HasCellEmptyData( pCell))
916 : 0 : aComp.bEmpty[ i ] = true;
917 [ + - ][ + + ]: 72 : else if (HasCellStringData( pCell))
918 : : {
919 [ + - ]: 36 : GetCellString( *aComp.pVal[ i ], pCell);
920 : 36 : aComp.bVal[ i ] = false;
921 : : }
922 : : else
923 : : {
924 [ + - ]: 36 : aComp.nVal[ i ] = GetCellValue( aAdr, pCell );
925 : 36 : aComp.bVal[ i ] = true;
926 : : }
927 : : }
928 : 72 : break;
929 : : case svDoubleRef:
930 : : case svMatrix:
931 [ + - ][ + - ]: 72 : pMat[ i ] = GetMatrix();
[ + - ]
932 [ - + ]: 72 : if ( !pMat[ i ] )
933 : 0 : SetError( errIllegalParameter);
934 : : else
935 [ + - ]: 72 : pMat[i]->SetErrorInterpreter( NULL);
936 : : // errors are transported as DoubleError inside matrix
937 : 72 : break;
938 : : default:
939 : 0 : SetError( errIllegalParameter);
940 : 0 : break;
941 : : }
942 : : }
943 : 72 : ScMatrixRef pResMat = NULL;
944 [ + - ]: 72 : if( !nGlobalError )
945 : : {
946 [ - + ][ # # ]: 72 : if ( pMat[0] && pMat[1] )
[ - + ]
947 : : {
948 : : SCSIZE nC0, nC1;
949 : : SCSIZE nR0, nR1;
950 [ # # ]: 0 : pMat[0]->GetDimensions( nC0, nR0 );
951 [ # # ]: 0 : pMat[1]->GetDimensions( nC1, nR1 );
952 : 0 : SCSIZE nC = Max( nC0, nC1 );
953 : 0 : SCSIZE nR = Max( nR0, nR1 );
954 [ # # ][ # # ]: 0 : pResMat = GetNewMat( nC, nR);
[ # # ]
955 [ # # ]: 0 : if ( !pResMat )
956 : 0 : return NULL;
957 [ # # ]: 0 : for ( SCSIZE j=0; j<nC; j++ )
958 : : {
959 [ # # ]: 0 : for ( SCSIZE k=0; k<nR; k++ )
960 : : {
961 : 0 : SCSIZE nCol = j, nRow = k;
962 [ # # ][ # # ]: 0 : if ( pMat[0]->ValidColRowOrReplicated( nCol, nRow ) &&
[ # # ][ # # ]
963 [ # # ]: 0 : pMat[1]->ValidColRowOrReplicated( nCol, nRow ))
964 : : {
965 [ # # ]: 0 : for ( short i=1; i>=0; i-- )
966 : : {
967 [ # # ][ # # ]: 0 : if ( pMat[i]->IsString(j,k) )
968 : : {
969 : 0 : aComp.bVal[i] = false;
970 [ # # ][ # # ]: 0 : *aComp.pVal[i] = pMat[i]->GetString(j,k);
971 [ # # ]: 0 : aComp.bEmpty[i] = pMat[i]->IsEmpty(j,k);
972 : : }
973 : : else
974 : : {
975 : 0 : aComp.bVal[i] = true;
976 [ # # ]: 0 : aComp.nVal[i] = pMat[i]->GetDouble(j,k);
977 : 0 : aComp.bEmpty[i] = false;
978 : : }
979 : : }
980 [ # # ][ # # ]: 0 : pResMat->PutDouble( CompareFunc( aComp, pOptions ), j,k );
981 : : }
982 : : else
983 [ # # ][ # # ]: 0 : pResMat->PutString( ScGlobal::GetRscString(STR_NO_VALUE), j,k );
[ # # ]
984 : : }
985 : : }
986 : : }
987 [ + - ][ + - ]: 72 : else if ( pMat[0] || pMat[1] )
[ + - ]
988 : : {
989 : 72 : short i = ( pMat[0] ? 0 : 1);
990 : : SCSIZE nC, nR;
991 [ + - ]: 72 : pMat[i]->GetDimensions( nC, nR );
992 [ + - ][ + - ]: 72 : pResMat = GetNewMat( nC, nR);
[ + - ]
993 [ - + ]: 72 : if ( !pResMat )
994 : 0 : return NULL;
995 : :
996 [ + + ]: 144 : for (SCSIZE j = 0; j < nC; ++j)
997 : : {
998 [ + + ]: 264 : for (SCSIZE k = 0; k < nR; ++k)
999 : : {
1000 [ + - ][ + + ]: 192 : if ( pMat[i]->IsValue(j,k) )
1001 : : {
1002 : 96 : aComp.bVal[i] = true;
1003 [ + - ]: 96 : aComp.nVal[i] = pMat[i]->GetDouble(j,k);
1004 : 96 : aComp.bEmpty[i] = false;
1005 : : }
1006 : : else
1007 : : {
1008 : 96 : aComp.bVal[i] = false;
1009 [ + - ][ + - ]: 96 : *aComp.pVal[i] = pMat[i]->GetString(j,k);
1010 [ + - ]: 96 : aComp.bEmpty[i] = pMat[i]->IsEmpty(j,k);
1011 : : }
1012 [ + - ][ + - ]: 192 : pResMat->PutDouble( CompareFunc(aComp, pOptions), j, k);
1013 : : }
1014 : : }
1015 : : }
1016 : : }
1017 : 72 : nCurFmtType = nFuncFmtType = NUMBERFORMAT_LOGICAL;
1018 [ + - ][ + + ]: 216 : return pResMat;
[ + - ][ + - ]
[ # # ]
1019 : : }
1020 : :
1021 : :
1022 : 0 : ScMatrixRef ScInterpreter::QueryMat( const ScMatrixRef& pMat, ScCompareOptions& rOptions )
1023 : : {
1024 : 0 : short nSaveCurFmtType = nCurFmtType;
1025 : 0 : short nSaveFuncFmtType = nFuncFmtType;
1026 : 0 : PushMatrix( pMat);
1027 : 0 : const ScQueryEntry::Item& rItem = rOptions.aQueryEntry.GetQueryItem();
1028 [ # # ]: 0 : if (rItem.meType == ScQueryEntry::ByString)
1029 [ # # ]: 0 : PushString(rItem.maString);
1030 : : else
1031 : 0 : PushDouble(rItem.mfVal);
1032 : 0 : ScMatrixRef pResultMatrix = CompareMat( &rOptions);
1033 : 0 : nCurFmtType = nSaveCurFmtType;
1034 : 0 : nFuncFmtType = nSaveFuncFmtType;
1035 [ # # ][ # # ]: 0 : if (nGlobalError || !pResultMatrix)
[ # # ]
1036 : : {
1037 : 0 : SetError( errIllegalParameter);
1038 : 0 : return pResultMatrix;
1039 : : }
1040 : :
1041 [ # # # # : 0 : switch (rOptions.aQueryEntry.eOp)
# # # ]
1042 : : {
1043 : : case SC_EQUAL:
1044 [ # # ]: 0 : pResultMatrix->CompareEqual();
1045 : 0 : break;
1046 : : case SC_LESS:
1047 [ # # ]: 0 : pResultMatrix->CompareLess();
1048 : 0 : break;
1049 : : case SC_GREATER:
1050 [ # # ]: 0 : pResultMatrix->CompareGreater();
1051 : 0 : break;
1052 : : case SC_LESS_EQUAL:
1053 [ # # ]: 0 : pResultMatrix->CompareLessEqual();
1054 : 0 : break;
1055 : : case SC_GREATER_EQUAL:
1056 [ # # ]: 0 : pResultMatrix->CompareGreaterEqual();
1057 : 0 : break;
1058 : : case SC_NOT_EQUAL:
1059 [ # # ]: 0 : pResultMatrix->CompareNotEqual();
1060 : 0 : break;
1061 : : default:
1062 : 0 : SetError( errIllegalArgument);
1063 : : OSL_TRACE( "ScInterpreter::QueryMat: unhandled comparison operator: %d", (int)rOptions.aQueryEntry.eOp);
1064 : : }
1065 : 0 : return pResultMatrix;
1066 : : }
1067 : :
1068 : :
1069 : 72 : void ScInterpreter::ScEqual()
1070 : : {
1071 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScEqual" );
1072 [ - + ][ # # ]: 72 : if ( GetStackType(1) == svMatrix || GetStackType(2) == svMatrix )
[ + - ]
1073 : : {
1074 [ + - ]: 72 : ScMatrixRef pMat = CompareMat();
1075 [ - + ]: 72 : if ( !pMat )
1076 [ # # ]: 0 : PushIllegalParameter();
1077 : : else
1078 : : {
1079 [ + - ]: 72 : pMat->CompareEqual();
1080 [ + - ]: 72 : PushMatrix( pMat );
1081 [ + - ]: 72 : }
1082 : : }
1083 : : else
1084 : 0 : PushInt( Compare() == 0 );
1085 : 72 : }
1086 : :
1087 : :
1088 : 0 : void ScInterpreter::ScNotEqual()
1089 : : {
1090 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScNotEqual" );
1091 [ # # ][ # # ]: 0 : if ( GetStackType(1) == svMatrix || GetStackType(2) == svMatrix )
[ # # ]
1092 : : {
1093 [ # # ]: 0 : ScMatrixRef pMat = CompareMat();
1094 [ # # ]: 0 : if ( !pMat )
1095 [ # # ]: 0 : PushIllegalParameter();
1096 : : else
1097 : : {
1098 [ # # ]: 0 : pMat->CompareNotEqual();
1099 [ # # ]: 0 : PushMatrix( pMat );
1100 [ # # ]: 0 : }
1101 : : }
1102 : : else
1103 : 0 : PushInt( Compare() != 0 );
1104 : 0 : }
1105 : :
1106 : :
1107 : 0 : void ScInterpreter::ScLess()
1108 : : {
1109 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScLess" );
1110 [ # # ][ # # ]: 0 : if ( GetStackType(1) == svMatrix || GetStackType(2) == svMatrix )
[ # # ]
1111 : : {
1112 [ # # ]: 0 : ScMatrixRef pMat = CompareMat();
1113 [ # # ]: 0 : if ( !pMat )
1114 [ # # ]: 0 : PushIllegalParameter();
1115 : : else
1116 : : {
1117 [ # # ]: 0 : pMat->CompareLess();
1118 [ # # ]: 0 : PushMatrix( pMat );
1119 [ # # ]: 0 : }
1120 : : }
1121 : : else
1122 : 0 : PushInt( Compare() < 0 );
1123 : 0 : }
1124 : :
1125 : :
1126 : 9 : void ScInterpreter::ScGreater()
1127 : : {
1128 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScGreater" );
1129 [ + - ][ - + ]: 9 : if ( GetStackType(1) == svMatrix || GetStackType(2) == svMatrix )
[ - + ]
1130 : : {
1131 [ # # ]: 0 : ScMatrixRef pMat = CompareMat();
1132 [ # # ]: 0 : if ( !pMat )
1133 [ # # ]: 0 : PushIllegalParameter();
1134 : : else
1135 : : {
1136 [ # # ]: 0 : pMat->CompareGreater();
1137 [ # # ]: 0 : PushMatrix( pMat );
1138 [ # # ]: 0 : }
1139 : : }
1140 : : else
1141 : 9 : PushInt( Compare() > 0 );
1142 : 9 : }
1143 : :
1144 : :
1145 : 0 : void ScInterpreter::ScLessEqual()
1146 : : {
1147 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScLessEqual" );
1148 [ # # ][ # # ]: 0 : if ( GetStackType(1) == svMatrix || GetStackType(2) == svMatrix )
[ # # ]
1149 : : {
1150 [ # # ]: 0 : ScMatrixRef pMat = CompareMat();
1151 [ # # ]: 0 : if ( !pMat )
1152 [ # # ]: 0 : PushIllegalParameter();
1153 : : else
1154 : : {
1155 [ # # ]: 0 : pMat->CompareLessEqual();
1156 [ # # ]: 0 : PushMatrix( pMat );
1157 [ # # ]: 0 : }
1158 : : }
1159 : : else
1160 : 0 : PushInt( Compare() <= 0 );
1161 : 0 : }
1162 : :
1163 : :
1164 : 0 : void ScInterpreter::ScGreaterEqual()
1165 : : {
1166 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScGreaterEqual" );
1167 [ # # ][ # # ]: 0 : if ( GetStackType(1) == svMatrix || GetStackType(2) == svMatrix )
[ # # ]
1168 : : {
1169 [ # # ]: 0 : ScMatrixRef pMat = CompareMat();
1170 [ # # ]: 0 : if ( !pMat )
1171 [ # # ]: 0 : PushIllegalParameter();
1172 : : else
1173 : : {
1174 [ # # ]: 0 : pMat->CompareGreaterEqual();
1175 [ # # ]: 0 : PushMatrix( pMat );
1176 [ # # ]: 0 : }
1177 : : }
1178 : : else
1179 : 0 : PushInt( Compare() >= 0 );
1180 : 0 : }
1181 : :
1182 : :
1183 : 27 : void ScInterpreter::ScAnd()
1184 : : {
1185 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScAnd" );
1186 : 27 : nFuncFmtType = NUMBERFORMAT_LOGICAL;
1187 : 27 : short nParamCount = GetByte();
1188 [ + - ][ + - ]: 27 : if ( MustHaveParamCountMin( nParamCount, 1 ) )
1189 : : {
1190 : 27 : bool bHaveValue = false;
1191 : 27 : short nRes = true;
1192 : 27 : size_t nRefInList = 0;
1193 [ + + ]: 90 : while( nParamCount-- > 0)
1194 : : {
1195 [ + - ]: 63 : if ( !nGlobalError )
1196 : : {
1197 [ + - ][ + - : 63 : switch ( GetStackType() )
- - + - ]
1198 : : {
1199 : : case svDouble :
1200 : 39 : bHaveValue = true;
1201 [ + - ]: 39 : nRes &= ( PopDouble() != 0.0 );
1202 : 39 : break;
1203 : : case svString :
1204 [ # # ]: 0 : Pop();
1205 : 0 : SetError( errNoValue );
1206 : 0 : break;
1207 : : case svSingleRef :
1208 : : {
1209 : 0 : ScAddress aAdr;
1210 [ # # ]: 0 : PopSingleRef( aAdr );
1211 [ # # ]: 0 : if ( !nGlobalError )
1212 : : {
1213 [ # # ]: 0 : ScBaseCell* pCell = GetCell( aAdr );
1214 [ # # ][ # # ]: 0 : if ( HasCellValueData( pCell ) )
1215 : : {
1216 : 0 : bHaveValue = true;
1217 [ # # ]: 0 : nRes &= ( GetCellValue( aAdr, pCell ) != 0.0 );
1218 : : }
1219 : : // else: Xcl raises no error here
1220 : : }
1221 : : }
1222 : 0 : break;
1223 : : case svDoubleRef:
1224 : : case svRefList:
1225 : : {
1226 : 0 : ScRange aRange;
1227 [ # # ]: 0 : PopDoubleRef( aRange, nParamCount, nRefInList);
1228 [ # # ]: 0 : if ( !nGlobalError )
1229 : : {
1230 : : double fVal;
1231 : 0 : sal_uInt16 nErr = 0;
1232 [ # # ]: 0 : ScValueIterator aValIter( pDok, aRange );
1233 [ # # ][ # # ]: 0 : if ( aValIter.GetFirst( fVal, nErr ) )
1234 : : {
1235 : 0 : bHaveValue = true;
1236 [ # # ][ # # ]: 0 : do
[ # # ]
1237 : : {
1238 : 0 : nRes &= ( fVal != 0.0 );
1239 : : } while ( (nErr == 0) &&
1240 [ # # ]: 0 : aValIter.GetNext( fVal, nErr ) );
1241 : : }
1242 : 0 : SetError( nErr );
1243 : : }
1244 : : }
1245 : 0 : break;
1246 : : case svExternalSingleRef:
1247 : : case svExternalDoubleRef:
1248 : : case svMatrix:
1249 : : {
1250 [ + - ]: 24 : ScMatrixRef pMat = GetMatrix();
1251 [ + - ]: 24 : if ( pMat )
1252 : : {
1253 : 24 : bHaveValue = true;
1254 [ + - ]: 24 : double fVal = pMat->And();
1255 : 24 : sal_uInt16 nErr = GetDoubleErrorValue( fVal );
1256 [ - + ]: 24 : if ( nErr )
1257 : : {
1258 : 0 : SetError( nErr );
1259 : 0 : nRes = false;
1260 : : }
1261 : : else
1262 : 24 : nRes &= (fVal != 0.0);
1263 [ + - ]: 24 : }
1264 : : // else: GetMatrix did set errIllegalParameter
1265 : : }
1266 : 24 : break;
1267 : : default:
1268 [ # # ]: 0 : Pop();
1269 : 63 : SetError( errIllegalParameter);
1270 : : }
1271 : : }
1272 : : else
1273 [ # # ]: 0 : Pop();
1274 : : }
1275 [ + - ]: 27 : if ( bHaveValue )
1276 [ + - ]: 27 : PushInt( nRes );
1277 : : else
1278 [ # # ]: 27 : PushNoValue();
1279 : : }
1280 : 27 : }
1281 : :
1282 : :
1283 : 39 : void ScInterpreter::ScOr()
1284 : : {
1285 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScOr" );
1286 : 39 : nFuncFmtType = NUMBERFORMAT_LOGICAL;
1287 : 39 : short nParamCount = GetByte();
1288 [ + - ][ + - ]: 39 : if ( MustHaveParamCountMin( nParamCount, 1 ) )
1289 : : {
1290 : 39 : bool bHaveValue = false;
1291 : 39 : short nRes = false;
1292 : 39 : size_t nRefInList = 0;
1293 [ + + ]: 123 : while( nParamCount-- > 0)
1294 : : {
1295 [ + - ]: 84 : if ( !nGlobalError )
1296 : : {
1297 [ + - ][ + - : 84 : switch ( GetStackType() )
- - + - ]
1298 : : {
1299 : : case svDouble :
1300 : 36 : bHaveValue = true;
1301 [ + - ]: 36 : nRes |= ( PopDouble() != 0.0 );
1302 : 36 : break;
1303 : : case svString :
1304 [ # # ]: 0 : Pop();
1305 : 0 : SetError( errNoValue );
1306 : 0 : break;
1307 : : case svSingleRef :
1308 : : {
1309 : 0 : ScAddress aAdr;
1310 [ # # ]: 0 : PopSingleRef( aAdr );
1311 [ # # ]: 0 : if ( !nGlobalError )
1312 : : {
1313 [ # # ]: 0 : ScBaseCell* pCell = GetCell( aAdr );
1314 [ # # ][ # # ]: 0 : if ( HasCellValueData( pCell ) )
1315 : : {
1316 : 0 : bHaveValue = true;
1317 [ # # ]: 0 : nRes |= ( GetCellValue( aAdr, pCell ) != 0.0 );
1318 : : }
1319 : : // else: Xcl raises no error here
1320 : : }
1321 : : }
1322 : 0 : break;
1323 : : case svDoubleRef:
1324 : : case svRefList:
1325 : : {
1326 : 0 : ScRange aRange;
1327 [ # # ]: 0 : PopDoubleRef( aRange, nParamCount, nRefInList);
1328 [ # # ]: 0 : if ( !nGlobalError )
1329 : : {
1330 : : double fVal;
1331 : 0 : sal_uInt16 nErr = 0;
1332 [ # # ]: 0 : ScValueIterator aValIter( pDok, aRange );
1333 [ # # ][ # # ]: 0 : if ( aValIter.GetFirst( fVal, nErr ) )
1334 : : {
1335 : 0 : bHaveValue = true;
1336 [ # # ][ # # ]: 0 : do
[ # # ]
1337 : : {
1338 : 0 : nRes |= ( fVal != 0.0 );
1339 : : } while ( (nErr == 0) &&
1340 [ # # ]: 0 : aValIter.GetNext( fVal, nErr ) );
1341 : : }
1342 : 0 : SetError( nErr );
1343 : : }
1344 : : }
1345 : 0 : break;
1346 : : case svExternalSingleRef:
1347 : : case svExternalDoubleRef:
1348 : : case svMatrix:
1349 : : {
1350 : 48 : bHaveValue = true;
1351 [ + - ]: 48 : ScMatrixRef pMat = GetMatrix();
1352 [ + - ]: 48 : if ( pMat )
1353 : : {
1354 : 48 : bHaveValue = true;
1355 [ + - ]: 48 : double fVal = pMat->Or();
1356 : 48 : sal_uInt16 nErr = GetDoubleErrorValue( fVal );
1357 [ - + ]: 48 : if ( nErr )
1358 : : {
1359 : 0 : SetError( nErr );
1360 : 0 : nRes = false;
1361 : : }
1362 : : else
1363 : 48 : nRes |= (fVal != 0.0);
1364 [ + - ]: 48 : }
1365 : : // else: GetMatrix did set errIllegalParameter
1366 : : }
1367 : 48 : break;
1368 : : default:
1369 [ # # ]: 0 : Pop();
1370 : 84 : SetError( errIllegalParameter);
1371 : : }
1372 : : }
1373 : : else
1374 [ # # ]: 0 : Pop();
1375 : : }
1376 [ + - ]: 39 : if ( bHaveValue )
1377 [ + - ]: 39 : PushInt( nRes );
1378 : : else
1379 [ # # ]: 39 : PushNoValue();
1380 : : }
1381 : 39 : }
1382 : :
1383 : :
1384 : 0 : void ScInterpreter::ScXor()
1385 : : {
1386 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScXor" );
1387 : :
1388 : 0 : nFuncFmtType = NUMBERFORMAT_LOGICAL;
1389 : 0 : short nParamCount = GetByte();
1390 [ # # ][ # # ]: 0 : if ( MustHaveParamCountMin( nParamCount, 1 ) )
1391 : : {
1392 : 0 : bool bHaveValue = false;
1393 : 0 : short nRes = false;
1394 : 0 : size_t nRefInList = 0;
1395 [ # # ]: 0 : while( nParamCount-- > 0)
1396 : : {
1397 [ # # ]: 0 : if ( !nGlobalError )
1398 : : {
1399 [ # # ][ # # : 0 : switch ( GetStackType() )
# # # # ]
1400 : : {
1401 : : case svDouble :
1402 : 0 : bHaveValue = true;
1403 [ # # ]: 0 : nRes ^= ( PopDouble() != 0.0 );
1404 : 0 : break;
1405 : : case svString :
1406 [ # # ]: 0 : Pop();
1407 : 0 : SetError( errNoValue );
1408 : 0 : break;
1409 : : case svSingleRef :
1410 : : {
1411 : 0 : ScAddress aAdr;
1412 [ # # ]: 0 : PopSingleRef( aAdr );
1413 [ # # ]: 0 : if ( !nGlobalError )
1414 : : {
1415 [ # # ]: 0 : ScBaseCell* pCell = GetCell( aAdr );
1416 [ # # ][ # # ]: 0 : if ( HasCellValueData( pCell ) )
1417 : : {
1418 : 0 : bHaveValue = true;
1419 [ # # ]: 0 : nRes ^= ( GetCellValue( aAdr, pCell ) != 0.0 );
1420 : : }
1421 : : // else: Xcl raises no error here
1422 : : }
1423 : : }
1424 : 0 : break;
1425 : : case svDoubleRef:
1426 : : case svRefList:
1427 : : {
1428 : 0 : ScRange aRange;
1429 [ # # ]: 0 : PopDoubleRef( aRange, nParamCount, nRefInList);
1430 [ # # ]: 0 : if ( !nGlobalError )
1431 : : {
1432 : : double fVal;
1433 : 0 : sal_uInt16 nErr = 0;
1434 [ # # ]: 0 : ScValueIterator aValIter( pDok, aRange );
1435 [ # # ][ # # ]: 0 : if ( aValIter.GetFirst( fVal, nErr ) )
1436 : : {
1437 : 0 : bHaveValue = true;
1438 [ # # ][ # # ]: 0 : do
[ # # ]
1439 : : {
1440 : 0 : nRes ^= ( fVal != 0.0 );
1441 : : } while ( (nErr == 0) &&
1442 [ # # ]: 0 : aValIter.GetNext( fVal, nErr ) );
1443 : : }
1444 : 0 : SetError( nErr );
1445 : : }
1446 : : }
1447 : 0 : break;
1448 : : case svExternalSingleRef:
1449 : : case svExternalDoubleRef:
1450 : : case svMatrix:
1451 : : {
1452 : 0 : bHaveValue = true;
1453 [ # # ]: 0 : ScMatrixRef pMat = GetMatrix();
1454 [ # # ]: 0 : if ( pMat )
1455 : : {
1456 : 0 : bHaveValue = true;
1457 [ # # ]: 0 : double fVal = pMat->Or();
1458 : 0 : sal_uInt16 nErr = GetDoubleErrorValue( fVal );
1459 [ # # ]: 0 : if ( nErr )
1460 : : {
1461 : 0 : SetError( nErr );
1462 : : }
1463 : : else
1464 : 0 : nRes ^= ( fVal != 0.0 );
1465 [ # # ]: 0 : }
1466 : : // else: GetMatrix did set errIllegalParameter
1467 : : }
1468 : 0 : break;
1469 : : default:
1470 [ # # ]: 0 : Pop();
1471 : 0 : SetError( errIllegalParameter);
1472 : : }
1473 : : }
1474 : : else
1475 [ # # ]: 0 : Pop();
1476 : : }
1477 [ # # ]: 0 : if ( bHaveValue )
1478 [ # # ]: 0 : PushInt( nRes );
1479 : : else
1480 [ # # ]: 0 : PushNoValue();
1481 : : }
1482 : 0 : }
1483 : :
1484 : :
1485 : 133 : void ScInterpreter::ScNeg()
1486 : : {
1487 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScNeg" );
1488 : : // Simple negation doesn't change current format type to number, keep
1489 : : // current type.
1490 : 133 : nFuncFmtType = nCurFmtType;
1491 [ - + ]: 133 : switch ( GetStackType() )
1492 : : {
1493 : : case svMatrix :
1494 : : {
1495 [ # # ]: 0 : ScMatrixRef pMat = GetMatrix();
1496 [ # # ]: 0 : if ( !pMat )
1497 [ # # ]: 0 : PushIllegalParameter();
1498 : : else
1499 : : {
1500 : : SCSIZE nC, nR;
1501 [ # # ]: 0 : pMat->GetDimensions( nC, nR );
1502 [ # # ]: 0 : ScMatrixRef pResMat = GetNewMat( nC, nR);
1503 [ # # ]: 0 : if ( !pResMat )
1504 [ # # ]: 0 : PushIllegalArgument();
1505 : : else
1506 : : {
1507 [ # # ]: 0 : for (SCSIZE i = 0; i < nC; ++i)
1508 : : {
1509 [ # # ]: 0 : for (SCSIZE j = 0; j < nR; ++j)
1510 : : {
1511 [ # # ][ # # ]: 0 : if ( pMat->IsValueOrEmpty(i,j) )
1512 [ # # ][ # # ]: 0 : pResMat->PutDouble( -pMat->GetDouble(i,j), i, j );
1513 : : else
1514 : : pResMat->PutString(
1515 [ # # ][ # # ]: 0 : ScGlobal::GetRscString( STR_NO_VALUE ), i, j );
[ # # ]
1516 : : }
1517 : : }
1518 [ # # ]: 0 : PushMatrix( pResMat );
1519 [ # # ]: 0 : }
1520 [ # # ]: 0 : }
1521 : : }
1522 : 0 : break;
1523 : : default:
1524 : 133 : PushDouble( -GetDouble() );
1525 : : }
1526 : 133 : }
1527 : :
1528 : :
1529 : 0 : void ScInterpreter::ScPercentSign()
1530 : : {
1531 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScPercentSign" );
1532 : 0 : nFuncFmtType = NUMBERFORMAT_PERCENT;
1533 : 0 : const FormulaToken* pSaveCur = pCur;
1534 : 0 : sal_uInt8 nSavePar = cPar;
1535 [ # # ]: 0 : PushInt( 100 );
1536 : 0 : cPar = 2;
1537 [ # # ]: 0 : FormulaByteToken aDivOp( ocDiv, cPar );
1538 : 0 : pCur = &aDivOp;
1539 [ # # ]: 0 : ScDiv();
1540 : 0 : pCur = pSaveCur;
1541 [ # # ]: 0 : cPar = nSavePar;
1542 : 0 : }
1543 : :
1544 : :
1545 : 21 : void ScInterpreter::ScNot()
1546 : : {
1547 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScNot" );
1548 : 21 : nFuncFmtType = NUMBERFORMAT_LOGICAL;
1549 [ - + ]: 21 : switch ( GetStackType() )
1550 : : {
1551 : : case svMatrix :
1552 : : {
1553 [ # # ]: 0 : ScMatrixRef pMat = GetMatrix();
1554 [ # # ]: 0 : if ( !pMat )
1555 [ # # ]: 0 : PushIllegalParameter();
1556 : : else
1557 : : {
1558 : : SCSIZE nC, nR;
1559 [ # # ]: 0 : pMat->GetDimensions( nC, nR );
1560 [ # # ]: 0 : ScMatrixRef pResMat = GetNewMat( nC, nR);
1561 [ # # ]: 0 : if ( !pResMat )
1562 [ # # ]: 0 : PushIllegalArgument();
1563 : : else
1564 : : {
1565 [ # # ]: 0 : for (SCSIZE i = 0; i < nC; ++i)
1566 : : {
1567 [ # # ]: 0 : for (SCSIZE j = 0; j < nR; ++j)
1568 : : {
1569 [ # # ][ # # ]: 0 : if ( pMat->IsValueOrEmpty(i,j) )
1570 [ # # ][ # # ]: 0 : pResMat->PutDouble( (pMat->GetDouble(i,j) == 0.0), i, j );
[ # # ]
1571 : : else
1572 : : pResMat->PutString(
1573 [ # # ][ # # ]: 0 : ScGlobal::GetRscString( STR_NO_VALUE ), i, j );
[ # # ]
1574 : : }
1575 : : }
1576 [ # # ]: 0 : PushMatrix( pResMat );
1577 [ # # ]: 0 : }
1578 [ # # ]: 0 : }
1579 : : }
1580 : 0 : break;
1581 : : default:
1582 : 21 : PushInt( GetDouble() == 0.0 );
1583 : : }
1584 : 21 : }
1585 : :
1586 : :
1587 : 9 : void ScInterpreter::ScBitAnd()
1588 : : {
1589 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "pechlaner", "ScInterpreter::ScBitAnd" );
1590 : :
1591 [ - + ]: 9 : if ( !MustHaveParamCount( GetByte(), 2 ) )
1592 : 9 : return;
1593 : :
1594 : 9 : double num1 = ::rtl::math::approxFloor( GetDouble());
1595 : 9 : double num2 = ::rtl::math::approxFloor( GetDouble());
1596 [ + - ][ + + ]: 9 : if ( (num1 >= n2power48) || (num1 < 0) ||
[ + + ][ + - ]
1597 : : (num2 >= n2power48) || (num2 < 0))
1598 : 6 : PushIllegalArgument();
1599 : : else
1600 : 3 : PushDouble ((sal_uInt64) num1 & (sal_uInt64) num2);
1601 : : }
1602 : :
1603 : :
1604 : 6 : void ScInterpreter::ScBitOr()
1605 : : {
1606 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "pechlaner", "ScInterpreter::ScBitOr" );
1607 : :
1608 [ - + ]: 6 : if ( !MustHaveParamCount( GetByte(), 2 ) )
1609 : 6 : return;
1610 : :
1611 : 6 : double num1 = ::rtl::math::approxFloor( GetDouble());
1612 : 6 : double num2 = ::rtl::math::approxFloor( GetDouble());
1613 [ + - ][ + - ]: 6 : if ( (num1 >= n2power48) || (num1 < 0) ||
[ + + ][ + - ]
1614 : : (num2 >= n2power48) || (num2 < 0))
1615 : 3 : PushIllegalArgument();
1616 : : else
1617 : 3 : PushDouble ((sal_uInt64) num1 | (sal_uInt64) num2);
1618 : : }
1619 : :
1620 : :
1621 : 6 : void ScInterpreter::ScBitXor()
1622 : : {
1623 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "pechlaner", "ScInterpreter::ScBitXor" );
1624 : :
1625 [ - + ]: 6 : if ( !MustHaveParamCount( GetByte(), 2 ) )
1626 : 6 : return;
1627 : :
1628 : 6 : double num1 = ::rtl::math::approxFloor( GetDouble());
1629 : 6 : double num2 = ::rtl::math::approxFloor( GetDouble());
1630 [ + - ][ + - ]: 6 : if ( (num1 >= n2power48) || (num1 < 0) ||
[ + + ][ + - ]
1631 : : (num2 >= n2power48) || (num2 < 0))
1632 : 3 : PushIllegalArgument();
1633 : : else
1634 : 3 : PushDouble ((sal_uInt64) num1 ^ (sal_uInt64) num2);
1635 : : }
1636 : :
1637 : :
1638 : 6 : void ScInterpreter::ScBitLshift()
1639 : : {
1640 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "pechlaner", "ScInterpreter::ScBitLshift" );
1641 : :
1642 [ - + ]: 6 : if ( !MustHaveParamCount( GetByte(), 2 ) )
1643 : 6 : return;
1644 : :
1645 : 6 : double fShift = ::rtl::math::approxFloor( GetDouble());
1646 : 6 : double num = ::rtl::math::approxFloor( GetDouble());
1647 [ - + ][ + - ]: 6 : if ((num >= n2power48) || (num < 0))
1648 : 0 : PushIllegalArgument();
1649 : : else
1650 : : {
1651 : : double fRes;
1652 [ + + ]: 6 : if (fShift < 0)
1653 : 3 : fRes = ::rtl::math::approxFloor( num / pow( 2.0, -fShift));
1654 [ - + ]: 3 : else if (fShift == 0)
1655 : 0 : fRes = num;
1656 : : else
1657 : 3 : fRes = num * pow( 2.0, fShift);
1658 : 6 : PushDouble( fRes);
1659 : : }
1660 : : }
1661 : :
1662 : :
1663 : 6 : void ScInterpreter::ScBitRshift()
1664 : : {
1665 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "pechlaner", "ScInterpreter::ScBitRshift" );
1666 : :
1667 [ - + ]: 6 : if ( !MustHaveParamCount( GetByte(), 2 ) )
1668 : 6 : return;
1669 : :
1670 : 6 : double fShift = ::rtl::math::approxFloor( GetDouble());
1671 : 6 : double num = ::rtl::math::approxFloor( GetDouble());
1672 [ - + ][ + - ]: 6 : if ((num >= n2power48) || (num < 0))
1673 : 0 : PushIllegalArgument();
1674 : : else
1675 : : {
1676 : : double fRes;
1677 [ + + ]: 6 : if (fShift < 0)
1678 : 3 : fRes = num * pow( 2.0, -fShift);
1679 [ - + ]: 3 : else if (fShift == 0)
1680 : 0 : fRes = num;
1681 : : else
1682 : 3 : fRes = ::rtl::math::approxFloor( num / pow( 2.0, fShift));
1683 : 6 : PushDouble( fRes);
1684 : : }
1685 : : }
1686 : :
1687 : :
1688 : 30 : void ScInterpreter::ScPi()
1689 : : {
1690 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScPi" );
1691 : 30 : PushDouble(F_PI);
1692 : 30 : }
1693 : :
1694 : :
1695 : 0 : void ScInterpreter::ScRandom()
1696 : : {
1697 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScRandom" );
1698 : 0 : PushDouble((double)rand() / ((double)RAND_MAX+1.0));
1699 : 0 : }
1700 : :
1701 : :
1702 : 27 : void ScInterpreter::ScTrue()
1703 : : {
1704 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScTrue" );
1705 : 27 : nFuncFmtType = NUMBERFORMAT_LOGICAL;
1706 : 27 : PushInt(1);
1707 : 27 : }
1708 : :
1709 : :
1710 : 12 : void ScInterpreter::ScFalse()
1711 : : {
1712 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScFalse" );
1713 : 12 : nFuncFmtType = NUMBERFORMAT_LOGICAL;
1714 : 12 : PushInt(0);
1715 : 12 : }
1716 : :
1717 : :
1718 : 0 : void ScInterpreter::ScDeg()
1719 : : {
1720 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScDeg" );
1721 : 0 : PushDouble((GetDouble() / F_PI) * 180.0);
1722 : 0 : }
1723 : :
1724 : :
1725 : 0 : void ScInterpreter::ScRad()
1726 : : {
1727 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScRad" );
1728 : 0 : PushDouble(GetDouble() * (F_PI / 180));
1729 : 0 : }
1730 : :
1731 : :
1732 : 6 : void ScInterpreter::ScSin()
1733 : : {
1734 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScSin" );
1735 : 6 : PushDouble(::rtl::math::sin(GetDouble()));
1736 : 6 : }
1737 : :
1738 : :
1739 : 6 : void ScInterpreter::ScCos()
1740 : : {
1741 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScCos" );
1742 : 6 : PushDouble(::rtl::math::cos(GetDouble()));
1743 : 6 : }
1744 : :
1745 : :
1746 : 0 : void ScInterpreter::ScTan()
1747 : : {
1748 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScTan" );
1749 : 0 : PushDouble(::rtl::math::tan(GetDouble()));
1750 : 0 : }
1751 : :
1752 : :
1753 : 0 : void ScInterpreter::ScCot()
1754 : : {
1755 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScCot" );
1756 : 0 : PushDouble(1.0 / ::rtl::math::tan(GetDouble()));
1757 : 0 : }
1758 : :
1759 : :
1760 : 0 : void ScInterpreter::ScArcSin()
1761 : : {
1762 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScArcSin" );
1763 : 0 : PushDouble(asin(GetDouble()));
1764 : 0 : }
1765 : :
1766 : :
1767 : 9 : void ScInterpreter::ScArcCos()
1768 : : {
1769 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScArcCos" );
1770 : 9 : PushDouble(acos(GetDouble()));
1771 : 9 : }
1772 : :
1773 : :
1774 : 0 : void ScInterpreter::ScArcTan()
1775 : : {
1776 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScArcTan" );
1777 : 0 : PushDouble(atan(GetDouble()));
1778 : 0 : }
1779 : :
1780 : :
1781 : 9 : void ScInterpreter::ScArcCot()
1782 : : {
1783 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScArcCot" );
1784 : 9 : PushDouble((F_PI2) - atan(GetDouble()));
1785 : 9 : }
1786 : :
1787 : :
1788 : 0 : void ScInterpreter::ScSinHyp()
1789 : : {
1790 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScSinHyp" );
1791 : 0 : PushDouble(sinh(GetDouble()));
1792 : 0 : }
1793 : :
1794 : :
1795 : 0 : void ScInterpreter::ScCosHyp()
1796 : : {
1797 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScCosHyp" );
1798 : 0 : PushDouble(cosh(GetDouble()));
1799 : 0 : }
1800 : :
1801 : :
1802 : 0 : void ScInterpreter::ScTanHyp()
1803 : : {
1804 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScTanHyp" );
1805 : 0 : PushDouble(tanh(GetDouble()));
1806 : 0 : }
1807 : :
1808 : :
1809 : 0 : void ScInterpreter::ScCotHyp()
1810 : : {
1811 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScCotHyp" );
1812 : 0 : PushDouble(1.0 / tanh(GetDouble()));
1813 : 0 : }
1814 : :
1815 : :
1816 : 0 : void ScInterpreter::ScArcSinHyp()
1817 : : {
1818 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScArcSinHyp" );
1819 : 0 : PushDouble( ::rtl::math::asinh( GetDouble()));
1820 : 0 : }
1821 : :
1822 : 6 : void ScInterpreter::ScArcCosHyp()
1823 : : {
1824 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScArcCosHyp" );
1825 : 6 : double fVal = GetDouble();
1826 [ + + ]: 6 : if (fVal < 1.0)
1827 : 3 : PushIllegalArgument();
1828 : : else
1829 : 3 : PushDouble( ::rtl::math::acosh( fVal));
1830 : 6 : }
1831 : :
1832 : 0 : void ScInterpreter::ScArcTanHyp()
1833 : : {
1834 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScArcTanHyp" );
1835 : 0 : double fVal = GetDouble();
1836 [ # # ]: 0 : if (fabs(fVal) >= 1.0)
1837 : 0 : PushIllegalArgument();
1838 : : else
1839 : 0 : PushDouble( ::rtl::math::atanh( fVal));
1840 : 0 : }
1841 : :
1842 : :
1843 : 0 : void ScInterpreter::ScArcCotHyp()
1844 : : {
1845 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScArcCotHyp" );
1846 : 0 : double nVal = GetDouble();
1847 [ # # ]: 0 : if (fabs(nVal) <= 1.0)
1848 : 0 : PushIllegalArgument();
1849 : : else
1850 : 0 : PushDouble(0.5 * log((nVal + 1.0) / (nVal - 1.0)));
1851 : 0 : }
1852 : :
1853 : 0 : void ScInterpreter::ScCosecant()
1854 : : {
1855 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "regina", "ScInterpreter::ScCosecant" );
1856 : 0 : PushDouble(1.0 / ::rtl::math::sin(GetDouble()));
1857 : 0 : }
1858 : :
1859 : 0 : void ScInterpreter::ScSecant()
1860 : : {
1861 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "regina", "ScInterpreter::ScSecant" );
1862 : 0 : PushDouble(1.0 / ::rtl::math::cos(GetDouble()));
1863 : 0 : }
1864 : :
1865 : 0 : void ScInterpreter::ScCosecantHyp()
1866 : : {
1867 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "regina", "ScInterpreter::ScCosecantHyp" );
1868 : 0 : PushDouble(1.0 / sinh(GetDouble()));
1869 : 0 : }
1870 : :
1871 : 0 : void ScInterpreter::ScSecantHyp()
1872 : : {
1873 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "regina", "ScInterpreter::ScSecantHyp" );
1874 : 0 : PushDouble(1.0 / cosh(GetDouble()));
1875 : 0 : }
1876 : :
1877 : :
1878 : 0 : void ScInterpreter::ScExp()
1879 : : {
1880 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScExp" );
1881 : 0 : PushDouble(exp(GetDouble()));
1882 : 0 : }
1883 : :
1884 : :
1885 : 148 : void ScInterpreter::ScSqrt()
1886 : : {
1887 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScSqrt" );
1888 : 148 : double fVal = GetDouble();
1889 [ + + ]: 148 : if (fVal >= 0.0)
1890 : 37 : PushDouble(sqrt(fVal));
1891 : : else
1892 : 111 : PushIllegalArgument();
1893 : 148 : }
1894 : :
1895 : :
1896 : 15 : void ScInterpreter::ScIsEmpty()
1897 : : {
1898 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScIsEmpty" );
1899 : 15 : short nRes = 0;
1900 : 15 : nFuncFmtType = NUMBERFORMAT_LOGICAL;
1901 [ - + - - ]: 15 : switch ( GetRawStackType() )
1902 : : {
1903 : : case svEmptyCell:
1904 : : {
1905 [ # # ]: 0 : FormulaTokenRef p = PopToken();
1906 [ # # ]: 0 : if (!static_cast<const ScEmptyCellToken*>(p.get())->IsInherited())
1907 [ # # ]: 0 : nRes = 1;
1908 : : }
1909 : 0 : break;
1910 : : case svDoubleRef :
1911 : : case svSingleRef :
1912 : : {
1913 : 15 : ScAddress aAdr;
1914 [ + - ][ + - ]: 15 : if ( !PopDoubleRefOrSingleRef( aAdr ) )
1915 : : break;
1916 : : // NOTE: this could test also on inherited emptiness, but then the
1917 : : // cell tested wouldn't be empty. Must correspond with
1918 : : // ScCountEmptyCells().
1919 : : // if (HasCellEmptyData( GetCell( aAdr)))
1920 [ + - ]: 15 : CellType eCellType = GetCellType( GetCell( aAdr ) );
1921 [ + + ][ + - ]: 15 : if((eCellType == CELLTYPE_NONE) || (eCellType == CELLTYPE_NOTE))
1922 : 3 : nRes = 1;
1923 : : }
1924 : 15 : break;
1925 : : case svExternalSingleRef:
1926 : : case svExternalDoubleRef:
1927 : : case svMatrix:
1928 : : {
1929 [ # # ]: 0 : ScMatrixRef pMat = GetMatrix();
1930 [ # # ]: 0 : if ( !pMat )
1931 : : ; // nothing
1932 [ # # ]: 0 : else if ( !pJumpMatrix )
1933 [ # # ]: 0 : nRes = pMat->IsEmpty( 0, 0);
1934 : : else
1935 : : {
1936 : : SCSIZE nCols, nRows, nC, nR;
1937 [ # # ]: 0 : pMat->GetDimensions( nCols, nRows);
1938 : 0 : pJumpMatrix->GetPos( nC, nR);
1939 [ # # ][ # # ]: 0 : if ( nC < nCols && nR < nRows )
1940 [ # # ]: 0 : nRes = pMat->IsEmpty( nC, nR);
1941 : : // else: false, not empty (which is what Xcl does)
1942 [ # # ]: 0 : }
1943 : : }
1944 : 0 : break;
1945 : : default:
1946 : 0 : Pop();
1947 : : }
1948 : 15 : nGlobalError = 0;
1949 : 15 : PushInt( nRes );
1950 : 15 : }
1951 : :
1952 : :
1953 : 27 : short ScInterpreter::IsString()
1954 : : {
1955 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::IsString" );
1956 : 27 : nFuncFmtType = NUMBERFORMAT_LOGICAL;
1957 : 27 : short nRes = 0;
1958 [ + + - + ]: 27 : switch ( GetRawStackType() )
1959 : : {
1960 : : case svString:
1961 : 3 : Pop();
1962 : 3 : nRes = 1;
1963 : 3 : break;
1964 : : case svDoubleRef :
1965 : : case svSingleRef :
1966 : : {
1967 : 21 : ScAddress aAdr;
1968 [ + - ][ + - ]: 21 : if ( !PopDoubleRefOrSingleRef( aAdr ) )
1969 : : break;
1970 [ + - ]: 21 : ScBaseCell* pCell = GetCell( aAdr );
1971 [ + - ][ + - ]: 21 : if (GetCellErrCode( pCell ) == 0)
1972 : : {
1973 [ - + - ]: 21 : switch ( GetCellType( pCell ) )
1974 : : {
1975 : : case CELLTYPE_STRING :
1976 : : case CELLTYPE_EDIT :
1977 : 0 : nRes = 1;
1978 : 0 : break;
1979 : : case CELLTYPE_FORMULA :
1980 [ + - ][ + - ]: 21 : nRes = !((ScFormulaCell*)pCell)->IsValue() &&
1981 [ + + ][ + - ]: 21 : !((ScFormulaCell*)pCell)->IsEmpty();
[ + - ][ + - ]
1982 : 21 : break;
1983 : : default:
1984 : : ; // nothing
1985 : : }
1986 : : }
1987 : : }
1988 : 21 : break;
1989 : : case svMatrix:
1990 : : {
1991 [ # # ]: 0 : ScMatrixRef pMat = PopMatrix();
1992 [ # # ]: 0 : if ( !pMat )
1993 : : ; // nothing
1994 [ # # ]: 0 : else if ( !pJumpMatrix )
1995 [ # # ][ # # ]: 0 : nRes = pMat->IsString(0, 0) && !pMat->IsEmpty(0, 0);
[ # # ][ # # ]
1996 : : else
1997 : : {
1998 : : SCSIZE nCols, nRows, nC, nR;
1999 [ # # ]: 0 : pMat->GetDimensions( nCols, nRows);
2000 : 0 : pJumpMatrix->GetPos( nC, nR);
2001 [ # # ][ # # ]: 0 : if ( nC < nCols && nR < nRows )
2002 [ # # ][ # # ]: 0 : nRes = pMat->IsString( nC, nR) && !pMat->IsEmpty( nC, nR);
[ # # ][ # # ]
2003 [ # # ]: 0 : }
2004 : : }
2005 : 0 : break;
2006 : : default:
2007 : 3 : Pop();
2008 : : }
2009 : 27 : nGlobalError = 0;
2010 : 27 : return nRes;
2011 : : }
2012 : :
2013 : :
2014 : 18 : void ScInterpreter::ScIsString()
2015 : : {
2016 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScIsString" );
2017 : 18 : PushInt( IsString() );
2018 : 18 : }
2019 : :
2020 : :
2021 : 9 : void ScInterpreter::ScIsNonString()
2022 : : {
2023 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScIsNonString" );
2024 : 9 : PushInt( !IsString() );
2025 : 9 : }
2026 : :
2027 : :
2028 : 12 : void ScInterpreter::ScIsLogical()
2029 : : {
2030 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScIsLogical" );
2031 : 12 : short nRes = 0;
2032 [ + + ]: 12 : switch ( GetStackType() )
2033 : : {
2034 : : case svDoubleRef :
2035 : : case svSingleRef :
2036 : : {
2037 : 3 : ScAddress aAdr;
2038 [ + - ][ + - ]: 3 : if ( !PopDoubleRefOrSingleRef( aAdr ) )
2039 : : break;
2040 [ + - ]: 3 : ScBaseCell* pCell = GetCell( aAdr );
2041 [ + - ][ + - ]: 3 : if (GetCellErrCode( pCell ) == 0)
2042 : : {
2043 [ + - ][ + - ]: 3 : if (HasCellValueData(pCell))
2044 : : {
2045 [ + - ]: 3 : sal_uLong nFormat = GetCellNumberFormat( aAdr, pCell );
2046 [ + - ]: 3 : nRes = ( pFormatter->GetType(nFormat)
2047 : 3 : == NUMBERFORMAT_LOGICAL);
2048 : : }
2049 : : }
2050 : : }
2051 : 3 : break;
2052 : : case svMatrix:
2053 : : // TODO: we don't have type information for arrays except
2054 : : // numerical/string.
2055 : : // Fall thru
2056 : : default:
2057 : 9 : PopError();
2058 [ + - ]: 9 : if ( !nGlobalError )
2059 : 9 : nRes = ( nCurFmtType == NUMBERFORMAT_LOGICAL );
2060 : : }
2061 : 12 : nCurFmtType = nFuncFmtType = NUMBERFORMAT_LOGICAL;
2062 : 12 : nGlobalError = 0;
2063 : 12 : PushInt( nRes );
2064 : 12 : }
2065 : :
2066 : :
2067 : 15 : void ScInterpreter::ScType()
2068 : : {
2069 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScType" );
2070 : 15 : short nType = 0;
2071 [ + + + + ]: 15 : switch ( GetStackType() )
2072 : : {
2073 : : case svDoubleRef :
2074 : : case svSingleRef :
2075 : : {
2076 : 3 : ScAddress aAdr;
2077 [ + - ][ + - ]: 3 : if ( !PopDoubleRefOrSingleRef( aAdr ) )
2078 : : break;
2079 [ + - ]: 3 : ScBaseCell* pCell = GetCell( aAdr );
2080 [ + - ][ + - ]: 3 : if (GetCellErrCode( pCell ) == 0)
2081 : : {
2082 [ - - - + : 3 : switch ( GetCellType( pCell ) )
- ]
2083 : : {
2084 : : // NOTE: this is Xcl nonsense!
2085 : : case CELLTYPE_NOTE :
2086 : 0 : nType = 1; // empty cell is value (0)
2087 : 0 : break;
2088 : : case CELLTYPE_STRING :
2089 : : case CELLTYPE_EDIT :
2090 : 0 : nType = 2;
2091 : 0 : break;
2092 : : case CELLTYPE_VALUE :
2093 : : {
2094 [ # # ]: 0 : sal_uLong nFormat = GetCellNumberFormat( aAdr, pCell );
2095 [ # # ][ # # ]: 0 : if (pFormatter->GetType(nFormat)
2096 : : == NUMBERFORMAT_LOGICAL)
2097 : 0 : nType = 4;
2098 : : else
2099 : 0 : nType = 1;
2100 : : }
2101 : 0 : break;
2102 : : case CELLTYPE_FORMULA :
2103 : 3 : nType = 8;
2104 : 3 : break;
2105 : : default:
2106 [ # # ]: 3 : PushIllegalArgument();
2107 : : }
2108 : : }
2109 : : else
2110 : 0 : nType = 16;
2111 : : }
2112 : 3 : break;
2113 : : case svString:
2114 : 3 : PopError();
2115 [ - + ]: 3 : if ( nGlobalError )
2116 : : {
2117 : 0 : nType = 16;
2118 : 0 : nGlobalError = 0;
2119 : : }
2120 : : else
2121 : 3 : nType = 2;
2122 : 3 : break;
2123 : : case svMatrix:
2124 : 3 : PopMatrix();
2125 [ - + ]: 3 : if ( nGlobalError )
2126 : : {
2127 : 0 : nType = 16;
2128 : 0 : nGlobalError = 0;
2129 : : }
2130 : : else
2131 : 3 : nType = 64;
2132 : : // we could return the type of one element if in JumpMatrix or
2133 : : // ForceArray mode, but Xcl doesn't ...
2134 : 3 : break;
2135 : : default:
2136 : 6 : PopError();
2137 [ + + ]: 6 : if ( nGlobalError )
2138 : : {
2139 : 3 : nType = 16;
2140 : 3 : nGlobalError = 0;
2141 : : }
2142 : : else
2143 : 3 : nType = 1;
2144 : : }
2145 : 15 : PushInt( nType );
2146 : 15 : }
2147 : :
2148 : :
2149 : 3 : inline bool lcl_FormatHasNegColor( const SvNumberformat* pFormat )
2150 : : {
2151 [ + - ][ - + ]: 3 : return pFormat && pFormat->GetColor( 1 );
2152 : : }
2153 : :
2154 : :
2155 : 3 : inline bool lcl_FormatHasOpenPar( const SvNumberformat* pFormat )
2156 : : {
2157 [ + - ][ - + ]: 3 : return pFormat && (pFormat->GetFormatstring().Search( '(' ) != STRING_NOTFOUND);
2158 : : }
2159 : :
2160 : : namespace {
2161 : :
2162 : 0 : void getFormatString(SvNumberFormatter* pFormatter, sal_uLong nFormat, String& rFmtStr)
2163 : : {
2164 : 0 : bool bAppendPrec = true;
2165 : : sal_uInt16 nPrec, nLeading;
2166 : : bool bThousand, bIsRed;
2167 [ # # ]: 0 : pFormatter->GetFormatSpecialInfo( nFormat, bThousand, bIsRed, nPrec, nLeading );
2168 : :
2169 [ # # ][ # # : 0 : switch( pFormatter->GetType( nFormat ) )
# # # ]
2170 : : {
2171 [ # # ][ # # ]: 0 : case NUMBERFORMAT_NUMBER: rFmtStr = (bThousand ? ',' : 'F'); break;
2172 [ # # ]: 0 : case NUMBERFORMAT_CURRENCY: rFmtStr = 'C'; break;
2173 [ # # ]: 0 : case NUMBERFORMAT_SCIENTIFIC: rFmtStr = 'S'; break;
2174 [ # # ]: 0 : case NUMBERFORMAT_PERCENT: rFmtStr = 'P'; break;
2175 : : default:
2176 : : {
2177 : 0 : bAppendPrec = false;
2178 [ # # ][ # # : 0 : switch( pFormatter->GetIndexTableOffset( nFormat ) )
# # # # #
# # # ]
2179 : : {
2180 : : case NF_DATE_SYSTEM_SHORT:
2181 : : case NF_DATE_SYS_DMMMYY:
2182 : : case NF_DATE_SYS_DDMMYY:
2183 : : case NF_DATE_SYS_DDMMYYYY:
2184 : : case NF_DATE_SYS_DMMMYYYY:
2185 : : case NF_DATE_DIN_DMMMYYYY:
2186 : : case NF_DATE_SYS_DMMMMYYYY:
2187 [ # # ]: 0 : case NF_DATE_DIN_DMMMMYYYY: rFmtStr.AssignAscii( RTL_CONSTASCII_STRINGPARAM( "D1" ) ); break;
2188 [ # # ]: 0 : case NF_DATE_SYS_DDMMM: rFmtStr.AssignAscii( RTL_CONSTASCII_STRINGPARAM( "D2" ) ); break;
2189 [ # # ]: 0 : case NF_DATE_SYS_MMYY: rFmtStr.AssignAscii( RTL_CONSTASCII_STRINGPARAM( "D3" ) ); break;
2190 : : case NF_DATETIME_SYSTEM_SHORT_HHMM:
2191 : : case NF_DATETIME_SYS_DDMMYYYY_HHMMSS:
2192 [ # # ]: 0 : rFmtStr.AssignAscii( RTL_CONSTASCII_STRINGPARAM( "D4" ) ); break;
2193 [ # # ]: 0 : case NF_DATE_DIN_MMDD: rFmtStr.AssignAscii( RTL_CONSTASCII_STRINGPARAM( "D5" ) ); break;
2194 [ # # ]: 0 : case NF_TIME_HHMMSSAMPM: rFmtStr.AssignAscii( RTL_CONSTASCII_STRINGPARAM( "D6" ) ); break;
2195 [ # # ]: 0 : case NF_TIME_HHMMAMPM: rFmtStr.AssignAscii( RTL_CONSTASCII_STRINGPARAM( "D7" ) ); break;
2196 [ # # ]: 0 : case NF_TIME_HHMMSS: rFmtStr.AssignAscii( RTL_CONSTASCII_STRINGPARAM( "D8" ) ); break;
2197 [ # # ]: 0 : case NF_TIME_HHMM: rFmtStr.AssignAscii( RTL_CONSTASCII_STRINGPARAM( "D9" ) ); break;
2198 [ # # ]: 0 : default: rFmtStr = 'G';
2199 : : }
2200 : : }
2201 : : }
2202 [ # # ]: 0 : if( bAppendPrec )
2203 [ # # ]: 0 : rFmtStr += rtl::OUString::valueOf(static_cast<sal_Int32>(nPrec));
2204 [ # # ]: 0 : const SvNumberformat* pFormat = pFormatter->GetEntry( nFormat );
2205 [ # # ][ # # ]: 0 : if( lcl_FormatHasNegColor( pFormat ) )
2206 [ # # ]: 0 : rFmtStr += '-';
2207 [ # # ][ # # ]: 0 : if( lcl_FormatHasOpenPar( pFormat ) )
2208 [ # # ]: 0 : rFmtStr.AppendAscii( RTL_CONSTASCII_STRINGPARAM( "()" ) );
2209 : 0 : }
2210 : :
2211 : : }
2212 : :
2213 : 57 : void ScInterpreter::ScCell()
2214 : : { // ATTRIBUTE ; [REF]
2215 : 57 : sal_uInt8 nParamCount = GetByte();
2216 [ + - ]: 57 : if( MustHaveParamCount( nParamCount, 1, 2 ) )
2217 : : {
2218 : 57 : ScAddress aCellPos( aPos );
2219 : 57 : bool bError = false;
2220 [ + - ]: 57 : if( nParamCount == 2 )
2221 : : {
2222 [ + - ][ - + ]: 57 : switch (GetStackType())
2223 : : {
2224 : : case svExternalSingleRef:
2225 : : case svExternalDoubleRef:
2226 : : {
2227 : : // Let's handle external reference separately...
2228 [ # # ]: 0 : ScCellExternal();
2229 : 57 : return;
2230 : : }
2231 : : default:
2232 : : ;
2233 : : }
2234 [ + - ]: 57 : bError = !PopDoubleRefOrSingleRef( aCellPos );
2235 : : }
2236 [ + - ][ + - ]: 57 : String aInfoType( GetString() );
2237 [ + - ][ - + ]: 57 : if( bError || nGlobalError )
2238 [ # # ]: 0 : PushIllegalParameter();
2239 : : else
2240 : : {
2241 [ + - ]: 57 : ScBaseCell* pCell = GetCell( aCellPos );
2242 : :
2243 [ + - ][ + - ]: 57 : ScCellKeywordTranslator::transKeyword(aInfoType, ScGlobal::GetLocale(), ocCell);
2244 : :
2245 : : // *** ADDRESS INFO ***
2246 [ + - ][ + + ]: 57 : if( aInfoType.EqualsAscii( "COL" ) )
2247 : : { // column number (1-based)
2248 [ + - ]: 6 : PushInt( aCellPos.Col() + 1 );
2249 : : }
2250 [ + - ][ + + ]: 51 : else if( aInfoType.EqualsAscii( "ROW" ) )
2251 : : { // row number (1-based)
2252 [ + - ]: 6 : PushInt( aCellPos.Row() + 1 );
2253 : : }
2254 [ + - ][ + + ]: 45 : else if( aInfoType.EqualsAscii( "SHEET" ) )
2255 : : { // table number (1-based)
2256 [ + - ]: 6 : PushInt( aCellPos.Tab() + 1 );
2257 : : }
2258 [ + - ][ + + ]: 39 : else if( aInfoType.EqualsAscii( "ADDRESS" ) )
2259 : : { // address formatted as [['FILENAME'#]$TABLE.]$COL$ROW
2260 [ + + ]: 9 : sal_uInt16 nFlags = (aCellPos.Tab() == aPos.Tab()) ? (SCA_ABS) : (SCA_ABS_3D);
2261 : 9 : rtl::OUString aStr;
2262 [ + - ][ + - ]: 9 : aCellPos.Format( aStr, nFlags, pDok, pDok->GetAddressConvention() );
2263 [ + - ][ + - ]: 9 : PushString(aStr);
[ + - ]
2264 : : }
2265 [ + - ][ - + ]: 30 : else if( aInfoType.EqualsAscii( "FILENAME" ) )
2266 : : { // file name and table name: 'FILENAME'#$TABLE
2267 : 0 : SCTAB nTab = aCellPos.Tab();
2268 : 0 : rtl::OUString aFuncResult;
2269 [ # # ][ # # ]: 0 : if( nTab < pDok->GetTableCount() )
2270 : : {
2271 [ # # ][ # # ]: 0 : if( pDok->GetLinkMode( nTab ) == SC_LINK_VALUE )
2272 [ # # ]: 0 : pDok->GetName( nTab, aFuncResult );
2273 : : else
2274 : : {
2275 : 0 : SfxObjectShell* pShell = pDok->GetDocumentShell();
2276 [ # # ][ # # ]: 0 : if( pShell && pShell->GetMedium() )
[ # # ]
2277 : : {
2278 : 0 : rtl::OUStringBuffer aBuf;
2279 [ # # ]: 0 : aBuf.append(sal_Unicode('\''));
2280 [ # # ]: 0 : const INetURLObject& rURLObj = pShell->GetMedium()->GetURLObject();
2281 [ # # ][ # # ]: 0 : aBuf.append(rURLObj.GetMainURL(INetURLObject::DECODE_UNAMBIGUOUS));
2282 [ # # ]: 0 : aBuf.appendAscii("'#$");
2283 : 0 : rtl::OUString aTabName;
2284 [ # # ]: 0 : pDok->GetName( nTab, aTabName );
2285 [ # # ]: 0 : aBuf.append(aTabName);
2286 [ # # ]: 0 : aFuncResult = aBuf.makeStringAndClear();
2287 : : }
2288 : : }
2289 : : }
2290 [ # # ][ # # ]: 0 : PushString( aFuncResult );
[ # # ]
2291 : : }
2292 [ + - ][ - + ]: 30 : else if( aInfoType.EqualsAscii( "COORD" ) )
2293 : : { // address, lotus 1-2-3 formatted: $TABLE:$COL$ROW
2294 : : // Yes, passing tab as col is intentional!
2295 : 0 : rtl::OUStringBuffer aFuncResult;
2296 : 0 : rtl::OUString aCellStr;
2297 : 0 : ScAddress( static_cast<SCCOL>(aCellPos.Tab()), 0, 0 ).Format(
2298 [ # # ][ # # ]: 0 : aCellStr, (SCA_COL_ABSOLUTE|SCA_VALID_COL), NULL, pDok->GetAddressConvention() );
2299 [ # # ]: 0 : aFuncResult.append(aCellStr);
2300 [ # # ]: 0 : aFuncResult.append(sal_Unicode(':'));
2301 : : aCellPos.Format( aCellStr, (SCA_COL_ABSOLUTE|SCA_VALID_COL|SCA_ROW_ABSOLUTE|SCA_VALID_ROW),
2302 [ # # ][ # # ]: 0 : NULL, pDok->GetAddressConvention() );
2303 [ # # ]: 0 : aFuncResult.append(aCellStr);
2304 [ # # ][ # # ]: 0 : PushString( aFuncResult.makeStringAndClear() );
[ # # ][ # # ]
2305 : : }
2306 : :
2307 : : // *** CELL PROPERTIES ***
2308 [ + - ][ + + ]: 30 : else if( aInfoType.EqualsAscii( "CONTENTS" ) )
2309 : : { // contents of the cell, no formatting
2310 [ + - ][ + - ]: 6 : if( pCell && pCell->HasStringData() )
[ + + ][ + + ]
2311 : : {
2312 [ + - ]: 3 : String aStr;
2313 [ + - ]: 3 : GetCellString( aStr, pCell );
2314 [ + - ][ + - ]: 3 : PushString( aStr );
2315 : : }
2316 : : else
2317 [ + - ][ + - ]: 3 : PushDouble( GetCellValue( aCellPos, pCell ) );
2318 : : }
2319 [ + - ][ + + ]: 24 : else if( aInfoType.EqualsAscii( "TYPE" ) )
2320 : : { // b = blank; l = string (label); v = otherwise (value)
2321 : : sal_Unicode c;
2322 [ + - ][ + + ]: 18 : if( HasCellStringData( pCell ) )
2323 : 6 : c = 'l';
2324 : : else
2325 [ + - ][ + + ]: 12 : c = HasCellValueData( pCell ) ? 'v' : 'b';
2326 [ + - ][ + - ]: 18 : PushString( rtl::OUString(c) );
[ + - ]
2327 : : }
2328 [ + - ][ - + ]: 6 : else if( aInfoType.EqualsAscii( "WIDTH" ) )
2329 : : { // column width (rounded off as count of zero characters in standard font and size)
2330 [ # # ]: 0 : Printer* pPrinter = pDok->GetPrinter();
2331 [ # # ]: 0 : MapMode aOldMode( pPrinter->GetMapMode() );
2332 [ # # ]: 0 : Font aOldFont( pPrinter->GetFont() );
2333 [ # # ]: 0 : Font aDefFont;
2334 : :
2335 [ # # ][ # # ]: 0 : pPrinter->SetMapMode( MAP_TWIP );
[ # # ]
2336 : : // font color doesn't matter here
2337 [ # # ][ # # ]: 0 : pDok->GetDefPattern()->GetFont( aDefFont, SC_AUTOCOL_BLACK, pPrinter );
2338 [ # # ]: 0 : pPrinter->SetFont( aDefFont );
2339 [ # # ][ # # ]: 0 : long nZeroWidth = pPrinter->GetTextWidth( rtl::OUString( '0' ) );
[ # # ]
2340 [ # # ]: 0 : pPrinter->SetFont( aOldFont );
2341 [ # # ]: 0 : pPrinter->SetMapMode( aOldMode );
2342 [ # # ]: 0 : int nZeroCount = (int)(pDok->GetColWidth( aCellPos.Col(), aCellPos.Tab() ) / nZeroWidth);
2343 [ # # ][ # # ]: 0 : PushInt( nZeroCount );
[ # # ][ # # ]
2344 : : }
2345 [ + - ][ - + ]: 6 : else if( aInfoType.EqualsAscii( "PREFIX" ) )
2346 : : { // ' = left; " = right; ^ = centered
2347 : 0 : sal_Unicode c = 0;
2348 [ # # ][ # # ]: 0 : if( HasCellStringData( pCell ) )
2349 : : {
2350 : : const SvxHorJustifyItem* pJustAttr = (const SvxHorJustifyItem*)
2351 [ # # ]: 0 : pDok->GetAttr( aCellPos.Col(), aCellPos.Row(), aCellPos.Tab(), ATTR_HOR_JUSTIFY );
2352 [ # # # # : 0 : switch( pJustAttr->GetValue() )
# ]
2353 : : {
2354 : : case SVX_HOR_JUSTIFY_STANDARD:
2355 : : case SVX_HOR_JUSTIFY_LEFT:
2356 : 0 : case SVX_HOR_JUSTIFY_BLOCK: c = '\''; break;
2357 : 0 : case SVX_HOR_JUSTIFY_CENTER: c = '^'; break;
2358 : 0 : case SVX_HOR_JUSTIFY_RIGHT: c = '"'; break;
2359 : 0 : case SVX_HOR_JUSTIFY_REPEAT: c = '\\'; break;
2360 : : }
2361 : : }
2362 [ # # ][ # # ]: 0 : PushString( rtl::OUString(c) );
[ # # ]
2363 : : }
2364 [ + - ][ - + ]: 6 : else if( aInfoType.EqualsAscii( "PROTECT" ) )
2365 : : { // 1 = cell locked
2366 : : const ScProtectionAttr* pProtAttr = (const ScProtectionAttr*)
2367 [ # # ]: 0 : pDok->GetAttr( aCellPos.Col(), aCellPos.Row(), aCellPos.Tab(), ATTR_PROTECTION );
2368 [ # # ][ # # ]: 0 : PushInt( pProtAttr->GetProtection() ? 1 : 0 );
2369 : : }
2370 : :
2371 : : // *** FORMATTING ***
2372 [ + - ][ - + ]: 6 : else if( aInfoType.EqualsAscii( "FORMAT" ) )
2373 : : { // specific format code for standard formats
2374 [ # # ]: 0 : String aFuncResult;
2375 [ # # ]: 0 : sal_uLong nFormat = pDok->GetNumberFormat( aCellPos );
2376 [ # # ]: 0 : getFormatString(pFormatter, nFormat, aFuncResult);
2377 [ # # ][ # # ]: 0 : PushString( aFuncResult );
2378 : : }
2379 [ + - ][ + + ]: 6 : else if( aInfoType.EqualsAscii( "COLOR" ) )
2380 : : { // 1 = negative values are colored, otherwise 0
2381 [ + - ][ + - ]: 3 : const SvNumberformat* pFormat = pFormatter->GetEntry( pDok->GetNumberFormat( aCellPos ) );
2382 [ + - ][ - + ]: 3 : PushInt( lcl_FormatHasNegColor( pFormat ) ? 1 : 0 );
[ + - ]
2383 : : }
2384 [ + - ][ + - ]: 3 : else if( aInfoType.EqualsAscii( "PARENTHESES" ) )
2385 : : { // 1 = format string contains a '(' character, otherwise 0
2386 [ + - ][ + - ]: 3 : const SvNumberformat* pFormat = pFormatter->GetEntry( pDok->GetNumberFormat( aCellPos ) );
2387 [ + - ][ - + ]: 3 : PushInt( lcl_FormatHasOpenPar( pFormat ) ? 1 : 0 );
[ + - ]
2388 : : }
2389 : : else
2390 [ # # ]: 0 : PushIllegalArgument();
2391 [ + - ]: 57 : }
2392 : : }
2393 : : }
2394 : :
2395 : 0 : void ScInterpreter::ScCellExternal()
2396 : : {
2397 : : sal_uInt16 nFileId;
2398 [ # # ]: 0 : String aTabName;
2399 : : ScSingleRefData aRef;
2400 : 0 : ScExternalRefCache::TokenRef pToken;
2401 [ # # ]: 0 : ScExternalRefCache::CellFormat aFmt;
2402 [ # # ]: 0 : PopExternalSingleRef(nFileId, aTabName, aRef, pToken, &aFmt);
2403 [ # # ]: 0 : if (nGlobalError)
2404 : : {
2405 [ # # ]: 0 : PushIllegalParameter();
2406 : : return;
2407 : : }
2408 : :
2409 [ # # ][ # # ]: 0 : rtl::OUString aInfoType = GetString();
2410 [ # # ]: 0 : if (nGlobalError)
2411 : : {
2412 [ # # ]: 0 : PushIllegalParameter();
2413 : : return;
2414 : : }
2415 : :
2416 : : SCCOL nCol;
2417 : : SCROW nRow;
2418 : : SCTAB nTab;
2419 : 0 : aRef.nTab = 0; // external ref has a tab index of -1, which SingleRefToVars() don't like.
2420 [ # # ]: 0 : SingleRefToVars(aRef, nCol, nRow, nTab);
2421 [ # # ]: 0 : if (nGlobalError)
2422 : : {
2423 [ # # ]: 0 : PushIllegalParameter();
2424 : : return;
2425 : : }
2426 : 0 : aRef.nTab = -1; // revert the value.
2427 : :
2428 [ # # ][ # # ]: 0 : ScCellKeywordTranslator::transKeyword(aInfoType, ScGlobal::GetLocale(), ocCell);
2429 [ # # ]: 0 : ScExternalRefManager* pRefMgr = pDok->GetExternalRefManager();
2430 : :
2431 [ # # ]: 0 : if ( aInfoType == "COL" )
2432 [ # # ]: 0 : PushInt(nCol + 1);
2433 [ # # ]: 0 : else if ( aInfoType == "ROW" )
2434 [ # # ]: 0 : PushInt(nRow + 1);
2435 [ # # ]: 0 : else if ( aInfoType == "SHEET" )
2436 : : {
2437 : : // For SHEET, No idea what number we should set, but let's always set
2438 : : // 1 if the external sheet exists, no matter what sheet. Excel does
2439 : : // the same.
2440 [ # # ][ # # ]: 0 : if (pRefMgr->hasCacheTable(nFileId, aTabName))
[ # # ]
2441 [ # # ]: 0 : PushInt(1);
2442 : : else
2443 : 0 : SetError(errNoName);
2444 : : }
2445 [ # # ]: 0 : else if ( aInfoType == "ADDRESS" )
2446 : : {
2447 : : // ODF 1.2 says we need to always display address using the ODF A1 grammar.
2448 [ # # ]: 0 : ScTokenArray aArray;
2449 [ # # ]: 0 : aArray.AddExternalSingleReference(nFileId, aTabName, aRef);
2450 [ # # ]: 0 : ScCompiler aComp(pDok, aPos, aArray);
2451 [ # # ]: 0 : aComp.SetGrammar(formula::FormulaGrammar::GRAM_ODFF_A1);
2452 [ # # ]: 0 : String aStr;
2453 [ # # ]: 0 : aComp.CreateStringFromTokenArray(aStr);
2454 [ # # ][ # # ]: 0 : PushString(aStr);
[ # # ][ # # ]
2455 : : }
2456 [ # # ]: 0 : else if ( aInfoType == "FILENAME" )
2457 : : {
2458 : : // 'file URI'#$SheetName
2459 : :
2460 [ # # ]: 0 : const rtl::OUString* p = pRefMgr->getExternalFileName(nFileId);
2461 [ # # ]: 0 : if (!p)
2462 : : {
2463 : : // In theory this should never happen...
2464 : 0 : SetError(errNoName);
2465 : : return;
2466 : : }
2467 : :
2468 : 0 : rtl::OUStringBuffer aBuf;
2469 [ # # ]: 0 : aBuf.append(sal_Unicode('\''));
2470 [ # # ]: 0 : aBuf.append(*p);
2471 [ # # ]: 0 : aBuf.appendAscii("'#$");
2472 [ # # ][ # # ]: 0 : aBuf.append(aTabName);
2473 [ # # ][ # # ]: 0 : PushString(aBuf.makeStringAndClear());
[ # # ][ # # ]
2474 : : }
2475 [ # # ]: 0 : else if ( aInfoType == "CONTENTS" )
2476 : : {
2477 [ # # # # ]: 0 : switch (pToken->GetType())
2478 : : {
2479 : : case svString:
2480 [ # # ][ # # ]: 0 : PushString(pToken->GetString());
2481 : 0 : break;
2482 : : case svDouble:
2483 [ # # ][ # # ]: 0 : PushString(rtl::OUString::valueOf(pToken->GetDouble()));
[ # # ][ # # ]
2484 : 0 : break;
2485 : : case svError:
2486 [ # # ][ # # ]: 0 : PushString(ScGlobal::GetErrorString(pToken->GetError()));
[ # # ][ # # ]
2487 : 0 : break;
2488 : : default:
2489 [ # # ][ # # ]: 0 : PushString(ScGlobal::GetEmptyString());
2490 : : }
2491 : : }
2492 [ # # ]: 0 : else if ( aInfoType == "TYPE" )
2493 : : {
2494 : 0 : sal_Unicode c = 'v';
2495 [ # # # ]: 0 : switch (pToken->GetType())
2496 : : {
2497 : : case svString:
2498 : 0 : c = 'l';
2499 : 0 : break;
2500 : : case svEmptyCell:
2501 : 0 : c = 'b';
2502 : 0 : break;
2503 : : default:
2504 : : ;
2505 : : }
2506 [ # # ][ # # ]: 0 : PushString(rtl::OUString(c));
[ # # ]
2507 : : }
2508 [ # # ]: 0 : else if ( aInfoType == "FORMAT" )
2509 : : {
2510 [ # # ]: 0 : String aFmtStr;
2511 [ # # ]: 0 : sal_uLong nFmt = aFmt.mbIsSet ? aFmt.mnIndex : 0;
2512 [ # # ]: 0 : getFormatString(pFormatter, nFmt, aFmtStr);
2513 [ # # ][ # # ]: 0 : PushString(aFmtStr);
2514 : : }
2515 [ # # ]: 0 : else if ( aInfoType == "COLOR" )
2516 : : {
2517 : : // 1 = negative values are colored, otherwise 0
2518 : 0 : int nVal = 0;
2519 [ # # ]: 0 : if (aFmt.mbIsSet)
2520 : : {
2521 [ # # ]: 0 : const SvNumberformat* pFormat = pFormatter->GetEntry(aFmt.mnIndex);
2522 [ # # ][ # # ]: 0 : nVal = lcl_FormatHasNegColor(pFormat) ? 1 : 0;
2523 : : }
2524 [ # # ]: 0 : PushInt(nVal);
2525 : : }
2526 [ # # ]: 0 : else if ( aInfoType == "PARENTHESES" )
2527 : : {
2528 : : // 1 = format string contains a '(' character, otherwise 0
2529 : 0 : int nVal = 0;
2530 [ # # ]: 0 : if (aFmt.mbIsSet)
2531 : : {
2532 [ # # ]: 0 : const SvNumberformat* pFormat = pFormatter->GetEntry(aFmt.mnIndex);
2533 [ # # ][ # # ]: 0 : nVal = lcl_FormatHasOpenPar(pFormat) ? 1 : 0;
2534 : : }
2535 [ # # ]: 0 : PushInt(nVal);
2536 : : }
2537 : : else
2538 [ # # ][ # # ]: 0 : PushIllegalParameter();
[ # # ][ # # ]
[ # # ][ # # ]
2539 : : }
2540 : :
2541 : 24 : void ScInterpreter::ScIsRef()
2542 : : {
2543 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScCell" );
2544 : 24 : nFuncFmtType = NUMBERFORMAT_LOGICAL;
2545 : 24 : short nRes = 0;
2546 [ + + - + ]: 24 : switch ( GetStackType() )
2547 : : {
2548 : : case svSingleRef :
2549 : : {
2550 : 3 : ScAddress aAdr;
2551 [ + - ]: 3 : PopSingleRef( aAdr );
2552 [ + - ]: 3 : if ( !nGlobalError )
2553 : 3 : nRes = 1;
2554 : : }
2555 : 3 : break;
2556 : : case svDoubleRef :
2557 : : {
2558 : 9 : ScRange aRange;
2559 [ + - ]: 9 : PopDoubleRef( aRange );
2560 [ + - ]: 9 : if ( !nGlobalError )
2561 : 9 : nRes = 1;
2562 : : }
2563 : 9 : break;
2564 : : case svRefList :
2565 : : {
2566 [ # # ]: 0 : FormulaTokenRef x = PopToken();
2567 [ # # ]: 0 : if ( !nGlobalError )
2568 [ # # ][ # # ]: 0 : nRes = !static_cast<ScToken*>(x.get())->GetRefList()->empty();
2569 : : }
2570 : 0 : break;
2571 : : default:
2572 : 12 : Pop();
2573 : : }
2574 : 24 : nGlobalError = 0;
2575 : 24 : PushInt( nRes );
2576 : 24 : }
2577 : :
2578 : :
2579 : 15 : void ScInterpreter::ScIsValue()
2580 : : {
2581 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScIsValue" );
2582 : 15 : nFuncFmtType = NUMBERFORMAT_LOGICAL;
2583 : 15 : short nRes = 0;
2584 [ - + - - ]: 15 : switch ( GetRawStackType() )
2585 : : {
2586 : : case svDouble:
2587 : 0 : Pop();
2588 : 0 : nRes = 1;
2589 : 0 : break;
2590 : : case svDoubleRef :
2591 : : case svSingleRef :
2592 : : {
2593 : 15 : ScAddress aAdr;
2594 [ + - ][ + - ]: 15 : if ( !PopDoubleRefOrSingleRef( aAdr ) )
2595 : : break;
2596 [ + - ]: 15 : ScBaseCell* pCell = GetCell( aAdr );
2597 [ + - ][ + - ]: 15 : if (GetCellErrCode( pCell ) == 0)
2598 : : {
2599 [ - + - ]: 15 : switch ( GetCellType( pCell ) )
2600 : : {
2601 : : case CELLTYPE_VALUE :
2602 : 0 : nRes = 1;
2603 : 0 : break;
2604 : : case CELLTYPE_FORMULA :
2605 [ + - ][ + - ]: 15 : nRes = ((ScFormulaCell*)pCell)->IsValue() &&
2606 [ + + ][ + - ]: 15 : !((ScFormulaCell*)pCell)->IsEmpty();
[ + - ][ + - ]
2607 : 15 : break;
2608 : : default:
2609 : : ; // nothing
2610 : : }
2611 : : }
2612 : : }
2613 : 15 : break;
2614 : : case svMatrix:
2615 : : {
2616 [ # # ]: 0 : ScMatrixRef pMat = PopMatrix();
2617 [ # # ]: 0 : if ( !pMat )
2618 : : ; // nothing
2619 [ # # ]: 0 : else if ( !pJumpMatrix )
2620 : : {
2621 [ # # ][ # # ]: 0 : if (pMat->GetErrorIfNotString( 0, 0) == 0)
2622 [ # # ]: 0 : nRes = pMat->IsValue( 0, 0);
2623 : : }
2624 : : else
2625 : : {
2626 : : SCSIZE nCols, nRows, nC, nR;
2627 [ # # ]: 0 : pMat->GetDimensions( nCols, nRows);
2628 : 0 : pJumpMatrix->GetPos( nC, nR);
2629 [ # # ][ # # ]: 0 : if ( nC < nCols && nR < nRows )
2630 [ # # ][ # # ]: 0 : if (pMat->GetErrorIfNotString( nC, nR) == 0)
2631 [ # # ]: 0 : nRes = pMat->IsValue( nC, nR);
2632 [ # # ]: 0 : }
2633 : : }
2634 : 0 : break;
2635 : : default:
2636 : 0 : Pop();
2637 : : }
2638 : 15 : nGlobalError = 0;
2639 : 15 : PushInt( nRes );
2640 : 15 : }
2641 : :
2642 : :
2643 : 9 : void ScInterpreter::ScIsFormula()
2644 : : {
2645 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScIsFormula" );
2646 : 9 : nFuncFmtType = NUMBERFORMAT_LOGICAL;
2647 : 9 : short nRes = 0;
2648 [ + - ]: 9 : switch ( GetStackType() )
2649 : : {
2650 : : case svDoubleRef :
2651 : : case svSingleRef :
2652 : : {
2653 : 9 : ScAddress aAdr;
2654 [ + - ][ + - ]: 9 : if ( !PopDoubleRefOrSingleRef( aAdr ) )
2655 : : break;
2656 [ + - ]: 9 : nRes = (GetCellType( GetCell( aAdr ) ) == CELLTYPE_FORMULA);
2657 : : }
2658 : 9 : break;
2659 : : default:
2660 : 0 : Pop();
2661 : : }
2662 : 9 : nGlobalError = 0;
2663 : 9 : PushInt( nRes );
2664 : 9 : }
2665 : :
2666 : :
2667 : 18 : void ScInterpreter::ScFormula()
2668 : : {
2669 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScFormula" );
2670 : 18 : rtl::OUString aFormula;
2671 [ + - ][ + - ]: 18 : switch ( GetStackType() )
2672 : : {
2673 : : case svDoubleRef :
2674 : : case svSingleRef :
2675 : : {
2676 : 18 : ScAddress aAdr;
2677 [ + - ][ + - ]: 18 : if ( !PopDoubleRefOrSingleRef( aAdr ) )
2678 : : break;
2679 [ + - ]: 18 : ScBaseCell* pCell = GetCell( aAdr );
2680 [ + - ]: 18 : switch ( GetCellType( pCell ) )
2681 : : {
2682 : : case CELLTYPE_FORMULA :
2683 [ + - ][ + - ]: 18 : ((ScFormulaCell*)pCell)->GetFormula( aFormula );
2684 : 18 : break;
2685 : : default:
2686 : 0 : SetError( NOTAVAILABLE );
2687 : : }
2688 : : }
2689 : 18 : break;
2690 : : default:
2691 [ # # ]: 0 : Pop();
2692 : 0 : SetError( NOTAVAILABLE );
2693 : : }
2694 [ + - ][ + - ]: 18 : PushString( aFormula );
[ + - ]
2695 : 18 : }
2696 : :
2697 : :
2698 : :
2699 : 18 : void ScInterpreter::ScIsNV()
2700 : : {
2701 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScIsNV" );
2702 : 18 : nFuncFmtType = NUMBERFORMAT_LOGICAL;
2703 : 18 : short nRes = 0;
2704 [ + - + ]: 18 : switch ( GetStackType() )
2705 : : {
2706 : : case svDoubleRef :
2707 : : case svSingleRef :
2708 : : {
2709 : 12 : ScAddress aAdr;
2710 [ + - ]: 12 : PopDoubleRefOrSingleRef( aAdr );
2711 [ - + ]: 12 : if ( nGlobalError == NOTAVAILABLE )
2712 : 0 : nRes = 1;
2713 : : else
2714 : : {
2715 [ + - ]: 12 : ScBaseCell* pCell = GetCell( aAdr );
2716 [ + - ]: 12 : sal_uInt16 nErr = GetCellErrCode( pCell );
2717 : 12 : nRes = (nErr == NOTAVAILABLE);
2718 : : }
2719 : : }
2720 : 12 : break;
2721 : : case svMatrix:
2722 : : {
2723 [ # # ]: 0 : ScMatrixRef pMat = PopMatrix();
2724 [ # # ]: 0 : if ( !pMat )
2725 : : ; // nothing
2726 [ # # ]: 0 : else if ( !pJumpMatrix )
2727 [ # # ]: 0 : nRes = (pMat->GetErrorIfNotString( 0, 0) == NOTAVAILABLE);
2728 : : else
2729 : : {
2730 : : SCSIZE nCols, nRows, nC, nR;
2731 [ # # ]: 0 : pMat->GetDimensions( nCols, nRows);
2732 : 0 : pJumpMatrix->GetPos( nC, nR);
2733 [ # # ][ # # ]: 0 : if ( nC < nCols && nR < nRows )
2734 [ # # ]: 0 : nRes = (pMat->GetErrorIfNotString( nC, nR) == NOTAVAILABLE);
2735 [ # # ]: 0 : }
2736 : : }
2737 : 0 : break;
2738 : : default:
2739 : 6 : PopError();
2740 [ + + ]: 6 : if ( nGlobalError == NOTAVAILABLE )
2741 : 3 : nRes = 1;
2742 : : }
2743 : 18 : nGlobalError = 0;
2744 : 18 : PushInt( nRes );
2745 : 18 : }
2746 : :
2747 : :
2748 : 12 : void ScInterpreter::ScIsErr()
2749 : : {
2750 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScIsErr" );
2751 : 12 : nFuncFmtType = NUMBERFORMAT_LOGICAL;
2752 : 12 : short nRes = 0;
2753 [ + - + ]: 12 : switch ( GetStackType() )
2754 : : {
2755 : : case svDoubleRef :
2756 : : case svSingleRef :
2757 : : {
2758 : 6 : ScAddress aAdr;
2759 [ + - ]: 6 : PopDoubleRefOrSingleRef( aAdr );
2760 [ - + ][ # # ]: 6 : if ( nGlobalError && nGlobalError != NOTAVAILABLE )
2761 : 0 : nRes = 1;
2762 : : else
2763 : : {
2764 [ + - ]: 6 : ScBaseCell* pCell = GetCell( aAdr );
2765 [ + - ]: 6 : sal_uInt16 nErr = GetCellErrCode( pCell );
2766 [ + + ][ + - ]: 6 : nRes = (nErr && nErr != NOTAVAILABLE);
2767 : : }
2768 : : }
2769 : 6 : break;
2770 : : case svMatrix:
2771 : : {
2772 [ # # ]: 0 : ScMatrixRef pMat = PopMatrix();
2773 [ # # ][ # # ]: 0 : if ( nGlobalError || !pMat )
[ # # ]
2774 [ # # ][ # # ]: 0 : nRes = ((nGlobalError && nGlobalError != NOTAVAILABLE) || !pMat);
[ # # ]
2775 [ # # ]: 0 : else if ( !pJumpMatrix )
2776 : : {
2777 [ # # ]: 0 : sal_uInt16 nErr = pMat->GetErrorIfNotString( 0, 0);
2778 [ # # ][ # # ]: 0 : nRes = (nErr && nErr != NOTAVAILABLE);
2779 : : }
2780 : : else
2781 : : {
2782 : : SCSIZE nCols, nRows, nC, nR;
2783 [ # # ]: 0 : pMat->GetDimensions( nCols, nRows);
2784 : 0 : pJumpMatrix->GetPos( nC, nR);
2785 [ # # ][ # # ]: 0 : if ( nC < nCols && nR < nRows )
2786 : : {
2787 [ # # ]: 0 : sal_uInt16 nErr = pMat->GetErrorIfNotString( nC, nR);
2788 [ # # ][ # # ]: 0 : nRes = (nErr && nErr != NOTAVAILABLE);
2789 : : }
2790 [ # # ]: 0 : }
2791 : : }
2792 : 0 : break;
2793 : : default:
2794 : 6 : PopError();
2795 [ + + ][ + - ]: 6 : if ( nGlobalError && nGlobalError != NOTAVAILABLE )
2796 : 3 : nRes = 1;
2797 : : }
2798 : 12 : nGlobalError = 0;
2799 : 12 : PushInt( nRes );
2800 : 12 : }
2801 : :
2802 : :
2803 : 18 : void ScInterpreter::ScIsError()
2804 : : {
2805 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScIsError" );
2806 : 18 : nFuncFmtType = NUMBERFORMAT_LOGICAL;
2807 : 18 : short nRes = 0;
2808 [ + - + ]: 18 : switch ( GetStackType() )
2809 : : {
2810 : : case svDoubleRef :
2811 : : case svSingleRef :
2812 : : {
2813 : 12 : ScAddress aAdr;
2814 [ - + ][ + - ]: 12 : if ( !PopDoubleRefOrSingleRef( aAdr ) )
2815 : : {
2816 : 0 : nRes = 1;
2817 : : break;
2818 : : }
2819 [ - + ]: 12 : if ( nGlobalError )
2820 : 0 : nRes = 1;
2821 : : else
2822 : : {
2823 [ + - ]: 12 : ScBaseCell* pCell = GetCell( aAdr );
2824 [ + - ]: 12 : nRes = (GetCellErrCode( pCell ) != 0);
2825 : : }
2826 : : }
2827 : 12 : break;
2828 : : case svMatrix:
2829 : : {
2830 [ # # ]: 0 : ScMatrixRef pMat = PopMatrix();
2831 [ # # ][ # # ]: 0 : if ( nGlobalError || !pMat )
[ # # ]
2832 : 0 : nRes = 1;
2833 [ # # ]: 0 : else if ( !pJumpMatrix )
2834 [ # # ]: 0 : nRes = (pMat->GetErrorIfNotString( 0, 0) != 0);
2835 : : else
2836 : : {
2837 : : SCSIZE nCols, nRows, nC, nR;
2838 [ # # ]: 0 : pMat->GetDimensions( nCols, nRows);
2839 : 0 : pJumpMatrix->GetPos( nC, nR);
2840 [ # # ][ # # ]: 0 : if ( nC < nCols && nR < nRows )
2841 [ # # ]: 0 : nRes = (pMat->GetErrorIfNotString( nC, nR) != 0);
2842 [ # # ]: 0 : }
2843 : : }
2844 : 0 : break;
2845 : : default:
2846 : 6 : PopError();
2847 [ + - ]: 6 : if ( nGlobalError )
2848 : 6 : nRes = 1;
2849 : : }
2850 : 18 : nGlobalError = 0;
2851 : 18 : PushInt( nRes );
2852 : 18 : }
2853 : :
2854 : :
2855 : 27 : short ScInterpreter::IsEven()
2856 : : {
2857 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::IsEven" );
2858 : 27 : nFuncFmtType = NUMBERFORMAT_LOGICAL;
2859 : 27 : short nRes = 0;
2860 : 27 : double fVal = 0.0;
2861 [ - + - - ]: 27 : switch ( GetStackType() )
2862 : : {
2863 : : case svDoubleRef :
2864 : : case svSingleRef :
2865 : : {
2866 : 0 : ScAddress aAdr;
2867 [ # # ][ # # ]: 0 : if ( !PopDoubleRefOrSingleRef( aAdr ) )
2868 : : break;
2869 [ # # ]: 0 : ScBaseCell* pCell = GetCell( aAdr );
2870 [ # # ]: 0 : sal_uInt16 nErr = GetCellErrCode( pCell );
2871 [ # # ]: 0 : if (nErr != 0)
2872 : 0 : SetError(nErr);
2873 : : else
2874 : : {
2875 [ # # # ]: 0 : switch ( GetCellType( pCell ) )
2876 : : {
2877 : : case CELLTYPE_VALUE :
2878 [ # # ]: 0 : fVal = GetCellValue( aAdr, pCell );
2879 : 0 : nRes = 1;
2880 : 0 : break;
2881 : : case CELLTYPE_FORMULA :
2882 [ # # ][ # # ]: 0 : if( ((ScFormulaCell*)pCell)->IsValue() )
[ # # ]
2883 : : {
2884 [ # # ]: 0 : fVal = GetCellValue( aAdr, pCell );
2885 : 0 : nRes = 1;
2886 : : }
2887 : 0 : break;
2888 : : default:
2889 : : ; // nothing
2890 : : }
2891 : : }
2892 : : }
2893 : 0 : break;
2894 : : case svDouble:
2895 : : {
2896 : 27 : fVal = PopDouble();
2897 : 27 : nRes = 1;
2898 : : }
2899 : 27 : break;
2900 : : case svMatrix:
2901 : : {
2902 [ # # ]: 0 : ScMatrixRef pMat = PopMatrix();
2903 [ # # ]: 0 : if ( !pMat )
2904 : : ; // nothing
2905 [ # # ]: 0 : else if ( !pJumpMatrix )
2906 : : {
2907 [ # # ]: 0 : nRes = pMat->IsValue( 0, 0);
2908 [ # # ]: 0 : if ( nRes )
2909 [ # # ]: 0 : fVal = pMat->GetDouble( 0, 0);
2910 : : }
2911 : : else
2912 : : {
2913 : : SCSIZE nCols, nRows, nC, nR;
2914 [ # # ]: 0 : pMat->GetDimensions( nCols, nRows);
2915 : 0 : pJumpMatrix->GetPos( nC, nR);
2916 [ # # ][ # # ]: 0 : if ( nC < nCols && nR < nRows )
2917 : : {
2918 [ # # ]: 0 : nRes = pMat->IsValue( nC, nR);
2919 [ # # ]: 0 : if ( nRes )
2920 [ # # ]: 0 : fVal = pMat->GetDouble( nC, nR);
2921 : : }
2922 : : else
2923 : 0 : SetError( errNoValue);
2924 [ # # ]: 0 : }
2925 : : }
2926 : 0 : break;
2927 : : default:
2928 : : ; // nothing
2929 : : }
2930 [ - + ]: 27 : if ( !nRes )
2931 : 0 : SetError( errIllegalParameter);
2932 : : else
2933 : 27 : nRes = ( fmod( ::rtl::math::approxFloor( fabs( fVal ) ), 2.0 ) < 0.5 );
2934 : 27 : return nRes;
2935 : : }
2936 : :
2937 : :
2938 : 12 : void ScInterpreter::ScIsEven()
2939 : : {
2940 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScIsEven" );
2941 : 12 : PushInt( IsEven() );
2942 : 12 : }
2943 : :
2944 : :
2945 : 15 : void ScInterpreter::ScIsOdd()
2946 : : {
2947 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScIsOdd" );
2948 : 15 : PushInt( !IsEven() );
2949 : 15 : }
2950 : :
2951 : 180 : void ScInterpreter::ScN()
2952 : : {
2953 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScN" );
2954 : 180 : sal_uInt16 nErr = nGlobalError;
2955 : 180 : nGlobalError = 0;
2956 : : // Temporarily override the ConvertStringToValue() error for
2957 : : // GetCellValue() / GetCellValueOrZero()
2958 : 180 : sal_uInt16 nSErr = mnStringNoValueError;
2959 : 180 : mnStringNoValueError = errCellNoValue;
2960 : 180 : double fVal = GetDouble();
2961 : 180 : mnStringNoValueError = nSErr;
2962 [ - + ]: 180 : if (nErr)
2963 : 0 : nGlobalError = nErr; // preserve previous error if any
2964 [ + + ]: 180 : else if (nGlobalError == errCellNoValue)
2965 : 30 : nGlobalError = 0; // reset temporary detection error
2966 : 180 : PushDouble(fVal);
2967 : 180 : }
2968 : :
2969 : 0 : void ScInterpreter::ScTrim()
2970 : : {
2971 : : // Doesn't only trim but also removes duplicated blanks within!
2972 [ # # ][ # # ]: 0 : String aVal = comphelper::string::strip(GetString(), ' ');
[ # # ][ # # ]
2973 [ # # ]: 0 : String aStr;
2974 : 0 : register const sal_Unicode* p = aVal.GetBuffer();
2975 : 0 : register const sal_Unicode* const pEnd = p + aVal.Len();
2976 [ # # ]: 0 : while ( p < pEnd )
2977 : : {
2978 [ # # ][ # # ]: 0 : if ( *p != ' ' || p[-1] != ' ' ) // first can't be ' ', so -1 is fine
2979 [ # # ]: 0 : aStr += *p;
2980 : 0 : p++;
2981 : : }
2982 [ # # ][ # # ]: 0 : PushString( aStr );
[ # # ]
2983 : 0 : }
2984 : :
2985 : :
2986 : 0 : void ScInterpreter::ScUpper()
2987 : : {
2988 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScTrim" );
2989 [ # # ][ # # ]: 0 : String aString = ScGlobal::pCharClass->uppercase(GetString());
[ # # ][ # # ]
2990 [ # # ][ # # ]: 0 : PushString(aString);
2991 : 0 : }
2992 : :
2993 : :
2994 : 0 : void ScInterpreter::ScPropper()
2995 : : {
2996 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScPropper" );
2997 : : //2do: what to do with I18N-CJK ?!?
2998 [ # # ][ # # ]: 0 : String aStr( GetString() );
2999 : 0 : const xub_StrLen nLen = aStr.Len();
3000 : : // #i82487# don't try to write to empty string's BufferAccess
3001 : : // (would crash now that the empty string is const)
3002 [ # # ]: 0 : if ( nLen > 0 )
3003 : : {
3004 [ # # ][ # # ]: 0 : String aUpr( ScGlobal::pCharClass->uppercase( aStr ) );
[ # # ]
3005 [ # # ][ # # ]: 0 : String aLwr( ScGlobal::pCharClass->lowercase( aStr ) );
[ # # ]
3006 [ # # ]: 0 : register sal_Unicode* pStr = aStr.GetBufferAccess();
3007 : 0 : const sal_Unicode* pUpr = aUpr.GetBuffer();
3008 : 0 : const sal_Unicode* pLwr = aLwr.GetBuffer();
3009 : 0 : *pStr = *pUpr;
3010 : 0 : xub_StrLen nPos = 1;
3011 [ # # ]: 0 : while( nPos < nLen )
3012 : : {
3013 : 0 : rtl::OUString aTmpStr( pStr[nPos-1] );
3014 [ # # ][ # # ]: 0 : if ( !ScGlobal::pCharClass->isLetter( aTmpStr, 0 ) )
[ # # ][ # # ]
3015 : 0 : pStr[nPos] = pUpr[nPos];
3016 : : else
3017 : 0 : pStr[nPos] = pLwr[nPos];
3018 : 0 : nPos++;
3019 : 0 : }
3020 [ # # ][ # # ]: 0 : aStr.ReleaseBufferAccess( nLen );
[ # # ]
3021 : : }
3022 [ # # ][ # # ]: 0 : PushString( aStr );
3023 : 0 : }
3024 : :
3025 : :
3026 : 0 : void ScInterpreter::ScLower()
3027 : : {
3028 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScLower" );
3029 [ # # ][ # # ]: 0 : String aString = ScGlobal::pCharClass->lowercase(GetString());
[ # # ][ # # ]
3030 [ # # ][ # # ]: 0 : PushString(aString);
3031 : 0 : }
3032 : :
3033 : :
3034 : 0 : void ScInterpreter::ScLen()
3035 : : {
3036 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScLen" );
3037 [ # # ][ # # ]: 0 : String aStr( GetString() );
3038 [ # # ][ # # ]: 0 : PushDouble( aStr.Len() );
3039 : 0 : }
3040 : :
3041 : :
3042 : 9 : void ScInterpreter::ScT()
3043 : : {
3044 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScT" );
3045 [ - + - - : 9 : switch ( GetStackType() )
- ]
3046 : : {
3047 : : case svDoubleRef :
3048 : : case svSingleRef :
3049 : : {
3050 : 0 : ScAddress aAdr;
3051 [ # # ][ # # ]: 0 : if ( !PopDoubleRefOrSingleRef( aAdr ) )
3052 : : {
3053 [ # # ]: 0 : PushInt(0);
3054 : 9 : return ;
3055 : : }
3056 : 0 : bool bValue = false;
3057 [ # # ]: 0 : ScBaseCell* pCell = GetCell( aAdr );
3058 [ # # ][ # # ]: 0 : if ( GetCellErrCode( pCell ) == 0 )
3059 : : {
3060 [ # # # ]: 0 : switch ( GetCellType( pCell ) )
3061 : : {
3062 : : case CELLTYPE_VALUE :
3063 : 0 : bValue = true;
3064 : 0 : break;
3065 : : case CELLTYPE_FORMULA :
3066 [ # # ][ # # ]: 0 : bValue = ((ScFormulaCell*)pCell)->IsValue();
3067 : 0 : break;
3068 : : default:
3069 : : ; // nothing
3070 : : }
3071 : : }
3072 [ # # ]: 0 : if ( bValue )
3073 [ # # ][ # # ]: 0 : PushString( EMPTY_STRING );
3074 : : else
3075 : : {
3076 : : // like GetString()
3077 [ # # ]: 0 : GetCellString( aTempStr, pCell );
3078 [ # # ]: 0 : PushString( aTempStr );
3079 : : }
3080 : : }
3081 : 0 : break;
3082 : : case svMatrix:
3083 : : case svExternalSingleRef:
3084 : : case svExternalDoubleRef:
3085 : : {
3086 : : double fVal;
3087 [ + - ]: 9 : String aStr;
3088 [ + - ]: 9 : ScMatValType nMatValType = GetDoubleOrStringFromMatrix( fVal, aStr);
3089 [ + + ]: 9 : if (ScMatrix::IsValueType( nMatValType))
3090 [ + - ][ + - ]: 3 : PushString( EMPTY_STRING);
3091 : : else
3092 [ + - ][ + - ]: 9 : PushString( aStr);
3093 : : }
3094 : 9 : break;
3095 : : case svDouble :
3096 : : {
3097 : 0 : PopError();
3098 : 0 : PushString( EMPTY_STRING );
3099 : : }
3100 : 0 : break;
3101 : : case svString :
3102 : : ; // leave on stack
3103 : 0 : break;
3104 : : default :
3105 : 0 : PushError( errUnknownOpCode);
3106 : : }
3107 : : }
3108 : :
3109 : :
3110 : 0 : void ScInterpreter::ScValue()
3111 : : {
3112 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScValue" );
3113 [ # # ]: 0 : String aInputString;
3114 : : double fVal;
3115 : :
3116 [ # # ][ # # : 0 : switch ( GetRawStackType() )
# # # ]
3117 : : {
3118 : : case svMissing:
3119 : : case svEmptyCell:
3120 [ # # ]: 0 : Pop();
3121 [ # # ]: 0 : PushInt(0);
3122 : : return;
3123 : : case svDouble:
3124 : : return; // leave on stack
3125 : : //break;
3126 : :
3127 : : case svSingleRef:
3128 : : case svDoubleRef:
3129 : : {
3130 : 0 : ScAddress aAdr;
3131 [ # # ][ # # ]: 0 : if ( !PopDoubleRefOrSingleRef( aAdr ) )
3132 : : {
3133 [ # # ]: 0 : PushInt(0);
3134 : : return;
3135 : : }
3136 [ # # ]: 0 : ScBaseCell* pCell = GetCell( aAdr );
3137 [ # # ][ # # ]: 0 : if ( pCell && pCell->HasStringData() )
[ # # ][ # # ]
3138 [ # # ]: 0 : GetCellString( aInputString, pCell );
3139 [ # # ][ # # ]: 0 : else if ( pCell && pCell->HasValueData() )
[ # # ][ # # ]
3140 : : {
3141 [ # # ][ # # ]: 0 : PushDouble( GetCellValue(aAdr, pCell) );
3142 : : return;
3143 : : }
3144 : : else
3145 : : {
3146 [ # # ]: 0 : PushDouble(0.0);
3147 : : return;
3148 : : }
3149 : : }
3150 : 0 : break;
3151 : : case svMatrix:
3152 : : {
3153 : : ScMatValType nType = GetDoubleOrStringFromMatrix( fVal,
3154 [ # # ]: 0 : aInputString);
3155 [ # # # # ]: 0 : switch (nType)
3156 : : {
3157 : : case SC_MATVAL_EMPTY:
3158 : 0 : fVal = 0.0;
3159 : : // fallthru
3160 : : case SC_MATVAL_VALUE:
3161 : : case SC_MATVAL_BOOLEAN:
3162 [ # # ]: 0 : PushDouble( fVal);
3163 : : return;
3164 : : //break;
3165 : : case SC_MATVAL_STRING:
3166 : : // evaluated below
3167 : 0 : break;
3168 : : default:
3169 [ # # ]: 0 : PushIllegalArgument();
3170 : : }
3171 : : }
3172 : 0 : break;
3173 : : default:
3174 [ # # ][ # # ]: 0 : aInputString = GetString();
3175 : 0 : break;
3176 : : }
3177 : :
3178 : 0 : sal_uInt32 nFIndex = 0; // 0 for default locale
3179 [ # # ][ # # ]: 0 : if (pFormatter->IsNumberFormat(aInputString, nFIndex, fVal))
3180 [ # # ]: 0 : PushDouble(fVal);
3181 : : else
3182 [ # # ][ # # ]: 0 : PushIllegalArgument();
[ # # ]
3183 : : }
3184 : :
3185 : :
3186 : : //2do: this should be a proper unicode string method
3187 : 0 : inline bool lcl_ScInterpreter_IsPrintable( sal_Unicode c )
3188 : : {
3189 [ # # ][ # # ]: 0 : return 0x20 <= c && c != 0x7f;
3190 : : }
3191 : :
3192 : 0 : void ScInterpreter::ScClean()
3193 : : {
3194 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScClean" );
3195 [ # # ][ # # ]: 0 : String aStr( GetString() );
3196 [ # # ]: 0 : for ( xub_StrLen i = 0; i < aStr.Len(); i++ )
3197 : : {
3198 [ # # ]: 0 : if ( !lcl_ScInterpreter_IsPrintable( aStr.GetChar( i ) ) )
3199 [ # # ]: 0 : aStr.Erase(i,1);
3200 : : }
3201 [ # # ][ # # ]: 0 : PushString(aStr);
3202 : 0 : }
3203 : :
3204 : :
3205 : 0 : void ScInterpreter::ScCode()
3206 : : {
3207 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScCode" );
3208 : : //2do: make it full range unicode?
3209 : 0 : const String& rStr = GetString();
3210 : : //"classic" ByteString conversion flags
3211 : : const sal_uInt32 convertFlags =
3212 : : RTL_UNICODETOTEXT_FLAGS_NONSPACING_IGNORE |
3213 : : RTL_UNICODETOTEXT_FLAGS_CONTROL_IGNORE |
3214 : : RTL_UNICODETOTEXT_FLAGS_FLUSH |
3215 : : RTL_UNICODETOTEXT_FLAGS_UNDEFINED_DEFAULT |
3216 : : RTL_UNICODETOTEXT_FLAGS_INVALID_DEFAULT |
3217 : 0 : RTL_UNICODETOTEXT_FLAGS_UNDEFINED_REPLACE;
3218 [ # # ][ # # ]: 0 : PushInt( (sal_uChar) rtl::OUStringToOString(rtl::OUString(rStr.GetChar(0)), osl_getThreadTextEncoding(), convertFlags).toChar() );
3219 : 0 : }
3220 : :
3221 : :
3222 : 0 : void ScInterpreter::ScChar()
3223 : : {
3224 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScChar" );
3225 : : //2do: make it full range unicode?
3226 : 0 : double fVal = GetDouble();
3227 [ # # ][ # # ]: 0 : if (fVal < 0.0 || fVal >= 256.0)
3228 : 0 : PushIllegalArgument();
3229 : : else
3230 : : {
3231 : : //"classic" ByteString conversion flags
3232 : : const sal_uInt32 convertFlags =
3233 : : RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_DEFAULT |
3234 : : RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_DEFAULT |
3235 : 0 : RTL_TEXTTOUNICODE_FLAGS_INVALID_DEFAULT;
3236 : :
3237 : 0 : sal_Char cEncodedChar = static_cast<sal_Char>(fVal);
3238 [ # # ][ # # ]: 0 : rtl::OUString aStr(&cEncodedChar, 1, osl_getThreadTextEncoding(), convertFlags);
3239 [ # # ][ # # ]: 0 : PushString(aStr);
[ # # ]
3240 : : }
3241 : 0 : }
3242 : :
3243 : :
3244 : : /* #i70213# fullwidth/halfwidth conversion provided by
3245 : : * Takashi Nakamoto <bluedwarf@ooo>
3246 : : * erAck: added Excel compatibility conversions as seen in issue's test case. */
3247 : :
3248 : 0 : static ::rtl::OUString lcl_convertIntoHalfWidth( const ::rtl::OUString & rStr )
3249 : : {
3250 : : static bool bFirstASCCall = true;
3251 [ # # ][ # # ]: 0 : static utl::TransliterationWrapper aTrans( ::comphelper::getProcessServiceFactory(), 0 );
[ # # ][ # # ]
[ # # ]
3252 : :
3253 [ # # ]: 0 : if( bFirstASCCall )
3254 : : {
3255 [ # # ][ # # ]: 0 : aTrans.loadModuleByImplName( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "FULLWIDTH_HALFWIDTH_LIKE_ASC" )), LANGUAGE_SYSTEM );
[ # # ]
3256 : 0 : bFirstASCCall = false;
3257 : : }
3258 : :
3259 [ # # ][ # # ]: 0 : return aTrans.transliterate( rStr, 0, sal_uInt16( rStr.getLength() ), NULL );
[ # # ]
3260 : : }
3261 : :
3262 : :
3263 : 0 : static ::rtl::OUString lcl_convertIntoFullWidth( const ::rtl::OUString & rStr )
3264 : : {
3265 : : static bool bFirstJISCall = true;
3266 [ # # ][ # # ]: 0 : static utl::TransliterationWrapper aTrans( ::comphelper::getProcessServiceFactory(), 0 );
[ # # ][ # # ]
[ # # ]
3267 : :
3268 [ # # ]: 0 : if( bFirstJISCall )
3269 : : {
3270 [ # # ][ # # ]: 0 : aTrans.loadModuleByImplName( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "HALFWIDTH_FULLWIDTH_LIKE_JIS" )), LANGUAGE_SYSTEM );
[ # # ]
3271 : 0 : bFirstJISCall = false;
3272 : : }
3273 : :
3274 [ # # ][ # # ]: 0 : return aTrans.transliterate( rStr, 0, sal_uInt16( rStr.getLength() ), NULL );
[ # # ]
3275 : : }
3276 : :
3277 : :
3278 : : /* ODFF:
3279 : : * Summary: Converts half-width to full-width ASCII and katakana characters.
3280 : : * Semantics: Conversion is done for half-width ASCII and katakana characters,
3281 : : * other characters are simply copied from T to the result. This is the
3282 : : * complementary function to ASC.
3283 : : * For references regarding halfwidth and fullwidth characters see
3284 : : * http://www.unicode.org/reports/tr11/
3285 : : * http://www.unicode.org/charts/charindex2.html#H
3286 : : * http://www.unicode.org/charts/charindex2.html#F
3287 : : */
3288 : 0 : void ScInterpreter::ScJis()
3289 : : {
3290 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScJis" );
3291 [ # # ]: 0 : if (MustHaveParamCount( GetByte(), 1))
3292 [ # # ][ # # ]: 0 : PushString( lcl_convertIntoFullWidth( GetString()));
[ # # ][ # # ]
3293 : 0 : }
3294 : :
3295 : :
3296 : : /* ODFF:
3297 : : * Summary: Converts full-width to half-width ASCII and katakana characters.
3298 : : * Semantics: Conversion is done for full-width ASCII and katakana characters,
3299 : : * other characters are simply copied from T to the result. This is the
3300 : : * complementary function to JIS.
3301 : : */
3302 : 0 : void ScInterpreter::ScAsc()
3303 : : {
3304 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScAsc" );
3305 [ # # ]: 0 : if (MustHaveParamCount( GetByte(), 1))
3306 [ # # ][ # # ]: 0 : PushString( lcl_convertIntoHalfWidth( GetString()));
[ # # ][ # # ]
3307 : 0 : }
3308 : :
3309 : 0 : void ScInterpreter::ScUnicode()
3310 : : {
3311 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScUnicode" );
3312 [ # # ]: 0 : if ( MustHaveParamCount( GetByte(), 1 ) )
3313 : : {
3314 : 0 : const rtl::OUString& rStr = GetString();
3315 [ # # ]: 0 : if (rStr.isEmpty())
3316 [ # # ]: 0 : PushIllegalParameter();
3317 : : else
3318 : : {
3319 : 0 : sal_Int32 i = 0;
3320 [ # # ][ # # ]: 0 : PushDouble( rStr.iterateCodePoints(&i) );
3321 : 0 : }
3322 : : }
3323 : 0 : }
3324 : :
3325 : 0 : void ScInterpreter::ScUnichar()
3326 : : {
3327 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScUnichar" );
3328 [ # # ]: 0 : if ( MustHaveParamCount( GetByte(), 1 ) )
3329 : : {
3330 : 0 : double dVal = ::rtl::math::approxFloor( GetDouble() );
3331 [ # # ][ # # ]: 0 : if ((dVal < 0x000000) || (dVal > 0x10FFFF))
3332 : 0 : PushIllegalArgument();
3333 : : else
3334 : : {
3335 : 0 : sal_uInt32 nCodePoint = static_cast<sal_uInt32>( dVal );
3336 [ # # ]: 0 : rtl::OUString aStr( &nCodePoint, 1 );
3337 [ # # ][ # # ]: 0 : PushString( aStr );
[ # # ]
3338 : : }
3339 : : }
3340 : 0 : }
3341 : :
3342 : :
3343 : 0 : void ScInterpreter::ScMin( bool bTextAsZero )
3344 : : {
3345 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScMin" );
3346 : 0 : short nParamCount = GetByte();
3347 [ # # ][ # # ]: 0 : if (!MustHaveParamCountMin( nParamCount, 1))
3348 : 0 : return;
3349 : 0 : double nMin = ::std::numeric_limits<double>::max();
3350 : 0 : double nVal = 0.0;
3351 : 0 : ScAddress aAdr;
3352 : 0 : ScRange aRange;
3353 : 0 : size_t nRefInList = 0;
3354 [ # # ]: 0 : while (nParamCount-- > 0)
3355 : : {
3356 [ # # ][ # # : 0 : switch (GetStackType())
# # # # ]
3357 : : {
3358 : : case svDouble :
3359 : : {
3360 [ # # ]: 0 : nVal = GetDouble();
3361 [ # # ]: 0 : if (nMin > nVal) nMin = nVal;
3362 : 0 : nFuncFmtType = NUMBERFORMAT_NUMBER;
3363 : : }
3364 : 0 : break;
3365 : : case svSingleRef :
3366 : : {
3367 [ # # ]: 0 : PopSingleRef( aAdr );
3368 [ # # ]: 0 : ScBaseCell* pCell = GetCell( aAdr );
3369 [ # # ][ # # ]: 0 : if (HasCellValueData(pCell))
3370 : : {
3371 [ # # ]: 0 : nVal = GetCellValue( aAdr, pCell );
3372 : 0 : CurFmtToFuncFmt();
3373 [ # # ]: 0 : if (nMin > nVal) nMin = nVal;
3374 : : }
3375 [ # # ][ # # ]: 0 : else if ( bTextAsZero && HasCellStringData( pCell ) )
[ # # ][ # # ]
3376 : : {
3377 [ # # ]: 0 : if ( nMin > 0.0 )
3378 : 0 : nMin = 0.0;
3379 : : }
3380 : : }
3381 : 0 : break;
3382 : : case svDoubleRef :
3383 : : case svRefList :
3384 : : {
3385 : 0 : sal_uInt16 nErr = 0;
3386 [ # # ]: 0 : PopDoubleRef( aRange, nParamCount, nRefInList);
3387 [ # # ]: 0 : ScValueIterator aValIter( pDok, aRange, glSubTotal, bTextAsZero );
3388 [ # # ][ # # ]: 0 : if (aValIter.GetFirst(nVal, nErr))
3389 : : {
3390 [ # # ]: 0 : if (nMin > nVal)
3391 : 0 : nMin = nVal;
3392 [ # # ]: 0 : aValIter.GetCurNumFmtInfo( nFuncFmtType, nFuncFmtIndex );
3393 [ # # ][ # # ]: 0 : while ((nErr == 0) && aValIter.GetNext(nVal, nErr))
[ # # ][ # # ]
3394 : : {
3395 [ # # ]: 0 : if (nMin > nVal)
3396 : 0 : nMin = nVal;
3397 : : }
3398 : 0 : SetError(nErr);
3399 : : }
3400 : : }
3401 : 0 : break;
3402 : : case svMatrix :
3403 : : case svExternalSingleRef:
3404 : : case svExternalDoubleRef:
3405 : : {
3406 [ # # ]: 0 : ScMatrixRef pMat = GetMatrix();
3407 [ # # ]: 0 : if (pMat)
3408 : : {
3409 : : SCSIZE nC, nR;
3410 : 0 : nFuncFmtType = NUMBERFORMAT_NUMBER;
3411 [ # # ]: 0 : pMat->GetDimensions(nC, nR);
3412 [ # # ][ # # ]: 0 : if (pMat->IsNumeric())
3413 : : {
3414 [ # # ]: 0 : for (SCSIZE nMatCol = 0; nMatCol < nC; nMatCol++)
3415 [ # # ]: 0 : for (SCSIZE nMatRow = 0; nMatRow < nR; nMatRow++)
3416 : : {
3417 [ # # ]: 0 : nVal = pMat->GetDouble(nMatCol,nMatRow);
3418 [ # # ]: 0 : if (nMin > nVal) nMin = nVal;
3419 : : }
3420 : : }
3421 : : else
3422 : : {
3423 [ # # ]: 0 : for (SCSIZE nMatCol = 0; nMatCol < nC; nMatCol++)
3424 : : {
3425 [ # # ]: 0 : for (SCSIZE nMatRow = 0; nMatRow < nR; nMatRow++)
3426 : : {
3427 [ # # ][ # # ]: 0 : if (!pMat->IsString(nMatCol,nMatRow))
3428 : : {
3429 [ # # ]: 0 : nVal = pMat->GetDouble(nMatCol,nMatRow);
3430 [ # # ]: 0 : if (nMin > nVal) nMin = nVal;
3431 : : }
3432 [ # # ]: 0 : else if ( bTextAsZero )
3433 : : {
3434 [ # # ]: 0 : if ( nMin > 0.0 )
3435 : 0 : nMin = 0.0;
3436 : : }
3437 : : }
3438 : : }
3439 : : }
3440 [ # # ]: 0 : }
3441 : : }
3442 : 0 : break;
3443 : : case svString :
3444 : : {
3445 [ # # ]: 0 : Pop();
3446 [ # # ]: 0 : if ( bTextAsZero )
3447 : : {
3448 [ # # ]: 0 : if ( nMin > 0.0 )
3449 : 0 : nMin = 0.0;
3450 : : }
3451 : : else
3452 : 0 : SetError(errIllegalParameter);
3453 : : }
3454 : 0 : break;
3455 : : default :
3456 [ # # ]: 0 : Pop();
3457 : 0 : SetError(errIllegalParameter);
3458 : : }
3459 : : }
3460 [ # # ]: 0 : if ( nVal < nMin )
3461 [ # # ]: 0 : PushDouble(0.0);
3462 : : else
3463 [ # # ]: 0 : PushDouble(nMin);
3464 : : }
3465 : :
3466 : 0 : void ScInterpreter::ScMax( bool bTextAsZero )
3467 : : {
3468 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScMax" );
3469 : 0 : short nParamCount = GetByte();
3470 [ # # ][ # # ]: 0 : if (!MustHaveParamCountMin( nParamCount, 1))
3471 : 0 : return;
3472 : 0 : double nMax = -(::std::numeric_limits<double>::max());
3473 : 0 : double nVal = 0.0;
3474 : 0 : ScAddress aAdr;
3475 : 0 : ScRange aRange;
3476 : 0 : size_t nRefInList = 0;
3477 [ # # ]: 0 : while (nParamCount-- > 0)
3478 : : {
3479 [ # # ][ # # : 0 : switch (GetStackType())
# # # # ]
3480 : : {
3481 : : case svDouble :
3482 : : {
3483 [ # # ]: 0 : nVal = GetDouble();
3484 [ # # ]: 0 : if (nMax < nVal) nMax = nVal;
3485 : 0 : nFuncFmtType = NUMBERFORMAT_NUMBER;
3486 : : }
3487 : 0 : break;
3488 : : case svSingleRef :
3489 : : {
3490 [ # # ]: 0 : PopSingleRef( aAdr );
3491 [ # # ]: 0 : ScBaseCell* pCell = GetCell( aAdr );
3492 [ # # ][ # # ]: 0 : if (HasCellValueData(pCell))
3493 : : {
3494 [ # # ]: 0 : nVal = GetCellValue( aAdr, pCell );
3495 : 0 : CurFmtToFuncFmt();
3496 [ # # ]: 0 : if (nMax < nVal) nMax = nVal;
3497 : : }
3498 [ # # ][ # # ]: 0 : else if ( bTextAsZero && HasCellStringData( pCell ) )
[ # # ][ # # ]
3499 : : {
3500 [ # # ]: 0 : if ( nMax < 0.0 )
3501 : 0 : nMax = 0.0;
3502 : : }
3503 : : }
3504 : 0 : break;
3505 : : case svDoubleRef :
3506 : : case svRefList :
3507 : : {
3508 : 0 : sal_uInt16 nErr = 0;
3509 [ # # ]: 0 : PopDoubleRef( aRange, nParamCount, nRefInList);
3510 [ # # ]: 0 : ScValueIterator aValIter( pDok, aRange, glSubTotal, bTextAsZero );
3511 [ # # ][ # # ]: 0 : if (aValIter.GetFirst(nVal, nErr))
3512 : : {
3513 [ # # ]: 0 : if (nMax < nVal)
3514 : 0 : nMax = nVal;
3515 [ # # ]: 0 : aValIter.GetCurNumFmtInfo( nFuncFmtType, nFuncFmtIndex );
3516 [ # # ][ # # ]: 0 : while ((nErr == 0) && aValIter.GetNext(nVal, nErr))
[ # # ][ # # ]
3517 : : {
3518 [ # # ]: 0 : if (nMax < nVal)
3519 : 0 : nMax = nVal;
3520 : : }
3521 : 0 : SetError(nErr);
3522 : : }
3523 : : }
3524 : 0 : break;
3525 : : case svMatrix :
3526 : : case svExternalSingleRef:
3527 : : case svExternalDoubleRef:
3528 : : {
3529 [ # # ]: 0 : ScMatrixRef pMat = GetMatrix();
3530 [ # # ]: 0 : if (pMat)
3531 : : {
3532 : 0 : nFuncFmtType = NUMBERFORMAT_NUMBER;
3533 : : SCSIZE nC, nR;
3534 [ # # ]: 0 : pMat->GetDimensions(nC, nR);
3535 [ # # ][ # # ]: 0 : if (pMat->IsNumeric())
3536 : : {
3537 [ # # ]: 0 : for (SCSIZE nMatCol = 0; nMatCol < nC; nMatCol++)
3538 [ # # ]: 0 : for (SCSIZE nMatRow = 0; nMatRow < nR; nMatRow++)
3539 : : {
3540 [ # # ]: 0 : nVal = pMat->GetDouble(nMatCol,nMatRow);
3541 [ # # ]: 0 : if (nMax < nVal) nMax = nVal;
3542 : : }
3543 : : }
3544 : : else
3545 : : {
3546 [ # # ]: 0 : for (SCSIZE nMatCol = 0; nMatCol < nC; nMatCol++)
3547 : : {
3548 [ # # ]: 0 : for (SCSIZE nMatRow = 0; nMatRow < nR; nMatRow++)
3549 : : {
3550 [ # # ][ # # ]: 0 : if (!pMat->IsString(nMatCol,nMatRow))
3551 : : {
3552 [ # # ]: 0 : nVal = pMat->GetDouble(nMatCol,nMatRow);
3553 [ # # ]: 0 : if (nMax < nVal) nMax = nVal;
3554 : : }
3555 [ # # ]: 0 : else if ( bTextAsZero )
3556 : : {
3557 [ # # ]: 0 : if ( nMax < 0.0 )
3558 : 0 : nMax = 0.0;
3559 : : }
3560 : : }
3561 : : }
3562 : : }
3563 [ # # ]: 0 : }
3564 : : }
3565 : 0 : break;
3566 : : case svString :
3567 : : {
3568 [ # # ]: 0 : Pop();
3569 [ # # ]: 0 : if ( bTextAsZero )
3570 : : {
3571 [ # # ]: 0 : if ( nMax < 0.0 )
3572 : 0 : nMax = 0.0;
3573 : : }
3574 : : else
3575 : 0 : SetError(errIllegalParameter);
3576 : : }
3577 : 0 : break;
3578 : : default :
3579 [ # # ]: 0 : Pop();
3580 : 0 : SetError(errIllegalParameter);
3581 : : }
3582 : : }
3583 [ # # ]: 0 : if ( nVal > nMax )
3584 [ # # ]: 0 : PushDouble(0.0);
3585 : : else
3586 [ # # ]: 0 : PushDouble(nMax);
3587 : : }
3588 : : #if defined(WIN) && defined(MSC)
3589 : : #pragma optimize("",on)
3590 : : #endif
3591 : :
3592 : : namespace {
3593 : :
3594 : 21 : void IterateMatrix(
3595 : : const ScMatrixRef& pMat, ScIterFunc eFunc, bool bTextAsZero,
3596 : : sal_uLong& rCount, short& rFuncFmtType, double& fRes, double& fMem, bool& bNull)
3597 : : {
3598 [ - + ]: 21 : if (!pMat)
3599 : 21 : return;
3600 : :
3601 : 21 : rFuncFmtType = NUMBERFORMAT_NUMBER;
3602 [ + + - + : 21 : switch (eFunc)
- - ]
3603 : : {
3604 : : case ifAVERAGE:
3605 : : case ifSUM:
3606 : : {
3607 [ + - ]: 12 : ScMatrix::IterateResult aRes = pMat->Sum(bTextAsZero);
3608 [ + - ]: 12 : if (bNull)
3609 : : {
3610 : 12 : bNull = false;
3611 : 12 : fMem = aRes.mfFirst;
3612 : 12 : fRes += aRes.mfRest;
3613 : : }
3614 : : else
3615 : 0 : fRes += aRes.mfFirst + aRes.mfRest;
3616 : 12 : rCount += aRes.mnCount;
3617 : : }
3618 : 12 : break;
3619 : : case ifCOUNT:
3620 : 6 : rCount += pMat->Count(bTextAsZero);
3621 : 6 : break;
3622 : : case ifCOUNT2:
3623 : 0 : rCount += pMat->Count(true);
3624 : 0 : break;
3625 : : case ifPRODUCT:
3626 : : {
3627 [ + - ]: 3 : ScMatrix::IterateResult aRes = pMat->Product(bTextAsZero);
3628 : 3 : fRes *= aRes.mfRest;
3629 : 3 : rCount += aRes.mnCount;
3630 : : }
3631 : 3 : break;
3632 : : case ifSUMSQ:
3633 : : {
3634 [ # # ]: 0 : ScMatrix::IterateResult aRes = pMat->SumSquare(bTextAsZero);
3635 : 0 : fRes += aRes.mfRest;
3636 : 0 : rCount += aRes.mnCount;
3637 : : }
3638 : 0 : break;
3639 : : default:
3640 : : ;
3641 : : }
3642 : : }
3643 : :
3644 : : }
3645 : :
3646 : 135 : double ScInterpreter::IterateParameters( ScIterFunc eFunc, bool bTextAsZero )
3647 : : {
3648 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::IterateParameters" );
3649 : 135 : short nParamCount = GetByte();
3650 [ + + ]: 135 : double fRes = ( eFunc == ifPRODUCT ) ? 1.0 : 0.0;
3651 : 135 : double fVal = 0.0;
3652 : 135 : double fMem = 0.0; // first numeric value.
3653 : 135 : bool bNull = true;
3654 : 135 : sal_uLong nCount = 0;
3655 : 135 : ScAddress aAdr;
3656 : 135 : ScRange aRange;
3657 : 135 : size_t nRefInList = 0;
3658 [ # # ][ # # ]: 135 : if ( nGlobalError && ( eFunc == ifCOUNT2 || eFunc == ifCOUNT ) )
[ - + ]
3659 : 0 : nGlobalError = 0;
3660 [ + + ]: 288 : while (nParamCount-- > 0)
3661 : : {
3662 [ + - ][ - + : 153 : switch (GetStackType())
- - + + +
- - ]
3663 : : {
3664 : :
3665 : : case svString:
3666 : : {
3667 [ # # ]: 0 : if( eFunc == ifCOUNT )
3668 : : {
3669 [ # # ][ # # ]: 0 : String aStr( PopString() );
3670 : 0 : sal_uInt32 nFIndex = 0; // damit default Land/Spr.
3671 [ # # ][ # # ]: 0 : if ( bTextAsZero || pFormatter->IsNumberFormat(aStr, nFIndex, fVal))
[ # # ][ # # ]
3672 [ # # ]: 0 : nCount++;
3673 : : }
3674 : : else
3675 : : {
3676 [ # # ]: 0 : switch ( eFunc )
3677 : : {
3678 : : case ifAVERAGE:
3679 : : case ifSUM:
3680 : : case ifSUMSQ:
3681 : : case ifPRODUCT:
3682 : : {
3683 [ # # ]: 0 : if ( bTextAsZero )
3684 : : {
3685 [ # # ]: 0 : Pop();
3686 : 0 : nCount++;
3687 [ # # ]: 0 : if ( eFunc == ifPRODUCT )
3688 : 0 : fRes = 0.0;
3689 : : }
3690 : : else
3691 : : {
3692 [ # # ]: 0 : while (nParamCount-- > 0)
3693 [ # # ]: 0 : Pop();
3694 : 0 : SetError( errNoValue );
3695 : : }
3696 : : }
3697 : 0 : break;
3698 : : default:
3699 [ # # ]: 0 : Pop();
3700 : 0 : nCount++;
3701 : : }
3702 : : }
3703 : : }
3704 : 0 : break;
3705 : : case svDouble :
3706 [ + - ]: 27 : fVal = GetDouble();
3707 : 27 : nCount++;
3708 [ + - - - ]: 27 : switch( eFunc )
3709 : : {
3710 : : case ifAVERAGE:
3711 : : case ifSUM:
3712 [ + + ][ + + ]: 27 : if ( bNull && fVal != 0.0 )
3713 : : {
3714 : 9 : bNull = false;
3715 : 9 : fMem = fVal;
3716 : : }
3717 : : else
3718 : 18 : fRes += fVal;
3719 : 27 : break;
3720 : 0 : case ifSUMSQ: fRes += fVal * fVal; break;
3721 : 0 : case ifPRODUCT: fRes *= fVal; break;
3722 : : default: ; // nothing
3723 : : }
3724 : 27 : nFuncFmtType = NUMBERFORMAT_NUMBER;
3725 : 27 : break;
3726 : : case svExternalSingleRef:
3727 : : {
3728 : 0 : ScExternalRefCache::TokenRef pToken;
3729 [ # # ]: 0 : ScExternalRefCache::CellFormat aFmt;
3730 [ # # ]: 0 : PopExternalSingleRef(pToken, &aFmt);
3731 [ # # ][ # # ]: 0 : if (nGlobalError && (eFunc == ifCOUNT2 || eFunc == ifCOUNT))
[ # # ]
3732 : : {
3733 : 0 : nGlobalError = 0;
3734 [ # # ]: 0 : if ( eFunc == ifCOUNT2 )
3735 : 0 : ++nCount;
3736 : : break;
3737 : : }
3738 : :
3739 [ # # ]: 0 : if (!pToken)
3740 : : break;
3741 : :
3742 : 0 : StackVar eType = pToken->GetType();
3743 [ # # ]: 0 : if (eFunc == ifCOUNT2)
3744 : : {
3745 [ # # ]: 0 : if (eType != formula::svEmptyCell)
3746 : 0 : nCount++;
3747 [ # # ]: 0 : if (nGlobalError)
3748 : 0 : nGlobalError = 0;
3749 : : }
3750 [ # # ]: 0 : else if (eType == formula::svDouble)
3751 : : {
3752 : 0 : nCount++;
3753 [ # # ]: 0 : fVal = pToken->GetDouble();
3754 [ # # ]: 0 : if (aFmt.mbIsSet)
3755 : : {
3756 : 0 : nFuncFmtType = aFmt.mnType;
3757 : 0 : nFuncFmtIndex = aFmt.mnIndex;
3758 : : }
3759 [ # # # # : 0 : switch( eFunc )
# ]
3760 : : {
3761 : : case ifAVERAGE:
3762 : : case ifSUM:
3763 [ # # ][ # # ]: 0 : if ( bNull && fVal != 0.0 )
3764 : : {
3765 : 0 : bNull = false;
3766 : 0 : fMem = fVal;
3767 : : }
3768 : : else
3769 : 0 : fRes += fVal;
3770 : 0 : break;
3771 : 0 : case ifSUMSQ: fRes += fVal * fVal; break;
3772 : 0 : case ifPRODUCT: fRes *= fVal; break;
3773 : : case ifCOUNT:
3774 [ # # ]: 0 : if ( nGlobalError )
3775 : : {
3776 : 0 : nGlobalError = 0;
3777 : 0 : nCount--;
3778 : : }
3779 : 0 : break;
3780 : : default: ; // nothing
3781 : : }
3782 : : }
3783 [ # # ][ # # ]: 0 : else if (bTextAsZero && eType == formula::svString)
3784 : : {
3785 : 0 : nCount++;
3786 [ # # ]: 0 : if ( eFunc == ifPRODUCT )
3787 : 0 : fRes = 0.0;
3788 [ # # ][ # # ]: 0 : }
3789 : : }
3790 : 0 : break;
3791 : : case svSingleRef :
3792 : : {
3793 [ # # ]: 0 : PopSingleRef( aAdr );
3794 [ # # ][ # # ]: 0 : if ( nGlobalError && ( eFunc == ifCOUNT2 || eFunc == ifCOUNT ) )
[ # # ]
3795 : : {
3796 : 0 : nGlobalError = 0;
3797 [ # # ]: 0 : if ( eFunc == ifCOUNT2 )
3798 : 0 : ++nCount;
3799 : 0 : break;
3800 : : }
3801 [ # # ]: 0 : ScBaseCell* pCell = GetCell( aAdr );
3802 [ # # ]: 0 : if ( pCell )
3803 : : {
3804 [ # # ]: 0 : if( eFunc == ifCOUNT2 )
3805 : : {
3806 : 0 : CellType eCellType = pCell->GetCellType();
3807 [ # # ][ # # ]: 0 : if (eCellType != CELLTYPE_NONE && eCellType != CELLTYPE_NOTE)
3808 : 0 : nCount++;
3809 [ # # ]: 0 : if ( nGlobalError )
3810 : 0 : nGlobalError = 0;
3811 : : }
3812 [ # # ][ # # ]: 0 : else if ( pCell->HasValueData() )
3813 : : {
3814 : 0 : nCount++;
3815 [ # # ]: 0 : fVal = GetCellValue( aAdr, pCell );
3816 : 0 : CurFmtToFuncFmt();
3817 [ # # # # : 0 : switch( eFunc )
# ]
3818 : : {
3819 : : case ifAVERAGE:
3820 : : case ifSUM:
3821 [ # # ][ # # ]: 0 : if ( bNull && fVal != 0.0 )
3822 : : {
3823 : 0 : bNull = false;
3824 : 0 : fMem = fVal;
3825 : : }
3826 : : else
3827 : 0 : fRes += fVal;
3828 : 0 : break;
3829 : 0 : case ifSUMSQ: fRes += fVal * fVal; break;
3830 : 0 : case ifPRODUCT: fRes *= fVal; break;
3831 : : case ifCOUNT:
3832 [ # # ]: 0 : if ( nGlobalError )
3833 : : {
3834 : 0 : nGlobalError = 0;
3835 : 0 : nCount--;
3836 : : }
3837 : 0 : break;
3838 : : default: ; // nothing
3839 : : }
3840 : : }
3841 [ # # ][ # # ]: 0 : else if ( bTextAsZero && pCell->HasStringData() )
[ # # ][ # # ]
3842 : : {
3843 : 0 : nCount++;
3844 [ # # ]: 0 : if ( eFunc == ifPRODUCT )
3845 : 0 : fRes = 0.0;
3846 : : }
3847 : : }
3848 : : }
3849 : 0 : break;
3850 : : case svDoubleRef :
3851 : : case svRefList :
3852 : : {
3853 [ + - ]: 105 : PopDoubleRef( aRange, nParamCount, nRefInList);
3854 [ - + ][ # # ]: 105 : if ( nGlobalError && ( eFunc == ifCOUNT2 || eFunc == ifCOUNT ) )
[ # # ]
3855 : : {
3856 : 0 : nGlobalError = 0;
3857 [ # # ]: 0 : if ( eFunc == ifCOUNT2 )
3858 : 0 : ++nCount;
3859 : 0 : break;
3860 : : }
3861 [ + + ]: 105 : if( eFunc == ifCOUNT2 )
3862 : : {
3863 : : ScBaseCell* pCell;
3864 [ + - ]: 3 : ScCellIterator aIter( pDok, aRange, glSubTotal );
3865 [ + - ][ + - ]: 3 : if ( (pCell = aIter.GetFirst()) != NULL )
3866 : : {
3867 [ + - ][ + + ]: 36 : do
3868 : : {
3869 : 36 : CellType eType = pCell->GetCellType();
3870 [ + - ][ + - ]: 36 : if( eType != CELLTYPE_NONE && eType != CELLTYPE_NOTE )
3871 : 36 : nCount++;
3872 : : }
3873 : : while ( (pCell = aIter.GetNext()) != NULL );
3874 : : }
3875 [ - + ]: 3 : if ( nGlobalError )
3876 : 3 : nGlobalError = 0;
3877 : : }
3878 : : else
3879 : : {
3880 [ + - ]: 102 : ScValueIterator aValIter( pDok, aRange, glSubTotal, bTextAsZero );
3881 : 102 : sal_uInt16 nErr = 0;
3882 [ + - ][ + + ]: 102 : if (aValIter.GetFirst(fVal, nErr))
3883 : : {
3884 : : // placed the loop on the inside for performance reasons:
3885 [ + - ]: 81 : aValIter.GetCurNumFmtInfo( nFuncFmtType, nFuncFmtIndex );
3886 [ + - + + : 81 : switch( eFunc )
- ]
3887 : : {
3888 : : case ifAVERAGE:
3889 : : case ifSUM:
3890 [ + - ][ + + ]: 427 : do
3891 : : {
3892 : 427 : SetError(nErr);
3893 [ + + ][ + + ]: 427 : if ( bNull && fVal != 0.0 )
3894 : : {
3895 : 72 : bNull = false;
3896 : 72 : fMem = fVal;
3897 : : }
3898 : : else
3899 : 355 : fRes += fVal;
3900 : 427 : nCount++;
3901 : : }
3902 : : while (aValIter.GetNext(fVal, nErr));
3903 : 72 : break;
3904 : : case ifSUMSQ:
3905 [ # # ][ # # ]: 0 : do
3906 : : {
3907 : 0 : SetError(nErr);
3908 : 0 : fRes += fVal * fVal;
3909 : 0 : nCount++;
3910 : : }
3911 : : while (aValIter.GetNext(fVal, nErr));
3912 : 0 : break;
3913 : : case ifPRODUCT:
3914 [ + + ][ + - ]: 18 : do
3915 : : {
3916 : 18 : SetError(nErr);
3917 : 18 : fRes *= fVal;
3918 : 18 : nCount++;
3919 : : }
3920 : : while (aValIter.GetNext(fVal, nErr));
3921 : 6 : break;
3922 : : case ifCOUNT:
3923 [ + - ][ + + ]: 18 : do
3924 : : {
3925 [ + + ]: 18 : if ( !nErr )
3926 : 15 : nCount++;
3927 : : }
3928 : : while (aValIter.GetNext(fVal, nErr));
3929 : 3 : break;
3930 : : default: ; // nothing
3931 : : }
3932 : 102 : SetError( nErr );
3933 : : }
3934 : : }
3935 : : }
3936 : 105 : break;
3937 : : case svExternalDoubleRef:
3938 : : {
3939 : 18 : ScMatrixRef pMat;
3940 [ + - ]: 18 : PopExternalDoubleRef(pMat);
3941 [ - + ]: 18 : if (nGlobalError)
3942 : : break;
3943 : :
3944 [ + - ][ + - ]: 18 : IterateMatrix(pMat, eFunc, bTextAsZero, nCount, nFuncFmtType, fRes, fMem, bNull);
[ + - ]
3945 : : }
3946 : 18 : break;
3947 : : case svMatrix :
3948 : : {
3949 [ + - ]: 3 : ScMatrixRef pMat = PopMatrix();
3950 [ + - ][ + - ]: 3 : IterateMatrix(pMat, eFunc, bTextAsZero, nCount, nFuncFmtType, fRes, fMem, bNull);
3951 : : }
3952 : 3 : break;
3953 : : case svError:
3954 : : {
3955 [ # # ]: 0 : PopError();
3956 [ # # ]: 0 : if ( eFunc == ifCOUNT )
3957 : : {
3958 : 0 : nGlobalError = 0;
3959 : : }
3960 [ # # ]: 0 : else if ( eFunc == ifCOUNT2 )
3961 : : {
3962 : 0 : nCount++;
3963 : 0 : nGlobalError = 0;
3964 : : }
3965 : : }
3966 : 0 : break;
3967 : : default :
3968 [ # # ]: 0 : while (nParamCount-- > 0)
3969 [ # # ]: 0 : PopError();
3970 : 0 : SetError(errIllegalParameter);
3971 : : }
3972 : : }
3973 [ + + + + : 135 : switch( eFunc )
- ]
3974 : : {
3975 : 102 : case ifSUM: fRes = ::rtl::math::approxAdd( fRes, fMem ); break;
3976 : 12 : case ifAVERAGE: fRes = div(::rtl::math::approxAdd( fRes, fMem ), nCount); break;
3977 : : case ifCOUNT2:
3978 : 12 : case ifCOUNT: fRes = nCount; break;
3979 [ - + ]: 9 : case ifPRODUCT: if ( !nCount ) fRes = 0.0; break;
3980 : : default: ; // nothing
3981 : : }
3982 : : // Bei Summen etc. macht ein bool-Ergebnis keinen Sinn
3983 : : // und Anzahl ist immer Number (#38345#)
3984 [ + + ][ - + ]: 135 : if( eFunc == ifCOUNT || nFuncFmtType == NUMBERFORMAT_LOGICAL )
3985 : 9 : nFuncFmtType = NUMBERFORMAT_NUMBER;
3986 : 135 : return fRes;
3987 : : }
3988 : :
3989 : :
3990 : 0 : void ScInterpreter::ScSumSQ()
3991 : : {
3992 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScSumSQ" );
3993 : 0 : PushDouble( IterateParameters( ifSUMSQ ) );
3994 : 0 : }
3995 : :
3996 : :
3997 : 102 : void ScInterpreter::ScSum()
3998 : : {
3999 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScSum" );
4000 : 102 : PushDouble( IterateParameters( ifSUM ) );
4001 : 102 : }
4002 : :
4003 : :
4004 : 9 : void ScInterpreter::ScProduct()
4005 : : {
4006 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScProduct" );
4007 : 9 : PushDouble( IterateParameters( ifPRODUCT ) );
4008 : 9 : }
4009 : :
4010 : :
4011 : 12 : void ScInterpreter::ScAverage( bool bTextAsZero )
4012 : : {
4013 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScAverage" );
4014 : 12 : PushDouble( IterateParameters( ifAVERAGE, bTextAsZero ) );
4015 : 12 : }
4016 : :
4017 : :
4018 : 9 : void ScInterpreter::ScCount()
4019 : : {
4020 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScCount" );
4021 : 9 : PushDouble( IterateParameters( ifCOUNT ) );
4022 : 9 : }
4023 : :
4024 : :
4025 : 3 : void ScInterpreter::ScCount2()
4026 : : {
4027 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScCount2" );
4028 : 3 : PushDouble( IterateParameters( ifCOUNT2 ) );
4029 : 3 : }
4030 : :
4031 : :
4032 : 0 : void ScInterpreter::GetStVarParams( double& rVal, double& rValCount,
4033 : : bool bTextAsZero )
4034 : : {
4035 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::GetStVarParams" );
4036 : 0 : short nParamCount = GetByte();
4037 : :
4038 [ # # ]: 0 : std::vector<double> values;
4039 : 0 : double fSum = 0.0;
4040 : 0 : double vSum = 0.0;
4041 : 0 : double vMean = 0.0;
4042 : 0 : double fVal = 0.0;
4043 : 0 : rValCount = 0.0;
4044 : 0 : ScAddress aAdr;
4045 : 0 : ScRange aRange;
4046 : 0 : size_t nRefInList = 0;
4047 [ # # ]: 0 : while (nParamCount-- > 0)
4048 : : {
4049 [ # # ][ # # : 0 : switch (GetStackType())
# # # # ]
4050 : : {
4051 : : case svDouble :
4052 : : {
4053 [ # # ]: 0 : fVal = GetDouble();
4054 [ # # ]: 0 : values.push_back(fVal);
4055 : 0 : fSum += fVal;
4056 : 0 : rValCount++;
4057 : : }
4058 : 0 : break;
4059 : : case svSingleRef :
4060 : : {
4061 [ # # ]: 0 : PopSingleRef( aAdr );
4062 [ # # ]: 0 : ScBaseCell* pCell = GetCell( aAdr );
4063 [ # # ][ # # ]: 0 : if (HasCellValueData(pCell))
4064 : : {
4065 [ # # ]: 0 : fVal = GetCellValue( aAdr, pCell );
4066 [ # # ]: 0 : values.push_back(fVal);
4067 : 0 : fSum += fVal;
4068 : 0 : rValCount++;
4069 : : }
4070 [ # # ][ # # ]: 0 : else if ( bTextAsZero && HasCellStringData( pCell ) )
[ # # ][ # # ]
4071 : : {
4072 [ # # ]: 0 : values.push_back(0.0);
4073 : 0 : rValCount++;
4074 : : }
4075 : : }
4076 : 0 : break;
4077 : : case svDoubleRef :
4078 : : case svRefList :
4079 : : {
4080 : 0 : sal_uInt16 nErr = 0;
4081 [ # # ]: 0 : PopDoubleRef( aRange, nParamCount, nRefInList);
4082 [ # # ]: 0 : ScValueIterator aValIter( pDok, aRange, glSubTotal, bTextAsZero );
4083 [ # # ][ # # ]: 0 : if (aValIter.GetFirst(fVal, nErr))
4084 : : {
4085 [ # # ][ # # ]: 0 : do
[ # # ]
4086 : : {
4087 [ # # ]: 0 : values.push_back(fVal);
4088 : 0 : fSum += fVal;
4089 : 0 : rValCount++;
4090 : : }
4091 [ # # ]: 0 : while ((nErr == 0) && aValIter.GetNext(fVal, nErr));
4092 : : }
4093 : : }
4094 : 0 : break;
4095 : : case svMatrix :
4096 : : {
4097 [ # # ]: 0 : ScMatrixRef pMat = PopMatrix();
4098 [ # # ]: 0 : if (pMat)
4099 : : {
4100 : : SCSIZE nC, nR;
4101 [ # # ]: 0 : pMat->GetDimensions(nC, nR);
4102 [ # # ]: 0 : for (SCSIZE nMatCol = 0; nMatCol < nC; nMatCol++)
4103 : : {
4104 [ # # ]: 0 : for (SCSIZE nMatRow = 0; nMatRow < nR; nMatRow++)
4105 : : {
4106 [ # # ][ # # ]: 0 : if (!pMat->IsString(nMatCol,nMatRow))
4107 : : {
4108 [ # # ]: 0 : fVal= pMat->GetDouble(nMatCol,nMatRow);
4109 [ # # ]: 0 : values.push_back(fVal);
4110 : 0 : fSum += fVal;
4111 : 0 : rValCount++;
4112 : : }
4113 [ # # ]: 0 : else if ( bTextAsZero )
4114 : : {
4115 [ # # ]: 0 : values.push_back(0.0);
4116 : 0 : rValCount++;
4117 : : }
4118 : : }
4119 : : }
4120 [ # # ]: 0 : }
4121 : : }
4122 : 0 : break;
4123 : : case svString :
4124 : : {
4125 [ # # ]: 0 : Pop();
4126 [ # # ]: 0 : if ( bTextAsZero )
4127 : : {
4128 [ # # ]: 0 : values.push_back(0.0);
4129 : 0 : rValCount++;
4130 : : }
4131 : : else
4132 : 0 : SetError(errIllegalParameter);
4133 : : }
4134 : 0 : break;
4135 : : default :
4136 [ # # ]: 0 : Pop();
4137 : 0 : SetError(errIllegalParameter);
4138 : : }
4139 : : }
4140 : :
4141 : 0 : ::std::vector<double>::size_type n = values.size();
4142 : 0 : vMean = fSum / n;
4143 [ # # ]: 0 : for (::std::vector<double>::size_type i = 0; i < n; i++)
4144 [ # # ][ # # ]: 0 : vSum += ::rtl::math::approxSub( values[i], vMean) * ::rtl::math::approxSub( values[i], vMean);
4145 : 0 : rVal = vSum;
4146 : 0 : }
4147 : :
4148 : :
4149 : 0 : void ScInterpreter::ScVar( bool bTextAsZero )
4150 : : {
4151 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScVar" );
4152 : : double nVal;
4153 : : double nValCount;
4154 [ # # ]: 0 : GetStVarParams( nVal, nValCount, bTextAsZero );
4155 : :
4156 [ # # ]: 0 : if (nValCount <= 1.0)
4157 [ # # ]: 0 : PushError( errDivisionByZero );
4158 : : else
4159 [ # # ]: 0 : PushDouble( nVal / (nValCount - 1.0));
4160 : 0 : }
4161 : :
4162 : :
4163 : 0 : void ScInterpreter::ScVarP( bool bTextAsZero )
4164 : : {
4165 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScVarP" );
4166 : : double nVal;
4167 : : double nValCount;
4168 [ # # ]: 0 : GetStVarParams( nVal, nValCount, bTextAsZero );
4169 : :
4170 [ # # ]: 0 : PushDouble( div( nVal, nValCount));
4171 : 0 : }
4172 : :
4173 : :
4174 : 0 : void ScInterpreter::ScStDev( bool bTextAsZero )
4175 : : {
4176 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScStDev" );
4177 : : double nVal;
4178 : : double nValCount;
4179 [ # # ]: 0 : GetStVarParams( nVal, nValCount, bTextAsZero );
4180 [ # # ]: 0 : if (nValCount <= 1.0)
4181 [ # # ]: 0 : PushError( errDivisionByZero );
4182 : : else
4183 [ # # ]: 0 : PushDouble( sqrt( nVal / (nValCount - 1.0)));
4184 : 0 : }
4185 : :
4186 : :
4187 : 0 : void ScInterpreter::ScStDevP( bool bTextAsZero )
4188 : : {
4189 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScStDevP" );
4190 : : double nVal;
4191 : : double nValCount;
4192 [ # # ]: 0 : GetStVarParams( nVal, nValCount, bTextAsZero );
4193 [ # # ]: 0 : if (nValCount == 0.0)
4194 [ # # ]: 0 : PushError( errDivisionByZero );
4195 : : else
4196 [ # # ]: 0 : PushDouble( sqrt( nVal / nValCount));
4197 : :
4198 : : /* this was: PushDouble( sqrt( div( nVal, nValCount)));
4199 : : *
4200 : : * Besides that the special NAN gets lost in the call through sqrt(),
4201 : : * unxlngi6.pro then looped back and forth somewhere between div() and
4202 : : * ::rtl::math::setNan(). Tests showed that
4203 : : *
4204 : : * sqrt( div( 1, 0));
4205 : : *
4206 : : * produced a loop, but
4207 : : *
4208 : : * double f1 = div( 1, 0);
4209 : : * sqrt( f1 );
4210 : : *
4211 : : * was fine. There seems to be some compiler optimization problem. It does
4212 : : * not occur when compiled with debug=t.
4213 : : */
4214 : 0 : }
4215 : :
4216 : :
4217 : 0 : void ScInterpreter::ScColumns()
4218 : : {
4219 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScColumns" );
4220 : 0 : sal_uInt8 nParamCount = GetByte();
4221 : 0 : sal_uLong nVal = 0;
4222 : : SCCOL nCol1;
4223 : : SCROW nRow1;
4224 : : SCTAB nTab1;
4225 : : SCCOL nCol2;
4226 : : SCROW nRow2;
4227 : : SCTAB nTab2;
4228 [ # # ]: 0 : while (nParamCount-- > 0)
4229 : : {
4230 [ # # ][ # # : 0 : switch ( GetStackType() )
# # # # ]
4231 : : {
4232 : : case svSingleRef:
4233 [ # # ]: 0 : PopError();
4234 : 0 : nVal++;
4235 : 0 : break;
4236 : : case svDoubleRef:
4237 [ # # ]: 0 : PopDoubleRef(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
4238 : : nVal += static_cast<sal_uLong>(nTab2 - nTab1 + 1) *
4239 : 0 : static_cast<sal_uLong>(nCol2 - nCol1 + 1);
4240 : 0 : break;
4241 : : case svMatrix:
4242 : : {
4243 [ # # ]: 0 : ScMatrixRef pMat = PopMatrix();
4244 [ # # ]: 0 : if (pMat)
4245 : : {
4246 : : SCSIZE nC, nR;
4247 [ # # ]: 0 : pMat->GetDimensions(nC, nR);
4248 : 0 : nVal += nC;
4249 [ # # ]: 0 : }
4250 : : }
4251 : 0 : break;
4252 : : case svExternalSingleRef:
4253 [ # # ]: 0 : PopError();
4254 : 0 : nVal++;
4255 : 0 : break;
4256 : : case svExternalDoubleRef:
4257 : : {
4258 : : sal_uInt16 nFileId;
4259 [ # # ]: 0 : String aTabName;
4260 : : ScComplexRefData aRef;
4261 [ # # ]: 0 : PopExternalDoubleRef( nFileId, aTabName, aRef);
4262 : : nVal += static_cast<sal_uLong>(aRef.Ref2.nTab - aRef.Ref1.nTab + 1) *
4263 [ # # ]: 0 : static_cast<sal_uLong>(aRef.Ref2.nCol - aRef.Ref1.nCol + 1);
4264 : : }
4265 : 0 : break;
4266 : : default:
4267 [ # # ]: 0 : PopError();
4268 : 0 : SetError(errIllegalParameter);
4269 : : }
4270 : : }
4271 [ # # ]: 0 : PushDouble((double)nVal);
4272 : 0 : }
4273 : :
4274 : :
4275 : 0 : void ScInterpreter::ScRows()
4276 : : {
4277 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScRows" );
4278 : 0 : sal_uInt8 nParamCount = GetByte();
4279 : 0 : sal_uLong nVal = 0;
4280 : : SCCOL nCol1;
4281 : : SCROW nRow1;
4282 : : SCTAB nTab1;
4283 : : SCCOL nCol2;
4284 : : SCROW nRow2;
4285 : : SCTAB nTab2;
4286 [ # # ]: 0 : while (nParamCount-- > 0)
4287 : : {
4288 [ # # ][ # # : 0 : switch ( GetStackType() )
# # # # ]
4289 : : {
4290 : : case svSingleRef:
4291 [ # # ]: 0 : PopError();
4292 : 0 : nVal++;
4293 : 0 : break;
4294 : : case svDoubleRef:
4295 [ # # ]: 0 : PopDoubleRef(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
4296 : : nVal += static_cast<sal_uLong>(nTab2 - nTab1 + 1) *
4297 : 0 : static_cast<sal_uLong>(nRow2 - nRow1 + 1);
4298 : 0 : break;
4299 : : case svMatrix:
4300 : : {
4301 [ # # ]: 0 : ScMatrixRef pMat = PopMatrix();
4302 [ # # ]: 0 : if (pMat)
4303 : : {
4304 : : SCSIZE nC, nR;
4305 [ # # ]: 0 : pMat->GetDimensions(nC, nR);
4306 : 0 : nVal += nR;
4307 [ # # ]: 0 : }
4308 : : }
4309 : 0 : break;
4310 : : case svExternalSingleRef:
4311 [ # # ]: 0 : PopError();
4312 : 0 : nVal++;
4313 : 0 : break;
4314 : : case svExternalDoubleRef:
4315 : : {
4316 : : sal_uInt16 nFileId;
4317 [ # # ]: 0 : String aTabName;
4318 : : ScComplexRefData aRef;
4319 [ # # ]: 0 : PopExternalDoubleRef( nFileId, aTabName, aRef);
4320 : : nVal += static_cast<sal_uLong>(aRef.Ref2.nTab - aRef.Ref1.nTab + 1) *
4321 [ # # ]: 0 : static_cast<sal_uLong>(aRef.Ref2.nRow - aRef.Ref1.nRow + 1);
4322 : : }
4323 : 0 : break;
4324 : : default:
4325 [ # # ]: 0 : PopError();
4326 : 0 : SetError(errIllegalParameter);
4327 : : }
4328 : : }
4329 [ # # ]: 0 : PushDouble((double)nVal);
4330 : 0 : }
4331 : :
4332 : 9 : void ScInterpreter::ScTables()
4333 : : {
4334 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScTables" );
4335 : 9 : sal_uInt8 nParamCount = GetByte();
4336 : : sal_uLong nVal;
4337 [ + - ]: 9 : if ( nParamCount == 0 )
4338 : 9 : nVal = pDok->GetTableCount();
4339 : : else
4340 : : {
4341 : 0 : nVal = 0;
4342 : : SCCOL nCol1;
4343 : : SCROW nRow1;
4344 : : SCTAB nTab1;
4345 : : SCCOL nCol2;
4346 : : SCROW nRow2;
4347 : : SCTAB nTab2;
4348 [ # # ]: 0 : while (nParamCount-- > 0)
4349 : : {
4350 [ # # ][ # # : 0 : switch ( GetStackType() )
# # # # ]
4351 : : {
4352 : : case svSingleRef:
4353 [ # # ]: 0 : PopError();
4354 : 0 : nVal++;
4355 : 0 : break;
4356 : : case svDoubleRef:
4357 [ # # ]: 0 : PopDoubleRef(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
4358 : 0 : nVal += static_cast<sal_uLong>(nTab2 - nTab1 + 1);
4359 : 0 : break;
4360 : : case svMatrix:
4361 [ # # ]: 0 : PopError();
4362 : 0 : nVal++;
4363 : 0 : break;
4364 : : case svExternalSingleRef:
4365 [ # # ]: 0 : PopError();
4366 : 0 : nVal++;
4367 : 0 : break;
4368 : : case svExternalDoubleRef:
4369 : : {
4370 : : sal_uInt16 nFileId;
4371 [ # # ]: 0 : String aTabName;
4372 : : ScComplexRefData aRef;
4373 [ # # ]: 0 : PopExternalDoubleRef( nFileId, aTabName, aRef);
4374 [ # # ]: 0 : nVal += static_cast<sal_uLong>(aRef.Ref2.nTab - aRef.Ref1.nTab + 1);
4375 : : }
4376 : 0 : break;
4377 : : default:
4378 [ # # ]: 0 : PopError();
4379 : 0 : SetError( errIllegalParameter );
4380 : : }
4381 : : }
4382 : : }
4383 : 9 : PushDouble( (double) nVal );
4384 : 9 : }
4385 : :
4386 : :
4387 : 54 : void ScInterpreter::ScColumn()
4388 : : {
4389 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScColumn" );
4390 : 54 : sal_uInt8 nParamCount = GetByte();
4391 [ + - ]: 54 : if ( MustHaveParamCount( nParamCount, 0, 1 ) )
4392 : : {
4393 : 54 : double nVal = 0;
4394 [ + + ]: 54 : if (nParamCount == 0)
4395 : : {
4396 : 9 : nVal = aPos.Col() + 1;
4397 [ + - ]: 9 : if (bMatrixFormula)
4398 : : {
4399 : : SCCOL nCols;
4400 : : SCROW nRows;
4401 [ + - ]: 9 : pMyFormulaCell->GetMatColsRows( nCols, nRows);
4402 [ + - ]: 9 : ScMatrixRef pResMat = GetNewMat( static_cast<SCSIZE>(nCols), 1);
4403 [ + - ]: 9 : if (pResMat)
4404 : : {
4405 [ + + ]: 18 : for (SCCOL i=0; i < nCols; ++i)
4406 [ + - ]: 9 : pResMat->PutDouble( nVal + i, static_cast<SCSIZE>(i), 0);
4407 [ + - ]: 9 : PushMatrix( pResMat);
4408 : : return;
4409 [ + - ][ - + ]: 9 : }
4410 : : }
4411 : : }
4412 : : else
4413 : : {
4414 [ + + - ]: 45 : switch ( GetStackType() )
4415 : : {
4416 : : case svSingleRef :
4417 : : {
4418 : : SCCOL nCol1;
4419 : : SCROW nRow1;
4420 : : SCTAB nTab1;
4421 [ + - ]: 27 : PopSingleRef( nCol1, nRow1, nTab1 );
4422 : 27 : nVal = (double) (nCol1 + 1);
4423 : : }
4424 : 27 : break;
4425 : : case svDoubleRef :
4426 : : {
4427 : : SCCOL nCol1;
4428 : : SCROW nRow1;
4429 : : SCTAB nTab1;
4430 : : SCCOL nCol2;
4431 : : SCROW nRow2;
4432 : : SCTAB nTab2;
4433 [ + - ]: 18 : PopDoubleRef( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 );
4434 [ + - ]: 18 : if (nCol2 > nCol1)
4435 : : {
4436 : : ScMatrixRef pResMat = GetNewMat(
4437 [ + - ]: 18 : static_cast<SCSIZE>(nCol2-nCol1+1), 1);
4438 [ + - ]: 18 : if (pResMat)
4439 : : {
4440 [ + + ]: 72 : for (SCCOL i = nCol1; i <= nCol2; i++)
4441 : : pResMat->PutDouble((double)(i+1),
4442 [ + - ]: 54 : static_cast<SCSIZE>(i-nCol1), 0);
4443 [ + - ]: 18 : PushMatrix(pResMat);
4444 : : return;
4445 : : }
4446 : : else
4447 [ + - ][ - + ]: 18 : nVal = 0.0;
4448 : : }
4449 : : else
4450 : 0 : nVal = (double) (nCol1 + 1);
4451 : : }
4452 : 0 : break;
4453 : : default:
4454 : 0 : SetError( errIllegalParameter );
4455 : 0 : nVal = 0.0;
4456 : : }
4457 : : }
4458 : 54 : PushDouble( nVal );
4459 : : }
4460 : : }
4461 : :
4462 : :
4463 : 27 : void ScInterpreter::ScRow()
4464 : : {
4465 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScRow" );
4466 : 27 : sal_uInt8 nParamCount = GetByte();
4467 [ + - ]: 27 : if ( MustHaveParamCount( nParamCount, 0, 1 ) )
4468 : : {
4469 : 27 : double nVal = 0;
4470 [ + + ]: 27 : if (nParamCount == 0)
4471 : : {
4472 : 9 : nVal = aPos.Row() + 1;
4473 [ + - ]: 9 : if (bMatrixFormula)
4474 : : {
4475 : : SCCOL nCols;
4476 : : SCROW nRows;
4477 [ + - ]: 9 : pMyFormulaCell->GetMatColsRows( nCols, nRows);
4478 [ + - ]: 9 : ScMatrixRef pResMat = GetNewMat( 1, static_cast<SCSIZE>(nRows));
4479 [ + - ]: 9 : if (pResMat)
4480 : : {
4481 [ + + ]: 18 : for (SCROW i=0; i < nRows; i++)
4482 [ + - ]: 9 : pResMat->PutDouble( nVal + i, 0, static_cast<SCSIZE>(i));
4483 [ + - ]: 9 : PushMatrix( pResMat);
4484 : : return;
4485 [ + - ][ - + ]: 9 : }
4486 : : }
4487 : : }
4488 : : else
4489 : : {
4490 [ + + - ]: 18 : switch ( GetStackType() )
4491 : : {
4492 : : case svSingleRef :
4493 : : {
4494 : : SCCOL nCol1;
4495 : : SCROW nRow1;
4496 : : SCTAB nTab1;
4497 [ + - ]: 15 : PopSingleRef( nCol1, nRow1, nTab1 );
4498 : 15 : nVal = (double) (nRow1 + 1);
4499 : : }
4500 : 15 : break;
4501 : : case svDoubleRef :
4502 : : {
4503 : : SCCOL nCol1;
4504 : : SCROW nRow1;
4505 : : SCTAB nTab1;
4506 : : SCCOL nCol2;
4507 : : SCROW nRow2;
4508 : : SCTAB nTab2;
4509 [ + - ]: 3 : PopDoubleRef( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 );
4510 [ + - ]: 3 : if (nRow2 > nRow1)
4511 : : {
4512 : : ScMatrixRef pResMat = GetNewMat( 1,
4513 [ + - ]: 3 : static_cast<SCSIZE>(nRow2-nRow1+1));
4514 [ + - ]: 3 : if (pResMat)
4515 : : {
4516 [ + + ]: 9 : for (SCROW i = nRow1; i <= nRow2; i++)
4517 : : pResMat->PutDouble((double)(i+1), 0,
4518 [ + - ]: 6 : static_cast<SCSIZE>(i-nRow1));
4519 [ + - ]: 3 : PushMatrix(pResMat);
4520 : : return;
4521 : : }
4522 : : else
4523 [ + - ][ - + ]: 3 : nVal = 0.0;
4524 : : }
4525 : : else
4526 : 0 : nVal = (double) (nRow1 + 1);
4527 : : }
4528 : 0 : break;
4529 : : default:
4530 : 0 : SetError( errIllegalParameter );
4531 : 0 : nVal = 0.0;
4532 : : }
4533 : : }
4534 : 27 : PushDouble( nVal );
4535 : : }
4536 : : }
4537 : :
4538 : 0 : void ScInterpreter::ScTable()
4539 : : {
4540 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScTable" );
4541 : 0 : sal_uInt8 nParamCount = GetByte();
4542 [ # # ]: 0 : if ( MustHaveParamCount( nParamCount, 0, 1 ) )
4543 : : {
4544 : 0 : SCTAB nVal = 0;
4545 [ # # ]: 0 : if ( nParamCount == 0 )
4546 : 0 : nVal = aPos.Tab() + 1;
4547 : : else
4548 : : {
4549 [ # # ]: 0 : switch ( GetStackType() )
[ # # # # ]
4550 : : {
4551 : : case svString :
4552 : : {
4553 [ # # ][ # # ]: 0 : String aStr( PopString() );
4554 [ # # ][ # # ]: 0 : if ( pDok->GetTable( aStr, nVal ) )
[ # # ]
4555 : 0 : ++nVal;
4556 : : else
4557 [ # # ]: 0 : SetError( errIllegalArgument );
4558 : : }
4559 : 0 : break;
4560 : : case svSingleRef :
4561 : : {
4562 : : SCCOL nCol1;
4563 : : SCROW nRow1;
4564 : : SCTAB nTab1;
4565 [ # # ]: 0 : PopSingleRef( nCol1, nRow1, nTab1 );
4566 : 0 : nVal = nTab1 + 1;
4567 : : }
4568 : 0 : break;
4569 : : case svDoubleRef :
4570 : : {
4571 : : SCCOL nCol1;
4572 : : SCROW nRow1;
4573 : : SCTAB nTab1;
4574 : : SCCOL nCol2;
4575 : : SCROW nRow2;
4576 : : SCTAB nTab2;
4577 [ # # ]: 0 : PopDoubleRef( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 );
4578 : 0 : nVal = nTab1 + 1;
4579 : : }
4580 : 0 : break;
4581 : : default:
4582 : 0 : SetError( errIllegalParameter );
4583 : : }
4584 [ # # ]: 0 : if ( nGlobalError )
4585 : 0 : nVal = 0;
4586 : : }
4587 [ # # ]: 0 : PushDouble( (double) nVal );
4588 : : }
4589 : 0 : }
4590 : :
4591 : : namespace {
4592 : :
4593 : : class VectorMatrixAccessor
4594 : : {
4595 : : public:
4596 : 0 : VectorMatrixAccessor(const ScMatrix& rMat, bool bColVec) :
4597 : 0 : mrMat(rMat), mbColVec(bColVec) {}
4598 : :
4599 : 0 : bool IsEmpty(SCSIZE i) const
4600 : : {
4601 [ # # ]: 0 : return mbColVec ? mrMat.IsEmpty(0, i) : mrMat.IsEmpty(i, 0);
4602 : : }
4603 : :
4604 : 0 : bool IsEmptyPath(SCSIZE i) const
4605 : : {
4606 [ # # ]: 0 : return mbColVec ? mrMat.IsEmptyPath(0, i) : mrMat.IsEmptyPath(i, 0);
4607 : : }
4608 : :
4609 : 0 : bool IsValue(SCSIZE i) const
4610 : : {
4611 [ # # ]: 0 : return mbColVec ? mrMat.IsValue(0, i) : mrMat.IsValue(i, 0);
4612 : : }
4613 : :
4614 : 0 : bool IsString(SCSIZE i) const
4615 : : {
4616 [ # # ]: 0 : return mbColVec ? mrMat.IsString(0, i) : mrMat.IsString(i, 0);
4617 : : }
4618 : :
4619 : 0 : double GetDouble(SCSIZE i) const
4620 : : {
4621 [ # # ]: 0 : return mbColVec ? mrMat.GetDouble(0, i) : mrMat.GetDouble(i, 0);
4622 : : }
4623 : :
4624 : 0 : rtl::OUString GetString(SCSIZE i) const
4625 : : {
4626 [ # # ]: 0 : return mbColVec ? mrMat.GetString(0, i) : mrMat.GetString(i, 0);
4627 : : }
4628 : :
4629 : 0 : SCSIZE GetElementCount() const
4630 : : {
4631 : : SCSIZE nC, nR;
4632 [ # # ]: 0 : mrMat.GetDimensions(nC, nR);
4633 [ # # ]: 0 : return mbColVec ? nR : nC;
4634 : : }
4635 : :
4636 : : private:
4637 : : const ScMatrix& mrMat;
4638 : : bool mbColVec;
4639 : : };
4640 : :
4641 : : /** returns -1 when the matrix value is smaller than the query value, 0 when
4642 : : they are equal, and 1 when the matrix value is larger than the query
4643 : : value. */
4644 : 0 : static sal_Int32 lcl_CompareMatrix2Query(
4645 : : SCSIZE i, const VectorMatrixAccessor& rMat, const ScQueryEntry& rEntry)
4646 : : {
4647 [ # # ][ # # ]: 0 : if (rMat.IsEmpty(i))
4648 : : {
4649 : : /* TODO: in case we introduced query for real empty this would have to
4650 : : * be changed! */
4651 : 0 : return -1; // empty always less than anything else
4652 : : }
4653 : :
4654 : : /* FIXME: what is an empty path (result of IF(false;true_path) in
4655 : : * comparisons? */
4656 : :
4657 [ # # ]: 0 : bool bByString = rEntry.GetQueryItem().meType == ScQueryEntry::ByString;
4658 [ # # ][ # # ]: 0 : if (rMat.IsValue(i))
4659 : : {
4660 [ # # ]: 0 : if (bByString)
4661 : 0 : return -1; // numeric always less than string
4662 : :
4663 [ # # ]: 0 : const double nVal1 = rMat.GetDouble(i);
4664 [ # # ]: 0 : const double nVal2 = rEntry.GetQueryItem().mfVal;
4665 [ # # ]: 0 : if (nVal1 == nVal2)
4666 : 0 : return 0;
4667 : :
4668 [ # # ]: 0 : return nVal1 < nVal2 ? -1 : 1;
4669 : : }
4670 : :
4671 [ # # ]: 0 : if (!bByString)
4672 : 0 : return 1; // string always greater than numeric
4673 : :
4674 [ # # ]: 0 : const rtl::OUString aStr1 = rMat.GetString(i);
4675 [ # # ]: 0 : const rtl::OUString& rStr2 = rEntry.GetQueryItem().maString;
4676 : :
4677 [ # # ][ # # ]: 0 : return ScGlobal::GetCollator()->compareString(aStr1, rStr2); // case-insensitive
4678 : : }
4679 : :
4680 : : /** returns the last item with the identical value as the original item
4681 : : value. */
4682 : 0 : static void lcl_GetLastMatch( SCSIZE& rIndex, const VectorMatrixAccessor& rMat,
4683 : : SCSIZE nMatCount, bool bReverse)
4684 : : {
4685 [ # # ]: 0 : if (rMat.IsValue(rIndex))
4686 : : {
4687 : 0 : double nVal = rMat.GetDouble(rIndex);
4688 [ # # ]: 0 : if (bReverse)
4689 [ # # ]: 0 : while (rIndex > 0 && rMat.IsValue(rIndex-1) &&
[ # # # # ]
[ # # ]
4690 : 0 : nVal == rMat.GetDouble(rIndex-1))
4691 : 0 : --rIndex;
4692 : : else
4693 [ # # ]: 0 : while (rIndex < nMatCount-1 && rMat.IsValue(rIndex+1) &&
[ # # # # ]
[ # # ]
4694 : 0 : nVal == rMat.GetDouble(rIndex+1))
4695 : 0 : ++rIndex;
4696 : : }
4697 : : //! Order of IsEmptyPath, IsEmpty, IsString is significant!
4698 [ # # ]: 0 : else if (rMat.IsEmptyPath(rIndex))
4699 : : {
4700 [ # # ]: 0 : if (bReverse)
4701 [ # # ][ # # ]: 0 : while (rIndex > 0 && rMat.IsEmptyPath(rIndex-1))
[ # # ]
4702 : 0 : --rIndex;
4703 : : else
4704 [ # # ][ # # ]: 0 : while (rIndex < nMatCount-1 && rMat.IsEmptyPath(rIndex+1))
[ # # ]
4705 : 0 : ++rIndex;
4706 : : }
4707 [ # # ]: 0 : else if (rMat.IsEmpty(rIndex))
4708 : : {
4709 [ # # ]: 0 : if (bReverse)
4710 [ # # ][ # # ]: 0 : while (rIndex > 0 && rMat.IsEmpty(rIndex-1))
[ # # ]
4711 : 0 : --rIndex;
4712 : : else
4713 [ # # ][ # # ]: 0 : while (rIndex < nMatCount-1 && rMat.IsEmpty(rIndex+1))
[ # # ]
4714 : 0 : ++rIndex;
4715 : : }
4716 [ # # ]: 0 : else if (rMat.IsString(rIndex))
4717 : : {
4718 [ # # ]: 0 : rtl::OUString aStr( rMat.GetString(rIndex));
4719 [ # # ]: 0 : if (bReverse)
4720 [ # # ][ # # ]: 0 : while (rIndex > 0 && rMat.IsString(rIndex-1) &&
[ # # # # ]
[ # # ]
4721 [ # # ][ # # ]: 0 : aStr == rMat.GetString(rIndex-1))
[ # # ]
4722 : 0 : --rIndex;
4723 : : else
4724 [ # # ][ # # ]: 0 : while (rIndex < nMatCount-1 && rMat.IsString(rIndex+1) &&
[ # # # # ]
[ # # ]
4725 [ # # ][ # # ]: 0 : aStr == rMat.GetString(rIndex+1))
[ # # ]
4726 : 0 : ++rIndex;
4727 : : }
4728 : : else
4729 : : {
4730 : : OSL_FAIL("lcl_GetLastMatch: unhandled matrix type");
4731 : : }
4732 : 0 : }
4733 : :
4734 : : }
4735 : :
4736 : 93 : void ScInterpreter::ScMatch()
4737 : : {
4738 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScMatch" );
4739 : :
4740 : 93 : sal_uInt8 nParamCount = GetByte();
4741 [ + - ]: 93 : if ( MustHaveParamCount( nParamCount, 2, 3 ) )
4742 : : {
4743 : : double fTyp;
4744 [ + - ]: 93 : if (nParamCount == 3)
4745 [ + - ]: 93 : fTyp = GetDouble();
4746 : : else
4747 : 0 : fTyp = 1.0;
4748 : 93 : SCCOL nCol1 = 0;
4749 : 93 : SCROW nRow1 = 0;
4750 : 93 : SCTAB nTab1 = 0;
4751 : 93 : SCCOL nCol2 = 0;
4752 : 93 : SCROW nRow2 = 0;
4753 : 93 : SCTAB nTab2 = 0;
4754 : 93 : ScMatrixRef pMatSrc = NULL;
4755 : :
4756 [ + - - ]: 93 : switch (GetStackType())
[ + - ]
4757 : : {
4758 : : case svDoubleRef:
4759 : : {
4760 [ + - ]: 93 : PopDoubleRef(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
4761 [ + - ][ - + ]: 93 : if (nTab1 != nTab2 || (nCol1 != nCol2 && nRow1 != nRow2))
[ # # ]
4762 : : {
4763 [ # # ]: 0 : PushIllegalParameter();
4764 : : return;
4765 : : }
4766 : : }
4767 : 93 : break;
4768 : : case svMatrix:
4769 : : case svExternalDoubleRef:
4770 : : {
4771 [ # # ][ # # ]: 0 : if (GetStackType() == svMatrix)
4772 [ # # ][ # # ]: 0 : pMatSrc = PopMatrix();
[ # # ]
4773 : : else
4774 [ # # ]: 0 : PopExternalDoubleRef(pMatSrc);
4775 : :
4776 [ # # ]: 0 : if (!pMatSrc)
4777 : : {
4778 [ # # ]: 0 : PushIllegalParameter();
4779 : : return;
4780 : : }
4781 : : }
4782 : 0 : break;
4783 : : default:
4784 [ # # ]: 0 : PushIllegalParameter();
4785 : : return;
4786 : : }
4787 : :
4788 [ + - ]: 93 : if (nGlobalError == 0)
4789 : : {
4790 : : double fVal;
4791 [ + - ]: 93 : String sStr;
4792 [ + - ]: 93 : ScQueryParam rParam;
4793 : 93 : rParam.nCol1 = nCol1;
4794 : 93 : rParam.nRow1 = nRow1;
4795 : 93 : rParam.nCol2 = nCol2;
4796 : 93 : rParam.nTab = nTab1;
4797 : :
4798 [ + - ]: 93 : ScQueryEntry& rEntry = rParam.GetEntry(0);
4799 [ + - ]: 93 : ScQueryEntry::Item& rItem = rEntry.GetQueryItem();
4800 : 93 : rEntry.bDoQuery = true;
4801 [ + + ]: 93 : if (fTyp < 0.0)
4802 : 48 : rEntry.eOp = SC_GREATER_EQUAL;
4803 [ + - ]: 45 : else if (fTyp > 0.0)
4804 : 45 : rEntry.eOp = SC_LESS_EQUAL;
4805 [ + - ][ - - : 93 : switch ( GetStackType() )
+ - - -
- ]
4806 : : {
4807 : : case svDouble:
4808 : : {
4809 [ # # ]: 0 : fVal = GetDouble();
4810 : 0 : rItem.mfVal = fVal;
4811 : 0 : rItem.meType = ScQueryEntry::ByValue;
4812 : : }
4813 : 0 : break;
4814 : : case svString:
4815 : : {
4816 [ # # ][ # # ]: 0 : sStr = GetString();
4817 : 0 : rItem.meType = ScQueryEntry::ByString;
4818 [ # # ]: 0 : rItem.maString = sStr;
4819 : : }
4820 : 0 : break;
4821 : : case svDoubleRef :
4822 : : case svSingleRef :
4823 : : {
4824 : 93 : ScAddress aAdr;
4825 [ - + ][ + - ]: 93 : if ( !PopDoubleRefOrSingleRef( aAdr ) )
4826 : : {
4827 [ # # ]: 0 : PushInt(0);
4828 : : return ;
4829 : : }
4830 [ + - ]: 93 : ScBaseCell* pCell = GetCell( aAdr );
4831 [ + - ][ + + ]: 93 : if (HasCellValueData(pCell))
4832 : : {
4833 [ + - ]: 72 : fVal = GetCellValue( aAdr, pCell );
4834 : 72 : rItem.meType = ScQueryEntry::ByValue;
4835 : 72 : rItem.mfVal = fVal;
4836 : : }
4837 : : else
4838 : : {
4839 [ + - ]: 21 : GetCellString(sStr, pCell);
4840 : 21 : rItem.meType = ScQueryEntry::ByString;
4841 [ + - ]: 21 : rItem.maString = sStr;
4842 : : }
4843 : : }
4844 : 93 : break;
4845 : : case svExternalSingleRef:
4846 : : {
4847 : 0 : ScExternalRefCache::TokenRef pToken;
4848 [ # # ]: 0 : PopExternalSingleRef(pToken);
4849 [ # # ]: 0 : if (!pToken)
4850 : : {
4851 [ # # ]: 0 : PushInt(0);
4852 : : return;
4853 : : }
4854 [ # # ]: 0 : if (pToken->GetType() == svDouble)
4855 : : {
4856 : 0 : rItem.meType = ScQueryEntry::ByValue;
4857 [ # # ]: 0 : rItem.mfVal = pToken->GetDouble();
4858 : : }
4859 : : else
4860 : : {
4861 : 0 : rItem.meType = ScQueryEntry::ByString;
4862 [ # # ][ # # ]: 0 : rItem.maString = pToken->GetString();
4863 [ # # ][ # # ]: 0 : }
4864 : : }
4865 : 0 : break;
4866 : : case svExternalDoubleRef:
4867 : : // TODO: Implement this.
4868 [ # # ]: 0 : PushIllegalParameter();
4869 : : return;
4870 : : break;
4871 : : case svMatrix :
4872 : : {
4873 [ # # ]: 0 : String aStr;
4874 : : ScMatValType nType = GetDoubleOrStringFromMatrix(
4875 [ # # ]: 0 : rItem.mfVal, aStr);
4876 [ # # ]: 0 : rItem.maString = aStr;
4877 : 0 : rItem.meType = ScMatrix::IsNonValueType(nType) ?
4878 [ # # ][ # # ]: 0 : ScQueryEntry::ByString : ScQueryEntry::ByValue;
4879 : : }
4880 : 0 : break;
4881 : : default:
4882 : : {
4883 [ # # ]: 0 : PushIllegalParameter();
4884 : : return;
4885 : : }
4886 : : }
4887 [ + + ]: 93 : if (rItem.meType == ScQueryEntry::ByString)
4888 : : {
4889 : 21 : bool bIsVBAMode = false;
4890 [ + - ]: 21 : if ( pDok )
4891 [ + - ]: 21 : bIsVBAMode = pDok->IsInVBAMode();
4892 : :
4893 : : // #TODO handle MSO wildcards
4894 [ - + ]: 21 : if ( bIsVBAMode )
4895 : 0 : rParam.bRegExp = false;
4896 : : else
4897 [ + - ][ + - ]: 21 : rParam.bRegExp = MayBeRegExp(rEntry.GetQueryItem().maString, pDok);
4898 : : }
4899 : :
4900 [ - + ]: 93 : if (pMatSrc) // The source data is matrix array.
4901 : : {
4902 : : SCSIZE nC, nR;
4903 [ # # ]: 0 : pMatSrc->GetDimensions( nC, nR);
4904 [ # # ][ # # ]: 0 : if (nC > 1 && nR > 1)
4905 : : {
4906 : : // The source matrix must be a vector.
4907 [ # # ]: 0 : PushIllegalParameter();
4908 : : return;
4909 : : }
4910 [ # # ]: 0 : SCSIZE nMatCount = (nC == 1) ? nR : nC;
4911 : 0 : VectorMatrixAccessor aMatAcc(*pMatSrc, nC == 1);
4912 : :
4913 : : // simple serial search for equality mode (source data doesn't
4914 : : // need to be sorted).
4915 : :
4916 [ # # ]: 0 : if (rEntry.eOp == SC_EQUAL)
4917 : : {
4918 [ # # ]: 0 : for (SCSIZE i = 0; i < nMatCount; ++i)
4919 : : {
4920 [ # # ][ # # ]: 0 : if (lcl_CompareMatrix2Query( i, aMatAcc, rEntry) == 0)
4921 : : {
4922 [ # # ]: 0 : PushDouble(i+1); // found !
4923 : : return;
4924 : : }
4925 : : }
4926 [ # # ]: 0 : PushNA(); // not found
4927 : : return;
4928 : : }
4929 : :
4930 : : // binary search for non-equality mode (the source data is
4931 : : // assumed to be sorted).
4932 : :
4933 : 0 : bool bAscOrder = (rEntry.eOp == SC_LESS_EQUAL);
4934 : 0 : SCSIZE nFirst = 0, nLast = nMatCount-1, nHitIndex = 0;
4935 [ # # ]: 0 : for (SCSIZE nLen = nLast-nFirst; nLen > 0; nLen = nLast-nFirst)
4936 : : {
4937 : 0 : SCSIZE nMid = nFirst + nLen/2;
4938 [ # # ]: 0 : sal_Int32 nCmp = lcl_CompareMatrix2Query( nMid, aMatAcc, rEntry);
4939 [ # # ]: 0 : if (nCmp == 0)
4940 : : {
4941 : : // exact match. find the last item with the same value.
4942 [ # # ]: 0 : lcl_GetLastMatch( nMid, aMatAcc, nMatCount, !bAscOrder);
4943 [ # # ]: 0 : PushDouble( nMid+1);
4944 : : return;
4945 : : }
4946 : :
4947 [ # # ]: 0 : if (nLen == 1) // first and last items are next to each other.
4948 : : {
4949 [ # # ]: 0 : if (nCmp < 0)
4950 [ # # ]: 0 : nHitIndex = bAscOrder ? nLast : nFirst;
4951 : : else
4952 [ # # ]: 0 : nHitIndex = bAscOrder ? nFirst : nLast;
4953 : : break;
4954 : : }
4955 : :
4956 [ # # ]: 0 : if (nCmp < 0)
4957 : : {
4958 [ # # ]: 0 : if (bAscOrder)
4959 : 0 : nFirst = nMid;
4960 : : else
4961 : 0 : nLast = nMid;
4962 : : }
4963 : : else
4964 : : {
4965 [ # # ]: 0 : if (bAscOrder)
4966 : 0 : nLast = nMid;
4967 : : else
4968 : 0 : nFirst = nMid;
4969 : : }
4970 : : }
4971 : :
4972 [ # # ]: 0 : if (nHitIndex == nMatCount-1) // last item
4973 : : {
4974 [ # # ]: 0 : sal_Int32 nCmp = lcl_CompareMatrix2Query( nHitIndex, aMatAcc, rEntry);
4975 [ # # ][ # # ]: 0 : if ((bAscOrder && nCmp <= 0) || (!bAscOrder && nCmp >= 0))
[ # # ][ # # ]
4976 : : {
4977 : : // either the last item is an exact match or the real
4978 : : // hit is beyond the last item.
4979 [ # # ]: 0 : PushDouble( nHitIndex+1);
4980 : : return;
4981 : : }
4982 : : }
4983 : :
4984 [ # # ]: 0 : if (nHitIndex > 0) // valid hit must be 2nd item or higher
4985 : : {
4986 [ # # ]: 0 : PushDouble( nHitIndex); // non-exact match
4987 : : return;
4988 : : }
4989 : :
4990 [ # # ]: 0 : PushNA();
4991 : : return;
4992 : : }
4993 : :
4994 : 93 : SCCOLROW nDelta = 0;
4995 [ + - ]: 93 : if (nCol1 == nCol2)
4996 : : { // search row in column
4997 : 93 : rParam.nRow2 = nRow2;
4998 : 93 : rEntry.nField = nCol1;
4999 : 93 : ScAddress aResultPos( nCol1, nRow1, nTab1);
5000 [ + + ][ + - ]: 93 : if (!LookupQueryWithCache( aResultPos, rParam))
5001 : : {
5002 [ + - ]: 12 : PushNA();
5003 : : return;
5004 : : }
5005 : 93 : nDelta = aResultPos.Row() - nRow1;
5006 : : }
5007 : : else
5008 : : { // search column in row
5009 : : SCCOL nC;
5010 : 0 : rParam.bByRow = false;
5011 : 0 : rParam.nRow2 = nRow1;
5012 : 0 : rEntry.nField = nCol1;
5013 [ # # ]: 0 : ScQueryCellIterator aCellIter(pDok, nTab1, rParam, false);
5014 : : // Advance Entry.nField in Iterator if column changed
5015 : 0 : aCellIter.SetAdvanceQueryParamEntryField( true );
5016 [ # # ]: 0 : if (fTyp == 0.0)
5017 : : { // EQUAL
5018 [ # # ][ # # ]: 0 : if ( aCellIter.GetFirst() )
5019 : 0 : nC = aCellIter.GetCol();
5020 : : else
5021 : : {
5022 [ # # ]: 0 : PushNA();
5023 : : return;
5024 : : }
5025 : : }
5026 : : else
5027 : : { // <= or >=
5028 : : SCROW nR;
5029 [ # # ][ # # ]: 0 : if ( !aCellIter.FindEqualOrSortedLastInRange( nC, nR ) )
5030 : : {
5031 [ # # ]: 0 : PushNA();
5032 : : return;
5033 : : }
5034 : : }
5035 [ # # ][ # # ]: 0 : nDelta = nC - nCol1;
5036 : : }
5037 [ + - ][ + - ]: 93 : PushDouble((double) (nDelta + 1));
[ + + ][ + - ]
[ + + ]
5038 : : }
5039 : : else
5040 [ # # ][ + - ]: 93 : PushIllegalParameter();
[ + + ]
5041 : : }
5042 : : }
5043 : :
5044 : :
5045 : 3 : void ScInterpreter::ScCountEmptyCells()
5046 : : {
5047 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScCountEmptyCells" );
5048 [ + - ]: 3 : if ( MustHaveParamCount( GetByte(), 1 ) )
5049 : : {
5050 : 3 : sal_uLong nMaxCount = 0, nCount = 0;
5051 : : CellType eCellType;
5052 [ - + - ]: 3 : switch (GetStackType())
5053 : : {
5054 : : case svSingleRef :
5055 : : {
5056 : 0 : nMaxCount = 1;
5057 : 0 : ScAddress aAdr;
5058 [ # # ]: 0 : PopSingleRef( aAdr );
5059 [ # # ]: 0 : eCellType = GetCellType( GetCell( aAdr ) );
5060 [ # # ][ # # ]: 0 : if (eCellType != CELLTYPE_NONE && eCellType != CELLTYPE_NOTE)
5061 : 0 : nCount = 1;
5062 : : }
5063 : 0 : break;
5064 : : case svDoubleRef :
5065 : : case svRefList :
5066 : : {
5067 : 3 : ScRange aRange;
5068 : 3 : short nParam = 1;
5069 : 3 : size_t nRefInList = 0;
5070 [ + + ]: 6 : while (nParam-- > 0)
5071 : : {
5072 [ + - ]: 3 : PopDoubleRef( aRange, nParam, nRefInList);
5073 : : nMaxCount +=
5074 : 3 : static_cast<sal_uLong>(aRange.aEnd.Row() - aRange.aStart.Row() + 1) *
5075 : 3 : static_cast<sal_uLong>(aRange.aEnd.Col() - aRange.aStart.Col() + 1) *
5076 : 3 : static_cast<sal_uLong>(aRange.aEnd.Tab() - aRange.aStart.Tab() + 1);
5077 : : ScBaseCell* pCell;
5078 [ + - ]: 3 : ScCellIterator aDocIter( pDok, aRange, glSubTotal);
5079 [ + - ][ + - ]: 3 : if ( (pCell = aDocIter.GetFirst()) != NULL )
5080 : : {
5081 [ + - ][ + + ]: 93 : do
5082 : : {
5083 [ + - ][ + - ]: 93 : if ((eCellType = pCell->GetCellType()) != CELLTYPE_NONE
[ + - ]
5084 : : && eCellType != CELLTYPE_NOTE)
5085 : 93 : nCount++;
5086 : : } while ( (pCell = aDocIter.GetNext()) != NULL );
5087 : : }
5088 : : }
5089 : : }
5090 : 3 : break;
5091 : 0 : default : SetError(errIllegalParameter); break;
5092 : : }
5093 : 3 : PushDouble(nMaxCount - nCount);
5094 : : }
5095 : 3 : }
5096 : :
5097 : :
5098 : 69 : void ScInterpreter::ScCountIf()
5099 : : {
5100 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScCountIf" );
5101 [ + - ]: 69 : if ( MustHaveParamCount( GetByte(), 2 ) )
5102 : : {
5103 [ + - ]: 69 : String rString;
5104 : 69 : double fVal = 0.0;
5105 : 69 : bool bIsString = true;
5106 [ + - ]: 69 : switch ( GetStackType() )
[ - - + + ]
5107 : : {
5108 : : case svDoubleRef :
5109 : : case svSingleRef :
5110 : : {
5111 : 0 : ScAddress aAdr;
5112 [ # # ][ # # ]: 0 : if ( !PopDoubleRefOrSingleRef( aAdr ) )
5113 : : {
5114 [ # # ]: 0 : PushInt(0);
5115 : : return ;
5116 : : }
5117 [ # # ]: 0 : ScBaseCell* pCell = GetCell( aAdr );
5118 [ # # # # ]: 0 : switch ( GetCellType( pCell ) )
5119 : : {
5120 : : case CELLTYPE_VALUE :
5121 [ # # ]: 0 : fVal = GetCellValue( aAdr, pCell );
5122 : 0 : bIsString = false;
5123 : 0 : break;
5124 : : case CELLTYPE_FORMULA :
5125 [ # # ][ # # ]: 0 : if( ((ScFormulaCell*)pCell)->IsValue() )
[ # # ]
5126 : : {
5127 [ # # ]: 0 : fVal = GetCellValue( aAdr, pCell );
5128 : 0 : bIsString = false;
5129 : : }
5130 : : else
5131 [ # # ]: 0 : GetCellString(rString, pCell);
5132 : 0 : break;
5133 : : case CELLTYPE_STRING :
5134 : : case CELLTYPE_EDIT :
5135 [ # # ]: 0 : GetCellString(rString, pCell);
5136 : 0 : break;
5137 : : default:
5138 : 0 : fVal = 0.0;
5139 : 0 : bIsString = false;
5140 : : }
5141 : : }
5142 : 0 : break;
5143 : : case svMatrix:
5144 : : case svExternalSingleRef:
5145 : : case svExternalDoubleRef:
5146 : : {
5147 : : ScMatValType nType = GetDoubleOrStringFromMatrix( fVal,
5148 [ # # ]: 0 : rString);
5149 : 0 : bIsString = ScMatrix::IsNonValueType( nType);
5150 : : }
5151 : 0 : break;
5152 : : case svString:
5153 [ + - ][ + - ]: 36 : rString = GetString();
5154 : 36 : break;
5155 : : default:
5156 : : {
5157 [ + - ]: 33 : fVal = GetDouble();
5158 : 33 : bIsString = false;
5159 : : }
5160 : : }
5161 : 69 : double fSum = 0.0;
5162 : 69 : short nParam = 1;
5163 : 69 : size_t nRefInList = 0;
5164 [ + + ]: 138 : while (nParam-- > 0)
5165 : : {
5166 : : SCCOL nCol1;
5167 : : SCROW nRow1;
5168 : : SCTAB nTab1;
5169 : : SCCOL nCol2;
5170 : : SCROW nRow2;
5171 : : SCTAB nTab2;
5172 : 69 : ScMatrixRef pQueryMatrix;
5173 [ + + - - ]: 69 : switch ( GetStackType() )
[ + - ]
5174 : : {
5175 : : case svDoubleRef :
5176 : : case svRefList :
5177 : : {
5178 : 66 : ScRange aRange;
5179 [ + - ]: 66 : PopDoubleRef( aRange, nParam, nRefInList);
5180 : 66 : aRange.GetVars( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
5181 : : }
5182 : 66 : break;
5183 : : case svSingleRef :
5184 [ + - ]: 3 : PopSingleRef( nCol1, nRow1, nTab1 );
5185 : 3 : nCol2 = nCol1;
5186 : 3 : nRow2 = nRow1;
5187 : 3 : nTab2 = nTab1;
5188 : 3 : break;
5189 : : case svMatrix:
5190 : : case svExternalSingleRef:
5191 : : case svExternalDoubleRef:
5192 : : {
5193 [ # # ][ # # ]: 0 : pQueryMatrix = GetMatrix();
[ # # ]
5194 [ # # ]: 0 : if (!pQueryMatrix)
5195 : : {
5196 [ # # ]: 0 : PushIllegalParameter();
5197 : : return;
5198 : : }
5199 : 0 : nCol1 = 0;
5200 : 0 : nRow1 = 0;
5201 : 0 : nTab1 = 0;
5202 : : SCSIZE nC, nR;
5203 [ # # ]: 0 : pQueryMatrix->GetDimensions( nC, nR);
5204 : 0 : nCol2 = static_cast<SCCOL>(nC - 1);
5205 : 0 : nRow2 = static_cast<SCROW>(nR - 1);
5206 : 0 : nTab2 = 0;
5207 : : }
5208 : 0 : break;
5209 : : default:
5210 [ # # ]: 0 : PushIllegalParameter();
5211 : : return ;
5212 : : }
5213 [ - + ]: 69 : if ( nTab1 != nTab2 )
5214 : : {
5215 [ # # ]: 0 : PushIllegalParameter();
5216 : : return;
5217 : : }
5218 [ - + ]: 69 : if (nCol1 > nCol2)
5219 : : {
5220 [ # # ]: 0 : PushIllegalParameter();
5221 : : return;
5222 : : }
5223 [ + - ]: 69 : if (nGlobalError == 0)
5224 : : {
5225 [ + - ]: 69 : ScQueryParam rParam;
5226 : 69 : rParam.nRow1 = nRow1;
5227 : 69 : rParam.nRow2 = nRow2;
5228 : :
5229 [ + - ]: 69 : ScQueryEntry& rEntry = rParam.GetEntry(0);
5230 [ + - ]: 69 : ScQueryEntry::Item& rItem = rEntry.GetQueryItem();
5231 : 69 : rEntry.bDoQuery = true;
5232 [ + + ]: 69 : if (!bIsString)
5233 : : {
5234 : 33 : rItem.meType = ScQueryEntry::ByValue;
5235 : 33 : rItem.mfVal = fVal;
5236 : 33 : rEntry.eOp = SC_EQUAL;
5237 : : }
5238 : : else
5239 : : {
5240 [ + - ][ + - ]: 36 : rParam.FillInExcelSyntax(rString, 0);
5241 : 36 : sal_uInt32 nIndex = 0;
5242 : : bool bNumber = pFormatter->IsNumberFormat(
5243 [ + - ][ + - ]: 36 : rItem.maString, nIndex, rItem.mfVal);
[ + - ]
5244 [ + + ]: 36 : rItem.meType = bNumber ? ScQueryEntry::ByValue : ScQueryEntry::ByString;
5245 [ + + ]: 36 : if (rItem.meType == ScQueryEntry::ByString)
5246 [ + - ]: 36 : rParam.bRegExp = MayBeRegExp(rItem.maString, pDok);
5247 : : }
5248 : 69 : rParam.nCol1 = nCol1;
5249 : 69 : rParam.nCol2 = nCol2;
5250 : 69 : rEntry.nField = nCol1;
5251 [ - + ]: 69 : if (pQueryMatrix)
5252 : : {
5253 : : // Never case-sensitive.
5254 [ # # ]: 0 : ScCompareOptions aOptions( pDok, rEntry, rParam.bRegExp);
5255 [ # # ]: 0 : ScMatrixRef pResultMatrix = QueryMat( pQueryMatrix, aOptions);
5256 [ # # ][ # # ]: 0 : if (nGlobalError || !pResultMatrix)
[ # # ]
5257 : : {
5258 [ # # ]: 0 : PushIllegalParameter();
5259 : : return;
5260 : : }
5261 : :
5262 [ # # ]: 0 : SCSIZE nSize = pResultMatrix->GetElementCount();
5263 [ # # ]: 0 : for (SCSIZE nIndex = 0; nIndex < nSize; ++nIndex)
5264 : : {
5265 [ # # ][ # # ]: 0 : if (pResultMatrix->IsValue( nIndex) &&
[ # # ][ # # ]
5266 [ # # ]: 0 : pResultMatrix->GetDouble( nIndex))
5267 : 0 : ++fSum;
5268 [ # # ][ # # ]: 0 : }
[ # # ][ # # ]
5269 : : }
5270 : : else
5271 : : {
5272 [ + - ]: 69 : ScQueryCellIterator aCellIter(pDok, nTab1, rParam, false);
5273 : : // Keep Entry.nField in iterator on column change
5274 : 69 : aCellIter.SetAdvanceQueryParamEntryField( true );
5275 [ + + ][ + - ]: 69 : if ( aCellIter.GetFirst() )
5276 : : {
5277 [ + + ]: 204 : do
5278 : : {
5279 : 204 : fSum++;
5280 [ + - ]: 204 : } while ( aCellIter.GetNext() );
5281 [ + - ]: 69 : }
5282 [ + - ][ + - ]: 69 : }
5283 : : }
5284 : : else
5285 : : {
5286 [ # # ]: 0 : PushIllegalParameter();
5287 : : return;
5288 : : }
5289 [ + - ][ + - ]: 69 : }
5290 [ + - ][ + - ]: 69 : PushDouble(fSum);
[ + - ]
5291 : : }
5292 : : }
5293 : :
5294 : :
5295 : 0 : void ScInterpreter::ScSumIf()
5296 : : {
5297 : 0 : sal_uInt8 nParamCount = GetByte();
5298 [ # # ][ # # ]: 0 : if ( !MustHaveParamCount( nParamCount, 2, 3 ) )
5299 : : return;
5300 : :
5301 : 0 : SCCOL nCol3 = 0;
5302 : 0 : SCROW nRow3 = 0;
5303 : 0 : SCTAB nTab3 = 0;
5304 : :
5305 : 0 : ScMatrixRef pSumExtraMatrix;
5306 : 0 : bool bSumExtraRange = (nParamCount == 3);
5307 [ # # ]: 0 : if (bSumExtraRange)
5308 : : {
5309 : : // Save only the upperleft cell in case of cell range. The geometry
5310 : : // of the 3rd parameter is taken from the 1st parameter.
5311 : :
5312 [ # # ][ # # : 0 : switch ( GetStackType() )
# # # # ]
5313 : : {
5314 : : case svDoubleRef :
5315 : : {
5316 : 0 : SCCOL nColJunk = 0;
5317 : 0 : SCROW nRowJunk = 0;
5318 : 0 : SCTAB nTabJunk = 0;
5319 [ # # ]: 0 : PopDoubleRef( nCol3, nRow3, nTab3, nColJunk, nRowJunk, nTabJunk );
5320 [ # # ]: 0 : if ( nTabJunk != nTab3 )
5321 : : {
5322 [ # # ]: 0 : PushIllegalParameter();
5323 : : return;
5324 : : }
5325 : : }
5326 : 0 : break;
5327 : : case svSingleRef :
5328 [ # # ]: 0 : PopSingleRef( nCol3, nRow3, nTab3 );
5329 : 0 : break;
5330 : : case svMatrix:
5331 [ # # ][ # # ]: 0 : pSumExtraMatrix = PopMatrix();
[ # # ]
5332 : : //! nCol3, nRow3, nTab3 remain 0
5333 : 0 : break;
5334 : : case svExternalSingleRef:
5335 : : {
5336 [ # # ][ # # ]: 0 : pSumExtraMatrix = new ScMatrix(1, 1, 0.0);
[ # # ]
5337 : 0 : ScExternalRefCache::TokenRef pToken;
5338 [ # # ]: 0 : PopExternalSingleRef(pToken);
5339 [ # # ]: 0 : if (!pToken)
5340 : : {
5341 [ # # ]: 0 : PushIllegalParameter();
5342 : : return;
5343 : : }
5344 : :
5345 [ # # ]: 0 : if (pToken->GetType() == svDouble)
5346 [ # # ][ # # ]: 0 : pSumExtraMatrix->PutDouble(pToken->GetDouble(), 0, 0);
5347 : : else
5348 [ # # ][ # # ]: 0 : pSumExtraMatrix->PutString(pToken->GetString(), 0, 0);
[ # # ][ # # ]
[ # # ]
5349 : : }
5350 : 0 : break;
5351 : : case svExternalDoubleRef:
5352 [ # # ]: 0 : PopExternalDoubleRef(pSumExtraMatrix);
5353 : 0 : break;
5354 : : default:
5355 [ # # ]: 0 : PushIllegalParameter();
5356 : : return ;
5357 : : }
5358 : : }
5359 : :
5360 [ # # ]: 0 : String aString;
5361 : 0 : double fVal = 0.0;
5362 : 0 : bool bIsString = true;
5363 [ # # ][ # # : 0 : switch ( GetStackType() )
# # # ]
5364 : : {
5365 : : case svDoubleRef :
5366 : : case svSingleRef :
5367 : : {
5368 : 0 : ScAddress aAdr;
5369 [ # # ][ # # ]: 0 : if ( !PopDoubleRefOrSingleRef( aAdr ) )
5370 : : {
5371 [ # # ]: 0 : PushInt(0);
5372 : : return ;
5373 : : }
5374 [ # # ]: 0 : ScBaseCell* pCell = GetCell( aAdr );
5375 [ # # # # ]: 0 : switch ( GetCellType( pCell ) )
5376 : : {
5377 : : case CELLTYPE_VALUE :
5378 [ # # ]: 0 : fVal = GetCellValue( aAdr, pCell );
5379 : 0 : bIsString = false;
5380 : 0 : break;
5381 : : case CELLTYPE_FORMULA :
5382 [ # # ][ # # ]: 0 : if( ((ScFormulaCell*)pCell)->IsValue() )
[ # # ]
5383 : : {
5384 [ # # ]: 0 : fVal = GetCellValue( aAdr, pCell );
5385 : 0 : bIsString = false;
5386 : : }
5387 : : else
5388 [ # # ]: 0 : GetCellString(aString, pCell);
5389 : 0 : break;
5390 : : case CELLTYPE_STRING :
5391 : : case CELLTYPE_EDIT :
5392 [ # # ]: 0 : GetCellString(aString, pCell);
5393 : 0 : break;
5394 : : default:
5395 : 0 : fVal = 0.0;
5396 : 0 : bIsString = false;
5397 : : }
5398 : : }
5399 : 0 : break;
5400 : : case svString:
5401 [ # # ][ # # ]: 0 : aString = GetString();
5402 : 0 : break;
5403 : : case svMatrix :
5404 : : case svExternalDoubleRef:
5405 : : {
5406 [ # # ]: 0 : ScMatValType nType = GetDoubleOrStringFromMatrix(fVal, aString);
5407 : 0 : bIsString = ScMatrix::IsNonValueType( nType);
5408 : : }
5409 : 0 : break;
5410 : : case svExternalSingleRef:
5411 : : {
5412 : 0 : ScExternalRefCache::TokenRef pToken;
5413 [ # # ]: 0 : PopExternalSingleRef(pToken);
5414 [ # # ]: 0 : if (pToken)
5415 : : {
5416 [ # # ]: 0 : if (pToken->GetType() == svDouble)
5417 : : {
5418 [ # # ]: 0 : fVal = pToken->GetDouble();
5419 : 0 : bIsString = false;
5420 : : }
5421 : : else
5422 [ # # ][ # # ]: 0 : aString = pToken->GetString();
5423 [ # # ]: 0 : }
5424 : : }
5425 : 0 : break;
5426 : : default:
5427 : : {
5428 [ # # ]: 0 : fVal = GetDouble();
5429 : 0 : bIsString = false;
5430 : : }
5431 : : }
5432 : :
5433 : 0 : double fSum = 0.0;
5434 : 0 : double fMem = 0.0;
5435 : 0 : bool bNull = true;
5436 : 0 : short nParam = 1;
5437 : 0 : size_t nRefInList = 0;
5438 [ # # ]: 0 : while (nParam-- > 0)
5439 : : {
5440 : : SCCOL nCol1;
5441 : : SCROW nRow1;
5442 : : SCTAB nTab1;
5443 : : SCCOL nCol2;
5444 : : SCROW nRow2;
5445 : : SCTAB nTab2;
5446 : 0 : ScMatrixRef pQueryMatrix;
5447 [ # # # # : 0 : switch ( GetStackType() )
# ][ # # ]
5448 : : {
5449 : : case svRefList :
5450 [ # # ]: 0 : if (bSumExtraRange)
5451 : : {
5452 [ # # ]: 0 : PushIllegalParameter();
5453 : : return;
5454 : : }
5455 : : else
5456 : : {
5457 : 0 : ScRange aRange;
5458 [ # # ]: 0 : PopDoubleRef( aRange, nParam, nRefInList);
5459 : 0 : aRange.GetVars( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
5460 : : }
5461 : 0 : break;
5462 : : case svDoubleRef :
5463 [ # # ]: 0 : PopDoubleRef( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 );
5464 : 0 : break;
5465 : : case svSingleRef :
5466 [ # # ]: 0 : PopSingleRef( nCol1, nRow1, nTab1 );
5467 : 0 : nCol2 = nCol1;
5468 : 0 : nRow2 = nRow1;
5469 : 0 : nTab2 = nTab1;
5470 : 0 : break;
5471 : : case svMatrix:
5472 : : case svExternalSingleRef:
5473 : : case svExternalDoubleRef:
5474 : : {
5475 [ # # ][ # # ]: 0 : pQueryMatrix = GetMatrix();
[ # # ]
5476 [ # # ]: 0 : if (!pQueryMatrix)
5477 : : {
5478 [ # # ]: 0 : PushIllegalParameter();
5479 : : return;
5480 : : }
5481 : 0 : nCol1 = 0;
5482 : 0 : nRow1 = 0;
5483 : 0 : nTab1 = 0;
5484 : : SCSIZE nC, nR;
5485 [ # # ]: 0 : pQueryMatrix->GetDimensions( nC, nR);
5486 : 0 : nCol2 = static_cast<SCCOL>(nC - 1);
5487 : 0 : nRow2 = static_cast<SCROW>(nR - 1);
5488 : 0 : nTab2 = 0;
5489 : : }
5490 : 0 : break;
5491 : : default:
5492 [ # # ]: 0 : PushIllegalParameter();
5493 : : return ;
5494 : : }
5495 [ # # ]: 0 : if ( nTab1 != nTab2 )
5496 : : {
5497 [ # # ]: 0 : PushIllegalArgument();
5498 : : return;
5499 : : }
5500 : :
5501 [ # # ]: 0 : if (bSumExtraRange)
5502 : : {
5503 : : // Take the range geometry of the 1st parameter and apply it to
5504 : : // the 3rd. If parts of the resulting range would point outside
5505 : : // the sheet, don't complain but silently ignore and simply cut
5506 : : // them away, this is what Xcl does :-/
5507 : :
5508 : : // For the cut-away part we also don't need to determine the
5509 : : // criteria match, so shrink the source range accordingly,
5510 : : // instead of the result range.
5511 : 0 : SCCOL nColDelta = nCol2 - nCol1;
5512 : 0 : SCROW nRowDelta = nRow2 - nRow1;
5513 : : SCCOL nMaxCol;
5514 : : SCROW nMaxRow;
5515 [ # # ]: 0 : if (pSumExtraMatrix)
5516 : : {
5517 : : SCSIZE nC, nR;
5518 [ # # ]: 0 : pSumExtraMatrix->GetDimensions( nC, nR);
5519 : 0 : nMaxCol = static_cast<SCCOL>(nC - 1);
5520 : 0 : nMaxRow = static_cast<SCROW>(nR - 1);
5521 : : }
5522 : : else
5523 : : {
5524 : 0 : nMaxCol = MAXCOL;
5525 : 0 : nMaxRow = MAXROW;
5526 : : }
5527 [ # # ]: 0 : if (nCol3 + nColDelta > nMaxCol)
5528 : : {
5529 : 0 : SCCOL nNewDelta = nMaxCol - nCol3;
5530 : 0 : nCol2 = nCol1 + nNewDelta;
5531 : : }
5532 : :
5533 [ # # ]: 0 : if (nRow3 + nRowDelta > nMaxRow)
5534 : : {
5535 : 0 : SCROW nNewDelta = nMaxRow - nRow3;
5536 : 0 : nRow2 = nRow1 + nNewDelta;
5537 : : }
5538 : : }
5539 : : else
5540 : : {
5541 : 0 : nCol3 = nCol1;
5542 : 0 : nRow3 = nRow1;
5543 : 0 : nTab3 = nTab1;
5544 : : }
5545 : :
5546 [ # # ]: 0 : if (nGlobalError == 0)
5547 : : {
5548 [ # # ]: 0 : ScQueryParam rParam;
5549 : 0 : rParam.nRow1 = nRow1;
5550 : 0 : rParam.nRow2 = nRow2;
5551 : :
5552 [ # # ]: 0 : ScQueryEntry& rEntry = rParam.GetEntry(0);
5553 [ # # ]: 0 : ScQueryEntry::Item& rItem = rEntry.GetQueryItem();
5554 : 0 : rEntry.bDoQuery = true;
5555 [ # # ]: 0 : if (!bIsString)
5556 : : {
5557 : 0 : rItem.meType = ScQueryEntry::ByValue;
5558 : 0 : rItem.mfVal = fVal;
5559 : 0 : rEntry.eOp = SC_EQUAL;
5560 : : }
5561 : : else
5562 : : {
5563 [ # # ][ # # ]: 0 : rParam.FillInExcelSyntax(aString, 0);
5564 : 0 : sal_uInt32 nIndex = 0;
5565 : : bool bNumber = pFormatter->IsNumberFormat(
5566 [ # # ][ # # ]: 0 : rItem.maString, nIndex, rItem.mfVal);
[ # # ]
5567 [ # # ]: 0 : rItem.meType = bNumber ? ScQueryEntry::ByValue : ScQueryEntry::ByString;
5568 [ # # ]: 0 : if (rItem.meType == ScQueryEntry::ByString)
5569 [ # # ]: 0 : rParam.bRegExp = MayBeRegExp(rItem.maString, pDok);
5570 : : }
5571 : 0 : ScAddress aAdr;
5572 : 0 : aAdr.SetTab( nTab3 );
5573 : 0 : rParam.nCol1 = nCol1;
5574 : 0 : rParam.nCol2 = nCol2;
5575 : 0 : rEntry.nField = nCol1;
5576 : 0 : SCsCOL nColDiff = nCol3 - nCol1;
5577 : 0 : SCsROW nRowDiff = nRow3 - nRow1;
5578 [ # # ]: 0 : if (pQueryMatrix)
5579 : : {
5580 : : // Never case-sensitive.
5581 [ # # ]: 0 : ScCompareOptions aOptions( pDok, rEntry, rParam.bRegExp);
5582 [ # # ]: 0 : ScMatrixRef pResultMatrix = QueryMat( pQueryMatrix, aOptions);
5583 [ # # ][ # # ]: 0 : if (nGlobalError || !pResultMatrix)
[ # # ]
5584 : : {
5585 [ # # ]: 0 : PushIllegalParameter();
5586 : : return;
5587 : : }
5588 : :
5589 [ # # ]: 0 : if (pSumExtraMatrix)
5590 : : {
5591 [ # # ]: 0 : for (SCCOL nCol = nCol1; nCol <= nCol2; ++nCol)
5592 : : {
5593 [ # # ]: 0 : for (SCROW nRow = nRow1; nRow <= nRow2; ++nRow)
5594 : : {
5595 [ # # ][ # # ]: 0 : if (pResultMatrix->IsValue( nCol, nRow) &&
[ # # ][ # # ]
5596 [ # # ]: 0 : pResultMatrix->GetDouble( nCol, nRow))
5597 : : {
5598 : 0 : SCSIZE nC = nCol + nColDiff;
5599 : 0 : SCSIZE nR = nRow + nRowDiff;
5600 [ # # ][ # # ]: 0 : if (pSumExtraMatrix->IsValue( nC, nR))
5601 : : {
5602 [ # # ]: 0 : fVal = pSumExtraMatrix->GetDouble( nC, nR);
5603 [ # # ][ # # ]: 0 : if ( bNull && fVal != 0.0 )
5604 : : {
5605 : 0 : bNull = false;
5606 : 0 : fMem = fVal;
5607 : : }
5608 : : else
5609 : 0 : fSum += fVal;
5610 : : }
5611 : : }
5612 : : }
5613 : : }
5614 : : }
5615 : : else
5616 : : {
5617 [ # # ]: 0 : for (SCCOL nCol = nCol1; nCol <= nCol2; ++nCol)
5618 : : {
5619 [ # # ]: 0 : for (SCROW nRow = nRow1; nRow <= nRow2; ++nRow)
5620 : : {
5621 [ # # ][ # # ]: 0 : if (pResultMatrix->GetDouble( nCol, nRow))
5622 : : {
5623 : 0 : aAdr.SetCol( nCol + nColDiff);
5624 : 0 : aAdr.SetRow( nRow + nRowDiff);
5625 [ # # ]: 0 : ScBaseCell* pCell = GetCell( aAdr );
5626 [ # # ][ # # ]: 0 : if ( HasCellValueData(pCell) )
5627 : : {
5628 [ # # ]: 0 : fVal = GetCellValue( aAdr, pCell );
5629 [ # # ][ # # ]: 0 : if ( bNull && fVal != 0.0 )
5630 : : {
5631 : 0 : bNull = false;
5632 : 0 : fMem = fVal;
5633 : : }
5634 : : else
5635 : 0 : fSum += fVal;
5636 : : }
5637 : : }
5638 : : }
5639 : : }
5640 [ # # ][ # # ]: 0 : }
[ # # ][ # # ]
5641 : : }
5642 : : else
5643 : : {
5644 [ # # ]: 0 : ScQueryCellIterator aCellIter(pDok, nTab1, rParam, false);
5645 : : // Increment Entry.nField in iterator when switching to next column.
5646 : 0 : aCellIter.SetAdvanceQueryParamEntryField( true );
5647 [ # # ][ # # ]: 0 : if ( aCellIter.GetFirst() )
5648 : : {
5649 [ # # ]: 0 : if (pSumExtraMatrix)
5650 : : {
5651 [ # # ]: 0 : do
5652 : : {
5653 : 0 : SCSIZE nC = aCellIter.GetCol() + nColDiff;
5654 : 0 : SCSIZE nR = aCellIter.GetRow() + nRowDiff;
5655 [ # # ][ # # ]: 0 : if (pSumExtraMatrix->IsValue( nC, nR))
5656 : : {
5657 [ # # ]: 0 : fVal = pSumExtraMatrix->GetDouble( nC, nR);
5658 [ # # ][ # # ]: 0 : if ( bNull && fVal != 0.0 )
5659 : : {
5660 : 0 : bNull = false;
5661 : 0 : fMem = fVal;
5662 : : }
5663 : : else
5664 : 0 : fSum += fVal;
5665 : : }
5666 [ # # ]: 0 : } while ( aCellIter.GetNext() );
5667 : : }
5668 : : else
5669 : : {
5670 [ # # ]: 0 : do
5671 : : {
5672 : 0 : aAdr.SetCol( aCellIter.GetCol() + nColDiff);
5673 : 0 : aAdr.SetRow( aCellIter.GetRow() + nRowDiff);
5674 [ # # ]: 0 : ScBaseCell* pCell = GetCell( aAdr );
5675 [ # # ][ # # ]: 0 : if ( HasCellValueData(pCell) )
5676 : : {
5677 [ # # ]: 0 : fVal = GetCellValue( aAdr, pCell );
5678 [ # # ][ # # ]: 0 : if ( bNull && fVal != 0.0 )
5679 : : {
5680 : 0 : bNull = false;
5681 : 0 : fMem = fVal;
5682 : : }
5683 : : else
5684 : 0 : fSum += fVal;
5685 : : }
5686 [ # # ]: 0 : } while ( aCellIter.GetNext() );
5687 : : }
5688 [ # # ]: 0 : }
5689 [ # # ][ # # ]: 0 : }
5690 : : }
5691 : : else
5692 : : {
5693 [ # # ]: 0 : PushIllegalParameter();
5694 : : return;
5695 : : }
5696 [ # # ][ # # ]: 0 : }
5697 [ # # ][ # # ]: 0 : PushDouble( ::rtl::math::approxAdd( fSum, fMem ) );
[ # # ][ # # ]
[ # # ]
5698 : : }
5699 : :
5700 : :
5701 : 0 : void ScInterpreter::ScLookup()
5702 : : {
5703 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScLookup" );
5704 : 0 : sal_uInt8 nParamCount = GetByte();
5705 [ # # ][ # # ]: 0 : if ( !MustHaveParamCount( nParamCount, 2, 3 ) )
5706 : : return ;
5707 : :
5708 : 0 : ScMatrixRef pDataMat = NULL, pResMat = NULL;
5709 : 0 : SCCOL nCol1 = 0, nCol2 = 0, nResCol1 = 0, nResCol2 = 0;
5710 : 0 : SCROW nRow1 = 0, nRow2 = 0, nResRow1 = 0, nResRow2 = 0;
5711 : 0 : SCTAB nTab1 = 0, nResTab = 0;
5712 : 0 : SCSIZE nLenMajor = 0; // length of major direction
5713 : 0 : bool bVertical = true; // whether to lookup vertically or horizontally
5714 : :
5715 : : // The third parameter, result array, for double, string and single reference.
5716 : 0 : double fResVal = 0.0;
5717 [ # # ]: 0 : String aResStr;
5718 : 0 : ScAddress aResAdr;
5719 : 0 : StackVar eResArrayType = svUnknown;
5720 : :
5721 [ # # ]: 0 : if (nParamCount == 3)
5722 : : {
5723 [ # # ]: 0 : eResArrayType = GetStackType();
5724 [ # # # # : 0 : switch (eResArrayType)
# # ]
5725 : : {
5726 : : case svDoubleRef:
5727 : : {
5728 : : SCTAB nTabJunk;
5729 : : PopDoubleRef(nResCol1, nResRow1, nResTab,
5730 [ # # ]: 0 : nResCol2, nResRow2, nTabJunk);
5731 [ # # ][ # # ]: 0 : if (nResTab != nTabJunk ||
[ # # ]
5732 : : ((nResRow2 - nResRow1) > 0 && (nResCol2 - nResCol1) > 0))
5733 : : {
5734 : : // The result array must be a vector.
5735 [ # # ]: 0 : PushIllegalParameter();
5736 : : return;
5737 : : }
5738 : : }
5739 : 0 : break;
5740 : : case svMatrix:
5741 : : case svExternalSingleRef:
5742 : : case svExternalDoubleRef:
5743 : : {
5744 [ # # ][ # # ]: 0 : pResMat = GetMatrix();
[ # # ]
5745 [ # # ]: 0 : if (!pResMat)
5746 : : {
5747 [ # # ]: 0 : PushIllegalParameter();
5748 : : return;
5749 : : }
5750 : : SCSIZE nC, nR;
5751 [ # # ]: 0 : pResMat->GetDimensions(nC, nR);
5752 [ # # ][ # # ]: 0 : if (nC != 1 && nR != 1)
5753 : : {
5754 : : // Result matrix must be a vector.
5755 [ # # ]: 0 : PushIllegalParameter();
5756 : : return;
5757 : : }
5758 : : }
5759 : 0 : break;
5760 : : case svDouble:
5761 [ # # ]: 0 : fResVal = GetDouble();
5762 : 0 : break;
5763 : : case svString:
5764 [ # # ][ # # ]: 0 : aResStr = GetString();
5765 : 0 : break;
5766 : : case svSingleRef:
5767 [ # # ]: 0 : PopSingleRef( aResAdr );
5768 : 0 : break;
5769 : : default:
5770 [ # # ]: 0 : PushIllegalParameter();
5771 : : return;
5772 : : }
5773 : : }
5774 : :
5775 : : // For double, string and single reference.
5776 : 0 : double fDataVal = 0.0;
5777 [ # # ]: 0 : String aDataStr;
5778 : 0 : ScAddress aDataAdr;
5779 : 0 : bool bValueData = false;
5780 : :
5781 : : // Get the data-result range and also determine whether this is vertical
5782 : : // lookup or horizontal lookup.
5783 : :
5784 [ # # ]: 0 : StackVar eDataArrayType = GetStackType();
5785 [ # # # # : 0 : switch (eDataArrayType)
# # ]
5786 : : {
5787 : : case svDoubleRef:
5788 : : {
5789 : : SCTAB nTabJunk;
5790 [ # # ]: 0 : PopDoubleRef(nCol1, nRow1, nTab1, nCol2, nRow2, nTabJunk);
5791 [ # # ]: 0 : if (nTab1 != nTabJunk)
5792 : : {
5793 [ # # ]: 0 : PushIllegalParameter();
5794 : : return;
5795 : : }
5796 : 0 : bVertical = (nRow2 - nRow1) >= (nCol2 - nCol1);
5797 [ # # ]: 0 : nLenMajor = bVertical ? nRow2 - nRow1 + 1 : nCol2 - nCol1 + 1;
5798 : : }
5799 : 0 : break;
5800 : : case svMatrix:
5801 : : case svExternalSingleRef:
5802 : : case svExternalDoubleRef:
5803 : : {
5804 [ # # ][ # # ]: 0 : pDataMat = GetMatrix();
[ # # ]
5805 [ # # ]: 0 : if (!pDataMat)
5806 : : {
5807 [ # # ]: 0 : PushIllegalParameter();
5808 : : return;
5809 : : }
5810 : :
5811 : : SCSIZE nC, nR;
5812 [ # # ]: 0 : pDataMat->GetDimensions(nC, nR);
5813 : 0 : bVertical = (nR >= nC);
5814 [ # # ]: 0 : nLenMajor = bVertical ? nR : nC;
5815 : : }
5816 : 0 : break;
5817 : : case svDouble:
5818 : : {
5819 [ # # ]: 0 : fDataVal = GetDouble();
5820 : 0 : bValueData = true;
5821 : : }
5822 : 0 : break;
5823 : : case svString:
5824 : : {
5825 [ # # ][ # # ]: 0 : aDataStr = GetString();
5826 : : }
5827 : 0 : break;
5828 : : case svSingleRef:
5829 : : {
5830 [ # # ]: 0 : PopSingleRef( aDataAdr );
5831 [ # # ]: 0 : const ScBaseCell* pDataCell = GetCell( aDataAdr );
5832 [ # # ][ # # ]: 0 : if (HasCellEmptyData( pDataCell))
5833 : : {
5834 : : // Empty cells aren't found anywhere, bail out early.
5835 : 0 : SetError( NOTAVAILABLE);
5836 : : }
5837 [ # # ][ # # ]: 0 : else if (HasCellValueData( pDataCell))
5838 : : {
5839 [ # # ]: 0 : fDataVal = GetCellValue( aDataAdr, pDataCell );
5840 : 0 : bValueData = true;
5841 : : }
5842 : : else
5843 [ # # ]: 0 : GetCellString( aDataStr, pDataCell );
5844 : : }
5845 : 0 : break;
5846 : : default:
5847 : 0 : SetError( errIllegalParameter);
5848 : : }
5849 : :
5850 : :
5851 [ # # ]: 0 : if (nGlobalError)
5852 : : {
5853 [ # # ]: 0 : PushError( nGlobalError);
5854 : : return;
5855 : : }
5856 : :
5857 : : // Get the lookup value.
5858 : :
5859 [ # # ]: 0 : ScQueryParam aParam;
5860 [ # # ]: 0 : ScQueryEntry& rEntry = aParam.GetEntry(0);
5861 [ # # ][ # # ]: 0 : if ( !FillEntry(rEntry) )
5862 : : return;
5863 : :
5864 [ # # ][ # # ]: 0 : if ( eDataArrayType == svDouble || eDataArrayType == svString ||
[ # # ]
5865 : : eDataArrayType == svSingleRef )
5866 : : {
5867 : : // Delta position for a single value is always 0.
5868 : :
5869 : : // Found if data <= query, but not if query is string and found data is
5870 : : // numeric or vice versa. This is how Excel does it but doesn't
5871 : : // document it.
5872 : :
5873 : 0 : bool bFound = false;
5874 [ # # ]: 0 : ScQueryEntry::Item& rItem = rEntry.GetQueryItem();
5875 : :
5876 [ # # ]: 0 : if ( bValueData )
5877 : : {
5878 [ # # ]: 0 : if (rItem.meType == ScQueryEntry::ByString)
5879 : 0 : bFound = false;
5880 : : else
5881 : 0 : bFound = (fDataVal <= rItem.mfVal);
5882 : : }
5883 : : else
5884 : : {
5885 [ # # ]: 0 : if (rItem.meType != ScQueryEntry::ByString)
5886 : 0 : bFound = false;
5887 : : else
5888 [ # # ][ # # ]: 0 : bFound = (ScGlobal::GetCollator()->compareString(aDataStr, rItem.maString) <= 0);
[ # # ]
5889 : : }
5890 : :
5891 [ # # ]: 0 : if (!bFound)
5892 : : {
5893 [ # # ]: 0 : PushNA();
5894 : : return;
5895 : : }
5896 : :
5897 [ # # ]: 0 : if (pResMat)
5898 : : {
5899 [ # # ][ # # ]: 0 : if (pResMat->IsValue( 0, 0 ))
5900 [ # # ][ # # ]: 0 : PushDouble(pResMat->GetDouble( 0, 0 ));
5901 : : else
5902 [ # # ][ # # ]: 0 : PushString(pResMat->GetString( 0, 0 ));
[ # # ][ # # ]
5903 : : }
5904 [ # # ]: 0 : else if (nParamCount == 3)
5905 : : {
5906 [ # # # # : 0 : switch (eResArrayType)
# ]
5907 : : {
5908 : : case svDouble:
5909 [ # # ]: 0 : PushDouble( fResVal );
5910 : 0 : break;
5911 : : case svString:
5912 [ # # ]: 0 : PushString( aResStr );
5913 : 0 : break;
5914 : : case svDoubleRef:
5915 : 0 : aResAdr.Set( nResCol1, nResRow1, nResTab);
5916 : : // fallthru
5917 : : case svSingleRef:
5918 [ # # ]: 0 : PushCellResultToken( true, aResAdr, NULL, NULL);
5919 : 0 : break;
5920 : : default:
5921 : : OSL_FAIL( "ScInterpreter::ScLookup: unhandled eResArrayType, single value data");
5922 : : }
5923 : : }
5924 : : else
5925 : : {
5926 [ # # # # ]: 0 : switch (eDataArrayType)
5927 : : {
5928 : : case svDouble:
5929 [ # # ]: 0 : PushDouble( fDataVal );
5930 : 0 : break;
5931 : : case svString:
5932 [ # # ]: 0 : PushString( aDataStr );
5933 : 0 : break;
5934 : : case svSingleRef:
5935 [ # # ]: 0 : PushCellResultToken( true, aDataAdr, NULL, NULL);
5936 : 0 : break;
5937 : : default:
5938 : : OSL_FAIL( "ScInterpreter::ScLookup: unhandled eDataArrayType, single value data");
5939 : : }
5940 : : }
5941 : : return;
5942 : : }
5943 : :
5944 : : // Now, perform the search to compute the delta position (nDelta).
5945 : :
5946 [ # # ]: 0 : if (pDataMat)
5947 : : {
5948 : : // Data array is given as a matrix.
5949 : 0 : rEntry.bDoQuery = true;
5950 : 0 : rEntry.eOp = SC_LESS_EQUAL;
5951 : 0 : bool bFound = false;
5952 : :
5953 : : SCSIZE nC, nR;
5954 [ # # ]: 0 : pDataMat->GetDimensions(nC, nR);
5955 : :
5956 : : // In case of non-vector matrix, only search the first row or column.
5957 : 0 : ScMatrixRef pDataMat2;
5958 [ # # ]: 0 : if (bVertical)
5959 : : {
5960 [ # # ][ # # ]: 0 : ScMatrixRef pTempMat(new ScMatrix(1, nR, 0.0));
5961 [ # # ]: 0 : for (SCSIZE i = 0; i < nR; ++i)
5962 [ # # ][ # # ]: 0 : if (pDataMat->IsValue(0, i))
5963 [ # # ][ # # ]: 0 : pTempMat->PutDouble(pDataMat->GetDouble(0, i), 0, i);
5964 : : else
5965 [ # # ][ # # ]: 0 : pTempMat->PutString(pDataMat->GetString(0, i), 0, i);
5966 [ # # ][ # # ]: 0 : pDataMat2 = pTempMat;
5967 : : }
5968 : : else
5969 : : {
5970 [ # # ][ # # ]: 0 : ScMatrixRef pTempMat(new ScMatrix(nC, 1, 0.0));
5971 [ # # ]: 0 : for (SCSIZE i = 0; i < nC; ++i)
5972 [ # # ][ # # ]: 0 : if (pDataMat->IsValue(i, 0))
5973 [ # # ][ # # ]: 0 : pTempMat->PutDouble(pDataMat->GetDouble(i, 0), i, 0);
5974 : : else
5975 [ # # ][ # # ]: 0 : pTempMat->PutString(pDataMat->GetString(i, 0), i, 0);
5976 [ # # ][ # # ]: 0 : pDataMat2 = pTempMat;
5977 : : }
5978 : :
5979 : 0 : VectorMatrixAccessor aMatAcc2(*pDataMat2, bVertical);
5980 : :
5981 : : // binary search for non-equality mode (the source data is
5982 : : // assumed to be sorted in ascending order).
5983 : :
5984 : 0 : SCCOLROW nDelta = -1;
5985 : :
5986 : 0 : SCSIZE nFirst = 0, nLast = nLenMajor-1; //, nHitIndex = 0;
5987 [ # # ]: 0 : for (SCSIZE nLen = nLast-nFirst; nLen > 0; nLen = nLast-nFirst)
5988 : : {
5989 : 0 : SCSIZE nMid = nFirst + nLen/2;
5990 [ # # ]: 0 : sal_Int32 nCmp = lcl_CompareMatrix2Query( nMid, aMatAcc2, rEntry);
5991 [ # # ]: 0 : if (nCmp == 0)
5992 : : {
5993 : : // exact match. find the last item with the same value.
5994 [ # # ]: 0 : lcl_GetLastMatch( nMid, aMatAcc2, nLenMajor, false);
5995 : 0 : nDelta = nMid;
5996 : 0 : bFound = true;
5997 : : break;
5998 : : }
5999 : :
6000 [ # # ]: 0 : if (nLen == 1) // first and last items are next to each other.
6001 : : {
6002 [ # # ]: 0 : nDelta = nCmp < 0 ? nLast - 1 : nFirst - 1;
6003 : : // If already the 1st item is greater there's nothing found.
6004 : 0 : bFound = (nDelta >= 0);
6005 : : break;
6006 : : }
6007 : :
6008 [ # # ]: 0 : if (nCmp < 0)
6009 : 0 : nFirst = nMid;
6010 : : else
6011 : 0 : nLast = nMid;
6012 : : }
6013 : :
6014 [ # # ]: 0 : if (nDelta == static_cast<SCCOLROW>(nLenMajor-2)) // last item
6015 : : {
6016 [ # # ]: 0 : sal_Int32 nCmp = lcl_CompareMatrix2Query(nDelta+1, aMatAcc2, rEntry);
6017 [ # # ]: 0 : if (nCmp <= 0)
6018 : : {
6019 : : // either the last item is an exact match or the real
6020 : : // hit is beyond the last item.
6021 : 0 : nDelta += 1;
6022 : 0 : bFound = true;
6023 : : }
6024 : : }
6025 [ # # ]: 0 : else if (nDelta > 0) // valid hit must be 2nd item or higher
6026 : : {
6027 : : // non-exact match
6028 : 0 : bFound = true;
6029 : : }
6030 : :
6031 : : // With 0-9 < A-Z, if query is numeric and data found is string, or
6032 : : // vice versa, the (yet another undocumented) Excel behavior is to
6033 : : // return #N/A instead.
6034 : :
6035 [ # # ]: 0 : if (bFound)
6036 : : {
6037 : 0 : VectorMatrixAccessor aMatAcc(*pDataMat, bVertical);
6038 : 0 : SCCOLROW i = nDelta;
6039 [ # # ]: 0 : SCSIZE n = aMatAcc.GetElementCount();
6040 [ # # ]: 0 : if (static_cast<SCSIZE>(i) >= n)
6041 : 0 : i = static_cast<SCCOLROW>(n);
6042 [ # # ]: 0 : bool bByString = rEntry.GetQueryItem().meType == ScQueryEntry::ByString;
6043 [ # # ][ # # ]: 0 : if (bByString == aMatAcc.IsValue(i))
6044 : 0 : bFound = false;
6045 : : }
6046 : :
6047 [ # # ]: 0 : if (!bFound)
6048 : : {
6049 [ # # ]: 0 : PushNA();
6050 : : return;
6051 : : }
6052 : :
6053 : : // Now that we've found the delta, push the result back to the cell.
6054 : :
6055 [ # # ]: 0 : if (pResMat)
6056 : : {
6057 : 0 : VectorMatrixAccessor aResMatAcc(*pResMat, bVertical);
6058 : : // result array is matrix.
6059 [ # # ][ # # ]: 0 : if (static_cast<SCSIZE>(nDelta) >= aResMatAcc.GetElementCount())
6060 : : {
6061 [ # # ]: 0 : PushNA();
6062 : : return;
6063 : : }
6064 [ # # ][ # # ]: 0 : if (aResMatAcc.IsValue(nDelta))
6065 [ # # ][ # # ]: 0 : PushDouble(aResMatAcc.GetDouble(nDelta));
6066 : : else
6067 [ # # ][ # # ]: 0 : PushString(aResMatAcc.GetString(nDelta));
[ # # ][ # # ]
6068 : : }
6069 [ # # ]: 0 : else if (nParamCount == 3)
6070 : : {
6071 : : // result array is cell range.
6072 : 0 : ScAddress aAdr;
6073 : 0 : aAdr.SetTab(nResTab);
6074 : 0 : bool bResVertical = (nResRow2 - nResRow1) > 0;
6075 [ # # ]: 0 : if (bResVertical)
6076 : : {
6077 : 0 : SCROW nTempRow = static_cast<SCROW>(nResRow1 + nDelta);
6078 [ # # ]: 0 : if (nTempRow > MAXROW)
6079 : : {
6080 [ # # ]: 0 : PushDouble(0);
6081 : : return;
6082 : : }
6083 : 0 : aAdr.SetCol(nResCol1);
6084 : 0 : aAdr.SetRow(nTempRow);
6085 : : }
6086 : : else
6087 : : {
6088 : 0 : SCCOL nTempCol = static_cast<SCCOL>(nResCol1 + nDelta);
6089 [ # # ]: 0 : if (nTempCol > MAXCOL)
6090 : : {
6091 [ # # ]: 0 : PushDouble(0);
6092 : : return;
6093 : : }
6094 : 0 : aAdr.SetCol(nTempCol);
6095 : 0 : aAdr.SetRow(nResRow1);
6096 : : }
6097 [ # # ]: 0 : PushCellResultToken(true, aAdr, NULL, NULL);
6098 : : }
6099 : : else
6100 : : {
6101 : : // no result array. Use the data array to get the final value from.
6102 [ # # ]: 0 : if (bVertical)
6103 : : {
6104 [ # # ][ # # ]: 0 : if (pDataMat->IsValue(nC-1, nDelta))
6105 [ # # ][ # # ]: 0 : PushDouble(pDataMat->GetDouble(nC-1, nDelta));
6106 : : else
6107 [ # # ][ # # ]: 0 : PushString(pDataMat->GetString(nC-1, nDelta));
[ # # ][ # # ]
6108 : : }
6109 : : else
6110 : : {
6111 [ # # ][ # # ]: 0 : if (pDataMat->IsValue(nDelta, nR-1))
6112 [ # # ][ # # ]: 0 : PushDouble(pDataMat->GetDouble(nDelta, nR-1));
6113 : : else
6114 [ # # ][ # # ]: 0 : PushString(pDataMat->GetString(nDelta, nR-1));
[ # # ][ # # ]
6115 : : }
6116 : : }
6117 : :
6118 [ # # ]: 0 : return;
6119 : : }
6120 : :
6121 : : // Perform cell range search.
6122 : :
6123 : 0 : aParam.nCol1 = nCol1;
6124 : 0 : aParam.nRow1 = nRow1;
6125 [ # # ]: 0 : aParam.nCol2 = bVertical ? nCol1 : nCol2;
6126 [ # # ]: 0 : aParam.nRow2 = bVertical ? nRow2 : nRow1;
6127 : 0 : aParam.bByRow = bVertical;
6128 : :
6129 : 0 : rEntry.bDoQuery = true;
6130 : 0 : rEntry.eOp = SC_LESS_EQUAL;
6131 : 0 : rEntry.nField = nCol1;
6132 [ # # ]: 0 : ScQueryEntry::Item& rItem = rEntry.GetQueryItem();
6133 [ # # ]: 0 : if (rItem.meType == ScQueryEntry::ByString)
6134 [ # # ]: 0 : aParam.bRegExp = MayBeRegExp(rItem.maString, pDok);
6135 : :
6136 [ # # ]: 0 : ScQueryCellIterator aCellIter(pDok, nTab1, aParam, false);
6137 : : SCCOL nC;
6138 : : SCROW nR;
6139 : : // Advance Entry.nField in iterator upon switching columns if
6140 : : // lookup in row.
6141 : 0 : aCellIter.SetAdvanceQueryParamEntryField(!bVertical);
6142 [ # # ][ # # ]: 0 : if ( !aCellIter.FindEqualOrSortedLastInRange(nC, nR) )
6143 : : {
6144 [ # # ]: 0 : PushNA();
6145 : : return;
6146 : : }
6147 : :
6148 [ # # ]: 0 : SCCOLROW nDelta = bVertical ? static_cast<SCSIZE>(nR-nRow1) : static_cast<SCSIZE>(nC-nCol1);
6149 : :
6150 [ # # ]: 0 : if (pResMat)
6151 : : {
6152 : 0 : VectorMatrixAccessor aResMatAcc(*pResMat, bVertical);
6153 : : // Use the matrix result array.
6154 [ # # ][ # # ]: 0 : if (aResMatAcc.IsValue(nDelta))
6155 [ # # ][ # # ]: 0 : PushDouble(aResMatAcc.GetDouble(nDelta));
6156 : : else
6157 [ # # ][ # # ]: 0 : PushString(aResMatAcc.GetString(nDelta));
[ # # ][ # # ]
6158 : : }
6159 [ # # ]: 0 : else if (nParamCount == 3)
6160 : : {
6161 [ # # # ]: 0 : switch (eResArrayType)
6162 : : {
6163 : : case svDoubleRef:
6164 : : {
6165 : : // Use the result array vector. Note that the result array is assumed
6166 : : // to be a vector (i.e. 1-dimensinoal array).
6167 : :
6168 : 0 : ScAddress aAdr;
6169 : 0 : aAdr.SetTab(nResTab);
6170 : 0 : bool bResVertical = (nResRow2 - nResRow1) > 0;
6171 [ # # ]: 0 : if (bResVertical)
6172 : : {
6173 : 0 : SCROW nTempRow = static_cast<SCROW>(nResRow1 + nDelta);
6174 [ # # ]: 0 : if (nTempRow > MAXROW)
6175 : : {
6176 [ # # ]: 0 : PushDouble(0);
6177 : : return;
6178 : : }
6179 : 0 : aAdr.SetCol(nResCol1);
6180 : 0 : aAdr.SetRow(nTempRow);
6181 : : }
6182 : : else
6183 : : {
6184 : 0 : SCCOL nTempCol = static_cast<SCCOL>(nResCol1 + nDelta);
6185 [ # # ]: 0 : if (nTempCol > MAXCOL)
6186 : : {
6187 [ # # ]: 0 : PushDouble(0);
6188 : : return;
6189 : : }
6190 : 0 : aAdr.SetCol(nTempCol);
6191 : 0 : aAdr.SetRow(nResRow1);
6192 : : }
6193 [ # # ]: 0 : PushCellResultToken( true, aAdr, NULL, NULL);
6194 : : }
6195 : 0 : break;
6196 : : case svDouble:
6197 : : case svString:
6198 : : case svSingleRef:
6199 : : {
6200 [ # # ]: 0 : if (nDelta != 0)
6201 [ # # ]: 0 : PushNA();
6202 : : else
6203 : : {
6204 [ # # # # ]: 0 : switch (eResArrayType)
6205 : : {
6206 : : case svDouble:
6207 [ # # ]: 0 : PushDouble( fResVal );
6208 : 0 : break;
6209 : : case svString:
6210 [ # # ]: 0 : PushString( aResStr );
6211 : 0 : break;
6212 : : case svSingleRef:
6213 [ # # ]: 0 : PushCellResultToken( true, aResAdr, NULL, NULL);
6214 : 0 : break;
6215 : : default:
6216 : : ; // nothing
6217 : : }
6218 : : }
6219 : : }
6220 : 0 : break;
6221 : : default:
6222 : : OSL_FAIL( "ScInterpreter::ScLookup: unhandled eResArrayType, range search");
6223 : : }
6224 : : }
6225 : : else
6226 : : {
6227 : : // Regardless of whether or not the result array exists, the last
6228 : : // array is always used as the "result" array.
6229 : :
6230 : 0 : ScAddress aAdr;
6231 : 0 : aAdr.SetTab(nTab1);
6232 [ # # ]: 0 : if (bVertical)
6233 : : {
6234 : 0 : SCROW nTempRow = static_cast<SCROW>(nRow1 + nDelta);
6235 [ # # ]: 0 : if (nTempRow > MAXROW)
6236 : : {
6237 [ # # ]: 0 : PushDouble(0);
6238 : : return;
6239 : : }
6240 : 0 : aAdr.SetCol(nCol2);
6241 : 0 : aAdr.SetRow(nTempRow);
6242 : : }
6243 : : else
6244 : : {
6245 : 0 : SCCOL nTempCol = static_cast<SCCOL>(nCol1 + nDelta);
6246 [ # # ]: 0 : if (nTempCol > MAXCOL)
6247 : : {
6248 [ # # ]: 0 : PushDouble(0);
6249 : : return;
6250 : : }
6251 : 0 : aAdr.SetCol(nTempCol);
6252 : 0 : aAdr.SetRow(nRow2);
6253 : : }
6254 [ # # ]: 0 : PushCellResultToken(true, aAdr, NULL, NULL);
6255 [ # # ][ # # ]: 0 : }
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
6256 : : }
6257 : :
6258 : :
6259 : 0 : void ScInterpreter::ScHLookup()
6260 : : {
6261 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScHLookup" );
6262 : 0 : CalculateLookup(true);
6263 : 0 : }
6264 : 51 : void ScInterpreter::CalculateLookup(bool HLookup)
6265 : : {
6266 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::CalculateLookup" );
6267 : 51 : sal_uInt8 nParamCount = GetByte();
6268 [ + - ]: 51 : if ( MustHaveParamCount( nParamCount, 3, 4 ) )
6269 : : {
6270 : : bool bSorted;
6271 [ + - ]: 51 : if (nParamCount == 4)
6272 [ + - ]: 51 : bSorted = GetBool();
6273 : : else
6274 : 0 : bSorted = true;
6275 [ + - ]: 51 : double fIndex = ::rtl::math::approxFloor( GetDouble() ) - 1.0;
6276 : 51 : ScMatrixRef pMat = NULL;
6277 : 51 : SCSIZE nC = 0, nR = 0;
6278 : 51 : SCCOL nCol1 = 0;
6279 : 51 : SCROW nRow1 = 0;
6280 : 51 : SCTAB nTab1 = 0;
6281 : 51 : SCCOL nCol2 = 0;
6282 : 51 : SCROW nRow2 = 0;
6283 : : SCTAB nTab2;
6284 [ + - ]: 51 : StackVar eType = GetStackType();
6285 [ + - ]: 51 : if (eType == svDoubleRef)
6286 : : {
6287 [ + - ]: 51 : PopDoubleRef(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
6288 [ - + ]: 51 : if (nTab1 != nTab2)
6289 : : {
6290 [ # # ]: 0 : PushIllegalParameter();
6291 : : return;
6292 : : }
6293 : : }
6294 [ # # ]: 0 : else if (eType == svSingleRef)
6295 : : {
6296 [ # # ]: 0 : PopSingleRef(nCol1, nRow1, nTab1);
6297 : 0 : nCol2 = nCol1;
6298 : 0 : nRow2 = nRow1;
6299 : : }
6300 [ # # ][ # # ]: 0 : else if (eType == svMatrix || eType == svExternalDoubleRef || eType == svExternalSingleRef)
[ # # ]
6301 : : {
6302 [ # # ][ # # ]: 0 : pMat = GetMatrix();
[ # # ]
6303 : :
6304 [ # # ]: 0 : if (pMat)
6305 [ # # ]: 0 : pMat->GetDimensions(nC, nR);
6306 : : else
6307 : : {
6308 [ # # ]: 0 : PushIllegalParameter();
6309 : : return;
6310 : : }
6311 : : }
6312 : : else
6313 : : {
6314 [ # # ]: 0 : PushIllegalParameter();
6315 : : return;
6316 : : }
6317 [ + - ][ - + ]: 51 : if ( fIndex < 0.0 || (HLookup ? (pMat ? (fIndex >= nR) : (fIndex+nRow1 > nRow2)) : (pMat ? (fIndex >= nC) : (fIndex+nCol1 > nCol2)) ) )
[ # # ][ # # ]
[ # # ][ - + ]
[ # # ][ - + ]
[ - + ]
6318 : : {
6319 [ # # ]: 0 : PushIllegalArgument();
6320 : : return;
6321 : : }
6322 : 51 : SCROW nZIndex = static_cast<SCROW>(fIndex);
6323 : 51 : SCCOL nSpIndex = static_cast<SCCOL>(fIndex);
6324 : :
6325 [ + - ]: 51 : if (!pMat)
6326 : : {
6327 : 51 : nZIndex += nRow1; // Wertzeile
6328 : 51 : nSpIndex = sal::static_int_cast<SCCOL>( nSpIndex + nCol1 ); // value column
6329 : : }
6330 : :
6331 [ + - ]: 51 : if (nGlobalError == 0)
6332 : : {
6333 [ + - ]: 51 : ScQueryParam rParam;
6334 : 51 : rParam.nCol1 = nCol1;
6335 : 51 : rParam.nRow1 = nRow1;
6336 [ - + ]: 51 : if ( HLookup )
6337 : : {
6338 : 0 : rParam.nCol2 = nCol2;
6339 : 0 : rParam.nRow2 = nRow1; // nur in der ersten Zeile suchen
6340 : 0 : rParam.bByRow = false;
6341 : : } // if ( HLookup )
6342 : : else
6343 : : {
6344 : 51 : rParam.nCol2 = nCol1; // nur in der ersten Spalte suchen
6345 : 51 : rParam.nRow2 = nRow2;
6346 : 51 : rParam.nTab = nTab1;
6347 : : }
6348 : :
6349 [ + - ]: 51 : ScQueryEntry& rEntry = rParam.GetEntry(0);
6350 : 51 : rEntry.bDoQuery = true;
6351 [ + - ]: 51 : if ( bSorted )
6352 : 51 : rEntry.eOp = SC_LESS_EQUAL;
6353 [ + - ][ - + ]: 51 : if ( !FillEntry(rEntry) )
6354 : : return;
6355 : :
6356 [ + - ]: 51 : ScQueryEntry::Item& rItem = rEntry.GetQueryItem();
6357 [ + + ]: 51 : if (rItem.meType == ScQueryEntry::ByString)
6358 [ + - ]: 24 : rParam.bRegExp = MayBeRegExp(rItem.maString, pDok);
6359 [ - + ]: 51 : if (pMat)
6360 : : {
6361 [ # # ]: 0 : SCSIZE nMatCount = HLookup ? nC : nR;
6362 : 0 : SCSIZE nDelta = SCSIZE_MAX;
6363 [ # # ]: 0 : if (rItem.meType == ScQueryEntry::ByString)
6364 : : {
6365 : : //!!!!!!!
6366 : : //! TODO: enable regex on matrix strings
6367 : : //!!!!!!!
6368 : 0 : const rtl::OUString& rParamStr = rItem.maString;
6369 [ # # ]: 0 : if ( bSorted )
6370 : : {
6371 [ # # ][ # # ]: 0 : static CollatorWrapper* pCollator = ScGlobal::GetCollator();
[ # # ][ # # ]
6372 [ # # ]: 0 : for (SCSIZE i = 0; i < nMatCount; i++)
6373 : : {
6374 [ # # ][ # # ]: 0 : if (HLookup ? pMat->IsString(i, 0) : pMat->IsString(0, i))
[ # # ][ # # ]
6375 : : {
6376 : : sal_Int32 nRes =
6377 [ # # ][ # # ]: 0 : pCollator->compareString( HLookup ? pMat->GetString(i,0) : pMat->GetString(0,i), rParamStr);
[ # # ][ # # ]
6378 [ # # ]: 0 : if (nRes <= 0)
6379 : 0 : nDelta = i;
6380 [ # # ]: 0 : else if (i>0) // #i2168# ignore first mismatch
6381 : 0 : i = nMatCount+1;
6382 : : }
6383 : : else
6384 : 0 : nDelta = i;
6385 : : }
6386 : : }
6387 : : else
6388 : : {
6389 [ # # ]: 0 : for (SCSIZE i = 0; i < nMatCount; i++)
6390 : : {
6391 [ # # ][ # # ]: 0 : if (HLookup ? pMat->IsString(i, 0) : pMat->IsString(0, i))
[ # # ][ # # ]
6392 : : {
6393 [ # # ]: 0 : if ( ScGlobal::GetpTransliteration()->isEqual(
6394 [ # # ][ # # ]: 0 : HLookup ? pMat->GetString(i,0) : pMat->GetString(0,i), rParamStr))
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
6395 : : {
6396 : 0 : nDelta = i;
6397 : 0 : i = nMatCount + 1;
6398 : : }
6399 : : }
6400 : : }
6401 : : }
6402 : : }
6403 : : else
6404 : : {
6405 [ # # ]: 0 : if ( bSorted )
6406 : : {
6407 : : // #i2168# ignore strings
6408 [ # # ]: 0 : for (SCSIZE i = 0; i < nMatCount; i++)
6409 : : {
6410 [ # # ][ # # ]: 0 : if (!(HLookup ? pMat->IsString(i, 0) : pMat->IsString(0, i)))
[ # # ][ # # ]
6411 : : {
6412 [ # # ][ # # ]: 0 : if ((HLookup ? pMat->GetDouble(i,0) : pMat->GetDouble(0,i)) <= rItem.mfVal)
[ # # ][ # # ]
6413 : 0 : nDelta = i;
6414 : : else
6415 : 0 : i = nMatCount+1;
6416 : : }
6417 : : }
6418 : : }
6419 : : else
6420 : : {
6421 [ # # ]: 0 : for (SCSIZE i = 0; i < nMatCount; i++)
6422 : : {
6423 [ # # ][ # # ]: 0 : if (!(HLookup ? pMat->IsString(i, 0) : pMat->IsString(0, i)))
[ # # ][ # # ]
6424 : : {
6425 [ # # ][ # # ]: 0 : if ((HLookup ? pMat->GetDouble(i,0) : pMat->GetDouble(0,i)) == rItem.mfVal)
[ # # ][ # # ]
6426 : : {
6427 : 0 : nDelta = i;
6428 : 0 : i = nMatCount + 1;
6429 : : }
6430 : : }
6431 : : }
6432 : : }
6433 : : }
6434 [ # # ]: 0 : if ( nDelta != SCSIZE_MAX )
6435 : : {
6436 : 0 : SCSIZE nX = static_cast<SCSIZE>(nSpIndex);
6437 : 0 : SCSIZE nY = nDelta;
6438 [ # # ]: 0 : if ( HLookup )
6439 : : {
6440 : 0 : nX = nDelta;
6441 : 0 : nY = static_cast<SCSIZE>(nZIndex);
6442 : : }
6443 [ # # ][ # # ]: 0 : if ( pMat->IsString( nX, nY) )
6444 [ # # ][ # # ]: 0 : PushString(pMat->GetString( nX,nY));
[ # # ][ # # ]
6445 : : else
6446 [ # # ][ # # ]: 0 : PushDouble(pMat->GetDouble( nX,nY));
6447 : : }
6448 : : else
6449 [ # # ]: 0 : PushNA();
6450 : : }
6451 : : else
6452 : : {
6453 : 51 : rEntry.nField = nCol1;
6454 : 51 : bool bFound = false;
6455 : 51 : SCCOL nCol = 0;
6456 : 51 : SCROW nRow = 0;
6457 [ + - ]: 51 : if ( bSorted )
6458 : 51 : rEntry.eOp = SC_LESS_EQUAL;
6459 [ - + ]: 51 : if ( HLookup )
6460 : : {
6461 [ # # ]: 0 : ScQueryCellIterator aCellIter(pDok, nTab1, rParam, false);
6462 : : // advance Entry.nField in Iterator upon switching columns
6463 : 0 : aCellIter.SetAdvanceQueryParamEntryField( true );
6464 [ # # ]: 0 : if ( bSorted )
6465 : : {
6466 : : SCROW nRow1_temp;
6467 [ # # ]: 0 : bFound = aCellIter.FindEqualOrSortedLastInRange( nCol, nRow1_temp );
6468 : : }
6469 [ # # ][ # # ]: 0 : else if ( aCellIter.GetFirst() )
6470 : : {
6471 : 0 : bFound = true;
6472 : 0 : nCol = aCellIter.GetCol();
6473 : : }
6474 [ # # ]: 0 : nRow = nZIndex;
6475 : : } // if ( HLookup )
6476 : : else
6477 : : {
6478 : 51 : ScAddress aResultPos( nCol1, nRow1, nTab1);
6479 [ + - ]: 51 : bFound = LookupQueryWithCache( aResultPos, rParam);
6480 : 51 : nRow = aResultPos.Row();
6481 : 51 : nCol = nSpIndex;
6482 : : }
6483 [ + + ]: 51 : if ( bFound )
6484 : : {
6485 : 48 : ScAddress aAdr( nCol, nRow, nTab1 );
6486 [ + - ]: 48 : PushCellResultToken( true, aAdr, NULL, NULL);
6487 : : }
6488 : : else
6489 [ + - ]: 51 : PushNA();
6490 [ + - ][ + - ]: 51 : }
6491 : : }
6492 : : else
6493 [ # # ][ + - ]: 51 : PushIllegalParameter();
[ + - ]
6494 : : }
6495 : : }
6496 : :
6497 : 51 : bool ScInterpreter::FillEntry(ScQueryEntry& rEntry)
6498 : : {
6499 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::FillEntry" );
6500 : 51 : ScQueryEntry::Item& rItem = rEntry.GetQueryItem();
6501 [ - - + - : 51 : switch ( GetStackType() )
- ]
6502 : : {
6503 : : case svDouble:
6504 : : {
6505 : 0 : rItem.meType = ScQueryEntry::ByValue;
6506 : 0 : rItem.mfVal = GetDouble();
6507 : : }
6508 : 0 : break;
6509 : : case svString:
6510 : : {
6511 : 0 : const String& sStr = GetString();
6512 : 0 : rItem.meType = ScQueryEntry::ByString;
6513 : 0 : rItem.maString = sStr;
6514 : : }
6515 : 0 : break;
6516 : : case svDoubleRef :
6517 : : case svSingleRef :
6518 : : {
6519 : 51 : ScAddress aAdr;
6520 [ - + ][ + - ]: 51 : if ( !PopDoubleRefOrSingleRef( aAdr ) )
6521 : : {
6522 [ # # ]: 0 : PushInt(0);
6523 : 0 : return false;
6524 : : }
6525 [ + - ]: 51 : ScBaseCell* pCell = GetCell( aAdr );
6526 [ + - ][ + + ]: 51 : if (HasCellValueData(pCell))
6527 : : {
6528 : 27 : rItem.meType = ScQueryEntry::ByValue;
6529 [ + - ]: 27 : rItem.mfVal = GetCellValue(aAdr, pCell);
6530 : : }
6531 : : else
6532 : : {
6533 [ - + ]: 24 : if ( GetCellType( pCell ) == CELLTYPE_NOTE )
6534 : : {
6535 : 0 : rItem.meType = ScQueryEntry::ByValue;
6536 : 0 : rItem.mfVal = 0.0;
6537 : : }
6538 : : else
6539 : : {
6540 [ + - ]: 24 : String sStr;
6541 [ + - ]: 24 : GetCellString(sStr, pCell);
6542 : 24 : rItem.meType = ScQueryEntry::ByString;
6543 [ + - ][ + - ]: 24 : rItem.maString = sStr;
6544 : : }
6545 : : }
6546 : : }
6547 : 51 : break;
6548 : : case svMatrix :
6549 : : {
6550 [ # # ]: 0 : String aStr;
6551 [ # # ]: 0 : const ScMatValType nType = GetDoubleOrStringFromMatrix(rItem.mfVal, aStr);
6552 [ # # ]: 0 : rItem.maString = aStr;
6553 : 0 : rItem.meType = ScMatrix::IsNonValueType(nType) ?
6554 [ # # ][ # # ]: 0 : ScQueryEntry::ByString : ScQueryEntry::ByValue;
6555 : : }
6556 : 0 : break;
6557 : : default:
6558 : : {
6559 : 0 : PushIllegalParameter();
6560 : 0 : return false;
6561 : : }
6562 : : } // switch ( GetStackType() )
6563 : 51 : return true;
6564 : : }
6565 : 51 : void ScInterpreter::ScVLookup()
6566 : : {
6567 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScVLookup" );
6568 : 51 : CalculateLookup(false);
6569 : 51 : }
6570 : :
6571 : 7 : void ScInterpreter::ScSubTotal()
6572 : : {
6573 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScSubTotal" );
6574 : 7 : sal_uInt8 nParamCount = GetByte();
6575 [ + - ]: 7 : if ( MustHaveParamCountMin( nParamCount, 2 ) )
6576 : : {
6577 : : // We must fish the 1st parameter deep from the stack! And push it on top.
6578 : 7 : const FormulaToken* p = pStack[ sp - nParamCount ];
6579 : 7 : PushTempToken( *p );
6580 : 7 : int nFunc = (int) ::rtl::math::approxFloor( GetDouble() );
6581 [ - + ][ + - ]: 7 : if( nFunc < 1 || nFunc > 11 )
6582 : 0 : PushIllegalArgument(); // simulate return on stack, not SetError(...)
6583 : : else
6584 : : {
6585 : 7 : cPar = nParamCount - 1;
6586 : 7 : glSubTotal = true;
6587 [ - - - - : 7 : switch( nFunc )
- - - - +
- - - ]
6588 : : {
6589 : 0 : case SUBTOTAL_FUNC_AVE : ScAverage(); break;
6590 : 0 : case SUBTOTAL_FUNC_CNT : ScCount(); break;
6591 : 0 : case SUBTOTAL_FUNC_CNT2 : ScCount2(); break;
6592 : 0 : case SUBTOTAL_FUNC_MAX : ScMax(); break;
6593 : 0 : case SUBTOTAL_FUNC_MIN : ScMin(); break;
6594 : 0 : case SUBTOTAL_FUNC_PROD : ScProduct(); break;
6595 : 0 : case SUBTOTAL_FUNC_STD : ScStDev(); break;
6596 : 0 : case SUBTOTAL_FUNC_STDP : ScStDevP(); break;
6597 : 7 : case SUBTOTAL_FUNC_SUM : ScSum(); break;
6598 : 0 : case SUBTOTAL_FUNC_VAR : ScVar(); break;
6599 : 0 : case SUBTOTAL_FUNC_VARP : ScVarP(); break;
6600 : 0 : default : PushIllegalArgument(); break;
6601 : : }
6602 : 7 : glSubTotal = false;
6603 : : }
6604 : : // Get rid of the 1st (fished) parameter.
6605 : 7 : double nVal = GetDouble();
6606 : 7 : Pop();
6607 : 7 : PushDouble( nVal );
6608 : : }
6609 : 7 : }
6610 : :
6611 : 24 : ScDBQueryParamBase* ScInterpreter::GetDBParams( bool& rMissingField )
6612 : : {
6613 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::GetDBParams" );
6614 : 24 : bool bAllowMissingField = false;
6615 [ + - ]: 24 : if ( rMissingField )
6616 : : {
6617 : 24 : bAllowMissingField = true;
6618 : 24 : rMissingField = false;
6619 : : }
6620 [ + - ]: 24 : if ( GetByte() == 3 )
6621 : : {
6622 : : // First, get the query criteria range.
6623 : : SAL_WNODEPRECATED_DECLARATIONS_PUSH
6624 [ + - ]: 24 : ::std::auto_ptr<ScDBRangeBase> pQueryRef( PopDBDoubleRef() );
6625 : : SAL_WNODEPRECATED_DECLARATIONS_POP
6626 [ - + ]: 24 : if (!pQueryRef.get())
6627 : 0 : return NULL;
6628 : :
6629 : 24 : bool bByVal = true;
6630 : 24 : double nVal = 0.0;
6631 [ + - ]: 24 : String aStr;
6632 : 24 : ScRange aMissingRange;
6633 : 24 : bool bRangeFake = false;
6634 [ + - - - : 24 : switch (GetStackType())
- - ][ + - ]
6635 : : {
6636 : : case svDouble :
6637 [ + - ]: 24 : nVal = ::rtl::math::approxFloor( GetDouble() );
6638 [ + + ][ + - ]: 24 : if ( bAllowMissingField && nVal == 0.0 )
6639 : 12 : rMissingField = true; // fake missing parameter
6640 : 24 : break;
6641 : : case svString :
6642 : 0 : bByVal = false;
6643 [ # # ][ # # ]: 0 : aStr = GetString();
6644 : 0 : break;
6645 : : case svSingleRef :
6646 : : {
6647 : 0 : ScAddress aAdr;
6648 [ # # ]: 0 : PopSingleRef( aAdr );
6649 [ # # ]: 0 : ScBaseCell* pCell = GetCell( aAdr );
6650 [ # # ][ # # ]: 0 : if (HasCellValueData(pCell))
6651 [ # # ]: 0 : nVal = GetCellValue( aAdr, pCell );
6652 : : else
6653 : : {
6654 : 0 : bByVal = false;
6655 [ # # ]: 0 : GetCellString(aStr, pCell);
6656 : : }
6657 : : }
6658 : 0 : break;
6659 : : case svDoubleRef :
6660 [ # # ]: 0 : if ( bAllowMissingField )
6661 : : { // fake missing parameter for old SO compatibility
6662 : 0 : bRangeFake = true;
6663 [ # # ]: 0 : PopDoubleRef( aMissingRange );
6664 : : }
6665 : : else
6666 : : {
6667 [ # # ]: 0 : PopError();
6668 : 0 : SetError( errIllegalParameter );
6669 : : }
6670 : 0 : break;
6671 : : case svMissing :
6672 [ # # ]: 0 : PopError();
6673 [ # # ]: 0 : if ( bAllowMissingField )
6674 : 0 : rMissingField = true;
6675 : : else
6676 : 0 : SetError( errIllegalParameter );
6677 : 0 : break;
6678 : : default:
6679 [ # # ]: 0 : PopError();
6680 : 0 : SetError( errIllegalParameter );
6681 : : }
6682 : :
6683 [ - + ]: 24 : if (nGlobalError)
6684 : 0 : return NULL;
6685 : :
6686 : : SAL_WNODEPRECATED_DECLARATIONS_PUSH
6687 [ + - ]: 24 : auto_ptr<ScDBRangeBase> pDBRef( PopDBDoubleRef() );
6688 : : SAL_WNODEPRECATED_DECLARATIONS_POP
6689 : :
6690 [ - + ][ - + ]: 24 : if (nGlobalError || !pDBRef.get())
[ + - ]
6691 : 0 : return NULL;
6692 : :
6693 [ - + ]: 24 : if ( bRangeFake )
6694 : : {
6695 : : // range parameter must match entire database range
6696 [ # # ][ # # ]: 0 : if (pDBRef->isRangeEqual(aMissingRange))
6697 : 0 : rMissingField = true;
6698 : : else
6699 : 0 : SetError( errIllegalParameter );
6700 : : }
6701 : :
6702 [ - + ]: 24 : if (nGlobalError)
6703 : 0 : return NULL;
6704 : :
6705 [ + - ]: 24 : SCCOL nField = pDBRef->getFirstFieldColumn();
6706 [ + + ]: 24 : if (rMissingField)
6707 : : ; // special case
6708 [ + - ]: 12 : else if (bByVal)
6709 [ + - ]: 12 : nField = pDBRef->findFieldColumn(static_cast<SCCOL>(nVal));
6710 : : else
6711 : : {
6712 : 0 : sal_uInt16 nErr = 0;
6713 [ # # ][ # # ]: 0 : nField = pDBRef->findFieldColumn(aStr, &nErr);
6714 : 0 : SetError(nErr);
6715 : : }
6716 : :
6717 [ - + ]: 24 : if (!ValidCol(nField))
6718 : 0 : return NULL;
6719 : :
6720 : : SAL_WNODEPRECATED_DECLARATIONS_PUSH
6721 [ + - ]: 24 : auto_ptr<ScDBQueryParamBase> pParam( pDBRef->createQueryParam(pQueryRef.get()) );
6722 : : SAL_WNODEPRECATED_DECLARATIONS_POP
6723 : :
6724 [ + - ]: 24 : if (pParam.get())
6725 : : {
6726 : : // An allowed missing field parameter sets the result field
6727 : : // to any of the query fields, just to be able to return
6728 : : // some cell from the iterator.
6729 [ + + ]: 24 : if ( rMissingField )
6730 [ + - ]: 12 : nField = static_cast<SCCOL>(pParam->GetEntry(0).nField);
6731 : 24 : pParam->mnField = nField;
6732 : :
6733 [ + - ]: 24 : SCSIZE nCount = pParam->GetEntryCount();
6734 [ + - ]: 84 : for ( SCSIZE i=0; i < nCount; i++ )
6735 : : {
6736 [ + - ]: 60 : ScQueryEntry& rEntry = pParam->GetEntry(i);
6737 [ + + ]: 60 : if (!rEntry.bDoQuery)
6738 : : break;
6739 : :
6740 [ + - ]: 36 : ScQueryEntry::Item& rItem = rEntry.GetQueryItem();
6741 : 36 : sal_uInt32 nIndex = 0;
6742 : 36 : const rtl::OUString& rQueryStr = rItem.maString;
6743 : : bool bNumber = pFormatter->IsNumberFormat(
6744 [ + - ][ + - ]: 36 : rQueryStr, nIndex, rItem.mfVal);
[ + - ]
6745 [ + - ]: 36 : rItem.meType = bNumber ? ScQueryEntry::ByValue : ScQueryEntry::ByString;
6746 : :
6747 [ - + ][ # # ]: 36 : if (!bNumber && !pParam->bRegExp)
[ - + ]
6748 [ # # ]: 0 : pParam->bRegExp = MayBeRegExp(rQueryStr, pDok);
6749 : : }
6750 : 24 : return pParam.release();
6751 [ + - ][ + - ]: 24 : }
[ + - ][ - + ]
[ + - ][ + - ]
[ + - ][ - + ]
6752 : : }
6753 : 24 : return NULL;
6754 : : }
6755 : :
6756 : :
6757 : 0 : void ScInterpreter::DBIterator( ScIterFunc eFunc )
6758 : : {
6759 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::DBIterator" );
6760 : 0 : double nErg = 0.0;
6761 : 0 : double fMem = 0.0;
6762 : 0 : bool bNull = true;
6763 : 0 : sal_uLong nCount = 0;
6764 : 0 : bool bMissingField = false;
6765 : : SAL_WNODEPRECATED_DECLARATIONS_PUSH
6766 [ # # ]: 0 : auto_ptr<ScDBQueryParamBase> pQueryParam( GetDBParams(bMissingField) );
6767 : : SAL_WNODEPRECATED_DECLARATIONS_POP
6768 [ # # ]: 0 : if (pQueryParam.get())
6769 : : {
6770 [ # # ][ # # ]: 0 : if (!pQueryParam->IsValidFieldIndex())
6771 : : {
6772 : 0 : SetError(errNoValue);
6773 : 0 : return;
6774 : : }
6775 [ # # ]: 0 : ScDBQueryDataIterator aValIter(pDok, pQueryParam.release());
6776 [ # # ]: 0 : ScDBQueryDataIterator::Value aValue;
6777 [ # # ][ # # ]: 0 : if ( aValIter.GetFirst(aValue) && !aValue.mnError )
[ # # ][ # # ]
6778 : : {
6779 [ # # # # ]: 0 : switch( eFunc )
6780 : : {
6781 : 0 : case ifPRODUCT: nErg = 1; break;
6782 : 0 : case ifMAX: nErg = -MAXDOUBLE; break;
6783 : 0 : case ifMIN: nErg = MAXDOUBLE; break;
6784 : : default: ; // nothing
6785 : : }
6786 [ # # ][ # # ]: 0 : do
[ # # ]
6787 : : {
6788 : 0 : nCount++;
6789 [ # # # # : 0 : switch( eFunc )
# # ]
6790 : : {
6791 : : case ifAVERAGE:
6792 : : case ifSUM:
6793 [ # # ][ # # ]: 0 : if ( bNull && aValue.mfValue != 0.0 )
6794 : : {
6795 : 0 : bNull = false;
6796 : 0 : fMem = aValue.mfValue;
6797 : : }
6798 : : else
6799 : 0 : nErg += aValue.mfValue;
6800 : 0 : break;
6801 : 0 : case ifSUMSQ: nErg += aValue.mfValue * aValue.mfValue; break;
6802 : 0 : case ifPRODUCT: nErg *= aValue.mfValue; break;
6803 [ # # ]: 0 : case ifMAX: if( aValue.mfValue > nErg ) nErg = aValue.mfValue; break;
6804 [ # # ]: 0 : case ifMIN: if( aValue.mfValue < nErg ) nErg = aValue.mfValue; break;
6805 : : default: ; // nothing
6806 : : }
6807 : : }
6808 [ # # ]: 0 : while ( aValIter.GetNext(aValue) && !aValue.mnError );
6809 : : }
6810 [ # # ]: 0 : SetError(aValue.mnError);
6811 : : }
6812 : : else
6813 : 0 : SetError( errIllegalParameter);
6814 [ # # # # ]: 0 : switch( eFunc )
6815 : : {
6816 : 0 : case ifCOUNT: nErg = nCount; break;
6817 : 0 : case ifSUM: nErg = ::rtl::math::approxAdd( nErg, fMem ); break;
6818 : 0 : case ifAVERAGE: nErg = ::rtl::math::approxAdd( nErg, fMem ) / nCount; break;
6819 : : default: ; // nothing
6820 : : }
6821 [ # # ][ # # ]: 0 : PushDouble( nErg );
[ # # ]
6822 : : }
6823 : :
6824 : :
6825 : 0 : void ScInterpreter::ScDBSum()
6826 : : {
6827 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScDBSum" );
6828 : 0 : DBIterator( ifSUM );
6829 : 0 : }
6830 : :
6831 : :
6832 : 24 : void ScInterpreter::ScDBCount()
6833 : : {
6834 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScDBCount" );
6835 : 24 : bool bMissingField = true;
6836 : : SAL_WNODEPRECATED_DECLARATIONS_PUSH
6837 [ + - ]: 24 : auto_ptr<ScDBQueryParamBase> pQueryParam( GetDBParams(bMissingField) );
6838 : : SAL_WNODEPRECATED_DECLARATIONS_POP
6839 [ + - ]: 24 : if (pQueryParam.get())
6840 : : {
6841 : 24 : sal_uLong nCount = 0;
6842 [ + + ][ + - ]: 24 : if ( bMissingField && pQueryParam->GetType() == ScDBQueryParamBase::INTERNAL )
[ + - ][ + + ]
6843 : : { // count all matching records
6844 : : // TODO: currently the QueryIterators only return cell pointers of
6845 : : // existing cells, so if a query matches an empty cell there's
6846 : : // nothing returned, and therefor not counted!
6847 : : // Since this has ever been the case and this code here only came
6848 : : // into existance to fix #i6899 and it never worked before we'll
6849 : : // have to live with it until we reimplement the iterators to also
6850 : : // return empty cells, which would mean to adapt all callers of
6851 : : // iterators.
6852 : 12 : ScDBQueryParamInternal* p = static_cast<ScDBQueryParamInternal*>(pQueryParam.get());
6853 : 12 : p->nCol2 = p->nCol1; // Don't forget to select only one column.
6854 : 12 : SCTAB nTab = p->nTab;
6855 : : // ScQueryCellIterator doesn't make use of ScDBQueryParamBase::mnField,
6856 : : // so the source range has to be restricted, like before the introduction
6857 : : // of ScDBQueryParamBase.
6858 : 12 : p->nCol1 = p->nCol2 = p->mnField;
6859 [ + - ][ + - ]: 12 : ScQueryCellIterator aCellIter( pDok, nTab, *p);
[ + - ]
6860 [ + - ][ + - ]: 12 : if ( aCellIter.GetFirst() )
6861 : : {
6862 [ + + ]: 24 : do
6863 : : {
6864 : 24 : nCount++;
6865 [ + - ]: 24 : } while ( aCellIter.GetNext() );
6866 [ + - ]: 12 : }
6867 : : }
6868 : : else
6869 : : { // count only matching records with a value in the "result" field
6870 [ + - ][ - + ]: 12 : if (!pQueryParam->IsValidFieldIndex())
6871 : : {
6872 : 0 : SetError(errNoValue);
6873 : 24 : return;
6874 : : }
6875 [ + - ]: 12 : ScDBQueryDataIterator aValIter( pDok, pQueryParam.release());
6876 [ + - ]: 12 : ScDBQueryDataIterator::Value aValue;
6877 [ + - ][ + - ]: 12 : if ( aValIter.GetFirst(aValue) && !aValue.mnError )
[ + - ][ + - ]
6878 : : {
6879 [ + + ][ + - ]: 48 : do
[ + + ]
6880 : : {
6881 : 48 : nCount++;
6882 : : }
6883 [ + - ]: 48 : while ( aValIter.GetNext(aValue) && !aValue.mnError );
6884 : : }
6885 [ + - ]: 12 : SetError(aValue.mnError);
6886 : : }
6887 [ + - ]: 24 : PushDouble( nCount );
6888 : : }
6889 : : else
6890 [ # # ][ + - ]: 24 : PushIllegalParameter();
[ + - ]
6891 : : }
6892 : :
6893 : :
6894 : 0 : void ScInterpreter::ScDBCount2()
6895 : : {
6896 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScDBCount2" );
6897 : 0 : bool bMissingField = true;
6898 : : SAL_WNODEPRECATED_DECLARATIONS_PUSH
6899 [ # # ]: 0 : auto_ptr<ScDBQueryParamBase> pQueryParam( GetDBParams(bMissingField) );
6900 : : SAL_WNODEPRECATED_DECLARATIONS_POP
6901 [ # # ]: 0 : if (pQueryParam.get())
6902 : : {
6903 [ # # ][ # # ]: 0 : if (!pQueryParam->IsValidFieldIndex())
6904 : : {
6905 : 0 : SetError(errNoValue);
6906 : 0 : return;
6907 : : }
6908 : 0 : sal_uLong nCount = 0;
6909 : 0 : pQueryParam->mbSkipString = false;
6910 [ # # ]: 0 : ScDBQueryDataIterator aValIter( pDok, pQueryParam.release());
6911 [ # # ]: 0 : ScDBQueryDataIterator::Value aValue;
6912 [ # # ][ # # ]: 0 : if ( aValIter.GetFirst(aValue) && !aValue.mnError )
[ # # ][ # # ]
6913 : : {
6914 [ # # ][ # # ]: 0 : do
[ # # ]
6915 : : {
6916 : 0 : nCount++;
6917 : : }
6918 [ # # ]: 0 : while ( aValIter.GetNext(aValue) && !aValue.mnError );
6919 : : }
6920 : 0 : SetError(aValue.mnError);
6921 [ # # ][ # # ]: 0 : PushDouble( nCount );
6922 : : }
6923 : : else
6924 [ # # ][ # # ]: 0 : PushIllegalParameter();
[ # # ]
6925 : : }
6926 : :
6927 : :
6928 : 0 : void ScInterpreter::ScDBAverage()
6929 : : {
6930 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScDBAverage" );
6931 : 0 : DBIterator( ifAVERAGE );
6932 : 0 : }
6933 : :
6934 : :
6935 : 0 : void ScInterpreter::ScDBMax()
6936 : : {
6937 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScDBMax" );
6938 : 0 : DBIterator( ifMAX );
6939 : 0 : }
6940 : :
6941 : :
6942 : 0 : void ScInterpreter::ScDBMin()
6943 : : {
6944 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScDBMin" );
6945 : 0 : DBIterator( ifMIN );
6946 : 0 : }
6947 : :
6948 : :
6949 : 0 : void ScInterpreter::ScDBProduct()
6950 : : {
6951 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScDBProduct" );
6952 : 0 : DBIterator( ifPRODUCT );
6953 : 0 : }
6954 : :
6955 : :
6956 : 0 : void ScInterpreter::GetDBStVarParams( double& rVal, double& rValCount )
6957 : : {
6958 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::GetDBStVarParams" );
6959 [ # # ]: 0 : std::vector<double> values;
6960 : 0 : double vSum = 0.0;
6961 : 0 : double vMean = 0.0;
6962 : :
6963 : 0 : rValCount = 0.0;
6964 : 0 : double fSum = 0.0;
6965 : 0 : bool bMissingField = false;
6966 : : SAL_WNODEPRECATED_DECLARATIONS_PUSH
6967 [ # # ]: 0 : auto_ptr<ScDBQueryParamBase> pQueryParam( GetDBParams(bMissingField) );
6968 : : SAL_WNODEPRECATED_DECLARATIONS_POP
6969 [ # # ]: 0 : if (pQueryParam.get())
6970 : : {
6971 [ # # ][ # # ]: 0 : if (!pQueryParam->IsValidFieldIndex())
6972 : : {
6973 : 0 : SetError(errNoValue);
6974 : 0 : return;
6975 : : }
6976 [ # # ]: 0 : ScDBQueryDataIterator aValIter(pDok, pQueryParam.release());
6977 [ # # ]: 0 : ScDBQueryDataIterator::Value aValue;
6978 [ # # ][ # # ]: 0 : if (aValIter.GetFirst(aValue) && !aValue.mnError)
[ # # ][ # # ]
6979 : : {
6980 [ # # ][ # # ]: 0 : do
[ # # ]
6981 : : {
6982 : 0 : rValCount++;
6983 [ # # ]: 0 : values.push_back(aValue.mfValue);
6984 : 0 : fSum += aValue.mfValue;
6985 : : }
6986 [ # # ]: 0 : while ((aValue.mnError == 0) && aValIter.GetNext(aValue));
6987 : : }
6988 [ # # ]: 0 : SetError(aValue.mnError);
6989 : : }
6990 : : else
6991 : 0 : SetError( errIllegalParameter);
6992 : :
6993 : 0 : vMean = fSum / values.size();
6994 : :
6995 [ # # ]: 0 : for (size_t i = 0; i < values.size(); i++)
6996 [ # # ][ # # ]: 0 : vSum += (values[i] - vMean) * (values[i] - vMean);
6997 : :
6998 [ # # ][ # # ]: 0 : rVal = vSum;
[ # # ]
6999 : : }
7000 : :
7001 : :
7002 : 0 : void ScInterpreter::ScDBStdDev()
7003 : : {
7004 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScDBStdDev" );
7005 : : double fVal, fCount;
7006 [ # # ]: 0 : GetDBStVarParams( fVal, fCount );
7007 [ # # ]: 0 : PushDouble( sqrt(fVal/(fCount-1)));
7008 : 0 : }
7009 : :
7010 : :
7011 : 0 : void ScInterpreter::ScDBStdDevP()
7012 : : {
7013 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScDBStdDevP" );
7014 : : double fVal, fCount;
7015 [ # # ]: 0 : GetDBStVarParams( fVal, fCount );
7016 [ # # ]: 0 : PushDouble( sqrt(fVal/fCount));
7017 : 0 : }
7018 : :
7019 : :
7020 : 0 : void ScInterpreter::ScDBVar()
7021 : : {
7022 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScDBVar" );
7023 : : double fVal, fCount;
7024 [ # # ]: 0 : GetDBStVarParams( fVal, fCount );
7025 [ # # ]: 0 : PushDouble(fVal/(fCount-1));
7026 : 0 : }
7027 : :
7028 : :
7029 : 0 : void ScInterpreter::ScDBVarP()
7030 : : {
7031 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScDBVarP" );
7032 : : double fVal, fCount;
7033 [ # # ]: 0 : GetDBStVarParams( fVal, fCount );
7034 [ # # ]: 0 : PushDouble(fVal/fCount);
7035 : 0 : }
7036 : :
7037 : 102 : void ScInterpreter::ScIndirect()
7038 : : {
7039 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScIndirect" );
7040 : 102 : sal_uInt8 nParamCount = GetByte();
7041 [ + - ]: 102 : if ( MustHaveParamCount( nParamCount, 1, 2 ) )
7042 : : {
7043 : : // Reference address syntax for INDIRECT is configurable.
7044 [ + - ]: 102 : FormulaGrammar::AddressConvention eConv = GetGlobalConfig().meStringRefAddressSyntax;
7045 [ + + ]: 102 : if (eConv == FormulaGrammar::CONV_UNSPECIFIED)
7046 : : // Use the current address syntax if unspecified.
7047 [ + - ]: 66 : eConv = pDok->GetAddressConvention();
7048 : :
7049 [ + + ][ + - ]: 102 : if (nParamCount == 2 && 0.0 == ::rtl::math::approxFloor( GetDouble()))
[ + - ][ + + ]
7050 : : {
7051 : : // Overwrite the config and try Excel R1C1.
7052 : 30 : eConv = FormulaGrammar::CONV_XL_R1C1;
7053 : : }
7054 [ + - ]: 102 : const ScAddress::Details aDetails( eConv, aPos );
7055 : 102 : SCTAB nTab = aPos.Tab();
7056 [ + - ][ + - ]: 102 : String sRefStr( GetString() );
7057 : 102 : ScRefAddress aRefAd, aRefAd2;
7058 : 102 : ScAddress::ExternalInfo aExtInfo;
7059 [ - + ][ + - ]: 102 : if (ConvertDoubleRef(pDok, sRefStr, nTab, aRefAd, aRefAd2, aDetails, &aExtInfo))
7060 : : {
7061 [ # # ]: 0 : if (aExtInfo.mbExternal)
7062 : : {
7063 : : PushExternalDoubleRef(
7064 : : aExtInfo.mnFileId, aExtInfo.maTabName,
7065 : 0 : aRefAd.Col(), aRefAd.Row(), aRefAd.Tab(),
7066 [ # # ][ # # ]: 0 : aRefAd2.Col(), aRefAd2.Row(), aRefAd2.Tab());
[ # # ]
7067 : : }
7068 : : else
7069 : 0 : PushDoubleRef( aRefAd.Col(), aRefAd.Row(), aRefAd.Tab(),
7070 [ # # ]: 0 : aRefAd2.Col(), aRefAd2.Row(), aRefAd2.Tab() );
7071 : : }
7072 [ + - ][ + + ]: 102 : else if (ConvertSingleRef(pDok, sRefStr, nTab, aRefAd, aDetails, &aExtInfo))
7073 : : {
7074 [ - + ]: 78 : if (aExtInfo.mbExternal)
7075 : : {
7076 : : PushExternalSingleRef(
7077 [ # # ][ # # ]: 0 : aExtInfo.mnFileId, aExtInfo.maTabName, aRefAd.Col(), aRefAd.Row(), aRefAd.Tab());
[ # # ]
7078 : : }
7079 : : else
7080 [ + - ]: 78 : PushSingleRef( aRefAd.Col(), aRefAd.Row(), aRefAd.Tab() );
7081 : : }
7082 : : else
7083 : : {
7084 : : do
7085 : : {
7086 [ + - ][ + - ]: 24 : ScRangeData* pData = ScRangeStringConverter::GetRangeDataFromString(sRefStr, nTab, pDok);
7087 [ - + ]: 24 : if (!pData)
7088 : : break;
7089 : :
7090 : : // We need this in order to obtain a good range.
7091 [ # # ]: 0 : pData->ValidateTabRefs();
7092 : :
7093 : 0 : ScRange aRange;
7094 : :
7095 : : // This is the usual way to treat named ranges containing
7096 : : // relative references.
7097 [ # # ][ # # ]: 0 : if (!pData->IsReference( aRange, aPos))
7098 : : break;
7099 : :
7100 [ # # ]: 0 : if (aRange.aStart == aRange.aEnd)
7101 : 0 : PushSingleRef( aRange.aStart.Col(), aRange.aStart.Row(),
7102 [ # # ]: 0 : aRange.aStart.Tab());
7103 : : else
7104 : 0 : PushDoubleRef( aRange.aStart.Col(), aRange.aStart.Row(),
7105 : 0 : aRange.aStart.Tab(), aRange.aEnd.Col(),
7106 [ # # ]: 0 : aRange.aEnd.Row(), aRange.aEnd.Tab());
7107 : :
7108 : : // success!
7109 : 102 : return;
7110 : : }
7111 : : while (false);
7112 : :
7113 [ + - ]: 102 : PushError( errNoRef);
7114 [ - + ][ + - ]: 102 : }
[ + - ]
7115 : : }
7116 : : }
7117 : :
7118 : :
7119 : 12 : void ScInterpreter::ScAddressFunc()
7120 : : {
7121 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScAddressFunc" );
7122 [ + - ]: 12 : String sTabStr;
7123 : :
7124 : 12 : sal_uInt8 nParamCount = GetByte();
7125 [ - + ][ + - ]: 12 : if( !MustHaveParamCount( nParamCount, 2, 5 ) )
7126 : : return;
7127 : :
7128 [ + + ]: 12 : if( nParamCount >= 5 )
7129 [ + - ][ + - ]: 6 : sTabStr = GetString();
7130 : :
7131 : 12 : FormulaGrammar::AddressConvention eConv = FormulaGrammar::CONV_OOO; // default
7132 [ + + ][ + - ]: 12 : if( nParamCount >= 4 && 0.0 == ::rtl::math::approxFloor( GetDoubleWithDefault( 1.0)))
[ + + ][ + + ]
7133 : 3 : eConv = FormulaGrammar::CONV_XL_R1C1;
7134 : :
7135 : 12 : sal_uInt16 nFlags = SCA_COL_ABSOLUTE | SCA_ROW_ABSOLUTE; // default
7136 [ + + ]: 12 : if( nParamCount >= 3 )
7137 : : {
7138 [ + - ]: 6 : sal_uInt16 n = (sal_uInt16) ::rtl::math::approxFloor( GetDoubleWithDefault( 1.0));
7139 [ - + + - : 6 : switch ( n )
- ]
7140 : : {
7141 : : default :
7142 [ # # ]: 0 : PushNoValue();
7143 : : return;
7144 : :
7145 : : case 5:
7146 : 3 : case 1 : break; // default
7147 : : case 6:
7148 : 3 : case 2 : nFlags = SCA_ROW_ABSOLUTE; break;
7149 : : case 7:
7150 : 0 : case 3 : nFlags = SCA_COL_ABSOLUTE; break;
7151 : : case 8:
7152 : 6 : case 4 : nFlags = 0; break; // both relative
7153 : : }
7154 : : }
7155 : 12 : nFlags |= SCA_VALID | SCA_VALID_ROW | SCA_VALID_COL;
7156 : :
7157 [ + - ]: 12 : SCCOL nCol = (SCCOL) ::rtl::math::approxFloor(GetDouble());
7158 [ + - ]: 12 : SCROW nRow = (SCROW) ::rtl::math::approxFloor(GetDouble());
7159 [ + + ]: 12 : if( eConv == FormulaGrammar::CONV_XL_R1C1 )
7160 : : {
7161 : : // YUCK! The XL interface actually treats rel R1C1 refs differently
7162 : : // than A1
7163 [ - + ]: 3 : if( !(nFlags & SCA_COL_ABSOLUTE) )
7164 : 0 : nCol += aPos.Col() + 1;
7165 [ - + ]: 3 : if( !(nFlags & SCA_ROW_ABSOLUTE) )
7166 : 0 : nRow += aPos.Row() + 1;
7167 : : }
7168 : :
7169 : 12 : --nCol;
7170 : 12 : --nRow;
7171 [ + - ][ - + ]: 12 : if(!ValidCol( nCol) || !ValidRow( nRow))
[ - + ]
7172 : : {
7173 [ # # ]: 0 : PushIllegalArgument();
7174 : : return;
7175 : : }
7176 : :
7177 [ + - ]: 12 : String aRefStr;
7178 [ + - ]: 12 : const ScAddress::Details aDetails( eConv, aPos );
7179 : 12 : const ScAddress aAdr( nCol, nRow, 0);
7180 [ + - ]: 12 : aAdr.Format( aRefStr, nFlags, pDok, aDetails );
7181 : :
7182 [ + + ]: 12 : if( nParamCount >= 5 )
7183 : : {
7184 [ + - ]: 6 : ScCompiler::CheckTabQuotes( sTabStr, eConv);
7185 [ + + ][ + - ]: 6 : sTabStr += static_cast<sal_Unicode>(eConv == FormulaGrammar::CONV_XL_R1C1 ? '!' : '.');
7186 [ + - ]: 6 : sTabStr += aRefStr;
7187 [ + - ]: 6 : PushString( sTabStr );
7188 : : }
7189 : : else
7190 [ + - ][ + - ]: 12 : PushString( aRefStr );
[ + - ][ + - ]
7191 : : }
7192 : :
7193 : :
7194 : 0 : void ScInterpreter::ScOffset()
7195 : : {
7196 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScOffset" );
7197 : 0 : sal_uInt8 nParamCount = GetByte();
7198 [ # # ]: 0 : if ( MustHaveParamCount( nParamCount, 3, 5 ) )
7199 : : {
7200 : 0 : long nColNew = -1, nRowNew = -1, nColPlus, nRowPlus;
7201 [ # # ]: 0 : if (nParamCount == 5)
7202 [ # # ]: 0 : nColNew = (long) ::rtl::math::approxFloor(GetDouble());
7203 [ # # ]: 0 : if (nParamCount >= 4)
7204 [ # # ]: 0 : nRowNew = (long) ::rtl::math::approxFloor(GetDoubleWithDefault( -1.0 ));
7205 [ # # ]: 0 : nColPlus = (long) ::rtl::math::approxFloor(GetDouble());
7206 [ # # ]: 0 : nRowPlus = (long) ::rtl::math::approxFloor(GetDouble());
7207 : 0 : SCCOL nCol1(0);
7208 : 0 : SCROW nRow1(0);
7209 : 0 : SCTAB nTab1(0);
7210 : 0 : SCCOL nCol2(0);
7211 : 0 : SCROW nRow2(0);
7212 : 0 : SCTAB nTab2(0);
7213 [ # # ][ # # ]: 0 : if (nColNew == 0 || nRowNew == 0)
7214 : : {
7215 [ # # ]: 0 : PushIllegalArgument();
7216 : 0 : return;
7217 : : }
7218 [ # # ][ # # ]: 0 : if (GetStackType() == svSingleRef)
7219 : : {
7220 [ # # ]: 0 : PopSingleRef(nCol1, nRow1, nTab1);
7221 [ # # ][ # # ]: 0 : if (nParamCount == 3 || (nColNew < 0 && nRowNew < 0))
[ # # ]
7222 : : {
7223 : 0 : nCol1 = (SCCOL)((long) nCol1 + nColPlus);
7224 : 0 : nRow1 = (SCROW)((long) nRow1 + nRowPlus);
7225 [ # # ][ # # ]: 0 : if (!ValidCol(nCol1) || !ValidRow(nRow1))
[ # # ]
7226 [ # # ]: 0 : PushIllegalArgument();
7227 : : else
7228 [ # # ]: 0 : PushSingleRef(nCol1, nRow1, nTab1);
7229 : : }
7230 : : else
7231 : : {
7232 [ # # ]: 0 : if (nColNew < 0)
7233 : 0 : nColNew = 1;
7234 [ # # ]: 0 : if (nRowNew < 0)
7235 : 0 : nRowNew = 1;
7236 : 0 : nCol1 = (SCCOL)((long)nCol1+nColPlus); // ! nCol1 wird veraendert!
7237 : 0 : nRow1 = (SCROW)((long)nRow1+nRowPlus);
7238 : 0 : nCol2 = (SCCOL)((long)nCol1+nColNew-1);
7239 : 0 : nRow2 = (SCROW)((long)nRow1+nRowNew-1);
7240 [ # # ][ # # : 0 : if (!ValidCol(nCol1) || !ValidRow(nRow1) ||
# # # # ]
[ # # ]
7241 : 0 : !ValidCol(nCol2) || !ValidRow(nRow2))
7242 [ # # ]: 0 : PushIllegalArgument();
7243 : : else
7244 [ # # ]: 0 : PushDoubleRef(nCol1, nRow1, nTab1, nCol2, nRow2, nTab1);
7245 : : }
7246 : : }
7247 [ # # ][ # # ]: 0 : else if (GetStackType() == svExternalSingleRef)
7248 : : {
7249 : : sal_uInt16 nFileId;
7250 [ # # ]: 0 : String aTabName;
7251 : : ScSingleRefData aRef;
7252 [ # # ]: 0 : PopExternalSingleRef(nFileId, aTabName, aRef);
7253 [ # # ]: 0 : aRef.CalcAbsIfRel(aPos);
7254 : 0 : nCol1 = aRef.nCol;
7255 : 0 : nRow1 = aRef.nRow;
7256 : 0 : nTab1 = aRef.nTab;
7257 : :
7258 [ # # ][ # # ]: 0 : if (nParamCount == 3 || (nColNew < 0 && nRowNew < 0))
[ # # ]
7259 : : {
7260 : 0 : nCol1 = (SCCOL)((long) nCol1 + nColPlus);
7261 : 0 : nRow1 = (SCROW)((long) nRow1 + nRowPlus);
7262 [ # # ][ # # ]: 0 : if (!ValidCol(nCol1) || !ValidRow(nRow1))
[ # # ]
7263 [ # # ]: 0 : PushIllegalArgument();
7264 : : else
7265 [ # # ]: 0 : PushExternalSingleRef(nFileId, aTabName, nCol1, nRow1, nTab1);
7266 : : }
7267 : : else
7268 : : {
7269 [ # # ]: 0 : if (nColNew < 0)
7270 : 0 : nColNew = 1;
7271 [ # # ]: 0 : if (nRowNew < 0)
7272 : 0 : nRowNew = 1;
7273 : 0 : nCol1 = (SCCOL)((long)nCol1+nColPlus); // ! nCol1 wird veraendert!
7274 : 0 : nRow1 = (SCROW)((long)nRow1+nRowPlus);
7275 : 0 : nCol2 = (SCCOL)((long)nCol1+nColNew-1);
7276 : 0 : nTab2 = nTab1;
7277 [ # # ][ # # : 0 : if (!ValidCol(nCol1) || !ValidRow(nRow1) ||
# # # # ]
[ # # ]
7278 : 0 : !ValidCol(nCol2) || !ValidRow(nRow2))
7279 [ # # ]: 0 : PushIllegalArgument();
7280 : : else
7281 [ # # ]: 0 : PushExternalDoubleRef(nFileId, aTabName, nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
7282 [ # # ]: 0 : }
7283 : : }
7284 [ # # ][ # # ]: 0 : else if (GetStackType() == svDoubleRef)
7285 : : {
7286 [ # # ]: 0 : PopDoubleRef(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
7287 [ # # ]: 0 : if (nColNew < 0)
7288 : 0 : nColNew = nCol2 - nCol1 + 1;
7289 [ # # ]: 0 : if (nRowNew < 0)
7290 : 0 : nRowNew = nRow2 - nRow1 + 1;
7291 : 0 : nCol1 = (SCCOL)((long)nCol1+nColPlus);
7292 : 0 : nRow1 = (SCROW)((long)nRow1+nRowPlus);
7293 : 0 : nCol2 = (SCCOL)((long)nCol1+nColNew-1);
7294 : 0 : nRow2 = (SCROW)((long)nRow1+nRowNew-1);
7295 [ # # ][ # # : 0 : if (!ValidCol(nCol1) || !ValidRow(nRow1) ||
# # # # ]
[ # # ][ # # ]
7296 : 0 : !ValidCol(nCol2) || !ValidRow(nRow2) || nTab1 != nTab2)
7297 [ # # ]: 0 : PushIllegalArgument();
7298 : : else
7299 [ # # ]: 0 : PushDoubleRef(nCol1, nRow1, nTab1, nCol2, nRow2, nTab1);
7300 : : }
7301 [ # # ][ # # ]: 0 : else if (GetStackType() == svExternalDoubleRef)
7302 : : {
7303 : : sal_uInt16 nFileId;
7304 [ # # ]: 0 : String aTabName;
7305 : : ScComplexRefData aRef;
7306 [ # # ]: 0 : PopExternalDoubleRef(nFileId, aTabName, aRef);
7307 [ # # ]: 0 : aRef.CalcAbsIfRel(aPos);
7308 : 0 : nCol1 = aRef.Ref1.nCol;
7309 : 0 : nRow1 = aRef.Ref1.nRow;
7310 : 0 : nTab1 = aRef.Ref1.nTab;
7311 : 0 : nCol2 = aRef.Ref2.nCol;
7312 : 0 : nRow2 = aRef.Ref2.nRow;
7313 : 0 : nTab2 = aRef.Ref2.nTab;
7314 [ # # ]: 0 : if (nColNew < 0)
7315 : 0 : nColNew = nCol2 - nCol1 + 1;
7316 [ # # ]: 0 : if (nRowNew < 0)
7317 : 0 : nRowNew = nRow2 - nRow1 + 1;
7318 : 0 : nCol1 = (SCCOL)((long)nCol1+nColPlus);
7319 : 0 : nRow1 = (SCROW)((long)nRow1+nRowPlus);
7320 : 0 : nCol2 = (SCCOL)((long)nCol1+nColNew-1);
7321 : 0 : nRow2 = (SCROW)((long)nRow1+nRowNew-1);
7322 [ # # ][ # # : 0 : if (!ValidCol(nCol1) || !ValidRow(nRow1) ||
# # # # ]
[ # # ][ # # ]
7323 : 0 : !ValidCol(nCol2) || !ValidRow(nRow2) || nTab1 != nTab2)
7324 [ # # ]: 0 : PushIllegalArgument();
7325 : : else
7326 [ # # ][ # # ]: 0 : PushExternalDoubleRef(nFileId, aTabName, nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
7327 : : }
7328 : : else
7329 [ # # ]: 0 : PushIllegalParameter();
7330 : : }
7331 : : }
7332 : :
7333 : :
7334 : 0 : void ScInterpreter::ScIndex()
7335 : : {
7336 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScIndex" );
7337 : 0 : sal_uInt8 nParamCount = GetByte();
7338 [ # # ]: 0 : if ( MustHaveParamCount( nParamCount, 1, 4 ) )
7339 : : {
7340 : : long nArea;
7341 : : size_t nAreaCount;
7342 : : SCCOL nCol;
7343 : : SCROW nRow;
7344 [ # # ]: 0 : if (nParamCount == 4)
7345 : 0 : nArea = (long) ::rtl::math::approxFloor(GetDouble());
7346 : : else
7347 : 0 : nArea = 1;
7348 [ # # ]: 0 : if (nParamCount >= 3)
7349 : 0 : nCol = (SCCOL) ::rtl::math::approxFloor(GetDouble());
7350 : : else
7351 : 0 : nCol = 0;
7352 [ # # ]: 0 : if (nParamCount >= 2)
7353 : 0 : nRow = (SCROW) ::rtl::math::approxFloor(GetDouble());
7354 : : else
7355 : 0 : nRow = 0;
7356 [ # # ]: 0 : if (GetStackType() == svRefList)
7357 [ # # ]: 0 : nAreaCount = (sp ? static_cast<ScToken*>(pStack[sp-1])->GetRefList()->size() : 0);
7358 : : else
7359 : 0 : nAreaCount = 1; // one reference or array or whatever
7360 [ # # ][ # # ]: 0 : if (nAreaCount == 0 || (size_t)nArea > nAreaCount)
7361 : : {
7362 : 0 : PushError( errNoRef);
7363 : 0 : return;
7364 : : }
7365 [ # # ][ # # ]: 0 : else if (nArea < 1 || nCol < 0 || nRow < 0)
[ # # ]
7366 : : {
7367 : 0 : PushIllegalArgument();
7368 : 0 : return;
7369 : : }
7370 [ # # # # ]: 0 : switch (GetStackType())
7371 : : {
7372 : : case svMatrix:
7373 : : case svExternalSingleRef:
7374 : : case svExternalDoubleRef:
7375 : : {
7376 [ # # ]: 0 : if (nArea != 1)
7377 : 0 : SetError(errIllegalArgument);
7378 : 0 : sal_uInt16 nOldSp = sp;
7379 [ # # ]: 0 : ScMatrixRef pMat = GetMatrix();
7380 [ # # ]: 0 : if (pMat)
7381 : : {
7382 : : SCSIZE nC, nR;
7383 [ # # ]: 0 : pMat->GetDimensions(nC, nR);
7384 : : // Access one element of a vector independent of col/row
7385 : : // orientation?
7386 [ # # ][ # # ]: 0 : bool bVector = ((nCol == 0 || nRow == 0) && (nC == 1 || nR == 1));
[ # # ][ # # ]
7387 : : SCSIZE nElement = ::std::max( static_cast<SCSIZE>(nCol),
7388 [ # # ]: 0 : static_cast<SCSIZE>(nRow));
7389 [ # # ][ # # ]: 0 : if (nC == 0 || nR == 0 ||
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
7390 : 0 : (!bVector && (static_cast<SCSIZE>(nCol) > nC ||
7391 : : static_cast<SCSIZE>(nRow) > nR)) ||
7392 : : (bVector && nElement > nC * nR))
7393 [ # # ]: 0 : PushIllegalArgument();
7394 [ # # ][ # # ]: 0 : else if (nCol == 0 && nRow == 0)
7395 : 0 : sp = nOldSp;
7396 [ # # ]: 0 : else if (bVector)
7397 : : {
7398 : 0 : --nElement;
7399 [ # # ][ # # ]: 0 : if (pMat->IsString( nElement))
7400 [ # # ][ # # ]: 0 : PushString( pMat->GetString( nElement));
[ # # ][ # # ]
7401 : : else
7402 [ # # ][ # # ]: 0 : PushDouble( pMat->GetDouble( nElement));
7403 : : }
7404 [ # # ]: 0 : else if (nCol == 0)
7405 : : {
7406 [ # # ]: 0 : ScMatrixRef pResMat = GetNewMat(nC, 1);
7407 [ # # ]: 0 : if (pResMat)
7408 : : {
7409 : 0 : SCSIZE nRowMinus1 = static_cast<SCSIZE>(nRow - 1);
7410 [ # # ]: 0 : for (SCSIZE i = 0; i < nC; i++)
7411 [ # # ][ # # ]: 0 : if (!pMat->IsString(i, nRowMinus1))
7412 : : pResMat->PutDouble(pMat->GetDouble(i,
7413 [ # # ][ # # ]: 0 : nRowMinus1), i, 0);
7414 : : else
7415 : : pResMat->PutString(pMat->GetString(i,
7416 [ # # ][ # # ]: 0 : nRowMinus1), i, 0);
7417 [ # # ]: 0 : PushMatrix(pResMat);
7418 : : }
7419 : : else
7420 [ # # ][ # # ]: 0 : PushIllegalArgument();
7421 : : }
7422 [ # # ]: 0 : else if (nRow == 0)
7423 : : {
7424 [ # # ]: 0 : ScMatrixRef pResMat = GetNewMat(1, nR);
7425 [ # # ]: 0 : if (pResMat)
7426 : : {
7427 : 0 : SCSIZE nColMinus1 = static_cast<SCSIZE>(nCol - 1);
7428 [ # # ]: 0 : for (SCSIZE i = 0; i < nR; i++)
7429 [ # # ][ # # ]: 0 : if (!pMat->IsString(nColMinus1, i))
7430 : : pResMat->PutDouble(pMat->GetDouble(nColMinus1,
7431 [ # # ][ # # ]: 0 : i), i);
7432 : : else
7433 : : pResMat->PutString(pMat->GetString(nColMinus1,
7434 [ # # ][ # # ]: 0 : i), i);
7435 [ # # ]: 0 : PushMatrix(pResMat);
7436 : : }
7437 : : else
7438 [ # # ][ # # ]: 0 : PushIllegalArgument();
7439 : : }
7440 : : else
7441 : : {
7442 [ # # ]: 0 : if (!pMat->IsString( static_cast<SCSIZE>(nCol-1),
7443 [ # # ]: 0 : static_cast<SCSIZE>(nRow-1)))
7444 : : PushDouble( pMat->GetDouble(
7445 : : static_cast<SCSIZE>(nCol-1),
7446 [ # # ][ # # ]: 0 : static_cast<SCSIZE>(nRow-1)));
7447 : : else
7448 : : PushString( pMat->GetString(
7449 : : static_cast<SCSIZE>(nCol-1),
7450 [ # # ][ # # ]: 0 : static_cast<SCSIZE>(nRow-1)));
[ # # ][ # # ]
7451 : : }
7452 [ # # ]: 0 : }
7453 : : }
7454 : 0 : break;
7455 : : case svSingleRef:
7456 : : {
7457 : 0 : SCCOL nCol1 = 0;
7458 : 0 : SCROW nRow1 = 0;
7459 : 0 : SCTAB nTab1 = 0;
7460 [ # # ]: 0 : PopSingleRef( nCol1, nRow1, nTab1);
7461 [ # # ][ # # ]: 0 : if (nCol > 1 || nRow > 1)
7462 [ # # ]: 0 : PushIllegalArgument();
7463 : : else
7464 [ # # ]: 0 : PushSingleRef( nCol1, nRow1, nTab1);
7465 : : }
7466 : 0 : break;
7467 : : case svDoubleRef:
7468 : : case svRefList:
7469 : : {
7470 : 0 : SCCOL nCol1 = 0;
7471 : 0 : SCROW nRow1 = 0;
7472 : 0 : SCTAB nTab1 = 0;
7473 : 0 : SCCOL nCol2 = 0;
7474 : 0 : SCROW nRow2 = 0;
7475 : 0 : SCTAB nTab2 = 0;
7476 : 0 : bool bRowArray = false;
7477 [ # # ][ # # ]: 0 : if (GetStackType() == svRefList)
7478 : : {
7479 [ # # ]: 0 : FormulaTokenRef xRef = PopToken();
7480 [ # # ][ # # ]: 0 : if (nGlobalError || !xRef)
[ # # ]
7481 : : {
7482 [ # # ]: 0 : PushIllegalParameter();
7483 : : return;
7484 : : }
7485 : 0 : ScRange aRange( ScAddress::UNINITIALIZED);
7486 [ # # ][ # # ]: 0 : DoubleRefToRange( (*(static_cast<ScToken*>(xRef.get())->GetRefList()))[nArea-1], aRange);
7487 : 0 : aRange.GetVars( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
7488 [ # # ][ # # ]: 0 : if ( nParamCount == 2 && nRow1 == nRow2 )
7489 [ # # ][ # # ]: 0 : bRowArray = true;
7490 : : }
7491 : : else
7492 : : {
7493 [ # # ]: 0 : PopDoubleRef( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
7494 [ # # ][ # # ]: 0 : if ( nParamCount == 2 && nRow1 == nRow2 )
7495 : 0 : bRowArray = true;
7496 : : }
7497 [ # # ][ # # ]: 0 : if ( nTab1 != nTab2 ||
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
7498 : : (nCol > 0 && nCol1+nCol-1 > nCol2) ||
7499 : 0 : (nRow > 0 && nRow1+nRow-1 > nRow2 && !bRowArray ) ||
7500 : : ( nRow > nCol2 - nCol1 + 1 && bRowArray ))
7501 [ # # ]: 0 : PushIllegalArgument();
7502 [ # # ][ # # ]: 0 : else if (nCol == 0 && nRow == 0)
7503 : : {
7504 [ # # ][ # # ]: 0 : if ( nCol1 == nCol2 && nRow1 == nRow2 )
7505 [ # # ]: 0 : PushSingleRef( nCol1, nRow1, nTab1 );
7506 : : else
7507 [ # # ]: 0 : PushDoubleRef( nCol1, nRow1, nTab1, nCol2, nRow2, nTab1 );
7508 : : }
7509 [ # # ]: 0 : else if (nRow == 0)
7510 : : {
7511 [ # # ]: 0 : if ( nRow1 == nRow2 )
7512 [ # # ]: 0 : PushSingleRef( nCol1+nCol-1, nRow1, nTab1 );
7513 : : else
7514 : : PushDoubleRef( nCol1+nCol-1, nRow1, nTab1,
7515 [ # # ]: 0 : nCol1+nCol-1, nRow2, nTab1 );
7516 : : }
7517 [ # # ]: 0 : else if (nCol == 0)
7518 : : {
7519 [ # # ]: 0 : if ( nCol1 == nCol2 )
7520 [ # # ]: 0 : PushSingleRef( nCol1, nRow1+nRow-1, nTab1 );
7521 [ # # ]: 0 : else if ( bRowArray )
7522 : : {
7523 : 0 : nCol =(SCCOL) nRow;
7524 : 0 : nRow = 1;
7525 [ # # ]: 0 : PushSingleRef( nCol1+nCol-1, nRow1+nRow-1, nTab1);
7526 : : }
7527 : : else
7528 : : PushDoubleRef( nCol1, nRow1+nRow-1, nTab1,
7529 [ # # ]: 0 : nCol2, nRow1+nRow-1, nTab1);
7530 : : }
7531 : : else
7532 [ # # ]: 0 : PushSingleRef( nCol1+nCol-1, nRow1+nRow-1, nTab1);
7533 : : }
7534 : 0 : break;
7535 : : default:
7536 : 0 : PushIllegalParameter();
7537 : : }
7538 : : }
7539 : : }
7540 : :
7541 : :
7542 : 0 : void ScInterpreter::ScMultiArea()
7543 : : {
7544 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScMultiArea" );
7545 : : // Legacy support, convert to RefList
7546 : 0 : sal_uInt8 nParamCount = GetByte();
7547 [ # # ]: 0 : if (MustHaveParamCountMin( nParamCount, 1))
7548 : : {
7549 [ # # ][ # # ]: 0 : while (!nGlobalError && nParamCount-- > 1)
[ # # ]
7550 : : {
7551 : 0 : ScUnionFunc();
7552 : : }
7553 : : }
7554 : 0 : }
7555 : :
7556 : :
7557 : 0 : void ScInterpreter::ScAreas()
7558 : : {
7559 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScAreas" );
7560 : 0 : sal_uInt8 nParamCount = GetByte();
7561 [ # # ]: 0 : if (MustHaveParamCount( nParamCount, 1))
7562 : : {
7563 : 0 : size_t nCount = 0;
7564 [ # # # # ]: 0 : switch (GetStackType())
7565 : : {
7566 : : case svSingleRef:
7567 : : {
7568 [ # # ]: 0 : FormulaTokenRef xT = PopToken();
7569 [ # # ][ # # ]: 0 : ValidateRef( static_cast<ScToken*>(xT.get())->GetSingleRef());
7570 [ # # ]: 0 : ++nCount;
7571 : : }
7572 : 0 : break;
7573 : : case svDoubleRef:
7574 : : {
7575 [ # # ]: 0 : FormulaTokenRef xT = PopToken();
7576 [ # # ][ # # ]: 0 : ValidateRef( static_cast<ScToken*>(xT.get())->GetDoubleRef());
7577 [ # # ]: 0 : ++nCount;
7578 : : }
7579 : 0 : break;
7580 : : case svRefList:
7581 : : {
7582 [ # # ]: 0 : FormulaTokenRef xT = PopToken();
7583 [ # # ][ # # ]: 0 : ValidateRef( *(static_cast<ScToken*>(xT.get())->GetRefList()));
7584 [ # # ][ # # ]: 0 : nCount += static_cast<ScToken*>(xT.get())->GetRefList()->size();
7585 : : }
7586 : 0 : break;
7587 : : default:
7588 : 0 : SetError( errIllegalParameter);
7589 : : }
7590 : 0 : PushDouble( double(nCount));
7591 : : }
7592 : 0 : }
7593 : :
7594 : :
7595 : 0 : void ScInterpreter::ScCurrency()
7596 : : {
7597 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScCurrency" );
7598 : 0 : sal_uInt8 nParamCount = GetByte();
7599 [ # # ]: 0 : if ( MustHaveParamCount( nParamCount, 1, 2 ) )
7600 : : {
7601 [ # # ]: 0 : String aStr;
7602 : : double fDec;
7603 [ # # ]: 0 : if (nParamCount == 2)
7604 : : {
7605 [ # # ]: 0 : fDec = ::rtl::math::approxFloor(GetDouble());
7606 [ # # ][ # # ]: 0 : if (fDec < -15.0 || fDec > 15.0)
7607 : : {
7608 [ # # ]: 0 : PushIllegalArgument();
7609 : 0 : return;
7610 : : }
7611 : : }
7612 : : else
7613 : 0 : fDec = 2.0;
7614 [ # # ]: 0 : double fVal = GetDouble();
7615 : : double fFac;
7616 [ # # ]: 0 : if ( fDec != 0.0 )
7617 : 0 : fFac = pow( (double)10, fDec );
7618 : : else
7619 : 0 : fFac = 1.0;
7620 [ # # ]: 0 : if (fVal < 0.0)
7621 : 0 : fVal = ceil(fVal*fFac-0.5)/fFac;
7622 : : else
7623 : 0 : fVal = floor(fVal*fFac+0.5)/fFac;
7624 : 0 : Color* pColor = NULL;
7625 [ # # ]: 0 : if ( fDec < 0.0 )
7626 : 0 : fDec = 0.0;
7627 : : sal_uLong nIndex = pFormatter->GetStandardFormat(
7628 : : NUMBERFORMAT_CURRENCY,
7629 [ # # ]: 0 : ScGlobal::eLnge);
7630 [ # # ][ # # ]: 0 : if ( (sal_uInt16) fDec != pFormatter->GetFormatPrecision( nIndex ) )
7631 : : {
7632 [ # # ]: 0 : String sFormatString;
7633 : : pFormatter->GenerateFormat(sFormatString,
7634 : : nIndex,
7635 : : ScGlobal::eLnge,
7636 : : true, // mit Tausenderpunkt
7637 : : false, // nicht rot
7638 : : (sal_uInt16) fDec,// Nachkommastellen
7639 [ # # ]: 0 : 1); // 1 Vorkommanull
7640 [ # # ]: 0 : if (!pFormatter->GetPreviewString(sFormatString,
7641 : : fVal,
7642 : : aStr,
7643 : : &pColor,
7644 [ # # ]: 0 : ScGlobal::eLnge))
7645 [ # # ]: 0 : SetError(errIllegalArgument);
7646 : : }
7647 : : else
7648 : : {
7649 [ # # ]: 0 : pFormatter->GetOutputString(fVal, nIndex, aStr, &pColor);
7650 : : }
7651 [ # # ][ # # ]: 0 : PushString(aStr);
[ # # ]
7652 : : }
7653 : : }
7654 : :
7655 : :
7656 : 0 : void ScInterpreter::ScReplace()
7657 : : {
7658 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScReplace" );
7659 [ # # ]: 0 : if ( MustHaveParamCount( GetByte(), 4 ) )
7660 : : {
7661 [ # # ][ # # ]: 0 : String aNewStr( GetString() );
7662 [ # # ]: 0 : double fCount = ::rtl::math::approxFloor( GetDouble());
7663 [ # # ]: 0 : double fPos = ::rtl::math::approxFloor( GetDouble());
7664 [ # # ][ # # ]: 0 : String aOldStr( GetString() );
7665 [ # # ][ # # ]: 0 : if (fPos < 1.0 || fPos > static_cast<double>(STRING_MAXLEN)
[ # # ][ # # ]
7666 : : || fCount < 0.0 || fCount > static_cast<double>(STRING_MAXLEN))
7667 [ # # ]: 0 : PushIllegalArgument();
7668 : : else
7669 : : {
7670 : 0 : xub_StrLen nCount = static_cast<xub_StrLen>(fCount);
7671 : 0 : xub_StrLen nPos = static_cast<xub_StrLen>(fPos);
7672 : 0 : xub_StrLen nLen = aOldStr.Len();
7673 [ # # ]: 0 : if (nPos > nLen + 1)
7674 : 0 : nPos = nLen + 1;
7675 [ # # ]: 0 : if (nCount > nLen - nPos + 1)
7676 : 0 : nCount = nLen - nPos + 1;
7677 [ # # ]: 0 : aOldStr.Erase( nPos-1, nCount );
7678 [ # # ][ # # ]: 0 : if ( CheckStringResultLen( aOldStr, aNewStr ) )
7679 [ # # ]: 0 : aOldStr.Insert( aNewStr, nPos-1 );
7680 [ # # ]: 0 : PushString( aOldStr );
7681 [ # # ][ # # ]: 0 : }
7682 : : }
7683 : 0 : }
7684 : :
7685 : :
7686 : 0 : void ScInterpreter::ScFixed()
7687 : : {
7688 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScFixed" );
7689 : 0 : sal_uInt8 nParamCount = GetByte();
7690 [ # # ]: 0 : if ( MustHaveParamCount( nParamCount, 1, 3 ) )
7691 : : {
7692 [ # # ]: 0 : String aStr;
7693 : : double fDec;
7694 : : bool bThousand;
7695 [ # # ]: 0 : if (nParamCount == 3)
7696 [ # # ]: 0 : bThousand = !GetBool(); // Param TRUE: keine Tausenderpunkte
7697 : : else
7698 : 0 : bThousand = true;
7699 [ # # ]: 0 : if (nParamCount >= 2)
7700 : : {
7701 [ # # ]: 0 : fDec = ::rtl::math::approxFloor(GetDoubleWithDefault( 2.0 ));
7702 [ # # ][ # # ]: 0 : if (fDec < -15.0 || fDec > 15.0)
7703 : : {
7704 [ # # ]: 0 : PushIllegalArgument();
7705 : 0 : return;
7706 : : }
7707 : : }
7708 : : else
7709 : 0 : fDec = 2.0;
7710 [ # # ]: 0 : double fVal = GetDouble();
7711 : : double fFac;
7712 [ # # ]: 0 : if ( fDec != 0.0 )
7713 : 0 : fFac = pow( (double)10, fDec );
7714 : : else
7715 : 0 : fFac = 1.0;
7716 [ # # ]: 0 : if (fVal < 0.0)
7717 : 0 : fVal = ceil(fVal*fFac-0.5)/fFac;
7718 : : else
7719 : 0 : fVal = floor(fVal*fFac+0.5)/fFac;
7720 : 0 : Color* pColor = NULL;
7721 [ # # ]: 0 : String sFormatString;
7722 [ # # ]: 0 : if (fDec < 0.0)
7723 : 0 : fDec = 0.0;
7724 : : sal_uLong nIndex = pFormatter->GetStandardFormat(
7725 : : NUMBERFORMAT_NUMBER,
7726 [ # # ]: 0 : ScGlobal::eLnge);
7727 : : pFormatter->GenerateFormat(sFormatString,
7728 : : nIndex,
7729 : : ScGlobal::eLnge,
7730 : : bThousand, // mit Tausenderpunkt
7731 : : false, // nicht rot
7732 : : (sal_uInt16) fDec,// Nachkommastellen
7733 [ # # ]: 0 : 1); // 1 Vorkommanull
7734 [ # # ]: 0 : if (!pFormatter->GetPreviewString(sFormatString,
7735 : : fVal,
7736 : : aStr,
7737 : : &pColor,
7738 [ # # ]: 0 : ScGlobal::eLnge))
7739 [ # # ]: 0 : PushIllegalArgument();
7740 : : else
7741 [ # # ][ # # ]: 0 : PushString(aStr);
[ # # ][ # # ]
7742 : : }
7743 : : }
7744 : :
7745 : :
7746 : 0 : void ScInterpreter::ScFind()
7747 : : {
7748 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScFind" );
7749 : 0 : sal_uInt8 nParamCount = GetByte();
7750 [ # # ]: 0 : if ( MustHaveParamCount( nParamCount, 2, 3 ) )
7751 : : {
7752 : : double fAnz;
7753 [ # # ]: 0 : if (nParamCount == 3)
7754 [ # # ]: 0 : fAnz = GetDouble();
7755 : : else
7756 : 0 : fAnz = 1.0;
7757 [ # # ][ # # ]: 0 : String sStr = GetString();
7758 [ # # ][ # # ]: 0 : if( fAnz < 1.0 || fAnz > (double) sStr.Len() )
[ # # ]
7759 [ # # ]: 0 : PushNoValue();
7760 : : else
7761 : : {
7762 [ # # ][ # # ]: 0 : xub_StrLen nPos = sStr.Search( GetString(), (xub_StrLen) fAnz - 1 );
7763 [ # # ]: 0 : if (nPos == STRING_NOTFOUND)
7764 [ # # ]: 0 : PushNoValue();
7765 : : else
7766 [ # # ]: 0 : PushDouble((double)(nPos + 1));
7767 [ # # ]: 0 : }
7768 : : }
7769 : 0 : }
7770 : :
7771 : :
7772 : 0 : void ScInterpreter::ScExact()
7773 : : {
7774 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScExact" );
7775 : 0 : nFuncFmtType = NUMBERFORMAT_LOGICAL;
7776 [ # # ]: 0 : if ( MustHaveParamCount( GetByte(), 2 ) )
7777 : : {
7778 [ # # ][ # # ]: 0 : String s1( GetString() );
7779 [ # # ][ # # ]: 0 : String s2( GetString() );
7780 [ # # ][ # # ]: 0 : PushInt( s1 == s2 );
[ # # ][ # # ]
7781 : : }
7782 : 0 : }
7783 : :
7784 : :
7785 : 0 : void ScInterpreter::ScLeft()
7786 : : {
7787 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScLeft" );
7788 : 0 : sal_uInt8 nParamCount = GetByte();
7789 [ # # ]: 0 : if ( MustHaveParamCount( nParamCount, 1, 2 ) )
7790 : : {
7791 : : xub_StrLen n;
7792 [ # # ]: 0 : if (nParamCount == 2)
7793 : : {
7794 [ # # ]: 0 : double nVal = ::rtl::math::approxFloor(GetDouble());
7795 [ # # ][ # # ]: 0 : if ( nVal < 0.0 || nVal > STRING_MAXLEN )
7796 : : {
7797 [ # # ]: 0 : PushIllegalArgument();
7798 : 0 : return ;
7799 : : }
7800 : : else
7801 : 0 : n = (xub_StrLen) nVal;
7802 : : }
7803 : : else
7804 : 0 : n = 1;
7805 [ # # ][ # # ]: 0 : String aStr( GetString() );
7806 [ # # ]: 0 : aStr.Erase( n );
7807 [ # # ][ # # ]: 0 : PushString( aStr );
7808 : : }
7809 : : }
7810 : :
7811 : :
7812 : 0 : void ScInterpreter::ScRight()
7813 : : {
7814 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScRight" );
7815 : 0 : sal_uInt8 nParamCount = GetByte();
7816 [ # # ]: 0 : if ( MustHaveParamCount( nParamCount, 1, 2 ) )
7817 : : {
7818 : : xub_StrLen n;
7819 [ # # ]: 0 : if (nParamCount == 2)
7820 : : {
7821 [ # # ]: 0 : double nVal = ::rtl::math::approxFloor(GetDouble());
7822 [ # # ][ # # ]: 0 : if ( nVal < 0.0 || nVal > STRING_MAXLEN )
7823 : : {
7824 [ # # ]: 0 : PushIllegalArgument();
7825 : 0 : return ;
7826 : : }
7827 : : else
7828 : 0 : n = (xub_StrLen) nVal;
7829 : : }
7830 : : else
7831 : 0 : n = 1;
7832 [ # # ][ # # ]: 0 : String aStr( GetString() );
7833 [ # # ]: 0 : if( n < aStr.Len() )
7834 [ # # ]: 0 : aStr.Erase( 0, aStr.Len() - n );
7835 [ # # ][ # # ]: 0 : PushString( aStr );
7836 : : }
7837 : : }
7838 : :
7839 : :
7840 : 0 : void ScInterpreter::ScSearch()
7841 : : {
7842 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScSearch" );
7843 : 0 : sal_uInt8 nParamCount = GetByte();
7844 [ # # ]: 0 : if ( MustHaveParamCount( nParamCount, 2, 3 ) )
7845 : : {
7846 : : double fAnz;
7847 [ # # ]: 0 : if (nParamCount == 3)
7848 : : {
7849 [ # # ]: 0 : fAnz = ::rtl::math::approxFloor(GetDouble());
7850 [ # # ]: 0 : if (fAnz > double(STRING_MAXLEN))
7851 : : {
7852 [ # # ]: 0 : PushIllegalArgument();
7853 : 0 : return;
7854 : : }
7855 : : }
7856 : : else
7857 : 0 : fAnz = 1.0;
7858 [ # # ][ # # ]: 0 : String sStr = GetString();
7859 [ # # ][ # # ]: 0 : OUString SearchStr = GetString();
7860 : 0 : xub_StrLen nPos = (xub_StrLen) fAnz - 1;
7861 : 0 : xub_StrLen nEndPos = sStr.Len();
7862 [ # # ]: 0 : if( nPos >= nEndPos )
7863 [ # # ]: 0 : PushNoValue();
7864 : : else
7865 : : {
7866 : : utl::SearchParam::SearchType eSearchType =
7867 [ # # ]: 0 : (MayBeRegExp( SearchStr, pDok ) ?
7868 [ # # ]: 0 : utl::SearchParam::SRCH_REGEXP : utl::SearchParam::SRCH_NORMAL);
7869 [ # # ]: 0 : utl::SearchParam sPar(SearchStr, eSearchType, false, false, false);
7870 [ # # ]: 0 : utl::TextSearch sT( sPar, *ScGlobal::pCharClass );
7871 [ # # ]: 0 : int nBool = sT.SearchFrwrd(sStr, &nPos, &nEndPos);
7872 [ # # ]: 0 : if (!nBool)
7873 [ # # ]: 0 : PushNoValue();
7874 : : else
7875 [ # # ][ # # ]: 0 : PushDouble((double)(nPos) + 1);
[ # # ]
7876 [ # # ]: 0 : }
7877 : : }
7878 : : }
7879 : :
7880 : :
7881 : 0 : void ScInterpreter::ScMid()
7882 : : {
7883 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScMid" );
7884 [ # # ]: 0 : if ( MustHaveParamCount( GetByte(), 3 ) )
7885 : : {
7886 : 0 : double fAnz = ::rtl::math::approxFloor(GetDouble());
7887 : 0 : double fAnfang = ::rtl::math::approxFloor(GetDouble());
7888 : 0 : const String& rStr = GetString();
7889 [ # # ][ # # ]: 0 : if (fAnfang < 1.0 || fAnz < 0.0 || fAnfang > double(STRING_MAXLEN) || fAnz > double(STRING_MAXLEN))
[ # # ][ # # ]
7890 : 0 : PushIllegalArgument();
7891 : : else
7892 [ # # ]: 0 : PushString(rStr.Copy( (xub_StrLen) fAnfang - 1, (xub_StrLen) fAnz ));
7893 : : }
7894 : 0 : }
7895 : :
7896 : :
7897 : 0 : void ScInterpreter::ScText()
7898 : : {
7899 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScText" );
7900 [ # # ]: 0 : if ( MustHaveParamCount( GetByte(), 2 ) )
7901 : : {
7902 [ # # ][ # # ]: 0 : String sFormatString = GetString();
7903 [ # # ]: 0 : String aStr;
7904 : 0 : bool bString = false;
7905 : 0 : double fVal = 0.0;
7906 [ # # ]: 0 : switch (GetStackType())
[ # # # ]
7907 : : {
7908 : : case svError:
7909 [ # # ]: 0 : PopError();
7910 : 0 : break;
7911 : : case svDouble:
7912 [ # # ]: 0 : fVal = PopDouble();
7913 : 0 : break;
7914 : : default:
7915 : : {
7916 [ # # ]: 0 : FormulaTokenRef xTok( PopToken());
7917 [ # # ]: 0 : if (!nGlobalError)
7918 : : {
7919 [ # # ]: 0 : PushTempToken( xTok.get());
7920 : : // Temporarily override the ConvertStringToValue()
7921 : : // error for GetCellValue() / GetCellValueOrZero()
7922 : 0 : sal_uInt16 nSErr = mnStringNoValueError;
7923 : 0 : mnStringNoValueError = errNotNumericString;
7924 [ # # ]: 0 : fVal = GetDouble();
7925 : 0 : mnStringNoValueError = nSErr;
7926 [ # # ]: 0 : if (nGlobalError == errNotNumericString)
7927 : : {
7928 : : // Not numeric.
7929 : 0 : nGlobalError = 0;
7930 [ # # ]: 0 : PushTempToken( xTok.get());
7931 [ # # ][ # # ]: 0 : aStr = GetString();
7932 : 0 : bString = true;
7933 : : }
7934 [ # # ]: 0 : }
7935 : : }
7936 : : }
7937 [ # # ]: 0 : if (nGlobalError)
7938 [ # # ]: 0 : PushError( nGlobalError);
7939 : : else
7940 : : {
7941 [ # # ]: 0 : String aResult;
7942 : 0 : Color* pColor = NULL;
7943 : : LanguageType eCellLang;
7944 : : const ScPatternAttr* pPattern = pDok->GetPattern(
7945 [ # # ]: 0 : aPos.Col(), aPos.Row(), aPos.Tab() );
7946 [ # # ]: 0 : if ( pPattern )
7947 : : eCellLang = ((const SvxLanguageItem&)
7948 [ # # ]: 0 : pPattern->GetItem( ATTR_LANGUAGE_FORMAT )).GetValue();
7949 : : else
7950 : 0 : eCellLang = ScGlobal::eLnge;
7951 [ # # ]: 0 : if (bString)
7952 : : {
7953 [ # # ]: 0 : if (!pFormatter->GetPreviewString( sFormatString, aStr,
7954 [ # # ]: 0 : aResult, &pColor, eCellLang))
7955 [ # # ]: 0 : PushIllegalArgument();
7956 : : else
7957 [ # # ]: 0 : PushString( aResult);
7958 : : }
7959 : : else
7960 : : {
7961 [ # # ]: 0 : if (!pFormatter->GetPreviewStringGuess( sFormatString, fVal,
7962 [ # # ]: 0 : aResult, &pColor, eCellLang))
7963 [ # # ]: 0 : PushIllegalArgument();
7964 : : else
7965 [ # # ]: 0 : PushString( aResult);
7966 [ # # ]: 0 : }
7967 [ # # ][ # # ]: 0 : }
7968 : : }
7969 : 0 : }
7970 : :
7971 : :
7972 : 0 : void ScInterpreter::ScSubstitute()
7973 : : {
7974 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScSubstitute" );
7975 : 0 : sal_uInt8 nParamCount = GetByte();
7976 [ # # ]: 0 : if ( MustHaveParamCount( nParamCount, 3, 4 ) )
7977 : : {
7978 : : xub_StrLen nAnz;
7979 [ # # ]: 0 : if (nParamCount == 4)
7980 : : {
7981 [ # # ]: 0 : double fAnz = ::rtl::math::approxFloor(GetDouble());
7982 [ # # ][ # # ]: 0 : if( fAnz < 1 || fAnz > STRING_MAXLEN )
7983 : : {
7984 [ # # ]: 0 : PushIllegalArgument();
7985 : 0 : return;
7986 : : }
7987 : : else
7988 : 0 : nAnz = (xub_StrLen) fAnz;
7989 : : }
7990 : : else
7991 : 0 : nAnz = 0;
7992 [ # # ][ # # ]: 0 : String sNewStr = GetString();
7993 [ # # ][ # # ]: 0 : String sOldStr = GetString();
7994 [ # # ][ # # ]: 0 : String sStr = GetString();
7995 : 0 : xub_StrLen nPos = 0;
7996 : 0 : xub_StrLen nCount = 0;
7997 : 0 : xub_StrLen nNewLen = sNewStr.Len();
7998 : 0 : xub_StrLen nOldLen = sOldStr.Len();
7999 : 0 : while( true )
8000 : : {
8001 [ # # ]: 0 : nPos = sStr.Search( sOldStr, nPos );
8002 [ # # ]: 0 : if (nPos != STRING_NOTFOUND)
8003 : : {
8004 : 0 : nCount++;
8005 [ # # ][ # # ]: 0 : if( !nAnz || nCount == nAnz )
8006 : : {
8007 [ # # ]: 0 : sStr.Erase(nPos,nOldLen);
8008 [ # # ][ # # ]: 0 : if ( CheckStringResultLen( sStr, sNewStr ) )
8009 : : {
8010 [ # # ]: 0 : sStr.Insert(sNewStr,nPos);
8011 : 0 : nPos = sal::static_int_cast<xub_StrLen>( nPos + nNewLen );
8012 : : }
8013 : : else
8014 : 0 : break;
8015 : : }
8016 : : else
8017 : 0 : nPos++;
8018 : : }
8019 : : else
8020 : 0 : break;
8021 : : }
8022 [ # # ][ # # ]: 0 : PushString( sStr );
[ # # ][ # # ]
8023 : : }
8024 : : }
8025 : :
8026 : :
8027 : 0 : void ScInterpreter::ScRept()
8028 : : {
8029 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScRept" );
8030 [ # # ]: 0 : if ( MustHaveParamCount( GetByte(), 2 ) )
8031 : : {
8032 [ # # ]: 0 : double fAnz = ::rtl::math::approxFloor(GetDouble());
8033 [ # # ][ # # ]: 0 : String aStr( GetString() );
8034 [ # # ]: 0 : if ( fAnz < 0.0 )
8035 [ # # ]: 0 : PushIllegalArgument();
8036 [ # # ]: 0 : else if ( fAnz * aStr.Len() > STRING_MAXLEN )
8037 : : {
8038 [ # # ]: 0 : PushError( errStringOverflow );
8039 : : }
8040 [ # # ]: 0 : else if ( fAnz == 0.0 )
8041 [ # # ][ # # ]: 0 : PushString( EMPTY_STRING );
8042 : : else
8043 : : {
8044 : 0 : const xub_StrLen nLen = aStr.Len();
8045 : 0 : xub_StrLen n = (xub_StrLen) fAnz;
8046 : 0 : rtl::OUStringBuffer aRes(n*nLen);
8047 [ # # ]: 0 : while( n-- )
8048 [ # # ][ # # ]: 0 : aRes.append(aStr);
8049 [ # # ][ # # ]: 0 : PushString( aRes.makeStringAndClear() );
[ # # ][ # # ]
8050 [ # # ]: 0 : }
8051 : : }
8052 : 0 : }
8053 : :
8054 : :
8055 : 0 : void ScInterpreter::ScConcat()
8056 : : {
8057 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScConcat" );
8058 : 0 : sal_uInt8 nParamCount = GetByte();
8059 [ # # ]: 0 : String aRes;
8060 [ # # ]: 0 : while( nParamCount-- > 0)
8061 : : {
8062 [ # # ]: 0 : const String& rStr = GetString();
8063 [ # # ]: 0 : aRes.Insert( rStr, 0 );
8064 : : }
8065 [ # # ][ # # ]: 0 : PushString( aRes );
8066 : 0 : }
8067 : :
8068 : :
8069 : 0 : void ScInterpreter::ScErrorType()
8070 : : {
8071 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScErrorType" );
8072 : : sal_uInt16 nErr;
8073 : 0 : sal_uInt16 nOldError = nGlobalError;
8074 : 0 : nGlobalError = 0;
8075 [ # # # # ]: 0 : switch ( GetStackType() )
8076 : : {
8077 : : case svRefList :
8078 : : {
8079 [ # # ]: 0 : FormulaTokenRef x = PopToken();
8080 [ # # ]: 0 : if (nGlobalError)
8081 : 0 : nErr = nGlobalError;
8082 : : else
8083 : : {
8084 [ # # ]: 0 : const ScRefList* pRefList = static_cast<ScToken*>(x.get())->GetRefList();
8085 : 0 : size_t n = pRefList->size();
8086 [ # # ]: 0 : if (!n)
8087 : 0 : nErr = errNoRef;
8088 [ # # ]: 0 : else if (n > 1)
8089 : 0 : nErr = errNoValue;
8090 : : else
8091 : : {
8092 : 0 : ScRange aRange;
8093 [ # # ]: 0 : DoubleRefToRange( (*pRefList)[0], aRange);
8094 [ # # ]: 0 : if (nGlobalError)
8095 : 0 : nErr = nGlobalError;
8096 : : else
8097 : : {
8098 : 0 : ScAddress aAdr;
8099 [ # # ][ # # ]: 0 : if ( DoubleRefToPosSingleRef( aRange, aAdr ) )
8100 [ # # ]: 0 : nErr = pDok->GetErrCode( aAdr );
8101 : : else
8102 : 0 : nErr = nGlobalError;
8103 : : }
8104 : : }
8105 [ # # ]: 0 : }
8106 : : }
8107 : 0 : break;
8108 : : case svDoubleRef :
8109 : : {
8110 : 0 : ScRange aRange;
8111 [ # # ]: 0 : PopDoubleRef( aRange );
8112 [ # # ]: 0 : if ( nGlobalError )
8113 : 0 : nErr = nGlobalError;
8114 : : else
8115 : : {
8116 : 0 : ScAddress aAdr;
8117 [ # # ][ # # ]: 0 : if ( DoubleRefToPosSingleRef( aRange, aAdr ) )
8118 [ # # ]: 0 : nErr = pDok->GetErrCode( aAdr );
8119 : : else
8120 : 0 : nErr = nGlobalError;
8121 : : }
8122 : : }
8123 : 0 : break;
8124 : : case svSingleRef :
8125 : : {
8126 : 0 : ScAddress aAdr;
8127 [ # # ]: 0 : PopSingleRef( aAdr );
8128 [ # # ]: 0 : if ( nGlobalError )
8129 : 0 : nErr = nGlobalError;
8130 : : else
8131 [ # # ]: 0 : nErr = pDok->GetErrCode( aAdr );
8132 : : }
8133 : 0 : break;
8134 : : default:
8135 : 0 : PopError();
8136 : 0 : nErr = nGlobalError;
8137 : : }
8138 [ # # ]: 0 : if ( nErr )
8139 : : {
8140 : 0 : nGlobalError = 0;
8141 : 0 : PushDouble( nErr );
8142 : : }
8143 : : else
8144 : : {
8145 : 0 : nGlobalError = nOldError;
8146 : 0 : PushNA();
8147 : : }
8148 : 0 : }
8149 : :
8150 : :
8151 : 51 : bool ScInterpreter::MayBeRegExp( const OUString& rStr, const ScDocument* pDoc )
8152 : : {
8153 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::MayBeRegExp" );
8154 [ + - ][ - + ]: 51 : if ( pDoc && !pDoc->GetDocOptions().IsFormulaRegexEnabled() )
[ - + ]
8155 : 0 : return false;
8156 [ + - ][ + + ]: 51 : if ( rStr.isEmpty() || (rStr.getLength() == 1 && rStr[0] != '.') )
[ + - ][ + + ]
8157 : 6 : return false; // single meta characters can not be a regexp
8158 : : static const sal_Unicode cre[] = { '.','*','+','?','[',']','^','$','\\','<','>','(',')','|', 0 };
8159 : 45 : const sal_Unicode* p1 = rStr.getStr();
8160 : : sal_Unicode c1;
8161 [ + + ]: 279 : while ( ( c1 = *p1++ ) != 0 )
8162 : : {
8163 : 234 : const sal_Unicode* p2 = cre;
8164 [ + + ]: 3510 : while ( *p2 )
8165 : : {
8166 [ - + ]: 3276 : if ( c1 == *p2++ )
8167 : 0 : return true;
8168 : : }
8169 : : }
8170 : 51 : return false;
8171 : : }
8172 : :
8173 : 144 : static bool lcl_LookupQuery( ScAddress & o_rResultPos, ScDocument * pDoc,
8174 : : const ScQueryParam & rParam, const ScQueryEntry & rEntry )
8175 : : {
8176 : 144 : bool bFound = false;
8177 [ + - ]: 144 : ScQueryCellIterator aCellIter( pDoc, rParam.nTab, rParam, false);
8178 [ + - ]: 144 : if (rEntry.eOp != SC_EQUAL)
8179 : : {
8180 : : // range lookup <= or >=
8181 : : SCCOL nCol;
8182 : : SCROW nRow;
8183 [ + - ]: 144 : bFound = aCellIter.FindEqualOrSortedLastInRange( nCol, nRow);
8184 [ + + ]: 144 : if (bFound)
8185 : : {
8186 : 129 : o_rResultPos.SetCol( nCol);
8187 : 144 : o_rResultPos.SetRow( nRow);
8188 : : }
8189 : : }
8190 [ # # ][ # # ]: 0 : else if (aCellIter.GetFirst())
8191 : : {
8192 : : // EQUAL
8193 : 0 : bFound = true;
8194 : 0 : o_rResultPos.SetCol( aCellIter.GetCol());
8195 : 0 : o_rResultPos.SetRow( aCellIter.GetRow());
8196 : : }
8197 [ + - ]: 144 : return bFound;
8198 : : }
8199 : :
8200 : 144 : bool ScInterpreter::LookupQueryWithCache( ScAddress & o_rResultPos,
8201 : : const ScQueryParam & rParam ) const
8202 : : {
8203 : : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::LookupQueryWithCache" );
8204 : 144 : bool bFound = false;
8205 : 144 : const ScQueryEntry& rEntry = rParam.GetEntry(0);
8206 : 144 : bool bColumnsMatch = (rParam.nCol1 == rEntry.nField);
8207 : : OSL_ENSURE( bColumnsMatch, "ScInterpreter::LookupQueryWithCache: columns don't match");
8208 [ - + ]: 144 : if (!bColumnsMatch)
8209 : 0 : bFound = lcl_LookupQuery( o_rResultPos, pDok, rParam, rEntry);
8210 : : else
8211 : : {
8212 : : ScRange aLookupRange( rParam.nCol1, rParam.nRow1, rParam.nTab,
8213 : 144 : rParam.nCol2, rParam.nRow2, rParam.nTab);
8214 [ + - ]: 144 : ScLookupCache& rCache = pDok->GetLookupCache( aLookupRange);
8215 [ + - ]: 144 : ScLookupCache::QueryCriteria aCriteria( rEntry);
8216 : : ScLookupCache::Result eCacheResult = rCache.lookup( o_rResultPos,
8217 [ + - ]: 144 : aCriteria, aPos);
8218 [ + - - - ]: 144 : switch (eCacheResult)
8219 : : {
8220 : : case ScLookupCache::NOT_CACHED :
8221 : : case ScLookupCache::CRITERIA_DIFFERENT :
8222 [ + - ]: 144 : bFound = lcl_LookupQuery( o_rResultPos, pDok, rParam, rEntry);
8223 [ + - ]: 144 : if (eCacheResult == ScLookupCache::NOT_CACHED)
8224 [ + - ]: 144 : rCache.insert( o_rResultPos, aCriteria, aPos, bFound);
8225 : 144 : break;
8226 : : case ScLookupCache::FOUND :
8227 : 0 : bFound = true;
8228 : 0 : break;
8229 : : case ScLookupCache::NOT_AVAILABLE :
8230 : : ; // nothing, bFound remains FALSE
8231 : 0 : break;
8232 [ + - ]: 144 : }
8233 : : }
8234 : 144 : return bFound;
8235 [ + - ][ + - ]: 153 : }
8236 : :
8237 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|