1b3f79822SAndrew Rist /**************************************************************
2cdf0e10cSrcweir *
3b3f79822SAndrew Rist * Licensed to the Apache Software Foundation (ASF) under one
4b3f79822SAndrew Rist * or more contributor license agreements. See the NOTICE file
5b3f79822SAndrew Rist * distributed with this work for additional information
6b3f79822SAndrew Rist * regarding copyright ownership. The ASF licenses this file
7b3f79822SAndrew Rist * to you under the Apache License, Version 2.0 (the
8b3f79822SAndrew Rist * "License"); you may not use this file except in compliance
9b3f79822SAndrew Rist * with the License. You may obtain a copy of the License at
10cdf0e10cSrcweir *
11b3f79822SAndrew Rist * http://www.apache.org/licenses/LICENSE-2.0
12cdf0e10cSrcweir *
13b3f79822SAndrew Rist * Unless required by applicable law or agreed to in writing,
14b3f79822SAndrew Rist * software distributed under the License is distributed on an
15b3f79822SAndrew Rist * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16b3f79822SAndrew Rist * KIND, either express or implied. See the License for the
17b3f79822SAndrew Rist * specific language governing permissions and limitations
18b3f79822SAndrew Rist * under the License.
19cdf0e10cSrcweir *
20b3f79822SAndrew Rist *************************************************************/
21b3f79822SAndrew Rist
22b3f79822SAndrew Rist
23cdf0e10cSrcweir
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_sc.hxx"
26cdf0e10cSrcweir
27cdf0e10cSrcweir // INCLUDE ---------------------------------------------------------------
28cdf0e10cSrcweir
29cdf0e10cSrcweir #include "scitems.hxx"
30cdf0e10cSrcweir #include <editeng/langitem.hxx>
31cdf0e10cSrcweir #include <svx/algitem.hxx>
32cdf0e10cSrcweir #include <unotools/textsearch.hxx>
33cdf0e10cSrcweir #include <svl/zforlist.hxx>
34cdf0e10cSrcweir #include <svl/zformat.hxx>
35cdf0e10cSrcweir #include <tools/urlobj.hxx>
36cdf0e10cSrcweir #include <unotools/charclass.hxx>
37cdf0e10cSrcweir #include <sfx2/docfile.hxx>
38cdf0e10cSrcweir #include <sfx2/printer.hxx>
39cdf0e10cSrcweir #include <unotools/collatorwrapper.hxx>
40cdf0e10cSrcweir #include <unotools/transliterationwrapper.hxx>
41cdf0e10cSrcweir #include <rtl/ustring.hxx>
42cdf0e10cSrcweir #include <rtl/logfile.hxx>
43b54ae672SPedro Giffuni #include <rtl/random.h>
4439c2db0bSWang Lei #include <unicode/uchar.h>
45cdf0e10cSrcweir
46cdf0e10cSrcweir #include "interpre.hxx"
47cdf0e10cSrcweir #include "patattr.hxx"
48cdf0e10cSrcweir #include "global.hxx"
49cdf0e10cSrcweir #include "document.hxx"
50cdf0e10cSrcweir #include "dociter.hxx"
51cdf0e10cSrcweir #include "cell.hxx"
52cdf0e10cSrcweir #include "scmatrix.hxx"
53cdf0e10cSrcweir #include "docoptio.hxx"
54cdf0e10cSrcweir #include "globstr.hrc"
55cdf0e10cSrcweir #include "attrib.hxx"
56cdf0e10cSrcweir #include "jumpmatrix.hxx"
57cdf0e10cSrcweir
58cdf0e10cSrcweir #ifndef _COMPHELPER_PROCESSFACTORY_HXX_
59cdf0e10cSrcweir #include <comphelper/processfactory.hxx>
60cdf0e10cSrcweir #endif
61cdf0e10cSrcweir
62cdf0e10cSrcweir #include <stdlib.h>
63cdf0e10cSrcweir #include <string.h>
64cdf0e10cSrcweir #include <math.h>
65cdf0e10cSrcweir #include <vector>
66cdf0e10cSrcweir #include <memory>
67cdf0e10cSrcweir #include "cellkeytranslator.hxx"
68cdf0e10cSrcweir #include "lookupcache.hxx"
69cdf0e10cSrcweir #include "rangenam.hxx"
70cdf0e10cSrcweir #include "compiler.hxx"
71cdf0e10cSrcweir #include "externalrefmgr.hxx"
72cdf0e10cSrcweir #include "doubleref.hxx"
73cdf0e10cSrcweir #include "queryparam.hxx"
74cdf0e10cSrcweir
7576ea2deeSPedro Giffuni #include <boost/math/special_functions/acosh.hpp>
7676ea2deeSPedro Giffuni #include <boost/math/special_functions/asinh.hpp>
7776ea2deeSPedro Giffuni #include <boost/math/special_functions/atanh.hpp>
7876ea2deeSPedro Giffuni
79cdf0e10cSrcweir #define SC_DOUBLE_MAXVALUE 1.7e307
80cdf0e10cSrcweir
81cdf0e10cSrcweir IMPL_FIXEDMEMPOOL_NEWDEL( ScTokenStack, 8, 4 )
82cdf0e10cSrcweir IMPL_FIXEDMEMPOOL_NEWDEL( ScInterpreter, 32, 16 )
83cdf0e10cSrcweir
84cdf0e10cSrcweir ScTokenStack* ScInterpreter::pGlobalStack = NULL;
85cdf0e10cSrcweir sal_Bool ScInterpreter::bGlobalStackInUse = sal_False;
86cdf0e10cSrcweir
87cdf0e10cSrcweir using namespace formula;
88cdf0e10cSrcweir using ::std::auto_ptr;
89cdf0e10cSrcweir
90cdf0e10cSrcweir //-----------------------------------------------------------------------------
91cdf0e10cSrcweir // Funktionen
92cdf0e10cSrcweir //-----------------------------------------------------------------------------
93cdf0e10cSrcweir
94cdf0e10cSrcweir
ScIfJump()95cdf0e10cSrcweir void ScInterpreter::ScIfJump()
96cdf0e10cSrcweir {
97cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScIfJump" );
98cdf0e10cSrcweir const short* pJump = pCur->GetJump();
99cdf0e10cSrcweir short nJumpCount = pJump[ 0 ];
100cdf0e10cSrcweir MatrixDoubleRefToMatrix();
101cdf0e10cSrcweir switch ( GetStackType() )
102cdf0e10cSrcweir {
103cdf0e10cSrcweir case svMatrix:
104cdf0e10cSrcweir {
105cdf0e10cSrcweir ScMatrixRef pMat = PopMatrix();
106cdf0e10cSrcweir if ( !pMat )
107cdf0e10cSrcweir PushIllegalParameter();
108cdf0e10cSrcweir else
109cdf0e10cSrcweir {
110cdf0e10cSrcweir FormulaTokenRef xNew;
111cdf0e10cSrcweir ScTokenMatrixMap::const_iterator aMapIter;
112cdf0e10cSrcweir // DoubleError handled by JumpMatrix
113cdf0e10cSrcweir pMat->SetErrorInterpreter( NULL);
114cdf0e10cSrcweir SCSIZE nCols, nRows;
115cdf0e10cSrcweir pMat->GetDimensions( nCols, nRows );
116cdf0e10cSrcweir if ( nCols == 0 || nRows == 0 )
117cdf0e10cSrcweir PushIllegalArgument();
118cdf0e10cSrcweir else if (pTokenMatrixMap && ((aMapIter = pTokenMatrixMap->find(
119cdf0e10cSrcweir pCur)) != pTokenMatrixMap->end()))
120cdf0e10cSrcweir xNew = (*aMapIter).second;
121cdf0e10cSrcweir else
122cdf0e10cSrcweir {
123cdf0e10cSrcweir ScJumpMatrix* pJumpMat = new ScJumpMatrix( nCols, nRows );
124cdf0e10cSrcweir for ( SCSIZE nC=0; nC < nCols; ++nC )
125cdf0e10cSrcweir {
126cdf0e10cSrcweir for ( SCSIZE nR=0; nR < nRows; ++nR )
127cdf0e10cSrcweir {
128cdf0e10cSrcweir double fVal;
129cdf0e10cSrcweir bool bTrue;
130cdf0e10cSrcweir ScMatValType nType = 0;
131cdf0e10cSrcweir const ScMatrixValue* pMatVal = pMat->Get( nC, nR,
132cdf0e10cSrcweir nType);
133cdf0e10cSrcweir bool bIsValue = ScMatrix::IsValueType( nType);
134cdf0e10cSrcweir if ( bIsValue )
135cdf0e10cSrcweir {
136cdf0e10cSrcweir fVal = pMatVal->fVal;
137cdf0e10cSrcweir bIsValue = ::rtl::math::isFinite( fVal );
138cdf0e10cSrcweir bTrue = bIsValue && (fVal != 0.0);
139cdf0e10cSrcweir if ( bTrue )
140cdf0e10cSrcweir fVal = 1.0;
141cdf0e10cSrcweir }
142cdf0e10cSrcweir else
143cdf0e10cSrcweir {
144cdf0e10cSrcweir // Treat empty and empty path as 0, but string
145cdf0e10cSrcweir // as error.
146cdf0e10cSrcweir bIsValue = !ScMatrix::IsRealStringType( nType);
147cdf0e10cSrcweir bTrue = false;
148cdf0e10cSrcweir fVal = (bIsValue ? 0.0 : CreateDoubleError( errNoValue));
149cdf0e10cSrcweir }
150cdf0e10cSrcweir if ( bTrue )
151cdf0e10cSrcweir { // TRUE
152cdf0e10cSrcweir if( nJumpCount >= 2 )
153cdf0e10cSrcweir { // THEN path
154cdf0e10cSrcweir pJumpMat->SetJump( nC, nR, fVal,
155cdf0e10cSrcweir pJump[ 1 ],
156cdf0e10cSrcweir pJump[ nJumpCount ]);
157cdf0e10cSrcweir }
158cdf0e10cSrcweir else
159cdf0e10cSrcweir { // no parameter given for THEN
160cdf0e10cSrcweir pJumpMat->SetJump( nC, nR, fVal,
161cdf0e10cSrcweir pJump[ nJumpCount ],
162cdf0e10cSrcweir pJump[ nJumpCount ]);
163cdf0e10cSrcweir }
164cdf0e10cSrcweir }
165cdf0e10cSrcweir else
166cdf0e10cSrcweir { // FALSE
167cdf0e10cSrcweir if( nJumpCount == 3 && bIsValue )
168cdf0e10cSrcweir { // ELSE path
169cdf0e10cSrcweir pJumpMat->SetJump( nC, nR, fVal,
170cdf0e10cSrcweir pJump[ 2 ],
171cdf0e10cSrcweir pJump[ nJumpCount ]);
172cdf0e10cSrcweir }
173cdf0e10cSrcweir else
174cdf0e10cSrcweir { // no parameter given for ELSE,
175cdf0e10cSrcweir // or DoubleError
176cdf0e10cSrcweir pJumpMat->SetJump( nC, nR, fVal,
177cdf0e10cSrcweir pJump[ nJumpCount ],
178cdf0e10cSrcweir pJump[ nJumpCount ]);
179cdf0e10cSrcweir }
180cdf0e10cSrcweir }
181cdf0e10cSrcweir }
182cdf0e10cSrcweir }
183cdf0e10cSrcweir xNew = new ScJumpMatrixToken( pJumpMat );
184cdf0e10cSrcweir GetTokenMatrixMap().insert( ScTokenMatrixMap::value_type(pCur, xNew));
185cdf0e10cSrcweir }
186cdf0e10cSrcweir PushTempToken( xNew);
187cdf0e10cSrcweir // set endpoint of path for main code line
188cdf0e10cSrcweir aCode.Jump( pJump[ nJumpCount ], pJump[ nJumpCount ] );
189cdf0e10cSrcweir }
190cdf0e10cSrcweir }
191cdf0e10cSrcweir break;
192cdf0e10cSrcweir default:
193cdf0e10cSrcweir {
194cdf0e10cSrcweir if ( GetBool() )
195cdf0e10cSrcweir { // TRUE
196cdf0e10cSrcweir if( nJumpCount >= 2 )
197cdf0e10cSrcweir { // THEN path
198cdf0e10cSrcweir aCode.Jump( pJump[ 1 ], pJump[ nJumpCount ] );
199cdf0e10cSrcweir }
200cdf0e10cSrcweir else
201cdf0e10cSrcweir { // no parameter given for THEN
202cdf0e10cSrcweir nFuncFmtType = NUMBERFORMAT_LOGICAL;
203cdf0e10cSrcweir PushInt(1);
204cdf0e10cSrcweir aCode.Jump( pJump[ nJumpCount ], pJump[ nJumpCount ] );
205cdf0e10cSrcweir }
206cdf0e10cSrcweir }
207cdf0e10cSrcweir else
208cdf0e10cSrcweir { // FALSE
209cdf0e10cSrcweir if( nJumpCount == 3 )
210cdf0e10cSrcweir { // ELSE path
211cdf0e10cSrcweir aCode.Jump( pJump[ 2 ], pJump[ nJumpCount ] );
212cdf0e10cSrcweir }
213cdf0e10cSrcweir else
214cdf0e10cSrcweir { // no parameter given for ELSE
215cdf0e10cSrcweir nFuncFmtType = NUMBERFORMAT_LOGICAL;
216cdf0e10cSrcweir PushInt(0);
217cdf0e10cSrcweir aCode.Jump( pJump[ nJumpCount ], pJump[ nJumpCount ] );
218cdf0e10cSrcweir }
219cdf0e10cSrcweir }
220cdf0e10cSrcweir }
221cdf0e10cSrcweir }
222cdf0e10cSrcweir }
223cdf0e10cSrcweir
224cdf0e10cSrcweir
ScChoseJump()225cdf0e10cSrcweir void ScInterpreter::ScChoseJump()
226cdf0e10cSrcweir {
227cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScChoseJump" );
228cdf0e10cSrcweir // We have to set a jump, if there was none chosen because of an error set
229cdf0e10cSrcweir // it to endpoint.
230cdf0e10cSrcweir bool bHaveJump = false;
231cdf0e10cSrcweir const short* pJump = pCur->GetJump();
232cdf0e10cSrcweir short nJumpCount = pJump[ 0 ];
233cdf0e10cSrcweir MatrixDoubleRefToMatrix();
234cdf0e10cSrcweir switch ( GetStackType() )
235cdf0e10cSrcweir {
236cdf0e10cSrcweir case svMatrix:
237cdf0e10cSrcweir {
238cdf0e10cSrcweir ScMatrixRef pMat = PopMatrix();
239cdf0e10cSrcweir if ( !pMat )
240cdf0e10cSrcweir PushIllegalParameter();
241cdf0e10cSrcweir else
242cdf0e10cSrcweir {
243cdf0e10cSrcweir FormulaTokenRef xNew;
244cdf0e10cSrcweir ScTokenMatrixMap::const_iterator aMapIter;
245cdf0e10cSrcweir // DoubleError handled by JumpMatrix
246cdf0e10cSrcweir pMat->SetErrorInterpreter( NULL);
247cdf0e10cSrcweir SCSIZE nCols, nRows;
248cdf0e10cSrcweir pMat->GetDimensions( nCols, nRows );
249cdf0e10cSrcweir if ( nCols == 0 || nRows == 0 )
250cdf0e10cSrcweir PushIllegalParameter();
251cdf0e10cSrcweir else if (pTokenMatrixMap && ((aMapIter = pTokenMatrixMap->find(
252cdf0e10cSrcweir pCur)) != pTokenMatrixMap->end()))
253cdf0e10cSrcweir xNew = (*aMapIter).second;
254cdf0e10cSrcweir else
255cdf0e10cSrcweir {
256cdf0e10cSrcweir ScJumpMatrix* pJumpMat = new ScJumpMatrix( nCols, nRows );
257cdf0e10cSrcweir for ( SCSIZE nC=0; nC < nCols; ++nC )
258cdf0e10cSrcweir {
259cdf0e10cSrcweir for ( SCSIZE nR=0; nR < nRows; ++nR )
260cdf0e10cSrcweir {
261cdf0e10cSrcweir double fVal;
262cdf0e10cSrcweir ScMatValType nType;
263cdf0e10cSrcweir const ScMatrixValue* pMatVal = pMat->Get( nC, nR,
264cdf0e10cSrcweir nType);
265cdf0e10cSrcweir bool bIsValue = ScMatrix::IsValueType( nType);
266cdf0e10cSrcweir if ( bIsValue )
267cdf0e10cSrcweir {
268cdf0e10cSrcweir fVal = pMatVal->fVal;
269cdf0e10cSrcweir bIsValue = ::rtl::math::isFinite( fVal );
270cdf0e10cSrcweir if ( bIsValue )
271cdf0e10cSrcweir {
272cdf0e10cSrcweir fVal = ::rtl::math::approxFloor( fVal);
273cdf0e10cSrcweir if ( (fVal < 1) || (fVal >= nJumpCount))
274cdf0e10cSrcweir {
275cdf0e10cSrcweir bIsValue = sal_False;
276cdf0e10cSrcweir fVal = CreateDoubleError(
277cdf0e10cSrcweir errIllegalArgument);
278cdf0e10cSrcweir }
279cdf0e10cSrcweir }
280cdf0e10cSrcweir }
281cdf0e10cSrcweir else
282cdf0e10cSrcweir {
283cdf0e10cSrcweir fVal = CreateDoubleError( errNoValue);
284cdf0e10cSrcweir }
285cdf0e10cSrcweir if ( bIsValue )
286cdf0e10cSrcweir {
287cdf0e10cSrcweir pJumpMat->SetJump( nC, nR, fVal,
288cdf0e10cSrcweir pJump[ (short)fVal ],
289cdf0e10cSrcweir pJump[ nJumpCount ]);
290cdf0e10cSrcweir }
291cdf0e10cSrcweir else
292cdf0e10cSrcweir {
293cdf0e10cSrcweir pJumpMat->SetJump( nC, nR, fVal,
294cdf0e10cSrcweir pJump[ nJumpCount ],
295cdf0e10cSrcweir pJump[ nJumpCount ]);
296cdf0e10cSrcweir }
297cdf0e10cSrcweir }
298cdf0e10cSrcweir }
299cdf0e10cSrcweir xNew = new ScJumpMatrixToken( pJumpMat );
300cdf0e10cSrcweir GetTokenMatrixMap().insert( ScTokenMatrixMap::value_type(
301cdf0e10cSrcweir pCur, xNew));
302cdf0e10cSrcweir }
303cdf0e10cSrcweir PushTempToken( xNew);
304cdf0e10cSrcweir // set endpoint of path for main code line
305cdf0e10cSrcweir aCode.Jump( pJump[ nJumpCount ], pJump[ nJumpCount ] );
306cdf0e10cSrcweir bHaveJump = true;
307cdf0e10cSrcweir }
308cdf0e10cSrcweir }
309cdf0e10cSrcweir break;
310cdf0e10cSrcweir default:
311cdf0e10cSrcweir {
312cdf0e10cSrcweir double nJumpIndex = ::rtl::math::approxFloor( GetDouble() );
313cdf0e10cSrcweir if (!nGlobalError && (nJumpIndex >= 1) && (nJumpIndex < nJumpCount))
314cdf0e10cSrcweir {
315cdf0e10cSrcweir aCode.Jump( pJump[ (short) nJumpIndex ], pJump[ nJumpCount ] );
316cdf0e10cSrcweir bHaveJump = true;
317cdf0e10cSrcweir }
318cdf0e10cSrcweir else
319cdf0e10cSrcweir PushIllegalArgument();
320cdf0e10cSrcweir }
321cdf0e10cSrcweir }
322cdf0e10cSrcweir if (!bHaveJump)
323cdf0e10cSrcweir aCode.Jump( pJump[ nJumpCount ], pJump[ nJumpCount ] );
324cdf0e10cSrcweir }
325cdf0e10cSrcweir
lcl_AdjustJumpMatrix(ScJumpMatrix * pJumpM,ScMatrixRef & pResMat,SCSIZE nParmCols,SCSIZE nParmRows)326cdf0e10cSrcweir void lcl_AdjustJumpMatrix( ScJumpMatrix* pJumpM, ScMatrixRef& pResMat, SCSIZE nParmCols, SCSIZE nParmRows )
327cdf0e10cSrcweir {
328cdf0e10cSrcweir SCSIZE nJumpCols, nJumpRows;
329cdf0e10cSrcweir SCSIZE nResCols, nResRows;
330cdf0e10cSrcweir SCSIZE nAdjustCols, nAdjustRows;
331cdf0e10cSrcweir pJumpM->GetDimensions( nJumpCols, nJumpRows );
332cdf0e10cSrcweir pJumpM->GetResMatDimensions( nResCols, nResRows );
333cdf0e10cSrcweir if (( nJumpCols == 1 && nParmCols > nResCols ) ||
334cdf0e10cSrcweir ( nJumpRows == 1 && nParmRows > nResRows ))
335cdf0e10cSrcweir {
336cdf0e10cSrcweir if ( nJumpCols == 1 && nJumpRows == 1 )
337cdf0e10cSrcweir {
338cdf0e10cSrcweir nAdjustCols = nParmCols > nResCols ? nParmCols : nResCols;
339cdf0e10cSrcweir nAdjustRows = nParmRows > nResRows ? nParmRows : nResRows;
340cdf0e10cSrcweir }
341cdf0e10cSrcweir else if ( nJumpCols == 1 )
342cdf0e10cSrcweir {
343cdf0e10cSrcweir nAdjustCols = nParmCols;
344cdf0e10cSrcweir nAdjustRows = nResRows;
345cdf0e10cSrcweir }
346cdf0e10cSrcweir else
347cdf0e10cSrcweir {
348cdf0e10cSrcweir nAdjustCols = nResCols;
349cdf0e10cSrcweir nAdjustRows = nParmRows;
350cdf0e10cSrcweir }
351cdf0e10cSrcweir pJumpM->SetNewResMat( nAdjustCols, nAdjustRows );
352cdf0e10cSrcweir pResMat = pJumpM->GetResultMatrix();
353cdf0e10cSrcweir }
354cdf0e10cSrcweir }
355cdf0e10cSrcweir
JumpMatrix(short nStackLevel)356cdf0e10cSrcweir bool ScInterpreter::JumpMatrix( short nStackLevel )
357cdf0e10cSrcweir {
358cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::JumpMatrix" );
359cdf0e10cSrcweir pJumpMatrix = static_cast<ScToken*>(pStack[sp-nStackLevel])->GetJumpMatrix();
360cdf0e10cSrcweir ScMatrixRef pResMat = pJumpMatrix->GetResultMatrix();
361cdf0e10cSrcweir SCSIZE nC, nR;
362cdf0e10cSrcweir if ( nStackLevel == 2 )
363cdf0e10cSrcweir {
364cdf0e10cSrcweir if ( aCode.HasStacked() )
365cdf0e10cSrcweir aCode.Pop(); // pop what Jump() pushed
366cdf0e10cSrcweir else
367cdf0e10cSrcweir {
368cdf0e10cSrcweir DBG_ERRORFILE( "ScInterpreter::JumpMatrix: pop goes the weasel" );
369cdf0e10cSrcweir }
370cdf0e10cSrcweir
371cdf0e10cSrcweir if ( !pResMat )
372cdf0e10cSrcweir {
373cdf0e10cSrcweir Pop();
374cdf0e10cSrcweir SetError( errUnknownStackVariable );
375cdf0e10cSrcweir }
376cdf0e10cSrcweir else
377cdf0e10cSrcweir {
378cdf0e10cSrcweir pJumpMatrix->GetPos( nC, nR );
379cdf0e10cSrcweir switch ( GetStackType() )
380cdf0e10cSrcweir {
381cdf0e10cSrcweir case svDouble:
382cdf0e10cSrcweir {
383cdf0e10cSrcweir double fVal = GetDouble();
384cdf0e10cSrcweir if ( nGlobalError )
385cdf0e10cSrcweir {
386cdf0e10cSrcweir fVal = CreateDoubleError( nGlobalError );
387cdf0e10cSrcweir nGlobalError = 0;
388cdf0e10cSrcweir }
389cdf0e10cSrcweir pResMat->PutDouble( fVal, nC, nR );
390cdf0e10cSrcweir }
391cdf0e10cSrcweir break;
392cdf0e10cSrcweir case svString:
393cdf0e10cSrcweir {
394cdf0e10cSrcweir const String& rStr = GetString();
395cdf0e10cSrcweir if ( nGlobalError )
396cdf0e10cSrcweir {
397cdf0e10cSrcweir pResMat->PutDouble( CreateDoubleError( nGlobalError),
398cdf0e10cSrcweir nC, nR);
399cdf0e10cSrcweir nGlobalError = 0;
400cdf0e10cSrcweir }
401cdf0e10cSrcweir else
402cdf0e10cSrcweir pResMat->PutString( rStr, nC, nR );
403cdf0e10cSrcweir }
404cdf0e10cSrcweir break;
405cdf0e10cSrcweir case svSingleRef:
406cdf0e10cSrcweir {
407cdf0e10cSrcweir ScAddress aAdr;
408cdf0e10cSrcweir PopSingleRef( aAdr );
409cdf0e10cSrcweir if ( nGlobalError )
410cdf0e10cSrcweir {
411cdf0e10cSrcweir pResMat->PutDouble( CreateDoubleError( nGlobalError),
412cdf0e10cSrcweir nC, nR);
413cdf0e10cSrcweir nGlobalError = 0;
414cdf0e10cSrcweir }
415cdf0e10cSrcweir else
416cdf0e10cSrcweir {
417cdf0e10cSrcweir ScBaseCell* pCell = GetCell( aAdr );
418cdf0e10cSrcweir if (HasCellEmptyData( pCell))
419cdf0e10cSrcweir pResMat->PutEmpty( nC, nR );
420cdf0e10cSrcweir else if (HasCellValueData( pCell))
421cdf0e10cSrcweir {
422cdf0e10cSrcweir double fVal = GetCellValue( aAdr, pCell);
423cdf0e10cSrcweir if ( nGlobalError )
424cdf0e10cSrcweir {
425cdf0e10cSrcweir fVal = CreateDoubleError(
426cdf0e10cSrcweir nGlobalError);
427cdf0e10cSrcweir nGlobalError = 0;
428cdf0e10cSrcweir }
429cdf0e10cSrcweir pResMat->PutDouble( fVal, nC, nR );
430cdf0e10cSrcweir }
431cdf0e10cSrcweir else
432cdf0e10cSrcweir {
433cdf0e10cSrcweir String aStr;
434cdf0e10cSrcweir GetCellString( aStr, pCell );
435cdf0e10cSrcweir if ( nGlobalError )
436cdf0e10cSrcweir {
437cdf0e10cSrcweir pResMat->PutDouble( CreateDoubleError(
438cdf0e10cSrcweir nGlobalError), nC, nR);
439cdf0e10cSrcweir nGlobalError = 0;
440cdf0e10cSrcweir }
441cdf0e10cSrcweir else
442cdf0e10cSrcweir pResMat->PutString( aStr, nC, nR);
443cdf0e10cSrcweir }
444cdf0e10cSrcweir }
445cdf0e10cSrcweir }
446cdf0e10cSrcweir break;
447cdf0e10cSrcweir case svDoubleRef:
448cdf0e10cSrcweir { // upper left plus offset within matrix
449cdf0e10cSrcweir double fVal;
450cdf0e10cSrcweir ScRange aRange;
451cdf0e10cSrcweir PopDoubleRef( aRange );
452cdf0e10cSrcweir if ( nGlobalError )
453cdf0e10cSrcweir {
454cdf0e10cSrcweir fVal = CreateDoubleError( nGlobalError );
455cdf0e10cSrcweir nGlobalError = 0;
456cdf0e10cSrcweir pResMat->PutDouble( fVal, nC, nR );
457cdf0e10cSrcweir }
458cdf0e10cSrcweir else
459cdf0e10cSrcweir {
460cdf0e10cSrcweir // Do not modify the original range because we use it
461cdf0e10cSrcweir // to adjust the size of the result matrix if necessary.
462cdf0e10cSrcweir ScAddress aAdr( aRange.aStart);
463cdf0e10cSrcweir sal_uLong nCol = (sal_uLong)aAdr.Col() + nC;
464cdf0e10cSrcweir sal_uLong nRow = (sal_uLong)aAdr.Row() + nR;
465cdf0e10cSrcweir if ((nCol > static_cast<sal_uLong>(aRange.aEnd.Col()) &&
466cdf0e10cSrcweir aRange.aEnd.Col() != aRange.aStart.Col())
467cdf0e10cSrcweir || (nRow > static_cast<sal_uLong>(aRange.aEnd.Row()) &&
468cdf0e10cSrcweir aRange.aEnd.Row() != aRange.aStart.Row()))
469cdf0e10cSrcweir {
470cdf0e10cSrcweir fVal = CreateDoubleError( NOTAVAILABLE );
471cdf0e10cSrcweir pResMat->PutDouble( fVal, nC, nR );
472cdf0e10cSrcweir }
473cdf0e10cSrcweir else
474cdf0e10cSrcweir {
475cdf0e10cSrcweir // Replicate column and/or row of a vector if it is
476cdf0e10cSrcweir // one. Note that this could be a range reference
477cdf0e10cSrcweir // that in fact consists of only one cell, e.g. A1:A1
478cdf0e10cSrcweir if (aRange.aEnd.Col() == aRange.aStart.Col())
479cdf0e10cSrcweir nCol = aRange.aStart.Col();
480cdf0e10cSrcweir if (aRange.aEnd.Row() == aRange.aStart.Row())
481cdf0e10cSrcweir nRow = aRange.aStart.Row();
482cdf0e10cSrcweir aAdr.SetCol( static_cast<SCCOL>(nCol) );
483cdf0e10cSrcweir aAdr.SetRow( static_cast<SCROW>(nRow) );
484cdf0e10cSrcweir ScBaseCell* pCell = GetCell( aAdr );
485cdf0e10cSrcweir if (HasCellEmptyData( pCell))
486cdf0e10cSrcweir pResMat->PutEmpty( nC, nR );
487cdf0e10cSrcweir else if (HasCellValueData( pCell))
488cdf0e10cSrcweir {
489cdf0e10cSrcweir double fCellVal = GetCellValue( aAdr, pCell);
490cdf0e10cSrcweir if ( nGlobalError )
491cdf0e10cSrcweir {
492cdf0e10cSrcweir fCellVal = CreateDoubleError(
493cdf0e10cSrcweir nGlobalError);
494cdf0e10cSrcweir nGlobalError = 0;
495cdf0e10cSrcweir }
496cdf0e10cSrcweir pResMat->PutDouble( fCellVal, nC, nR );
497cdf0e10cSrcweir }
498cdf0e10cSrcweir else
499cdf0e10cSrcweir {
500cdf0e10cSrcweir String aStr;
501cdf0e10cSrcweir GetCellString( aStr, pCell );
502cdf0e10cSrcweir if ( nGlobalError )
503cdf0e10cSrcweir {
504cdf0e10cSrcweir pResMat->PutDouble( CreateDoubleError(
505cdf0e10cSrcweir nGlobalError), nC, nR);
506cdf0e10cSrcweir nGlobalError = 0;
507cdf0e10cSrcweir }
508cdf0e10cSrcweir else
509cdf0e10cSrcweir pResMat->PutString( aStr, nC, nR );
510cdf0e10cSrcweir }
511cdf0e10cSrcweir }
512cdf0e10cSrcweir SCSIZE nParmCols = aRange.aEnd.Col() - aRange.aStart.Col() + 1;
513cdf0e10cSrcweir SCSIZE nParmRows = aRange.aEnd.Row() - aRange.aStart.Row() + 1;
514cdf0e10cSrcweir lcl_AdjustJumpMatrix( pJumpMatrix, pResMat, nParmCols, nParmRows );
515cdf0e10cSrcweir }
516cdf0e10cSrcweir }
517cdf0e10cSrcweir break;
518cdf0e10cSrcweir case svMatrix:
519cdf0e10cSrcweir { // match matrix offsets
520cdf0e10cSrcweir double fVal;
521cdf0e10cSrcweir ScMatrixRef pMat = PopMatrix();
522cdf0e10cSrcweir if ( nGlobalError )
523cdf0e10cSrcweir {
524cdf0e10cSrcweir fVal = CreateDoubleError( nGlobalError );
525cdf0e10cSrcweir nGlobalError = 0;
526cdf0e10cSrcweir pResMat->PutDouble( fVal, nC, nR );
527cdf0e10cSrcweir }
528cdf0e10cSrcweir else if ( !pMat )
529cdf0e10cSrcweir {
530cdf0e10cSrcweir fVal = CreateDoubleError( errUnknownVariable );
531cdf0e10cSrcweir pResMat->PutDouble( fVal, nC, nR );
532cdf0e10cSrcweir }
533cdf0e10cSrcweir else
534cdf0e10cSrcweir {
535cdf0e10cSrcweir SCSIZE nCols, nRows;
536cdf0e10cSrcweir pMat->GetDimensions( nCols, nRows );
537cdf0e10cSrcweir if ((nCols <= nC && nCols != 1) ||
538cdf0e10cSrcweir (nRows <= nR && nRows != 1))
539cdf0e10cSrcweir {
540cdf0e10cSrcweir fVal = CreateDoubleError( NOTAVAILABLE );
541cdf0e10cSrcweir pResMat->PutDouble( fVal, nC, nR );
542cdf0e10cSrcweir }
543cdf0e10cSrcweir else
544cdf0e10cSrcweir {
545cdf0e10cSrcweir if ( pMat->IsValue( nC, nR ) )
546cdf0e10cSrcweir {
547cdf0e10cSrcweir fVal = pMat->GetDouble( nC, nR );
548cdf0e10cSrcweir pResMat->PutDouble( fVal, nC, nR );
549cdf0e10cSrcweir }
550cdf0e10cSrcweir else if ( pMat->IsEmpty( nC, nR ) )
551cdf0e10cSrcweir pResMat->PutEmpty( nC, nR );
552cdf0e10cSrcweir else
553cdf0e10cSrcweir {
554cdf0e10cSrcweir const String& rStr = pMat->GetString( nC, nR );
555cdf0e10cSrcweir pResMat->PutString( rStr, nC, nR );
556cdf0e10cSrcweir }
557cdf0e10cSrcweir }
558cdf0e10cSrcweir lcl_AdjustJumpMatrix( pJumpMatrix, pResMat, nCols, nRows );
559cdf0e10cSrcweir }
560cdf0e10cSrcweir }
561cdf0e10cSrcweir break;
562cdf0e10cSrcweir case svError:
563cdf0e10cSrcweir {
564cdf0e10cSrcweir PopError();
565cdf0e10cSrcweir double fVal = CreateDoubleError( nGlobalError);
566cdf0e10cSrcweir nGlobalError = 0;
567cdf0e10cSrcweir pResMat->PutDouble( fVal, nC, nR );
568cdf0e10cSrcweir }
569cdf0e10cSrcweir break;
570cdf0e10cSrcweir default:
571cdf0e10cSrcweir {
572cdf0e10cSrcweir Pop();
573cdf0e10cSrcweir double fVal = CreateDoubleError( errIllegalArgument);
574cdf0e10cSrcweir pResMat->PutDouble( fVal, nC, nR );
575cdf0e10cSrcweir }
576cdf0e10cSrcweir }
577cdf0e10cSrcweir }
578cdf0e10cSrcweir }
579cdf0e10cSrcweir bool bCont = pJumpMatrix->Next( nC, nR );
580cdf0e10cSrcweir if ( bCont )
581cdf0e10cSrcweir {
582cdf0e10cSrcweir double fBool;
583cdf0e10cSrcweir short nStart, nNext, nStop;
584cdf0e10cSrcweir pJumpMatrix->GetJump( nC, nR, fBool, nStart, nNext, nStop );
585cdf0e10cSrcweir while ( bCont && nStart == nNext )
586cdf0e10cSrcweir { // push all results that have no jump path
587cdf0e10cSrcweir if ( pResMat )
588cdf0e10cSrcweir {
589cdf0e10cSrcweir // a sal_False without path results in an empty path value
590cdf0e10cSrcweir if ( fBool == 0.0 )
591cdf0e10cSrcweir pResMat->PutEmptyPath( nC, nR );
592cdf0e10cSrcweir else
593cdf0e10cSrcweir pResMat->PutDouble( fBool, nC, nR );
594cdf0e10cSrcweir }
595cdf0e10cSrcweir bCont = pJumpMatrix->Next( nC, nR );
596cdf0e10cSrcweir if ( bCont )
597cdf0e10cSrcweir pJumpMatrix->GetJump( nC, nR, fBool, nStart, nNext, nStop );
598cdf0e10cSrcweir }
599cdf0e10cSrcweir if ( bCont && nStart != nNext )
600cdf0e10cSrcweir {
601cdf0e10cSrcweir const ScTokenVec* pParams = pJumpMatrix->GetJumpParameters();
602cdf0e10cSrcweir if ( pParams )
603cdf0e10cSrcweir {
604cdf0e10cSrcweir for ( ScTokenVec::const_iterator i = pParams->begin();
605cdf0e10cSrcweir i != pParams->end(); ++i )
606cdf0e10cSrcweir {
607cdf0e10cSrcweir // This is not the current state of the interpreter, so
608cdf0e10cSrcweir // push without error, and elements' errors are coded into
609cdf0e10cSrcweir // double.
610cdf0e10cSrcweir PushWithoutError( *(*i));
611cdf0e10cSrcweir }
612cdf0e10cSrcweir }
613cdf0e10cSrcweir aCode.Jump( nStart, nNext, nStop );
614cdf0e10cSrcweir }
615cdf0e10cSrcweir }
616cdf0e10cSrcweir if ( !bCont )
617cdf0e10cSrcweir { // we're done with it, throw away jump matrix, keep result
618cdf0e10cSrcweir pJumpMatrix = NULL;
619cdf0e10cSrcweir Pop();
620cdf0e10cSrcweir PushMatrix( pResMat );
621cdf0e10cSrcweir // Remove jump matrix from map and remember result matrix in case it
622cdf0e10cSrcweir // could be reused in another path of the same condition.
623cdf0e10cSrcweir if (pTokenMatrixMap)
624cdf0e10cSrcweir {
625cdf0e10cSrcweir pTokenMatrixMap->erase( pCur);
626cdf0e10cSrcweir pTokenMatrixMap->insert( ScTokenMatrixMap::value_type( pCur,
627cdf0e10cSrcweir pStack[sp-1]));
628cdf0e10cSrcweir }
629cdf0e10cSrcweir return true;
630cdf0e10cSrcweir }
631cdf0e10cSrcweir return false;
632cdf0e10cSrcweir }
633cdf0e10cSrcweir
634cdf0e10cSrcweir
ScCompareOptions(ScDocument * pDoc,const ScQueryEntry & rEntry,bool bReg)635cdf0e10cSrcweir ScCompareOptions::ScCompareOptions( ScDocument* pDoc, const ScQueryEntry& rEntry, bool bReg ) :
636cdf0e10cSrcweir aQueryEntry(rEntry),
637cdf0e10cSrcweir bRegEx(bReg),
638cdf0e10cSrcweir bMatchWholeCell(pDoc->GetDocOptions().IsMatchWholeCell()),
639cdf0e10cSrcweir bIgnoreCase(true)
640cdf0e10cSrcweir {
641cdf0e10cSrcweir bRegEx = (bRegEx && (aQueryEntry.eOp == SC_EQUAL || aQueryEntry.eOp == SC_NOT_EQUAL));
642cdf0e10cSrcweir // Interpreter functions usually are case insensitive, except the simple
643cdf0e10cSrcweir // comparison operators, for which these options aren't used. Override in
644cdf0e10cSrcweir // struct if needed.
645cdf0e10cSrcweir }
646cdf0e10cSrcweir
647cdf0e10cSrcweir
CompareFunc(const ScCompare & rComp,ScCompareOptions * pOptions)648cdf0e10cSrcweir double ScInterpreter::CompareFunc( const ScCompare& rComp, ScCompareOptions* pOptions )
649cdf0e10cSrcweir {
650cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::CompareFunc" );
651cdf0e10cSrcweir // Keep DoubleError if encountered
652cdf0e10cSrcweir // #i40539# if bEmpty is set, bVal/nVal are uninitialized
653cdf0e10cSrcweir if ( !rComp.bEmpty[0] && rComp.bVal[0] && !::rtl::math::isFinite( rComp.nVal[0]))
654cdf0e10cSrcweir return rComp.nVal[0];
655cdf0e10cSrcweir if ( !rComp.bEmpty[1] && rComp.bVal[1] && !::rtl::math::isFinite( rComp.nVal[1]))
656cdf0e10cSrcweir return rComp.nVal[1];
657cdf0e10cSrcweir
658cdf0e10cSrcweir size_t nStringQuery = 0; // 0:=no, 1:=0, 2:=1
659cdf0e10cSrcweir double fRes = 0;
660cdf0e10cSrcweir if ( rComp.bEmpty[ 0 ] )
661cdf0e10cSrcweir {
662cdf0e10cSrcweir if ( rComp.bEmpty[ 1 ] )
663cdf0e10cSrcweir ; // empty cell == empty cell, fRes 0
664cdf0e10cSrcweir else if( rComp.bVal[ 1 ] )
665cdf0e10cSrcweir {
666cdf0e10cSrcweir if ( !::rtl::math::approxEqual( rComp.nVal[ 1 ], 0.0 ) )
667cdf0e10cSrcweir {
668cdf0e10cSrcweir if ( rComp.nVal[ 1 ] < 0.0 )
669cdf0e10cSrcweir fRes = 1; // empty cell > -x
670cdf0e10cSrcweir else
671cdf0e10cSrcweir fRes = -1; // empty cell < x
672cdf0e10cSrcweir }
673cdf0e10cSrcweir // else: empty cell == 0.0
674cdf0e10cSrcweir }
675cdf0e10cSrcweir else
676cdf0e10cSrcweir {
677cdf0e10cSrcweir if ( rComp.pVal[ 1 ]->Len() )
678cdf0e10cSrcweir fRes = -1; // empty cell < "..."
679cdf0e10cSrcweir // else: empty cell == ""
680cdf0e10cSrcweir }
681cdf0e10cSrcweir }
682cdf0e10cSrcweir else if ( rComp.bEmpty[ 1 ] )
683cdf0e10cSrcweir {
684cdf0e10cSrcweir if( rComp.bVal[ 0 ] )
685cdf0e10cSrcweir {
686cdf0e10cSrcweir if ( !::rtl::math::approxEqual( rComp.nVal[ 0 ], 0.0 ) )
687cdf0e10cSrcweir {
688cdf0e10cSrcweir if ( rComp.nVal[ 0 ] < 0.0 )
689cdf0e10cSrcweir fRes = -1; // -x < empty cell
690cdf0e10cSrcweir else
691cdf0e10cSrcweir fRes = 1; // x > empty cell
692cdf0e10cSrcweir }
693cdf0e10cSrcweir // else: empty cell == 0.0
694cdf0e10cSrcweir }
695cdf0e10cSrcweir else
696cdf0e10cSrcweir {
697cdf0e10cSrcweir if ( rComp.pVal[ 0 ]->Len() )
698cdf0e10cSrcweir fRes = 1; // "..." > empty cell
699cdf0e10cSrcweir // else: "" == empty cell
700cdf0e10cSrcweir }
701cdf0e10cSrcweir }
702cdf0e10cSrcweir else if( rComp.bVal[ 0 ] )
703cdf0e10cSrcweir {
704cdf0e10cSrcweir if( rComp.bVal[ 1 ] )
705cdf0e10cSrcweir {
706cdf0e10cSrcweir if ( !::rtl::math::approxEqual( rComp.nVal[ 0 ], rComp.nVal[ 1 ] ) )
707cdf0e10cSrcweir {
708cdf0e10cSrcweir if( rComp.nVal[ 0 ] - rComp.nVal[ 1 ] < 0 )
709cdf0e10cSrcweir fRes = -1;
710cdf0e10cSrcweir else
711cdf0e10cSrcweir fRes = 1;
712cdf0e10cSrcweir }
713cdf0e10cSrcweir }
714cdf0e10cSrcweir else
715cdf0e10cSrcweir {
716cdf0e10cSrcweir fRes = -1; // number is less than string
717cdf0e10cSrcweir nStringQuery = 2; // 1+1
718cdf0e10cSrcweir }
719cdf0e10cSrcweir }
720cdf0e10cSrcweir else if( rComp.bVal[ 1 ] )
721cdf0e10cSrcweir {
722cdf0e10cSrcweir fRes = 1; // string is greater than number
723cdf0e10cSrcweir nStringQuery = 1; // 0+1
724cdf0e10cSrcweir }
725cdf0e10cSrcweir else
726cdf0e10cSrcweir {
727cdf0e10cSrcweir // Both strings.
728cdf0e10cSrcweir if (pOptions)
729cdf0e10cSrcweir {
730cdf0e10cSrcweir // All similar to ScTable::ValidQuery(), *rComp.pVal[1] actually
731cdf0e10cSrcweir // is/must be identical to *rEntry.pStr, which is essential for
732cdf0e10cSrcweir // regex to work through GetSearchTextPtr().
733cdf0e10cSrcweir ScQueryEntry& rEntry = pOptions->aQueryEntry;
734cdf0e10cSrcweir DBG_ASSERT( *rComp.pVal[1] == *rEntry.pStr, "ScInterpreter::CompareFunc: broken options");
735cdf0e10cSrcweir if (pOptions->bRegEx)
736cdf0e10cSrcweir {
737cdf0e10cSrcweir xub_StrLen nStart = 0;
738cdf0e10cSrcweir xub_StrLen nStop = rComp.pVal[0]->Len();
739cdf0e10cSrcweir bool bMatch = rEntry.GetSearchTextPtr(
740cdf0e10cSrcweir !pOptions->bIgnoreCase)->SearchFrwrd( *rComp.pVal[0],
741cdf0e10cSrcweir &nStart, &nStop);
742cdf0e10cSrcweir if (bMatch && pOptions->bMatchWholeCell && (nStart != 0 || nStop != rComp.pVal[0]->Len()))
743cdf0e10cSrcweir bMatch = false; // RegEx must match entire string.
744cdf0e10cSrcweir fRes = (bMatch ? 0 : 1);
745cdf0e10cSrcweir }
746cdf0e10cSrcweir else if (rEntry.eOp == SC_EQUAL || rEntry.eOp == SC_NOT_EQUAL)
747cdf0e10cSrcweir {
748cdf0e10cSrcweir ::utl::TransliterationWrapper* pTransliteration =
749cdf0e10cSrcweir (pOptions->bIgnoreCase ? ScGlobal::GetpTransliteration() :
750cdf0e10cSrcweir ScGlobal::GetCaseTransliteration());
751cdf0e10cSrcweir bool bMatch;
752cdf0e10cSrcweir if (pOptions->bMatchWholeCell)
753cdf0e10cSrcweir bMatch = pTransliteration->isEqual( *rComp.pVal[0], *rComp.pVal[1]);
754cdf0e10cSrcweir else
755cdf0e10cSrcweir {
756cdf0e10cSrcweir String aCell( pTransliteration->transliterate(
757cdf0e10cSrcweir *rComp.pVal[0], ScGlobal::eLnge, 0,
758cdf0e10cSrcweir rComp.pVal[0]->Len(), NULL));
759cdf0e10cSrcweir String aQuer( pTransliteration->transliterate(
760cdf0e10cSrcweir *rComp.pVal[1], ScGlobal::eLnge, 0,
761cdf0e10cSrcweir rComp.pVal[1]->Len(), NULL));
762cdf0e10cSrcweir bMatch = (aCell.Search( aQuer ) != STRING_NOTFOUND);
763cdf0e10cSrcweir }
764cdf0e10cSrcweir fRes = (bMatch ? 0 : 1);
765cdf0e10cSrcweir }
766cdf0e10cSrcweir else if (pOptions->bIgnoreCase)
767cdf0e10cSrcweir fRes = (double) ScGlobal::GetCollator()->compareString(
768cdf0e10cSrcweir *rComp.pVal[ 0 ], *rComp.pVal[ 1 ] );
769cdf0e10cSrcweir else
770cdf0e10cSrcweir fRes = (double) ScGlobal::GetCaseCollator()->compareString(
771cdf0e10cSrcweir *rComp.pVal[ 0 ], *rComp.pVal[ 1 ] );
772cdf0e10cSrcweir }
773cdf0e10cSrcweir else if (pDok->GetDocOptions().IsIgnoreCase())
774cdf0e10cSrcweir fRes = (double) ScGlobal::GetCollator()->compareString(
775cdf0e10cSrcweir *rComp.pVal[ 0 ], *rComp.pVal[ 1 ] );
776cdf0e10cSrcweir else
777cdf0e10cSrcweir fRes = (double) ScGlobal::GetCaseCollator()->compareString(
778cdf0e10cSrcweir *rComp.pVal[ 0 ], *rComp.pVal[ 1 ] );
779cdf0e10cSrcweir }
780cdf0e10cSrcweir if (nStringQuery && pOptions)
781cdf0e10cSrcweir {
782cdf0e10cSrcweir const ScQueryEntry& rEntry = pOptions->aQueryEntry;
783cdf0e10cSrcweir if (!rEntry.bQueryByString && rEntry.pStr->Len() &&
784cdf0e10cSrcweir (rEntry.eOp == SC_EQUAL || rEntry.eOp == SC_NOT_EQUAL))
785cdf0e10cSrcweir {
786cdf0e10cSrcweir // As in ScTable::ValidQuery() match a numeric string for a
787cdf0e10cSrcweir // number query that originated from a string, e.g. in SUMIF
788cdf0e10cSrcweir // and COUNTIF. Transliteration is not needed here.
789cdf0e10cSrcweir bool bEqual = rComp.pVal[nStringQuery-1]->Equals( *rEntry.pStr);
790cdf0e10cSrcweir // match => fRes=0, else fRes=1
791cdf0e10cSrcweir fRes = (rEntry.eOp == SC_NOT_EQUAL) ? bEqual : !bEqual;
792cdf0e10cSrcweir }
793cdf0e10cSrcweir }
794cdf0e10cSrcweir return fRes;
795cdf0e10cSrcweir }
796cdf0e10cSrcweir
797cdf0e10cSrcweir
Compare()798cdf0e10cSrcweir double ScInterpreter::Compare()
799cdf0e10cSrcweir {
800cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::Compare" );
801cdf0e10cSrcweir String aVal1, aVal2;
802cdf0e10cSrcweir ScCompare aComp( &aVal1, &aVal2 );
803cdf0e10cSrcweir for( short i = 1; i >= 0; i-- )
804cdf0e10cSrcweir {
805cdf0e10cSrcweir switch ( GetRawStackType() )
806cdf0e10cSrcweir {
807cdf0e10cSrcweir case svEmptyCell:
808cdf0e10cSrcweir Pop();
809cdf0e10cSrcweir aComp.bEmpty[ i ] = sal_True;
810cdf0e10cSrcweir break;
811cdf0e10cSrcweir case svMissing:
812cdf0e10cSrcweir case svDouble:
813cdf0e10cSrcweir aComp.nVal[ i ] = GetDouble();
814cdf0e10cSrcweir aComp.bVal[ i ] = sal_True;
815cdf0e10cSrcweir break;
816cdf0e10cSrcweir case svString:
817cdf0e10cSrcweir *aComp.pVal[ i ] = GetString();
818cdf0e10cSrcweir aComp.bVal[ i ] = sal_False;
819cdf0e10cSrcweir break;
820cdf0e10cSrcweir case svDoubleRef :
821cdf0e10cSrcweir case svSingleRef :
822cdf0e10cSrcweir {
823cdf0e10cSrcweir ScAddress aAdr;
824cdf0e10cSrcweir if ( !PopDoubleRefOrSingleRef( aAdr ) )
825cdf0e10cSrcweir break;
826cdf0e10cSrcweir ScBaseCell* pCell = GetCell( aAdr );
827cdf0e10cSrcweir if (HasCellEmptyData( pCell))
828cdf0e10cSrcweir aComp.bEmpty[ i ] = sal_True;
829cdf0e10cSrcweir else if (HasCellStringData( pCell))
830cdf0e10cSrcweir {
831cdf0e10cSrcweir GetCellString( *aComp.pVal[ i ], pCell);
832cdf0e10cSrcweir aComp.bVal[ i ] = sal_False;
833cdf0e10cSrcweir }
834cdf0e10cSrcweir else
835cdf0e10cSrcweir {
836cdf0e10cSrcweir aComp.nVal[ i ] = GetCellValue( aAdr, pCell );
837cdf0e10cSrcweir aComp.bVal[ i ] = sal_True;
838cdf0e10cSrcweir }
839cdf0e10cSrcweir }
840cdf0e10cSrcweir break;
841cdf0e10cSrcweir default:
842cdf0e10cSrcweir SetError( errIllegalParameter);
843cdf0e10cSrcweir break;
844cdf0e10cSrcweir }
845cdf0e10cSrcweir }
846cdf0e10cSrcweir if( nGlobalError )
847cdf0e10cSrcweir return 0;
848cdf0e10cSrcweir nCurFmtType = nFuncFmtType = NUMBERFORMAT_LOGICAL;
849cdf0e10cSrcweir return CompareFunc( aComp );
850cdf0e10cSrcweir }
851cdf0e10cSrcweir
852cdf0e10cSrcweir
CompareMat(ScCompareOptions * pOptions)853cdf0e10cSrcweir ScMatrixRef ScInterpreter::CompareMat( ScCompareOptions* pOptions )
854cdf0e10cSrcweir {
855cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::CompareMat" );
856cdf0e10cSrcweir String aVal1, aVal2;
857cdf0e10cSrcweir ScCompare aComp( &aVal1, &aVal2 );
858cdf0e10cSrcweir ScMatrixRef pMat[2];
859cdf0e10cSrcweir ScAddress aAdr;
860cdf0e10cSrcweir for( short i = 1; i >= 0; i-- )
861cdf0e10cSrcweir {
862cdf0e10cSrcweir switch (GetRawStackType())
863cdf0e10cSrcweir {
864cdf0e10cSrcweir case svEmptyCell:
865cdf0e10cSrcweir Pop();
866cdf0e10cSrcweir aComp.bEmpty[ i ] = sal_True;
867cdf0e10cSrcweir break;
868cdf0e10cSrcweir case svMissing:
869cdf0e10cSrcweir case svDouble:
870cdf0e10cSrcweir aComp.nVal[ i ] = GetDouble();
871cdf0e10cSrcweir aComp.bVal[ i ] = sal_True;
872cdf0e10cSrcweir break;
873cdf0e10cSrcweir case svString:
874cdf0e10cSrcweir *aComp.pVal[ i ] = GetString();
875cdf0e10cSrcweir aComp.bVal[ i ] = sal_False;
876cdf0e10cSrcweir break;
877cdf0e10cSrcweir case svSingleRef:
878cdf0e10cSrcweir {
879cdf0e10cSrcweir PopSingleRef( aAdr );
880cdf0e10cSrcweir ScBaseCell* pCell = GetCell( aAdr );
881cdf0e10cSrcweir if (HasCellEmptyData( pCell))
882cdf0e10cSrcweir aComp.bEmpty[ i ] = sal_True;
883cdf0e10cSrcweir else if (HasCellStringData( pCell))
884cdf0e10cSrcweir {
885cdf0e10cSrcweir GetCellString( *aComp.pVal[ i ], pCell);
886cdf0e10cSrcweir aComp.bVal[ i ] = sal_False;
887cdf0e10cSrcweir }
888cdf0e10cSrcweir else
889cdf0e10cSrcweir {
890cdf0e10cSrcweir aComp.nVal[ i ] = GetCellValue( aAdr, pCell );
891cdf0e10cSrcweir aComp.bVal[ i ] = sal_True;
892cdf0e10cSrcweir }
893cdf0e10cSrcweir }
894cdf0e10cSrcweir break;
895cdf0e10cSrcweir case svDoubleRef:
896cdf0e10cSrcweir case svMatrix:
897cdf0e10cSrcweir pMat[ i ] = GetMatrix();
898cdf0e10cSrcweir if ( !pMat[ i ] )
899cdf0e10cSrcweir SetError( errIllegalParameter);
900cdf0e10cSrcweir else
901cdf0e10cSrcweir pMat[i]->SetErrorInterpreter( NULL);
902cdf0e10cSrcweir // errors are transported as DoubleError inside matrix
903cdf0e10cSrcweir break;
904cdf0e10cSrcweir default:
905cdf0e10cSrcweir SetError( errIllegalParameter);
906cdf0e10cSrcweir break;
907cdf0e10cSrcweir }
908cdf0e10cSrcweir }
909cdf0e10cSrcweir ScMatrixRef pResMat = NULL;
910cdf0e10cSrcweir if( !nGlobalError )
911cdf0e10cSrcweir {
912cdf0e10cSrcweir if ( pMat[0] && pMat[1] )
913cdf0e10cSrcweir {
914cdf0e10cSrcweir SCSIZE nC0, nC1;
915cdf0e10cSrcweir SCSIZE nR0, nR1;
916cdf0e10cSrcweir pMat[0]->GetDimensions( nC0, nR0 );
917cdf0e10cSrcweir pMat[1]->GetDimensions( nC1, nR1 );
918cdf0e10cSrcweir SCSIZE nC = Max( nC0, nC1 );
919cdf0e10cSrcweir SCSIZE nR = Max( nR0, nR1 );
920cdf0e10cSrcweir pResMat = GetNewMat( nC, nR);
921cdf0e10cSrcweir if ( !pResMat )
922cdf0e10cSrcweir return NULL;
923cdf0e10cSrcweir for ( SCSIZE j=0; j<nC; j++ )
924cdf0e10cSrcweir {
925cdf0e10cSrcweir for ( SCSIZE k=0; k<nR; k++ )
926cdf0e10cSrcweir {
927cdf0e10cSrcweir SCSIZE nCol = j, nRow = k;
928cdf0e10cSrcweir if ( pMat[0]->ValidColRowOrReplicated( nCol, nRow ) &&
929cdf0e10cSrcweir pMat[1]->ValidColRowOrReplicated( nCol, nRow ))
930cdf0e10cSrcweir {
931cdf0e10cSrcweir for ( short i=1; i>=0; i-- )
932cdf0e10cSrcweir {
933cdf0e10cSrcweir if ( pMat[i]->IsString(j,k) )
934cdf0e10cSrcweir {
935cdf0e10cSrcweir aComp.bVal[i] = sal_False;
936cdf0e10cSrcweir *aComp.pVal[i] = pMat[i]->GetString(j,k);
937cdf0e10cSrcweir aComp.bEmpty[i] = pMat[i]->IsEmpty(j,k);
938cdf0e10cSrcweir }
939cdf0e10cSrcweir else
940cdf0e10cSrcweir {
941cdf0e10cSrcweir aComp.bVal[i] = sal_True;
942cdf0e10cSrcweir aComp.nVal[i] = pMat[i]->GetDouble(j,k);
943cdf0e10cSrcweir aComp.bEmpty[i] = sal_False;
944cdf0e10cSrcweir }
945cdf0e10cSrcweir }
946cdf0e10cSrcweir pResMat->PutDouble( CompareFunc( aComp, pOptions ), j,k );
947cdf0e10cSrcweir }
948cdf0e10cSrcweir else
949cdf0e10cSrcweir pResMat->PutString( ScGlobal::GetRscString(STR_NO_VALUE), j,k );
950cdf0e10cSrcweir }
951cdf0e10cSrcweir }
952cdf0e10cSrcweir }
953cdf0e10cSrcweir else if ( pMat[0] || pMat[1] )
954cdf0e10cSrcweir {
955cdf0e10cSrcweir short i = ( pMat[0] ? 0 : 1);
956cdf0e10cSrcweir SCSIZE nC, nR;
957cdf0e10cSrcweir pMat[i]->GetDimensions( nC, nR );
958cdf0e10cSrcweir pResMat = GetNewMat( nC, nR);
959cdf0e10cSrcweir if ( !pResMat )
960cdf0e10cSrcweir return NULL;
961cdf0e10cSrcweir SCSIZE n = nC * nR;
962cdf0e10cSrcweir for ( SCSIZE j=0; j<n; j++ )
963cdf0e10cSrcweir {
964cdf0e10cSrcweir if ( pMat[i]->IsValue(j) )
965cdf0e10cSrcweir {
966cdf0e10cSrcweir aComp.bVal[i] = sal_True;
967cdf0e10cSrcweir aComp.nVal[i] = pMat[i]->GetDouble(j);
968cdf0e10cSrcweir aComp.bEmpty[i] = sal_False;
969cdf0e10cSrcweir }
970cdf0e10cSrcweir else
971cdf0e10cSrcweir {
972cdf0e10cSrcweir aComp.bVal[i] = sal_False;
973cdf0e10cSrcweir *aComp.pVal[i] = pMat[i]->GetString(j);
974cdf0e10cSrcweir aComp.bEmpty[i] = pMat[i]->IsEmpty(j);
975cdf0e10cSrcweir }
976cdf0e10cSrcweir pResMat->PutDouble( CompareFunc( aComp, pOptions ), j );
977cdf0e10cSrcweir }
978cdf0e10cSrcweir }
979cdf0e10cSrcweir }
980cdf0e10cSrcweir nCurFmtType = nFuncFmtType = NUMBERFORMAT_LOGICAL;
981cdf0e10cSrcweir return pResMat;
982cdf0e10cSrcweir }
983cdf0e10cSrcweir
984cdf0e10cSrcweir
QueryMat(ScMatrix * pMat,ScCompareOptions & rOptions)985cdf0e10cSrcweir ScMatrixRef ScInterpreter::QueryMat( ScMatrix* pMat, ScCompareOptions& rOptions )
986cdf0e10cSrcweir {
987cdf0e10cSrcweir short nSaveCurFmtType = nCurFmtType;
988cdf0e10cSrcweir short nSaveFuncFmtType = nFuncFmtType;
989cdf0e10cSrcweir PushMatrix( pMat);
990cdf0e10cSrcweir if (rOptions.aQueryEntry.bQueryByString)
991cdf0e10cSrcweir PushString( *rOptions.aQueryEntry.pStr);
992cdf0e10cSrcweir else
993cdf0e10cSrcweir PushDouble( rOptions.aQueryEntry.nVal);
994cdf0e10cSrcweir ScMatrixRef pResultMatrix = CompareMat( &rOptions);
995cdf0e10cSrcweir nCurFmtType = nSaveCurFmtType;
996cdf0e10cSrcweir nFuncFmtType = nSaveFuncFmtType;
997cdf0e10cSrcweir if (nGlobalError || !pResultMatrix)
998cdf0e10cSrcweir {
999cdf0e10cSrcweir SetError( errIllegalParameter);
1000cdf0e10cSrcweir return pResultMatrix;
1001cdf0e10cSrcweir }
1002cdf0e10cSrcweir
1003cdf0e10cSrcweir switch (rOptions.aQueryEntry.eOp)
1004cdf0e10cSrcweir {
1005cdf0e10cSrcweir case SC_EQUAL:
1006cdf0e10cSrcweir pResultMatrix->CompareEqual();
1007cdf0e10cSrcweir break;
1008cdf0e10cSrcweir case SC_LESS:
1009cdf0e10cSrcweir pResultMatrix->CompareLess();
1010cdf0e10cSrcweir break;
1011cdf0e10cSrcweir case SC_GREATER:
1012cdf0e10cSrcweir pResultMatrix->CompareGreater();
1013cdf0e10cSrcweir break;
1014cdf0e10cSrcweir case SC_LESS_EQUAL:
1015cdf0e10cSrcweir pResultMatrix->CompareLessEqual();
1016cdf0e10cSrcweir break;
1017cdf0e10cSrcweir case SC_GREATER_EQUAL:
1018cdf0e10cSrcweir pResultMatrix->CompareGreaterEqual();
1019cdf0e10cSrcweir break;
1020cdf0e10cSrcweir case SC_NOT_EQUAL:
1021cdf0e10cSrcweir pResultMatrix->CompareNotEqual();
1022cdf0e10cSrcweir break;
1023cdf0e10cSrcweir default:
1024cdf0e10cSrcweir SetError( errIllegalArgument);
1025cdf0e10cSrcweir DBG_ERROR1( "ScInterpreter::QueryMat: unhandled comparison operator: %d", (int)rOptions.aQueryEntry.eOp);
1026cdf0e10cSrcweir }
1027cdf0e10cSrcweir return pResultMatrix;
1028cdf0e10cSrcweir }
1029cdf0e10cSrcweir
1030cdf0e10cSrcweir
ScEqual()1031cdf0e10cSrcweir void ScInterpreter::ScEqual()
1032cdf0e10cSrcweir {
1033cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScEqual" );
1034cdf0e10cSrcweir if ( GetStackType(1) == svMatrix || GetStackType(2) == svMatrix )
1035cdf0e10cSrcweir {
1036cdf0e10cSrcweir ScMatrixRef pMat = CompareMat();
1037cdf0e10cSrcweir if ( !pMat )
1038cdf0e10cSrcweir PushIllegalParameter();
1039cdf0e10cSrcweir else
1040cdf0e10cSrcweir {
1041cdf0e10cSrcweir pMat->CompareEqual();
1042cdf0e10cSrcweir PushMatrix( pMat );
1043cdf0e10cSrcweir }
1044cdf0e10cSrcweir }
1045cdf0e10cSrcweir else
1046cdf0e10cSrcweir PushInt( Compare() == 0 );
1047cdf0e10cSrcweir }
1048cdf0e10cSrcweir
1049cdf0e10cSrcweir
ScNotEqual()1050cdf0e10cSrcweir void ScInterpreter::ScNotEqual()
1051cdf0e10cSrcweir {
1052cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScNotEqual" );
1053cdf0e10cSrcweir if ( GetStackType(1) == svMatrix || GetStackType(2) == svMatrix )
1054cdf0e10cSrcweir {
1055cdf0e10cSrcweir ScMatrixRef pMat = CompareMat();
1056cdf0e10cSrcweir if ( !pMat )
1057cdf0e10cSrcweir PushIllegalParameter();
1058cdf0e10cSrcweir else
1059cdf0e10cSrcweir {
1060cdf0e10cSrcweir pMat->CompareNotEqual();
1061cdf0e10cSrcweir PushMatrix( pMat );
1062cdf0e10cSrcweir }
1063cdf0e10cSrcweir }
1064cdf0e10cSrcweir else
1065cdf0e10cSrcweir PushInt( Compare() != 0 );
1066cdf0e10cSrcweir }
1067cdf0e10cSrcweir
1068cdf0e10cSrcweir
ScLess()1069cdf0e10cSrcweir void ScInterpreter::ScLess()
1070cdf0e10cSrcweir {
1071cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScLess" );
1072cdf0e10cSrcweir if ( GetStackType(1) == svMatrix || GetStackType(2) == svMatrix )
1073cdf0e10cSrcweir {
1074cdf0e10cSrcweir ScMatrixRef pMat = CompareMat();
1075cdf0e10cSrcweir if ( !pMat )
1076cdf0e10cSrcweir PushIllegalParameter();
1077cdf0e10cSrcweir else
1078cdf0e10cSrcweir {
1079cdf0e10cSrcweir pMat->CompareLess();
1080cdf0e10cSrcweir PushMatrix( pMat );
1081cdf0e10cSrcweir }
1082cdf0e10cSrcweir }
1083cdf0e10cSrcweir else
1084cdf0e10cSrcweir PushInt( Compare() < 0 );
1085cdf0e10cSrcweir }
1086cdf0e10cSrcweir
1087cdf0e10cSrcweir
ScGreater()1088cdf0e10cSrcweir void ScInterpreter::ScGreater()
1089cdf0e10cSrcweir {
1090cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScGreater" );
1091cdf0e10cSrcweir if ( GetStackType(1) == svMatrix || GetStackType(2) == svMatrix )
1092cdf0e10cSrcweir {
1093cdf0e10cSrcweir ScMatrixRef pMat = CompareMat();
1094cdf0e10cSrcweir if ( !pMat )
1095cdf0e10cSrcweir PushIllegalParameter();
1096cdf0e10cSrcweir else
1097cdf0e10cSrcweir {
1098cdf0e10cSrcweir pMat->CompareGreater();
1099cdf0e10cSrcweir PushMatrix( pMat );
1100cdf0e10cSrcweir }
1101cdf0e10cSrcweir }
1102cdf0e10cSrcweir else
1103cdf0e10cSrcweir PushInt( Compare() > 0 );
1104cdf0e10cSrcweir }
1105cdf0e10cSrcweir
1106cdf0e10cSrcweir
ScLessEqual()1107cdf0e10cSrcweir void ScInterpreter::ScLessEqual()
1108cdf0e10cSrcweir {
1109cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScLessEqual" );
1110cdf0e10cSrcweir if ( GetStackType(1) == svMatrix || GetStackType(2) == svMatrix )
1111cdf0e10cSrcweir {
1112cdf0e10cSrcweir ScMatrixRef pMat = CompareMat();
1113cdf0e10cSrcweir if ( !pMat )
1114cdf0e10cSrcweir PushIllegalParameter();
1115cdf0e10cSrcweir else
1116cdf0e10cSrcweir {
1117cdf0e10cSrcweir pMat->CompareLessEqual();
1118cdf0e10cSrcweir PushMatrix( pMat );
1119cdf0e10cSrcweir }
1120cdf0e10cSrcweir }
1121cdf0e10cSrcweir else
1122cdf0e10cSrcweir PushInt( Compare() <= 0 );
1123cdf0e10cSrcweir }
1124cdf0e10cSrcweir
1125cdf0e10cSrcweir
ScGreaterEqual()1126cdf0e10cSrcweir void ScInterpreter::ScGreaterEqual()
1127cdf0e10cSrcweir {
1128cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScGreaterEqual" );
1129cdf0e10cSrcweir if ( GetStackType(1) == svMatrix || GetStackType(2) == svMatrix )
1130cdf0e10cSrcweir {
1131cdf0e10cSrcweir ScMatrixRef pMat = CompareMat();
1132cdf0e10cSrcweir if ( !pMat )
1133cdf0e10cSrcweir PushIllegalParameter();
1134cdf0e10cSrcweir else
1135cdf0e10cSrcweir {
1136cdf0e10cSrcweir pMat->CompareGreaterEqual();
1137cdf0e10cSrcweir PushMatrix( pMat );
1138cdf0e10cSrcweir }
1139cdf0e10cSrcweir }
1140cdf0e10cSrcweir else
1141cdf0e10cSrcweir PushInt( Compare() >= 0 );
1142cdf0e10cSrcweir }
1143cdf0e10cSrcweir
ScBitAnd()11440f94c4d7SDamjan Jovanovic void ScInterpreter::ScBitAnd() {
11450f94c4d7SDamjan Jovanovic ScBitArithmeticOps(bitOperations::BITAND);
11460f94c4d7SDamjan Jovanovic }
11470f94c4d7SDamjan Jovanovic
ScBitOr()11480f94c4d7SDamjan Jovanovic void ScInterpreter::ScBitOr() {
11490f94c4d7SDamjan Jovanovic ScBitArithmeticOps(bitOperations::BITOR);
11500f94c4d7SDamjan Jovanovic }
11510f94c4d7SDamjan Jovanovic
ScBitXor()11520f94c4d7SDamjan Jovanovic void ScInterpreter::ScBitXor() {
11530f94c4d7SDamjan Jovanovic ScBitArithmeticOps(bitOperations::BITXOR);
11540f94c4d7SDamjan Jovanovic }
11550f94c4d7SDamjan Jovanovic
11560f94c4d7SDamjan Jovanovic /* Helper function that calculates the result in bitwise arithmetic operations helping avoid code repetition */
doOperation(sal_uInt64 val,ScInterpreter::bitOperations::bitArithmetic bitOp,sal_uInt64 & res,sal_Bool & first)11570f94c4d7SDamjan Jovanovic static void doOperation( sal_uInt64 val, ScInterpreter::bitOperations::bitArithmetic bitOp, sal_uInt64 &res, sal_Bool &first )
11580f94c4d7SDamjan Jovanovic {
11590f94c4d7SDamjan Jovanovic if ( first )
11600f94c4d7SDamjan Jovanovic {
11610f94c4d7SDamjan Jovanovic res = val;
11620f94c4d7SDamjan Jovanovic first = sal_False;
11630f94c4d7SDamjan Jovanovic }
11640f94c4d7SDamjan Jovanovic else
11650f94c4d7SDamjan Jovanovic {
11660f94c4d7SDamjan Jovanovic if (bitOp == ScInterpreter::bitOperations::BITAND)
11670f94c4d7SDamjan Jovanovic res = res & val;
11680f94c4d7SDamjan Jovanovic else if (bitOp == ScInterpreter::bitOperations::BITOR)
11690f94c4d7SDamjan Jovanovic res = res | val;
11700f94c4d7SDamjan Jovanovic else if (bitOp == ScInterpreter::bitOperations::BITXOR)
11710f94c4d7SDamjan Jovanovic res = res ^ val;
11720f94c4d7SDamjan Jovanovic }
11730f94c4d7SDamjan Jovanovic }
11740f94c4d7SDamjan Jovanovic
ScBitArithmeticOps(bitOperations::bitArithmetic bitOp)11750f94c4d7SDamjan Jovanovic void ScInterpreter::ScBitArithmeticOps(bitOperations::bitArithmetic bitOp)
11760f94c4d7SDamjan Jovanovic {
11770f94c4d7SDamjan Jovanovic nFuncFmtType = NUMBERFORMAT_NUMBER;
11780f94c4d7SDamjan Jovanovic short nParamCount = GetByte();
11790f94c4d7SDamjan Jovanovic static const sal_uInt64 max_val = SAL_CONST_UINT64( 281474976710656 );
11800f94c4d7SDamjan Jovanovic static const int NUMBER_OF_ARGUMENTS = 2;
11810f94c4d7SDamjan Jovanovic
11820f94c4d7SDamjan Jovanovic if ( MustHaveParamCount( nParamCount, NUMBER_OF_ARGUMENTS ) )
11830f94c4d7SDamjan Jovanovic {
11840f94c4d7SDamjan Jovanovic double *arguments = new double[NUMBER_OF_ARGUMENTS];
11850f94c4d7SDamjan Jovanovic
11860f94c4d7SDamjan Jovanovic for (int i=0; i<NUMBER_OF_ARGUMENTS; i++)
11870f94c4d7SDamjan Jovanovic {
11880f94c4d7SDamjan Jovanovic arguments[i] = ::rtl::math::approxFloor( GetDouble() );
11890f94c4d7SDamjan Jovanovic if ( arguments[i] < 0 || arguments[i] > max_val )
11900f94c4d7SDamjan Jovanovic {
11910f94c4d7SDamjan Jovanovic PushIllegalArgument();
11920f94c4d7SDamjan Jovanovic }
11930f94c4d7SDamjan Jovanovic }
11940f94c4d7SDamjan Jovanovic
11950f94c4d7SDamjan Jovanovic sal_uInt64 res = 0;
11960f94c4d7SDamjan Jovanovic sal_Bool first = sal_True;
11970f94c4d7SDamjan Jovanovic
11980f94c4d7SDamjan Jovanovic
11990f94c4d7SDamjan Jovanovic for (int i=0; i<NUMBER_OF_ARGUMENTS; i++)
12000f94c4d7SDamjan Jovanovic {
12010f94c4d7SDamjan Jovanovic doOperation( ( sal_uInt64 )arguments[i], bitOp, res, first );
12020f94c4d7SDamjan Jovanovic }
12030f94c4d7SDamjan Jovanovic
12040f94c4d7SDamjan Jovanovic delete[] arguments;
12050f94c4d7SDamjan Jovanovic PushDouble( (double) res );
12060f94c4d7SDamjan Jovanovic
12070f94c4d7SDamjan Jovanovic }
12080f94c4d7SDamjan Jovanovic }
12090f94c4d7SDamjan Jovanovic
ScBitRShift()1210a940b7f5Sasf-sync-process void ScInterpreter::ScBitRShift() {
1211a940b7f5Sasf-sync-process ScBitShiftOps(bitOperations::BITRSHIFT);
1212a940b7f5Sasf-sync-process }
1213a940b7f5Sasf-sync-process
ScBitLShift()1214a940b7f5Sasf-sync-process void ScInterpreter::ScBitLShift() {
1215a940b7f5Sasf-sync-process ScBitShiftOps(bitOperations::BITLSHIFT);
1216a940b7f5Sasf-sync-process }
1217a940b7f5Sasf-sync-process
ScBitShiftOps(bitOperations::bitShift bitOp)1218a940b7f5Sasf-sync-process void ScInterpreter::ScBitShiftOps(bitOperations::bitShift bitOp) {
1219a940b7f5Sasf-sync-process if ( MustHaveParamCount( GetByte(), 2 ) )
1220a940b7f5Sasf-sync-process {
1221a940b7f5Sasf-sync-process double n = ::rtl::math::approxFloor( GetDouble() );
1222a940b7f5Sasf-sync-process double val = ::rtl::math::approxFloor( GetDouble() );
1223a940b7f5Sasf-sync-process
1224a940b7f5Sasf-sync-process if ( val < 0 )
1225a940b7f5Sasf-sync-process {
1226a940b7f5Sasf-sync-process PushIllegalArgument();
1227a940b7f5Sasf-sync-process }
1228a940b7f5Sasf-sync-process else
1229a940b7f5Sasf-sync-process {
1230a940b7f5Sasf-sync-process double result;
1231a940b7f5Sasf-sync-process if (n < 0)
1232a940b7f5Sasf-sync-process {
1233a940b7f5Sasf-sync-process if (bitOp == bitOperations::BITLSHIFT)
1234a940b7f5Sasf-sync-process result = (sal_uInt64) val >> (sal_uInt64) -n;
1235a940b7f5Sasf-sync-process else
1236a940b7f5Sasf-sync-process result = (sal_uInt64) val << (sal_uInt64) -n;
1237a940b7f5Sasf-sync-process }
1238a940b7f5Sasf-sync-process else if( n == 0)
1239a940b7f5Sasf-sync-process result = val;
1240a940b7f5Sasf-sync-process else
1241a940b7f5Sasf-sync-process {
1242a940b7f5Sasf-sync-process if (bitOp == bitOperations::BITLSHIFT)
1243a940b7f5Sasf-sync-process result = (sal_uInt64) val << (sal_uInt64) n;
1244a940b7f5Sasf-sync-process else
1245a940b7f5Sasf-sync-process result = (sal_uInt64) val >> (sal_uInt64) n;
1246a940b7f5Sasf-sync-process
1247a940b7f5Sasf-sync-process }
1248a940b7f5Sasf-sync-process PushDouble( result );
1249a940b7f5Sasf-sync-process }
1250a940b7f5Sasf-sync-process }
1251a940b7f5Sasf-sync-process }
1252cdf0e10cSrcweir
ScAnd()1253cdf0e10cSrcweir void ScInterpreter::ScAnd()
1254cdf0e10cSrcweir {
1255cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScAnd" );
1256cdf0e10cSrcweir nFuncFmtType = NUMBERFORMAT_LOGICAL;
1257cdf0e10cSrcweir short nParamCount = GetByte();
1258cdf0e10cSrcweir if ( MustHaveParamCountMin( nParamCount, 1 ) )
1259cdf0e10cSrcweir {
1260cdf0e10cSrcweir sal_Bool bHaveValue = sal_False;
1261cdf0e10cSrcweir short nRes = sal_True;
1262cdf0e10cSrcweir size_t nRefInList = 0;
1263cdf0e10cSrcweir while( nParamCount-- > 0)
1264cdf0e10cSrcweir {
1265cdf0e10cSrcweir if ( !nGlobalError )
1266cdf0e10cSrcweir {
1267cdf0e10cSrcweir switch ( GetStackType() )
1268cdf0e10cSrcweir {
1269cdf0e10cSrcweir case svDouble :
1270cdf0e10cSrcweir bHaveValue = sal_True;
1271cdf0e10cSrcweir nRes &= ( PopDouble() != 0.0 );
1272cdf0e10cSrcweir break;
1273cdf0e10cSrcweir case svString :
1274cdf0e10cSrcweir Pop();
1275cdf0e10cSrcweir SetError( errNoValue );
1276cdf0e10cSrcweir break;
1277cdf0e10cSrcweir case svSingleRef :
1278cdf0e10cSrcweir {
1279cdf0e10cSrcweir ScAddress aAdr;
1280cdf0e10cSrcweir PopSingleRef( aAdr );
1281cdf0e10cSrcweir if ( !nGlobalError )
1282cdf0e10cSrcweir {
1283cdf0e10cSrcweir ScBaseCell* pCell = GetCell( aAdr );
1284cdf0e10cSrcweir if ( HasCellValueData( pCell ) )
1285cdf0e10cSrcweir {
1286cdf0e10cSrcweir bHaveValue = sal_True;
1287cdf0e10cSrcweir nRes &= ( GetCellValue( aAdr, pCell ) != 0.0 );
1288cdf0e10cSrcweir }
1289cdf0e10cSrcweir // else: Xcl setzt hier keinen Fehler
1290cdf0e10cSrcweir }
1291cdf0e10cSrcweir }
1292cdf0e10cSrcweir break;
1293cdf0e10cSrcweir case svDoubleRef:
1294cdf0e10cSrcweir case svRefList:
1295cdf0e10cSrcweir {
1296cdf0e10cSrcweir ScRange aRange;
1297cdf0e10cSrcweir PopDoubleRef( aRange, nParamCount, nRefInList);
1298cdf0e10cSrcweir if ( !nGlobalError )
1299cdf0e10cSrcweir {
1300cdf0e10cSrcweir double fVal;
1301cdf0e10cSrcweir sal_uInt16 nErr = 0;
1302cdf0e10cSrcweir ScValueIterator aValIter( pDok, aRange );
1303cdf0e10cSrcweir if ( aValIter.GetFirst( fVal, nErr ) )
1304cdf0e10cSrcweir {
1305cdf0e10cSrcweir bHaveValue = sal_True;
1306cdf0e10cSrcweir do
1307cdf0e10cSrcweir {
1308cdf0e10cSrcweir nRes &= ( fVal != 0.0 );
1309cdf0e10cSrcweir } while ( (nErr == 0) &&
1310cdf0e10cSrcweir aValIter.GetNext( fVal, nErr ) );
1311cdf0e10cSrcweir }
1312cdf0e10cSrcweir SetError( nErr );
1313cdf0e10cSrcweir }
1314cdf0e10cSrcweir }
1315cdf0e10cSrcweir break;
1316cdf0e10cSrcweir case svMatrix:
1317cdf0e10cSrcweir {
1318cdf0e10cSrcweir ScMatrixRef pMat = GetMatrix();
1319cdf0e10cSrcweir if ( pMat )
1320cdf0e10cSrcweir {
1321cdf0e10cSrcweir bHaveValue = sal_True;
1322cdf0e10cSrcweir double fVal = pMat->And();
1323cdf0e10cSrcweir sal_uInt16 nErr = GetDoubleErrorValue( fVal );
1324cdf0e10cSrcweir if ( nErr )
1325cdf0e10cSrcweir {
1326cdf0e10cSrcweir SetError( nErr );
1327cdf0e10cSrcweir nRes = sal_False;
1328cdf0e10cSrcweir }
1329cdf0e10cSrcweir else
1330cdf0e10cSrcweir nRes &= (fVal != 0.0);
1331cdf0e10cSrcweir }
1332cdf0e10cSrcweir // else: GetMatrix did set errIllegalParameter
1333cdf0e10cSrcweir }
1334cdf0e10cSrcweir break;
1335cdf0e10cSrcweir default:
1336cdf0e10cSrcweir Pop();
1337cdf0e10cSrcweir SetError( errIllegalParameter);
1338cdf0e10cSrcweir }
1339cdf0e10cSrcweir }
1340cdf0e10cSrcweir else
1341cdf0e10cSrcweir Pop();
1342cdf0e10cSrcweir }
1343cdf0e10cSrcweir if ( bHaveValue )
1344cdf0e10cSrcweir PushInt( nRes );
1345cdf0e10cSrcweir else
1346cdf0e10cSrcweir PushNoValue();
1347cdf0e10cSrcweir }
1348cdf0e10cSrcweir }
1349cdf0e10cSrcweir
1350cdf0e10cSrcweir
ScOr()1351cdf0e10cSrcweir void ScInterpreter::ScOr()
1352cdf0e10cSrcweir {
1353cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScOr" );
1354cdf0e10cSrcweir nFuncFmtType = NUMBERFORMAT_LOGICAL;
1355cdf0e10cSrcweir short nParamCount = GetByte();
1356cdf0e10cSrcweir if ( MustHaveParamCountMin( nParamCount, 1 ) )
1357cdf0e10cSrcweir {
1358cdf0e10cSrcweir sal_Bool bHaveValue = sal_False;
1359cdf0e10cSrcweir short nRes = sal_False;
1360cdf0e10cSrcweir size_t nRefInList = 0;
1361cdf0e10cSrcweir while( nParamCount-- > 0)
1362cdf0e10cSrcweir {
1363cdf0e10cSrcweir if ( !nGlobalError )
1364cdf0e10cSrcweir {
1365cdf0e10cSrcweir switch ( GetStackType() )
1366cdf0e10cSrcweir {
1367cdf0e10cSrcweir case svDouble :
1368cdf0e10cSrcweir bHaveValue = sal_True;
1369cdf0e10cSrcweir nRes |= ( PopDouble() != 0.0 );
1370cdf0e10cSrcweir break;
1371cdf0e10cSrcweir case svString :
1372cdf0e10cSrcweir Pop();
1373cdf0e10cSrcweir SetError( errNoValue );
1374cdf0e10cSrcweir break;
1375cdf0e10cSrcweir case svSingleRef :
1376cdf0e10cSrcweir {
1377cdf0e10cSrcweir ScAddress aAdr;
1378cdf0e10cSrcweir PopSingleRef( aAdr );
1379cdf0e10cSrcweir if ( !nGlobalError )
1380cdf0e10cSrcweir {
1381cdf0e10cSrcweir ScBaseCell* pCell = GetCell( aAdr );
1382cdf0e10cSrcweir if ( HasCellValueData( pCell ) )
1383cdf0e10cSrcweir {
1384cdf0e10cSrcweir bHaveValue = sal_True;
1385cdf0e10cSrcweir nRes |= ( GetCellValue( aAdr, pCell ) != 0.0 );
1386cdf0e10cSrcweir }
1387cdf0e10cSrcweir // else: Xcl setzt hier keinen Fehler
1388cdf0e10cSrcweir }
1389cdf0e10cSrcweir }
1390cdf0e10cSrcweir break;
1391cdf0e10cSrcweir case svDoubleRef:
1392cdf0e10cSrcweir case svRefList:
1393cdf0e10cSrcweir {
1394cdf0e10cSrcweir ScRange aRange;
1395cdf0e10cSrcweir PopDoubleRef( aRange, nParamCount, nRefInList);
1396cdf0e10cSrcweir if ( !nGlobalError )
1397cdf0e10cSrcweir {
1398cdf0e10cSrcweir double fVal;
1399cdf0e10cSrcweir sal_uInt16 nErr = 0;
1400cdf0e10cSrcweir ScValueIterator aValIter( pDok, aRange );
1401cdf0e10cSrcweir if ( aValIter.GetFirst( fVal, nErr ) )
1402cdf0e10cSrcweir {
1403cdf0e10cSrcweir bHaveValue = sal_True;
1404cdf0e10cSrcweir do
1405cdf0e10cSrcweir {
1406cdf0e10cSrcweir nRes |= ( fVal != 0.0 );
1407cdf0e10cSrcweir } while ( (nErr == 0) &&
1408cdf0e10cSrcweir aValIter.GetNext( fVal, nErr ) );
1409cdf0e10cSrcweir }
1410cdf0e10cSrcweir SetError( nErr );
1411cdf0e10cSrcweir }
1412cdf0e10cSrcweir }
1413cdf0e10cSrcweir break;
1414cdf0e10cSrcweir case svMatrix:
1415cdf0e10cSrcweir {
1416cdf0e10cSrcweir bHaveValue = sal_True;
1417cdf0e10cSrcweir ScMatrixRef pMat = GetMatrix();
1418cdf0e10cSrcweir if ( pMat )
1419cdf0e10cSrcweir {
1420cdf0e10cSrcweir bHaveValue = sal_True;
1421cdf0e10cSrcweir double fVal = pMat->Or();
1422cdf0e10cSrcweir sal_uInt16 nErr = GetDoubleErrorValue( fVal );
1423cdf0e10cSrcweir if ( nErr )
1424cdf0e10cSrcweir {
1425cdf0e10cSrcweir SetError( nErr );
1426cdf0e10cSrcweir nRes = sal_False;
1427cdf0e10cSrcweir }
1428cdf0e10cSrcweir else
1429cdf0e10cSrcweir nRes |= (fVal != 0.0);
1430cdf0e10cSrcweir }
1431cdf0e10cSrcweir // else: GetMatrix did set errIllegalParameter
1432cdf0e10cSrcweir }
1433cdf0e10cSrcweir break;
1434cdf0e10cSrcweir default:
1435cdf0e10cSrcweir Pop();
1436cdf0e10cSrcweir SetError( errIllegalParameter);
1437cdf0e10cSrcweir }
1438cdf0e10cSrcweir }
1439cdf0e10cSrcweir else
1440cdf0e10cSrcweir Pop();
1441cdf0e10cSrcweir }
1442cdf0e10cSrcweir if ( bHaveValue )
1443cdf0e10cSrcweir PushInt( nRes );
1444cdf0e10cSrcweir else
1445cdf0e10cSrcweir PushNoValue();
1446cdf0e10cSrcweir }
1447cdf0e10cSrcweir }
1448cdf0e10cSrcweir
ScXor()1449245212b4SAndrew Rist void ScInterpreter::ScXor()
1450245212b4SAndrew Rist {
1451245212b4SAndrew Rist RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "makkica", "ScInterpreter::ScXor" );
1452245212b4SAndrew Rist nFuncFmtType = NUMBERFORMAT_LOGICAL;
1453245212b4SAndrew Rist short nParamCount = GetByte();
1454245212b4SAndrew Rist if ( MustHaveParamCountMin( nParamCount, 1 ) )
1455245212b4SAndrew Rist {
1456245212b4SAndrew Rist bool bHaveValue = false;
1457245212b4SAndrew Rist short nRes = 0;
1458245212b4SAndrew Rist size_t nRefInList = 0;
1459245212b4SAndrew Rist while( nParamCount-- > 0)
1460245212b4SAndrew Rist {
1461245212b4SAndrew Rist if ( !nGlobalError )
1462245212b4SAndrew Rist {
1463245212b4SAndrew Rist switch ( GetStackType() )
1464245212b4SAndrew Rist {
1465245212b4SAndrew Rist case svDouble :
1466245212b4SAndrew Rist bHaveValue = true;
1467245212b4SAndrew Rist nRes ^= ( PopDouble() != 0.0 );
1468245212b4SAndrew Rist break;
1469245212b4SAndrew Rist case svString :
1470245212b4SAndrew Rist Pop();
1471245212b4SAndrew Rist SetError( errNoValue );
1472245212b4SAndrew Rist break;
1473245212b4SAndrew Rist case svSingleRef :
1474245212b4SAndrew Rist {
1475245212b4SAndrew Rist ScAddress aAdr;
1476245212b4SAndrew Rist PopSingleRef( aAdr );
1477245212b4SAndrew Rist if ( !nGlobalError )
1478245212b4SAndrew Rist {
1479245212b4SAndrew Rist ScBaseCell* pCell = GetCell( aAdr );
1480245212b4SAndrew Rist if ( HasCellValueData( pCell ) )
1481245212b4SAndrew Rist {
1482245212b4SAndrew Rist bHaveValue = true;
1483245212b4SAndrew Rist nRes ^= ( GetCellValue( aAdr, pCell ) != 0.0 );
1484245212b4SAndrew Rist }
1485245212b4SAndrew Rist /* TODO: set error? Excel doesn't have XOR, but
1486245212b4SAndrew Rist * doesn't set an error in this case for AND and
1487245212b4SAndrew Rist * OR. */
1488245212b4SAndrew Rist }
1489245212b4SAndrew Rist }
1490245212b4SAndrew Rist break;
1491245212b4SAndrew Rist case svDoubleRef:
1492245212b4SAndrew Rist case svRefList:
1493245212b4SAndrew Rist {
1494245212b4SAndrew Rist ScRange aRange;
1495245212b4SAndrew Rist PopDoubleRef( aRange, nParamCount, nRefInList);
1496245212b4SAndrew Rist if ( !nGlobalError )
1497245212b4SAndrew Rist {
1498245212b4SAndrew Rist double fVal;
1499245212b4SAndrew Rist sal_uInt16 nErr = 0;
1500245212b4SAndrew Rist ScValueIterator aValIter( pDok, aRange );
1501245212b4SAndrew Rist if ( aValIter.GetFirst( fVal, nErr ) )
1502245212b4SAndrew Rist {
1503245212b4SAndrew Rist bHaveValue = true;
1504245212b4SAndrew Rist do
1505245212b4SAndrew Rist {
1506245212b4SAndrew Rist nRes ^= ( fVal != 0.0 );
1507245212b4SAndrew Rist } while ( (nErr == 0) &&
1508245212b4SAndrew Rist aValIter.GetNext( fVal, nErr ) );
1509245212b4SAndrew Rist }
1510245212b4SAndrew Rist SetError( nErr );
1511245212b4SAndrew Rist }
1512245212b4SAndrew Rist }
1513245212b4SAndrew Rist break;
1514245212b4SAndrew Rist case svMatrix:
1515245212b4SAndrew Rist {
1516245212b4SAndrew Rist bHaveValue = true;
1517245212b4SAndrew Rist ScMatrixRef pMat = GetMatrix();
1518245212b4SAndrew Rist if ( pMat )
1519245212b4SAndrew Rist {
1520245212b4SAndrew Rist bHaveValue = true;
1521245212b4SAndrew Rist double fVal = pMat->Xor();
1522245212b4SAndrew Rist sal_uInt16 nErr = GetDoubleErrorValue( fVal );
1523245212b4SAndrew Rist if ( nErr )
1524245212b4SAndrew Rist {
1525245212b4SAndrew Rist SetError( nErr );
1526245212b4SAndrew Rist nRes = 0;
1527245212b4SAndrew Rist }
1528245212b4SAndrew Rist else
1529245212b4SAndrew Rist nRes ^= (fVal != 0.0);
1530245212b4SAndrew Rist }
1531245212b4SAndrew Rist // else: GetMatrix did set errIllegalParameter
1532245212b4SAndrew Rist }
1533245212b4SAndrew Rist break;
1534245212b4SAndrew Rist default:
1535245212b4SAndrew Rist Pop();
1536245212b4SAndrew Rist SetError( errIllegalParameter);
1537245212b4SAndrew Rist }
1538245212b4SAndrew Rist }
1539245212b4SAndrew Rist else
1540245212b4SAndrew Rist Pop();
1541245212b4SAndrew Rist }
1542245212b4SAndrew Rist if ( bHaveValue )
1543245212b4SAndrew Rist PushInt( nRes );
1544245212b4SAndrew Rist else
1545245212b4SAndrew Rist PushNoValue();
1546245212b4SAndrew Rist }
1547245212b4SAndrew Rist }
1548245212b4SAndrew Rist
1549cdf0e10cSrcweir
ScNeg()1550cdf0e10cSrcweir void ScInterpreter::ScNeg()
1551cdf0e10cSrcweir {
1552cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScNeg" );
1553cdf0e10cSrcweir // Simple negation doesn't change current format type to number, keep
1554cdf0e10cSrcweir // current type.
1555cdf0e10cSrcweir nFuncFmtType = nCurFmtType;
1556cdf0e10cSrcweir switch ( GetStackType() )
1557cdf0e10cSrcweir {
1558cdf0e10cSrcweir case svMatrix :
1559cdf0e10cSrcweir {
1560cdf0e10cSrcweir ScMatrixRef pMat = GetMatrix();
1561cdf0e10cSrcweir if ( !pMat )
1562cdf0e10cSrcweir PushIllegalParameter();
1563cdf0e10cSrcweir else
1564cdf0e10cSrcweir {
1565cdf0e10cSrcweir SCSIZE nC, nR;
1566cdf0e10cSrcweir pMat->GetDimensions( nC, nR );
1567cdf0e10cSrcweir ScMatrixRef pResMat = GetNewMat( nC, nR);
1568cdf0e10cSrcweir if ( !pResMat )
1569cdf0e10cSrcweir PushIllegalArgument();
1570cdf0e10cSrcweir else
1571cdf0e10cSrcweir {
1572cdf0e10cSrcweir SCSIZE nCount = nC * nR;
1573cdf0e10cSrcweir for ( SCSIZE j=0; j<nCount; ++j )
1574cdf0e10cSrcweir {
1575cdf0e10cSrcweir if ( pMat->IsValueOrEmpty(j) )
1576cdf0e10cSrcweir pResMat->PutDouble( -pMat->GetDouble(j), j );
1577cdf0e10cSrcweir else
1578cdf0e10cSrcweir pResMat->PutString(
1579cdf0e10cSrcweir ScGlobal::GetRscString( STR_NO_VALUE ), j );
1580cdf0e10cSrcweir }
1581cdf0e10cSrcweir PushMatrix( pResMat );
1582cdf0e10cSrcweir }
1583cdf0e10cSrcweir }
1584cdf0e10cSrcweir }
1585cdf0e10cSrcweir break;
1586cdf0e10cSrcweir default:
1587cdf0e10cSrcweir PushDouble( -GetDouble() );
1588cdf0e10cSrcweir }
1589cdf0e10cSrcweir }
1590cdf0e10cSrcweir
1591cdf0e10cSrcweir
ScPercentSign()1592cdf0e10cSrcweir void ScInterpreter::ScPercentSign()
1593cdf0e10cSrcweir {
1594cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScPercentSign" );
1595cdf0e10cSrcweir nFuncFmtType = NUMBERFORMAT_PERCENT;
1596cdf0e10cSrcweir const FormulaToken* pSaveCur = pCur;
1597cdf0e10cSrcweir sal_uInt8 nSavePar = cPar;
1598cdf0e10cSrcweir PushInt( 100 );
1599cdf0e10cSrcweir cPar = 2;
1600cdf0e10cSrcweir FormulaByteToken aDivOp( ocDiv, cPar );
1601cdf0e10cSrcweir pCur = &aDivOp;
1602cdf0e10cSrcweir ScDiv();
1603cdf0e10cSrcweir pCur = pSaveCur;
1604cdf0e10cSrcweir cPar = nSavePar;
1605cdf0e10cSrcweir }
1606cdf0e10cSrcweir
1607cdf0e10cSrcweir
ScNot()1608cdf0e10cSrcweir void ScInterpreter::ScNot()
1609cdf0e10cSrcweir {
1610cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScNot" );
1611cdf0e10cSrcweir nFuncFmtType = NUMBERFORMAT_LOGICAL;
1612cdf0e10cSrcweir switch ( GetStackType() )
1613cdf0e10cSrcweir {
1614cdf0e10cSrcweir case svMatrix :
1615cdf0e10cSrcweir {
1616cdf0e10cSrcweir ScMatrixRef pMat = GetMatrix();
1617cdf0e10cSrcweir if ( !pMat )
1618cdf0e10cSrcweir PushIllegalParameter();
1619cdf0e10cSrcweir else
1620cdf0e10cSrcweir {
1621cdf0e10cSrcweir SCSIZE nC, nR;
1622cdf0e10cSrcweir pMat->GetDimensions( nC, nR );
1623cdf0e10cSrcweir ScMatrixRef pResMat = GetNewMat( nC, nR);
1624cdf0e10cSrcweir if ( !pResMat )
1625cdf0e10cSrcweir PushIllegalArgument();
1626cdf0e10cSrcweir else
1627cdf0e10cSrcweir {
1628cdf0e10cSrcweir SCSIZE nCount = nC * nR;
1629cdf0e10cSrcweir for ( SCSIZE j=0; j<nCount; ++j )
1630cdf0e10cSrcweir {
1631cdf0e10cSrcweir if ( pMat->IsValueOrEmpty(j) )
1632cdf0e10cSrcweir pResMat->PutDouble( (pMat->GetDouble(j) == 0.0), j );
1633cdf0e10cSrcweir else
1634cdf0e10cSrcweir pResMat->PutString(
1635cdf0e10cSrcweir ScGlobal::GetRscString( STR_NO_VALUE ), j );
1636cdf0e10cSrcweir }
1637cdf0e10cSrcweir PushMatrix( pResMat );
1638cdf0e10cSrcweir }
1639cdf0e10cSrcweir }
1640cdf0e10cSrcweir }
1641cdf0e10cSrcweir break;
1642cdf0e10cSrcweir default:
1643cdf0e10cSrcweir PushInt( GetDouble() == 0.0 );
1644cdf0e10cSrcweir }
1645cdf0e10cSrcweir }
1646cdf0e10cSrcweir
1647cdf0e10cSrcweir
ScPi()1648cdf0e10cSrcweir void ScInterpreter::ScPi()
1649cdf0e10cSrcweir {
1650cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScPi" );
1651cdf0e10cSrcweir PushDouble(F_PI);
1652cdf0e10cSrcweir }
1653cdf0e10cSrcweir
1654b54ae672SPedro Giffuni #define SCRANDOMQ_SIZE 4194304
1655b54ae672SPedro Giffuni static sal_uInt32 nScRandomQ[SCRANDOMQ_SIZE], nScCarry = 0;
1656b54ae672SPedro Giffuni
1657b54ae672SPedro Giffuni // Multiply with Carry
1658b54ae672SPedro Giffuni sal_uInt32
b32MWC(void)1659b54ae672SPedro Giffuni b32MWC(void)
1660b54ae672SPedro Giffuni {
1661b54ae672SPedro Giffuni sal_uInt32 t, x;
1662b54ae672SPedro Giffuni static int j = (SCRANDOMQ_SIZE - 1);
1663b54ae672SPedro Giffuni
1664b54ae672SPedro Giffuni j = (j + 1) & (SCRANDOMQ_SIZE - 1);
1665b54ae672SPedro Giffuni x = nScRandomQ[j];
1666b54ae672SPedro Giffuni t = (x << 28) + nScCarry;
1667b54ae672SPedro Giffuni nScCarry = (x >> 4) - (t < x);
1668b54ae672SPedro Giffuni return (nScRandomQ[j] = t - x);
1669b54ae672SPedro Giffuni }
1670b54ae672SPedro Giffuni
1671b54ae672SPedro Giffuni // Congruential
1672c9b8e806SPedro Giffuni #define CNG ( ScCNG = 69069 * ScCNG + 13579 )
1673b54ae672SPedro Giffuni // Xorshift
1674c9b8e806SPedro Giffuni #define XS ( ScXS ^= (ScXS << 13), ScXS ^= (ScXS >> 17), ScXS ^= (ScXS << 5) )
1675b54ae672SPedro Giffuni
1676b54ae672SPedro Giffuni #define KISS (b32MWC() + CNG + XS)
1677cdf0e10cSrcweir
ScRandom()1678cdf0e10cSrcweir void ScInterpreter::ScRandom()
1679cdf0e10cSrcweir {
1680b54ae672SPedro Giffuni RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "pfg", "ScInterpreter::ScRandom" );
168105aa205cSPedro Giffuni
1682b54ae672SPedro Giffuni static sal_Bool SqSeeded = sal_False;
1683c9b8e806SPedro Giffuni static sal_uInt32 ScCNG, ScXS = 362436069;
168405aa205cSPedro Giffuni
1685b54ae672SPedro Giffuni // Seeding for the PRNG
1686b54ae672SPedro Giffuni if (SqSeeded == sal_False) {
16875dfc2e73Spfg rtlRandomPool aPool = rtl_random_createPool();
1688c9b8e806SPedro Giffuni rtl_random_getBytes(aPool, &ScCNG, sizeof(ScCNG));
1689b54ae672SPedro Giffuni rtl_random_getBytes(aPool, &nScRandomQ,
1690b54ae672SPedro Giffuni sizeof(nScRandomQ[0]) * SCRANDOMQ_SIZE);
16915dfc2e73Spfg rtl_random_destroyPool(aPool);
1692b54ae672SPedro Giffuni SqSeeded = sal_True;
1693cdf0e10cSrcweir }
1694b54ae672SPedro Giffuni PushDouble(static_cast<double>(KISS) / SAL_MAX_UINT32);
1695b54ae672SPedro Giffuni }
1696cdf0e10cSrcweir
ScTrue()1697cdf0e10cSrcweir void ScInterpreter::ScTrue()
1698cdf0e10cSrcweir {
1699cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScTrue" );
1700cdf0e10cSrcweir nFuncFmtType = NUMBERFORMAT_LOGICAL;
1701cdf0e10cSrcweir PushInt(1);
1702cdf0e10cSrcweir }
1703cdf0e10cSrcweir
1704cdf0e10cSrcweir
ScFalse()1705cdf0e10cSrcweir void ScInterpreter::ScFalse()
1706cdf0e10cSrcweir {
1707cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScFalse" );
1708cdf0e10cSrcweir nFuncFmtType = NUMBERFORMAT_LOGICAL;
1709cdf0e10cSrcweir PushInt(0);
1710cdf0e10cSrcweir }
1711cdf0e10cSrcweir
1712cdf0e10cSrcweir
ScDeg()1713cdf0e10cSrcweir void ScInterpreter::ScDeg()
1714cdf0e10cSrcweir {
1715cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScDeg" );
1716cdf0e10cSrcweir PushDouble((GetDouble() / F_PI) * 180.0);
1717cdf0e10cSrcweir }
1718cdf0e10cSrcweir
1719cdf0e10cSrcweir
ScRad()1720cdf0e10cSrcweir void ScInterpreter::ScRad()
1721cdf0e10cSrcweir {
1722cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScRad" );
1723cdf0e10cSrcweir PushDouble(GetDouble() * (F_PI / 180));
1724cdf0e10cSrcweir }
1725cdf0e10cSrcweir
1726cdf0e10cSrcweir
ScSin()1727cdf0e10cSrcweir void ScInterpreter::ScSin()
1728cdf0e10cSrcweir {
1729cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScSin" );
1730cdf0e10cSrcweir PushDouble(::rtl::math::sin(GetDouble()));
1731cdf0e10cSrcweir }
1732cdf0e10cSrcweir
1733cdf0e10cSrcweir
ScCos()1734cdf0e10cSrcweir void ScInterpreter::ScCos()
1735cdf0e10cSrcweir {
1736cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScCos" );
1737cdf0e10cSrcweir PushDouble(::rtl::math::cos(GetDouble()));
1738cdf0e10cSrcweir }
1739cdf0e10cSrcweir
1740cdf0e10cSrcweir
ScTan()1741cdf0e10cSrcweir void ScInterpreter::ScTan()
1742cdf0e10cSrcweir {
1743cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScTan" );
1744cdf0e10cSrcweir PushDouble(::rtl::math::tan(GetDouble()));
1745cdf0e10cSrcweir }
1746cdf0e10cSrcweir
1747cdf0e10cSrcweir
ScCot()1748cdf0e10cSrcweir void ScInterpreter::ScCot()
1749cdf0e10cSrcweir {
1750cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScCot" );
1751cdf0e10cSrcweir PushDouble(1.0 / ::rtl::math::tan(GetDouble()));
1752cdf0e10cSrcweir }
1753cdf0e10cSrcweir
1754cdf0e10cSrcweir
ScArcSin()1755cdf0e10cSrcweir void ScInterpreter::ScArcSin()
1756cdf0e10cSrcweir {
1757cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScArcSin" );
1758cdf0e10cSrcweir PushDouble(asin(GetDouble()));
1759cdf0e10cSrcweir }
1760cdf0e10cSrcweir
1761cdf0e10cSrcweir
ScArcCos()1762cdf0e10cSrcweir void ScInterpreter::ScArcCos()
1763cdf0e10cSrcweir {
1764cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScArcCos" );
1765cdf0e10cSrcweir PushDouble(acos(GetDouble()));
1766cdf0e10cSrcweir }
1767cdf0e10cSrcweir
1768cdf0e10cSrcweir
ScArcTan()1769cdf0e10cSrcweir void ScInterpreter::ScArcTan()
1770cdf0e10cSrcweir {
1771cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScArcTan" );
1772cdf0e10cSrcweir PushDouble(atan(GetDouble()));
1773cdf0e10cSrcweir }
1774cdf0e10cSrcweir
1775cdf0e10cSrcweir
ScArcCot()1776cdf0e10cSrcweir void ScInterpreter::ScArcCot()
1777cdf0e10cSrcweir {
1778cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScArcCot" );
1779cdf0e10cSrcweir PushDouble((F_PI2) - atan(GetDouble()));
1780cdf0e10cSrcweir }
1781cdf0e10cSrcweir
1782cdf0e10cSrcweir
ScSinHyp()1783cdf0e10cSrcweir void ScInterpreter::ScSinHyp()
1784cdf0e10cSrcweir {
1785cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScSinHyp" );
1786cdf0e10cSrcweir PushDouble(sinh(GetDouble()));
1787cdf0e10cSrcweir }
1788cdf0e10cSrcweir
1789cdf0e10cSrcweir
ScCosHyp()1790cdf0e10cSrcweir void ScInterpreter::ScCosHyp()
1791cdf0e10cSrcweir {
1792cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScCosHyp" );
1793cdf0e10cSrcweir PushDouble(cosh(GetDouble()));
1794cdf0e10cSrcweir }
1795cdf0e10cSrcweir
1796cdf0e10cSrcweir
ScTanHyp()1797cdf0e10cSrcweir void ScInterpreter::ScTanHyp()
1798cdf0e10cSrcweir {
1799cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScTanHyp" );
1800cdf0e10cSrcweir PushDouble(tanh(GetDouble()));
1801cdf0e10cSrcweir }
1802cdf0e10cSrcweir
1803cdf0e10cSrcweir
ScCotHyp()1804cdf0e10cSrcweir void ScInterpreter::ScCotHyp()
1805cdf0e10cSrcweir {
1806cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScCotHyp" );
1807cdf0e10cSrcweir PushDouble(1.0 / tanh(GetDouble()));
1808cdf0e10cSrcweir }
1809cdf0e10cSrcweir
1810cdf0e10cSrcweir
ScArcSinHyp()1811cdf0e10cSrcweir void ScInterpreter::ScArcSinHyp()
1812cdf0e10cSrcweir {
1813cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScArcSinHyp" );
181476ea2deeSPedro Giffuni PushDouble( ::boost::math::asinh( GetDouble()));
1815cdf0e10cSrcweir }
1816cdf0e10cSrcweir
ScArcCosHyp()1817cdf0e10cSrcweir void ScInterpreter::ScArcCosHyp()
1818cdf0e10cSrcweir {
1819cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScArcCosHyp" );
1820cdf0e10cSrcweir double fVal = GetDouble();
1821cdf0e10cSrcweir if (fVal < 1.0)
1822cdf0e10cSrcweir PushIllegalArgument();
1823cdf0e10cSrcweir else
182476ea2deeSPedro Giffuni PushDouble( ::boost::math::acosh( fVal));
1825cdf0e10cSrcweir }
1826cdf0e10cSrcweir
ScArcTanHyp()1827cdf0e10cSrcweir void ScInterpreter::ScArcTanHyp()
1828cdf0e10cSrcweir {
1829cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScArcTanHyp" );
1830cdf0e10cSrcweir double fVal = GetDouble();
1831cdf0e10cSrcweir if (fabs(fVal) >= 1.0)
1832cdf0e10cSrcweir PushIllegalArgument();
1833cdf0e10cSrcweir else
183476ea2deeSPedro Giffuni PushDouble( ::boost::math::atanh( fVal));
1835cdf0e10cSrcweir }
1836cdf0e10cSrcweir
1837cdf0e10cSrcweir
ScArcCotHyp()1838cdf0e10cSrcweir void ScInterpreter::ScArcCotHyp()
1839cdf0e10cSrcweir {
1840cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScArcCotHyp" );
1841cdf0e10cSrcweir double nVal = GetDouble();
1842cdf0e10cSrcweir if (fabs(nVal) <= 1.0)
1843cdf0e10cSrcweir PushIllegalArgument();
1844cdf0e10cSrcweir else
1845cdf0e10cSrcweir PushDouble(0.5 * log((nVal + 1.0) / (nVal - 1.0)));
1846cdf0e10cSrcweir }
1847cdf0e10cSrcweir
ScCosecant()1848cdf0e10cSrcweir void ScInterpreter::ScCosecant()
1849cdf0e10cSrcweir {
1850cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "regina", "ScInterpreter::ScCosecant" );
1851cdf0e10cSrcweir PushDouble(1.0 / ::rtl::math::sin(GetDouble()));
1852cdf0e10cSrcweir }
1853cdf0e10cSrcweir
ScSecant()1854cdf0e10cSrcweir void ScInterpreter::ScSecant()
1855cdf0e10cSrcweir {
1856cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "regina", "ScInterpreter::ScSecant" );
1857cdf0e10cSrcweir PushDouble(1.0 / ::rtl::math::cos(GetDouble()));
1858cdf0e10cSrcweir }
1859cdf0e10cSrcweir
ScCosecantHyp()1860cdf0e10cSrcweir void ScInterpreter::ScCosecantHyp()
1861cdf0e10cSrcweir {
1862cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "regina", "ScInterpreter::ScCosecantHyp" );
1863cdf0e10cSrcweir PushDouble(1.0 / sinh(GetDouble()));
1864cdf0e10cSrcweir }
1865cdf0e10cSrcweir
ScSecantHyp()1866cdf0e10cSrcweir void ScInterpreter::ScSecantHyp()
1867cdf0e10cSrcweir {
1868cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "regina", "ScInterpreter::ScSecantHyp" );
1869cdf0e10cSrcweir PushDouble(1.0 / cosh(GetDouble()));
1870cdf0e10cSrcweir }
1871cdf0e10cSrcweir
1872cdf0e10cSrcweir
ScExp()1873cdf0e10cSrcweir void ScInterpreter::ScExp()
1874cdf0e10cSrcweir {
1875cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScExp" );
1876cdf0e10cSrcweir PushDouble(exp(GetDouble()));
1877cdf0e10cSrcweir }
1878cdf0e10cSrcweir
1879cdf0e10cSrcweir
ScSqrt()1880cdf0e10cSrcweir void ScInterpreter::ScSqrt()
1881cdf0e10cSrcweir {
1882cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScSqrt" );
1883cdf0e10cSrcweir double fVal = GetDouble();
1884cdf0e10cSrcweir if (fVal >= 0.0)
1885cdf0e10cSrcweir PushDouble(sqrt(fVal));
1886cdf0e10cSrcweir else
1887cdf0e10cSrcweir PushIllegalArgument();
1888cdf0e10cSrcweir }
1889cdf0e10cSrcweir
1890cdf0e10cSrcweir
ScIsEmpty()1891cdf0e10cSrcweir void ScInterpreter::ScIsEmpty()
1892cdf0e10cSrcweir {
1893cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScIsEmpty" );
1894cdf0e10cSrcweir short nRes = 0;
1895cdf0e10cSrcweir nFuncFmtType = NUMBERFORMAT_LOGICAL;
1896cdf0e10cSrcweir switch ( GetRawStackType() )
1897cdf0e10cSrcweir {
1898cdf0e10cSrcweir case svEmptyCell:
1899cdf0e10cSrcweir {
1900cdf0e10cSrcweir FormulaTokenRef p = PopToken();
1901cdf0e10cSrcweir if (!static_cast<const ScEmptyCellToken*>(p.get())->IsInherited())
1902cdf0e10cSrcweir nRes = 1;
1903cdf0e10cSrcweir }
1904cdf0e10cSrcweir break;
1905cdf0e10cSrcweir case svDoubleRef :
1906cdf0e10cSrcweir case svSingleRef :
1907cdf0e10cSrcweir {
1908cdf0e10cSrcweir ScAddress aAdr;
1909cdf0e10cSrcweir if ( !PopDoubleRefOrSingleRef( aAdr ) )
1910cdf0e10cSrcweir break;
1911cdf0e10cSrcweir // NOTE: this could test also on inherited emptiness, but then the
1912cdf0e10cSrcweir // cell tested wouldn't be empty. Must correspond with
1913cdf0e10cSrcweir // ScCountEmptyCells().
1914cdf0e10cSrcweir // if (HasCellEmptyData( GetCell( aAdr)))
1915cdf0e10cSrcweir CellType eCellType = GetCellType( GetCell( aAdr ) );
1916cdf0e10cSrcweir if((eCellType == CELLTYPE_NONE) || (eCellType == CELLTYPE_NOTE))
1917cdf0e10cSrcweir nRes = 1;
1918cdf0e10cSrcweir }
1919cdf0e10cSrcweir break;
1920cdf0e10cSrcweir case svMatrix:
1921cdf0e10cSrcweir {
1922cdf0e10cSrcweir ScMatrixRef pMat = PopMatrix();
1923cdf0e10cSrcweir if ( !pMat )
1924cdf0e10cSrcweir ; // nothing
1925cdf0e10cSrcweir else if ( !pJumpMatrix )
1926cdf0e10cSrcweir nRes = pMat->IsEmpty( 0 );
1927cdf0e10cSrcweir else
1928cdf0e10cSrcweir {
1929cdf0e10cSrcweir SCSIZE nCols, nRows, nC, nR;
1930cdf0e10cSrcweir pMat->GetDimensions( nCols, nRows);
1931cdf0e10cSrcweir pJumpMatrix->GetPos( nC, nR);
1932cdf0e10cSrcweir if ( nC < nCols && nR < nRows )
1933cdf0e10cSrcweir nRes = pMat->IsEmpty( nC, nR);
1934cdf0e10cSrcweir // else: sal_False, not empty (which is what Xcl does)
1935cdf0e10cSrcweir }
1936cdf0e10cSrcweir }
1937cdf0e10cSrcweir break;
1938cdf0e10cSrcweir default:
1939cdf0e10cSrcweir Pop();
1940cdf0e10cSrcweir }
1941cdf0e10cSrcweir nGlobalError = 0;
1942cdf0e10cSrcweir PushInt( nRes );
1943cdf0e10cSrcweir }
1944cdf0e10cSrcweir
1945cdf0e10cSrcweir
IsString()1946cdf0e10cSrcweir short ScInterpreter::IsString()
1947cdf0e10cSrcweir {
1948cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::IsString" );
1949cdf0e10cSrcweir nFuncFmtType = NUMBERFORMAT_LOGICAL;
1950cdf0e10cSrcweir short nRes = 0;
1951cdf0e10cSrcweir switch ( GetRawStackType() )
1952cdf0e10cSrcweir {
1953cdf0e10cSrcweir case svString:
1954cdf0e10cSrcweir Pop();
1955cdf0e10cSrcweir nRes = 1;
1956cdf0e10cSrcweir break;
1957cdf0e10cSrcweir case svDoubleRef :
1958cdf0e10cSrcweir case svSingleRef :
1959cdf0e10cSrcweir {
1960cdf0e10cSrcweir ScAddress aAdr;
1961cdf0e10cSrcweir if ( !PopDoubleRefOrSingleRef( aAdr ) )
1962cdf0e10cSrcweir break;
1963cdf0e10cSrcweir ScBaseCell* pCell = GetCell( aAdr );
1964cdf0e10cSrcweir if (GetCellErrCode( pCell ) == 0)
1965cdf0e10cSrcweir {
1966cdf0e10cSrcweir switch ( GetCellType( pCell ) )
1967cdf0e10cSrcweir {
1968cdf0e10cSrcweir case CELLTYPE_STRING :
1969cdf0e10cSrcweir case CELLTYPE_EDIT :
1970cdf0e10cSrcweir nRes = 1;
1971cdf0e10cSrcweir break;
1972cdf0e10cSrcweir case CELLTYPE_FORMULA :
1973cdf0e10cSrcweir nRes = !((ScFormulaCell*)pCell)->IsValue() &&
1974cdf0e10cSrcweir !((ScFormulaCell*)pCell)->IsEmpty();
1975cdf0e10cSrcweir break;
1976cdf0e10cSrcweir default:
1977cdf0e10cSrcweir ; // nothing
1978cdf0e10cSrcweir }
1979cdf0e10cSrcweir }
1980cdf0e10cSrcweir }
1981cdf0e10cSrcweir break;
1982cdf0e10cSrcweir case svMatrix:
1983cdf0e10cSrcweir {
1984cdf0e10cSrcweir ScMatrixRef pMat = PopMatrix();
1985cdf0e10cSrcweir if ( !pMat )
1986cdf0e10cSrcweir ; // nothing
1987cdf0e10cSrcweir else if ( !pJumpMatrix )
1988cdf0e10cSrcweir nRes = pMat->IsString(0) && !pMat->IsEmpty(0);
1989cdf0e10cSrcweir else
1990cdf0e10cSrcweir {
1991cdf0e10cSrcweir SCSIZE nCols, nRows, nC, nR;
1992cdf0e10cSrcweir pMat->GetDimensions( nCols, nRows);
1993cdf0e10cSrcweir pJumpMatrix->GetPos( nC, nR);
1994cdf0e10cSrcweir if ( nC < nCols && nR < nRows )
1995cdf0e10cSrcweir nRes = pMat->IsString( nC, nR) && !pMat->IsEmpty( nC, nR);
1996cdf0e10cSrcweir }
1997cdf0e10cSrcweir }
1998cdf0e10cSrcweir break;
1999cdf0e10cSrcweir default:
2000cdf0e10cSrcweir Pop();
2001cdf0e10cSrcweir }
2002cdf0e10cSrcweir nGlobalError = 0;
2003cdf0e10cSrcweir return nRes;
2004cdf0e10cSrcweir }
2005cdf0e10cSrcweir
2006cdf0e10cSrcweir
ScIsString()2007cdf0e10cSrcweir void ScInterpreter::ScIsString()
2008cdf0e10cSrcweir {
2009cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScIsString" );
2010cdf0e10cSrcweir PushInt( IsString() );
2011cdf0e10cSrcweir }
2012cdf0e10cSrcweir
2013cdf0e10cSrcweir
ScIsNonString()2014cdf0e10cSrcweir void ScInterpreter::ScIsNonString()
2015cdf0e10cSrcweir {
2016cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScIsNonString" );
2017cdf0e10cSrcweir PushInt( !IsString() );
2018cdf0e10cSrcweir }
2019cdf0e10cSrcweir
2020cdf0e10cSrcweir
ScIsLogical()2021cdf0e10cSrcweir void ScInterpreter::ScIsLogical()
2022cdf0e10cSrcweir {
2023cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScIsLogical" );
2024cdf0e10cSrcweir short nRes = 0;
2025cdf0e10cSrcweir switch ( GetStackType() )
2026cdf0e10cSrcweir {
2027cdf0e10cSrcweir case svDoubleRef :
2028cdf0e10cSrcweir case svSingleRef :
2029cdf0e10cSrcweir {
2030cdf0e10cSrcweir ScAddress aAdr;
2031cdf0e10cSrcweir if ( !PopDoubleRefOrSingleRef( aAdr ) )
2032cdf0e10cSrcweir break;
2033cdf0e10cSrcweir ScBaseCell* pCell = GetCell( aAdr );
2034cdf0e10cSrcweir if (GetCellErrCode( pCell ) == 0)
2035cdf0e10cSrcweir {
2036cdf0e10cSrcweir if (HasCellValueData(pCell))
2037cdf0e10cSrcweir {
2038cdf0e10cSrcweir sal_uLong nFormat = GetCellNumberFormat( aAdr, pCell );
2039cdf0e10cSrcweir nRes = ( pFormatter->GetType(nFormat)
2040cdf0e10cSrcweir == NUMBERFORMAT_LOGICAL);
2041cdf0e10cSrcweir }
2042cdf0e10cSrcweir }
2043cdf0e10cSrcweir }
2044cdf0e10cSrcweir break;
2045cdf0e10cSrcweir case svMatrix:
2046cdf0e10cSrcweir // TODO: we don't have type information for arrays except
2047cdf0e10cSrcweir // numerical/string.
2048cdf0e10cSrcweir // Fall thru
2049cdf0e10cSrcweir default:
2050cdf0e10cSrcweir PopError();
2051cdf0e10cSrcweir if ( !nGlobalError )
2052cdf0e10cSrcweir nRes = ( nCurFmtType == NUMBERFORMAT_LOGICAL );
2053cdf0e10cSrcweir }
2054cdf0e10cSrcweir nCurFmtType = nFuncFmtType = NUMBERFORMAT_LOGICAL;
2055cdf0e10cSrcweir nGlobalError = 0;
2056cdf0e10cSrcweir PushInt( nRes );
2057cdf0e10cSrcweir }
2058cdf0e10cSrcweir
2059cdf0e10cSrcweir
ScType()2060cdf0e10cSrcweir void ScInterpreter::ScType()
2061cdf0e10cSrcweir {
2062cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScType" );
2063cdf0e10cSrcweir short nType = 0;
2064cdf0e10cSrcweir switch ( GetStackType() )
2065cdf0e10cSrcweir {
2066cdf0e10cSrcweir case svDoubleRef :
2067cdf0e10cSrcweir case svSingleRef :
2068cdf0e10cSrcweir {
2069cdf0e10cSrcweir ScAddress aAdr;
2070cdf0e10cSrcweir if ( !PopDoubleRefOrSingleRef( aAdr ) )
2071cdf0e10cSrcweir break;
2072cdf0e10cSrcweir ScBaseCell* pCell = GetCell( aAdr );
2073cdf0e10cSrcweir if (GetCellErrCode( pCell ) == 0)
2074cdf0e10cSrcweir {
2075cdf0e10cSrcweir switch ( GetCellType( pCell ) )
2076cdf0e10cSrcweir {
2077cdf0e10cSrcweir // NOTE: this is Xcl nonsense!
2078cdf0e10cSrcweir case CELLTYPE_NOTE :
2079cdf0e10cSrcweir nType = 1; // empty cell is value (0)
2080cdf0e10cSrcweir break;
2081cdf0e10cSrcweir case CELLTYPE_STRING :
2082cdf0e10cSrcweir case CELLTYPE_EDIT :
2083cdf0e10cSrcweir nType = 2;
2084cdf0e10cSrcweir break;
2085cdf0e10cSrcweir case CELLTYPE_VALUE :
2086cdf0e10cSrcweir {
2087cdf0e10cSrcweir sal_uLong nFormat = GetCellNumberFormat( aAdr, pCell );
2088cdf0e10cSrcweir if (pFormatter->GetType(nFormat)
2089cdf0e10cSrcweir == NUMBERFORMAT_LOGICAL)
2090cdf0e10cSrcweir nType = 4;
2091cdf0e10cSrcweir else
2092cdf0e10cSrcweir nType = 1;
2093cdf0e10cSrcweir }
2094cdf0e10cSrcweir break;
2095cdf0e10cSrcweir case CELLTYPE_FORMULA :
2096cdf0e10cSrcweir nType = 8;
2097cdf0e10cSrcweir break;
2098cdf0e10cSrcweir default:
2099cdf0e10cSrcweir PushIllegalArgument();
2100cdf0e10cSrcweir }
2101cdf0e10cSrcweir }
2102cdf0e10cSrcweir else
2103cdf0e10cSrcweir nType = 16;
2104cdf0e10cSrcweir }
2105cdf0e10cSrcweir break;
2106cdf0e10cSrcweir case svString:
2107cdf0e10cSrcweir PopError();
2108cdf0e10cSrcweir if ( nGlobalError )
2109cdf0e10cSrcweir {
2110cdf0e10cSrcweir nType = 16;
2111cdf0e10cSrcweir nGlobalError = 0;
2112cdf0e10cSrcweir }
2113cdf0e10cSrcweir else
2114cdf0e10cSrcweir nType = 2;
2115cdf0e10cSrcweir break;
2116cdf0e10cSrcweir case svMatrix:
2117cdf0e10cSrcweir PopMatrix();
2118cdf0e10cSrcweir if ( nGlobalError )
2119cdf0e10cSrcweir {
2120cdf0e10cSrcweir nType = 16;
2121cdf0e10cSrcweir nGlobalError = 0;
2122cdf0e10cSrcweir }
2123cdf0e10cSrcweir else
2124cdf0e10cSrcweir nType = 64;
2125cdf0e10cSrcweir // we could return the type of one element if in JumpMatrix or
2126cdf0e10cSrcweir // ForceArray mode, but Xcl doesn't ...
2127cdf0e10cSrcweir break;
2128cdf0e10cSrcweir default:
2129cdf0e10cSrcweir PopError();
2130cdf0e10cSrcweir if ( nGlobalError )
2131cdf0e10cSrcweir {
2132cdf0e10cSrcweir nType = 16;
2133cdf0e10cSrcweir nGlobalError = 0;
2134cdf0e10cSrcweir }
2135cdf0e10cSrcweir else
2136cdf0e10cSrcweir nType = 1;
2137cdf0e10cSrcweir }
2138cdf0e10cSrcweir PushInt( nType );
2139cdf0e10cSrcweir }
2140cdf0e10cSrcweir
2141cdf0e10cSrcweir
lcl_FormatHasNegColor(const SvNumberformat * pFormat)2142cdf0e10cSrcweir inline sal_Bool lcl_FormatHasNegColor( const SvNumberformat* pFormat )
2143cdf0e10cSrcweir {
2144cdf0e10cSrcweir return pFormat && pFormat->GetColor( 1 );
2145cdf0e10cSrcweir }
2146cdf0e10cSrcweir
2147cdf0e10cSrcweir
lcl_FormatHasOpenPar(const SvNumberformat * pFormat)2148cdf0e10cSrcweir inline sal_Bool lcl_FormatHasOpenPar( const SvNumberformat* pFormat )
2149cdf0e10cSrcweir {
2150cdf0e10cSrcweir return pFormat && (pFormat->GetFormatstring().Search( '(' ) != STRING_NOTFOUND);
2151cdf0e10cSrcweir }
2152cdf0e10cSrcweir
2153cdf0e10cSrcweir
ScCell()2154cdf0e10cSrcweir void ScInterpreter::ScCell()
2155cdf0e10cSrcweir { // ATTRIBUTE ; [REF]
2156cdf0e10cSrcweir sal_uInt8 nParamCount = GetByte();
2157cdf0e10cSrcweir if( MustHaveParamCount( nParamCount, 1, 2 ) )
2158cdf0e10cSrcweir {
2159cdf0e10cSrcweir ScAddress aCellPos( aPos );
2160cdf0e10cSrcweir sal_Bool bError = sal_False;
2161cdf0e10cSrcweir if( nParamCount == 2 )
2162cdf0e10cSrcweir bError = !PopDoubleRefOrSingleRef( aCellPos );
2163cdf0e10cSrcweir String aInfoType( GetString() );
2164cdf0e10cSrcweir if( bError || nGlobalError )
2165cdf0e10cSrcweir PushIllegalParameter();
2166cdf0e10cSrcweir else
2167cdf0e10cSrcweir {
2168cdf0e10cSrcweir String aFuncResult;
2169cdf0e10cSrcweir ScBaseCell* pCell = GetCell( aCellPos );
2170cdf0e10cSrcweir
2171cdf0e10cSrcweir ScCellKeywordTranslator::transKeyword(aInfoType, ScGlobal::GetLocale(), ocCell);
2172cdf0e10cSrcweir
2173cdf0e10cSrcweir // *** ADDRESS INFO ***
2174cdf0e10cSrcweir if( aInfoType.EqualsAscii( "COL" ) )
2175cdf0e10cSrcweir { // column number (1-based)
2176cdf0e10cSrcweir PushInt( aCellPos.Col() + 1 );
2177cdf0e10cSrcweir }
2178cdf0e10cSrcweir else if( aInfoType.EqualsAscii( "ROW" ) )
2179cdf0e10cSrcweir { // row number (1-based)
2180cdf0e10cSrcweir PushInt( aCellPos.Row() + 1 );
2181cdf0e10cSrcweir }
2182cdf0e10cSrcweir else if( aInfoType.EqualsAscii( "SHEET" ) )
2183cdf0e10cSrcweir { // table number (1-based)
2184cdf0e10cSrcweir PushInt( aCellPos.Tab() + 1 );
2185cdf0e10cSrcweir }
2186cdf0e10cSrcweir else if( aInfoType.EqualsAscii( "ADDRESS" ) )
2187cdf0e10cSrcweir { // address formatted as [['FILENAME'#]$TABLE.]$COL$ROW
2188cdf0e10cSrcweir sal_uInt16 nFlags = (aCellPos.Tab() == aPos.Tab()) ? (SCA_ABS) : (SCA_ABS_3D);
2189cdf0e10cSrcweir aCellPos.Format( aFuncResult, nFlags, pDok, pDok->GetAddressConvention() );
2190cdf0e10cSrcweir PushString( aFuncResult );
2191cdf0e10cSrcweir }
2192cdf0e10cSrcweir else if( aInfoType.EqualsAscii( "FILENAME" ) )
2193cdf0e10cSrcweir { // file name and table name: 'FILENAME'#$TABLE
2194cdf0e10cSrcweir SCTAB nTab = aCellPos.Tab();
2195cdf0e10cSrcweir if( nTab < pDok->GetTableCount() )
2196cdf0e10cSrcweir {
2197cdf0e10cSrcweir if( pDok->GetLinkMode( nTab ) == SC_LINK_VALUE )
2198cdf0e10cSrcweir pDok->GetName( nTab, aFuncResult );
2199cdf0e10cSrcweir else
2200cdf0e10cSrcweir {
2201cdf0e10cSrcweir SfxObjectShell* pShell = pDok->GetDocumentShell();
2202cdf0e10cSrcweir if( pShell && pShell->GetMedium() )
2203cdf0e10cSrcweir {
2204cdf0e10cSrcweir aFuncResult = (sal_Unicode) '\'';
2205cdf0e10cSrcweir const INetURLObject& rURLObj = pShell->GetMedium()->GetURLObject();
2206cdf0e10cSrcweir aFuncResult += String( rURLObj.GetMainURL( INetURLObject::DECODE_UNAMBIGUOUS ) );
2207cdf0e10cSrcweir aFuncResult.AppendAscii( "'#$" );
2208cdf0e10cSrcweir String aTabName;
2209cdf0e10cSrcweir pDok->GetName( nTab, aTabName );
2210cdf0e10cSrcweir aFuncResult += aTabName;
2211cdf0e10cSrcweir }
2212cdf0e10cSrcweir }
2213cdf0e10cSrcweir }
2214cdf0e10cSrcweir PushString( aFuncResult );
2215cdf0e10cSrcweir }
2216cdf0e10cSrcweir else if( aInfoType.EqualsAscii( "COORD" ) )
2217cdf0e10cSrcweir { // address, lotus 1-2-3 formatted: $TABLE:$COL$ROW
2218cdf0e10cSrcweir // Yes, passing tab as col is intentional!
2219cdf0e10cSrcweir ScAddress( static_cast<SCCOL>(aCellPos.Tab()), 0, 0 ).Format(
2220cdf0e10cSrcweir aFuncResult, (SCA_COL_ABSOLUTE|SCA_VALID_COL), NULL, pDok->GetAddressConvention() );
2221cdf0e10cSrcweir aFuncResult += ':';
2222cdf0e10cSrcweir String aCellStr;
2223cdf0e10cSrcweir aCellPos.Format( aCellStr, (SCA_COL_ABSOLUTE|SCA_VALID_COL|SCA_ROW_ABSOLUTE|SCA_VALID_ROW),
2224cdf0e10cSrcweir NULL, pDok->GetAddressConvention() );
2225cdf0e10cSrcweir aFuncResult += aCellStr;
2226cdf0e10cSrcweir PushString( aFuncResult );
2227cdf0e10cSrcweir }
2228cdf0e10cSrcweir
2229cdf0e10cSrcweir // *** CELL PROPERTIES ***
2230cdf0e10cSrcweir else if( aInfoType.EqualsAscii( "CONTENTS" ) )
2231cdf0e10cSrcweir { // contents of the cell, no formatting
2232cdf0e10cSrcweir if( pCell && pCell->HasStringData() )
2233cdf0e10cSrcweir {
2234cdf0e10cSrcweir GetCellString( aFuncResult, pCell );
2235cdf0e10cSrcweir PushString( aFuncResult );
2236cdf0e10cSrcweir }
2237cdf0e10cSrcweir else
2238cdf0e10cSrcweir PushDouble( GetCellValue( aCellPos, pCell ) );
2239cdf0e10cSrcweir }
2240cdf0e10cSrcweir else if( aInfoType.EqualsAscii( "TYPE" ) )
2241cdf0e10cSrcweir { // b = blank; l = string (label); v = otherwise (value)
2242cdf0e10cSrcweir if( HasCellStringData( pCell ) )
2243cdf0e10cSrcweir aFuncResult = 'l';
2244cdf0e10cSrcweir else
2245cdf0e10cSrcweir aFuncResult = HasCellValueData( pCell ) ? 'v' : 'b';
2246cdf0e10cSrcweir PushString( aFuncResult );
2247cdf0e10cSrcweir }
2248cdf0e10cSrcweir else if( aInfoType.EqualsAscii( "WIDTH" ) )
2249cdf0e10cSrcweir { // column width (rounded off as count of zero characters in standard font and size)
2250cdf0e10cSrcweir Printer* pPrinter = pDok->GetPrinter();
2251cdf0e10cSrcweir MapMode aOldMode( pPrinter->GetMapMode() );
2252cdf0e10cSrcweir Font aOldFont( pPrinter->GetFont() );
2253cdf0e10cSrcweir Font aDefFont;
2254cdf0e10cSrcweir
2255cdf0e10cSrcweir pPrinter->SetMapMode( MAP_TWIP );
2256cdf0e10cSrcweir // font color doesn't matter here
2257cdf0e10cSrcweir pDok->GetDefPattern()->GetFont( aDefFont, SC_AUTOCOL_BLACK, pPrinter );
2258cdf0e10cSrcweir pPrinter->SetFont( aDefFont );
2259cdf0e10cSrcweir long nZeroWidth = pPrinter->GetTextWidth( String( '0' ) );
2260cdf0e10cSrcweir pPrinter->SetFont( aOldFont );
2261cdf0e10cSrcweir pPrinter->SetMapMode( aOldMode );
2262cdf0e10cSrcweir int nZeroCount = (int)(pDok->GetColWidth( aCellPos.Col(), aCellPos.Tab() ) / nZeroWidth);
2263cdf0e10cSrcweir PushInt( nZeroCount );
2264cdf0e10cSrcweir }
2265cdf0e10cSrcweir else if( aInfoType.EqualsAscii( "PREFIX" ) )
2266cdf0e10cSrcweir { // ' = left; " = right; ^ = centered
2267cdf0e10cSrcweir if( HasCellStringData( pCell ) )
2268cdf0e10cSrcweir {
2269cdf0e10cSrcweir const SvxHorJustifyItem* pJustAttr = (const SvxHorJustifyItem*)
2270cdf0e10cSrcweir pDok->GetAttr( aCellPos.Col(), aCellPos.Row(), aCellPos.Tab(), ATTR_HOR_JUSTIFY );
2271cdf0e10cSrcweir switch( pJustAttr->GetValue() )
2272cdf0e10cSrcweir {
2273cdf0e10cSrcweir case SVX_HOR_JUSTIFY_STANDARD:
2274cdf0e10cSrcweir case SVX_HOR_JUSTIFY_LEFT:
2275cdf0e10cSrcweir case SVX_HOR_JUSTIFY_BLOCK: aFuncResult = '\''; break;
2276cdf0e10cSrcweir case SVX_HOR_JUSTIFY_CENTER: aFuncResult = '^'; break;
2277cdf0e10cSrcweir case SVX_HOR_JUSTIFY_RIGHT: aFuncResult = '"'; break;
2278cdf0e10cSrcweir case SVX_HOR_JUSTIFY_REPEAT: aFuncResult = '\\'; break;
2279cdf0e10cSrcweir }
2280cdf0e10cSrcweir }
2281cdf0e10cSrcweir PushString( aFuncResult );
2282cdf0e10cSrcweir }
2283cdf0e10cSrcweir else if( aInfoType.EqualsAscii( "PROTECT" ) )
2284cdf0e10cSrcweir { // 1 = cell locked
2285cdf0e10cSrcweir const ScProtectionAttr* pProtAttr = (const ScProtectionAttr*)
2286cdf0e10cSrcweir pDok->GetAttr( aCellPos.Col(), aCellPos.Row(), aCellPos.Tab(), ATTR_PROTECTION );
2287cdf0e10cSrcweir PushInt( pProtAttr->GetProtection() ? 1 : 0 );
2288cdf0e10cSrcweir }
2289cdf0e10cSrcweir
2290cdf0e10cSrcweir // *** FORMATTING ***
2291cdf0e10cSrcweir else if( aInfoType.EqualsAscii( "FORMAT" ) )
2292cdf0e10cSrcweir { // specific format code for standard formats
2293cdf0e10cSrcweir sal_uLong nFormat = pDok->GetNumberFormat( aCellPos );
2294cdf0e10cSrcweir sal_Bool bAppendPrec = sal_True;
2295cdf0e10cSrcweir sal_uInt16 nPrec, nLeading;
2296cdf0e10cSrcweir sal_Bool bThousand, bIsRed;
2297cdf0e10cSrcweir pFormatter->GetFormatSpecialInfo( nFormat, bThousand, bIsRed, nPrec, nLeading );
2298cdf0e10cSrcweir
2299cdf0e10cSrcweir switch( pFormatter->GetType( nFormat ) )
2300cdf0e10cSrcweir {
2301cdf0e10cSrcweir case NUMBERFORMAT_NUMBER: aFuncResult = (bThousand ? ',' : 'F'); break;
2302cdf0e10cSrcweir case NUMBERFORMAT_CURRENCY: aFuncResult = 'C'; break;
2303cdf0e10cSrcweir case NUMBERFORMAT_SCIENTIFIC: aFuncResult = 'S'; break;
2304cdf0e10cSrcweir case NUMBERFORMAT_PERCENT: aFuncResult = 'P'; break;
2305cdf0e10cSrcweir default:
2306cdf0e10cSrcweir {
2307cdf0e10cSrcweir bAppendPrec = sal_False;
2308cdf0e10cSrcweir switch( pFormatter->GetIndexTableOffset( nFormat ) )
2309cdf0e10cSrcweir {
2310cdf0e10cSrcweir case NF_DATE_SYSTEM_SHORT:
2311cdf0e10cSrcweir case NF_DATE_SYS_DMMMYY:
2312cdf0e10cSrcweir case NF_DATE_SYS_DDMMYY:
2313cdf0e10cSrcweir case NF_DATE_SYS_DDMMYYYY:
2314cdf0e10cSrcweir case NF_DATE_SYS_DMMMYYYY:
2315cdf0e10cSrcweir case NF_DATE_DIN_DMMMYYYY:
2316cdf0e10cSrcweir case NF_DATE_SYS_DMMMMYYYY:
2317cdf0e10cSrcweir case NF_DATE_DIN_DMMMMYYYY: aFuncResult.AssignAscii( RTL_CONSTASCII_STRINGPARAM( "D1" ) ); break;
2318cdf0e10cSrcweir case NF_DATE_SYS_DDMMM: aFuncResult.AssignAscii( RTL_CONSTASCII_STRINGPARAM( "D2" ) ); break;
2319cdf0e10cSrcweir case NF_DATE_SYS_MMYY: aFuncResult.AssignAscii( RTL_CONSTASCII_STRINGPARAM( "D3" ) ); break;
2320cdf0e10cSrcweir case NF_DATETIME_SYSTEM_SHORT_HHMM:
2321cdf0e10cSrcweir case NF_DATETIME_SYS_DDMMYYYY_HHMMSS:
2322cdf0e10cSrcweir aFuncResult.AssignAscii( RTL_CONSTASCII_STRINGPARAM( "D4" ) ); break;
2323cdf0e10cSrcweir case NF_DATE_DIN_MMDD: aFuncResult.AssignAscii( RTL_CONSTASCII_STRINGPARAM( "D5" ) ); break;
2324cdf0e10cSrcweir case NF_TIME_HHMMSSAMPM: aFuncResult.AssignAscii( RTL_CONSTASCII_STRINGPARAM( "D6" ) ); break;
2325cdf0e10cSrcweir case NF_TIME_HHMMAMPM: aFuncResult.AssignAscii( RTL_CONSTASCII_STRINGPARAM( "D7" ) ); break;
2326cdf0e10cSrcweir case NF_TIME_HHMMSS: aFuncResult.AssignAscii( RTL_CONSTASCII_STRINGPARAM( "D8" ) ); break;
2327cdf0e10cSrcweir case NF_TIME_HHMM: aFuncResult.AssignAscii( RTL_CONSTASCII_STRINGPARAM( "D9" ) ); break;
2328cdf0e10cSrcweir default: aFuncResult = 'G';
2329cdf0e10cSrcweir }
2330cdf0e10cSrcweir }
2331cdf0e10cSrcweir }
2332cdf0e10cSrcweir if( bAppendPrec )
2333cdf0e10cSrcweir aFuncResult += String::CreateFromInt32( nPrec );
2334cdf0e10cSrcweir const SvNumberformat* pFormat = pFormatter->GetEntry( nFormat );
2335cdf0e10cSrcweir if( lcl_FormatHasNegColor( pFormat ) )
2336cdf0e10cSrcweir aFuncResult += '-';
2337cdf0e10cSrcweir if( lcl_FormatHasOpenPar( pFormat ) )
2338cdf0e10cSrcweir aFuncResult.AppendAscii( RTL_CONSTASCII_STRINGPARAM( "()" ) );
2339cdf0e10cSrcweir PushString( aFuncResult );
2340cdf0e10cSrcweir }
2341cdf0e10cSrcweir else if( aInfoType.EqualsAscii( "COLOR" ) )
2342cdf0e10cSrcweir { // 1 = negative values are colored, otherwise 0
2343cdf0e10cSrcweir const SvNumberformat* pFormat = pFormatter->GetEntry( pDok->GetNumberFormat( aCellPos ) );
2344cdf0e10cSrcweir PushInt( lcl_FormatHasNegColor( pFormat ) ? 1 : 0 );
2345cdf0e10cSrcweir }
2346cdf0e10cSrcweir else if( aInfoType.EqualsAscii( "PARENTHESES" ) )
2347cdf0e10cSrcweir { // 1 = format string contains a '(' character, otherwise 0
2348cdf0e10cSrcweir const SvNumberformat* pFormat = pFormatter->GetEntry( pDok->GetNumberFormat( aCellPos ) );
2349cdf0e10cSrcweir PushInt( lcl_FormatHasOpenPar( pFormat ) ? 1 : 0 );
2350cdf0e10cSrcweir }
2351cdf0e10cSrcweir else
2352cdf0e10cSrcweir PushIllegalArgument();
2353cdf0e10cSrcweir }
2354cdf0e10cSrcweir }
2355cdf0e10cSrcweir }
2356cdf0e10cSrcweir
2357cdf0e10cSrcweir
ScIsRef()2358cdf0e10cSrcweir void ScInterpreter::ScIsRef()
2359cdf0e10cSrcweir {
2360cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScCell" );
2361cdf0e10cSrcweir nFuncFmtType = NUMBERFORMAT_LOGICAL;
2362cdf0e10cSrcweir short nRes = 0;
2363cdf0e10cSrcweir switch ( GetStackType() )
2364cdf0e10cSrcweir {
2365cdf0e10cSrcweir case svSingleRef :
2366cdf0e10cSrcweir {
2367cdf0e10cSrcweir ScAddress aAdr;
2368cdf0e10cSrcweir PopSingleRef( aAdr );
2369cdf0e10cSrcweir if ( !nGlobalError )
2370cdf0e10cSrcweir nRes = 1;
2371cdf0e10cSrcweir }
2372cdf0e10cSrcweir break;
2373cdf0e10cSrcweir case svDoubleRef :
2374cdf0e10cSrcweir {
2375cdf0e10cSrcweir ScRange aRange;
2376cdf0e10cSrcweir PopDoubleRef( aRange );
2377cdf0e10cSrcweir if ( !nGlobalError )
2378cdf0e10cSrcweir nRes = 1;
2379cdf0e10cSrcweir }
2380cdf0e10cSrcweir break;
2381cdf0e10cSrcweir case svRefList :
2382cdf0e10cSrcweir {
2383cdf0e10cSrcweir FormulaTokenRef x = PopToken();
2384cdf0e10cSrcweir if ( !nGlobalError )
2385cdf0e10cSrcweir nRes = !static_cast<ScToken*>(x.get())->GetRefList()->empty();
2386cdf0e10cSrcweir }
2387cdf0e10cSrcweir break;
2388cdf0e10cSrcweir default:
2389cdf0e10cSrcweir Pop();
2390cdf0e10cSrcweir }
2391cdf0e10cSrcweir nGlobalError = 0;
2392cdf0e10cSrcweir PushInt( nRes );
2393cdf0e10cSrcweir }
2394cdf0e10cSrcweir
2395cdf0e10cSrcweir
ScIsValue()2396cdf0e10cSrcweir void ScInterpreter::ScIsValue()
2397cdf0e10cSrcweir {
2398cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScIsValue" );
2399cdf0e10cSrcweir nFuncFmtType = NUMBERFORMAT_LOGICAL;
2400cdf0e10cSrcweir short nRes = 0;
2401cdf0e10cSrcweir switch ( GetRawStackType() )
2402cdf0e10cSrcweir {
2403cdf0e10cSrcweir case svDouble:
2404cdf0e10cSrcweir Pop();
2405cdf0e10cSrcweir nRes = 1;
2406cdf0e10cSrcweir break;
2407cdf0e10cSrcweir case svDoubleRef :
2408cdf0e10cSrcweir case svSingleRef :
2409cdf0e10cSrcweir {
2410cdf0e10cSrcweir ScAddress aAdr;
2411cdf0e10cSrcweir if ( !PopDoubleRefOrSingleRef( aAdr ) )
2412cdf0e10cSrcweir break;
2413cdf0e10cSrcweir ScBaseCell* pCell = GetCell( aAdr );
2414cdf0e10cSrcweir if (GetCellErrCode( pCell ) == 0)
2415cdf0e10cSrcweir {
2416cdf0e10cSrcweir switch ( GetCellType( pCell ) )
2417cdf0e10cSrcweir {
2418cdf0e10cSrcweir case CELLTYPE_VALUE :
2419cdf0e10cSrcweir nRes = 1;
2420cdf0e10cSrcweir break;
2421cdf0e10cSrcweir case CELLTYPE_FORMULA :
2422cdf0e10cSrcweir nRes = ((ScFormulaCell*)pCell)->IsValue() &&
2423cdf0e10cSrcweir !((ScFormulaCell*)pCell)->IsEmpty();
2424cdf0e10cSrcweir break;
2425cdf0e10cSrcweir default:
2426cdf0e10cSrcweir ; // nothing
2427cdf0e10cSrcweir }
2428cdf0e10cSrcweir }
2429cdf0e10cSrcweir }
2430cdf0e10cSrcweir break;
2431cdf0e10cSrcweir case svMatrix:
2432cdf0e10cSrcweir {
2433cdf0e10cSrcweir ScMatrixRef pMat = PopMatrix();
2434cdf0e10cSrcweir if ( !pMat )
2435cdf0e10cSrcweir ; // nothing
2436cdf0e10cSrcweir else if ( !pJumpMatrix )
2437cdf0e10cSrcweir {
2438cdf0e10cSrcweir if (pMat->GetErrorIfNotString( 0 ) == 0)
2439cdf0e10cSrcweir nRes = pMat->IsValue( 0 );
2440cdf0e10cSrcweir }
2441cdf0e10cSrcweir else
2442cdf0e10cSrcweir {
2443cdf0e10cSrcweir SCSIZE nCols, nRows, nC, nR;
2444cdf0e10cSrcweir pMat->GetDimensions( nCols, nRows);
2445cdf0e10cSrcweir pJumpMatrix->GetPos( nC, nR);
2446cdf0e10cSrcweir if ( nC < nCols && nR < nRows )
2447cdf0e10cSrcweir if (pMat->GetErrorIfNotString( nC, nR) == 0)
2448cdf0e10cSrcweir nRes = pMat->IsValue( nC, nR);
2449cdf0e10cSrcweir }
2450cdf0e10cSrcweir }
2451cdf0e10cSrcweir break;
2452cdf0e10cSrcweir default:
2453cdf0e10cSrcweir Pop();
2454cdf0e10cSrcweir }
2455cdf0e10cSrcweir nGlobalError = 0;
2456cdf0e10cSrcweir PushInt( nRes );
2457cdf0e10cSrcweir }
2458cdf0e10cSrcweir
2459cdf0e10cSrcweir
ScIsFormula()2460cdf0e10cSrcweir void ScInterpreter::ScIsFormula()
2461cdf0e10cSrcweir {
2462cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScIsFormula" );
2463cdf0e10cSrcweir nFuncFmtType = NUMBERFORMAT_LOGICAL;
2464cdf0e10cSrcweir short nRes = 0;
2465cdf0e10cSrcweir switch ( GetStackType() )
2466cdf0e10cSrcweir {
2467cdf0e10cSrcweir case svDoubleRef :
2468cdf0e10cSrcweir case svSingleRef :
2469cdf0e10cSrcweir {
2470cdf0e10cSrcweir ScAddress aAdr;
2471cdf0e10cSrcweir if ( !PopDoubleRefOrSingleRef( aAdr ) )
2472cdf0e10cSrcweir break;
2473cdf0e10cSrcweir nRes = (GetCellType( GetCell( aAdr ) ) == CELLTYPE_FORMULA);
2474cdf0e10cSrcweir }
2475cdf0e10cSrcweir break;
2476cdf0e10cSrcweir default:
2477cdf0e10cSrcweir Pop();
2478cdf0e10cSrcweir }
2479cdf0e10cSrcweir nGlobalError = 0;
2480cdf0e10cSrcweir PushInt( nRes );
2481cdf0e10cSrcweir }
2482cdf0e10cSrcweir
2483cdf0e10cSrcweir
ScFormula()2484cdf0e10cSrcweir void ScInterpreter::ScFormula()
2485cdf0e10cSrcweir {
2486cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScFormula" );
2487cdf0e10cSrcweir String aFormula;
2488cdf0e10cSrcweir switch ( GetStackType() )
2489cdf0e10cSrcweir {
2490cdf0e10cSrcweir case svDoubleRef :
2491cdf0e10cSrcweir case svSingleRef :
2492cdf0e10cSrcweir {
2493cdf0e10cSrcweir ScAddress aAdr;
2494cdf0e10cSrcweir if ( !PopDoubleRefOrSingleRef( aAdr ) )
2495cdf0e10cSrcweir break;
2496cdf0e10cSrcweir ScBaseCell* pCell = GetCell( aAdr );
2497cdf0e10cSrcweir switch ( GetCellType( pCell ) )
2498cdf0e10cSrcweir {
2499cdf0e10cSrcweir case CELLTYPE_FORMULA :
2500cdf0e10cSrcweir ((ScFormulaCell*)pCell)->GetFormula( aFormula );
2501cdf0e10cSrcweir break;
2502cdf0e10cSrcweir default:
2503cdf0e10cSrcweir SetError( NOTAVAILABLE );
2504cdf0e10cSrcweir }
2505cdf0e10cSrcweir }
2506cdf0e10cSrcweir break;
2507cdf0e10cSrcweir default:
2508cdf0e10cSrcweir Pop();
2509cdf0e10cSrcweir SetError( NOTAVAILABLE );
2510cdf0e10cSrcweir }
2511cdf0e10cSrcweir PushString( aFormula );
2512cdf0e10cSrcweir }
2513cdf0e10cSrcweir
2514cdf0e10cSrcweir
2515cdf0e10cSrcweir
ScIsNV()2516cdf0e10cSrcweir void ScInterpreter::ScIsNV()
2517cdf0e10cSrcweir {
2518cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScIsNV" );
2519cdf0e10cSrcweir nFuncFmtType = NUMBERFORMAT_LOGICAL;
2520cdf0e10cSrcweir short nRes = 0;
2521cdf0e10cSrcweir switch ( GetStackType() )
2522cdf0e10cSrcweir {
2523cdf0e10cSrcweir case svDoubleRef :
2524cdf0e10cSrcweir case svSingleRef :
2525cdf0e10cSrcweir {
2526cdf0e10cSrcweir ScAddress aAdr;
2527cdf0e10cSrcweir PopDoubleRefOrSingleRef( aAdr );
2528cdf0e10cSrcweir if ( nGlobalError == NOTAVAILABLE )
2529cdf0e10cSrcweir nRes = 1;
2530cdf0e10cSrcweir else
2531cdf0e10cSrcweir {
2532cdf0e10cSrcweir ScBaseCell* pCell = GetCell( aAdr );
2533cdf0e10cSrcweir sal_uInt16 nErr = GetCellErrCode( pCell );
2534cdf0e10cSrcweir nRes = (nErr == NOTAVAILABLE);
2535cdf0e10cSrcweir }
2536cdf0e10cSrcweir }
2537cdf0e10cSrcweir break;
2538cdf0e10cSrcweir case svMatrix:
2539cdf0e10cSrcweir {
2540cdf0e10cSrcweir ScMatrixRef pMat = PopMatrix();
2541cdf0e10cSrcweir if ( !pMat )
2542cdf0e10cSrcweir ; // nothing
2543cdf0e10cSrcweir else if ( !pJumpMatrix )
2544cdf0e10cSrcweir nRes = (pMat->GetErrorIfNotString( 0 ) == NOTAVAILABLE);
2545cdf0e10cSrcweir else
2546cdf0e10cSrcweir {
2547cdf0e10cSrcweir SCSIZE nCols, nRows, nC, nR;
2548cdf0e10cSrcweir pMat->GetDimensions( nCols, nRows);
2549cdf0e10cSrcweir pJumpMatrix->GetPos( nC, nR);
2550cdf0e10cSrcweir if ( nC < nCols && nR < nRows )
2551cdf0e10cSrcweir nRes = (pMat->GetErrorIfNotString( nC, nR) == NOTAVAILABLE);
2552cdf0e10cSrcweir }
2553cdf0e10cSrcweir }
2554cdf0e10cSrcweir break;
2555cdf0e10cSrcweir default:
2556cdf0e10cSrcweir PopError();
2557cdf0e10cSrcweir if ( nGlobalError == NOTAVAILABLE )
2558cdf0e10cSrcweir nRes = 1;
2559cdf0e10cSrcweir }
2560cdf0e10cSrcweir nGlobalError = 0;
2561cdf0e10cSrcweir PushInt( nRes );
2562cdf0e10cSrcweir }
2563cdf0e10cSrcweir
2564cdf0e10cSrcweir
ScIsErr()2565cdf0e10cSrcweir void ScInterpreter::ScIsErr()
2566cdf0e10cSrcweir {
2567cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScIsErr" );
2568cdf0e10cSrcweir nFuncFmtType = NUMBERFORMAT_LOGICAL;
2569cdf0e10cSrcweir short nRes = 0;
2570cdf0e10cSrcweir switch ( GetStackType() )
2571cdf0e10cSrcweir {
2572cdf0e10cSrcweir case svDoubleRef :
2573cdf0e10cSrcweir case svSingleRef :
2574cdf0e10cSrcweir {
2575cdf0e10cSrcweir ScAddress aAdr;
2576cdf0e10cSrcweir PopDoubleRefOrSingleRef( aAdr );
2577cdf0e10cSrcweir if ( nGlobalError && nGlobalError != NOTAVAILABLE )
2578cdf0e10cSrcweir nRes = 1;
2579cdf0e10cSrcweir else
2580cdf0e10cSrcweir {
2581cdf0e10cSrcweir ScBaseCell* pCell = GetCell( aAdr );
2582cdf0e10cSrcweir sal_uInt16 nErr = GetCellErrCode( pCell );
2583cdf0e10cSrcweir nRes = (nErr && nErr != NOTAVAILABLE);
2584cdf0e10cSrcweir }
2585cdf0e10cSrcweir }
2586cdf0e10cSrcweir break;
2587cdf0e10cSrcweir case svMatrix:
2588cdf0e10cSrcweir {
2589cdf0e10cSrcweir ScMatrixRef pMat = PopMatrix();
2590cdf0e10cSrcweir if ( nGlobalError || !pMat )
2591cdf0e10cSrcweir nRes = ((nGlobalError && nGlobalError != NOTAVAILABLE) || !pMat);
2592cdf0e10cSrcweir else if ( !pJumpMatrix )
2593cdf0e10cSrcweir {
2594cdf0e10cSrcweir sal_uInt16 nErr = pMat->GetErrorIfNotString( 0 );
2595cdf0e10cSrcweir nRes = (nErr && nErr != NOTAVAILABLE);
2596cdf0e10cSrcweir }
2597cdf0e10cSrcweir else
2598cdf0e10cSrcweir {
2599cdf0e10cSrcweir SCSIZE nCols, nRows, nC, nR;
2600cdf0e10cSrcweir pMat->GetDimensions( nCols, nRows);
2601cdf0e10cSrcweir pJumpMatrix->GetPos( nC, nR);
2602cdf0e10cSrcweir if ( nC < nCols && nR < nRows )
2603cdf0e10cSrcweir {
2604cdf0e10cSrcweir sal_uInt16 nErr = pMat->GetErrorIfNotString( nC, nR);
2605cdf0e10cSrcweir nRes = (nErr && nErr != NOTAVAILABLE);
2606cdf0e10cSrcweir }
2607cdf0e10cSrcweir }
2608cdf0e10cSrcweir }
2609cdf0e10cSrcweir break;
2610cdf0e10cSrcweir default:
2611cdf0e10cSrcweir PopError();
2612cdf0e10cSrcweir if ( nGlobalError && nGlobalError != NOTAVAILABLE )
2613cdf0e10cSrcweir nRes = 1;
2614cdf0e10cSrcweir }
2615cdf0e10cSrcweir nGlobalError = 0;
2616cdf0e10cSrcweir PushInt( nRes );
2617cdf0e10cSrcweir }
2618cdf0e10cSrcweir
2619cdf0e10cSrcweir
ScIsError()2620cdf0e10cSrcweir void ScInterpreter::ScIsError()
2621cdf0e10cSrcweir {
2622cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScIsError" );
2623cdf0e10cSrcweir nFuncFmtType = NUMBERFORMAT_LOGICAL;
2624cdf0e10cSrcweir short nRes = 0;
2625cdf0e10cSrcweir switch ( GetStackType() )
2626cdf0e10cSrcweir {
2627cdf0e10cSrcweir case svDoubleRef :
2628cdf0e10cSrcweir case svSingleRef :
2629cdf0e10cSrcweir {
2630cdf0e10cSrcweir ScAddress aAdr;
2631cdf0e10cSrcweir if ( !PopDoubleRefOrSingleRef( aAdr ) )
2632cdf0e10cSrcweir {
2633cdf0e10cSrcweir nRes = 1;
2634cdf0e10cSrcweir break;
2635cdf0e10cSrcweir }
2636cdf0e10cSrcweir if ( nGlobalError )
2637cdf0e10cSrcweir nRes = 1;
2638cdf0e10cSrcweir else
2639cdf0e10cSrcweir {
2640cdf0e10cSrcweir ScBaseCell* pCell = GetCell( aAdr );
2641cdf0e10cSrcweir nRes = (GetCellErrCode( pCell ) != 0);
2642cdf0e10cSrcweir }
2643cdf0e10cSrcweir }
2644cdf0e10cSrcweir break;
2645cdf0e10cSrcweir case svMatrix:
2646cdf0e10cSrcweir {
2647cdf0e10cSrcweir ScMatrixRef pMat = PopMatrix();
2648cdf0e10cSrcweir if ( nGlobalError || !pMat )
2649cdf0e10cSrcweir nRes = 1;
2650cdf0e10cSrcweir else if ( !pJumpMatrix )
2651cdf0e10cSrcweir nRes = (pMat->GetErrorIfNotString( 0 ) != 0);
2652cdf0e10cSrcweir else
2653cdf0e10cSrcweir {
2654cdf0e10cSrcweir SCSIZE nCols, nRows, nC, nR;
2655cdf0e10cSrcweir pMat->GetDimensions( nCols, nRows);
2656cdf0e10cSrcweir pJumpMatrix->GetPos( nC, nR);
2657cdf0e10cSrcweir if ( nC < nCols && nR < nRows )
2658cdf0e10cSrcweir nRes = (pMat->GetErrorIfNotString( nC, nR) != 0);
2659cdf0e10cSrcweir }
2660cdf0e10cSrcweir }
2661cdf0e10cSrcweir break;
2662cdf0e10cSrcweir default:
2663cdf0e10cSrcweir PopError();
2664cdf0e10cSrcweir if ( nGlobalError )
2665cdf0e10cSrcweir nRes = 1;
2666cdf0e10cSrcweir }
2667cdf0e10cSrcweir nGlobalError = 0;
2668cdf0e10cSrcweir PushInt( nRes );
2669cdf0e10cSrcweir }
2670cdf0e10cSrcweir
2671cdf0e10cSrcweir
IsEven()2672cdf0e10cSrcweir short ScInterpreter::IsEven()
2673cdf0e10cSrcweir {
2674cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::IsEven" );
2675cdf0e10cSrcweir nFuncFmtType = NUMBERFORMAT_LOGICAL;
2676cdf0e10cSrcweir short nRes = 0;
2677cdf0e10cSrcweir double fVal = 0.0;
2678cdf0e10cSrcweir switch ( GetStackType() )
2679cdf0e10cSrcweir {
2680cdf0e10cSrcweir case svDoubleRef :
2681cdf0e10cSrcweir case svSingleRef :
2682cdf0e10cSrcweir {
2683cdf0e10cSrcweir ScAddress aAdr;
2684cdf0e10cSrcweir if ( !PopDoubleRefOrSingleRef( aAdr ) )
2685cdf0e10cSrcweir break;
2686cdf0e10cSrcweir ScBaseCell* pCell = GetCell( aAdr );
2687cdf0e10cSrcweir sal_uInt16 nErr = GetCellErrCode( pCell );
2688cdf0e10cSrcweir if (nErr != 0)
2689cdf0e10cSrcweir SetError(nErr);
2690cdf0e10cSrcweir else
2691cdf0e10cSrcweir {
2692cdf0e10cSrcweir switch ( GetCellType( pCell ) )
2693cdf0e10cSrcweir {
2694cdf0e10cSrcweir case CELLTYPE_VALUE :
2695cdf0e10cSrcweir fVal = GetCellValue( aAdr, pCell );
2696cdf0e10cSrcweir nRes = 1;
2697cdf0e10cSrcweir break;
2698cdf0e10cSrcweir case CELLTYPE_FORMULA :
2699cdf0e10cSrcweir if( ((ScFormulaCell*)pCell)->IsValue() )
2700cdf0e10cSrcweir {
2701cdf0e10cSrcweir fVal = GetCellValue( aAdr, pCell );
2702cdf0e10cSrcweir nRes = 1;
2703cdf0e10cSrcweir }
2704cdf0e10cSrcweir break;
2705cdf0e10cSrcweir default:
2706cdf0e10cSrcweir ; // nothing
2707cdf0e10cSrcweir }
2708cdf0e10cSrcweir }
2709cdf0e10cSrcweir }
2710cdf0e10cSrcweir break;
2711cdf0e10cSrcweir case svDouble:
2712cdf0e10cSrcweir {
2713cdf0e10cSrcweir fVal = PopDouble();
2714cdf0e10cSrcweir nRes = 1;
2715cdf0e10cSrcweir }
2716cdf0e10cSrcweir break;
2717cdf0e10cSrcweir case svMatrix:
2718cdf0e10cSrcweir {
2719cdf0e10cSrcweir ScMatrixRef pMat = PopMatrix();
2720cdf0e10cSrcweir if ( !pMat )
2721cdf0e10cSrcweir ; // nothing
2722cdf0e10cSrcweir else if ( !pJumpMatrix )
2723cdf0e10cSrcweir {
2724cdf0e10cSrcweir nRes = pMat->IsValue( 0 );
2725cdf0e10cSrcweir if ( nRes )
2726cdf0e10cSrcweir fVal = pMat->GetDouble( 0 );
2727cdf0e10cSrcweir }
2728cdf0e10cSrcweir else
2729cdf0e10cSrcweir {
2730cdf0e10cSrcweir SCSIZE nCols, nRows, nC, nR;
2731cdf0e10cSrcweir pMat->GetDimensions( nCols, nRows);
2732cdf0e10cSrcweir pJumpMatrix->GetPos( nC, nR);
2733cdf0e10cSrcweir if ( nC < nCols && nR < nRows )
2734cdf0e10cSrcweir {
2735cdf0e10cSrcweir nRes = pMat->IsValue( nC, nR);
2736cdf0e10cSrcweir if ( nRes )
2737cdf0e10cSrcweir fVal = pMat->GetDouble( nC, nR);
2738cdf0e10cSrcweir }
2739cdf0e10cSrcweir else
2740cdf0e10cSrcweir SetError( errNoValue);
2741cdf0e10cSrcweir }
2742cdf0e10cSrcweir }
2743cdf0e10cSrcweir break;
2744cdf0e10cSrcweir default:
2745cdf0e10cSrcweir ; // nothing
2746cdf0e10cSrcweir }
2747cdf0e10cSrcweir if ( !nRes )
2748cdf0e10cSrcweir SetError( errIllegalParameter);
2749cdf0e10cSrcweir else
2750cdf0e10cSrcweir nRes = ( fmod( ::rtl::math::approxFloor( fabs( fVal ) ), 2.0 ) < 0.5 );
2751cdf0e10cSrcweir return nRes;
2752cdf0e10cSrcweir }
2753cdf0e10cSrcweir
2754cdf0e10cSrcweir
ScIsEven()2755cdf0e10cSrcweir void ScInterpreter::ScIsEven()
2756cdf0e10cSrcweir {
2757cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScIsEven" );
2758cdf0e10cSrcweir PushInt( IsEven() );
2759cdf0e10cSrcweir }
2760cdf0e10cSrcweir
2761cdf0e10cSrcweir
ScIsOdd()2762cdf0e10cSrcweir void ScInterpreter::ScIsOdd()
2763cdf0e10cSrcweir {
2764cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScIsOdd" );
2765cdf0e10cSrcweir PushInt( !IsEven() );
2766cdf0e10cSrcweir }
2767cdf0e10cSrcweir
2768cdf0e10cSrcweir
ScN()2769cdf0e10cSrcweir void ScInterpreter::ScN()
2770cdf0e10cSrcweir {
2771cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScN" );
2772cdf0e10cSrcweir sal_uInt16 nErr = nGlobalError;
2773cdf0e10cSrcweir nGlobalError = 0;
2774cdf0e10cSrcweir // Temporarily override the ConvertStringToValue() error for
2775cdf0e10cSrcweir // GetCellValue() / GetCellValueOrZero()
2776cdf0e10cSrcweir sal_uInt16 nSErr = mnStringNoValueError;
2777cdf0e10cSrcweir mnStringNoValueError = errCellNoValue;
2778cdf0e10cSrcweir double fVal = GetDouble();
2779cdf0e10cSrcweir mnStringNoValueError = nSErr;
2780cdf0e10cSrcweir if ( nGlobalError == NOTAVAILABLE || nGlobalError == errCellNoValue )
2781cdf0e10cSrcweir nGlobalError = 0; // N(#NA) and N("text") are ok
2782cdf0e10cSrcweir if ( !nGlobalError && nErr != NOTAVAILABLE )
2783cdf0e10cSrcweir nGlobalError = nErr;
2784cdf0e10cSrcweir PushDouble( fVal );
2785cdf0e10cSrcweir }
2786cdf0e10cSrcweir
2787cdf0e10cSrcweir
ScTrim()2788cdf0e10cSrcweir void ScInterpreter::ScTrim()
2789cdf0e10cSrcweir { // trimmt nicht nur sondern schnibbelt auch doppelte raus!
2790cdf0e10cSrcweir String aVal( GetString() );
2791cdf0e10cSrcweir aVal.EraseLeadingChars();
2792cdf0e10cSrcweir aVal.EraseTrailingChars();
2793cdf0e10cSrcweir String aStr;
2794cdf0e10cSrcweir register const sal_Unicode* p = aVal.GetBuffer();
2795cdf0e10cSrcweir register const sal_Unicode* const pEnd = p + aVal.Len();
2796cdf0e10cSrcweir while ( p < pEnd )
2797cdf0e10cSrcweir {
2798cdf0e10cSrcweir if ( *p != ' ' || p[-1] != ' ' ) // erster kann kein ' ' sein, -1 ist also ok
2799cdf0e10cSrcweir aStr += *p;
2800cdf0e10cSrcweir p++;
2801cdf0e10cSrcweir }
2802cdf0e10cSrcweir PushString( aStr );
2803cdf0e10cSrcweir }
2804cdf0e10cSrcweir
2805cdf0e10cSrcweir
ScUpper()2806cdf0e10cSrcweir void ScInterpreter::ScUpper()
2807cdf0e10cSrcweir {
2808cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScTrim" );
2809cdf0e10cSrcweir String aString = GetString();
2810cdf0e10cSrcweir ScGlobal::pCharClass->toUpper(aString);
2811cdf0e10cSrcweir PushString(aString);
2812cdf0e10cSrcweir }
2813cdf0e10cSrcweir
2814cdf0e10cSrcweir
ScPropper()2815cdf0e10cSrcweir void ScInterpreter::ScPropper()
2816cdf0e10cSrcweir {
2817cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScPropper" );
2818*5cd1c826Smseidel // TODO: what to do with I18N-CJK ?!?
2819cdf0e10cSrcweir String aStr( GetString() );
2820cdf0e10cSrcweir const xub_StrLen nLen = aStr.Len();
2821cdf0e10cSrcweir // #i82487# don't try to write to empty string's BufferAccess
2822cdf0e10cSrcweir // (would crash now that the empty string is const)
2823cdf0e10cSrcweir if ( nLen > 0 )
2824cdf0e10cSrcweir {
2825cdf0e10cSrcweir String aUpr( ScGlobal::pCharClass->upper( aStr ) );
2826cdf0e10cSrcweir String aLwr( ScGlobal::pCharClass->lower( aStr ) );
2827cdf0e10cSrcweir register sal_Unicode* pStr = aStr.GetBufferAccess();
2828cdf0e10cSrcweir const sal_Unicode* pUpr = aUpr.GetBuffer();
2829cdf0e10cSrcweir const sal_Unicode* pLwr = aLwr.GetBuffer();
2830cdf0e10cSrcweir *pStr = *pUpr;
2831cdf0e10cSrcweir String aTmpStr( 'x' );
2832cdf0e10cSrcweir xub_StrLen nPos = 1;
2833cdf0e10cSrcweir while( nPos < nLen )
2834cdf0e10cSrcweir {
2835cdf0e10cSrcweir aTmpStr.SetChar( 0, pStr[nPos-1] );
2836cdf0e10cSrcweir if ( !ScGlobal::pCharClass->isLetter( aTmpStr, 0 ) )
2837cdf0e10cSrcweir pStr[nPos] = pUpr[nPos];
2838cdf0e10cSrcweir else
2839cdf0e10cSrcweir pStr[nPos] = pLwr[nPos];
2840cdf0e10cSrcweir nPos++;
2841cdf0e10cSrcweir }
2842cdf0e10cSrcweir aStr.ReleaseBufferAccess( nLen );
2843cdf0e10cSrcweir }
2844cdf0e10cSrcweir PushString( aStr );
2845cdf0e10cSrcweir }
2846cdf0e10cSrcweir
2847cdf0e10cSrcweir
ScLower()2848cdf0e10cSrcweir void ScInterpreter::ScLower()
2849cdf0e10cSrcweir {
2850cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScLower" );
2851cdf0e10cSrcweir String aString( GetString() );
2852cdf0e10cSrcweir ScGlobal::pCharClass->toLower(aString);
2853cdf0e10cSrcweir PushString(aString);
2854cdf0e10cSrcweir }
2855cdf0e10cSrcweir
2856cdf0e10cSrcweir
ScLen()2857cdf0e10cSrcweir void ScInterpreter::ScLen()
2858cdf0e10cSrcweir {
2859cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScLen" );
2860cdf0e10cSrcweir String aStr( GetString() );
2861cdf0e10cSrcweir PushDouble( aStr.Len() );
2862cdf0e10cSrcweir }
2863cdf0e10cSrcweir
2864cdf0e10cSrcweir
ScT()2865cdf0e10cSrcweir void ScInterpreter::ScT()
2866cdf0e10cSrcweir {
2867cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScT" );
2868cdf0e10cSrcweir switch ( GetStackType() )
2869cdf0e10cSrcweir {
2870cdf0e10cSrcweir case svDoubleRef :
2871cdf0e10cSrcweir case svSingleRef :
2872cdf0e10cSrcweir {
2873cdf0e10cSrcweir ScAddress aAdr;
2874cdf0e10cSrcweir if ( !PopDoubleRefOrSingleRef( aAdr ) )
2875cdf0e10cSrcweir {
2876cdf0e10cSrcweir PushInt(0);
2877cdf0e10cSrcweir return ;
2878cdf0e10cSrcweir }
2879cdf0e10cSrcweir sal_Bool bValue = sal_False;
2880cdf0e10cSrcweir ScBaseCell* pCell = GetCell( aAdr );
2881cdf0e10cSrcweir if ( GetCellErrCode( pCell ) == 0 )
2882cdf0e10cSrcweir {
2883cdf0e10cSrcweir switch ( GetCellType( pCell ) )
2884cdf0e10cSrcweir {
2885cdf0e10cSrcweir case CELLTYPE_VALUE :
2886cdf0e10cSrcweir bValue = sal_True;
2887cdf0e10cSrcweir break;
2888cdf0e10cSrcweir case CELLTYPE_FORMULA :
2889cdf0e10cSrcweir bValue = ((ScFormulaCell*)pCell)->IsValue();
2890cdf0e10cSrcweir break;
2891cdf0e10cSrcweir default:
2892cdf0e10cSrcweir ; // nothing
2893cdf0e10cSrcweir }
2894cdf0e10cSrcweir }
2895cdf0e10cSrcweir if ( bValue )
2896cdf0e10cSrcweir PushString( EMPTY_STRING );
2897cdf0e10cSrcweir else
2898cdf0e10cSrcweir {
2899cdf0e10cSrcweir // wie GetString()
2900cdf0e10cSrcweir GetCellString( aTempStr, pCell );
2901cdf0e10cSrcweir PushString( aTempStr );
2902cdf0e10cSrcweir }
2903cdf0e10cSrcweir }
2904cdf0e10cSrcweir break;
2905cdf0e10cSrcweir case svDouble :
2906cdf0e10cSrcweir {
2907cdf0e10cSrcweir PopError();
2908cdf0e10cSrcweir PushString( EMPTY_STRING );
2909cdf0e10cSrcweir }
2910cdf0e10cSrcweir break;
2911cdf0e10cSrcweir case svString :
2912cdf0e10cSrcweir ; // leave on stack
2913cdf0e10cSrcweir break;
2914cdf0e10cSrcweir default :
2915cdf0e10cSrcweir PushError( errUnknownOpCode);
2916cdf0e10cSrcweir }
2917cdf0e10cSrcweir }
2918cdf0e10cSrcweir
2919cdf0e10cSrcweir
ScValue()2920cdf0e10cSrcweir void ScInterpreter::ScValue()
2921cdf0e10cSrcweir {
2922cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScValue" );
2923cdf0e10cSrcweir String aInputString;
2924cdf0e10cSrcweir double fVal;
2925cdf0e10cSrcweir
2926cdf0e10cSrcweir switch ( GetRawStackType() )
2927cdf0e10cSrcweir {
2928cdf0e10cSrcweir case svMissing:
2929cdf0e10cSrcweir case svEmptyCell:
2930cdf0e10cSrcweir Pop();
2931cdf0e10cSrcweir PushInt(0);
2932cdf0e10cSrcweir return;
2933cdf0e10cSrcweir case svDouble:
2934cdf0e10cSrcweir return; // leave on stack
2935cdf0e10cSrcweir //break;
2936cdf0e10cSrcweir
2937cdf0e10cSrcweir case svSingleRef:
2938cdf0e10cSrcweir case svDoubleRef:
2939cdf0e10cSrcweir {
2940cdf0e10cSrcweir ScAddress aAdr;
2941cdf0e10cSrcweir if ( !PopDoubleRefOrSingleRef( aAdr ) )
2942cdf0e10cSrcweir {
2943cdf0e10cSrcweir PushInt(0);
2944cdf0e10cSrcweir return;
2945cdf0e10cSrcweir }
2946cdf0e10cSrcweir ScBaseCell* pCell = GetCell( aAdr );
2947cdf0e10cSrcweir if ( pCell && pCell->HasStringData() )
2948cdf0e10cSrcweir GetCellString( aInputString, pCell );
2949cdf0e10cSrcweir else if ( pCell && pCell->HasValueData() )
2950cdf0e10cSrcweir {
2951cdf0e10cSrcweir PushDouble( GetCellValue(aAdr, pCell) );
2952cdf0e10cSrcweir return;
2953cdf0e10cSrcweir }
2954cdf0e10cSrcweir else
2955cdf0e10cSrcweir {
2956cdf0e10cSrcweir PushDouble(0.0);
2957cdf0e10cSrcweir return;
2958cdf0e10cSrcweir }
2959cdf0e10cSrcweir }
2960cdf0e10cSrcweir break;
2961cdf0e10cSrcweir case svMatrix:
2962cdf0e10cSrcweir {
2963cdf0e10cSrcweir ScMatValType nType = GetDoubleOrStringFromMatrix( fVal,
2964cdf0e10cSrcweir aInputString);
2965cdf0e10cSrcweir switch (nType)
2966cdf0e10cSrcweir {
2967cdf0e10cSrcweir case SC_MATVAL_EMPTY:
2968cdf0e10cSrcweir fVal = 0.0;
2969cdf0e10cSrcweir // fallthru
2970cdf0e10cSrcweir case SC_MATVAL_VALUE:
2971cdf0e10cSrcweir case SC_MATVAL_BOOLEAN:
2972cdf0e10cSrcweir PushDouble( fVal);
2973cdf0e10cSrcweir return;
2974cdf0e10cSrcweir //break;
2975cdf0e10cSrcweir case SC_MATVAL_STRING:
2976cdf0e10cSrcweir // evaluated below
2977cdf0e10cSrcweir break;
2978cdf0e10cSrcweir default:
2979cdf0e10cSrcweir PushIllegalArgument();
2980cdf0e10cSrcweir }
2981cdf0e10cSrcweir }
2982cdf0e10cSrcweir break;
2983cdf0e10cSrcweir default:
2984cdf0e10cSrcweir aInputString = GetString();
2985cdf0e10cSrcweir break;
2986cdf0e10cSrcweir }
2987cdf0e10cSrcweir
2988cdf0e10cSrcweir sal_uInt32 nFIndex = 0; // 0 for default locale
2989cdf0e10cSrcweir if (pFormatter->IsNumberFormat(aInputString, nFIndex, fVal))
2990cdf0e10cSrcweir PushDouble(fVal);
2991cdf0e10cSrcweir else
2992cdf0e10cSrcweir PushIllegalArgument();
2993cdf0e10cSrcweir }
2994cdf0e10cSrcweir
2995cdf0e10cSrcweir
2996*5cd1c826Smseidel // TODO: this should be a proper unicode string method
lcl_ScInterpreter_IsPrintable(sal_Unicode c)2997cdf0e10cSrcweir inline sal_Bool lcl_ScInterpreter_IsPrintable( sal_Unicode c )
2998cdf0e10cSrcweir {
2999cdf0e10cSrcweir return 0x20 <= c && c != 0x7f;
3000cdf0e10cSrcweir }
3001cdf0e10cSrcweir
ScClean()3002cdf0e10cSrcweir void ScInterpreter::ScClean()
3003cdf0e10cSrcweir {
3004cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScClean" );
3005cdf0e10cSrcweir String aStr( GetString() );
3006cdf0e10cSrcweir for ( xub_StrLen i = 0; i < aStr.Len(); i++ )
3007cdf0e10cSrcweir {
3008cdf0e10cSrcweir if ( !lcl_ScInterpreter_IsPrintable( aStr.GetChar( i ) ) )
3009cdf0e10cSrcweir aStr.Erase(i,1);
3010cdf0e10cSrcweir }
3011cdf0e10cSrcweir PushString(aStr);
3012cdf0e10cSrcweir }
3013cdf0e10cSrcweir
3014cdf0e10cSrcweir
ScCode()3015cdf0e10cSrcweir void ScInterpreter::ScCode()
3016cdf0e10cSrcweir {
3017cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScCode" );
3018*5cd1c826Smseidel // TODO: make it full range unicode?
3019cdf0e10cSrcweir const String& rStr = GetString();
3020cdf0e10cSrcweir PushInt( (sal_uChar) ByteString::ConvertFromUnicode( rStr.GetChar(0), gsl_getSystemTextEncoding() ) );
3021cdf0e10cSrcweir }
3022cdf0e10cSrcweir
3023cdf0e10cSrcweir
ScChar()3024cdf0e10cSrcweir void ScInterpreter::ScChar()
3025cdf0e10cSrcweir {
3026cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScChar" );
3027*5cd1c826Smseidel // TODO: make it full range unicode?
3028cdf0e10cSrcweir double fVal = GetDouble();
3029cdf0e10cSrcweir if (fVal < 0.0 || fVal >= 256.0)
3030cdf0e10cSrcweir PushIllegalArgument();
3031cdf0e10cSrcweir else
3032cdf0e10cSrcweir {
3033cdf0e10cSrcweir String aStr( '0' );
3034cdf0e10cSrcweir aStr.SetChar( 0, ByteString::ConvertToUnicode( (sal_Char) fVal, gsl_getSystemTextEncoding() ) );
3035cdf0e10cSrcweir PushString( aStr );
3036cdf0e10cSrcweir }
3037cdf0e10cSrcweir }
3038cdf0e10cSrcweir
3039cdf0e10cSrcweir
3040cdf0e10cSrcweir /* #i70213# fullwidth/halfwidth conversion provided by
3041cdf0e10cSrcweir * Takashi Nakamoto <bluedwarf@ooo>
3042cdf0e10cSrcweir * erAck: added Excel compatibility conversions as seen in issue's test case. */
3043cdf0e10cSrcweir
lcl_convertIntoHalfWidth(const::rtl::OUString & rStr)3044cdf0e10cSrcweir static ::rtl::OUString lcl_convertIntoHalfWidth( const ::rtl::OUString & rStr )
3045cdf0e10cSrcweir {
3046cdf0e10cSrcweir static bool bFirstASCCall = true;
3047cdf0e10cSrcweir static utl::TransliterationWrapper aTrans( ::comphelper::getProcessServiceFactory(), 0 );
3048cdf0e10cSrcweir
3049cdf0e10cSrcweir if( bFirstASCCall )
3050cdf0e10cSrcweir {
3051cdf0e10cSrcweir aTrans.loadModuleByImplName( ::rtl::OUString::createFromAscii( "FULLWIDTH_HALFWIDTH_LIKE_ASC" ), LANGUAGE_SYSTEM );
3052cdf0e10cSrcweir bFirstASCCall = false;
3053cdf0e10cSrcweir }
3054cdf0e10cSrcweir
3055cdf0e10cSrcweir return aTrans.transliterate( rStr, 0, sal_uInt16( rStr.getLength() ), NULL );
3056cdf0e10cSrcweir }
3057cdf0e10cSrcweir
3058cdf0e10cSrcweir
lcl_convertIntoFullWidth(const::rtl::OUString & rStr)3059cdf0e10cSrcweir static ::rtl::OUString lcl_convertIntoFullWidth( const ::rtl::OUString & rStr )
3060cdf0e10cSrcweir {
3061cdf0e10cSrcweir static bool bFirstJISCall = true;
3062cdf0e10cSrcweir static utl::TransliterationWrapper aTrans( ::comphelper::getProcessServiceFactory(), 0 );
3063cdf0e10cSrcweir
3064cdf0e10cSrcweir if( bFirstJISCall )
3065cdf0e10cSrcweir {
3066cdf0e10cSrcweir aTrans.loadModuleByImplName( ::rtl::OUString::createFromAscii( "HALFWIDTH_FULLWIDTH_LIKE_JIS" ), LANGUAGE_SYSTEM );
3067cdf0e10cSrcweir bFirstJISCall = false;
3068cdf0e10cSrcweir }
3069cdf0e10cSrcweir
3070cdf0e10cSrcweir return aTrans.transliterate( rStr, 0, sal_uInt16( rStr.getLength() ), NULL );
3071cdf0e10cSrcweir }
3072cdf0e10cSrcweir
3073cdf0e10cSrcweir
3074cdf0e10cSrcweir /* ODFF:
3075cdf0e10cSrcweir * Summary: Converts half-width to full-width ASCII and katakana characters.
3076cdf0e10cSrcweir * Semantics: Conversion is done for half-width ASCII and katakana characters,
3077cdf0e10cSrcweir * other characters are simply copied from T to the result. This is the
3078cdf0e10cSrcweir * complementary function to ASC.
3079cdf0e10cSrcweir * For references regarding halfwidth and fullwidth characters see
3080cdf0e10cSrcweir * http://www.unicode.org/reports/tr11/
3081cdf0e10cSrcweir * http://www.unicode.org/charts/charindex2.html#H
3082cdf0e10cSrcweir * http://www.unicode.org/charts/charindex2.html#F
3083cdf0e10cSrcweir */
ScJis()3084cdf0e10cSrcweir void ScInterpreter::ScJis()
3085cdf0e10cSrcweir {
3086cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScJis" );
3087cdf0e10cSrcweir if (MustHaveParamCount( GetByte(), 1))
3088cdf0e10cSrcweir PushString( lcl_convertIntoFullWidth( GetString()));
3089cdf0e10cSrcweir }
3090cdf0e10cSrcweir
3091cdf0e10cSrcweir
3092cdf0e10cSrcweir /* ODFF:
3093cdf0e10cSrcweir * Summary: Converts full-width to half-width ASCII and katakana characters.
3094cdf0e10cSrcweir * Semantics: Conversion is done for full-width ASCII and katakana characters,
3095cdf0e10cSrcweir * other characters are simply copied from T to the result. This is the
3096cdf0e10cSrcweir * complementary function to JIS.
3097cdf0e10cSrcweir */
ScAsc()3098cdf0e10cSrcweir void ScInterpreter::ScAsc()
3099cdf0e10cSrcweir {
3100cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScAsc" );
3101cdf0e10cSrcweir if (MustHaveParamCount( GetByte(), 1))
3102cdf0e10cSrcweir PushString( lcl_convertIntoHalfWidth( GetString()));
3103cdf0e10cSrcweir }
3104cdf0e10cSrcweir
ScUnicode()3105cdf0e10cSrcweir void ScInterpreter::ScUnicode()
3106cdf0e10cSrcweir {
3107cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScUnicode" );
3108cdf0e10cSrcweir if ( MustHaveParamCount( GetByte(), 1 ) )
3109cdf0e10cSrcweir {
3110cdf0e10cSrcweir const rtl::OUString& rStr = GetString();
3111cdf0e10cSrcweir if (rStr.getLength() <= 0)
3112cdf0e10cSrcweir PushIllegalParameter();
3113cdf0e10cSrcweir else
3114cdf0e10cSrcweir {
3115cdf0e10cSrcweir sal_Int32 i = 0;
3116cdf0e10cSrcweir PushDouble( rStr.iterateCodePoints(&i) );
3117cdf0e10cSrcweir }
3118cdf0e10cSrcweir }
3119cdf0e10cSrcweir }
3120cdf0e10cSrcweir
ScUnichar()3121cdf0e10cSrcweir void ScInterpreter::ScUnichar()
3122cdf0e10cSrcweir {
3123cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScUnichar" );
3124cdf0e10cSrcweir if ( MustHaveParamCount( GetByte(), 1 ) )
3125cdf0e10cSrcweir {
3126cdf0e10cSrcweir double dVal = ::rtl::math::approxFloor( GetDouble() );
3127cdf0e10cSrcweir if ((dVal < 0x000000) || (dVal > 0x10FFFF))
3128cdf0e10cSrcweir PushIllegalArgument();
3129cdf0e10cSrcweir else
3130cdf0e10cSrcweir {
3131cdf0e10cSrcweir sal_uInt32 nCodePoint = static_cast<sal_uInt32>( dVal );
3132cdf0e10cSrcweir rtl::OUString aStr( &nCodePoint, 1 );
3133cdf0e10cSrcweir PushString( aStr );
3134cdf0e10cSrcweir }
3135cdf0e10cSrcweir }
3136cdf0e10cSrcweir }
3137cdf0e10cSrcweir
3138cdf0e10cSrcweir
ScMin(sal_Bool bTextAsZero)3139cdf0e10cSrcweir void ScInterpreter::ScMin( sal_Bool bTextAsZero )
3140cdf0e10cSrcweir {
3141cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScMin" );
3142cdf0e10cSrcweir short nParamCount = GetByte();
3143cdf0e10cSrcweir if (!MustHaveParamCountMin( nParamCount, 1))
3144cdf0e10cSrcweir return;
3145cdf0e10cSrcweir double nMin = ::std::numeric_limits<double>::max();
3146cdf0e10cSrcweir double nVal = 0.0;
3147cdf0e10cSrcweir ScAddress aAdr;
3148cdf0e10cSrcweir ScRange aRange;
3149cdf0e10cSrcweir size_t nRefInList = 0;
3150cdf0e10cSrcweir while (nParamCount-- > 0)
3151cdf0e10cSrcweir {
3152cdf0e10cSrcweir switch (GetStackType())
3153cdf0e10cSrcweir {
3154cdf0e10cSrcweir case svDouble :
3155cdf0e10cSrcweir {
3156cdf0e10cSrcweir nVal = GetDouble();
3157cdf0e10cSrcweir if (nMin > nVal) nMin = nVal;
3158cdf0e10cSrcweir nFuncFmtType = NUMBERFORMAT_NUMBER;
3159cdf0e10cSrcweir }
3160cdf0e10cSrcweir break;
3161cdf0e10cSrcweir case svSingleRef :
3162cdf0e10cSrcweir {
3163cdf0e10cSrcweir PopSingleRef( aAdr );
3164cdf0e10cSrcweir ScBaseCell* pCell = GetCell( aAdr );
3165cdf0e10cSrcweir if (HasCellValueData(pCell))
3166cdf0e10cSrcweir {
3167cdf0e10cSrcweir nVal = GetCellValue( aAdr, pCell );
3168cdf0e10cSrcweir CurFmtToFuncFmt();
3169cdf0e10cSrcweir if (nMin > nVal) nMin = nVal;
3170cdf0e10cSrcweir }
3171cdf0e10cSrcweir else if ( bTextAsZero && HasCellStringData( pCell ) )
3172cdf0e10cSrcweir {
3173cdf0e10cSrcweir if ( nMin > 0.0 )
3174cdf0e10cSrcweir nMin = 0.0;
3175cdf0e10cSrcweir }
3176cdf0e10cSrcweir }
3177cdf0e10cSrcweir break;
3178cdf0e10cSrcweir case svDoubleRef :
3179cdf0e10cSrcweir case svRefList :
3180cdf0e10cSrcweir {
3181cdf0e10cSrcweir sal_uInt16 nErr = 0;
3182cdf0e10cSrcweir PopDoubleRef( aRange, nParamCount, nRefInList);
3183cdf0e10cSrcweir ScValueIterator aValIter( pDok, aRange, glSubTotal, bTextAsZero );
3184cdf0e10cSrcweir if (aValIter.GetFirst(nVal, nErr))
3185cdf0e10cSrcweir {
3186cdf0e10cSrcweir if (nMin > nVal)
3187cdf0e10cSrcweir nMin = nVal;
3188cdf0e10cSrcweir aValIter.GetCurNumFmtInfo( nFuncFmtType, nFuncFmtIndex );
3189cdf0e10cSrcweir while ((nErr == 0) && aValIter.GetNext(nVal, nErr))
3190cdf0e10cSrcweir {
3191cdf0e10cSrcweir if (nMin > nVal)
3192cdf0e10cSrcweir nMin = nVal;
3193cdf0e10cSrcweir }
3194cdf0e10cSrcweir SetError(nErr);
3195cdf0e10cSrcweir }
3196cdf0e10cSrcweir }
3197cdf0e10cSrcweir break;
3198cdf0e10cSrcweir case svMatrix :
3199cdf0e10cSrcweir {
3200cdf0e10cSrcweir ScMatrixRef pMat = PopMatrix();
3201cdf0e10cSrcweir if (pMat)
3202cdf0e10cSrcweir {
3203cdf0e10cSrcweir SCSIZE nC, nR;
3204cdf0e10cSrcweir nFuncFmtType = NUMBERFORMAT_NUMBER;
3205cdf0e10cSrcweir pMat->GetDimensions(nC, nR);
3206cdf0e10cSrcweir if (pMat->IsNumeric())
3207cdf0e10cSrcweir {
3208cdf0e10cSrcweir for (SCSIZE nMatCol = 0; nMatCol < nC; nMatCol++)
3209cdf0e10cSrcweir for (SCSIZE nMatRow = 0; nMatRow < nR; nMatRow++)
3210cdf0e10cSrcweir {
3211cdf0e10cSrcweir nVal = pMat->GetDouble(nMatCol,nMatRow);
3212cdf0e10cSrcweir if (nMin > nVal) nMin = nVal;
3213cdf0e10cSrcweir }
3214cdf0e10cSrcweir }
3215cdf0e10cSrcweir else
3216cdf0e10cSrcweir {
3217cdf0e10cSrcweir for (SCSIZE nMatCol = 0; nMatCol < nC; nMatCol++)
3218cdf0e10cSrcweir {
3219cdf0e10cSrcweir for (SCSIZE nMatRow = 0; nMatRow < nR; nMatRow++)
3220cdf0e10cSrcweir {
3221cdf0e10cSrcweir if (!pMat->IsString(nMatCol,nMatRow))
3222cdf0e10cSrcweir {
3223cdf0e10cSrcweir nVal = pMat->GetDouble(nMatCol,nMatRow);
3224cdf0e10cSrcweir if (nMin > nVal) nMin = nVal;
3225cdf0e10cSrcweir }
3226cdf0e10cSrcweir else if ( bTextAsZero )
3227cdf0e10cSrcweir {
3228cdf0e10cSrcweir if ( nMin > 0.0 )
3229cdf0e10cSrcweir nMin = 0.0;
3230cdf0e10cSrcweir }
3231cdf0e10cSrcweir }
3232cdf0e10cSrcweir }
3233cdf0e10cSrcweir }
3234cdf0e10cSrcweir }
3235cdf0e10cSrcweir }
3236cdf0e10cSrcweir break;
3237cdf0e10cSrcweir case svString :
3238cdf0e10cSrcweir {
3239cdf0e10cSrcweir Pop();
3240cdf0e10cSrcweir if ( bTextAsZero )
3241cdf0e10cSrcweir {
3242cdf0e10cSrcweir if ( nMin > 0.0 )
3243cdf0e10cSrcweir nMin = 0.0;
3244cdf0e10cSrcweir }
3245cdf0e10cSrcweir else
3246cdf0e10cSrcweir SetError(errIllegalParameter);
3247cdf0e10cSrcweir }
3248cdf0e10cSrcweir break;
3249cdf0e10cSrcweir default :
3250cdf0e10cSrcweir Pop();
3251cdf0e10cSrcweir SetError(errIllegalParameter);
3252cdf0e10cSrcweir }
3253cdf0e10cSrcweir }
3254cdf0e10cSrcweir if ( nVal < nMin )
3255cdf0e10cSrcweir PushDouble(0.0);
3256cdf0e10cSrcweir else
3257cdf0e10cSrcweir PushDouble(nMin);
3258cdf0e10cSrcweir }
3259cdf0e10cSrcweir
ScMax(sal_Bool bTextAsZero)3260cdf0e10cSrcweir void ScInterpreter::ScMax( sal_Bool bTextAsZero )
3261cdf0e10cSrcweir {
3262cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScMax" );
3263cdf0e10cSrcweir short nParamCount = GetByte();
3264cdf0e10cSrcweir if (!MustHaveParamCountMin( nParamCount, 1))
3265cdf0e10cSrcweir return;
3266cdf0e10cSrcweir double nMax = -(::std::numeric_limits<double>::max());
3267cdf0e10cSrcweir double nVal = 0.0;
3268cdf0e10cSrcweir ScAddress aAdr;
3269cdf0e10cSrcweir ScRange aRange;
3270cdf0e10cSrcweir size_t nRefInList = 0;
3271cdf0e10cSrcweir while (nParamCount-- > 0)
3272cdf0e10cSrcweir {
3273cdf0e10cSrcweir switch (GetStackType())
3274cdf0e10cSrcweir {
3275cdf0e10cSrcweir case svDouble :
3276cdf0e10cSrcweir {
3277cdf0e10cSrcweir nVal = GetDouble();
3278cdf0e10cSrcweir if (nMax < nVal) nMax = nVal;
3279cdf0e10cSrcweir nFuncFmtType = NUMBERFORMAT_NUMBER;
3280cdf0e10cSrcweir }
3281cdf0e10cSrcweir break;
3282cdf0e10cSrcweir case svSingleRef :
3283cdf0e10cSrcweir {
3284cdf0e10cSrcweir PopSingleRef( aAdr );
3285cdf0e10cSrcweir ScBaseCell* pCell = GetCell( aAdr );
3286cdf0e10cSrcweir if (HasCellValueData(pCell))
3287cdf0e10cSrcweir {
3288cdf0e10cSrcweir nVal = GetCellValue( aAdr, pCell );
3289cdf0e10cSrcweir CurFmtToFuncFmt();
3290cdf0e10cSrcweir if (nMax < nVal) nMax = nVal;
3291cdf0e10cSrcweir }
3292cdf0e10cSrcweir else if ( bTextAsZero && HasCellStringData( pCell ) )
3293cdf0e10cSrcweir {
3294cdf0e10cSrcweir if ( nMax < 0.0 )
3295cdf0e10cSrcweir nMax = 0.0;
3296cdf0e10cSrcweir }
3297cdf0e10cSrcweir }
3298cdf0e10cSrcweir break;
3299cdf0e10cSrcweir case svDoubleRef :
3300cdf0e10cSrcweir case svRefList :
3301cdf0e10cSrcweir {
3302cdf0e10cSrcweir sal_uInt16 nErr = 0;
3303cdf0e10cSrcweir PopDoubleRef( aRange, nParamCount, nRefInList);
3304cdf0e10cSrcweir ScValueIterator aValIter( pDok, aRange, glSubTotal, bTextAsZero );
3305cdf0e10cSrcweir if (aValIter.GetFirst(nVal, nErr))
3306cdf0e10cSrcweir {
3307cdf0e10cSrcweir if (nMax < nVal)
3308cdf0e10cSrcweir nMax = nVal;
3309cdf0e10cSrcweir aValIter.GetCurNumFmtInfo( nFuncFmtType, nFuncFmtIndex );
3310cdf0e10cSrcweir while ((nErr == 0) && aValIter.GetNext(nVal, nErr))
3311cdf0e10cSrcweir {
3312cdf0e10cSrcweir if (nMax < nVal)
3313cdf0e10cSrcweir nMax = nVal;
3314cdf0e10cSrcweir }
3315cdf0e10cSrcweir SetError(nErr);
3316cdf0e10cSrcweir }
3317cdf0e10cSrcweir }
3318cdf0e10cSrcweir break;
3319cdf0e10cSrcweir case svMatrix :
3320cdf0e10cSrcweir {
3321cdf0e10cSrcweir ScMatrixRef pMat = PopMatrix();
3322cdf0e10cSrcweir if (pMat)
3323cdf0e10cSrcweir {
3324cdf0e10cSrcweir nFuncFmtType = NUMBERFORMAT_NUMBER;
3325cdf0e10cSrcweir SCSIZE nC, nR;
3326cdf0e10cSrcweir pMat->GetDimensions(nC, nR);
3327cdf0e10cSrcweir if (pMat->IsNumeric())
3328cdf0e10cSrcweir {
3329cdf0e10cSrcweir for (SCSIZE nMatCol = 0; nMatCol < nC; nMatCol++)
3330cdf0e10cSrcweir for (SCSIZE nMatRow = 0; nMatRow < nR; nMatRow++)
3331cdf0e10cSrcweir {
3332cdf0e10cSrcweir nVal = pMat->GetDouble(nMatCol,nMatRow);
3333cdf0e10cSrcweir if (nMax < nVal) nMax = nVal;
3334cdf0e10cSrcweir }
3335cdf0e10cSrcweir }
3336cdf0e10cSrcweir else
3337cdf0e10cSrcweir {
3338cdf0e10cSrcweir for (SCSIZE nMatCol = 0; nMatCol < nC; nMatCol++)
3339cdf0e10cSrcweir {
3340cdf0e10cSrcweir for (SCSIZE nMatRow = 0; nMatRow < nR; nMatRow++)
3341cdf0e10cSrcweir {
3342cdf0e10cSrcweir if (!pMat->IsString(nMatCol,nMatRow))
3343cdf0e10cSrcweir {
3344cdf0e10cSrcweir nVal = pMat->GetDouble(nMatCol,nMatRow);
3345cdf0e10cSrcweir if (nMax < nVal) nMax = nVal;
3346cdf0e10cSrcweir }
3347cdf0e10cSrcweir else if ( bTextAsZero )
3348cdf0e10cSrcweir {
3349cdf0e10cSrcweir if ( nMax < 0.0 )
3350cdf0e10cSrcweir nMax = 0.0;
3351cdf0e10cSrcweir }
3352cdf0e10cSrcweir }
3353cdf0e10cSrcweir }
3354cdf0e10cSrcweir }
3355cdf0e10cSrcweir }
3356cdf0e10cSrcweir }
3357cdf0e10cSrcweir break;
3358cdf0e10cSrcweir case svString :
3359cdf0e10cSrcweir {
3360cdf0e10cSrcweir Pop();
3361cdf0e10cSrcweir if ( bTextAsZero )
3362cdf0e10cSrcweir {
3363cdf0e10cSrcweir if ( nMax < 0.0 )
3364cdf0e10cSrcweir nMax = 0.0;
3365cdf0e10cSrcweir }
3366cdf0e10cSrcweir else
3367cdf0e10cSrcweir SetError(errIllegalParameter);
3368cdf0e10cSrcweir }
3369cdf0e10cSrcweir break;
3370cdf0e10cSrcweir default :
3371cdf0e10cSrcweir Pop();
3372cdf0e10cSrcweir SetError(errIllegalParameter);
3373cdf0e10cSrcweir }
3374cdf0e10cSrcweir }
3375cdf0e10cSrcweir if ( nVal > nMax )
3376cdf0e10cSrcweir PushDouble(0.0);
3377cdf0e10cSrcweir else
3378cdf0e10cSrcweir PushDouble(nMax);
3379cdf0e10cSrcweir }
3380cdf0e10cSrcweir
IterateParameters(ScIterFunc eFunc,sal_Bool bTextAsZero)3381cdf0e10cSrcweir double ScInterpreter::IterateParameters( ScIterFunc eFunc, sal_Bool bTextAsZero )
3382cdf0e10cSrcweir {
3383cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::IterateParameters" );
3384cdf0e10cSrcweir short nParamCount = GetByte();
3385cdf0e10cSrcweir double fRes = ( eFunc == ifPRODUCT ) ? 1.0 : 0.0;
3386cdf0e10cSrcweir double fVal = 0.0;
3387cdf0e10cSrcweir double fMem = 0.0;
3388cdf0e10cSrcweir sal_Bool bNull = sal_True;
3389cdf0e10cSrcweir sal_uLong nCount = 0;
3390cdf0e10cSrcweir ScAddress aAdr;
3391cdf0e10cSrcweir ScRange aRange;
3392cdf0e10cSrcweir size_t nRefInList = 0;
3393cdf0e10cSrcweir if ( nGlobalError && ( eFunc == ifCOUNT2 || eFunc == ifCOUNT ) )
3394cdf0e10cSrcweir nGlobalError = 0;
3395cdf0e10cSrcweir while (nParamCount-- > 0)
3396cdf0e10cSrcweir {
3397cdf0e10cSrcweir switch (GetStackType())
3398cdf0e10cSrcweir {
3399cdf0e10cSrcweir
3400cdf0e10cSrcweir case svString:
3401cdf0e10cSrcweir {
3402cdf0e10cSrcweir if( eFunc == ifCOUNT )
3403cdf0e10cSrcweir {
3404cdf0e10cSrcweir String aStr( PopString() );
3405cdf0e10cSrcweir sal_uInt32 nFIndex = 0; // damit default Land/Spr.
3406cdf0e10cSrcweir if ( bTextAsZero || pFormatter->IsNumberFormat(aStr, nFIndex, fVal))
3407cdf0e10cSrcweir nCount++;
3408cdf0e10cSrcweir }
3409cdf0e10cSrcweir else
3410cdf0e10cSrcweir {
3411cdf0e10cSrcweir switch ( eFunc )
3412cdf0e10cSrcweir {
3413cdf0e10cSrcweir case ifAVERAGE:
3414cdf0e10cSrcweir case ifSUM:
3415cdf0e10cSrcweir case ifSUMSQ:
3416cdf0e10cSrcweir case ifPRODUCT:
3417cdf0e10cSrcweir {
3418cdf0e10cSrcweir if ( bTextAsZero )
3419cdf0e10cSrcweir {
3420cdf0e10cSrcweir Pop();
3421cdf0e10cSrcweir nCount++;
3422cdf0e10cSrcweir if ( eFunc == ifPRODUCT )
3423cdf0e10cSrcweir fRes = 0.0;
3424cdf0e10cSrcweir }
3425cdf0e10cSrcweir else
3426cdf0e10cSrcweir {
3427cdf0e10cSrcweir while (nParamCount-- > 0)
3428cdf0e10cSrcweir Pop();
3429cdf0e10cSrcweir SetError( errNoValue );
3430cdf0e10cSrcweir }
3431cdf0e10cSrcweir }
3432cdf0e10cSrcweir break;
3433cdf0e10cSrcweir default:
3434cdf0e10cSrcweir Pop();
3435cdf0e10cSrcweir nCount++;
3436cdf0e10cSrcweir }
3437cdf0e10cSrcweir }
3438cdf0e10cSrcweir }
3439cdf0e10cSrcweir break;
3440cdf0e10cSrcweir case svDouble :
3441cdf0e10cSrcweir fVal = GetDouble();
3442cdf0e10cSrcweir nCount++;
3443cdf0e10cSrcweir switch( eFunc )
3444cdf0e10cSrcweir {
3445cdf0e10cSrcweir case ifAVERAGE:
3446cdf0e10cSrcweir case ifSUM:
3447cdf0e10cSrcweir if ( bNull && fVal != 0.0 )
3448cdf0e10cSrcweir {
3449cdf0e10cSrcweir bNull = sal_False;
3450cdf0e10cSrcweir fMem = fVal;
3451cdf0e10cSrcweir }
3452cdf0e10cSrcweir else
3453cdf0e10cSrcweir fRes += fVal;
3454cdf0e10cSrcweir break;
3455cdf0e10cSrcweir case ifSUMSQ: fRes += fVal * fVal; break;
3456cdf0e10cSrcweir case ifPRODUCT: fRes *= fVal; break;
3457cdf0e10cSrcweir default: ; // nothing
3458cdf0e10cSrcweir }
3459cdf0e10cSrcweir nFuncFmtType = NUMBERFORMAT_NUMBER;
3460cdf0e10cSrcweir break;
3461cdf0e10cSrcweir case svSingleRef :
3462cdf0e10cSrcweir {
3463cdf0e10cSrcweir PopSingleRef( aAdr );
3464cdf0e10cSrcweir if ( nGlobalError && ( eFunc == ifCOUNT2 || eFunc == ifCOUNT ) )
3465cdf0e10cSrcweir {
3466cdf0e10cSrcweir nGlobalError = 0;
3467cdf0e10cSrcweir if ( eFunc == ifCOUNT2 )
3468cdf0e10cSrcweir ++nCount;
3469cdf0e10cSrcweir break;
3470cdf0e10cSrcweir }
3471cdf0e10cSrcweir ScBaseCell* pCell = GetCell( aAdr );
3472cdf0e10cSrcweir if ( pCell )
3473cdf0e10cSrcweir {
3474cdf0e10cSrcweir if( eFunc == ifCOUNT2 )
3475cdf0e10cSrcweir {
3476cdf0e10cSrcweir CellType eCellType = pCell->GetCellType();
3477cdf0e10cSrcweir if (eCellType != CELLTYPE_NONE && eCellType != CELLTYPE_NOTE)
3478cdf0e10cSrcweir nCount++;
3479cdf0e10cSrcweir if ( nGlobalError )
3480cdf0e10cSrcweir nGlobalError = 0;
3481cdf0e10cSrcweir }
3482cdf0e10cSrcweir else if ( pCell->HasValueData() )
3483cdf0e10cSrcweir {
3484cdf0e10cSrcweir nCount++;
3485cdf0e10cSrcweir fVal = GetCellValue( aAdr, pCell );
3486cdf0e10cSrcweir CurFmtToFuncFmt();
3487cdf0e10cSrcweir switch( eFunc )
3488cdf0e10cSrcweir {
3489cdf0e10cSrcweir case ifAVERAGE:
3490cdf0e10cSrcweir case ifSUM:
3491cdf0e10cSrcweir if ( bNull && fVal != 0.0 )
3492cdf0e10cSrcweir {
3493cdf0e10cSrcweir bNull = sal_False;
3494cdf0e10cSrcweir fMem = fVal;
3495cdf0e10cSrcweir }
3496cdf0e10cSrcweir else
3497cdf0e10cSrcweir fRes += fVal;
3498cdf0e10cSrcweir break;
3499cdf0e10cSrcweir case ifSUMSQ: fRes += fVal * fVal; break;
3500cdf0e10cSrcweir case ifPRODUCT: fRes *= fVal; break;
3501cdf0e10cSrcweir case ifCOUNT:
3502cdf0e10cSrcweir if ( nGlobalError )
3503cdf0e10cSrcweir {
3504cdf0e10cSrcweir nGlobalError = 0;
3505cdf0e10cSrcweir nCount--;
3506cdf0e10cSrcweir }
3507cdf0e10cSrcweir break;
3508cdf0e10cSrcweir default: ; // nothing
3509cdf0e10cSrcweir }
3510cdf0e10cSrcweir }
3511cdf0e10cSrcweir else if ( bTextAsZero && pCell->HasStringData() )
3512cdf0e10cSrcweir {
3513cdf0e10cSrcweir nCount++;
3514cdf0e10cSrcweir if ( eFunc == ifPRODUCT )
3515cdf0e10cSrcweir fRes = 0.0;
3516cdf0e10cSrcweir }
3517cdf0e10cSrcweir }
3518cdf0e10cSrcweir }
3519cdf0e10cSrcweir break;
3520cdf0e10cSrcweir case svDoubleRef :
3521cdf0e10cSrcweir case svRefList :
3522cdf0e10cSrcweir {
3523cdf0e10cSrcweir sal_uInt16 nErr = 0;
3524cdf0e10cSrcweir PopDoubleRef( aRange, nParamCount, nRefInList);
3525cdf0e10cSrcweir if ( nGlobalError && ( eFunc == ifCOUNT2 || eFunc == ifCOUNT ) )
3526cdf0e10cSrcweir {
3527cdf0e10cSrcweir nGlobalError = 0;
3528cdf0e10cSrcweir if ( eFunc == ifCOUNT2 )
3529cdf0e10cSrcweir ++nCount;
3530cdf0e10cSrcweir break;
3531cdf0e10cSrcweir }
3532cdf0e10cSrcweir if( eFunc == ifCOUNT2 )
3533cdf0e10cSrcweir {
3534cdf0e10cSrcweir ScBaseCell* pCell;
3535cdf0e10cSrcweir ScCellIterator aIter( pDok, aRange, glSubTotal );
3536cdf0e10cSrcweir if ( (pCell = aIter.GetFirst()) != NULL )
3537cdf0e10cSrcweir {
3538cdf0e10cSrcweir do
3539cdf0e10cSrcweir {
3540cdf0e10cSrcweir CellType eType = pCell->GetCellType();
3541cdf0e10cSrcweir if( eType != CELLTYPE_NONE && eType != CELLTYPE_NOTE )
3542cdf0e10cSrcweir nCount++;
3543cdf0e10cSrcweir }
3544cdf0e10cSrcweir while ( (pCell = aIter.GetNext()) != NULL );
3545cdf0e10cSrcweir }
3546cdf0e10cSrcweir if ( nGlobalError )
3547cdf0e10cSrcweir nGlobalError = 0;
3548cdf0e10cSrcweir }
3549cdf0e10cSrcweir else
3550cdf0e10cSrcweir {
3551cdf0e10cSrcweir ScValueIterator aValIter( pDok, aRange, glSubTotal, bTextAsZero );
3552cdf0e10cSrcweir if (aValIter.GetFirst(fVal, nErr))
3553cdf0e10cSrcweir {
3554cdf0e10cSrcweir // Schleife aus Performance-Gruenden nach innen verlegt:
3555cdf0e10cSrcweir aValIter.GetCurNumFmtInfo( nFuncFmtType, nFuncFmtIndex );
3556cdf0e10cSrcweir switch( eFunc )
3557cdf0e10cSrcweir {
3558cdf0e10cSrcweir case ifAVERAGE:
3559cdf0e10cSrcweir case ifSUM:
3560cdf0e10cSrcweir do
3561cdf0e10cSrcweir {
3562cdf0e10cSrcweir SetError(nErr);
3563cdf0e10cSrcweir if ( bNull && fVal != 0.0 )
3564cdf0e10cSrcweir {
3565cdf0e10cSrcweir bNull = sal_False;
3566cdf0e10cSrcweir fMem = fVal;
3567cdf0e10cSrcweir }
3568cdf0e10cSrcweir else
3569cdf0e10cSrcweir fRes += fVal;
3570cdf0e10cSrcweir nCount++;
3571cdf0e10cSrcweir }
3572cdf0e10cSrcweir while (aValIter.GetNext(fVal, nErr));
3573cdf0e10cSrcweir break;
3574cdf0e10cSrcweir case ifSUMSQ:
3575cdf0e10cSrcweir do
3576cdf0e10cSrcweir {
3577cdf0e10cSrcweir SetError(nErr);
3578cdf0e10cSrcweir fRes += fVal * fVal;
3579cdf0e10cSrcweir nCount++;
3580cdf0e10cSrcweir }
3581cdf0e10cSrcweir while (aValIter.GetNext(fVal, nErr));
3582cdf0e10cSrcweir break;
3583cdf0e10cSrcweir case ifPRODUCT:
3584cdf0e10cSrcweir do
3585cdf0e10cSrcweir {
3586cdf0e10cSrcweir SetError(nErr);
3587cdf0e10cSrcweir fRes *= fVal;
3588cdf0e10cSrcweir nCount++;
3589cdf0e10cSrcweir }
3590cdf0e10cSrcweir while (aValIter.GetNext(fVal, nErr));
3591cdf0e10cSrcweir break;
3592cdf0e10cSrcweir case ifCOUNT:
3593cdf0e10cSrcweir do
3594cdf0e10cSrcweir {
3595cdf0e10cSrcweir if ( !nErr )
3596cdf0e10cSrcweir nCount++;
3597cdf0e10cSrcweir }
3598cdf0e10cSrcweir while (aValIter.GetNext(fVal, nErr));
3599cdf0e10cSrcweir break;
3600cdf0e10cSrcweir default: ; // nothing
3601cdf0e10cSrcweir }
3602cdf0e10cSrcweir SetError( nErr );
3603cdf0e10cSrcweir }
3604cdf0e10cSrcweir }
3605cdf0e10cSrcweir }
3606cdf0e10cSrcweir break;
3607cdf0e10cSrcweir case svMatrix :
3608cdf0e10cSrcweir {
3609cdf0e10cSrcweir ScMatrixRef pMat = PopMatrix();
3610cdf0e10cSrcweir if (pMat)
3611cdf0e10cSrcweir {
3612cdf0e10cSrcweir SCSIZE nC, nR;
3613cdf0e10cSrcweir nFuncFmtType = NUMBERFORMAT_NUMBER;
3614cdf0e10cSrcweir pMat->GetDimensions(nC, nR);
3615cdf0e10cSrcweir if( eFunc == ifCOUNT2 )
3616cdf0e10cSrcweir nCount += (sal_uLong) nC * nR;
3617cdf0e10cSrcweir else
3618cdf0e10cSrcweir {
3619cdf0e10cSrcweir for (SCSIZE nMatCol = 0; nMatCol < nC; nMatCol++)
3620cdf0e10cSrcweir {
3621cdf0e10cSrcweir for (SCSIZE nMatRow = 0; nMatRow < nR; nMatRow++)
3622cdf0e10cSrcweir {
3623cdf0e10cSrcweir if (!pMat->IsString(nMatCol,nMatRow))
3624cdf0e10cSrcweir {
3625cdf0e10cSrcweir nCount++;
3626cdf0e10cSrcweir fVal = pMat->GetDouble(nMatCol,nMatRow);
3627cdf0e10cSrcweir switch( eFunc )
3628cdf0e10cSrcweir {
3629cdf0e10cSrcweir case ifAVERAGE:
3630cdf0e10cSrcweir case ifSUM:
3631cdf0e10cSrcweir if ( bNull && fVal != 0.0 )
3632cdf0e10cSrcweir {
3633cdf0e10cSrcweir bNull = sal_False;
3634cdf0e10cSrcweir fMem = fVal;
3635cdf0e10cSrcweir }
3636cdf0e10cSrcweir else
3637cdf0e10cSrcweir fRes += fVal;
3638cdf0e10cSrcweir break;
3639cdf0e10cSrcweir case ifSUMSQ: fRes += fVal * fVal; break;
3640cdf0e10cSrcweir case ifPRODUCT: fRes *= fVal; break;
3641cdf0e10cSrcweir default: ; // nothing
3642cdf0e10cSrcweir }
3643cdf0e10cSrcweir }
3644cdf0e10cSrcweir else if ( bTextAsZero )
3645cdf0e10cSrcweir {
3646cdf0e10cSrcweir nCount++;
3647cdf0e10cSrcweir if ( eFunc == ifPRODUCT )
3648cdf0e10cSrcweir fRes = 0.0;
3649cdf0e10cSrcweir }
3650cdf0e10cSrcweir }
3651cdf0e10cSrcweir }
3652cdf0e10cSrcweir }
3653cdf0e10cSrcweir }
3654cdf0e10cSrcweir }
3655cdf0e10cSrcweir break;
3656cdf0e10cSrcweir case svError:
3657cdf0e10cSrcweir {
3658cdf0e10cSrcweir Pop();
3659cdf0e10cSrcweir if ( eFunc == ifCOUNT )
3660cdf0e10cSrcweir {
3661cdf0e10cSrcweir nGlobalError = 0;
3662cdf0e10cSrcweir }
3663cdf0e10cSrcweir else if ( eFunc == ifCOUNT2 )
3664cdf0e10cSrcweir {
3665cdf0e10cSrcweir nCount++;
3666cdf0e10cSrcweir nGlobalError = 0;
3667cdf0e10cSrcweir }
3668cdf0e10cSrcweir }
3669cdf0e10cSrcweir break;
3670cdf0e10cSrcweir default :
3671cdf0e10cSrcweir while (nParamCount-- > 0)
3672cdf0e10cSrcweir PopError();
3673cdf0e10cSrcweir SetError(errIllegalParameter);
3674cdf0e10cSrcweir }
3675cdf0e10cSrcweir }
3676cdf0e10cSrcweir switch( eFunc )
3677cdf0e10cSrcweir {
3678cdf0e10cSrcweir case ifSUM: fRes = ::rtl::math::approxAdd( fRes, fMem ); break;
3679cdf0e10cSrcweir case ifAVERAGE: fRes = div(::rtl::math::approxAdd( fRes, fMem ), nCount); break;
3680cdf0e10cSrcweir case ifCOUNT2:
3681cdf0e10cSrcweir case ifCOUNT: fRes = nCount; break;
3682cdf0e10cSrcweir case ifPRODUCT: if ( !nCount ) fRes = 0.0; break;
3683cdf0e10cSrcweir default: ; // nothing
3684cdf0e10cSrcweir }
3685cdf0e10cSrcweir // Bei Summen etc. macht ein sal_Bool-Ergebnis keinen Sinn
3686cdf0e10cSrcweir // und Anzahl ist immer Number (#38345#)
3687cdf0e10cSrcweir if( eFunc == ifCOUNT || nFuncFmtType == NUMBERFORMAT_LOGICAL )
3688cdf0e10cSrcweir nFuncFmtType = NUMBERFORMAT_NUMBER;
3689cdf0e10cSrcweir return fRes;
3690cdf0e10cSrcweir }
3691cdf0e10cSrcweir
3692cdf0e10cSrcweir
ScSumSQ()3693cdf0e10cSrcweir void ScInterpreter::ScSumSQ()
3694cdf0e10cSrcweir {
3695cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScSumSQ" );
3696cdf0e10cSrcweir PushDouble( IterateParameters( ifSUMSQ ) );
3697cdf0e10cSrcweir }
3698cdf0e10cSrcweir
3699cdf0e10cSrcweir
ScSum()3700cdf0e10cSrcweir void ScInterpreter::ScSum()
3701cdf0e10cSrcweir {
3702cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScSum" );
3703cdf0e10cSrcweir PushDouble( IterateParameters( ifSUM ) );
3704cdf0e10cSrcweir }
3705cdf0e10cSrcweir
3706cdf0e10cSrcweir
ScProduct()3707cdf0e10cSrcweir void ScInterpreter::ScProduct()
3708cdf0e10cSrcweir {
3709cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScProduct" );
3710cdf0e10cSrcweir PushDouble( IterateParameters( ifPRODUCT ) );
3711cdf0e10cSrcweir }
3712cdf0e10cSrcweir
3713cdf0e10cSrcweir
ScAverage(sal_Bool bTextAsZero)3714cdf0e10cSrcweir void ScInterpreter::ScAverage( sal_Bool bTextAsZero )
3715cdf0e10cSrcweir {
3716cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScAverage" );
3717cdf0e10cSrcweir PushDouble( IterateParameters( ifAVERAGE, bTextAsZero ) );
3718cdf0e10cSrcweir }
3719cdf0e10cSrcweir
3720cdf0e10cSrcweir
ScCount()3721cdf0e10cSrcweir void ScInterpreter::ScCount()
3722cdf0e10cSrcweir {
3723cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScCount" );
3724cdf0e10cSrcweir PushDouble( IterateParameters( ifCOUNT ) );
3725cdf0e10cSrcweir }
3726cdf0e10cSrcweir
3727cdf0e10cSrcweir
ScCount2()3728cdf0e10cSrcweir void ScInterpreter::ScCount2()
3729cdf0e10cSrcweir {
3730cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScCount2" );
3731cdf0e10cSrcweir PushDouble( IterateParameters( ifCOUNT2 ) );
3732cdf0e10cSrcweir }
3733cdf0e10cSrcweir
3734cdf0e10cSrcweir
GetStVarParams(double & rVal,double & rValCount,sal_Bool bTextAsZero)3735cdf0e10cSrcweir void ScInterpreter::GetStVarParams( double& rVal, double& rValCount,
3736cdf0e10cSrcweir sal_Bool bTextAsZero )
3737cdf0e10cSrcweir {
3738cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::GetStVarParams" );
3739cdf0e10cSrcweir short nParamCount = GetByte();
3740cdf0e10cSrcweir
3741cdf0e10cSrcweir std::vector<double> values;
3742cdf0e10cSrcweir double fSum = 0.0;
3743cdf0e10cSrcweir double vSum = 0.0;
3744cdf0e10cSrcweir double vMean = 0.0;
3745cdf0e10cSrcweir double fVal = 0.0;
3746cdf0e10cSrcweir rValCount = 0.0;
3747cdf0e10cSrcweir ScAddress aAdr;
3748cdf0e10cSrcweir ScRange aRange;
3749cdf0e10cSrcweir size_t nRefInList = 0;
3750cdf0e10cSrcweir while (nParamCount-- > 0)
3751cdf0e10cSrcweir {
3752cdf0e10cSrcweir switch (GetStackType())
3753cdf0e10cSrcweir {
3754cdf0e10cSrcweir case svDouble :
3755cdf0e10cSrcweir {
3756cdf0e10cSrcweir fVal = GetDouble();
3757cdf0e10cSrcweir values.push_back(fVal);
3758cdf0e10cSrcweir fSum += fVal;
3759cdf0e10cSrcweir rValCount++;
3760cdf0e10cSrcweir }
3761cdf0e10cSrcweir break;
3762cdf0e10cSrcweir case svSingleRef :
3763cdf0e10cSrcweir {
3764cdf0e10cSrcweir PopSingleRef( aAdr );
3765cdf0e10cSrcweir ScBaseCell* pCell = GetCell( aAdr );
3766cdf0e10cSrcweir if (HasCellValueData(pCell))
3767cdf0e10cSrcweir {
3768cdf0e10cSrcweir fVal = GetCellValue( aAdr, pCell );
3769cdf0e10cSrcweir values.push_back(fVal);
3770cdf0e10cSrcweir fSum += fVal;
3771cdf0e10cSrcweir rValCount++;
3772cdf0e10cSrcweir }
3773cdf0e10cSrcweir else if ( bTextAsZero && HasCellStringData( pCell ) )
3774cdf0e10cSrcweir {
3775cdf0e10cSrcweir values.push_back(0.0);
3776cdf0e10cSrcweir rValCount++;
3777cdf0e10cSrcweir }
3778cdf0e10cSrcweir }
3779cdf0e10cSrcweir break;
3780cdf0e10cSrcweir case svDoubleRef :
3781cdf0e10cSrcweir case svRefList :
3782cdf0e10cSrcweir {
3783cdf0e10cSrcweir sal_uInt16 nErr = 0;
3784cdf0e10cSrcweir PopDoubleRef( aRange, nParamCount, nRefInList);
3785cdf0e10cSrcweir ScValueIterator aValIter( pDok, aRange, glSubTotal, bTextAsZero );
3786cdf0e10cSrcweir if (aValIter.GetFirst(fVal, nErr))
3787cdf0e10cSrcweir {
3788cdf0e10cSrcweir do
3789cdf0e10cSrcweir {
3790cdf0e10cSrcweir values.push_back(fVal);
3791cdf0e10cSrcweir fSum += fVal;
3792cdf0e10cSrcweir rValCount++;
3793cdf0e10cSrcweir }
3794cdf0e10cSrcweir while ((nErr == 0) && aValIter.GetNext(fVal, nErr));
3795cdf0e10cSrcweir }
3796cdf0e10cSrcweir }
3797cdf0e10cSrcweir break;
3798cdf0e10cSrcweir case svMatrix :
3799cdf0e10cSrcweir {
3800cdf0e10cSrcweir ScMatrixRef pMat = PopMatrix();
3801cdf0e10cSrcweir if (pMat)
3802cdf0e10cSrcweir {
3803cdf0e10cSrcweir SCSIZE nC, nR;
3804cdf0e10cSrcweir pMat->GetDimensions(nC, nR);
3805cdf0e10cSrcweir for (SCSIZE nMatCol = 0; nMatCol < nC; nMatCol++)
3806cdf0e10cSrcweir {
3807cdf0e10cSrcweir for (SCSIZE nMatRow = 0; nMatRow < nR; nMatRow++)
3808cdf0e10cSrcweir {
3809cdf0e10cSrcweir if (!pMat->IsString(nMatCol,nMatRow))
3810cdf0e10cSrcweir {
3811cdf0e10cSrcweir fVal= pMat->GetDouble(nMatCol,nMatRow);
3812cdf0e10cSrcweir values.push_back(fVal);
3813cdf0e10cSrcweir fSum += fVal;
3814cdf0e10cSrcweir rValCount++;
3815cdf0e10cSrcweir }
3816cdf0e10cSrcweir else if ( bTextAsZero )
3817cdf0e10cSrcweir {
3818cdf0e10cSrcweir values.push_back(0.0);
3819cdf0e10cSrcweir rValCount++;
3820cdf0e10cSrcweir }
3821cdf0e10cSrcweir }
3822cdf0e10cSrcweir }
3823cdf0e10cSrcweir }
3824cdf0e10cSrcweir }
3825cdf0e10cSrcweir break;
3826cdf0e10cSrcweir case svString :
3827cdf0e10cSrcweir {
3828cdf0e10cSrcweir Pop();
3829cdf0e10cSrcweir if ( bTextAsZero )
3830cdf0e10cSrcweir {
3831cdf0e10cSrcweir values.push_back(0.0);
3832cdf0e10cSrcweir rValCount++;
3833cdf0e10cSrcweir }
3834cdf0e10cSrcweir else
3835cdf0e10cSrcweir SetError(errIllegalParameter);
3836cdf0e10cSrcweir }
3837cdf0e10cSrcweir break;
3838cdf0e10cSrcweir default :
3839cdf0e10cSrcweir Pop();
3840cdf0e10cSrcweir SetError(errIllegalParameter);
3841cdf0e10cSrcweir }
3842cdf0e10cSrcweir }
3843cdf0e10cSrcweir
3844cdf0e10cSrcweir ::std::vector<double>::size_type n = values.size();
3845cdf0e10cSrcweir vMean = fSum / n;
3846cdf0e10cSrcweir for (::std::vector<double>::size_type i = 0; i < n; i++)
3847cdf0e10cSrcweir vSum += ::rtl::math::approxSub( values[i], vMean) * ::rtl::math::approxSub( values[i], vMean);
3848cdf0e10cSrcweir rVal = vSum;
3849cdf0e10cSrcweir }
3850cdf0e10cSrcweir
3851cdf0e10cSrcweir
ScVar(sal_Bool bTextAsZero)3852cdf0e10cSrcweir void ScInterpreter::ScVar( sal_Bool bTextAsZero )
3853cdf0e10cSrcweir {
3854cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScVar" );
3855cdf0e10cSrcweir double nVal;
3856cdf0e10cSrcweir double nValCount;
3857cdf0e10cSrcweir GetStVarParams( nVal, nValCount, bTextAsZero );
3858cdf0e10cSrcweir
3859cdf0e10cSrcweir if (nValCount <= 1.0)
3860cdf0e10cSrcweir PushError( errDivisionByZero );
3861cdf0e10cSrcweir else
3862cdf0e10cSrcweir PushDouble( nVal / (nValCount - 1.0));
3863cdf0e10cSrcweir }
3864cdf0e10cSrcweir
3865cdf0e10cSrcweir
ScVarP(sal_Bool bTextAsZero)3866cdf0e10cSrcweir void ScInterpreter::ScVarP( sal_Bool bTextAsZero )
3867cdf0e10cSrcweir {
3868cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScVarP" );
3869cdf0e10cSrcweir double nVal;
3870cdf0e10cSrcweir double nValCount;
3871cdf0e10cSrcweir GetStVarParams( nVal, nValCount, bTextAsZero );
3872cdf0e10cSrcweir
3873cdf0e10cSrcweir PushDouble( div( nVal, nValCount));
3874cdf0e10cSrcweir }
3875cdf0e10cSrcweir
3876cdf0e10cSrcweir
ScStDev(sal_Bool bTextAsZero)3877cdf0e10cSrcweir void ScInterpreter::ScStDev( sal_Bool bTextAsZero )
3878cdf0e10cSrcweir {
3879cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScStDev" );
3880cdf0e10cSrcweir double nVal;
3881cdf0e10cSrcweir double nValCount;
3882cdf0e10cSrcweir GetStVarParams( nVal, nValCount, bTextAsZero );
3883cdf0e10cSrcweir if (nValCount <= 1.0)
3884cdf0e10cSrcweir PushError( errDivisionByZero );
3885cdf0e10cSrcweir else
3886cdf0e10cSrcweir PushDouble( sqrt( nVal / (nValCount - 1.0)));
3887cdf0e10cSrcweir }
3888cdf0e10cSrcweir
3889cdf0e10cSrcweir
ScStDevP(sal_Bool bTextAsZero)3890cdf0e10cSrcweir void ScInterpreter::ScStDevP( sal_Bool bTextAsZero )
3891cdf0e10cSrcweir {
3892cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScStDevP" );
3893cdf0e10cSrcweir double nVal;
3894cdf0e10cSrcweir double nValCount;
3895cdf0e10cSrcweir GetStVarParams( nVal, nValCount, bTextAsZero );
3896cdf0e10cSrcweir if (nValCount == 0.0)
3897cdf0e10cSrcweir PushError( errDivisionByZero );
3898cdf0e10cSrcweir else
3899cdf0e10cSrcweir PushDouble( sqrt( nVal / nValCount));
3900cdf0e10cSrcweir
3901cdf0e10cSrcweir /* this was: PushDouble( sqrt( div( nVal, nValCount)));
3902cdf0e10cSrcweir *
3903cdf0e10cSrcweir * Besides that the special NAN gets lost in the call through sqrt(),
3904cdf0e10cSrcweir * unxlngi6.pro then looped back and forth somewhere between div() and
3905cdf0e10cSrcweir * ::rtl::math::setNan(). Tests showed that
3906cdf0e10cSrcweir *
3907cdf0e10cSrcweir * sqrt( div( 1, 0));
3908cdf0e10cSrcweir *
3909cdf0e10cSrcweir * produced a loop, but
3910cdf0e10cSrcweir *
3911cdf0e10cSrcweir * double f1 = div( 1, 0);
3912cdf0e10cSrcweir * sqrt( f1 );
3913cdf0e10cSrcweir *
3914cdf0e10cSrcweir * was fine. There seems to be some compiler optimization problem. It does
3915cdf0e10cSrcweir * not occur when compiled with debug=t.
3916cdf0e10cSrcweir */
3917cdf0e10cSrcweir }
3918cdf0e10cSrcweir
3919cdf0e10cSrcweir
ScColumns()3920cdf0e10cSrcweir void ScInterpreter::ScColumns()
3921cdf0e10cSrcweir {
3922cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScColumns" );
3923cdf0e10cSrcweir sal_uInt8 nParamCount = GetByte();
3924cdf0e10cSrcweir sal_uLong nVal = 0;
3925cdf0e10cSrcweir SCCOL nCol1;
3926cdf0e10cSrcweir SCROW nRow1;
3927cdf0e10cSrcweir SCTAB nTab1;
3928cdf0e10cSrcweir SCCOL nCol2;
3929cdf0e10cSrcweir SCROW nRow2;
3930cdf0e10cSrcweir SCTAB nTab2;
3931cdf0e10cSrcweir while (nParamCount-- > 0)
3932cdf0e10cSrcweir {
3933cdf0e10cSrcweir switch ( GetStackType() )
3934cdf0e10cSrcweir {
3935cdf0e10cSrcweir case svSingleRef:
3936cdf0e10cSrcweir PopError();
3937cdf0e10cSrcweir nVal++;
3938cdf0e10cSrcweir break;
3939cdf0e10cSrcweir case svDoubleRef:
3940cdf0e10cSrcweir PopDoubleRef(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
3941cdf0e10cSrcweir nVal += static_cast<sal_uLong>(nTab2 - nTab1 + 1) *
3942cdf0e10cSrcweir static_cast<sal_uLong>(nCol2 - nCol1 + 1);
3943cdf0e10cSrcweir break;
3944cdf0e10cSrcweir case svMatrix:
3945cdf0e10cSrcweir {
3946cdf0e10cSrcweir ScMatrixRef pMat = PopMatrix();
3947cdf0e10cSrcweir if (pMat)
3948cdf0e10cSrcweir {
3949cdf0e10cSrcweir SCSIZE nC, nR;
3950cdf0e10cSrcweir pMat->GetDimensions(nC, nR);
3951cdf0e10cSrcweir nVal += nC;
3952cdf0e10cSrcweir }
3953cdf0e10cSrcweir }
3954cdf0e10cSrcweir break;
3955cdf0e10cSrcweir default:
3956cdf0e10cSrcweir PopError();
3957cdf0e10cSrcweir SetError(errIllegalParameter);
3958cdf0e10cSrcweir }
3959cdf0e10cSrcweir }
3960cdf0e10cSrcweir PushDouble((double)nVal);
3961cdf0e10cSrcweir }
3962cdf0e10cSrcweir
3963cdf0e10cSrcweir
ScRows()3964cdf0e10cSrcweir void ScInterpreter::ScRows()
3965cdf0e10cSrcweir {
3966cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScRows" );
3967cdf0e10cSrcweir sal_uInt8 nParamCount = GetByte();
3968cdf0e10cSrcweir sal_uLong nVal = 0;
3969cdf0e10cSrcweir SCCOL nCol1;
3970cdf0e10cSrcweir SCROW nRow1;
3971cdf0e10cSrcweir SCTAB nTab1;
3972cdf0e10cSrcweir SCCOL nCol2;
3973cdf0e10cSrcweir SCROW nRow2;
3974cdf0e10cSrcweir SCTAB nTab2;
3975cdf0e10cSrcweir while (nParamCount-- > 0)
3976cdf0e10cSrcweir {
3977cdf0e10cSrcweir switch ( GetStackType() )
3978cdf0e10cSrcweir {
3979cdf0e10cSrcweir case svSingleRef:
3980cdf0e10cSrcweir PopError();
3981cdf0e10cSrcweir nVal++;
3982cdf0e10cSrcweir break;
3983cdf0e10cSrcweir case svDoubleRef:
3984cdf0e10cSrcweir PopDoubleRef(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
3985cdf0e10cSrcweir nVal += static_cast<sal_uLong>(nTab2 - nTab1 + 1) *
3986cdf0e10cSrcweir static_cast<sal_uLong>(nRow2 - nRow1 + 1);
3987cdf0e10cSrcweir break;
3988cdf0e10cSrcweir case svMatrix:
3989cdf0e10cSrcweir {
3990cdf0e10cSrcweir ScMatrixRef pMat = PopMatrix();
3991cdf0e10cSrcweir if (pMat)
3992cdf0e10cSrcweir {
3993cdf0e10cSrcweir SCSIZE nC, nR;
3994cdf0e10cSrcweir pMat->GetDimensions(nC, nR);
3995cdf0e10cSrcweir nVal += nR;
3996cdf0e10cSrcweir }
3997cdf0e10cSrcweir }
3998cdf0e10cSrcweir break;
3999cdf0e10cSrcweir default:
4000cdf0e10cSrcweir PopError();
4001cdf0e10cSrcweir SetError(errIllegalParameter);
4002cdf0e10cSrcweir }
4003cdf0e10cSrcweir }
4004cdf0e10cSrcweir PushDouble((double)nVal);
4005cdf0e10cSrcweir }
4006cdf0e10cSrcweir
ScTables()4007cdf0e10cSrcweir void ScInterpreter::ScTables()
4008cdf0e10cSrcweir {
4009cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScTables" );
4010cdf0e10cSrcweir sal_uInt8 nParamCount = GetByte();
4011cdf0e10cSrcweir sal_uLong nVal;
4012cdf0e10cSrcweir if ( nParamCount == 0 )
4013cdf0e10cSrcweir nVal = pDok->GetTableCount();
4014cdf0e10cSrcweir else
4015cdf0e10cSrcweir {
4016cdf0e10cSrcweir nVal = 0;
4017cdf0e10cSrcweir SCCOL nCol1;
4018cdf0e10cSrcweir SCROW nRow1;
4019cdf0e10cSrcweir SCTAB nTab1;
4020cdf0e10cSrcweir SCCOL nCol2;
4021cdf0e10cSrcweir SCROW nRow2;
4022cdf0e10cSrcweir SCTAB nTab2;
4023cdf0e10cSrcweir while (nParamCount-- > 0)
4024cdf0e10cSrcweir {
4025cdf0e10cSrcweir switch ( GetStackType() )
4026cdf0e10cSrcweir {
4027cdf0e10cSrcweir case svSingleRef:
4028cdf0e10cSrcweir PopError();
4029cdf0e10cSrcweir nVal++;
4030cdf0e10cSrcweir break;
4031cdf0e10cSrcweir case svDoubleRef:
4032cdf0e10cSrcweir PopDoubleRef(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
4033cdf0e10cSrcweir nVal += static_cast<sal_uLong>(nTab2 - nTab1 + 1);
4034cdf0e10cSrcweir break;
4035cdf0e10cSrcweir case svMatrix:
4036cdf0e10cSrcweir PopError();
4037cdf0e10cSrcweir nVal++;
4038cdf0e10cSrcweir break;
4039cdf0e10cSrcweir default:
4040cdf0e10cSrcweir PopError();
4041cdf0e10cSrcweir SetError( errIllegalParameter );
4042cdf0e10cSrcweir }
4043cdf0e10cSrcweir }
4044cdf0e10cSrcweir }
4045cdf0e10cSrcweir PushDouble( (double) nVal );
4046cdf0e10cSrcweir }
4047cdf0e10cSrcweir
4048cdf0e10cSrcweir
ScColumn()4049cdf0e10cSrcweir void ScInterpreter::ScColumn()
4050cdf0e10cSrcweir {
4051cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScColumn" );
4052cdf0e10cSrcweir sal_uInt8 nParamCount = GetByte();
4053cdf0e10cSrcweir if ( MustHaveParamCount( nParamCount, 0, 1 ) )
4054cdf0e10cSrcweir {
4055cdf0e10cSrcweir double nVal = 0;
4056cdf0e10cSrcweir if (nParamCount == 0)
4057cdf0e10cSrcweir {
4058cdf0e10cSrcweir nVal = aPos.Col() + 1;
4059cdf0e10cSrcweir if (bMatrixFormula)
4060cdf0e10cSrcweir {
4061cdf0e10cSrcweir SCCOL nCols;
4062cdf0e10cSrcweir SCROW nRows;
4063cdf0e10cSrcweir pMyFormulaCell->GetMatColsRows( nCols, nRows);
4064cdf0e10cSrcweir ScMatrixRef pResMat = GetNewMat( static_cast<SCSIZE>(nCols), 1);
4065cdf0e10cSrcweir if (pResMat)
4066cdf0e10cSrcweir {
4067cdf0e10cSrcweir for (SCCOL i=0; i < nCols; ++i)
4068cdf0e10cSrcweir pResMat->PutDouble( nVal + i, static_cast<SCSIZE>(i), 0);
4069cdf0e10cSrcweir PushMatrix( pResMat);
4070cdf0e10cSrcweir return;
4071cdf0e10cSrcweir }
4072cdf0e10cSrcweir }
4073cdf0e10cSrcweir }
4074cdf0e10cSrcweir else
4075cdf0e10cSrcweir {
4076cdf0e10cSrcweir switch ( GetStackType() )
4077cdf0e10cSrcweir {
4078cdf0e10cSrcweir case svSingleRef :
4079cdf0e10cSrcweir {
4080cdf0e10cSrcweir SCCOL nCol1;
4081cdf0e10cSrcweir SCROW nRow1;
4082cdf0e10cSrcweir SCTAB nTab1;
4083cdf0e10cSrcweir PopSingleRef( nCol1, nRow1, nTab1 );
4084cdf0e10cSrcweir nVal = (double) (nCol1 + 1);
4085cdf0e10cSrcweir }
4086cdf0e10cSrcweir break;
4087cdf0e10cSrcweir case svDoubleRef :
4088cdf0e10cSrcweir {
4089cdf0e10cSrcweir SCCOL nCol1;
4090cdf0e10cSrcweir SCROW nRow1;
4091cdf0e10cSrcweir SCTAB nTab1;
4092cdf0e10cSrcweir SCCOL nCol2;
4093cdf0e10cSrcweir SCROW nRow2;
4094cdf0e10cSrcweir SCTAB nTab2;
4095cdf0e10cSrcweir PopDoubleRef( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 );
4096cdf0e10cSrcweir if (nCol2 > nCol1)
4097cdf0e10cSrcweir {
4098cdf0e10cSrcweir ScMatrixRef pResMat = GetNewMat(
4099cdf0e10cSrcweir static_cast<SCSIZE>(nCol2-nCol1+1), 1);
4100cdf0e10cSrcweir if (pResMat)
4101cdf0e10cSrcweir {
4102cdf0e10cSrcweir for (SCCOL i = nCol1; i <= nCol2; i++)
4103cdf0e10cSrcweir pResMat->PutDouble((double)(i+1),
4104cdf0e10cSrcweir static_cast<SCSIZE>(i-nCol1), 0);
4105cdf0e10cSrcweir PushMatrix(pResMat);
4106cdf0e10cSrcweir return;
4107cdf0e10cSrcweir }
4108cdf0e10cSrcweir else
4109cdf0e10cSrcweir nVal = 0.0;
4110cdf0e10cSrcweir }
4111cdf0e10cSrcweir else
4112cdf0e10cSrcweir nVal = (double) (nCol1 + 1);
4113cdf0e10cSrcweir }
4114cdf0e10cSrcweir break;
4115cdf0e10cSrcweir default:
4116cdf0e10cSrcweir SetError( errIllegalParameter );
4117cdf0e10cSrcweir nVal = 0.0;
4118cdf0e10cSrcweir }
4119cdf0e10cSrcweir }
4120cdf0e10cSrcweir PushDouble( nVal );
4121cdf0e10cSrcweir }
4122cdf0e10cSrcweir }
4123cdf0e10cSrcweir
4124cdf0e10cSrcweir
ScRow()4125cdf0e10cSrcweir void ScInterpreter::ScRow()
4126cdf0e10cSrcweir {
4127cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScRow" );
4128cdf0e10cSrcweir sal_uInt8 nParamCount = GetByte();
4129cdf0e10cSrcweir if ( MustHaveParamCount( nParamCount, 0, 1 ) )
4130cdf0e10cSrcweir {
4131cdf0e10cSrcweir double nVal = 0;
4132cdf0e10cSrcweir if (nParamCount == 0)
4133cdf0e10cSrcweir {
4134cdf0e10cSrcweir nVal = aPos.Row() + 1;
4135cdf0e10cSrcweir if (bMatrixFormula)
4136cdf0e10cSrcweir {
4137cdf0e10cSrcweir SCCOL nCols;
4138cdf0e10cSrcweir SCROW nRows;
4139cdf0e10cSrcweir pMyFormulaCell->GetMatColsRows( nCols, nRows);
4140cdf0e10cSrcweir ScMatrixRef pResMat = GetNewMat( 1, static_cast<SCSIZE>(nRows));
4141cdf0e10cSrcweir if (pResMat)
4142cdf0e10cSrcweir {
4143cdf0e10cSrcweir for (SCROW i=0; i < nRows; i++)
4144cdf0e10cSrcweir pResMat->PutDouble( nVal + i, 0, static_cast<SCSIZE>(i));
4145cdf0e10cSrcweir PushMatrix( pResMat);
4146cdf0e10cSrcweir return;
4147cdf0e10cSrcweir }
4148cdf0e10cSrcweir }
4149cdf0e10cSrcweir }
4150cdf0e10cSrcweir else
4151cdf0e10cSrcweir {
4152cdf0e10cSrcweir switch ( GetStackType() )
4153cdf0e10cSrcweir {
4154cdf0e10cSrcweir case svSingleRef :
4155cdf0e10cSrcweir {
4156cdf0e10cSrcweir SCCOL nCol1;
4157cdf0e10cSrcweir SCROW nRow1;
4158cdf0e10cSrcweir SCTAB nTab1;
4159cdf0e10cSrcweir PopSingleRef( nCol1, nRow1, nTab1 );
4160cdf0e10cSrcweir nVal = (double) (nRow1 + 1);
4161cdf0e10cSrcweir }
4162cdf0e10cSrcweir break;
4163cdf0e10cSrcweir case svDoubleRef :
4164cdf0e10cSrcweir {
4165cdf0e10cSrcweir SCCOL nCol1;
4166cdf0e10cSrcweir SCROW nRow1;
4167cdf0e10cSrcweir SCTAB nTab1;
4168cdf0e10cSrcweir SCCOL nCol2;
4169cdf0e10cSrcweir SCROW nRow2;
4170cdf0e10cSrcweir SCTAB nTab2;
4171cdf0e10cSrcweir PopDoubleRef( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 );
4172cdf0e10cSrcweir if (nRow2 > nRow1)
4173cdf0e10cSrcweir {
4174cdf0e10cSrcweir ScMatrixRef pResMat = GetNewMat( 1,
4175cdf0e10cSrcweir static_cast<SCSIZE>(nRow2-nRow1+1));
4176cdf0e10cSrcweir if (pResMat)
4177cdf0e10cSrcweir {
4178cdf0e10cSrcweir for (SCROW i = nRow1; i <= nRow2; i++)
4179cdf0e10cSrcweir pResMat->PutDouble((double)(i+1), 0,
4180cdf0e10cSrcweir static_cast<SCSIZE>(i-nRow1));
4181cdf0e10cSrcweir PushMatrix(pResMat);
4182cdf0e10cSrcweir return;
4183cdf0e10cSrcweir }
4184cdf0e10cSrcweir else
4185cdf0e10cSrcweir nVal = 0.0;
4186cdf0e10cSrcweir }
4187cdf0e10cSrcweir else
4188cdf0e10cSrcweir nVal = (double) (nRow1 + 1);
4189cdf0e10cSrcweir }
4190cdf0e10cSrcweir break;
4191cdf0e10cSrcweir default:
4192cdf0e10cSrcweir SetError( errIllegalParameter );
4193cdf0e10cSrcweir nVal = 0.0;
4194cdf0e10cSrcweir }
4195cdf0e10cSrcweir }
4196cdf0e10cSrcweir PushDouble( nVal );
4197cdf0e10cSrcweir }
4198cdf0e10cSrcweir }
4199cdf0e10cSrcweir
ScTable()4200cdf0e10cSrcweir void ScInterpreter::ScTable()
4201cdf0e10cSrcweir {
4202cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScTable" );
4203cdf0e10cSrcweir sal_uInt8 nParamCount = GetByte();
4204cdf0e10cSrcweir if ( MustHaveParamCount( nParamCount, 0, 1 ) )
4205cdf0e10cSrcweir {
4206cdf0e10cSrcweir SCTAB nVal = 0;
4207cdf0e10cSrcweir if ( nParamCount == 0 )
4208cdf0e10cSrcweir nVal = aPos.Tab() + 1;
4209cdf0e10cSrcweir else
4210cdf0e10cSrcweir {
4211cdf0e10cSrcweir switch ( GetStackType() )
4212cdf0e10cSrcweir {
4213cdf0e10cSrcweir case svString :
4214cdf0e10cSrcweir {
4215cdf0e10cSrcweir String aStr( PopString() );
4216cdf0e10cSrcweir if ( pDok->GetTable( aStr, nVal ) )
4217cdf0e10cSrcweir ++nVal;
4218cdf0e10cSrcweir else
4219cdf0e10cSrcweir SetError( errIllegalArgument );
4220cdf0e10cSrcweir }
4221cdf0e10cSrcweir break;
4222cdf0e10cSrcweir case svSingleRef :
4223cdf0e10cSrcweir {
4224cdf0e10cSrcweir SCCOL nCol1;
4225cdf0e10cSrcweir SCROW nRow1;
4226cdf0e10cSrcweir SCTAB nTab1;
4227cdf0e10cSrcweir PopSingleRef( nCol1, nRow1, nTab1 );
4228cdf0e10cSrcweir nVal = nTab1 + 1;
4229cdf0e10cSrcweir }
4230cdf0e10cSrcweir break;
4231cdf0e10cSrcweir case svDoubleRef :
4232cdf0e10cSrcweir {
4233cdf0e10cSrcweir SCCOL nCol1;
4234cdf0e10cSrcweir SCROW nRow1;
4235cdf0e10cSrcweir SCTAB nTab1;
4236cdf0e10cSrcweir SCCOL nCol2;
4237cdf0e10cSrcweir SCROW nRow2;
4238cdf0e10cSrcweir SCTAB nTab2;
4239cdf0e10cSrcweir PopDoubleRef( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 );
4240cdf0e10cSrcweir nVal = nTab1 + 1;
4241cdf0e10cSrcweir }
4242cdf0e10cSrcweir break;
4243cdf0e10cSrcweir default:
4244cdf0e10cSrcweir SetError( errIllegalParameter );
4245cdf0e10cSrcweir }
4246cdf0e10cSrcweir if ( nGlobalError )
4247cdf0e10cSrcweir nVal = 0;
4248cdf0e10cSrcweir }
4249cdf0e10cSrcweir PushDouble( (double) nVal );
4250cdf0e10cSrcweir }
4251cdf0e10cSrcweir }
4252cdf0e10cSrcweir
4253cdf0e10cSrcweir /** returns -1 when the matrix value is smaller than the query value, 0 when
4254cdf0e10cSrcweir they are equal, and 1 when the matrix value is larger than the query
4255cdf0e10cSrcweir value. */
lcl_CompareMatrix2Query(SCSIZE i,const ScMatrix & rMat,const ScQueryEntry & rEntry)4256cdf0e10cSrcweir static sal_Int32 lcl_CompareMatrix2Query( SCSIZE i, const ScMatrix& rMat,
4257cdf0e10cSrcweir const ScQueryEntry& rEntry)
4258cdf0e10cSrcweir {
4259cdf0e10cSrcweir if (rMat.IsEmpty(i))
4260cdf0e10cSrcweir {
4261cdf0e10cSrcweir /* TODO: in case we introduced query for real empty this would have to
4262cdf0e10cSrcweir * be changed! */
4263cdf0e10cSrcweir return -1; // empty always less than anything else
4264cdf0e10cSrcweir }
4265cdf0e10cSrcweir
4266cdf0e10cSrcweir /* FIXME: what is an empty path (result of IF(false;true_path) in
4267cdf0e10cSrcweir * comparisons? */
4268cdf0e10cSrcweir
4269cdf0e10cSrcweir if (rMat.IsValue(i))
4270cdf0e10cSrcweir {
4271cdf0e10cSrcweir if (rEntry.bQueryByString)
4272cdf0e10cSrcweir return -1; // numeric always less than string
4273cdf0e10cSrcweir
4274cdf0e10cSrcweir const double nVal1 = rMat.GetDouble(i);
4275cdf0e10cSrcweir const double nVal2 = rEntry.nVal;
4276cdf0e10cSrcweir if (nVal1 == nVal2)
4277cdf0e10cSrcweir return 0;
4278cdf0e10cSrcweir
4279cdf0e10cSrcweir return nVal1 < nVal2 ? -1 : 1;
4280cdf0e10cSrcweir }
4281cdf0e10cSrcweir
4282cdf0e10cSrcweir if (!rEntry.bQueryByString)
4283cdf0e10cSrcweir return 1; // string always greater than numeric
4284cdf0e10cSrcweir
4285cdf0e10cSrcweir if (!rEntry.pStr)
4286cdf0e10cSrcweir // this should not happen!
4287cdf0e10cSrcweir return 1;
4288cdf0e10cSrcweir
4289cdf0e10cSrcweir const String& rStr1 = rMat.GetString(i);
4290cdf0e10cSrcweir const String& rStr2 = *rEntry.pStr;
4291cdf0e10cSrcweir
4292cdf0e10cSrcweir return ScGlobal::GetCollator()->compareString( rStr1, rStr2); // case-insensitive
4293cdf0e10cSrcweir }
4294cdf0e10cSrcweir
4295cdf0e10cSrcweir /** returns the last item with the identical value as the original item
4296cdf0e10cSrcweir value. */
lcl_GetLastMatch(SCSIZE & rIndex,const ScMatrix & rMat,SCSIZE nMatCount,bool bReverse)4297cdf0e10cSrcweir static void lcl_GetLastMatch( SCSIZE& rIndex, const ScMatrix& rMat,
4298cdf0e10cSrcweir SCSIZE nMatCount, bool bReverse)
4299cdf0e10cSrcweir {
4300cdf0e10cSrcweir if (rMat.IsValue(rIndex))
4301cdf0e10cSrcweir {
4302cdf0e10cSrcweir double nVal = rMat.GetDouble(rIndex);
4303cdf0e10cSrcweir if (bReverse)
4304cdf0e10cSrcweir while (rIndex > 0 && rMat.IsValue(rIndex-1) &&
4305cdf0e10cSrcweir nVal == rMat.GetDouble(rIndex-1))
4306cdf0e10cSrcweir --rIndex;
4307cdf0e10cSrcweir else
4308cdf0e10cSrcweir while (rIndex < nMatCount-1 && rMat.IsValue(rIndex+1) &&
4309cdf0e10cSrcweir nVal == rMat.GetDouble(rIndex+1))
4310cdf0e10cSrcweir ++rIndex;
4311cdf0e10cSrcweir }
4312cdf0e10cSrcweir //! Order of IsEmptyPath, IsEmpty, IsString is significant!
4313cdf0e10cSrcweir else if (rMat.IsEmptyPath(rIndex))
4314cdf0e10cSrcweir {
4315cdf0e10cSrcweir if (bReverse)
4316cdf0e10cSrcweir while (rIndex > 0 && rMat.IsEmptyPath(rIndex-1))
4317cdf0e10cSrcweir --rIndex;
4318cdf0e10cSrcweir else
4319cdf0e10cSrcweir while (rIndex < nMatCount-1 && rMat.IsEmptyPath(rIndex+1))
4320cdf0e10cSrcweir ++rIndex;
4321cdf0e10cSrcweir }
4322cdf0e10cSrcweir else if (rMat.IsEmpty(rIndex))
4323cdf0e10cSrcweir {
4324cdf0e10cSrcweir if (bReverse)
4325cdf0e10cSrcweir while (rIndex > 0 && rMat.IsEmpty(rIndex-1))
4326cdf0e10cSrcweir --rIndex;
4327cdf0e10cSrcweir else
4328cdf0e10cSrcweir while (rIndex < nMatCount-1 && rMat.IsEmpty(rIndex+1))
4329cdf0e10cSrcweir ++rIndex;
4330cdf0e10cSrcweir }
4331cdf0e10cSrcweir else if (rMat.IsString(rIndex))
4332cdf0e10cSrcweir {
4333cdf0e10cSrcweir String aStr( rMat.GetString(rIndex));
4334cdf0e10cSrcweir if (bReverse)
4335cdf0e10cSrcweir while (rIndex > 0 && rMat.IsString(rIndex-1) &&
4336cdf0e10cSrcweir aStr == rMat.GetString(rIndex-1))
4337cdf0e10cSrcweir --rIndex;
4338cdf0e10cSrcweir else
4339cdf0e10cSrcweir while (rIndex < nMatCount-1 && rMat.IsString(rIndex+1) &&
4340cdf0e10cSrcweir aStr == rMat.GetString(rIndex+1))
4341cdf0e10cSrcweir ++rIndex;
4342cdf0e10cSrcweir }
4343cdf0e10cSrcweir else
4344cdf0e10cSrcweir {
4345cdf0e10cSrcweir DBG_ERRORFILE("lcl_GetLastMatch: unhandled matrix type");
4346cdf0e10cSrcweir }
4347cdf0e10cSrcweir }
4348cdf0e10cSrcweir
ScMatch()4349cdf0e10cSrcweir void ScInterpreter::ScMatch()
4350cdf0e10cSrcweir {
4351cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScMatch" );
4352cdf0e10cSrcweir ScMatrixRef pMatSrc = NULL;
4353cdf0e10cSrcweir
4354cdf0e10cSrcweir sal_uInt8 nParamCount = GetByte();
4355cdf0e10cSrcweir if ( MustHaveParamCount( nParamCount, 2, 3 ) )
4356cdf0e10cSrcweir {
4357cdf0e10cSrcweir double fTyp;
4358cdf0e10cSrcweir if (nParamCount == 3)
4359cdf0e10cSrcweir fTyp = GetDouble();
4360cdf0e10cSrcweir else
4361cdf0e10cSrcweir fTyp = 1.0;
4362cdf0e10cSrcweir SCCOL nCol1 = 0;
4363cdf0e10cSrcweir SCROW nRow1 = 0;
4364cdf0e10cSrcweir SCTAB nTab1 = 0;
4365cdf0e10cSrcweir SCCOL nCol2 = 0;
4366cdf0e10cSrcweir SCROW nRow2 = 0;
4367cdf0e10cSrcweir SCTAB nTab2 = 0;
4368cdf0e10cSrcweir if (GetStackType() == svDoubleRef)
4369cdf0e10cSrcweir {
4370cdf0e10cSrcweir PopDoubleRef(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
4371cdf0e10cSrcweir if (nTab1 != nTab2 || (nCol1 != nCol2 && nRow1 != nRow2))
4372cdf0e10cSrcweir {
4373cdf0e10cSrcweir PushIllegalParameter();
4374cdf0e10cSrcweir return;
4375cdf0e10cSrcweir }
4376cdf0e10cSrcweir }
4377cdf0e10cSrcweir else if (GetStackType() == svMatrix)
4378cdf0e10cSrcweir {
4379cdf0e10cSrcweir pMatSrc = PopMatrix();
4380cdf0e10cSrcweir if (!pMatSrc)
4381cdf0e10cSrcweir {
4382cdf0e10cSrcweir PushIllegalParameter();
4383cdf0e10cSrcweir return;
4384cdf0e10cSrcweir }
4385cdf0e10cSrcweir }
4386cdf0e10cSrcweir else
4387cdf0e10cSrcweir {
4388cdf0e10cSrcweir PushIllegalParameter();
4389cdf0e10cSrcweir return;
4390cdf0e10cSrcweir }
4391cdf0e10cSrcweir if (nGlobalError == 0)
4392cdf0e10cSrcweir {
4393cdf0e10cSrcweir double fVal;
4394cdf0e10cSrcweir String sStr;
4395cdf0e10cSrcweir ScQueryParam rParam;
4396cdf0e10cSrcweir rParam.nCol1 = nCol1;
4397cdf0e10cSrcweir rParam.nRow1 = nRow1;
4398cdf0e10cSrcweir rParam.nCol2 = nCol2;
4399cdf0e10cSrcweir rParam.nTab = nTab1;
4400cdf0e10cSrcweir rParam.bMixedComparison = sal_True;
4401cdf0e10cSrcweir
4402cdf0e10cSrcweir ScQueryEntry& rEntry = rParam.GetEntry(0);
4403cdf0e10cSrcweir rEntry.bDoQuery = sal_True;
4404cdf0e10cSrcweir if (fTyp < 0.0)
4405cdf0e10cSrcweir rEntry.eOp = SC_GREATER_EQUAL;
4406cdf0e10cSrcweir else if (fTyp > 0.0)
4407cdf0e10cSrcweir rEntry.eOp = SC_LESS_EQUAL;
4408cdf0e10cSrcweir switch ( GetStackType() )
4409cdf0e10cSrcweir {
4410cdf0e10cSrcweir case svDouble:
4411cdf0e10cSrcweir {
4412cdf0e10cSrcweir fVal = GetDouble();
4413cdf0e10cSrcweir rEntry.bQueryByString = sal_False;
4414cdf0e10cSrcweir rEntry.nVal = fVal;
4415cdf0e10cSrcweir }
4416cdf0e10cSrcweir break;
4417cdf0e10cSrcweir case svString:
4418cdf0e10cSrcweir {
4419cdf0e10cSrcweir sStr = GetString();
4420cdf0e10cSrcweir rEntry.bQueryByString = sal_True;
4421cdf0e10cSrcweir *rEntry.pStr = sStr;
4422cdf0e10cSrcweir }
4423cdf0e10cSrcweir break;
4424cdf0e10cSrcweir case svDoubleRef :
4425cdf0e10cSrcweir case svSingleRef :
4426cdf0e10cSrcweir {
4427cdf0e10cSrcweir ScAddress aAdr;
4428cdf0e10cSrcweir if ( !PopDoubleRefOrSingleRef( aAdr ) )
4429cdf0e10cSrcweir {
4430cdf0e10cSrcweir PushInt(0);
4431cdf0e10cSrcweir return ;
4432cdf0e10cSrcweir }
4433cdf0e10cSrcweir ScBaseCell* pCell = GetCell( aAdr );
4434cdf0e10cSrcweir if (HasCellValueData(pCell))
4435cdf0e10cSrcweir {
4436cdf0e10cSrcweir fVal = GetCellValue( aAdr, pCell );
4437cdf0e10cSrcweir rEntry.bQueryByString = sal_False;
4438cdf0e10cSrcweir rEntry.nVal = fVal;
4439cdf0e10cSrcweir }
4440cdf0e10cSrcweir else
4441cdf0e10cSrcweir {
4442cdf0e10cSrcweir GetCellString(sStr, pCell);
4443cdf0e10cSrcweir rEntry.bQueryByString = sal_True;
4444cdf0e10cSrcweir *rEntry.pStr = sStr;
4445cdf0e10cSrcweir }
4446cdf0e10cSrcweir }
4447cdf0e10cSrcweir break;
4448cdf0e10cSrcweir case svMatrix :
4449cdf0e10cSrcweir {
4450cdf0e10cSrcweir ScMatValType nType = GetDoubleOrStringFromMatrix(
4451cdf0e10cSrcweir rEntry.nVal, *rEntry.pStr);
4452cdf0e10cSrcweir rEntry.bQueryByString = ScMatrix::IsNonValueType( nType);
4453cdf0e10cSrcweir }
4454cdf0e10cSrcweir break;
4455cdf0e10cSrcweir default:
4456cdf0e10cSrcweir {
4457cdf0e10cSrcweir PushIllegalParameter();
4458cdf0e10cSrcweir return;
4459cdf0e10cSrcweir }
4460cdf0e10cSrcweir }
4461cdf0e10cSrcweir if ( rEntry.bQueryByString )
4462cdf0e10cSrcweir rParam.bRegExp = MayBeRegExp( *rEntry.pStr, pDok );
4463cdf0e10cSrcweir
4464cdf0e10cSrcweir if (pMatSrc) // The source data is matrix array.
4465cdf0e10cSrcweir {
4466cdf0e10cSrcweir SCSIZE nC, nR;
4467cdf0e10cSrcweir pMatSrc->GetDimensions( nC, nR);
4468cdf0e10cSrcweir if (nC > 1 && nR > 1)
4469cdf0e10cSrcweir {
4470cdf0e10cSrcweir // The source matrix must be a vector.
4471cdf0e10cSrcweir PushIllegalParameter();
4472cdf0e10cSrcweir return;
4473cdf0e10cSrcweir }
4474cdf0e10cSrcweir SCSIZE nMatCount = (nC == 1) ? nR : nC;
4475cdf0e10cSrcweir
4476cdf0e10cSrcweir // simple serial search for equality mode (source data doesn't
4477cdf0e10cSrcweir // need to be sorted).
4478cdf0e10cSrcweir
4479cdf0e10cSrcweir if (rEntry.eOp == SC_EQUAL)
4480cdf0e10cSrcweir {
4481cdf0e10cSrcweir for (SCSIZE i = 0; i < nMatCount; ++i)
4482cdf0e10cSrcweir {
4483cdf0e10cSrcweir if (lcl_CompareMatrix2Query( i, *pMatSrc, rEntry) == 0)
4484cdf0e10cSrcweir {
4485cdf0e10cSrcweir PushDouble(i+1); // found !
4486cdf0e10cSrcweir return;
4487cdf0e10cSrcweir }
4488cdf0e10cSrcweir }
4489cdf0e10cSrcweir PushNA(); // not found
4490cdf0e10cSrcweir return;
4491cdf0e10cSrcweir }
4492cdf0e10cSrcweir
4493cdf0e10cSrcweir // binary search for non-equality mode (the source data is
4494cdf0e10cSrcweir // assumed to be sorted).
4495cdf0e10cSrcweir
4496cdf0e10cSrcweir bool bAscOrder = (rEntry.eOp == SC_LESS_EQUAL);
4497cdf0e10cSrcweir SCSIZE nFirst = 0, nLast = nMatCount-1, nHitIndex = 0;
4498cdf0e10cSrcweir for (SCSIZE nLen = nLast-nFirst; nLen > 0; nLen = nLast-nFirst)
4499cdf0e10cSrcweir {
4500cdf0e10cSrcweir SCSIZE nMid = nFirst + nLen/2;
4501cdf0e10cSrcweir sal_Int32 nCmp = lcl_CompareMatrix2Query( nMid, *pMatSrc, rEntry);
4502cdf0e10cSrcweir if (nCmp == 0)
4503cdf0e10cSrcweir {
4504cdf0e10cSrcweir // exact match. find the last item with the same value.
4505cdf0e10cSrcweir lcl_GetLastMatch( nMid, *pMatSrc, nMatCount, !bAscOrder);
4506cdf0e10cSrcweir PushDouble( nMid+1);
4507cdf0e10cSrcweir return;
4508cdf0e10cSrcweir }
4509cdf0e10cSrcweir
4510cdf0e10cSrcweir if (nLen == 1) // first and last items are next to each other.
4511cdf0e10cSrcweir {
4512cdf0e10cSrcweir if (nCmp < 0)
4513cdf0e10cSrcweir nHitIndex = bAscOrder ? nLast : nFirst;
4514cdf0e10cSrcweir else
4515cdf0e10cSrcweir nHitIndex = bAscOrder ? nFirst : nLast;
4516cdf0e10cSrcweir break;
4517cdf0e10cSrcweir }
4518cdf0e10cSrcweir
4519cdf0e10cSrcweir if (nCmp < 0)
4520cdf0e10cSrcweir {
4521cdf0e10cSrcweir if (bAscOrder)
4522cdf0e10cSrcweir nFirst = nMid;
4523cdf0e10cSrcweir else
4524cdf0e10cSrcweir nLast = nMid;
4525cdf0e10cSrcweir }
4526cdf0e10cSrcweir else
4527cdf0e10cSrcweir {
4528cdf0e10cSrcweir if (bAscOrder)
4529cdf0e10cSrcweir nLast = nMid;
4530cdf0e10cSrcweir else
4531cdf0e10cSrcweir nFirst = nMid;
4532cdf0e10cSrcweir }
4533cdf0e10cSrcweir }
4534cdf0e10cSrcweir
4535cdf0e10cSrcweir if (nHitIndex == nMatCount-1) // last item
4536cdf0e10cSrcweir {
4537cdf0e10cSrcweir sal_Int32 nCmp = lcl_CompareMatrix2Query( nHitIndex, *pMatSrc, rEntry);
4538cdf0e10cSrcweir if ((bAscOrder && nCmp <= 0) || (!bAscOrder && nCmp >= 0))
4539cdf0e10cSrcweir {
4540cdf0e10cSrcweir // either the last item is an exact match or the real
4541cdf0e10cSrcweir // hit is beyond the last item.
4542cdf0e10cSrcweir PushDouble( nHitIndex+1);
4543cdf0e10cSrcweir return;
4544cdf0e10cSrcweir }
4545cdf0e10cSrcweir }
4546cdf0e10cSrcweir
4547cdf0e10cSrcweir if (nHitIndex > 0) // valid hit must be 2nd item or higher
4548cdf0e10cSrcweir {
4549cdf0e10cSrcweir PushDouble( nHitIndex); // non-exact match
4550cdf0e10cSrcweir return;
4551cdf0e10cSrcweir }
4552cdf0e10cSrcweir
4553cdf0e10cSrcweir PushNA();
4554cdf0e10cSrcweir return;
4555cdf0e10cSrcweir }
4556cdf0e10cSrcweir
4557cdf0e10cSrcweir SCCOLROW nDelta = 0;
4558cdf0e10cSrcweir if (nCol1 == nCol2)
4559cdf0e10cSrcweir { // search row in column
4560cdf0e10cSrcweir rParam.nRow2 = nRow2;
4561cdf0e10cSrcweir rEntry.nField = nCol1;
4562cdf0e10cSrcweir ScAddress aResultPos( nCol1, nRow1, nTab1);
4563cdf0e10cSrcweir if (!LookupQueryWithCache( aResultPos, rParam))
4564cdf0e10cSrcweir {
4565cdf0e10cSrcweir PushNA();
4566cdf0e10cSrcweir return;
4567cdf0e10cSrcweir }
4568cdf0e10cSrcweir nDelta = aResultPos.Row() - nRow1;
4569cdf0e10cSrcweir }
4570cdf0e10cSrcweir else
4571cdf0e10cSrcweir { // search column in row
4572cdf0e10cSrcweir SCCOL nC;
4573cdf0e10cSrcweir rParam.bByRow = sal_False;
4574cdf0e10cSrcweir rParam.nRow2 = nRow1;
4575cdf0e10cSrcweir rEntry.nField = nCol1;
4576cdf0e10cSrcweir ScQueryCellIterator aCellIter(pDok, nTab1, rParam, sal_False);
4577cdf0e10cSrcweir // Advance Entry.nField in Iterator if column changed
4578cdf0e10cSrcweir aCellIter.SetAdvanceQueryParamEntryField( sal_True );
4579cdf0e10cSrcweir if (fTyp == 0.0)
4580cdf0e10cSrcweir { // EQUAL
4581cdf0e10cSrcweir if ( aCellIter.GetFirst() )
4582cdf0e10cSrcweir nC = aCellIter.GetCol();
4583cdf0e10cSrcweir else
4584cdf0e10cSrcweir {
4585cdf0e10cSrcweir PushNA();
4586cdf0e10cSrcweir return;
4587cdf0e10cSrcweir }
4588cdf0e10cSrcweir }
4589cdf0e10cSrcweir else
4590cdf0e10cSrcweir { // <= or >=
4591cdf0e10cSrcweir SCROW nR;
4592cdf0e10cSrcweir if ( !aCellIter.FindEqualOrSortedLastInRange( nC, nR ) )
4593cdf0e10cSrcweir {
4594cdf0e10cSrcweir PushNA();
4595cdf0e10cSrcweir return;
4596cdf0e10cSrcweir }
4597cdf0e10cSrcweir }
4598cdf0e10cSrcweir nDelta = nC - nCol1;
4599cdf0e10cSrcweir }
4600cdf0e10cSrcweir PushDouble((double) (nDelta + 1));
4601cdf0e10cSrcweir }
4602cdf0e10cSrcweir else
4603cdf0e10cSrcweir PushIllegalParameter();
4604cdf0e10cSrcweir }
4605cdf0e10cSrcweir }
4606cdf0e10cSrcweir
4607cdf0e10cSrcweir
ScCountEmptyCells()4608cdf0e10cSrcweir void ScInterpreter::ScCountEmptyCells()
4609cdf0e10cSrcweir {
4610cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScCountEmptyCells" );
4611cdf0e10cSrcweir if ( MustHaveParamCount( GetByte(), 1 ) )
4612cdf0e10cSrcweir {
4613cdf0e10cSrcweir sal_uLong nMaxCount = 0, nCount = 0;
4614cdf0e10cSrcweir CellType eCellType;
4615cdf0e10cSrcweir switch (GetStackType())
4616cdf0e10cSrcweir {
4617cdf0e10cSrcweir case svSingleRef :
4618cdf0e10cSrcweir {
4619cdf0e10cSrcweir nMaxCount = 1;
4620cdf0e10cSrcweir ScAddress aAdr;
4621cdf0e10cSrcweir PopSingleRef( aAdr );
4622cdf0e10cSrcweir eCellType = GetCellType( GetCell( aAdr ) );
4623cdf0e10cSrcweir if (eCellType != CELLTYPE_NONE && eCellType != CELLTYPE_NOTE)
4624cdf0e10cSrcweir nCount = 1;
4625cdf0e10cSrcweir }
4626cdf0e10cSrcweir break;
4627cdf0e10cSrcweir case svDoubleRef :
4628cdf0e10cSrcweir case svRefList :
4629cdf0e10cSrcweir {
4630cdf0e10cSrcweir ScRange aRange;
4631cdf0e10cSrcweir short nParam = 1;
4632cdf0e10cSrcweir size_t nRefInList = 0;
4633cdf0e10cSrcweir while (nParam-- > 0)
4634cdf0e10cSrcweir {
4635cdf0e10cSrcweir PopDoubleRef( aRange, nParam, nRefInList);
4636cdf0e10cSrcweir nMaxCount +=
4637cdf0e10cSrcweir static_cast<sal_uLong>(aRange.aEnd.Row() - aRange.aStart.Row() + 1) *
4638cdf0e10cSrcweir static_cast<sal_uLong>(aRange.aEnd.Col() - aRange.aStart.Col() + 1) *
4639cdf0e10cSrcweir static_cast<sal_uLong>(aRange.aEnd.Tab() - aRange.aStart.Tab() + 1);
4640cdf0e10cSrcweir ScBaseCell* pCell;
4641cdf0e10cSrcweir ScCellIterator aDocIter( pDok, aRange, glSubTotal);
4642cdf0e10cSrcweir if ( (pCell = aDocIter.GetFirst()) != NULL )
4643cdf0e10cSrcweir {
4644cdf0e10cSrcweir do
4645cdf0e10cSrcweir {
4646cdf0e10cSrcweir if ((eCellType = pCell->GetCellType()) != CELLTYPE_NONE
4647cdf0e10cSrcweir && eCellType != CELLTYPE_NOTE)
4648cdf0e10cSrcweir nCount++;
4649cdf0e10cSrcweir } while ( (pCell = aDocIter.GetNext()) != NULL );
4650cdf0e10cSrcweir }
4651cdf0e10cSrcweir }
4652cdf0e10cSrcweir }
4653cdf0e10cSrcweir break;
4654cdf0e10cSrcweir default : SetError(errIllegalParameter); break;
4655cdf0e10cSrcweir }
4656cdf0e10cSrcweir PushDouble(nMaxCount - nCount);
4657cdf0e10cSrcweir }
4658cdf0e10cSrcweir }
4659cdf0e10cSrcweir
4660cdf0e10cSrcweir
IterateParametersIf(ScIterFuncIf eFunc)4661f53782ebSAndrew Rist double ScInterpreter::IterateParametersIf( ScIterFuncIf eFunc )
4662f53782ebSAndrew Rist {
4663f53782ebSAndrew Rist sal_uInt8 nParamCount = GetByte();
4664f53782ebSAndrew Rist if ( MustHaveParamCount( nParamCount, 2, 3 ) )
4665f53782ebSAndrew Rist {
4666f53782ebSAndrew Rist SCCOL nCol3 = 0;
4667f53782ebSAndrew Rist SCROW nRow3 = 0;
4668f53782ebSAndrew Rist SCTAB nTab3 = 0;
4669f53782ebSAndrew Rist
4670f53782ebSAndrew Rist ScMatrixRef pSumExtraMatrix;
4671f53782ebSAndrew Rist bool bSumExtraRange = (nParamCount == 3);
4672f53782ebSAndrew Rist if (bSumExtraRange)
4673f53782ebSAndrew Rist {
4674f53782ebSAndrew Rist // Save only the upperleft cell in case of cell range. The geometry
4675f53782ebSAndrew Rist // of the 3rd parameter is taken from the 1st parameter.
4676f53782ebSAndrew Rist
4677f53782ebSAndrew Rist switch ( GetStackType() )
4678f53782ebSAndrew Rist {
4679f53782ebSAndrew Rist case svDoubleRef :
4680f53782ebSAndrew Rist {
4681f53782ebSAndrew Rist SCCOL nColJunk = 0;
4682f53782ebSAndrew Rist SCROW nRowJunk = 0;
4683f53782ebSAndrew Rist SCTAB nTabJunk = 0;
4684f53782ebSAndrew Rist PopDoubleRef( nCol3, nRow3, nTab3, nColJunk, nRowJunk, nTabJunk );
4685f53782ebSAndrew Rist if ( nTabJunk != nTab3 )
4686f53782ebSAndrew Rist {
4687f53782ebSAndrew Rist SetError( errIllegalParameter);
4688f53782ebSAndrew Rist }
4689f53782ebSAndrew Rist }
4690f53782ebSAndrew Rist break;
4691f53782ebSAndrew Rist case svSingleRef :
4692f53782ebSAndrew Rist PopSingleRef( nCol3, nRow3, nTab3 );
4693f53782ebSAndrew Rist break;
4694f53782ebSAndrew Rist case svMatrix:
4695f53782ebSAndrew Rist pSumExtraMatrix = PopMatrix();
4696f53782ebSAndrew Rist //! nCol3, nRow3, nTab3 remain 0
4697f53782ebSAndrew Rist break;
4698f53782ebSAndrew Rist default:
4699f53782ebSAndrew Rist SetError( errIllegalParameter);
4700f53782ebSAndrew Rist }
4701f53782ebSAndrew Rist }
4702f53782ebSAndrew Rist String rString;
4703f53782ebSAndrew Rist double fVal = 0.0;
4704f53782ebSAndrew Rist bool bIsString = true;
4705f53782ebSAndrew Rist switch ( GetStackType() )
4706f53782ebSAndrew Rist {
4707f53782ebSAndrew Rist case svDoubleRef :
4708f53782ebSAndrew Rist case svSingleRef :
4709f53782ebSAndrew Rist {
4710f53782ebSAndrew Rist ScAddress aAdr;
4711f53782ebSAndrew Rist if ( !PopDoubleRefOrSingleRef( aAdr ) )
4712f53782ebSAndrew Rist return 0;
4713f53782ebSAndrew Rist
4714f53782ebSAndrew Rist ScBaseCell* pCell = GetCell( aAdr );
4715f53782ebSAndrew Rist switch ( GetCellType( pCell ) )
4716f53782ebSAndrew Rist {
4717f53782ebSAndrew Rist case CELLTYPE_VALUE :
4718f53782ebSAndrew Rist fVal = GetCellValue( aAdr, pCell );
4719f53782ebSAndrew Rist bIsString = false;
4720f53782ebSAndrew Rist break;
4721f53782ebSAndrew Rist case CELLTYPE_FORMULA :
4722f53782ebSAndrew Rist if( ((ScFormulaCell*)pCell)->IsValue() )
4723f53782ebSAndrew Rist {
4724f53782ebSAndrew Rist fVal = GetCellValue( aAdr, pCell );
4725f53782ebSAndrew Rist bIsString = false;
4726f53782ebSAndrew Rist }
4727f53782ebSAndrew Rist else
4728f53782ebSAndrew Rist GetCellString(rString, pCell);
4729f53782ebSAndrew Rist break;
4730f53782ebSAndrew Rist case CELLTYPE_STRING :
4731f53782ebSAndrew Rist case CELLTYPE_EDIT :
4732f53782ebSAndrew Rist GetCellString(rString, pCell);
4733f53782ebSAndrew Rist break;
4734f53782ebSAndrew Rist default:
4735f53782ebSAndrew Rist fVal = 0.0;
4736f53782ebSAndrew Rist bIsString = false;
4737f53782ebSAndrew Rist }
4738f53782ebSAndrew Rist }
4739f53782ebSAndrew Rist break;
4740f53782ebSAndrew Rist case svString:
4741f53782ebSAndrew Rist rString = GetString();
4742f53782ebSAndrew Rist break;
4743f53782ebSAndrew Rist case svMatrix :
4744f53782ebSAndrew Rist {
4745f53782ebSAndrew Rist ScMatValType nType = GetDoubleOrStringFromMatrix( fVal, rString);
4746f53782ebSAndrew Rist bIsString = ScMatrix::IsNonValueType( nType);
4747f53782ebSAndrew Rist }
4748f53782ebSAndrew Rist break;
4749f53782ebSAndrew Rist default:
4750f53782ebSAndrew Rist {
4751f53782ebSAndrew Rist fVal = GetDouble();
4752f53782ebSAndrew Rist bIsString = false;
4753f53782ebSAndrew Rist }
4754f53782ebSAndrew Rist }
4755f53782ebSAndrew Rist
4756f53782ebSAndrew Rist double fSum = 0.0;
4757f53782ebSAndrew Rist double fMem = 0.0;
4758f53782ebSAndrew Rist double fRes = 0.0;
4759f53782ebSAndrew Rist double fCount = 0.0;
4760f53782ebSAndrew Rist bool bNull = true;
4761f53782ebSAndrew Rist short nParam = 1;
4762f53782ebSAndrew Rist size_t nRefInList = 0;
4763f53782ebSAndrew Rist while (nParam-- > 0)
4764f53782ebSAndrew Rist {
476551df7705SAndrew Rist SCCOL nCol1 = 0;
476651df7705SAndrew Rist SCROW nRow1 = 0;
476751df7705SAndrew Rist SCTAB nTab1 = 0;
476851df7705SAndrew Rist SCCOL nCol2 = 0;
476951df7705SAndrew Rist SCROW nRow2 = 0;
477051df7705SAndrew Rist SCTAB nTab2 = 0;
4771f53782ebSAndrew Rist ScMatrixRef pQueryMatrix;
4772f53782ebSAndrew Rist switch ( GetStackType() )
4773f53782ebSAndrew Rist {
4774f53782ebSAndrew Rist case svRefList :
4775f53782ebSAndrew Rist if (bSumExtraRange)
4776f53782ebSAndrew Rist {
4777f53782ebSAndrew Rist SetError( errIllegalParameter);
4778f53782ebSAndrew Rist }
4779f53782ebSAndrew Rist else
4780f53782ebSAndrew Rist {
4781f53782ebSAndrew Rist ScRange aRange;
4782f53782ebSAndrew Rist PopDoubleRef( aRange, nParam, nRefInList);
4783f53782ebSAndrew Rist aRange.GetVars( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
4784f53782ebSAndrew Rist }
4785f53782ebSAndrew Rist break;
4786f53782ebSAndrew Rist case svDoubleRef :
4787f53782ebSAndrew Rist PopDoubleRef( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 );
4788f53782ebSAndrew Rist break;
4789f53782ebSAndrew Rist case svSingleRef :
4790f53782ebSAndrew Rist PopSingleRef( nCol1, nRow1, nTab1 );
4791f53782ebSAndrew Rist nCol2 = nCol1;
4792f53782ebSAndrew Rist nRow2 = nRow1;
4793f53782ebSAndrew Rist nTab2 = nTab1;
4794f53782ebSAndrew Rist break;
4795f53782ebSAndrew Rist case svMatrix:
4796f53782ebSAndrew Rist {
4797f53782ebSAndrew Rist pQueryMatrix = PopMatrix();
4798f53782ebSAndrew Rist if (!pQueryMatrix)
4799f53782ebSAndrew Rist {
4800f53782ebSAndrew Rist SetError( errIllegalParameter);
4801f53782ebSAndrew Rist }
4802f53782ebSAndrew Rist nCol1 = 0;
4803f53782ebSAndrew Rist nRow1 = 0;
4804f53782ebSAndrew Rist nTab1 = 0;
4805f53782ebSAndrew Rist SCSIZE nC, nR;
4806f53782ebSAndrew Rist pQueryMatrix->GetDimensions( nC, nR);
4807f53782ebSAndrew Rist nCol2 = static_cast<SCCOL>(nC - 1);
4808f53782ebSAndrew Rist nRow2 = static_cast<SCROW>(nR - 1);
4809f53782ebSAndrew Rist nTab2 = 0;
4810f53782ebSAndrew Rist }
4811f53782ebSAndrew Rist break;
4812f53782ebSAndrew Rist default:
4813f53782ebSAndrew Rist SetError( errIllegalParameter);
4814f53782ebSAndrew Rist }
4815f53782ebSAndrew Rist if ( nTab1 != nTab2 )
4816f53782ebSAndrew Rist {
4817f53782ebSAndrew Rist SetError( errIllegalParameter);
4818f53782ebSAndrew Rist }
4819f53782ebSAndrew Rist
4820f53782ebSAndrew Rist if (bSumExtraRange)
4821f53782ebSAndrew Rist {
4822f53782ebSAndrew Rist // Take the range geometry of the 1st parameter and apply it to
4823f53782ebSAndrew Rist // the 3rd. If parts of the resulting range would point outside
4824f53782ebSAndrew Rist // the sheet, don't complain but silently ignore and simply cut
4825f53782ebSAndrew Rist // them away, this is what Xcl does :-/
4826f53782ebSAndrew Rist
4827f53782ebSAndrew Rist // For the cut-away part we also don't need to determine the
4828f53782ebSAndrew Rist // criteria match, so shrink the source range accordingly,
4829f53782ebSAndrew Rist // instead of the result range.
4830f53782ebSAndrew Rist SCCOL nColDelta = nCol2 - nCol1;
4831f53782ebSAndrew Rist SCROW nRowDelta = nRow2 - nRow1;
4832f53782ebSAndrew Rist SCCOL nMaxCol;
4833f53782ebSAndrew Rist SCROW nMaxRow;
4834f53782ebSAndrew Rist if (pSumExtraMatrix)
4835f53782ebSAndrew Rist {
4836f53782ebSAndrew Rist SCSIZE nC, nR;
4837f53782ebSAndrew Rist pSumExtraMatrix->GetDimensions( nC, nR);
4838f53782ebSAndrew Rist nMaxCol = static_cast<SCCOL>(nC - 1);
4839f53782ebSAndrew Rist nMaxRow = static_cast<SCROW>(nR - 1);
4840f53782ebSAndrew Rist }
4841f53782ebSAndrew Rist else
4842f53782ebSAndrew Rist {
4843f53782ebSAndrew Rist nMaxCol = MAXCOL;
4844f53782ebSAndrew Rist nMaxRow = MAXROW;
4845f53782ebSAndrew Rist }
4846f53782ebSAndrew Rist if (nCol3 + nColDelta > nMaxCol)
4847f53782ebSAndrew Rist {
4848f53782ebSAndrew Rist SCCOL nNewDelta = nMaxCol - nCol3;
4849f53782ebSAndrew Rist nCol2 = nCol1 + nNewDelta;
4850f53782ebSAndrew Rist }
4851f53782ebSAndrew Rist
4852f53782ebSAndrew Rist if (nRow3 + nRowDelta > nMaxRow)
4853f53782ebSAndrew Rist {
4854f53782ebSAndrew Rist SCROW nNewDelta = nMaxRow - nRow3;
4855f53782ebSAndrew Rist nRow2 = nRow1 + nNewDelta;
4856f53782ebSAndrew Rist }
4857f53782ebSAndrew Rist }
4858f53782ebSAndrew Rist else
4859f53782ebSAndrew Rist {
4860f53782ebSAndrew Rist nCol3 = nCol1;
4861f53782ebSAndrew Rist nRow3 = nRow1;
4862f53782ebSAndrew Rist nTab3 = nTab1;
4863f53782ebSAndrew Rist }
4864f53782ebSAndrew Rist
4865f53782ebSAndrew Rist if (nGlobalError == 0)
4866f53782ebSAndrew Rist {
4867f53782ebSAndrew Rist ScQueryParam rParam;
4868f53782ebSAndrew Rist rParam.nRow1 = nRow1;
4869f53782ebSAndrew Rist rParam.nRow2 = nRow2;
4870f53782ebSAndrew Rist
4871f53782ebSAndrew Rist ScQueryEntry& rEntry = rParam.GetEntry(0);
4872f53782ebSAndrew Rist rEntry.bDoQuery = true;
4873f53782ebSAndrew Rist if (!bIsString)
4874f53782ebSAndrew Rist {
4875f53782ebSAndrew Rist rEntry.bQueryByString = false;
4876f53782ebSAndrew Rist rEntry.nVal = fVal;
4877f53782ebSAndrew Rist rEntry.eOp = SC_EQUAL;
4878f53782ebSAndrew Rist }
4879f53782ebSAndrew Rist else
4880f53782ebSAndrew Rist {
4881f53782ebSAndrew Rist rParam.FillInExcelSyntax(rString, 0);
4882f53782ebSAndrew Rist sal_uInt32 nIndex = 0;
4883f53782ebSAndrew Rist rEntry.bQueryByString =
4884f53782ebSAndrew Rist !(pFormatter->IsNumberFormat(
4885f53782ebSAndrew Rist *rEntry.pStr, nIndex, rEntry.nVal));
4886f53782ebSAndrew Rist if ( rEntry.bQueryByString )
4887f53782ebSAndrew Rist rParam.bRegExp = MayBeRegExp( *rEntry.pStr, pDok );
4888f53782ebSAndrew Rist }
4889f53782ebSAndrew Rist ScAddress aAdr;
4890f53782ebSAndrew Rist aAdr.SetTab( nTab3 );
4891f53782ebSAndrew Rist rParam.nCol1 = nCol1;
4892f53782ebSAndrew Rist rParam.nCol2 = nCol2;
4893f53782ebSAndrew Rist rEntry.nField = nCol1;
4894f53782ebSAndrew Rist SCsCOL nColDiff = nCol3 - nCol1;
4895f53782ebSAndrew Rist SCsROW nRowDiff = nRow3 - nRow1;
4896f53782ebSAndrew Rist if (pQueryMatrix)
4897f53782ebSAndrew Rist {
4898f53782ebSAndrew Rist // Never case-sensitive.
4899f53782ebSAndrew Rist ScCompareOptions aOptions( pDok, rEntry, rParam.bRegExp);
4900f53782ebSAndrew Rist ScMatrixRef pResultMatrix = QueryMat( pQueryMatrix, aOptions);
4901f53782ebSAndrew Rist if (nGlobalError || !pResultMatrix)
4902f53782ebSAndrew Rist {
4903f53782ebSAndrew Rist SetError( errIllegalParameter);
4904f53782ebSAndrew Rist }
4905f53782ebSAndrew Rist
4906f53782ebSAndrew Rist if (pSumExtraMatrix)
4907f53782ebSAndrew Rist {
4908f53782ebSAndrew Rist for (SCCOL nCol = nCol1; nCol <= nCol2; ++nCol)
4909f53782ebSAndrew Rist {
4910f53782ebSAndrew Rist for (SCROW nRow = nRow1; nRow <= nRow2; ++nRow)
4911f53782ebSAndrew Rist {
4912f53782ebSAndrew Rist if (pResultMatrix->IsValue( nCol, nRow) &&
4913f53782ebSAndrew Rist pResultMatrix->GetDouble( nCol, nRow))
4914f53782ebSAndrew Rist {
4915f53782ebSAndrew Rist SCSIZE nC = nCol + nColDiff;
4916f53782ebSAndrew Rist SCSIZE nR = nRow + nRowDiff;
4917f53782ebSAndrew Rist if (pSumExtraMatrix->IsValue( nC, nR))
4918f53782ebSAndrew Rist {
4919f53782ebSAndrew Rist fVal = pSumExtraMatrix->GetDouble( nC, nR);
4920f53782ebSAndrew Rist ++fCount;
4921f53782ebSAndrew Rist if ( bNull && fVal != 0.0 )
4922f53782ebSAndrew Rist {
4923f53782ebSAndrew Rist bNull = false;
4924f53782ebSAndrew Rist fMem = fVal;
4925f53782ebSAndrew Rist }
4926f53782ebSAndrew Rist else
4927f53782ebSAndrew Rist fSum += fVal;
4928f53782ebSAndrew Rist }
4929f53782ebSAndrew Rist }
4930f53782ebSAndrew Rist }
4931f53782ebSAndrew Rist }
4932f53782ebSAndrew Rist }
4933f53782ebSAndrew Rist else
4934f53782ebSAndrew Rist {
4935f53782ebSAndrew Rist for (SCCOL nCol = nCol1; nCol <= nCol2; ++nCol)
4936f53782ebSAndrew Rist {
4937f53782ebSAndrew Rist for (SCROW nRow = nRow1; nRow <= nRow2; ++nRow)
4938f53782ebSAndrew Rist {
4939f53782ebSAndrew Rist if (pResultMatrix->GetDouble( nCol, nRow))
4940f53782ebSAndrew Rist {
4941f53782ebSAndrew Rist aAdr.SetCol( nCol + nColDiff);
4942f53782ebSAndrew Rist aAdr.SetRow( nRow + nRowDiff);
4943f53782ebSAndrew Rist ScBaseCell* pCell = GetCell( aAdr );
4944f53782ebSAndrew Rist if ( HasCellValueData(pCell) )
4945f53782ebSAndrew Rist {
4946f53782ebSAndrew Rist fVal = GetCellValue( aAdr, pCell );
4947f53782ebSAndrew Rist ++fCount;
4948f53782ebSAndrew Rist if ( bNull && fVal != 0.0 )
4949f53782ebSAndrew Rist {
4950f53782ebSAndrew Rist bNull = false;
4951f53782ebSAndrew Rist fMem = fVal;
4952f53782ebSAndrew Rist }
4953f53782ebSAndrew Rist else
4954f53782ebSAndrew Rist fSum += fVal;
4955f53782ebSAndrew Rist }
4956f53782ebSAndrew Rist }
4957f53782ebSAndrew Rist }
4958f53782ebSAndrew Rist }
4959f53782ebSAndrew Rist }
4960f53782ebSAndrew Rist }
4961f53782ebSAndrew Rist else
4962f53782ebSAndrew Rist {
4963f53782ebSAndrew Rist ScQueryCellIterator aCellIter(pDok, nTab1, rParam, false);
4964f53782ebSAndrew Rist // Increment Entry.nField in iterator when switching to next column.
4965f53782ebSAndrew Rist aCellIter.SetAdvanceQueryParamEntryField( true );
4966f53782ebSAndrew Rist if ( aCellIter.GetFirst() )
4967f53782ebSAndrew Rist {
4968f53782ebSAndrew Rist if (pSumExtraMatrix)
4969f53782ebSAndrew Rist {
4970f53782ebSAndrew Rist do
4971f53782ebSAndrew Rist {
4972f53782ebSAndrew Rist SCSIZE nC = aCellIter.GetCol() + nColDiff;
4973f53782ebSAndrew Rist SCSIZE nR = aCellIter.GetRow() + nRowDiff;
4974f53782ebSAndrew Rist if (pSumExtraMatrix->IsValue( nC, nR))
4975f53782ebSAndrew Rist {
4976f53782ebSAndrew Rist fVal = pSumExtraMatrix->GetDouble( nC, nR);
4977f53782ebSAndrew Rist ++fCount;
4978f53782ebSAndrew Rist if ( bNull && fVal != 0.0 )
4979f53782ebSAndrew Rist {
4980f53782ebSAndrew Rist bNull = false;
4981f53782ebSAndrew Rist fMem = fVal;
4982f53782ebSAndrew Rist }
4983f53782ebSAndrew Rist else
4984f53782ebSAndrew Rist fSum += fVal;
4985f53782ebSAndrew Rist }
4986f53782ebSAndrew Rist } while ( aCellIter.GetNext() );
4987f53782ebSAndrew Rist }
4988f53782ebSAndrew Rist else
4989f53782ebSAndrew Rist {
4990f53782ebSAndrew Rist do
4991f53782ebSAndrew Rist {
4992f53782ebSAndrew Rist aAdr.SetCol( aCellIter.GetCol() + nColDiff);
4993f53782ebSAndrew Rist aAdr.SetRow( aCellIter.GetRow() + nRowDiff);
4994f53782ebSAndrew Rist ScBaseCell* pCell = GetCell( aAdr );
4995f53782ebSAndrew Rist if ( HasCellValueData(pCell) )
4996f53782ebSAndrew Rist {
4997f53782ebSAndrew Rist fVal = GetCellValue( aAdr, pCell );
4998f53782ebSAndrew Rist ++fCount;
4999f53782ebSAndrew Rist if ( bNull && fVal != 0.0 )
5000f53782ebSAndrew Rist {
5001f53782ebSAndrew Rist bNull = false;
5002f53782ebSAndrew Rist fMem = fVal;
5003f53782ebSAndrew Rist }
5004f53782ebSAndrew Rist else
5005f53782ebSAndrew Rist fSum += fVal;
5006f53782ebSAndrew Rist }
5007f53782ebSAndrew Rist } while ( aCellIter.GetNext() );
5008f53782ebSAndrew Rist }
5009f53782ebSAndrew Rist }
5010f53782ebSAndrew Rist }
5011f53782ebSAndrew Rist }
5012f53782ebSAndrew Rist else
5013f53782ebSAndrew Rist {
5014f53782ebSAndrew Rist SetError( errIllegalParameter);
5015f53782ebSAndrew Rist }
5016f53782ebSAndrew Rist }
5017f53782ebSAndrew Rist
5018f53782ebSAndrew Rist switch( eFunc )
5019f53782ebSAndrew Rist {
5020f53782ebSAndrew Rist case ifSUMIF: fRes = ::rtl::math::approxAdd( fSum, fMem ); break;
5021f53782ebSAndrew Rist case ifAVERAGEIF: fRes = div( ::rtl::math::approxAdd( fSum, fMem ), fCount); break;
5022f53782ebSAndrew Rist }
5023f53782ebSAndrew Rist return fRes;
5024f53782ebSAndrew Rist }
5025f53782ebSAndrew Rist return 0;
5026f53782ebSAndrew Rist }
5027f53782ebSAndrew Rist
ScSumIf()5028f53782ebSAndrew Rist void ScInterpreter::ScSumIf()
5029f53782ebSAndrew Rist {
5030f53782ebSAndrew Rist RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScSumIf" );
5031f53782ebSAndrew Rist PushDouble( IterateParametersIf( ifSUMIF));
5032f53782ebSAndrew Rist }
5033f53782ebSAndrew Rist
ScAverageIf()5034f53782ebSAndrew Rist void ScInterpreter::ScAverageIf()
5035f53782ebSAndrew Rist {
5036f53782ebSAndrew Rist RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "makkica", "ScInterpreter::ScAverageIf" );
5037f53782ebSAndrew Rist PushDouble( IterateParametersIf( ifAVERAGEIF));
5038f53782ebSAndrew Rist }
5039f53782ebSAndrew Rist
ScCountIf()5040cdf0e10cSrcweir void ScInterpreter::ScCountIf()
5041cdf0e10cSrcweir {
5042cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScCountIf" );
5043cdf0e10cSrcweir if ( MustHaveParamCount( GetByte(), 2 ) )
5044cdf0e10cSrcweir {
5045cdf0e10cSrcweir String rString;
5046cdf0e10cSrcweir double fVal = 0.0;
5047cdf0e10cSrcweir sal_Bool bIsString = sal_True;
5048cdf0e10cSrcweir switch ( GetStackType() )
5049cdf0e10cSrcweir {
5050cdf0e10cSrcweir case svDoubleRef :
5051cdf0e10cSrcweir case svSingleRef :
5052cdf0e10cSrcweir {
5053cdf0e10cSrcweir ScAddress aAdr;
5054cdf0e10cSrcweir if ( !PopDoubleRefOrSingleRef( aAdr ) )
5055cdf0e10cSrcweir {
5056cdf0e10cSrcweir PushInt(0);
5057cdf0e10cSrcweir return ;
5058cdf0e10cSrcweir }
5059cdf0e10cSrcweir ScBaseCell* pCell = GetCell( aAdr );
5060cdf0e10cSrcweir switch ( GetCellType( pCell ) )
5061cdf0e10cSrcweir {
5062cdf0e10cSrcweir case CELLTYPE_VALUE :
5063cdf0e10cSrcweir fVal = GetCellValue( aAdr, pCell );
5064cdf0e10cSrcweir bIsString = sal_False;
5065cdf0e10cSrcweir break;
5066cdf0e10cSrcweir case CELLTYPE_FORMULA :
5067cdf0e10cSrcweir if( ((ScFormulaCell*)pCell)->IsValue() )
5068cdf0e10cSrcweir {
5069cdf0e10cSrcweir fVal = GetCellValue( aAdr, pCell );
5070cdf0e10cSrcweir bIsString = sal_False;
5071cdf0e10cSrcweir }
5072cdf0e10cSrcweir else
5073cdf0e10cSrcweir GetCellString(rString, pCell);
5074cdf0e10cSrcweir break;
5075cdf0e10cSrcweir case CELLTYPE_STRING :
5076cdf0e10cSrcweir case CELLTYPE_EDIT :
5077cdf0e10cSrcweir GetCellString(rString, pCell);
5078cdf0e10cSrcweir break;
5079cdf0e10cSrcweir default:
5080cdf0e10cSrcweir fVal = 0.0;
5081cdf0e10cSrcweir bIsString = sal_False;
5082cdf0e10cSrcweir }
5083cdf0e10cSrcweir }
5084cdf0e10cSrcweir break;
5085cdf0e10cSrcweir case svMatrix :
5086cdf0e10cSrcweir {
5087f53782ebSAndrew Rist ScMatValType nType = GetDoubleOrStringFromMatrix( fVal, rString);
5088cdf0e10cSrcweir bIsString = ScMatrix::IsNonValueType( nType);
5089cdf0e10cSrcweir }
5090cdf0e10cSrcweir break;
5091cdf0e10cSrcweir case svString:
5092cdf0e10cSrcweir rString = GetString();
5093cdf0e10cSrcweir break;
5094cdf0e10cSrcweir default:
5095cdf0e10cSrcweir {
5096cdf0e10cSrcweir fVal = GetDouble();
5097cdf0e10cSrcweir bIsString = sal_False;
5098cdf0e10cSrcweir }
5099cdf0e10cSrcweir }
5100f53782ebSAndrew Rist double fCount = 0.0;
5101cdf0e10cSrcweir short nParam = 1;
5102cdf0e10cSrcweir size_t nRefInList = 0;
5103cdf0e10cSrcweir while (nParam-- > 0)
5104cdf0e10cSrcweir {
5105cdf0e10cSrcweir SCCOL nCol1;
5106cdf0e10cSrcweir SCROW nRow1;
5107cdf0e10cSrcweir SCTAB nTab1;
5108cdf0e10cSrcweir SCCOL nCol2;
5109cdf0e10cSrcweir SCROW nRow2;
5110cdf0e10cSrcweir SCTAB nTab2;
5111cdf0e10cSrcweir ScMatrixRef pQueryMatrix;
5112cdf0e10cSrcweir switch ( GetStackType() )
5113cdf0e10cSrcweir {
5114cdf0e10cSrcweir case svDoubleRef :
5115cdf0e10cSrcweir case svRefList :
5116cdf0e10cSrcweir {
5117cdf0e10cSrcweir ScRange aRange;
5118cdf0e10cSrcweir PopDoubleRef( aRange, nParam, nRefInList);
5119cdf0e10cSrcweir aRange.GetVars( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
5120cdf0e10cSrcweir }
5121cdf0e10cSrcweir break;
5122cdf0e10cSrcweir case svSingleRef :
5123cdf0e10cSrcweir PopSingleRef( nCol1, nRow1, nTab1 );
5124cdf0e10cSrcweir nCol2 = nCol1;
5125cdf0e10cSrcweir nRow2 = nRow1;
5126cdf0e10cSrcweir nTab2 = nTab1;
5127cdf0e10cSrcweir break;
5128cdf0e10cSrcweir case svMatrix:
5129cdf0e10cSrcweir {
5130cdf0e10cSrcweir pQueryMatrix = PopMatrix();
5131cdf0e10cSrcweir if (!pQueryMatrix)
5132cdf0e10cSrcweir {
5133cdf0e10cSrcweir PushIllegalParameter();
5134cdf0e10cSrcweir return;
5135cdf0e10cSrcweir }
5136cdf0e10cSrcweir nCol1 = 0;
5137cdf0e10cSrcweir nRow1 = 0;
5138cdf0e10cSrcweir nTab1 = 0;
5139cdf0e10cSrcweir SCSIZE nC, nR;
5140cdf0e10cSrcweir pQueryMatrix->GetDimensions( nC, nR);
5141cdf0e10cSrcweir nCol2 = static_cast<SCCOL>(nC - 1);
5142cdf0e10cSrcweir nRow2 = static_cast<SCROW>(nR - 1);
5143cdf0e10cSrcweir nTab2 = 0;
5144cdf0e10cSrcweir }
5145cdf0e10cSrcweir break;
5146cdf0e10cSrcweir default:
5147cdf0e10cSrcweir PushIllegalParameter();
5148cdf0e10cSrcweir return ;
5149cdf0e10cSrcweir }
5150cdf0e10cSrcweir if ( nTab1 != nTab2 )
5151cdf0e10cSrcweir {
5152cdf0e10cSrcweir PushIllegalParameter();
5153cdf0e10cSrcweir return;
5154cdf0e10cSrcweir }
5155cdf0e10cSrcweir if (nCol1 > nCol2)
5156cdf0e10cSrcweir {
5157cdf0e10cSrcweir PushIllegalParameter();
5158cdf0e10cSrcweir return;
5159cdf0e10cSrcweir }
5160cdf0e10cSrcweir if (nGlobalError == 0)
5161cdf0e10cSrcweir {
5162cdf0e10cSrcweir ScQueryParam rParam;
5163cdf0e10cSrcweir rParam.nRow1 = nRow1;
5164cdf0e10cSrcweir rParam.nRow2 = nRow2;
5165cdf0e10cSrcweir
5166cdf0e10cSrcweir ScQueryEntry& rEntry = rParam.GetEntry(0);
5167cdf0e10cSrcweir rEntry.bDoQuery = sal_True;
5168cdf0e10cSrcweir if (!bIsString)
5169cdf0e10cSrcweir {
5170cdf0e10cSrcweir rEntry.bQueryByString = sal_False;
5171cdf0e10cSrcweir rEntry.nVal = fVal;
5172cdf0e10cSrcweir rEntry.eOp = SC_EQUAL;
5173cdf0e10cSrcweir }
5174cdf0e10cSrcweir else
5175cdf0e10cSrcweir {
5176cdf0e10cSrcweir rParam.FillInExcelSyntax(rString, 0);
5177cdf0e10cSrcweir sal_uInt32 nIndex = 0;
5178cdf0e10cSrcweir rEntry.bQueryByString =
5179cdf0e10cSrcweir !(pFormatter->IsNumberFormat(
5180cdf0e10cSrcweir *rEntry.pStr, nIndex, rEntry.nVal));
5181cdf0e10cSrcweir if ( rEntry.bQueryByString )
5182cdf0e10cSrcweir rParam.bRegExp = MayBeRegExp( *rEntry.pStr, pDok );
5183cdf0e10cSrcweir }
5184cdf0e10cSrcweir rParam.nCol1 = nCol1;
5185cdf0e10cSrcweir rParam.nCol2 = nCol2;
5186cdf0e10cSrcweir rEntry.nField = nCol1;
5187cdf0e10cSrcweir if (pQueryMatrix)
5188cdf0e10cSrcweir {
5189cdf0e10cSrcweir // Never case-sensitive.
5190cdf0e10cSrcweir ScCompareOptions aOptions( pDok, rEntry, rParam.bRegExp);
5191cdf0e10cSrcweir ScMatrixRef pResultMatrix = QueryMat( pQueryMatrix, aOptions);
5192cdf0e10cSrcweir if (nGlobalError || !pResultMatrix)
5193cdf0e10cSrcweir {
5194cdf0e10cSrcweir PushIllegalParameter();
5195cdf0e10cSrcweir return;
5196cdf0e10cSrcweir }
5197cdf0e10cSrcweir
5198cdf0e10cSrcweir SCSIZE nSize = pResultMatrix->GetElementCount();
5199cdf0e10cSrcweir for (SCSIZE nIndex = 0; nIndex < nSize; ++nIndex)
5200cdf0e10cSrcweir {
5201cdf0e10cSrcweir if (pResultMatrix->IsValue( nIndex) &&
5202cdf0e10cSrcweir pResultMatrix->GetDouble( nIndex))
5203f53782ebSAndrew Rist ++fCount;
5204cdf0e10cSrcweir }
5205cdf0e10cSrcweir }
5206cdf0e10cSrcweir else
5207cdf0e10cSrcweir {
5208cdf0e10cSrcweir ScQueryCellIterator aCellIter(pDok, nTab1, rParam, sal_False);
5209cdf0e10cSrcweir // Entry.nField im Iterator bei Spaltenwechsel weiterschalten
5210cdf0e10cSrcweir aCellIter.SetAdvanceQueryParamEntryField( sal_True );
5211cdf0e10cSrcweir if ( aCellIter.GetFirst() )
5212cdf0e10cSrcweir {
5213cdf0e10cSrcweir do
5214cdf0e10cSrcweir {
5215f53782ebSAndrew Rist fCount++;
5216cdf0e10cSrcweir } while ( aCellIter.GetNext() );
5217cdf0e10cSrcweir }
5218cdf0e10cSrcweir }
5219cdf0e10cSrcweir }
5220cdf0e10cSrcweir else
5221cdf0e10cSrcweir {
5222cdf0e10cSrcweir PushIllegalParameter();
5223cdf0e10cSrcweir return;
5224cdf0e10cSrcweir }
5225cdf0e10cSrcweir }
5226f53782ebSAndrew Rist PushDouble(fCount);
5227cdf0e10cSrcweir }
5228cdf0e10cSrcweir }
5229cdf0e10cSrcweir
IterateParametersIfs(ScIterFuncIfs eFunc)52301b1b70fbSAndrew Rist double ScInterpreter::IterateParametersIfs( ScIterFuncIfs eFunc )
52311b1b70fbSAndrew Rist {
52321b1b70fbSAndrew Rist sal_uInt8 nParamCount = GetByte();
52331b1b70fbSAndrew Rist sal_uInt8 nQueryCount = nParamCount / 2;
52341b1b70fbSAndrew Rist
52351b1b70fbSAndrew Rist bool bCheck;
52361b1b70fbSAndrew Rist if ( eFunc == ifCOUNTIFS )
52371b1b70fbSAndrew Rist bCheck = (nParamCount >= 2) && (nParamCount % 2 == 0);
52381b1b70fbSAndrew Rist else
52391b1b70fbSAndrew Rist bCheck = (nParamCount >= 3) && (nParamCount % 2 == 1);
52401b1b70fbSAndrew Rist
52411b1b70fbSAndrew Rist if ( !bCheck )
52421b1b70fbSAndrew Rist {
52431b1b70fbSAndrew Rist SetError( errParameterExpected);
52441b1b70fbSAndrew Rist }
52451b1b70fbSAndrew Rist else
52461b1b70fbSAndrew Rist {
52471b1b70fbSAndrew Rist ScMatrixRef pResMat;
52481b1b70fbSAndrew Rist double fVal = 0.0;
52491b1b70fbSAndrew Rist double fSum = 0.0;
52501b1b70fbSAndrew Rist double fMem = 0.0;
52511b1b70fbSAndrew Rist double fRes = 0.0;
52521b1b70fbSAndrew Rist double fCount = 0.0;
52531b1b70fbSAndrew Rist short nParam = 1;
52541b1b70fbSAndrew Rist size_t nRefInList = 0;
52556e86bbc1SAndrew Rist SCCOL nDimensionCols = 0;
52566e86bbc1SAndrew Rist SCROW nDimensionRows = 0;
52571b1b70fbSAndrew Rist
52581b1b70fbSAndrew Rist while (nParamCount > 1 && !nGlobalError)
52591b1b70fbSAndrew Rist {
52601b1b70fbSAndrew Rist // take criteria
52611b1b70fbSAndrew Rist String rString;
52621b1b70fbSAndrew Rist fVal = 0.0;
52631b1b70fbSAndrew Rist bool bIsString = true;
52641b1b70fbSAndrew Rist switch ( GetStackType() )
52651b1b70fbSAndrew Rist {
52661b1b70fbSAndrew Rist case svDoubleRef :
52671b1b70fbSAndrew Rist case svSingleRef :
52681b1b70fbSAndrew Rist {
52691b1b70fbSAndrew Rist ScAddress aAdr;
52701b1b70fbSAndrew Rist if ( !PopDoubleRefOrSingleRef( aAdr ) )
52711b1b70fbSAndrew Rist return 0;
52721b1b70fbSAndrew Rist
52731b1b70fbSAndrew Rist ScBaseCell* pCell = GetCell( aAdr );
52741b1b70fbSAndrew Rist switch ( GetCellType( pCell ) )
52751b1b70fbSAndrew Rist {
52761b1b70fbSAndrew Rist case CELLTYPE_VALUE :
52771b1b70fbSAndrew Rist fVal = GetCellValue( aAdr, pCell );
52781b1b70fbSAndrew Rist bIsString = false;
52791b1b70fbSAndrew Rist break;
52801b1b70fbSAndrew Rist case CELLTYPE_FORMULA :
52811b1b70fbSAndrew Rist if( ((ScFormulaCell*)pCell)->IsValue() )
52821b1b70fbSAndrew Rist {
52831b1b70fbSAndrew Rist fVal = GetCellValue( aAdr, pCell );
52841b1b70fbSAndrew Rist bIsString = false;
52851b1b70fbSAndrew Rist }
52861b1b70fbSAndrew Rist else
52871b1b70fbSAndrew Rist GetCellString(rString, pCell);
52881b1b70fbSAndrew Rist break;
52891b1b70fbSAndrew Rist case CELLTYPE_STRING :
52901b1b70fbSAndrew Rist case CELLTYPE_EDIT :
52911b1b70fbSAndrew Rist GetCellString(rString, pCell);
52921b1b70fbSAndrew Rist break;
52931b1b70fbSAndrew Rist default:
52941b1b70fbSAndrew Rist fVal = 0.0;
52951b1b70fbSAndrew Rist bIsString = false;
52961b1b70fbSAndrew Rist }
52971b1b70fbSAndrew Rist }
52981b1b70fbSAndrew Rist break;
52991b1b70fbSAndrew Rist case svString:
53001b1b70fbSAndrew Rist rString = GetString();
53011b1b70fbSAndrew Rist break;
53021b1b70fbSAndrew Rist case svMatrix :
53031b1b70fbSAndrew Rist {
53041b1b70fbSAndrew Rist ScMatValType nType = GetDoubleOrStringFromMatrix( fVal, rString);
53051b1b70fbSAndrew Rist bIsString = ScMatrix::IsNonValueType( nType);
53061b1b70fbSAndrew Rist }
53071b1b70fbSAndrew Rist break;
53081b1b70fbSAndrew Rist default:
53091b1b70fbSAndrew Rist {
53101b1b70fbSAndrew Rist fVal = GetDouble();
53111b1b70fbSAndrew Rist bIsString = false;
53121b1b70fbSAndrew Rist }
53131b1b70fbSAndrew Rist }
53141b1b70fbSAndrew Rist
53156e86bbc1SAndrew Rist if (nGlobalError)
53166e86bbc1SAndrew Rist continue; // and bail out, no need to evaluate other arguments
53176e86bbc1SAndrew Rist
53181b1b70fbSAndrew Rist // take range
53191b1b70fbSAndrew Rist nParam = 1;
53201b1b70fbSAndrew Rist nRefInList = 0;
532151df7705SAndrew Rist SCCOL nCol1 = 0;
532251df7705SAndrew Rist SCROW nRow1 = 0;
532351df7705SAndrew Rist SCTAB nTab1 = 0;
532451df7705SAndrew Rist SCCOL nCol2 = 0;
532551df7705SAndrew Rist SCROW nRow2 = 0;
532651df7705SAndrew Rist SCTAB nTab2 = 0;
53271b1b70fbSAndrew Rist ScMatrixRef pQueryMatrix;
53281b1b70fbSAndrew Rist switch ( GetStackType() )
53291b1b70fbSAndrew Rist {
53301b1b70fbSAndrew Rist case svRefList :
53311b1b70fbSAndrew Rist {
53321b1b70fbSAndrew Rist ScRange aRange;
53331b1b70fbSAndrew Rist PopDoubleRef( aRange, nParam, nRefInList);
53341b1b70fbSAndrew Rist aRange.GetVars( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
53351b1b70fbSAndrew Rist }
53361b1b70fbSAndrew Rist break;
53371b1b70fbSAndrew Rist case svDoubleRef :
53381b1b70fbSAndrew Rist PopDoubleRef( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 );
53391b1b70fbSAndrew Rist break;
53401b1b70fbSAndrew Rist case svSingleRef :
53411b1b70fbSAndrew Rist PopSingleRef( nCol1, nRow1, nTab1 );
53421b1b70fbSAndrew Rist nCol2 = nCol1;
53431b1b70fbSAndrew Rist nRow2 = nRow1;
53441b1b70fbSAndrew Rist nTab2 = nTab1;
53451b1b70fbSAndrew Rist break;
53461b1b70fbSAndrew Rist case svMatrix:
53471b1b70fbSAndrew Rist {
53481b1b70fbSAndrew Rist pQueryMatrix = PopMatrix();
53491b1b70fbSAndrew Rist if (!pQueryMatrix)
53501b1b70fbSAndrew Rist {
53511b1b70fbSAndrew Rist SetError( errIllegalParameter);
53521b1b70fbSAndrew Rist }
53531b1b70fbSAndrew Rist nCol1 = 0;
53541b1b70fbSAndrew Rist nRow1 = 0;
53551b1b70fbSAndrew Rist nTab1 = 0;
53561b1b70fbSAndrew Rist SCSIZE nC, nR;
53571b1b70fbSAndrew Rist pQueryMatrix->GetDimensions( nC, nR);
53581b1b70fbSAndrew Rist nCol2 = static_cast<SCCOL>(nC - 1);
53591b1b70fbSAndrew Rist nRow2 = static_cast<SCROW>(nR - 1);
53601b1b70fbSAndrew Rist nTab2 = 0;
53611b1b70fbSAndrew Rist }
53621b1b70fbSAndrew Rist break;
53631b1b70fbSAndrew Rist default:
53641b1b70fbSAndrew Rist SetError( errIllegalParameter);
53651b1b70fbSAndrew Rist }
53661b1b70fbSAndrew Rist if ( nTab1 != nTab2 )
53676e86bbc1SAndrew Rist SetError( errIllegalArgument);
53686e86bbc1SAndrew Rist
53696e86bbc1SAndrew Rist // All reference ranges must be of same dimension and size.
53706e86bbc1SAndrew Rist if (!nDimensionCols)
53716e86bbc1SAndrew Rist nDimensionCols = nCol2 - nCol1 + 1;
53726e86bbc1SAndrew Rist if (!nDimensionRows)
53736e86bbc1SAndrew Rist nDimensionRows = nRow2 - nRow1 + 1;
53746e86bbc1SAndrew Rist if ((nDimensionCols != (nCol2 - nCol1 + 1)) || (nDimensionRows != (nRow2 - nRow1 + 1)))
53756e86bbc1SAndrew Rist SetError ( errIllegalArgument);
53766e86bbc1SAndrew Rist
53776e86bbc1SAndrew Rist // recalculate matrix values
53786e86bbc1SAndrew Rist if (nGlobalError == 0)
53791b1b70fbSAndrew Rist {
53801b1b70fbSAndrew Rist // initialize temporary result matrix
53811b1b70fbSAndrew Rist if (!pResMat)
53821b1b70fbSAndrew Rist {
53831b1b70fbSAndrew Rist SCSIZE nResC, nResR;
53841b1b70fbSAndrew Rist nResC = nCol2 - nCol1 + 1;
53851b1b70fbSAndrew Rist nResR = nRow2 - nRow1 + 1;
53861b1b70fbSAndrew Rist pResMat = GetNewMat(nResC, nResR);
53871b1b70fbSAndrew Rist if (!pResMat)
53881b1b70fbSAndrew Rist SetError( errIllegalParameter);
53891b1b70fbSAndrew Rist else
53901b1b70fbSAndrew Rist pResMat->FillDouble( 0.0, 0, 0, nResC-1, nResR-1);
53911b1b70fbSAndrew Rist }
53926e86bbc1SAndrew Rist
53931b1b70fbSAndrew Rist ScQueryParam rParam;
53941b1b70fbSAndrew Rist rParam.nRow1 = nRow1;
53951b1b70fbSAndrew Rist rParam.nRow2 = nRow2;
53961b1b70fbSAndrew Rist
53971b1b70fbSAndrew Rist ScQueryEntry& rEntry = rParam.GetEntry(0);
53981b1b70fbSAndrew Rist rEntry.bDoQuery = true;
53991b1b70fbSAndrew Rist if (!bIsString)
54001b1b70fbSAndrew Rist {
54011b1b70fbSAndrew Rist rEntry.bQueryByString = false;
54021b1b70fbSAndrew Rist rEntry.nVal = fVal;
54031b1b70fbSAndrew Rist rEntry.eOp = SC_EQUAL;
54041b1b70fbSAndrew Rist }
54051b1b70fbSAndrew Rist else
54061b1b70fbSAndrew Rist {
54071b1b70fbSAndrew Rist rParam.FillInExcelSyntax(rString, 0);
54081b1b70fbSAndrew Rist sal_uInt32 nIndex = 0;
54091b1b70fbSAndrew Rist rEntry.bQueryByString =
54101b1b70fbSAndrew Rist !(pFormatter->IsNumberFormat(
54111b1b70fbSAndrew Rist *rEntry.pStr, nIndex, rEntry.nVal));
54121b1b70fbSAndrew Rist if ( rEntry.bQueryByString )
54131b1b70fbSAndrew Rist rParam.bRegExp = MayBeRegExp( *rEntry.pStr, pDok );
54141b1b70fbSAndrew Rist }
54151b1b70fbSAndrew Rist ScAddress aAdr;
54161b1b70fbSAndrew Rist aAdr.SetTab( nTab1 );
54171b1b70fbSAndrew Rist rParam.nCol1 = nCol1;
54181b1b70fbSAndrew Rist rParam.nCol2 = nCol2;
54191b1b70fbSAndrew Rist rEntry.nField = nCol1;
54201b1b70fbSAndrew Rist SCsCOL nColDiff = -nCol1;
54211b1b70fbSAndrew Rist SCsROW nRowDiff = -nRow1;
54221b1b70fbSAndrew Rist if (pQueryMatrix)
54231b1b70fbSAndrew Rist {
54241b1b70fbSAndrew Rist // Never case-sensitive.
54251b1b70fbSAndrew Rist ScCompareOptions aOptions( pDok, rEntry, rParam.bRegExp);
54261b1b70fbSAndrew Rist ScMatrixRef pResultMatrix = QueryMat( pQueryMatrix, aOptions);
54271b1b70fbSAndrew Rist if (nGlobalError || !pResultMatrix)
54281b1b70fbSAndrew Rist {
54291b1b70fbSAndrew Rist SetError( errIllegalParameter);
54301b1b70fbSAndrew Rist }
54311b1b70fbSAndrew Rist
54321b1b70fbSAndrew Rist for (SCCOL nCol = nCol1; nCol <= nCol2; ++nCol)
54331b1b70fbSAndrew Rist {
54341b1b70fbSAndrew Rist for (SCROW nRow = nRow1; nRow <= nRow2; ++nRow)
54351b1b70fbSAndrew Rist {
54361b1b70fbSAndrew Rist if (pResultMatrix->IsValue( nCol, nRow) &&
54371b1b70fbSAndrew Rist pResultMatrix->GetDouble( nCol, nRow))
54381b1b70fbSAndrew Rist {
54391b1b70fbSAndrew Rist SCSIZE nC = nCol + nColDiff;
54401b1b70fbSAndrew Rist SCSIZE nR = nRow + nRowDiff;
54411b1b70fbSAndrew Rist pResMat->PutDouble(pResMat->GetDouble(nC, nR)+1.0, nC, nR);
54421b1b70fbSAndrew Rist }
54431b1b70fbSAndrew Rist }
54441b1b70fbSAndrew Rist }
54451b1b70fbSAndrew Rist }
54461b1b70fbSAndrew Rist else
54471b1b70fbSAndrew Rist {
54481b1b70fbSAndrew Rist ScQueryCellIterator aCellIter(pDok, nTab1, rParam, false);
54491b1b70fbSAndrew Rist // Increment Entry.nField in iterator when switching to next column.
54501b1b70fbSAndrew Rist aCellIter.SetAdvanceQueryParamEntryField( true );
54511b1b70fbSAndrew Rist if ( aCellIter.GetFirst() )
54521b1b70fbSAndrew Rist {
54531b1b70fbSAndrew Rist do
54541b1b70fbSAndrew Rist {
54551b1b70fbSAndrew Rist SCSIZE nC = aCellIter.GetCol() + nColDiff;
54561b1b70fbSAndrew Rist SCSIZE nR = aCellIter.GetRow() + nRowDiff;
54571b1b70fbSAndrew Rist pResMat->PutDouble(pResMat->GetDouble(nC, nR)+1.0, nC, nR);
54581b1b70fbSAndrew Rist } while ( aCellIter.GetNext() );
54591b1b70fbSAndrew Rist }
54601b1b70fbSAndrew Rist }
54611b1b70fbSAndrew Rist }
54621b1b70fbSAndrew Rist nParamCount -= 2;
54631b1b70fbSAndrew Rist }
54641b1b70fbSAndrew Rist
54656e86bbc1SAndrew Rist if (nGlobalError)
54666e86bbc1SAndrew Rist return 0; // bail out
54676e86bbc1SAndrew Rist
54681b1b70fbSAndrew Rist // main range - only for AVERAGEIFS and SUMIFS
54691b1b70fbSAndrew Rist if (nParamCount == 1)
54701b1b70fbSAndrew Rist {
54711b1b70fbSAndrew Rist nParam = 1;
54721b1b70fbSAndrew Rist nRefInList = 0;
54731b1b70fbSAndrew Rist bool bNull = true;
547451df7705SAndrew Rist SCCOL nMainCol1 = 0;
547551df7705SAndrew Rist SCROW nMainRow1 = 0;
547651df7705SAndrew Rist SCTAB nMainTab1 = 0;
547751df7705SAndrew Rist SCCOL nMainCol2 = 0;
547851df7705SAndrew Rist SCROW nMainRow2 = 0;
547951df7705SAndrew Rist SCTAB nMainTab2 = 0;
54801b1b70fbSAndrew Rist ScMatrixRef pMainMatrix;
54811b1b70fbSAndrew Rist switch ( GetStackType() )
54821b1b70fbSAndrew Rist {
54831b1b70fbSAndrew Rist case svRefList :
54841b1b70fbSAndrew Rist {
54851b1b70fbSAndrew Rist ScRange aRange;
54861b1b70fbSAndrew Rist PopDoubleRef( aRange, nParam, nRefInList);
54871b1b70fbSAndrew Rist aRange.GetVars( nMainCol1, nMainRow1, nMainTab1, nMainCol2, nMainRow2, nMainTab2);
54881b1b70fbSAndrew Rist }
54891b1b70fbSAndrew Rist break;
54901b1b70fbSAndrew Rist case svDoubleRef :
54911b1b70fbSAndrew Rist PopDoubleRef( nMainCol1, nMainRow1, nMainTab1, nMainCol2, nMainRow2, nMainTab2 );
54921b1b70fbSAndrew Rist break;
54931b1b70fbSAndrew Rist case svSingleRef :
54941b1b70fbSAndrew Rist PopSingleRef( nMainCol1, nMainRow1, nMainTab1 );
54951b1b70fbSAndrew Rist nMainCol2 = nMainCol1;
54961b1b70fbSAndrew Rist nMainRow2 = nMainRow1;
54971b1b70fbSAndrew Rist nMainTab2 = nMainTab1;
54981b1b70fbSAndrew Rist break;
54991b1b70fbSAndrew Rist case svMatrix:
55001b1b70fbSAndrew Rist {
55011b1b70fbSAndrew Rist pMainMatrix = PopMatrix();
55021b1b70fbSAndrew Rist if (!pMainMatrix)
55031b1b70fbSAndrew Rist {
55041b1b70fbSAndrew Rist SetError( errIllegalParameter);
55051b1b70fbSAndrew Rist }
55061b1b70fbSAndrew Rist nMainCol1 = 0;
55071b1b70fbSAndrew Rist nMainRow1 = 0;
55081b1b70fbSAndrew Rist nMainTab1 = 0;
55091b1b70fbSAndrew Rist SCSIZE nC, nR;
55101b1b70fbSAndrew Rist pMainMatrix->GetDimensions( nC, nR);
55111b1b70fbSAndrew Rist nMainCol2 = static_cast<SCCOL>(nC - 1);
55121b1b70fbSAndrew Rist nMainRow2 = static_cast<SCROW>(nR - 1);
55131b1b70fbSAndrew Rist nMainTab2 = 0;
55141b1b70fbSAndrew Rist }
55151b1b70fbSAndrew Rist break;
55161b1b70fbSAndrew Rist default:
55171b1b70fbSAndrew Rist SetError( errIllegalParameter);
55181b1b70fbSAndrew Rist }
55191b1b70fbSAndrew Rist if ( nMainTab1 != nMainTab2 )
55206e86bbc1SAndrew Rist SetError( errIllegalArgument);
55216e86bbc1SAndrew Rist
55226e86bbc1SAndrew Rist // All reference ranges must be of same dimension and size.
55236e86bbc1SAndrew Rist if ((nDimensionCols != (nMainCol2 - nMainCol1 + 1)) || (nDimensionRows != (nMainRow2 - nMainRow1 + 1)))
55246e86bbc1SAndrew Rist SetError ( errIllegalArgument);
55256e86bbc1SAndrew Rist
55266e86bbc1SAndrew Rist if (nGlobalError)
55276e86bbc1SAndrew Rist return 0; // bail out
55286e86bbc1SAndrew Rist
55291b1b70fbSAndrew Rist // end-result calculation
55301b1b70fbSAndrew Rist ScAddress aAdr;
55311b1b70fbSAndrew Rist aAdr.SetTab( nMainTab1 );
55321b1b70fbSAndrew Rist if (pMainMatrix)
55331b1b70fbSAndrew Rist {
55341b1b70fbSAndrew Rist SCSIZE nC, nR;
55351b1b70fbSAndrew Rist pResMat->GetDimensions(nC, nR);
55361b1b70fbSAndrew Rist for (SCSIZE nCol = 0; nCol < nC; ++nCol)
55371b1b70fbSAndrew Rist {
55381b1b70fbSAndrew Rist for (SCSIZE nRow = 0; nRow < nR; ++nRow)
55391b1b70fbSAndrew Rist {
55401b1b70fbSAndrew Rist if (pResMat->GetDouble( nCol, nRow) == nQueryCount)
55411b1b70fbSAndrew Rist {
55421b1b70fbSAndrew Rist if (pMainMatrix->IsValue( nCol, nRow))
55431b1b70fbSAndrew Rist {
55441b1b70fbSAndrew Rist fVal = pMainMatrix->GetDouble( nCol, nRow);
55451b1b70fbSAndrew Rist ++fCount;
55461b1b70fbSAndrew Rist if ( bNull && fVal != 0.0 )
55471b1b70fbSAndrew Rist {
55481b1b70fbSAndrew Rist bNull = false;
55491b1b70fbSAndrew Rist fMem = fVal;
55501b1b70fbSAndrew Rist }
55511b1b70fbSAndrew Rist else
55521b1b70fbSAndrew Rist fSum += fVal;
55531b1b70fbSAndrew Rist }
55541b1b70fbSAndrew Rist }
55551b1b70fbSAndrew Rist }
55561b1b70fbSAndrew Rist }
55571b1b70fbSAndrew Rist }
55581b1b70fbSAndrew Rist else
55591b1b70fbSAndrew Rist {
55601b1b70fbSAndrew Rist SCSIZE nC, nR;
55611b1b70fbSAndrew Rist pResMat->GetDimensions(nC, nR);
55621b1b70fbSAndrew Rist for (SCSIZE nCol = 0; nCol < nC; ++nCol)
55631b1b70fbSAndrew Rist {
55641b1b70fbSAndrew Rist for (SCSIZE nRow = 0; nRow < nR; ++nRow)
55651b1b70fbSAndrew Rist {
55661b1b70fbSAndrew Rist if (pResMat->GetDouble( nCol, nRow) == nQueryCount)
55671b1b70fbSAndrew Rist {
556841f10097SAndrew Rist aAdr.SetCol( static_cast<SCCOL>(nCol) + nMainCol1);
556941f10097SAndrew Rist aAdr.SetRow( static_cast<SCROW>(nRow) + nMainRow1);
55701b1b70fbSAndrew Rist ScBaseCell* pCell = GetCell( aAdr );
55711b1b70fbSAndrew Rist if ( HasCellValueData(pCell) )
55721b1b70fbSAndrew Rist {
55731b1b70fbSAndrew Rist fVal = GetCellValue( aAdr, pCell );
55741b1b70fbSAndrew Rist ++fCount;
55751b1b70fbSAndrew Rist if ( bNull && fVal != 0.0 )
55761b1b70fbSAndrew Rist {
55771b1b70fbSAndrew Rist bNull = false;
55781b1b70fbSAndrew Rist fMem = fVal;
55791b1b70fbSAndrew Rist }
55801b1b70fbSAndrew Rist else
55811b1b70fbSAndrew Rist fSum += fVal;
55821b1b70fbSAndrew Rist }
55831b1b70fbSAndrew Rist }
55841b1b70fbSAndrew Rist }
55851b1b70fbSAndrew Rist }
55861b1b70fbSAndrew Rist }
55871b1b70fbSAndrew Rist }
55881b1b70fbSAndrew Rist else
55891b1b70fbSAndrew Rist {
55901b1b70fbSAndrew Rist SCSIZE nC, nR;
55911b1b70fbSAndrew Rist pResMat->GetDimensions(nC, nR);
55921b1b70fbSAndrew Rist for (SCSIZE nCol = 0; nCol < nC; ++nCol)
55931b1b70fbSAndrew Rist {
55941b1b70fbSAndrew Rist for (SCSIZE nRow = 0; nRow < nR; ++nRow)
55951b1b70fbSAndrew Rist if (pResMat->GetDouble( nCol, nRow) == nQueryCount)
55961b1b70fbSAndrew Rist ++fCount;
55971b1b70fbSAndrew Rist }
55981b1b70fbSAndrew Rist }
55996e86bbc1SAndrew Rist
56001b1b70fbSAndrew Rist switch( eFunc )
56011b1b70fbSAndrew Rist {
56021b1b70fbSAndrew Rist case ifSUMIFS: fRes = ::rtl::math::approxAdd( fSum, fMem ); break;
56031b1b70fbSAndrew Rist case ifAVERAGEIFS: fRes = div( ::rtl::math::approxAdd( fSum, fMem ), fCount); break;
56041b1b70fbSAndrew Rist case ifCOUNTIFS: fRes = fCount; break;
56051b1b70fbSAndrew Rist default: ; // nothing
56061b1b70fbSAndrew Rist }
56071b1b70fbSAndrew Rist return fRes;
56081b1b70fbSAndrew Rist }
56091b1b70fbSAndrew Rist return 0;
56101b1b70fbSAndrew Rist }
56111b1b70fbSAndrew Rist
ScSumIfs()56121b1b70fbSAndrew Rist void ScInterpreter::ScSumIfs()
56131b1b70fbSAndrew Rist {
56141b1b70fbSAndrew Rist RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "makkica", "ScInterpreter::ScSumIfs" );
56151b1b70fbSAndrew Rist PushDouble( IterateParametersIfs( ifSUMIFS));
56161b1b70fbSAndrew Rist }
56171b1b70fbSAndrew Rist
ScAverageIfs()56181b1b70fbSAndrew Rist void ScInterpreter::ScAverageIfs()
56191b1b70fbSAndrew Rist {
56201b1b70fbSAndrew Rist RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "makkica", "ScInterpreter::ScAverageIfs" );
56211b1b70fbSAndrew Rist PushDouble( IterateParametersIfs( ifAVERAGEIFS));
56221b1b70fbSAndrew Rist }
56231b1b70fbSAndrew Rist
ScCountIfs()56241b1b70fbSAndrew Rist void ScInterpreter::ScCountIfs()
56251b1b70fbSAndrew Rist {
56261b1b70fbSAndrew Rist RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "makkica", "ScInterpreter::ScCountIfs" );
56271b1b70fbSAndrew Rist PushDouble( IterateParametersIfs( ifCOUNTIFS));
56281b1b70fbSAndrew Rist }
5629cdf0e10cSrcweir
ScLookup()5630cdf0e10cSrcweir void ScInterpreter::ScLookup()
5631cdf0e10cSrcweir {
5632cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScLookup" );
5633cdf0e10cSrcweir sal_uInt8 nParamCount = GetByte();
5634cdf0e10cSrcweir if ( !MustHaveParamCount( nParamCount, 2, 3 ) )
5635cdf0e10cSrcweir return ;
5636cdf0e10cSrcweir
5637cdf0e10cSrcweir ScMatrixRef pDataMat = NULL, pResMat = NULL;
5638cdf0e10cSrcweir SCCOL nCol1 = 0, nCol2 = 0, nResCol1 = 0, nResCol2 = 0;
5639cdf0e10cSrcweir SCROW nRow1 = 0, nRow2 = 0, nResRow1 = 0, nResRow2 = 0;
5640cdf0e10cSrcweir SCTAB nTab1 = 0, nResTab = 0;
5641cdf0e10cSrcweir SCSIZE nLenMajor = 0; // length of major direction
5642cdf0e10cSrcweir bool bVertical = true; // whether to lookup vertically or horizontally
5643cdf0e10cSrcweir
5644cdf0e10cSrcweir // The third parameter, result array, for double, string and single reference.
5645cdf0e10cSrcweir double fResVal = 0.0;
5646cdf0e10cSrcweir String aResStr;
5647cdf0e10cSrcweir ScAddress aResAdr;
5648cdf0e10cSrcweir StackVar eResArrayType = svUnknown;
5649cdf0e10cSrcweir
5650cdf0e10cSrcweir if (nParamCount == 3)
5651cdf0e10cSrcweir {
5652cdf0e10cSrcweir eResArrayType = GetStackType();
5653cdf0e10cSrcweir switch (eResArrayType)
5654cdf0e10cSrcweir {
5655cdf0e10cSrcweir case svDoubleRef:
5656cdf0e10cSrcweir {
5657cdf0e10cSrcweir SCTAB nTabJunk;
5658cdf0e10cSrcweir PopDoubleRef(nResCol1, nResRow1, nResTab,
5659cdf0e10cSrcweir nResCol2, nResRow2, nTabJunk);
5660cdf0e10cSrcweir if (nResTab != nTabJunk ||
5661cdf0e10cSrcweir ((nResRow2 - nResRow1) > 0 && (nResCol2 - nResCol1) > 0))
5662cdf0e10cSrcweir {
5663cdf0e10cSrcweir // The result array must be a vector.
5664cdf0e10cSrcweir PushIllegalParameter();
5665cdf0e10cSrcweir return;
5666cdf0e10cSrcweir }
5667cdf0e10cSrcweir }
5668cdf0e10cSrcweir break;
5669cdf0e10cSrcweir case svMatrix:
5670cdf0e10cSrcweir {
5671cdf0e10cSrcweir pResMat = PopMatrix();
5672cdf0e10cSrcweir if (!pResMat)
5673cdf0e10cSrcweir {
5674cdf0e10cSrcweir PushIllegalParameter();
5675cdf0e10cSrcweir return;
5676cdf0e10cSrcweir }
5677cdf0e10cSrcweir SCSIZE nC, nR;
5678cdf0e10cSrcweir pResMat->GetDimensions(nC, nR);
5679cdf0e10cSrcweir if (nC != 1 && nR != 1)
5680cdf0e10cSrcweir {
5681cdf0e10cSrcweir // Result matrix must be a vector.
5682cdf0e10cSrcweir PushIllegalParameter();
5683cdf0e10cSrcweir return;
5684cdf0e10cSrcweir }
5685cdf0e10cSrcweir }
5686cdf0e10cSrcweir break;
5687cdf0e10cSrcweir case svDouble:
5688cdf0e10cSrcweir fResVal = GetDouble();
5689cdf0e10cSrcweir break;
5690cdf0e10cSrcweir case svString:
5691cdf0e10cSrcweir aResStr = GetString();
5692cdf0e10cSrcweir break;
5693cdf0e10cSrcweir case svSingleRef:
5694cdf0e10cSrcweir PopSingleRef( aResAdr );
5695cdf0e10cSrcweir break;
5696cdf0e10cSrcweir default:
5697cdf0e10cSrcweir PushIllegalParameter();
5698cdf0e10cSrcweir return;
5699cdf0e10cSrcweir }
5700cdf0e10cSrcweir }
5701cdf0e10cSrcweir
5702cdf0e10cSrcweir // For double, string and single reference.
5703cdf0e10cSrcweir double fDataVal = 0.0;
5704cdf0e10cSrcweir String aDataStr;
5705cdf0e10cSrcweir ScAddress aDataAdr;
5706cdf0e10cSrcweir bool bValueData = false;
5707cdf0e10cSrcweir
5708cdf0e10cSrcweir // Get the data-result range and also determine whether this is vertical
5709cdf0e10cSrcweir // lookup or horizontal lookup.
5710cdf0e10cSrcweir
5711cdf0e10cSrcweir StackVar eDataArrayType = GetStackType();
5712cdf0e10cSrcweir switch (eDataArrayType)
5713cdf0e10cSrcweir {
5714cdf0e10cSrcweir case svDoubleRef:
5715cdf0e10cSrcweir {
5716cdf0e10cSrcweir SCTAB nTabJunk;
5717cdf0e10cSrcweir PopDoubleRef(nCol1, nRow1, nTab1, nCol2, nRow2, nTabJunk);
5718cdf0e10cSrcweir if (nTab1 != nTabJunk)
5719cdf0e10cSrcweir {
5720cdf0e10cSrcweir PushIllegalParameter();
5721cdf0e10cSrcweir return;
5722cdf0e10cSrcweir }
5723cdf0e10cSrcweir bVertical = (nRow2 - nRow1) >= (nCol2 - nCol1);
5724cdf0e10cSrcweir nLenMajor = bVertical ? nRow2 - nRow1 + 1 : nCol2 - nCol1 + 1;
5725cdf0e10cSrcweir }
5726cdf0e10cSrcweir break;
5727cdf0e10cSrcweir case svMatrix:
5728cdf0e10cSrcweir {
5729cdf0e10cSrcweir pDataMat = PopMatrix();
5730cdf0e10cSrcweir if (!pDataMat)
5731cdf0e10cSrcweir {
5732cdf0e10cSrcweir PushIllegalParameter();
5733cdf0e10cSrcweir return;
5734cdf0e10cSrcweir }
5735cdf0e10cSrcweir
5736cdf0e10cSrcweir SCSIZE nC, nR;
5737cdf0e10cSrcweir pDataMat->GetDimensions(nC, nR);
5738cdf0e10cSrcweir bVertical = (nR >= nC);
5739cdf0e10cSrcweir nLenMajor = bVertical ? nR : nC;
5740cdf0e10cSrcweir }
5741cdf0e10cSrcweir break;
5742cdf0e10cSrcweir case svDouble:
5743cdf0e10cSrcweir {
5744cdf0e10cSrcweir fDataVal = GetDouble();
5745cdf0e10cSrcweir bValueData = true;
5746cdf0e10cSrcweir }
5747cdf0e10cSrcweir break;
5748cdf0e10cSrcweir case svString:
5749cdf0e10cSrcweir {
5750cdf0e10cSrcweir aDataStr = GetString();
5751cdf0e10cSrcweir }
5752cdf0e10cSrcweir break;
5753cdf0e10cSrcweir case svSingleRef:
5754cdf0e10cSrcweir {
5755cdf0e10cSrcweir PopSingleRef( aDataAdr );
5756cdf0e10cSrcweir const ScBaseCell* pDataCell = GetCell( aDataAdr );
5757cdf0e10cSrcweir if (HasCellEmptyData( pDataCell))
5758cdf0e10cSrcweir {
5759cdf0e10cSrcweir // Empty cells aren't found anywhere, bail out early.
5760cdf0e10cSrcweir SetError( NOTAVAILABLE);
5761cdf0e10cSrcweir }
5762cdf0e10cSrcweir else if (HasCellValueData( pDataCell))
5763cdf0e10cSrcweir {
5764cdf0e10cSrcweir fDataVal = GetCellValue( aDataAdr, pDataCell );
5765cdf0e10cSrcweir bValueData = true;
5766cdf0e10cSrcweir }
5767cdf0e10cSrcweir else
5768cdf0e10cSrcweir GetCellString( aDataStr, pDataCell );
5769cdf0e10cSrcweir }
5770cdf0e10cSrcweir break;
5771cdf0e10cSrcweir default:
5772cdf0e10cSrcweir SetError( errIllegalParameter);
5773cdf0e10cSrcweir }
5774cdf0e10cSrcweir
5775cdf0e10cSrcweir
5776cdf0e10cSrcweir if (nGlobalError)
5777cdf0e10cSrcweir {
5778cdf0e10cSrcweir PushError( nGlobalError);
5779cdf0e10cSrcweir return;
5780cdf0e10cSrcweir }
5781cdf0e10cSrcweir
5782cdf0e10cSrcweir // Get the lookup value.
5783cdf0e10cSrcweir
5784cdf0e10cSrcweir ScQueryParam aParam;
5785cdf0e10cSrcweir ScQueryEntry& rEntry = aParam.GetEntry(0);
5786cdf0e10cSrcweir if ( !FillEntry(rEntry) )
5787cdf0e10cSrcweir return;
5788cdf0e10cSrcweir
5789cdf0e10cSrcweir if ( eDataArrayType == svDouble || eDataArrayType == svString ||
5790cdf0e10cSrcweir eDataArrayType == svSingleRef )
5791cdf0e10cSrcweir {
5792cdf0e10cSrcweir // Delta position for a single value is always 0.
5793cdf0e10cSrcweir
5794cdf0e10cSrcweir // Found if data <= query, but not if query is string and found data is
5795cdf0e10cSrcweir // numeric or vice versa. This is how Excel does it but doesn't
5796cdf0e10cSrcweir // document it.
5797cdf0e10cSrcweir
5798cdf0e10cSrcweir bool bFound = false;
5799cdf0e10cSrcweir if ( bValueData )
5800cdf0e10cSrcweir {
5801cdf0e10cSrcweir if ( rEntry.bQueryByString )
5802cdf0e10cSrcweir bFound = false;
5803cdf0e10cSrcweir else
5804cdf0e10cSrcweir bFound = (fDataVal <= rEntry.nVal);
5805cdf0e10cSrcweir }
5806cdf0e10cSrcweir else
5807cdf0e10cSrcweir {
5808cdf0e10cSrcweir if ( !rEntry.bQueryByString )
5809cdf0e10cSrcweir bFound = false;
5810cdf0e10cSrcweir else
5811cdf0e10cSrcweir bFound = (ScGlobal::GetCollator()->compareString( aDataStr, *rEntry.pStr) <= 0);
5812cdf0e10cSrcweir }
5813cdf0e10cSrcweir
5814cdf0e10cSrcweir if (!bFound)
5815cdf0e10cSrcweir {
5816cdf0e10cSrcweir PushNA();
5817cdf0e10cSrcweir return;
5818cdf0e10cSrcweir }
5819cdf0e10cSrcweir
5820cdf0e10cSrcweir if (pResMat)
5821cdf0e10cSrcweir {
5822cdf0e10cSrcweir if (pResMat->IsValue( 0 ))
5823cdf0e10cSrcweir PushDouble(pResMat->GetDouble( 0 ));
5824cdf0e10cSrcweir else
5825cdf0e10cSrcweir PushString(pResMat->GetString( 0 ));
5826cdf0e10cSrcweir }
5827cdf0e10cSrcweir else if (nParamCount == 3)
5828cdf0e10cSrcweir {
5829cdf0e10cSrcweir switch (eResArrayType)
5830cdf0e10cSrcweir {
5831cdf0e10cSrcweir case svDouble:
5832cdf0e10cSrcweir PushDouble( fResVal );
5833cdf0e10cSrcweir break;
5834cdf0e10cSrcweir case svString:
5835cdf0e10cSrcweir PushString( aResStr );
5836cdf0e10cSrcweir break;
5837cdf0e10cSrcweir case svDoubleRef:
5838cdf0e10cSrcweir aResAdr.Set( nResCol1, nResRow1, nResTab);
5839cdf0e10cSrcweir // fallthru
5840cdf0e10cSrcweir case svSingleRef:
5841cdf0e10cSrcweir PushCellResultToken( true, aResAdr, NULL, NULL);
5842cdf0e10cSrcweir break;
5843cdf0e10cSrcweir default:
5844cdf0e10cSrcweir DBG_ERRORFILE( "ScInterpreter::ScLookup: unhandled eResArrayType, single value data");
5845cdf0e10cSrcweir }
5846cdf0e10cSrcweir }
5847cdf0e10cSrcweir else
5848cdf0e10cSrcweir {
5849cdf0e10cSrcweir switch (eDataArrayType)
5850cdf0e10cSrcweir {
5851cdf0e10cSrcweir case svDouble:
5852cdf0e10cSrcweir PushDouble( fDataVal );
5853cdf0e10cSrcweir break;
5854cdf0e10cSrcweir case svString:
5855cdf0e10cSrcweir PushString( aDataStr );
5856cdf0e10cSrcweir break;
5857cdf0e10cSrcweir case svSingleRef:
5858cdf0e10cSrcweir PushCellResultToken( true, aDataAdr, NULL, NULL);
5859cdf0e10cSrcweir break;
5860cdf0e10cSrcweir default:
5861cdf0e10cSrcweir DBG_ERRORFILE( "ScInterpreter::ScLookup: unhandled eDataArrayType, single value data");
5862cdf0e10cSrcweir }
5863cdf0e10cSrcweir }
5864cdf0e10cSrcweir return;
5865cdf0e10cSrcweir }
5866cdf0e10cSrcweir
5867cdf0e10cSrcweir // Now, perform the search to compute the delta position (nDelta).
5868cdf0e10cSrcweir
5869cdf0e10cSrcweir if (pDataMat)
5870cdf0e10cSrcweir {
5871cdf0e10cSrcweir // Data array is given as a matrix.
5872cdf0e10cSrcweir rEntry.bDoQuery = true;
5873cdf0e10cSrcweir rEntry.eOp = SC_LESS_EQUAL;
5874cdf0e10cSrcweir bool bFound = false;
5875cdf0e10cSrcweir
5876cdf0e10cSrcweir SCSIZE nC, nR;
5877cdf0e10cSrcweir pDataMat->GetDimensions(nC, nR);
5878cdf0e10cSrcweir
5879cdf0e10cSrcweir // In case of non-vector matrix, only search the first row or column.
5880cdf0e10cSrcweir ScMatrixRef pDataMat2;
5881cdf0e10cSrcweir if (bVertical)
5882cdf0e10cSrcweir {
5883cdf0e10cSrcweir ScMatrixRef pTempMat(new ScMatrix(1, nR));
5884cdf0e10cSrcweir for (SCSIZE i = 0; i < nR; ++i)
5885cdf0e10cSrcweir if (pDataMat->IsValue(0, i))
5886cdf0e10cSrcweir pTempMat->PutDouble(pDataMat->GetDouble(0, i), 0, i);
5887cdf0e10cSrcweir else
5888cdf0e10cSrcweir pTempMat->PutString(pDataMat->GetString(0, i), 0, i);
5889cdf0e10cSrcweir pDataMat2 = pTempMat;
5890cdf0e10cSrcweir }
5891cdf0e10cSrcweir else
5892cdf0e10cSrcweir {
5893cdf0e10cSrcweir ScMatrixRef pTempMat(new ScMatrix(nC, 1));
5894cdf0e10cSrcweir for (SCSIZE i = 0; i < nC; ++i)
5895cdf0e10cSrcweir if (pDataMat->IsValue(i, 0))
5896cdf0e10cSrcweir pTempMat->PutDouble(pDataMat->GetDouble(i, 0), i, 0);
5897cdf0e10cSrcweir else
5898cdf0e10cSrcweir pTempMat->PutString(pDataMat->GetString(i, 0), i, 0);
5899cdf0e10cSrcweir pDataMat2 = pTempMat;
5900cdf0e10cSrcweir }
5901cdf0e10cSrcweir
5902cdf0e10cSrcweir // binary search for non-equality mode (the source data is
5903cdf0e10cSrcweir // assumed to be sorted in ascending order).
5904cdf0e10cSrcweir
5905cdf0e10cSrcweir SCCOLROW nDelta = -1;
5906cdf0e10cSrcweir
5907cdf0e10cSrcweir SCSIZE nFirst = 0, nLast = nLenMajor-1; //, nHitIndex = 0;
5908cdf0e10cSrcweir for (SCSIZE nLen = nLast-nFirst; nLen > 0; nLen = nLast-nFirst)
5909cdf0e10cSrcweir {
5910cdf0e10cSrcweir SCSIZE nMid = nFirst + nLen/2;
5911cdf0e10cSrcweir sal_Int32 nCmp = lcl_CompareMatrix2Query( nMid, *pDataMat2, rEntry);
5912cdf0e10cSrcweir if (nCmp == 0)
5913cdf0e10cSrcweir {
5914cdf0e10cSrcweir // exact match. find the last item with the same value.
5915cdf0e10cSrcweir lcl_GetLastMatch( nMid, *pDataMat2, nLenMajor, false);
5916cdf0e10cSrcweir nDelta = nMid;
5917cdf0e10cSrcweir bFound = true;
5918cdf0e10cSrcweir break;
5919cdf0e10cSrcweir }
5920cdf0e10cSrcweir
5921cdf0e10cSrcweir if (nLen == 1) // first and last items are next to each other.
5922cdf0e10cSrcweir {
5923cdf0e10cSrcweir nDelta = nCmp < 0 ? nLast - 1 : nFirst - 1;
5924cdf0e10cSrcweir // If already the 1st item is greater there's nothing found.
5925cdf0e10cSrcweir bFound = (nDelta >= 0);
5926cdf0e10cSrcweir break;
5927cdf0e10cSrcweir }
5928cdf0e10cSrcweir
5929cdf0e10cSrcweir if (nCmp < 0)
5930cdf0e10cSrcweir nFirst = nMid;
5931cdf0e10cSrcweir else
5932cdf0e10cSrcweir nLast = nMid;
5933cdf0e10cSrcweir }
5934cdf0e10cSrcweir
5935cdf0e10cSrcweir if (nDelta == static_cast<SCCOLROW>(nLenMajor-2)) // last item
5936cdf0e10cSrcweir {
5937cdf0e10cSrcweir sal_Int32 nCmp = lcl_CompareMatrix2Query(nDelta+1, *pDataMat2, rEntry);
5938cdf0e10cSrcweir if (nCmp <= 0)
5939cdf0e10cSrcweir {
5940cdf0e10cSrcweir // either the last item is an exact match or the real
5941cdf0e10cSrcweir // hit is beyond the last item.
5942cdf0e10cSrcweir nDelta += 1;
5943cdf0e10cSrcweir bFound = true;
5944cdf0e10cSrcweir }
5945cdf0e10cSrcweir }
5946cdf0e10cSrcweir else if (nDelta > 0) // valid hit must be 2nd item or higher
5947cdf0e10cSrcweir {
5948cdf0e10cSrcweir // non-exact match
5949cdf0e10cSrcweir bFound = true;
5950cdf0e10cSrcweir }
5951cdf0e10cSrcweir
5952cdf0e10cSrcweir // With 0-9 < A-Z, if query is numeric and data found is string, or
5953cdf0e10cSrcweir // vice versa, the (yet another undocumented) Excel behavior is to
5954cdf0e10cSrcweir // return #N/A instead.
5955cdf0e10cSrcweir
5956cdf0e10cSrcweir if (bFound)
5957cdf0e10cSrcweir {
5958cdf0e10cSrcweir SCCOLROW i = nDelta;
5959cdf0e10cSrcweir SCSIZE n = pDataMat->GetElementCount();
5960cdf0e10cSrcweir if (static_cast<SCSIZE>(i) >= n)
5961cdf0e10cSrcweir i = static_cast<SCCOLROW>(n);
5962cdf0e10cSrcweir if (bool(rEntry.bQueryByString) == bool(pDataMat->IsValue(i)))
5963cdf0e10cSrcweir bFound = false;
5964cdf0e10cSrcweir }
5965cdf0e10cSrcweir
5966cdf0e10cSrcweir if (!bFound)
5967cdf0e10cSrcweir {
5968cdf0e10cSrcweir PushNA();
5969cdf0e10cSrcweir return;
5970cdf0e10cSrcweir }
5971cdf0e10cSrcweir
5972cdf0e10cSrcweir // Now that we've found the delta, push the result back to the cell.
5973cdf0e10cSrcweir
5974cdf0e10cSrcweir if (pResMat)
5975cdf0e10cSrcweir {
5976cdf0e10cSrcweir // result array is matrix.
5977cdf0e10cSrcweir if (static_cast<SCSIZE>(nDelta) >= pResMat->GetElementCount())
5978cdf0e10cSrcweir {
5979cdf0e10cSrcweir PushNA();
5980cdf0e10cSrcweir return;
5981cdf0e10cSrcweir }
5982cdf0e10cSrcweir if (pResMat->IsValue(nDelta))
5983cdf0e10cSrcweir PushDouble(pResMat->GetDouble(nDelta));
5984cdf0e10cSrcweir else
5985cdf0e10cSrcweir PushString(pResMat->GetString(nDelta));
5986cdf0e10cSrcweir }
5987cdf0e10cSrcweir else if (nParamCount == 3)
5988cdf0e10cSrcweir {
5989cdf0e10cSrcweir // result array is cell range.
5990cdf0e10cSrcweir ScAddress aAdr;
5991cdf0e10cSrcweir aAdr.SetTab(nResTab);
5992cdf0e10cSrcweir bool bResVertical = (nResRow2 - nResRow1) > 0;
5993cdf0e10cSrcweir if (bResVertical)
5994cdf0e10cSrcweir {
5995cdf0e10cSrcweir SCROW nTempRow = static_cast<SCROW>(nResRow1 + nDelta);
5996cdf0e10cSrcweir if (nTempRow > MAXROW)
5997cdf0e10cSrcweir {
5998cdf0e10cSrcweir PushDouble(0);
5999cdf0e10cSrcweir return;
6000cdf0e10cSrcweir }
6001cdf0e10cSrcweir aAdr.SetCol(nResCol1);
6002cdf0e10cSrcweir aAdr.SetRow(nTempRow);
6003cdf0e10cSrcweir }
6004cdf0e10cSrcweir else
6005cdf0e10cSrcweir {
6006cdf0e10cSrcweir SCCOL nTempCol = static_cast<SCCOL>(nResCol1 + nDelta);
6007cdf0e10cSrcweir if (nTempCol > MAXCOL)
6008cdf0e10cSrcweir {
6009cdf0e10cSrcweir PushDouble(0);
6010cdf0e10cSrcweir return;
6011cdf0e10cSrcweir }
6012cdf0e10cSrcweir aAdr.SetCol(nTempCol);
6013cdf0e10cSrcweir aAdr.SetRow(nResRow1);
6014cdf0e10cSrcweir }
6015cdf0e10cSrcweir PushCellResultToken(true, aAdr, NULL, NULL);
6016cdf0e10cSrcweir }
6017cdf0e10cSrcweir else
6018cdf0e10cSrcweir {
6019cdf0e10cSrcweir // no result array. Use the data array to get the final value from.
6020cdf0e10cSrcweir if (bVertical)
6021cdf0e10cSrcweir {
6022cdf0e10cSrcweir if (pDataMat->IsValue(nC-1, nDelta))
6023cdf0e10cSrcweir PushDouble(pDataMat->GetDouble(nC-1, nDelta));
6024cdf0e10cSrcweir else
6025cdf0e10cSrcweir PushString(pDataMat->GetString(nC-1, nDelta));
6026cdf0e10cSrcweir }
6027cdf0e10cSrcweir else
6028cdf0e10cSrcweir {
6029cdf0e10cSrcweir if (pDataMat->IsValue(nDelta, nR-1))
6030cdf0e10cSrcweir PushDouble(pDataMat->GetDouble(nDelta, nR-1));
6031cdf0e10cSrcweir else
6032cdf0e10cSrcweir PushString(pDataMat->GetString(nDelta, nR-1));
6033cdf0e10cSrcweir }
6034cdf0e10cSrcweir }
6035cdf0e10cSrcweir
6036cdf0e10cSrcweir return;
6037cdf0e10cSrcweir }
6038cdf0e10cSrcweir
6039cdf0e10cSrcweir // Perform cell range search.
6040cdf0e10cSrcweir
6041cdf0e10cSrcweir aParam.nCol1 = nCol1;
6042cdf0e10cSrcweir aParam.nRow1 = nRow1;
6043cdf0e10cSrcweir aParam.nCol2 = bVertical ? nCol1 : nCol2;
6044cdf0e10cSrcweir aParam.nRow2 = bVertical ? nRow2 : nRow1;
6045cdf0e10cSrcweir aParam.bByRow = bVertical;
6046cdf0e10cSrcweir aParam.bMixedComparison = true;
6047cdf0e10cSrcweir
6048cdf0e10cSrcweir rEntry.bDoQuery = sal_True;
6049cdf0e10cSrcweir rEntry.eOp = SC_LESS_EQUAL;
6050cdf0e10cSrcweir rEntry.nField = nCol1;
6051cdf0e10cSrcweir if ( rEntry.bQueryByString )
6052cdf0e10cSrcweir aParam.bRegExp = MayBeRegExp( *rEntry.pStr, pDok );
6053cdf0e10cSrcweir
6054cdf0e10cSrcweir ScQueryCellIterator aCellIter(pDok, nTab1, aParam, sal_False);
6055cdf0e10cSrcweir SCCOL nC;
6056cdf0e10cSrcweir SCROW nR;
6057cdf0e10cSrcweir // Advance Entry.nField in iterator upon switching columns if
6058cdf0e10cSrcweir // lookup in row.
6059cdf0e10cSrcweir aCellIter.SetAdvanceQueryParamEntryField(!bVertical);
6060cdf0e10cSrcweir if ( !aCellIter.FindEqualOrSortedLastInRange(nC, nR) )
6061cdf0e10cSrcweir {
6062cdf0e10cSrcweir PushNA();
6063cdf0e10cSrcweir return;
6064cdf0e10cSrcweir }
6065cdf0e10cSrcweir
6066cdf0e10cSrcweir SCCOLROW nDelta = bVertical ? static_cast<SCSIZE>(nR-nRow1) : static_cast<SCSIZE>(nC-nCol1);
6067cdf0e10cSrcweir
6068cdf0e10cSrcweir if (pResMat)
6069cdf0e10cSrcweir {
6070cdf0e10cSrcweir // Use the matrix result array.
6071cdf0e10cSrcweir if (pResMat->IsValue(nDelta))
6072cdf0e10cSrcweir PushDouble(pResMat->GetDouble(nDelta));
6073cdf0e10cSrcweir else
6074cdf0e10cSrcweir PushString(pResMat->GetString(nDelta));
6075cdf0e10cSrcweir }
6076cdf0e10cSrcweir else if (nParamCount == 3)
6077cdf0e10cSrcweir {
6078cdf0e10cSrcweir switch (eResArrayType)
6079cdf0e10cSrcweir {
6080cdf0e10cSrcweir case svDoubleRef:
6081cdf0e10cSrcweir {
6082cdf0e10cSrcweir // Use the result array vector. Note that the result array is assumed
6083cdf0e10cSrcweir // to be a vector (i.e. 1-dimensinoal array).
6084cdf0e10cSrcweir
6085cdf0e10cSrcweir ScAddress aAdr;
6086cdf0e10cSrcweir aAdr.SetTab(nResTab);
6087cdf0e10cSrcweir bool bResVertical = (nResRow2 - nResRow1) > 0;
6088cdf0e10cSrcweir if (bResVertical)
6089cdf0e10cSrcweir {
6090cdf0e10cSrcweir SCROW nTempRow = static_cast<SCROW>(nResRow1 + nDelta);
6091cdf0e10cSrcweir if (nTempRow > MAXROW)
6092cdf0e10cSrcweir {
6093cdf0e10cSrcweir PushDouble(0);
6094cdf0e10cSrcweir return;
6095cdf0e10cSrcweir }
6096cdf0e10cSrcweir aAdr.SetCol(nResCol1);
6097cdf0e10cSrcweir aAdr.SetRow(nTempRow);
6098cdf0e10cSrcweir }
6099cdf0e10cSrcweir else
6100cdf0e10cSrcweir {
6101cdf0e10cSrcweir SCCOL nTempCol = static_cast<SCCOL>(nResCol1 + nDelta);
6102cdf0e10cSrcweir if (nTempCol > MAXCOL)
6103cdf0e10cSrcweir {
6104cdf0e10cSrcweir PushDouble(0);
6105cdf0e10cSrcweir return;
6106cdf0e10cSrcweir }
6107cdf0e10cSrcweir aAdr.SetCol(nTempCol);
6108cdf0e10cSrcweir aAdr.SetRow(nResRow1);
6109cdf0e10cSrcweir }
6110cdf0e10cSrcweir PushCellResultToken( true, aAdr, NULL, NULL);
6111cdf0e10cSrcweir }
6112cdf0e10cSrcweir break;
6113cdf0e10cSrcweir case svDouble:
6114cdf0e10cSrcweir case svString:
6115cdf0e10cSrcweir case svSingleRef:
6116cdf0e10cSrcweir {
6117cdf0e10cSrcweir if (nDelta != 0)
6118cdf0e10cSrcweir PushNA();
6119cdf0e10cSrcweir else
6120cdf0e10cSrcweir {
6121cdf0e10cSrcweir switch (eResArrayType)
6122cdf0e10cSrcweir {
6123cdf0e10cSrcweir case svDouble:
6124cdf0e10cSrcweir PushDouble( fResVal );
6125cdf0e10cSrcweir break;
6126cdf0e10cSrcweir case svString:
6127cdf0e10cSrcweir PushString( aResStr );
6128cdf0e10cSrcweir break;
6129cdf0e10cSrcweir case svSingleRef:
6130cdf0e10cSrcweir PushCellResultToken( true, aResAdr, NULL, NULL);
6131cdf0e10cSrcweir break;
6132cdf0e10cSrcweir default:
6133cdf0e10cSrcweir ; // nothing
6134cdf0e10cSrcweir }
6135cdf0e10cSrcweir }
6136cdf0e10cSrcweir }
6137cdf0e10cSrcweir break;
6138cdf0e10cSrcweir default:
6139cdf0e10cSrcweir DBG_ERRORFILE( "ScInterpreter::ScLookup: unhandled eResArrayType, range search");
6140cdf0e10cSrcweir }
6141cdf0e10cSrcweir }
6142cdf0e10cSrcweir else
6143cdf0e10cSrcweir {
6144cdf0e10cSrcweir // Regardless of whether or not the result array exists, the last
6145cdf0e10cSrcweir // array is always used as the "result" array.
6146cdf0e10cSrcweir
6147cdf0e10cSrcweir ScAddress aAdr;
6148cdf0e10cSrcweir aAdr.SetTab(nTab1);
6149cdf0e10cSrcweir if (bVertical)
6150cdf0e10cSrcweir {
6151cdf0e10cSrcweir SCROW nTempRow = static_cast<SCROW>(nRow1 + nDelta);
6152cdf0e10cSrcweir if (nTempRow > MAXROW)
6153cdf0e10cSrcweir {
6154cdf0e10cSrcweir PushDouble(0);
6155cdf0e10cSrcweir return;
6156cdf0e10cSrcweir }
6157cdf0e10cSrcweir aAdr.SetCol(nCol2);
6158cdf0e10cSrcweir aAdr.SetRow(nTempRow);
6159cdf0e10cSrcweir }
6160cdf0e10cSrcweir else
6161cdf0e10cSrcweir {
6162cdf0e10cSrcweir SCCOL nTempCol = static_cast<SCCOL>(nCol1 + nDelta);
6163cdf0e10cSrcweir if (nTempCol > MAXCOL)
6164cdf0e10cSrcweir {
6165cdf0e10cSrcweir PushDouble(0);
6166cdf0e10cSrcweir return;
6167cdf0e10cSrcweir }
6168cdf0e10cSrcweir aAdr.SetCol(nTempCol);
6169cdf0e10cSrcweir aAdr.SetRow(nRow2);
6170cdf0e10cSrcweir }
6171cdf0e10cSrcweir PushCellResultToken(true, aAdr, NULL, NULL);
6172cdf0e10cSrcweir }
6173cdf0e10cSrcweir }
6174cdf0e10cSrcweir
6175cdf0e10cSrcweir
ScHLookup()6176cdf0e10cSrcweir void ScInterpreter::ScHLookup()
6177cdf0e10cSrcweir {
6178cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScHLookup" );
6179cdf0e10cSrcweir CalculateLookup(sal_True);
6180cdf0e10cSrcweir }
CalculateLookup(sal_Bool HLookup)6181cdf0e10cSrcweir void ScInterpreter::CalculateLookup(sal_Bool HLookup)
6182cdf0e10cSrcweir {
6183cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::CalculateLookup" );
6184cdf0e10cSrcweir sal_uInt8 nParamCount = GetByte();
6185cdf0e10cSrcweir if ( MustHaveParamCount( nParamCount, 3, 4 ) )
6186cdf0e10cSrcweir {
6187cdf0e10cSrcweir sal_Bool bSorted;
6188cdf0e10cSrcweir if (nParamCount == 4)
6189cdf0e10cSrcweir bSorted = GetBool();
6190cdf0e10cSrcweir else
6191cdf0e10cSrcweir bSorted = sal_True;
6192cdf0e10cSrcweir double fIndex = ::rtl::math::approxFloor( GetDouble() ) - 1.0;
6193cdf0e10cSrcweir ScMatrixRef pMat = NULL;
6194cdf0e10cSrcweir SCSIZE nC = 0, nR = 0;
6195cdf0e10cSrcweir SCCOL nCol1 = 0;
6196cdf0e10cSrcweir SCROW nRow1 = 0;
6197cdf0e10cSrcweir SCTAB nTab1 = 0;
6198cdf0e10cSrcweir SCCOL nCol2 = 0;
6199cdf0e10cSrcweir SCROW nRow2 = 0;
6200cdf0e10cSrcweir SCTAB nTab2;
6201cdf0e10cSrcweir if (GetStackType() == svDoubleRef)
6202cdf0e10cSrcweir {
6203cdf0e10cSrcweir PopDoubleRef(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
6204cdf0e10cSrcweir if (nTab1 != nTab2)
6205cdf0e10cSrcweir {
6206cdf0e10cSrcweir PushIllegalParameter();
6207cdf0e10cSrcweir return;
6208cdf0e10cSrcweir }
6209cdf0e10cSrcweir }
6210cdf0e10cSrcweir else if (GetStackType() == svMatrix)
6211cdf0e10cSrcweir {
6212cdf0e10cSrcweir pMat = PopMatrix();
6213cdf0e10cSrcweir if (pMat)
6214cdf0e10cSrcweir pMat->GetDimensions(nC, nR);
6215cdf0e10cSrcweir else
6216cdf0e10cSrcweir {
6217cdf0e10cSrcweir PushIllegalParameter();
6218cdf0e10cSrcweir return;
6219cdf0e10cSrcweir }
6220cdf0e10cSrcweir }
6221cdf0e10cSrcweir else
6222cdf0e10cSrcweir {
6223cdf0e10cSrcweir PushIllegalParameter();
6224cdf0e10cSrcweir return;
6225cdf0e10cSrcweir }
6226cdf0e10cSrcweir if ( fIndex < 0.0 || (HLookup ? (pMat ? (fIndex >= nR) : (fIndex+nRow1 > nRow2)) : (pMat ? (fIndex >= nC) : (fIndex+nCol1 > nCol2)) ) )
6227cdf0e10cSrcweir {
6228cdf0e10cSrcweir PushIllegalArgument();
6229cdf0e10cSrcweir return;
6230cdf0e10cSrcweir }
6231cdf0e10cSrcweir SCROW nZIndex = static_cast<SCROW>(fIndex);
6232cdf0e10cSrcweir SCCOL nSpIndex = static_cast<SCCOL>(fIndex);
6233cdf0e10cSrcweir
6234cdf0e10cSrcweir if (!pMat)
6235cdf0e10cSrcweir {
6236cdf0e10cSrcweir nZIndex += nRow1; // Wertzeile
6237cdf0e10cSrcweir nSpIndex = sal::static_int_cast<SCCOL>( nSpIndex + nCol1 ); // value column
6238cdf0e10cSrcweir }
6239cdf0e10cSrcweir
6240cdf0e10cSrcweir if (nGlobalError == 0)
6241cdf0e10cSrcweir {
6242cdf0e10cSrcweir ScQueryParam rParam;
6243cdf0e10cSrcweir rParam.nCol1 = nCol1;
6244cdf0e10cSrcweir rParam.nRow1 = nRow1;
6245cdf0e10cSrcweir if ( HLookup )
6246cdf0e10cSrcweir {
6247cdf0e10cSrcweir rParam.nCol2 = nCol2;
6248cdf0e10cSrcweir rParam.nRow2 = nRow1; // nur in der ersten Zeile suchen
6249cdf0e10cSrcweir rParam.bByRow = sal_False;
6250cdf0e10cSrcweir } // if ( HLookup )
6251cdf0e10cSrcweir else
6252cdf0e10cSrcweir {
6253cdf0e10cSrcweir rParam.nCol2 = nCol1; // nur in der ersten Spalte suchen
6254cdf0e10cSrcweir rParam.nRow2 = nRow2;
6255cdf0e10cSrcweir rParam.nTab = nTab1;
6256cdf0e10cSrcweir }
6257cdf0e10cSrcweir rParam.bMixedComparison = sal_True;
6258cdf0e10cSrcweir
6259cdf0e10cSrcweir ScQueryEntry& rEntry = rParam.GetEntry(0);
6260cdf0e10cSrcweir rEntry.bDoQuery = sal_True;
6261cdf0e10cSrcweir if ( bSorted )
6262cdf0e10cSrcweir rEntry.eOp = SC_LESS_EQUAL;
6263cdf0e10cSrcweir if ( !FillEntry(rEntry) )
6264cdf0e10cSrcweir return;
6265cdf0e10cSrcweir if ( rEntry.bQueryByString )
6266cdf0e10cSrcweir rParam.bRegExp = MayBeRegExp( *rEntry.pStr, pDok );
6267cdf0e10cSrcweir if (pMat)
6268cdf0e10cSrcweir {
6269cdf0e10cSrcweir SCSIZE nMatCount = HLookup ? nC : nR;
6270cdf0e10cSrcweir SCSIZE nDelta = SCSIZE_MAX;
6271cdf0e10cSrcweir if (rEntry.bQueryByString)
6272cdf0e10cSrcweir {
6273cdf0e10cSrcweir //!!!!!!!
6274cdf0e10cSrcweir //! TODO: enable regex on matrix strings
6275cdf0e10cSrcweir //!!!!!!!
6276cdf0e10cSrcweir String aParamStr = *rEntry.pStr;
6277cdf0e10cSrcweir if ( bSorted )
6278cdf0e10cSrcweir {
6279cdf0e10cSrcweir static CollatorWrapper* pCollator = ScGlobal::GetCollator();
6280cdf0e10cSrcweir for (SCSIZE i = 0; i < nMatCount; i++)
6281cdf0e10cSrcweir {
6282cdf0e10cSrcweir if (HLookup ? pMat->IsString(i, 0) : pMat->IsString(0, i))
6283cdf0e10cSrcweir {
6284cdf0e10cSrcweir sal_Int32 nRes =
6285cdf0e10cSrcweir pCollator->compareString( HLookup ? pMat->GetString(i,0) : pMat->GetString(0,i), aParamStr);
6286cdf0e10cSrcweir if (nRes <= 0)
6287cdf0e10cSrcweir nDelta = i;
6288cdf0e10cSrcweir else if (i>0) // #i2168# ignore first mismatch
6289cdf0e10cSrcweir i = nMatCount+1;
6290cdf0e10cSrcweir }
6291cdf0e10cSrcweir else
6292cdf0e10cSrcweir nDelta = i;
6293cdf0e10cSrcweir }
6294cdf0e10cSrcweir }
6295cdf0e10cSrcweir else
6296cdf0e10cSrcweir {
6297cdf0e10cSrcweir for (SCSIZE i = 0; i < nMatCount; i++)
6298cdf0e10cSrcweir {
6299cdf0e10cSrcweir if (HLookup ? pMat->IsString(i, 0) : pMat->IsString(0, i))
6300cdf0e10cSrcweir {
6301cdf0e10cSrcweir if ( ScGlobal::GetpTransliteration()->isEqual(
6302cdf0e10cSrcweir HLookup ? pMat->GetString(i,0) : pMat->GetString(0,i), aParamStr ) )
6303cdf0e10cSrcweir {
6304cdf0e10cSrcweir nDelta = i;
6305cdf0e10cSrcweir i = nMatCount + 1;
6306cdf0e10cSrcweir }
6307cdf0e10cSrcweir }
6308cdf0e10cSrcweir }
6309cdf0e10cSrcweir }
6310cdf0e10cSrcweir }
6311cdf0e10cSrcweir else
6312cdf0e10cSrcweir {
6313cdf0e10cSrcweir if ( bSorted )
6314cdf0e10cSrcweir {
6315cdf0e10cSrcweir // #i2168# ignore strings
6316cdf0e10cSrcweir for (SCSIZE i = 0; i < nMatCount; i++)
6317cdf0e10cSrcweir {
6318cdf0e10cSrcweir if (!(HLookup ? pMat->IsString(i, 0) : pMat->IsString(0, i)))
6319cdf0e10cSrcweir {
6320cdf0e10cSrcweir if ((HLookup ? pMat->GetDouble(i,0) : pMat->GetDouble(0,i)) <= rEntry.nVal)
6321cdf0e10cSrcweir nDelta = i;
6322cdf0e10cSrcweir else
6323cdf0e10cSrcweir i = nMatCount+1;
6324cdf0e10cSrcweir }
6325cdf0e10cSrcweir }
6326cdf0e10cSrcweir }
6327cdf0e10cSrcweir else
6328cdf0e10cSrcweir {
6329cdf0e10cSrcweir for (SCSIZE i = 0; i < nMatCount; i++)
6330cdf0e10cSrcweir {
6331cdf0e10cSrcweir if (!(HLookup ? pMat->IsString(i, 0) : pMat->IsString(0, i)))
6332cdf0e10cSrcweir {
6333cdf0e10cSrcweir if ((HLookup ? pMat->GetDouble(i,0) : pMat->GetDouble(0,i)) == rEntry.nVal)
6334cdf0e10cSrcweir {
6335cdf0e10cSrcweir nDelta = i;
6336cdf0e10cSrcweir i = nMatCount + 1;
6337cdf0e10cSrcweir }
6338cdf0e10cSrcweir }
6339cdf0e10cSrcweir }
6340cdf0e10cSrcweir }
6341cdf0e10cSrcweir }
6342cdf0e10cSrcweir if ( nDelta != SCSIZE_MAX )
6343cdf0e10cSrcweir {
6344cdf0e10cSrcweir SCSIZE nX = static_cast<SCSIZE>(nSpIndex);
6345cdf0e10cSrcweir SCSIZE nY = nDelta;
6346cdf0e10cSrcweir if ( HLookup )
6347cdf0e10cSrcweir {
6348cdf0e10cSrcweir nX = nDelta;
6349cdf0e10cSrcweir nY = static_cast<SCSIZE>(nZIndex);
6350cdf0e10cSrcweir }
6351cdf0e10cSrcweir if ( pMat->IsString( nX, nY) )
6352cdf0e10cSrcweir PushString(pMat->GetString( nX,nY));
6353cdf0e10cSrcweir else
6354cdf0e10cSrcweir PushDouble(pMat->GetDouble( nX,nY));
6355cdf0e10cSrcweir }
6356cdf0e10cSrcweir else
6357cdf0e10cSrcweir PushNA();
6358cdf0e10cSrcweir }
6359cdf0e10cSrcweir else
6360cdf0e10cSrcweir {
6361cdf0e10cSrcweir rEntry.nField = nCol1;
6362cdf0e10cSrcweir sal_Bool bFound = sal_False;
6363cdf0e10cSrcweir SCCOL nCol = 0;
6364cdf0e10cSrcweir SCROW nRow = 0;
6365cdf0e10cSrcweir if ( bSorted )
6366cdf0e10cSrcweir rEntry.eOp = SC_LESS_EQUAL;
6367cdf0e10cSrcweir if ( HLookup )
6368cdf0e10cSrcweir {
6369cdf0e10cSrcweir ScQueryCellIterator aCellIter(pDok, nTab1, rParam, sal_False);
6370cdf0e10cSrcweir // advance Entry.nField in Iterator upon switching columns
6371cdf0e10cSrcweir aCellIter.SetAdvanceQueryParamEntryField( sal_True );
6372cdf0e10cSrcweir if ( bSorted )
6373cdf0e10cSrcweir {
6374cdf0e10cSrcweir SCROW nRow1_temp;
6375cdf0e10cSrcweir bFound = aCellIter.FindEqualOrSortedLastInRange( nCol, nRow1_temp );
6376cdf0e10cSrcweir }
6377cdf0e10cSrcweir else if ( aCellIter.GetFirst() )
6378cdf0e10cSrcweir {
6379cdf0e10cSrcweir bFound = sal_True;
6380cdf0e10cSrcweir nCol = aCellIter.GetCol();
6381cdf0e10cSrcweir }
6382cdf0e10cSrcweir nRow = nZIndex;
6383cdf0e10cSrcweir } // if ( HLookup )
6384cdf0e10cSrcweir else
6385cdf0e10cSrcweir {
6386cdf0e10cSrcweir ScAddress aResultPos( nCol1, nRow1, nTab1);
6387cdf0e10cSrcweir bFound = LookupQueryWithCache( aResultPos, rParam);
6388cdf0e10cSrcweir nRow = aResultPos.Row();
6389cdf0e10cSrcweir nCol = nSpIndex;
6390cdf0e10cSrcweir }
6391cdf0e10cSrcweir if ( bFound )
6392cdf0e10cSrcweir {
6393cdf0e10cSrcweir ScAddress aAdr( nCol, nRow, nTab1 );
6394cdf0e10cSrcweir PushCellResultToken( true, aAdr, NULL, NULL);
6395cdf0e10cSrcweir }
6396cdf0e10cSrcweir else
6397cdf0e10cSrcweir PushNA();
6398cdf0e10cSrcweir }
6399cdf0e10cSrcweir }
6400cdf0e10cSrcweir else
6401cdf0e10cSrcweir PushIllegalParameter();
6402cdf0e10cSrcweir }
6403cdf0e10cSrcweir }
6404cdf0e10cSrcweir
FillEntry(ScQueryEntry & rEntry)6405cdf0e10cSrcweir bool ScInterpreter::FillEntry(ScQueryEntry& rEntry)
6406cdf0e10cSrcweir {
6407cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::FillEntry" );
6408cdf0e10cSrcweir switch ( GetStackType() )
6409cdf0e10cSrcweir {
6410cdf0e10cSrcweir case svDouble:
6411cdf0e10cSrcweir {
6412cdf0e10cSrcweir rEntry.bQueryByString = sal_False;
6413cdf0e10cSrcweir rEntry.nVal = GetDouble();
6414cdf0e10cSrcweir }
6415cdf0e10cSrcweir break;
6416cdf0e10cSrcweir case svString:
6417cdf0e10cSrcweir {
6418cdf0e10cSrcweir const String sStr = GetString();
6419cdf0e10cSrcweir rEntry.bQueryByString = sal_True;
6420cdf0e10cSrcweir *rEntry.pStr = sStr;
6421cdf0e10cSrcweir }
6422cdf0e10cSrcweir break;
6423cdf0e10cSrcweir case svDoubleRef :
6424cdf0e10cSrcweir case svSingleRef :
6425cdf0e10cSrcweir {
6426cdf0e10cSrcweir ScAddress aAdr;
6427cdf0e10cSrcweir if ( !PopDoubleRefOrSingleRef( aAdr ) )
6428cdf0e10cSrcweir {
6429cdf0e10cSrcweir PushInt(0);
6430cdf0e10cSrcweir return false;
6431cdf0e10cSrcweir }
6432cdf0e10cSrcweir ScBaseCell* pCell = GetCell( aAdr );
6433cdf0e10cSrcweir if (HasCellValueData(pCell))
6434cdf0e10cSrcweir {
6435cdf0e10cSrcweir rEntry.bQueryByString = sal_False;
6436cdf0e10cSrcweir rEntry.nVal = GetCellValue( aAdr, pCell );
6437cdf0e10cSrcweir }
6438cdf0e10cSrcweir else
6439cdf0e10cSrcweir {
6440cdf0e10cSrcweir if ( GetCellType( pCell ) == CELLTYPE_NOTE )
6441cdf0e10cSrcweir {
6442cdf0e10cSrcweir rEntry.bQueryByString = sal_False;
6443cdf0e10cSrcweir rEntry.nVal = 0.0;
6444cdf0e10cSrcweir }
6445cdf0e10cSrcweir else
6446cdf0e10cSrcweir {
6447cdf0e10cSrcweir String sStr;
6448cdf0e10cSrcweir GetCellString(sStr, pCell);
6449cdf0e10cSrcweir rEntry.bQueryByString = sal_True;
6450cdf0e10cSrcweir *rEntry.pStr = sStr;
6451cdf0e10cSrcweir }
6452cdf0e10cSrcweir }
6453cdf0e10cSrcweir }
6454cdf0e10cSrcweir break;
6455cdf0e10cSrcweir case svMatrix :
6456cdf0e10cSrcweir {
6457cdf0e10cSrcweir const ScMatValType nType = GetDoubleOrStringFromMatrix(rEntry.nVal, *rEntry.pStr);
6458cdf0e10cSrcweir rEntry.bQueryByString = ScMatrix::IsNonValueType( nType);
6459cdf0e10cSrcweir }
6460cdf0e10cSrcweir break;
6461cdf0e10cSrcweir default:
6462cdf0e10cSrcweir {
6463cdf0e10cSrcweir PushIllegalParameter();
6464cdf0e10cSrcweir return false;
6465cdf0e10cSrcweir }
6466cdf0e10cSrcweir } // switch ( GetStackType() )
6467cdf0e10cSrcweir return true;
6468cdf0e10cSrcweir }
ScVLookup()6469cdf0e10cSrcweir void ScInterpreter::ScVLookup()
6470cdf0e10cSrcweir {
6471cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScVLookup" );
6472cdf0e10cSrcweir CalculateLookup(sal_False);
6473cdf0e10cSrcweir }
6474cdf0e10cSrcweir
ScSubTotal()6475cdf0e10cSrcweir void ScInterpreter::ScSubTotal()
6476cdf0e10cSrcweir {
6477cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScSubTotal" );
6478cdf0e10cSrcweir sal_uInt8 nParamCount = GetByte();
6479cdf0e10cSrcweir if ( MustHaveParamCountMin( nParamCount, 2 ) )
6480cdf0e10cSrcweir {
6481cdf0e10cSrcweir // We must fish the 1st parameter deep from the stack! And push it on top.
6482cdf0e10cSrcweir const FormulaToken* p = pStack[ sp - nParamCount ];
6483cdf0e10cSrcweir PushTempToken( *p );
6484cdf0e10cSrcweir int nFunc = (int) ::rtl::math::approxFloor( GetDouble() );
6485cdf0e10cSrcweir if( nFunc < 1 || nFunc > 11 )
6486cdf0e10cSrcweir PushIllegalArgument(); // simulate return on stack, not SetError(...)
6487cdf0e10cSrcweir else
6488cdf0e10cSrcweir {
6489cdf0e10cSrcweir cPar = nParamCount - 1;
6490cdf0e10cSrcweir glSubTotal = sal_True;
6491cdf0e10cSrcweir switch( nFunc )
6492cdf0e10cSrcweir {
6493cdf0e10cSrcweir case SUBTOTAL_FUNC_AVE : ScAverage(); break;
6494cdf0e10cSrcweir case SUBTOTAL_FUNC_CNT : ScCount(); break;
6495cdf0e10cSrcweir case SUBTOTAL_FUNC_CNT2 : ScCount2(); break;
6496cdf0e10cSrcweir case SUBTOTAL_FUNC_MAX : ScMax(); break;
6497cdf0e10cSrcweir case SUBTOTAL_FUNC_MIN : ScMin(); break;
6498cdf0e10cSrcweir case SUBTOTAL_FUNC_PROD : ScProduct(); break;
6499cdf0e10cSrcweir case SUBTOTAL_FUNC_STD : ScStDev(); break;
6500cdf0e10cSrcweir case SUBTOTAL_FUNC_STDP : ScStDevP(); break;
6501cdf0e10cSrcweir case SUBTOTAL_FUNC_SUM : ScSum(); break;
6502cdf0e10cSrcweir case SUBTOTAL_FUNC_VAR : ScVar(); break;
6503cdf0e10cSrcweir case SUBTOTAL_FUNC_VARP : ScVarP(); break;
6504cdf0e10cSrcweir default : PushIllegalArgument(); break;
6505cdf0e10cSrcweir }
6506cdf0e10cSrcweir glSubTotal = sal_False;
6507cdf0e10cSrcweir }
6508cdf0e10cSrcweir // Get rid of the 1st (fished) parameter.
6509cdf0e10cSrcweir double nVal = GetDouble();
6510cdf0e10cSrcweir Pop();
6511cdf0e10cSrcweir PushDouble( nVal );
6512cdf0e10cSrcweir }
6513cdf0e10cSrcweir }
6514cdf0e10cSrcweir
GetDBParams(sal_Bool & rMissingField)6515cdf0e10cSrcweir ScDBQueryParamBase* ScInterpreter::GetDBParams( sal_Bool& rMissingField )
6516cdf0e10cSrcweir {
6517cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::GetDBParams" );
6518cdf0e10cSrcweir sal_Bool bAllowMissingField = sal_False;
6519cdf0e10cSrcweir if ( rMissingField )
6520cdf0e10cSrcweir {
6521cdf0e10cSrcweir bAllowMissingField = sal_True;
6522cdf0e10cSrcweir rMissingField = sal_False;
6523cdf0e10cSrcweir }
6524cdf0e10cSrcweir if ( GetByte() == 3 )
6525cdf0e10cSrcweir {
6526cdf0e10cSrcweir // First, get the query criteria range.
6527cdf0e10cSrcweir ::std::auto_ptr<ScDBRangeBase> pQueryRef( PopDoubleRef() );
6528cdf0e10cSrcweir if (!pQueryRef.get())
6529cdf0e10cSrcweir return NULL;
6530cdf0e10cSrcweir
6531cdf0e10cSrcweir sal_Bool bByVal = sal_True;
6532cdf0e10cSrcweir double nVal = 0.0;
6533cdf0e10cSrcweir String aStr;
6534cdf0e10cSrcweir ScRange aMissingRange;
6535cdf0e10cSrcweir sal_Bool bRangeFake = sal_False;
6536cdf0e10cSrcweir switch (GetStackType())
6537cdf0e10cSrcweir {
6538cdf0e10cSrcweir case svDouble :
6539cdf0e10cSrcweir nVal = ::rtl::math::approxFloor( GetDouble() );
6540cdf0e10cSrcweir if ( bAllowMissingField && nVal == 0.0 )
6541cdf0e10cSrcweir rMissingField = sal_True; // fake missing parameter
6542cdf0e10cSrcweir break;
6543cdf0e10cSrcweir case svString :
6544cdf0e10cSrcweir bByVal = sal_False;
6545cdf0e10cSrcweir aStr = GetString();
6546cdf0e10cSrcweir break;
6547cdf0e10cSrcweir case svSingleRef :
6548cdf0e10cSrcweir {
6549cdf0e10cSrcweir ScAddress aAdr;
6550cdf0e10cSrcweir PopSingleRef( aAdr );
6551cdf0e10cSrcweir ScBaseCell* pCell = GetCell( aAdr );
6552cdf0e10cSrcweir if (HasCellValueData(pCell))
6553cdf0e10cSrcweir nVal = GetCellValue( aAdr, pCell );
6554cdf0e10cSrcweir else
6555cdf0e10cSrcweir {
6556cdf0e10cSrcweir bByVal = sal_False;
6557cdf0e10cSrcweir GetCellString(aStr, pCell);
6558cdf0e10cSrcweir }
6559cdf0e10cSrcweir }
6560cdf0e10cSrcweir break;
6561cdf0e10cSrcweir case svDoubleRef :
6562cdf0e10cSrcweir if ( bAllowMissingField )
6563cdf0e10cSrcweir { // fake missing parameter for old SO compatibility
6564cdf0e10cSrcweir bRangeFake = sal_True;
6565cdf0e10cSrcweir PopDoubleRef( aMissingRange );
6566cdf0e10cSrcweir }
6567cdf0e10cSrcweir else
6568cdf0e10cSrcweir {
6569cdf0e10cSrcweir PopError();
6570cdf0e10cSrcweir SetError( errIllegalParameter );
6571cdf0e10cSrcweir }
6572cdf0e10cSrcweir break;
6573cdf0e10cSrcweir case svMissing :
6574cdf0e10cSrcweir PopError();
6575cdf0e10cSrcweir if ( bAllowMissingField )
6576cdf0e10cSrcweir rMissingField = sal_True;
6577cdf0e10cSrcweir else
6578cdf0e10cSrcweir SetError( errIllegalParameter );
6579cdf0e10cSrcweir break;
6580cdf0e10cSrcweir default:
6581cdf0e10cSrcweir PopError();
6582cdf0e10cSrcweir SetError( errIllegalParameter );
6583cdf0e10cSrcweir }
6584cdf0e10cSrcweir
6585cdf0e10cSrcweir auto_ptr<ScDBRangeBase> pDBRef( PopDoubleRef() );
6586cdf0e10cSrcweir
6587cdf0e10cSrcweir if (nGlobalError || !pDBRef.get())
6588cdf0e10cSrcweir return NULL;
6589cdf0e10cSrcweir
6590cdf0e10cSrcweir if ( bRangeFake )
6591cdf0e10cSrcweir {
6592cdf0e10cSrcweir // range parameter must match entire database range
6593cdf0e10cSrcweir if (pDBRef->isRangeEqual(aMissingRange))
6594cdf0e10cSrcweir rMissingField = sal_True;
6595cdf0e10cSrcweir else
6596cdf0e10cSrcweir SetError( errIllegalParameter );
6597cdf0e10cSrcweir }
6598cdf0e10cSrcweir
6599cdf0e10cSrcweir if (nGlobalError)
6600cdf0e10cSrcweir return NULL;
6601cdf0e10cSrcweir
6602cdf0e10cSrcweir SCCOL nField = pDBRef->getFirstFieldColumn();
6603cdf0e10cSrcweir if (rMissingField)
6604cdf0e10cSrcweir ; // special case
6605cdf0e10cSrcweir else if (bByVal)
6606cdf0e10cSrcweir nField = pDBRef->findFieldColumn(static_cast<SCCOL>(nVal));
6607cdf0e10cSrcweir else
6608cdf0e10cSrcweir {
6609cdf0e10cSrcweir sal_uInt16 nErr = 0;
6610cdf0e10cSrcweir nField = pDBRef->findFieldColumn(aStr, &nErr);
6611cdf0e10cSrcweir SetError(nErr);
6612cdf0e10cSrcweir }
6613cdf0e10cSrcweir
6614cdf0e10cSrcweir if (!ValidCol(nField))
6615cdf0e10cSrcweir return NULL;
6616cdf0e10cSrcweir
6617cdf0e10cSrcweir auto_ptr<ScDBQueryParamBase> pParam( pDBRef->createQueryParam(pQueryRef.get()) );
6618cdf0e10cSrcweir
6619cdf0e10cSrcweir if (pParam.get())
6620cdf0e10cSrcweir {
6621cdf0e10cSrcweir // An allowed missing field parameter sets the result field
6622cdf0e10cSrcweir // to any of the query fields, just to be able to return
6623cdf0e10cSrcweir // some cell from the iterator.
6624cdf0e10cSrcweir if ( rMissingField )
6625cdf0e10cSrcweir nField = static_cast<SCCOL>(pParam->GetEntry(0).nField);
6626cdf0e10cSrcweir pParam->mnField = nField;
6627cdf0e10cSrcweir
6628cdf0e10cSrcweir SCSIZE nCount = pParam->GetEntryCount();
6629cdf0e10cSrcweir for ( SCSIZE i=0; i < nCount; i++ )
6630cdf0e10cSrcweir {
6631cdf0e10cSrcweir ScQueryEntry& rEntry = pParam->GetEntry(i);
6632cdf0e10cSrcweir if ( rEntry.bDoQuery )
6633cdf0e10cSrcweir {
6634cdf0e10cSrcweir sal_uInt32 nIndex = 0;
6635cdf0e10cSrcweir rEntry.bQueryByString = !pFormatter->IsNumberFormat(
6636cdf0e10cSrcweir *rEntry.pStr, nIndex, rEntry.nVal );
6637cdf0e10cSrcweir if ( rEntry.bQueryByString && !pParam->bRegExp )
6638cdf0e10cSrcweir pParam->bRegExp = MayBeRegExp( *rEntry.pStr, pDok );
6639cdf0e10cSrcweir }
6640cdf0e10cSrcweir else
6641cdf0e10cSrcweir break; // for
6642cdf0e10cSrcweir }
6643cdf0e10cSrcweir return pParam.release();
6644cdf0e10cSrcweir }
6645cdf0e10cSrcweir }
664646d2a04eSHerbert Dürr return NULL;
6647cdf0e10cSrcweir }
6648cdf0e10cSrcweir
6649cdf0e10cSrcweir
DBIterator(ScIterFunc eFunc)6650cdf0e10cSrcweir void ScInterpreter::DBIterator( ScIterFunc eFunc )
6651cdf0e10cSrcweir {
6652cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::DBIterator" );
6653cdf0e10cSrcweir double nErg = 0.0;
6654cdf0e10cSrcweir double fMem = 0.0;
6655cdf0e10cSrcweir sal_Bool bNull = sal_True;
6656cdf0e10cSrcweir sal_uLong nCount = 0;
6657cdf0e10cSrcweir sal_Bool bMissingField = sal_False;
6658cdf0e10cSrcweir auto_ptr<ScDBQueryParamBase> pQueryParam( GetDBParams(bMissingField) );
6659cdf0e10cSrcweir if (pQueryParam.get())
6660cdf0e10cSrcweir {
6661cdf0e10cSrcweir ScDBQueryDataIterator aValIter(pDok, pQueryParam.release());
6662cdf0e10cSrcweir ScDBQueryDataIterator::Value aValue;
6663cdf0e10cSrcweir if ( aValIter.GetFirst(aValue) && !aValue.mnError )
6664cdf0e10cSrcweir {
6665cdf0e10cSrcweir switch( eFunc )
6666cdf0e10cSrcweir {
6667cdf0e10cSrcweir case ifPRODUCT: nErg = 1; break;
6668cdf0e10cSrcweir case ifMAX: nErg = -MAXDOUBLE; break;
6669cdf0e10cSrcweir case ifMIN: nErg = MAXDOUBLE; break;
6670cdf0e10cSrcweir default: ; // nothing
6671cdf0e10cSrcweir }
6672cdf0e10cSrcweir do
6673cdf0e10cSrcweir {
6674cdf0e10cSrcweir nCount++;
6675cdf0e10cSrcweir switch( eFunc )
6676cdf0e10cSrcweir {
6677cdf0e10cSrcweir case ifAVERAGE:
6678cdf0e10cSrcweir case ifSUM:
6679cdf0e10cSrcweir if ( bNull && aValue.mfValue != 0.0 )
6680cdf0e10cSrcweir {
6681cdf0e10cSrcweir bNull = sal_False;
6682cdf0e10cSrcweir fMem = aValue.mfValue;
6683cdf0e10cSrcweir }
6684cdf0e10cSrcweir else
6685cdf0e10cSrcweir nErg += aValue.mfValue;
6686cdf0e10cSrcweir break;
6687cdf0e10cSrcweir case ifSUMSQ: nErg += aValue.mfValue * aValue.mfValue; break;
6688cdf0e10cSrcweir case ifPRODUCT: nErg *= aValue.mfValue; break;
6689cdf0e10cSrcweir case ifMAX: if( aValue.mfValue > nErg ) nErg = aValue.mfValue; break;
6690cdf0e10cSrcweir case ifMIN: if( aValue.mfValue < nErg ) nErg = aValue.mfValue; break;
6691cdf0e10cSrcweir default: ; // nothing
6692cdf0e10cSrcweir }
6693cdf0e10cSrcweir }
6694cdf0e10cSrcweir while ( aValIter.GetNext(aValue) && !aValue.mnError );
6695cdf0e10cSrcweir }
6696cdf0e10cSrcweir SetError(aValue.mnError);
6697cdf0e10cSrcweir }
6698cdf0e10cSrcweir else
6699cdf0e10cSrcweir SetError( errIllegalParameter);
6700cdf0e10cSrcweir switch( eFunc )
6701cdf0e10cSrcweir {
6702cdf0e10cSrcweir case ifCOUNT: nErg = nCount; break;
6703cdf0e10cSrcweir case ifSUM: nErg = ::rtl::math::approxAdd( nErg, fMem ); break;
6704cdf0e10cSrcweir case ifAVERAGE: nErg = ::rtl::math::approxAdd( nErg, fMem ) / nCount; break;
6705cdf0e10cSrcweir default: ; // nothing
6706cdf0e10cSrcweir }
6707cdf0e10cSrcweir PushDouble( nErg );
6708cdf0e10cSrcweir }
6709cdf0e10cSrcweir
6710cdf0e10cSrcweir
ScDBSum()6711cdf0e10cSrcweir void ScInterpreter::ScDBSum()
6712cdf0e10cSrcweir {
6713cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScDBSum" );
6714cdf0e10cSrcweir DBIterator( ifSUM );
6715cdf0e10cSrcweir }
6716cdf0e10cSrcweir
6717cdf0e10cSrcweir
ScDBCount()6718cdf0e10cSrcweir void ScInterpreter::ScDBCount()
6719cdf0e10cSrcweir {
6720cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScDBCount" );
6721cdf0e10cSrcweir sal_Bool bMissingField = sal_True;
6722cdf0e10cSrcweir auto_ptr<ScDBQueryParamBase> pQueryParam( GetDBParams(bMissingField) );
6723cdf0e10cSrcweir if (pQueryParam.get())
6724cdf0e10cSrcweir {
6725cdf0e10cSrcweir sal_uLong nCount = 0;
6726cdf0e10cSrcweir if ( bMissingField && pQueryParam->GetType() == ScDBQueryParamBase::INTERNAL )
6727cdf0e10cSrcweir { // count all matching records
6728cdf0e10cSrcweir // TODO: currently the QueryIterators only return cell pointers of
6729cdf0e10cSrcweir // existing cells, so if a query matches an empty cell there's
6730cdf0e10cSrcweir // nothing returned, and therefor not counted!
6731cdf0e10cSrcweir // Since this has ever been the case and this code here only came
673286e1cf34SPedro Giffuni // into existence to fix #i6899 and it never worked before we'll
6733cdf0e10cSrcweir // have to live with it until we reimplement the iterators to also
6734cdf0e10cSrcweir // return empty cells, which would mean to adapt all callers of
6735cdf0e10cSrcweir // iterators.
6736cdf0e10cSrcweir ScDBQueryParamInternal* p = static_cast<ScDBQueryParamInternal*>(pQueryParam.get());
6737cdf0e10cSrcweir SCTAB nTab = p->nTab;
6738cdf0e10cSrcweir // ScQueryCellIterator doesn't make use of ScDBQueryParamBase::mnField,
6739cdf0e10cSrcweir // so the source range has to be restricted, like before the introduction
6740cdf0e10cSrcweir // of ScDBQueryParamBase.
6741cdf0e10cSrcweir p->nCol1 = p->nCol2 = p->mnField;
6742cdf0e10cSrcweir ScQueryCellIterator aCellIter( pDok, nTab, *p);
6743cdf0e10cSrcweir if ( aCellIter.GetFirst() )
6744cdf0e10cSrcweir {
6745cdf0e10cSrcweir do
6746cdf0e10cSrcweir {
6747cdf0e10cSrcweir nCount++;
6748cdf0e10cSrcweir } while ( aCellIter.GetNext() );
6749cdf0e10cSrcweir }
6750cdf0e10cSrcweir }
6751cdf0e10cSrcweir else
6752cdf0e10cSrcweir { // count only matching records with a value in the "result" field
6753cdf0e10cSrcweir ScDBQueryDataIterator aValIter( pDok, pQueryParam.release());
6754cdf0e10cSrcweir ScDBQueryDataIterator::Value aValue;
6755cdf0e10cSrcweir if ( aValIter.GetFirst(aValue) && !aValue.mnError )
6756cdf0e10cSrcweir {
6757cdf0e10cSrcweir do
6758cdf0e10cSrcweir {
6759cdf0e10cSrcweir nCount++;
6760cdf0e10cSrcweir }
6761cdf0e10cSrcweir while ( aValIter.GetNext(aValue) && !aValue.mnError );
6762cdf0e10cSrcweir }
6763cdf0e10cSrcweir SetError(aValue.mnError);
6764cdf0e10cSrcweir }
6765cdf0e10cSrcweir PushDouble( nCount );
6766cdf0e10cSrcweir }
6767cdf0e10cSrcweir else
6768cdf0e10cSrcweir PushIllegalParameter();
6769cdf0e10cSrcweir }
6770cdf0e10cSrcweir
6771cdf0e10cSrcweir
ScDBCount2()6772cdf0e10cSrcweir void ScInterpreter::ScDBCount2()
6773cdf0e10cSrcweir {
6774cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScDBCount2" );
6775cdf0e10cSrcweir sal_Bool bMissingField = sal_True;
6776cdf0e10cSrcweir auto_ptr<ScDBQueryParamBase> pQueryParam( GetDBParams(bMissingField) );
6777cdf0e10cSrcweir if (pQueryParam.get())
6778cdf0e10cSrcweir {
6779cdf0e10cSrcweir sal_uLong nCount = 0;
6780cdf0e10cSrcweir pQueryParam->mbSkipString = false;
6781cdf0e10cSrcweir ScDBQueryDataIterator aValIter( pDok, pQueryParam.release());
6782cdf0e10cSrcweir ScDBQueryDataIterator::Value aValue;
6783cdf0e10cSrcweir if ( aValIter.GetFirst(aValue) && !aValue.mnError )
6784cdf0e10cSrcweir {
6785cdf0e10cSrcweir do
6786cdf0e10cSrcweir {
6787cdf0e10cSrcweir nCount++;
6788cdf0e10cSrcweir }
6789cdf0e10cSrcweir while ( aValIter.GetNext(aValue) && !aValue.mnError );
6790cdf0e10cSrcweir }
6791cdf0e10cSrcweir SetError(aValue.mnError);
6792cdf0e10cSrcweir PushDouble( nCount );
6793cdf0e10cSrcweir }
6794cdf0e10cSrcweir else
6795cdf0e10cSrcweir PushIllegalParameter();
6796cdf0e10cSrcweir }
6797cdf0e10cSrcweir
6798cdf0e10cSrcweir
ScDBAverage()6799cdf0e10cSrcweir void ScInterpreter::ScDBAverage()
6800cdf0e10cSrcweir {
6801cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScDBAverage" );
6802cdf0e10cSrcweir DBIterator( ifAVERAGE );
6803cdf0e10cSrcweir }
6804cdf0e10cSrcweir
6805cdf0e10cSrcweir
ScDBMax()6806cdf0e10cSrcweir void ScInterpreter::ScDBMax()
6807cdf0e10cSrcweir {
6808cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScDBMax" );
6809cdf0e10cSrcweir DBIterator( ifMAX );
6810cdf0e10cSrcweir }
6811cdf0e10cSrcweir
6812cdf0e10cSrcweir
ScDBMin()6813cdf0e10cSrcweir void ScInterpreter::ScDBMin()
6814cdf0e10cSrcweir {
6815cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScDBMin" );
6816cdf0e10cSrcweir DBIterator( ifMIN );
6817cdf0e10cSrcweir }
6818cdf0e10cSrcweir
6819cdf0e10cSrcweir
ScDBProduct()6820cdf0e10cSrcweir void ScInterpreter::ScDBProduct()
6821cdf0e10cSrcweir {
6822cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScDBProduct" );
6823cdf0e10cSrcweir DBIterator( ifPRODUCT );
6824cdf0e10cSrcweir }
6825cdf0e10cSrcweir
6826cdf0e10cSrcweir
GetDBStVarParams(double & rVal,double & rValCount)6827cdf0e10cSrcweir void ScInterpreter::GetDBStVarParams( double& rVal, double& rValCount )
6828cdf0e10cSrcweir {
6829cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::GetDBStVarParams" );
6830cdf0e10cSrcweir std::vector<double> values;
6831cdf0e10cSrcweir double vSum = 0.0;
6832cdf0e10cSrcweir double vMean = 0.0;
6833cdf0e10cSrcweir
6834cdf0e10cSrcweir rValCount = 0.0;
6835cdf0e10cSrcweir double fSum = 0.0;
6836cdf0e10cSrcweir sal_Bool bMissingField = sal_False;
6837cdf0e10cSrcweir auto_ptr<ScDBQueryParamBase> pQueryParam( GetDBParams(bMissingField) );
6838cdf0e10cSrcweir if (pQueryParam.get())
6839cdf0e10cSrcweir {
6840cdf0e10cSrcweir ScDBQueryDataIterator aValIter(pDok, pQueryParam.release());
6841cdf0e10cSrcweir ScDBQueryDataIterator::Value aValue;
6842cdf0e10cSrcweir if (aValIter.GetFirst(aValue) && !aValue.mnError)
6843cdf0e10cSrcweir {
6844cdf0e10cSrcweir do
6845cdf0e10cSrcweir {
6846cdf0e10cSrcweir rValCount++;
6847cdf0e10cSrcweir values.push_back(aValue.mfValue);
6848cdf0e10cSrcweir fSum += aValue.mfValue;
6849cdf0e10cSrcweir }
6850cdf0e10cSrcweir while ((aValue.mnError == 0) && aValIter.GetNext(aValue));
6851cdf0e10cSrcweir }
6852cdf0e10cSrcweir SetError(aValue.mnError);
6853cdf0e10cSrcweir }
6854cdf0e10cSrcweir else
6855cdf0e10cSrcweir SetError( errIllegalParameter);
6856cdf0e10cSrcweir
6857cdf0e10cSrcweir vMean = fSum / values.size();
6858cdf0e10cSrcweir
6859cdf0e10cSrcweir for (size_t i = 0; i < values.size(); i++)
6860cdf0e10cSrcweir vSum += (values[i] - vMean) * (values[i] - vMean);
6861cdf0e10cSrcweir
6862cdf0e10cSrcweir rVal = vSum;
6863cdf0e10cSrcweir }
6864cdf0e10cSrcweir
6865cdf0e10cSrcweir
ScDBStdDev()6866cdf0e10cSrcweir void ScInterpreter::ScDBStdDev()
6867cdf0e10cSrcweir {
6868cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScDBStdDev" );
6869cdf0e10cSrcweir double fVal, fCount;
6870cdf0e10cSrcweir GetDBStVarParams( fVal, fCount );
6871cdf0e10cSrcweir PushDouble( sqrt(fVal/(fCount-1)));
6872cdf0e10cSrcweir }
6873cdf0e10cSrcweir
6874cdf0e10cSrcweir
ScDBStdDevP()6875cdf0e10cSrcweir void ScInterpreter::ScDBStdDevP()
6876cdf0e10cSrcweir {
6877cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScDBStdDevP" );
6878cdf0e10cSrcweir double fVal, fCount;
6879cdf0e10cSrcweir GetDBStVarParams( fVal, fCount );
6880cdf0e10cSrcweir PushDouble( sqrt(fVal/fCount));
6881cdf0e10cSrcweir }
6882cdf0e10cSrcweir
6883cdf0e10cSrcweir
ScDBVar()6884cdf0e10cSrcweir void ScInterpreter::ScDBVar()
6885cdf0e10cSrcweir {
6886cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScDBVar" );
6887cdf0e10cSrcweir double fVal, fCount;
6888cdf0e10cSrcweir GetDBStVarParams( fVal, fCount );
6889cdf0e10cSrcweir PushDouble(fVal/(fCount-1));
6890cdf0e10cSrcweir }
6891cdf0e10cSrcweir
6892cdf0e10cSrcweir
ScDBVarP()6893cdf0e10cSrcweir void ScInterpreter::ScDBVarP()
6894cdf0e10cSrcweir {
6895cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScDBVarP" );
6896cdf0e10cSrcweir double fVal, fCount;
6897cdf0e10cSrcweir GetDBStVarParams( fVal, fCount );
6898cdf0e10cSrcweir PushDouble(fVal/fCount);
6899cdf0e10cSrcweir }
6900cdf0e10cSrcweir
6901cdf0e10cSrcweir
lcl_CreateExternalRefSubroutine(const ScAddress & rPos,ScDocument * pDoc,const ScAddress::ExternalInfo & rExtInfo,const ScRefAddress & rRefAd1,const ScRefAddress * pRefAd2)6902cdf0e10cSrcweir FormulaSubroutineToken* lcl_CreateExternalRefSubroutine( const ScAddress& rPos, ScDocument* pDoc,
6903cdf0e10cSrcweir const ScAddress::ExternalInfo& rExtInfo, const ScRefAddress& rRefAd1,
6904cdf0e10cSrcweir const ScRefAddress* pRefAd2 )
6905cdf0e10cSrcweir {
6906cdf0e10cSrcweir ScExternalRefManager* pRefMgr = pDoc->GetExternalRefManager();
6907cdf0e10cSrcweir size_t nSheets = 1;
6908cdf0e10cSrcweir const String* pRealTab = pRefMgr->getRealTableName( rExtInfo.mnFileId, rExtInfo.maTabName);
6909cdf0e10cSrcweir ScTokenArray* pTokenArray = new ScTokenArray;
6910cdf0e10cSrcweir if (pRefAd2)
6911cdf0e10cSrcweir {
6912cdf0e10cSrcweir ScComplexRefData aRef;
6913cdf0e10cSrcweir aRef.InitRangeRel( ScRange( rRefAd1.GetAddress(), pRefAd2->GetAddress()), rPos);
6914cdf0e10cSrcweir aRef.Ref1.SetColRel( rRefAd1.IsRelCol());
6915cdf0e10cSrcweir aRef.Ref1.SetRowRel( rRefAd1.IsRelRow());
6916cdf0e10cSrcweir aRef.Ref1.SetTabRel( rRefAd1.IsRelTab());
6917cdf0e10cSrcweir aRef.Ref1.SetFlag3D( true);
6918cdf0e10cSrcweir aRef.Ref2.SetColRel( pRefAd2->IsRelCol());
6919cdf0e10cSrcweir aRef.Ref2.SetRowRel( pRefAd2->IsRelRow());
6920cdf0e10cSrcweir aRef.Ref2.SetTabRel( pRefAd2->IsRelTab());
6921cdf0e10cSrcweir nSheets = aRef.Ref2.nTab - aRef.Ref1.nTab + 1;
6922cdf0e10cSrcweir aRef.Ref2.SetFlag3D( nSheets > 1 );
6923cdf0e10cSrcweir pTokenArray->AddExternalDoubleReference( rExtInfo.mnFileId,
6924cdf0e10cSrcweir (pRealTab ? *pRealTab : rExtInfo.maTabName), aRef);
6925cdf0e10cSrcweir }
6926cdf0e10cSrcweir else
6927cdf0e10cSrcweir {
6928cdf0e10cSrcweir ScSingleRefData aRef;
6929cdf0e10cSrcweir aRef.InitAddressRel( rRefAd1.GetAddress(), rPos);
6930cdf0e10cSrcweir aRef.SetColRel( rRefAd1.IsRelCol());
6931cdf0e10cSrcweir aRef.SetRowRel( rRefAd1.IsRelRow());
6932cdf0e10cSrcweir aRef.SetTabRel( rRefAd1.IsRelTab());
6933cdf0e10cSrcweir aRef.SetFlag3D( true);
6934cdf0e10cSrcweir pTokenArray->AddExternalSingleReference( rExtInfo.mnFileId,
6935cdf0e10cSrcweir (pRealTab ? *pRealTab : rExtInfo.maTabName), aRef);
6936cdf0e10cSrcweir }
6937cdf0e10cSrcweir // The indirect usage of the external table can't be detected during the
6938cdf0e10cSrcweir // store-to-file cycle, mark it as permanently referenced so it gets stored
6939cdf0e10cSrcweir // even if not directly referenced anywhere.
6940cdf0e10cSrcweir pRefMgr->setCacheTableReferencedPermanently( rExtInfo.mnFileId,
6941cdf0e10cSrcweir rExtInfo.maTabName, nSheets);
6942cdf0e10cSrcweir ScCompiler aComp( pDoc, rPos, *pTokenArray);
6943cdf0e10cSrcweir aComp.CompileTokenArray();
6944cdf0e10cSrcweir return new FormulaSubroutineToken( pTokenArray);
6945cdf0e10cSrcweir }
6946cdf0e10cSrcweir
6947cdf0e10cSrcweir
ScIndirect()6948cdf0e10cSrcweir void ScInterpreter::ScIndirect()
6949cdf0e10cSrcweir {
6950cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScIndirect" );
6951cdf0e10cSrcweir sal_uInt8 nParamCount = GetByte();
6952cdf0e10cSrcweir if ( MustHaveParamCount( nParamCount, 1, 2 ) )
6953cdf0e10cSrcweir {
6954cdf0e10cSrcweir bool bTryXlA1 = true; // whether to try XL_A1 style as well.
6955cdf0e10cSrcweir FormulaGrammar::AddressConvention eConv = FormulaGrammar::CONV_OOO;
6956cdf0e10cSrcweir if (nParamCount == 2 && 0.0 == ::rtl::math::approxFloor( GetDouble()))
6957cdf0e10cSrcweir {
6958cdf0e10cSrcweir eConv = FormulaGrammar::CONV_XL_R1C1;
6959cdf0e10cSrcweir bTryXlA1 = false;
6960cdf0e10cSrcweir }
6961cdf0e10cSrcweir const ScAddress::Details aDetails( eConv, aPos );
6962cdf0e10cSrcweir const ScAddress::Details aDetailsXlA1( FormulaGrammar::CONV_XL_A1, aPos );
6963cdf0e10cSrcweir SCTAB nTab = aPos.Tab();
6964cdf0e10cSrcweir String sRefStr( GetString() );
6965cdf0e10cSrcweir ScRefAddress aRefAd, aRefAd2;
6966cdf0e10cSrcweir ScAddress::ExternalInfo aExtInfo;
6967cdf0e10cSrcweir if ( ConvertDoubleRef( pDok, sRefStr, nTab, aRefAd, aRefAd2, aDetails, &aExtInfo) ||
6968cdf0e10cSrcweir (bTryXlA1 && ConvertDoubleRef( pDok, sRefStr, nTab, aRefAd,
6969cdf0e10cSrcweir aRefAd2, aDetailsXlA1, &aExtInfo)))
6970cdf0e10cSrcweir {
6971cdf0e10cSrcweir if (aExtInfo.mbExternal)
6972cdf0e10cSrcweir {
6973cdf0e10cSrcweir // Push a subroutine that resolves the external reference as
6974cdf0e10cSrcweir // the next instruction.
6975cdf0e10cSrcweir PushTempToken( lcl_CreateExternalRefSubroutine( aPos, pDok,
6976cdf0e10cSrcweir aExtInfo, aRefAd, &aRefAd2));
6977cdf0e10cSrcweir }
6978cdf0e10cSrcweir else
6979cdf0e10cSrcweir PushDoubleRef( aRefAd.Col(), aRefAd.Row(), aRefAd.Tab(),
6980cdf0e10cSrcweir aRefAd2.Col(), aRefAd2.Row(), aRefAd2.Tab() );
6981cdf0e10cSrcweir }
6982cdf0e10cSrcweir else if ( ConvertSingleRef ( pDok, sRefStr, nTab, aRefAd, aDetails, &aExtInfo) ||
6983cdf0e10cSrcweir (bTryXlA1 && ConvertSingleRef ( pDok, sRefStr, nTab, aRefAd,
6984cdf0e10cSrcweir aDetailsXlA1, &aExtInfo)))
6985cdf0e10cSrcweir {
6986cdf0e10cSrcweir if (aExtInfo.mbExternal)
6987cdf0e10cSrcweir {
6988cdf0e10cSrcweir // Push a subroutine that resolves the external reference as
6989cdf0e10cSrcweir // the next instruction.
6990cdf0e10cSrcweir PushTempToken( lcl_CreateExternalRefSubroutine( aPos, pDok,
6991cdf0e10cSrcweir aExtInfo, aRefAd, NULL));
6992cdf0e10cSrcweir }
6993cdf0e10cSrcweir else
6994cdf0e10cSrcweir PushSingleRef( aRefAd.Col(), aRefAd.Row(), aRefAd.Tab() );
6995cdf0e10cSrcweir }
6996cdf0e10cSrcweir else
6997cdf0e10cSrcweir {
6998cdf0e10cSrcweir do
6999cdf0e10cSrcweir {
7000cdf0e10cSrcweir ScRangeName* pNames = pDok->GetRangeName();
7001cdf0e10cSrcweir if (!pNames)
7002cdf0e10cSrcweir break;
7003cdf0e10cSrcweir
7004cdf0e10cSrcweir sal_uInt16 nPos = 0;
7005cdf0e10cSrcweir if (!pNames->SearchName( sRefStr, nPos))
7006cdf0e10cSrcweir break;
7007cdf0e10cSrcweir
7008cdf0e10cSrcweir ScRangeData* rData = (*pNames)[nPos];
7009cdf0e10cSrcweir if (!rData)
7010cdf0e10cSrcweir break;
7011cdf0e10cSrcweir
7012cdf0e10cSrcweir // We need this in order to obtain a good range.
7013cdf0e10cSrcweir rData->ValidateTabRefs();
7014cdf0e10cSrcweir
7015cdf0e10cSrcweir ScRange aRange;
7016cdf0e10cSrcweir #if 0
7017cdf0e10cSrcweir // This is some really odd Excel behavior and renders named
7018cdf0e10cSrcweir // ranges containing relative references totally useless.
7019cdf0e10cSrcweir if (!rData->IsReference(aRange, ScAddress( aPos.Tab(), 0, 0)))
7020cdf0e10cSrcweir break;
7021cdf0e10cSrcweir #else
7022cdf0e10cSrcweir // This is the usual way to treat named ranges containing
7023cdf0e10cSrcweir // relative references.
7024cdf0e10cSrcweir if (!rData->IsReference( aRange, aPos))
7025cdf0e10cSrcweir break;
7026cdf0e10cSrcweir #endif
7027cdf0e10cSrcweir
7028cdf0e10cSrcweir if (aRange.aStart == aRange.aEnd)
7029cdf0e10cSrcweir PushSingleRef( aRange.aStart.Col(), aRange.aStart.Row(),
7030cdf0e10cSrcweir aRange.aStart.Tab());
7031cdf0e10cSrcweir else
7032cdf0e10cSrcweir PushDoubleRef( aRange.aStart.Col(), aRange.aStart.Row(),
7033cdf0e10cSrcweir aRange.aStart.Tab(), aRange.aEnd.Col(),
7034cdf0e10cSrcweir aRange.aEnd.Row(), aRange.aEnd.Tab());
7035cdf0e10cSrcweir
7036cdf0e10cSrcweir // success!
7037cdf0e10cSrcweir return;
7038cdf0e10cSrcweir }
7039cdf0e10cSrcweir while (false);
7040cdf0e10cSrcweir
7041cdf0e10cSrcweir PushIllegalArgument();
7042cdf0e10cSrcweir }
7043cdf0e10cSrcweir }
7044cdf0e10cSrcweir }
7045cdf0e10cSrcweir
7046cdf0e10cSrcweir
ScAddressFunc()7047cdf0e10cSrcweir void ScInterpreter::ScAddressFunc()
7048cdf0e10cSrcweir {
7049cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScAddressFunc" );
7050cdf0e10cSrcweir String sTabStr;
7051cdf0e10cSrcweir
7052cdf0e10cSrcweir sal_uInt8 nParamCount = GetByte();
7053cdf0e10cSrcweir if( !MustHaveParamCount( nParamCount, 2, 5 ) )
7054cdf0e10cSrcweir return;
7055cdf0e10cSrcweir
7056cdf0e10cSrcweir if( nParamCount >= 5 )
7057cdf0e10cSrcweir sTabStr = GetString();
7058cdf0e10cSrcweir
7059cdf0e10cSrcweir FormulaGrammar::AddressConvention eConv = FormulaGrammar::CONV_OOO; // default
7060cdf0e10cSrcweir if( nParamCount >= 4 && 0.0 == ::rtl::math::approxFloor( GetDoubleWithDefault( 1.0)))
7061cdf0e10cSrcweir eConv = FormulaGrammar::CONV_XL_R1C1;
7062cdf0e10cSrcweir
7063cdf0e10cSrcweir sal_uInt16 nFlags = SCA_COL_ABSOLUTE | SCA_ROW_ABSOLUTE; // default
7064cdf0e10cSrcweir if( nParamCount >= 3 )
7065cdf0e10cSrcweir {
7066cdf0e10cSrcweir sal_uInt16 n = (sal_uInt16) ::rtl::math::approxFloor( GetDoubleWithDefault( 1.0));
7067cdf0e10cSrcweir switch ( n )
7068cdf0e10cSrcweir {
7069cdf0e10cSrcweir default :
7070cdf0e10cSrcweir PushNoValue();
7071cdf0e10cSrcweir return;
7072cdf0e10cSrcweir
7073cdf0e10cSrcweir case 5:
7074cdf0e10cSrcweir case 1 : break; // default
7075cdf0e10cSrcweir case 6:
7076cdf0e10cSrcweir case 2 : nFlags = SCA_ROW_ABSOLUTE; break;
7077cdf0e10cSrcweir case 7:
7078cdf0e10cSrcweir case 3 : nFlags = SCA_COL_ABSOLUTE; break;
7079cdf0e10cSrcweir case 8:
7080cdf0e10cSrcweir case 4 : nFlags = 0; break; // both relative
7081cdf0e10cSrcweir }
7082cdf0e10cSrcweir }
7083cdf0e10cSrcweir nFlags |= SCA_VALID | SCA_VALID_ROW | SCA_VALID_COL;
7084cdf0e10cSrcweir
7085cdf0e10cSrcweir SCCOL nCol = (SCCOL) ::rtl::math::approxFloor(GetDouble());
7086cdf0e10cSrcweir SCROW nRow = (SCROW) ::rtl::math::approxFloor(GetDouble());
7087cdf0e10cSrcweir if( eConv == FormulaGrammar::CONV_XL_R1C1 )
7088cdf0e10cSrcweir {
7089cdf0e10cSrcweir // YUCK! The XL interface actually treats rel R1C1 refs differently
7090cdf0e10cSrcweir // than A1
7091cdf0e10cSrcweir if( !(nFlags & SCA_COL_ABSOLUTE) )
7092cdf0e10cSrcweir nCol += aPos.Col() + 1;
7093cdf0e10cSrcweir if( !(nFlags & SCA_ROW_ABSOLUTE) )
7094cdf0e10cSrcweir nRow += aPos.Row() + 1;
7095cdf0e10cSrcweir }
7096cdf0e10cSrcweir
7097cdf0e10cSrcweir --nCol;
7098cdf0e10cSrcweir --nRow;
7099cdf0e10cSrcweir if(!ValidCol( nCol) || !ValidRow( nRow))
7100cdf0e10cSrcweir {
7101cdf0e10cSrcweir PushIllegalArgument();
7102cdf0e10cSrcweir return;
7103cdf0e10cSrcweir }
7104cdf0e10cSrcweir
7105cdf0e10cSrcweir String aRefStr;
7106cdf0e10cSrcweir const ScAddress::Details aDetails( eConv, aPos );
7107cdf0e10cSrcweir const ScAddress aAdr( nCol, nRow, 0);
7108cdf0e10cSrcweir aAdr.Format( aRefStr, nFlags, pDok, aDetails );
7109cdf0e10cSrcweir
7110cdf0e10cSrcweir if( nParamCount >= 5 && sTabStr.Len() )
7111cdf0e10cSrcweir {
7112cdf0e10cSrcweir String aDoc;
7113cdf0e10cSrcweir if (eConv == FormulaGrammar::CONV_OOO)
7114cdf0e10cSrcweir {
7115cdf0e10cSrcweir // Isolate Tab from 'Doc'#Tab
7116cdf0e10cSrcweir xub_StrLen nPos = ScCompiler::GetDocTabPos( sTabStr);
7117cdf0e10cSrcweir if (nPos != STRING_NOTFOUND)
7118cdf0e10cSrcweir {
7119cdf0e10cSrcweir if (sTabStr.GetChar(nPos+1) == '$')
7120cdf0e10cSrcweir ++nPos; // also split 'Doc'#$Tab
7121cdf0e10cSrcweir aDoc = sTabStr.Copy( 0, nPos+1);
7122cdf0e10cSrcweir sTabStr.Erase( 0, nPos+1);
7123cdf0e10cSrcweir }
7124cdf0e10cSrcweir }
7125cdf0e10cSrcweir /* TODO: yet unsupported external reference in CONV_XL_R1C1 syntax may
7126cdf0e10cSrcweir * need some extra handling to isolate Tab from Doc. */
7127cdf0e10cSrcweir if (sTabStr.GetChar(0) != '\'' || sTabStr.GetChar(sTabStr.Len()-1) != '\'')
7128cdf0e10cSrcweir ScCompiler::CheckTabQuotes( sTabStr, eConv);
7129cdf0e10cSrcweir if (aDoc.Len())
7130cdf0e10cSrcweir sTabStr.Insert( aDoc, 0);
7131cdf0e10cSrcweir sTabStr += static_cast<sal_Unicode>(eConv == FormulaGrammar::CONV_XL_R1C1 ? '!' : '.');
7132cdf0e10cSrcweir sTabStr += aRefStr;
7133cdf0e10cSrcweir PushString( sTabStr );
7134cdf0e10cSrcweir }
7135cdf0e10cSrcweir else
7136cdf0e10cSrcweir PushString( aRefStr );
7137cdf0e10cSrcweir }
7138cdf0e10cSrcweir
7139cdf0e10cSrcweir
lcl_CreateExternalRefSubroutine(const ScAddress & rPos,ScDocument * pDoc,const FormulaTokenRef & xExtRef)7140cdf0e10cSrcweir FormulaSubroutineToken* lcl_CreateExternalRefSubroutine( const ScAddress& rPos,
7141cdf0e10cSrcweir ScDocument* pDoc, const FormulaTokenRef& xExtRef )
7142cdf0e10cSrcweir {
7143cdf0e10cSrcweir // The exact usage (which cell range) of the external table can't be
7144cdf0e10cSrcweir // detected during the store-to-file cycle, mark it as permanently
7145cdf0e10cSrcweir // referenced so it gets stored even if not directly referenced anywhere.
7146cdf0e10cSrcweir ScExternalRefManager* pRefMgr = pDoc->GetExternalRefManager();
7147cdf0e10cSrcweir pRefMgr->setCacheTableReferencedPermanently(
7148cdf0e10cSrcweir static_cast<const ScToken*>(xExtRef.get())->GetIndex(),
7149cdf0e10cSrcweir static_cast<const ScToken*>(xExtRef.get())->GetString(), 1);
7150cdf0e10cSrcweir ScTokenArray* pTokenArray = new ScTokenArray;
7151cdf0e10cSrcweir pTokenArray->AddToken( *xExtRef);
7152cdf0e10cSrcweir ScCompiler aComp( pDoc, rPos, *pTokenArray);
7153cdf0e10cSrcweir aComp.CompileTokenArray();
7154cdf0e10cSrcweir return new FormulaSubroutineToken( pTokenArray);
7155cdf0e10cSrcweir }
7156cdf0e10cSrcweir
7157cdf0e10cSrcweir
ScOffset()7158cdf0e10cSrcweir void ScInterpreter::ScOffset()
7159cdf0e10cSrcweir {
7160cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScOffset" );
7161cdf0e10cSrcweir sal_uInt8 nParamCount = GetByte();
7162cdf0e10cSrcweir if ( MustHaveParamCount( nParamCount, 3, 5 ) )
7163cdf0e10cSrcweir {
7164cdf0e10cSrcweir long nColNew = -1, nRowNew = -1, nColPlus, nRowPlus;
7165cdf0e10cSrcweir if (nParamCount == 5)
7166cdf0e10cSrcweir nColNew = (long) ::rtl::math::approxFloor(GetDouble());
7167cdf0e10cSrcweir if (nParamCount >= 4)
7168cdf0e10cSrcweir nRowNew = (long) ::rtl::math::approxFloor(GetDoubleWithDefault( -1.0 ));
7169cdf0e10cSrcweir nColPlus = (long) ::rtl::math::approxFloor(GetDouble());
7170cdf0e10cSrcweir nRowPlus = (long) ::rtl::math::approxFloor(GetDouble());
7171cdf0e10cSrcweir SCCOL nCol1;
7172cdf0e10cSrcweir SCROW nRow1;
7173cdf0e10cSrcweir SCTAB nTab1;
7174cdf0e10cSrcweir SCCOL nCol2;
7175cdf0e10cSrcweir SCROW nRow2;
7176cdf0e10cSrcweir SCTAB nTab2;
7177cdf0e10cSrcweir if (nColNew == 0 || nRowNew == 0)
7178cdf0e10cSrcweir {
7179cdf0e10cSrcweir PushIllegalArgument();
7180cdf0e10cSrcweir return;
7181cdf0e10cSrcweir }
7182cdf0e10cSrcweir FormulaTokenRef xExtRef;
7183cdf0e10cSrcweir switch (GetStackType())
7184cdf0e10cSrcweir {
7185cdf0e10cSrcweir case svExternalSingleRef:
7186cdf0e10cSrcweir xExtRef = PopToken()->Clone();
7187cdf0e10cSrcweir // fallthru
7188cdf0e10cSrcweir case svSingleRef:
7189cdf0e10cSrcweir {
7190cdf0e10cSrcweir if (xExtRef)
7191cdf0e10cSrcweir {
7192cdf0e10cSrcweir ScSingleRefData& rData = static_cast<ScToken*>(xExtRef.get())->GetSingleRef();
7193cdf0e10cSrcweir rData.CalcAbsIfRel( aPos);
7194cdf0e10cSrcweir nCol1 = rData.nCol;
7195cdf0e10cSrcweir nRow1 = rData.nRow;
7196cdf0e10cSrcweir nTab1 = rData.nTab;
7197cdf0e10cSrcweir }
7198cdf0e10cSrcweir else
7199cdf0e10cSrcweir PopSingleRef( nCol1, nRow1, nTab1);
7200cdf0e10cSrcweir if (nParamCount == 3 || (nColNew < 0 && nRowNew < 0))
7201cdf0e10cSrcweir {
7202cdf0e10cSrcweir nCol1 = (SCCOL)((long) nCol1 + nColPlus);
7203cdf0e10cSrcweir nRow1 = (SCROW)((long) nRow1 + nRowPlus);
7204cdf0e10cSrcweir if (!ValidCol(nCol1) || !ValidRow(nRow1))
7205cdf0e10cSrcweir PushIllegalArgument();
7206cdf0e10cSrcweir else if (xExtRef)
7207cdf0e10cSrcweir {
7208cdf0e10cSrcweir ScSingleRefData& rData = static_cast<ScToken*>(xExtRef.get())->GetSingleRef();
7209cdf0e10cSrcweir rData.nCol = nCol1;
7210cdf0e10cSrcweir rData.nRow = nRow1;
7211cdf0e10cSrcweir rData.nTab = nTab1;
7212cdf0e10cSrcweir rData.CalcRelFromAbs( aPos);
7213cdf0e10cSrcweir // Push a subroutine that resolves the external
7214cdf0e10cSrcweir // reference as the next instruction.
7215cdf0e10cSrcweir PushTempToken( lcl_CreateExternalRefSubroutine( aPos, pDok, xExtRef));
7216cdf0e10cSrcweir }
7217cdf0e10cSrcweir else
7218cdf0e10cSrcweir PushSingleRef(nCol1, nRow1, nTab1);
7219cdf0e10cSrcweir }
7220cdf0e10cSrcweir else
7221cdf0e10cSrcweir {
7222cdf0e10cSrcweir if (nColNew < 0)
7223cdf0e10cSrcweir nColNew = 1;
7224cdf0e10cSrcweir if (nRowNew < 0)
7225cdf0e10cSrcweir nRowNew = 1;
7226cdf0e10cSrcweir nCol1 = (SCCOL)((long)nCol1+nColPlus); // ! nCol1 is modified
7227cdf0e10cSrcweir nRow1 = (SCROW)((long)nRow1+nRowPlus);
7228cdf0e10cSrcweir nCol2 = (SCCOL)((long)nCol1+nColNew-1);
7229cdf0e10cSrcweir nRow2 = (SCROW)((long)nRow1+nRowNew-1);
7230cdf0e10cSrcweir if (!ValidCol(nCol1) || !ValidRow(nRow1) ||
7231cdf0e10cSrcweir !ValidCol(nCol2) || !ValidRow(nRow2))
7232cdf0e10cSrcweir PushIllegalArgument();
7233cdf0e10cSrcweir else if (xExtRef)
7234cdf0e10cSrcweir {
7235cdf0e10cSrcweir // Convert SingleRef to DoubleRef.
7236cdf0e10cSrcweir xExtRef = new ScExternalDoubleRefToken(
7237cdf0e10cSrcweir *static_cast<const ScExternalSingleRefToken*>(xExtRef.get()));
7238cdf0e10cSrcweir ScComplexRefData& rData = static_cast<ScToken*>(xExtRef.get())->GetDoubleRef();
7239cdf0e10cSrcweir rData.Ref1.nCol = nCol1;
7240cdf0e10cSrcweir rData.Ref1.nRow = nRow1;
7241cdf0e10cSrcweir rData.Ref1.nTab = nTab1;
7242cdf0e10cSrcweir rData.Ref2.nCol = nCol2;
7243cdf0e10cSrcweir rData.Ref2.nRow = nRow2;
7244cdf0e10cSrcweir rData.Ref2.nTab = nTab1;
7245cdf0e10cSrcweir rData.CalcRelFromAbs( aPos);
7246cdf0e10cSrcweir // Push a subroutine that resolves the external
7247cdf0e10cSrcweir // reference as the next instruction.
7248cdf0e10cSrcweir PushTempToken( lcl_CreateExternalRefSubroutine( aPos, pDok, xExtRef));
7249cdf0e10cSrcweir }
7250cdf0e10cSrcweir else
7251cdf0e10cSrcweir PushDoubleRef(nCol1, nRow1, nTab1, nCol2, nRow2, nTab1);
7252cdf0e10cSrcweir }
7253cdf0e10cSrcweir }
7254cdf0e10cSrcweir break;
7255cdf0e10cSrcweir case svExternalDoubleRef:
7256cdf0e10cSrcweir xExtRef = PopToken()->Clone();
7257cdf0e10cSrcweir // fallthru
7258cdf0e10cSrcweir case svDoubleRef:
7259cdf0e10cSrcweir {
7260cdf0e10cSrcweir if (xExtRef)
7261cdf0e10cSrcweir {
7262cdf0e10cSrcweir ScComplexRefData& rData = static_cast<ScToken*>(xExtRef.get())->GetDoubleRef();
7263cdf0e10cSrcweir rData.CalcAbsIfRel( aPos);
7264cdf0e10cSrcweir nCol1 = rData.Ref1.nCol;
7265cdf0e10cSrcweir nRow1 = rData.Ref1.nRow;
7266cdf0e10cSrcweir nTab1 = rData.Ref1.nTab;
7267cdf0e10cSrcweir nCol2 = rData.Ref2.nCol;
7268cdf0e10cSrcweir nRow2 = rData.Ref2.nRow;
7269cdf0e10cSrcweir nTab2 = rData.Ref2.nTab;
7270cdf0e10cSrcweir }
7271cdf0e10cSrcweir else
7272cdf0e10cSrcweir PopDoubleRef(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
7273cdf0e10cSrcweir if (nColNew < 0)
7274cdf0e10cSrcweir nColNew = nCol2 - nCol1 + 1;
7275cdf0e10cSrcweir if (nRowNew < 0)
7276cdf0e10cSrcweir nRowNew = nRow2 - nRow1 + 1;
7277cdf0e10cSrcweir nCol1 = (SCCOL)((long)nCol1+nColPlus);
7278cdf0e10cSrcweir nRow1 = (SCROW)((long)nRow1+nRowPlus);
7279cdf0e10cSrcweir nCol2 = (SCCOL)((long)nCol1+nColNew-1);
7280cdf0e10cSrcweir nRow2 = (SCROW)((long)nRow1+nRowNew-1);
7281cdf0e10cSrcweir if (!ValidCol(nCol1) || !ValidRow(nRow1) ||
7282cdf0e10cSrcweir !ValidCol(nCol2) || !ValidRow(nRow2) || nTab1 != nTab2)
7283cdf0e10cSrcweir PushIllegalArgument();
7284cdf0e10cSrcweir else if (xExtRef)
7285cdf0e10cSrcweir {
7286cdf0e10cSrcweir ScComplexRefData& rData = static_cast<ScToken*>(xExtRef.get())->GetDoubleRef();
7287cdf0e10cSrcweir rData.Ref1.nCol = nCol1;
7288cdf0e10cSrcweir rData.Ref1.nRow = nRow1;
7289cdf0e10cSrcweir rData.Ref1.nTab = nTab1;
7290cdf0e10cSrcweir rData.Ref2.nCol = nCol2;
7291cdf0e10cSrcweir rData.Ref2.nRow = nRow2;
7292cdf0e10cSrcweir rData.Ref2.nTab = nTab1;
7293cdf0e10cSrcweir rData.CalcRelFromAbs( aPos);
7294cdf0e10cSrcweir // Push a subroutine that resolves the external
7295cdf0e10cSrcweir // reference as the next instruction.
7296cdf0e10cSrcweir PushTempToken( lcl_CreateExternalRefSubroutine( aPos, pDok, xExtRef));
7297cdf0e10cSrcweir }
7298cdf0e10cSrcweir else
7299cdf0e10cSrcweir PushDoubleRef(nCol1, nRow1, nTab1, nCol2, nRow2, nTab1);
7300cdf0e10cSrcweir }
7301cdf0e10cSrcweir break;
7302cdf0e10cSrcweir default:
7303cdf0e10cSrcweir PushIllegalParameter();
7304cdf0e10cSrcweir }
7305cdf0e10cSrcweir }
7306cdf0e10cSrcweir }
7307cdf0e10cSrcweir
7308cdf0e10cSrcweir
ScIndex()7309cdf0e10cSrcweir void ScInterpreter::ScIndex()
7310cdf0e10cSrcweir {
7311cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScIndex" );
7312cdf0e10cSrcweir sal_uInt8 nParamCount = GetByte();
7313cdf0e10cSrcweir if ( MustHaveParamCount( nParamCount, 1, 4 ) )
7314cdf0e10cSrcweir {
7315cdf0e10cSrcweir long nArea;
7316cdf0e10cSrcweir size_t nAreaCount;
7317cdf0e10cSrcweir SCCOL nCol;
7318cdf0e10cSrcweir SCROW nRow;
7319cdf0e10cSrcweir if (nParamCount == 4)
7320cdf0e10cSrcweir nArea = (long) ::rtl::math::approxFloor(GetDouble());
7321cdf0e10cSrcweir else
7322cdf0e10cSrcweir nArea = 1;
7323cdf0e10cSrcweir if (nParamCount >= 3)
7324cdf0e10cSrcweir nCol = (SCCOL) ::rtl::math::approxFloor(GetDouble());
7325cdf0e10cSrcweir else
7326cdf0e10cSrcweir nCol = 0;
7327cdf0e10cSrcweir if (nParamCount >= 2)
7328cdf0e10cSrcweir nRow = (SCROW) ::rtl::math::approxFloor(GetDouble());
7329cdf0e10cSrcweir else
7330cdf0e10cSrcweir nRow = 0;
7331cdf0e10cSrcweir if (GetStackType() == svRefList)
7332cdf0e10cSrcweir nAreaCount = (sp ? static_cast<ScToken*>(pStack[sp-1])->GetRefList()->size() : 0);
7333cdf0e10cSrcweir else
7334cdf0e10cSrcweir nAreaCount = 1; // one reference or array or whatever
7335cdf0e10cSrcweir if (nAreaCount == 0 || (size_t)nArea > nAreaCount)
7336cdf0e10cSrcweir {
7337cdf0e10cSrcweir PushError( errNoRef);
7338cdf0e10cSrcweir return;
7339cdf0e10cSrcweir }
7340cdf0e10cSrcweir else if (nArea < 1 || nCol < 0 || nRow < 0)
7341cdf0e10cSrcweir {
7342cdf0e10cSrcweir PushIllegalArgument();
7343cdf0e10cSrcweir return;
7344cdf0e10cSrcweir }
7345cdf0e10cSrcweir switch (GetStackType())
7346cdf0e10cSrcweir {
7347cdf0e10cSrcweir case svMatrix:
7348cdf0e10cSrcweir {
7349cdf0e10cSrcweir if (nArea != 1)
7350cdf0e10cSrcweir SetError(errIllegalArgument);
7351cdf0e10cSrcweir sal_uInt16 nOldSp = sp;
7352cdf0e10cSrcweir ScMatrixRef pMat = GetMatrix();
7353cdf0e10cSrcweir if (pMat)
7354cdf0e10cSrcweir {
7355cdf0e10cSrcweir SCSIZE nC, nR;
7356cdf0e10cSrcweir pMat->GetDimensions(nC, nR);
7357cdf0e10cSrcweir // Access one element of a vector independent of col/row
7358cdf0e10cSrcweir // orientation?
7359cdf0e10cSrcweir bool bVector = ((nCol == 0 || nRow == 0) && (nC == 1 || nR == 1));
7360cdf0e10cSrcweir SCSIZE nElement = ::std::max( static_cast<SCSIZE>(nCol),
7361cdf0e10cSrcweir static_cast<SCSIZE>(nRow));
7362cdf0e10cSrcweir if (nC == 0 || nR == 0 ||
7363cdf0e10cSrcweir (!bVector && (static_cast<SCSIZE>(nCol) > nC ||
7364cdf0e10cSrcweir static_cast<SCSIZE>(nRow) > nR)) ||
7365cdf0e10cSrcweir (bVector && nElement > nC * nR))
7366cdf0e10cSrcweir PushIllegalArgument();
7367cdf0e10cSrcweir else if (nCol == 0 && nRow == 0)
7368cdf0e10cSrcweir sp = nOldSp;
7369cdf0e10cSrcweir else if (bVector)
7370cdf0e10cSrcweir {
7371cdf0e10cSrcweir --nElement;
7372cdf0e10cSrcweir if (pMat->IsString( nElement))
7373cdf0e10cSrcweir PushString( pMat->GetString( nElement));
7374cdf0e10cSrcweir else
7375cdf0e10cSrcweir PushDouble( pMat->GetDouble( nElement));
7376cdf0e10cSrcweir }
7377cdf0e10cSrcweir else if (nCol == 0)
7378cdf0e10cSrcweir {
7379cdf0e10cSrcweir ScMatrixRef pResMat = GetNewMat(nC, 1);
7380cdf0e10cSrcweir if (pResMat)
7381cdf0e10cSrcweir {
7382cdf0e10cSrcweir SCSIZE nRowMinus1 = static_cast<SCSIZE>(nRow - 1);
7383cdf0e10cSrcweir for (SCSIZE i = 0; i < nC; i++)
7384cdf0e10cSrcweir if (!pMat->IsString(i, nRowMinus1))
7385cdf0e10cSrcweir pResMat->PutDouble(pMat->GetDouble(i,
7386cdf0e10cSrcweir nRowMinus1), i, 0);
7387cdf0e10cSrcweir else
7388cdf0e10cSrcweir pResMat->PutString(pMat->GetString(i,
7389cdf0e10cSrcweir nRowMinus1), i, 0);
7390cdf0e10cSrcweir PushMatrix(pResMat);
7391cdf0e10cSrcweir }
7392cdf0e10cSrcweir else
7393cdf0e10cSrcweir PushIllegalArgument();
7394cdf0e10cSrcweir }
7395cdf0e10cSrcweir else if (nRow == 0)
7396cdf0e10cSrcweir {
7397cdf0e10cSrcweir ScMatrixRef pResMat = GetNewMat(1, nR);
7398cdf0e10cSrcweir if (pResMat)
7399cdf0e10cSrcweir {
7400cdf0e10cSrcweir SCSIZE nColMinus1 = static_cast<SCSIZE>(nCol - 1);
7401cdf0e10cSrcweir for (SCSIZE i = 0; i < nR; i++)
7402cdf0e10cSrcweir if (!pMat->IsString(nColMinus1, i))
7403cdf0e10cSrcweir pResMat->PutDouble(pMat->GetDouble(nColMinus1,
7404cdf0e10cSrcweir i), i);
7405cdf0e10cSrcweir else
7406cdf0e10cSrcweir pResMat->PutString(pMat->GetString(nColMinus1,
7407cdf0e10cSrcweir i), i);
7408cdf0e10cSrcweir PushMatrix(pResMat);
7409cdf0e10cSrcweir }
7410cdf0e10cSrcweir else
7411cdf0e10cSrcweir PushIllegalArgument();
7412cdf0e10cSrcweir }
7413cdf0e10cSrcweir else
7414cdf0e10cSrcweir {
7415cdf0e10cSrcweir if (!pMat->IsString( static_cast<SCSIZE>(nCol-1),
7416cdf0e10cSrcweir static_cast<SCSIZE>(nRow-1)))
7417cdf0e10cSrcweir PushDouble( pMat->GetDouble(
7418cdf0e10cSrcweir static_cast<SCSIZE>(nCol-1),
7419cdf0e10cSrcweir static_cast<SCSIZE>(nRow-1)));
7420cdf0e10cSrcweir else
7421cdf0e10cSrcweir PushString( pMat->GetString(
7422cdf0e10cSrcweir static_cast<SCSIZE>(nCol-1),
7423cdf0e10cSrcweir static_cast<SCSIZE>(nRow-1)));
7424cdf0e10cSrcweir }
7425cdf0e10cSrcweir }
7426cdf0e10cSrcweir }
7427cdf0e10cSrcweir break;
7428cdf0e10cSrcweir case svSingleRef:
7429cdf0e10cSrcweir {
7430cdf0e10cSrcweir SCCOL nCol1 = 0;
7431cdf0e10cSrcweir SCROW nRow1 = 0;
7432cdf0e10cSrcweir SCTAB nTab1 = 0;
7433cdf0e10cSrcweir PopSingleRef( nCol1, nRow1, nTab1);
7434cdf0e10cSrcweir if (nCol > 1 || nRow > 1)
7435cdf0e10cSrcweir PushIllegalArgument();
7436cdf0e10cSrcweir else
7437cdf0e10cSrcweir PushSingleRef( nCol1, nRow1, nTab1);
7438cdf0e10cSrcweir }
7439cdf0e10cSrcweir break;
7440cdf0e10cSrcweir case svDoubleRef:
7441cdf0e10cSrcweir case svRefList:
7442cdf0e10cSrcweir {
7443cdf0e10cSrcweir SCCOL nCol1 = 0;
7444cdf0e10cSrcweir SCROW nRow1 = 0;
7445cdf0e10cSrcweir SCTAB nTab1 = 0;
7446cdf0e10cSrcweir SCCOL nCol2 = 0;
7447cdf0e10cSrcweir SCROW nRow2 = 0;
7448cdf0e10cSrcweir SCTAB nTab2 = 0;
7449cdf0e10cSrcweir sal_Bool bRowArray = sal_False;
7450cdf0e10cSrcweir if (GetStackType() == svRefList)
7451cdf0e10cSrcweir {
7452cdf0e10cSrcweir FormulaTokenRef xRef = PopToken();
7453cdf0e10cSrcweir if (nGlobalError || !xRef)
7454cdf0e10cSrcweir {
7455cdf0e10cSrcweir PushIllegalParameter();
7456cdf0e10cSrcweir return;
7457cdf0e10cSrcweir }
7458cdf0e10cSrcweir ScRange aRange( ScAddress::UNINITIALIZED);
7459cdf0e10cSrcweir DoubleRefToRange( (*(static_cast<ScToken*>(xRef.get())->GetRefList()))[nArea-1], aRange);
7460cdf0e10cSrcweir aRange.GetVars( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
7461cdf0e10cSrcweir if ( nParamCount == 2 && nRow1 == nRow2 )
7462cdf0e10cSrcweir bRowArray = sal_True;
7463cdf0e10cSrcweir }
7464cdf0e10cSrcweir else
7465cdf0e10cSrcweir {
7466cdf0e10cSrcweir PopDoubleRef( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
7467cdf0e10cSrcweir if ( nParamCount == 2 && nRow1 == nRow2 )
7468cdf0e10cSrcweir bRowArray = sal_True;
7469cdf0e10cSrcweir }
7470cdf0e10cSrcweir if ( nTab1 != nTab2 ||
7471cdf0e10cSrcweir (nCol > 0 && nCol1+nCol-1 > nCol2) ||
7472cdf0e10cSrcweir (nRow > 0 && nRow1+nRow-1 > nRow2 && !bRowArray ) ||
7473cdf0e10cSrcweir ( nRow > nCol2 - nCol1 + 1 && bRowArray ))
7474cdf0e10cSrcweir PushIllegalArgument();
7475cdf0e10cSrcweir else if (nCol == 0 && nRow == 0)
7476cdf0e10cSrcweir {
7477cdf0e10cSrcweir if ( nCol1 == nCol2 && nRow1 == nRow2 )
7478cdf0e10cSrcweir PushSingleRef( nCol1, nRow1, nTab1 );
7479cdf0e10cSrcweir else
7480cdf0e10cSrcweir PushDoubleRef( nCol1, nRow1, nTab1, nCol2, nRow2, nTab1 );
7481cdf0e10cSrcweir }
7482cdf0e10cSrcweir else if (nRow == 0)
7483cdf0e10cSrcweir {
7484cdf0e10cSrcweir if ( nRow1 == nRow2 )
7485cdf0e10cSrcweir PushSingleRef( nCol1+nCol-1, nRow1, nTab1 );
7486cdf0e10cSrcweir else
7487cdf0e10cSrcweir PushDoubleRef( nCol1+nCol-1, nRow1, nTab1,
7488cdf0e10cSrcweir nCol1+nCol-1, nRow2, nTab1 );
7489cdf0e10cSrcweir }
7490cdf0e10cSrcweir else if (nCol == 0)
7491cdf0e10cSrcweir {
7492cdf0e10cSrcweir if ( nCol1 == nCol2 )
7493cdf0e10cSrcweir PushSingleRef( nCol1, nRow1+nRow-1, nTab1 );
7494cdf0e10cSrcweir else if ( bRowArray )
7495cdf0e10cSrcweir {
7496cdf0e10cSrcweir nCol =(SCCOL) nRow;
7497cdf0e10cSrcweir nRow = 1;
7498cdf0e10cSrcweir PushSingleRef( nCol1+nCol-1, nRow1+nRow-1, nTab1);
7499cdf0e10cSrcweir }
7500cdf0e10cSrcweir else
7501cdf0e10cSrcweir PushDoubleRef( nCol1, nRow1+nRow-1, nTab1,
7502cdf0e10cSrcweir nCol2, nRow1+nRow-1, nTab1);
7503cdf0e10cSrcweir }
7504cdf0e10cSrcweir else
7505cdf0e10cSrcweir PushSingleRef( nCol1+nCol-1, nRow1+nRow-1, nTab1);
7506cdf0e10cSrcweir }
7507cdf0e10cSrcweir break;
7508cdf0e10cSrcweir default:
7509cdf0e10cSrcweir PushIllegalParameter();
7510cdf0e10cSrcweir }
7511cdf0e10cSrcweir }
7512cdf0e10cSrcweir }
7513cdf0e10cSrcweir
7514cdf0e10cSrcweir
ScMultiArea()7515cdf0e10cSrcweir void ScInterpreter::ScMultiArea()
7516cdf0e10cSrcweir {
7517cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScMultiArea" );
7518cdf0e10cSrcweir // Legacy support, convert to RefList
7519cdf0e10cSrcweir sal_uInt8 nParamCount = GetByte();
7520cdf0e10cSrcweir if (MustHaveParamCountMin( nParamCount, 1))
7521cdf0e10cSrcweir {
7522cdf0e10cSrcweir while (!nGlobalError && nParamCount-- > 1)
7523cdf0e10cSrcweir {
7524cdf0e10cSrcweir ScUnionFunc();
7525cdf0e10cSrcweir }
7526cdf0e10cSrcweir }
7527cdf0e10cSrcweir }
7528cdf0e10cSrcweir
7529cdf0e10cSrcweir
ScAreas()7530cdf0e10cSrcweir void ScInterpreter::ScAreas()
7531cdf0e10cSrcweir {
7532cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScAreas" );
7533cdf0e10cSrcweir sal_uInt8 nParamCount = GetByte();
7534cdf0e10cSrcweir if (MustHaveParamCount( nParamCount, 1))
7535cdf0e10cSrcweir {
7536cdf0e10cSrcweir size_t nCount = 0;
7537cdf0e10cSrcweir switch (GetStackType())
7538cdf0e10cSrcweir {
7539cdf0e10cSrcweir case svSingleRef:
7540cdf0e10cSrcweir {
7541cdf0e10cSrcweir FormulaTokenRef xT = PopToken();
7542cdf0e10cSrcweir ValidateRef( static_cast<ScToken*>(xT.get())->GetSingleRef());
7543cdf0e10cSrcweir ++nCount;
7544cdf0e10cSrcweir }
7545cdf0e10cSrcweir break;
7546cdf0e10cSrcweir case svDoubleRef:
7547cdf0e10cSrcweir {
7548cdf0e10cSrcweir FormulaTokenRef xT = PopToken();
7549cdf0e10cSrcweir ValidateRef( static_cast<ScToken*>(xT.get())->GetDoubleRef());
7550cdf0e10cSrcweir ++nCount;
7551cdf0e10cSrcweir }
7552cdf0e10cSrcweir break;
7553cdf0e10cSrcweir case svRefList:
7554cdf0e10cSrcweir {
7555cdf0e10cSrcweir FormulaTokenRef xT = PopToken();
7556cdf0e10cSrcweir ValidateRef( *(static_cast<ScToken*>(xT.get())->GetRefList()));
7557cdf0e10cSrcweir nCount += static_cast<ScToken*>(xT.get())->GetRefList()->size();
7558cdf0e10cSrcweir }
7559cdf0e10cSrcweir break;
7560cdf0e10cSrcweir default:
7561cdf0e10cSrcweir SetError( errIllegalParameter);
7562cdf0e10cSrcweir }
7563cdf0e10cSrcweir PushDouble( double(nCount));
7564cdf0e10cSrcweir }
7565cdf0e10cSrcweir }
7566cdf0e10cSrcweir
7567cdf0e10cSrcweir
ScCurrency()7568cdf0e10cSrcweir void ScInterpreter::ScCurrency()
7569cdf0e10cSrcweir {
7570cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScCurrency" );
7571cdf0e10cSrcweir sal_uInt8 nParamCount = GetByte();
7572cdf0e10cSrcweir if ( MustHaveParamCount( nParamCount, 1, 2 ) )
7573cdf0e10cSrcweir {
7574cdf0e10cSrcweir String aStr;
7575cdf0e10cSrcweir double fDec;
7576cdf0e10cSrcweir if (nParamCount == 2)
7577cdf0e10cSrcweir {
7578cdf0e10cSrcweir fDec = ::rtl::math::approxFloor(GetDouble());
7579cdf0e10cSrcweir if (fDec < -15.0 || fDec > 15.0)
7580cdf0e10cSrcweir {
7581cdf0e10cSrcweir PushIllegalArgument();
7582cdf0e10cSrcweir return;
7583cdf0e10cSrcweir }
7584cdf0e10cSrcweir }
7585cdf0e10cSrcweir else
7586cdf0e10cSrcweir fDec = 2.0;
7587cdf0e10cSrcweir double fVal = GetDouble();
7588cdf0e10cSrcweir double fFac;
7589cdf0e10cSrcweir if ( fDec != 0.0 )
7590cdf0e10cSrcweir fFac = pow( (double)10, fDec );
7591cdf0e10cSrcweir else
7592cdf0e10cSrcweir fFac = 1.0;
7593cdf0e10cSrcweir if (fVal < 0.0)
7594cdf0e10cSrcweir fVal = ceil(fVal*fFac-0.5)/fFac;
7595cdf0e10cSrcweir else
7596cdf0e10cSrcweir fVal = floor(fVal*fFac+0.5)/fFac;
7597cdf0e10cSrcweir Color* pColor = NULL;
7598cdf0e10cSrcweir if ( fDec < 0.0 )
7599cdf0e10cSrcweir fDec = 0.0;
7600cdf0e10cSrcweir sal_uLong nIndex = pFormatter->GetStandardFormat(
7601cdf0e10cSrcweir NUMBERFORMAT_CURRENCY,
7602cdf0e10cSrcweir ScGlobal::eLnge);
7603cdf0e10cSrcweir if ( (sal_uInt16) fDec != pFormatter->GetFormatPrecision( nIndex ) )
7604cdf0e10cSrcweir {
7605cdf0e10cSrcweir String sFormatString;
7606cdf0e10cSrcweir pFormatter->GenerateFormat(sFormatString,
7607cdf0e10cSrcweir nIndex,
7608cdf0e10cSrcweir ScGlobal::eLnge,
7609cdf0e10cSrcweir sal_True, // mit Tausenderpunkt
7610cdf0e10cSrcweir sal_False, // nicht rot
7611cdf0e10cSrcweir (sal_uInt16) fDec,// Nachkommastellen
7612cdf0e10cSrcweir 1); // 1 Vorkommanull
7613cdf0e10cSrcweir if (!pFormatter->GetPreviewString(sFormatString,
7614cdf0e10cSrcweir fVal,
7615cdf0e10cSrcweir aStr,
7616cdf0e10cSrcweir &pColor,
7617cdf0e10cSrcweir ScGlobal::eLnge))
7618cdf0e10cSrcweir SetError(errIllegalArgument);
7619cdf0e10cSrcweir }
7620cdf0e10cSrcweir else
7621cdf0e10cSrcweir {
7622cdf0e10cSrcweir pFormatter->GetOutputString(fVal, nIndex, aStr, &pColor);
7623cdf0e10cSrcweir }
7624cdf0e10cSrcweir PushString(aStr);
7625cdf0e10cSrcweir }
7626cdf0e10cSrcweir }
7627cdf0e10cSrcweir
7628cdf0e10cSrcweir
ScReplace()7629cdf0e10cSrcweir void ScInterpreter::ScReplace()
7630cdf0e10cSrcweir {
7631cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScReplace" );
7632cdf0e10cSrcweir if ( MustHaveParamCount( GetByte(), 4 ) )
7633cdf0e10cSrcweir {
7634cdf0e10cSrcweir String aNewStr( GetString() );
7635cdf0e10cSrcweir double fCount = ::rtl::math::approxFloor( GetDouble());
7636cdf0e10cSrcweir double fPos = ::rtl::math::approxFloor( GetDouble());
7637cdf0e10cSrcweir String aOldStr( GetString() );
7638cdf0e10cSrcweir if (fPos < 1.0 || fPos > static_cast<double>(STRING_MAXLEN)
7639cdf0e10cSrcweir || fCount < 0.0 || fCount > static_cast<double>(STRING_MAXLEN))
7640cdf0e10cSrcweir PushIllegalArgument();
7641cdf0e10cSrcweir else
7642cdf0e10cSrcweir {
7643cdf0e10cSrcweir xub_StrLen nCount = static_cast<xub_StrLen>(fCount);
7644cdf0e10cSrcweir xub_StrLen nPos = static_cast<xub_StrLen>(fPos);
7645cdf0e10cSrcweir xub_StrLen nLen = aOldStr.Len();
7646cdf0e10cSrcweir if (nPos > nLen + 1)
7647cdf0e10cSrcweir nPos = nLen + 1;
7648cdf0e10cSrcweir if (nCount > nLen - nPos + 1)
7649cdf0e10cSrcweir nCount = nLen - nPos + 1;
7650cdf0e10cSrcweir aOldStr.Erase( nPos-1, nCount );
7651cdf0e10cSrcweir if ( CheckStringResultLen( aOldStr, aNewStr ) )
7652cdf0e10cSrcweir aOldStr.Insert( aNewStr, nPos-1 );
7653cdf0e10cSrcweir PushString( aOldStr );
7654cdf0e10cSrcweir }
7655cdf0e10cSrcweir }
7656cdf0e10cSrcweir }
7657cdf0e10cSrcweir
7658cdf0e10cSrcweir
ScFixed()7659cdf0e10cSrcweir void ScInterpreter::ScFixed()
7660cdf0e10cSrcweir {
7661cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScFixed" );
7662cdf0e10cSrcweir sal_uInt8 nParamCount = GetByte();
7663cdf0e10cSrcweir if ( MustHaveParamCount( nParamCount, 1, 3 ) )
7664cdf0e10cSrcweir {
7665cdf0e10cSrcweir String aStr;
7666cdf0e10cSrcweir double fDec;
7667cdf0e10cSrcweir sal_Bool bThousand;
7668cdf0e10cSrcweir if (nParamCount == 3)
7669cdf0e10cSrcweir bThousand = !GetBool(); // Param TRUE: keine Tausenderpunkte
7670cdf0e10cSrcweir else
7671cdf0e10cSrcweir bThousand = sal_True;
7672cdf0e10cSrcweir if (nParamCount >= 2)
7673cdf0e10cSrcweir {
7674cdf0e10cSrcweir fDec = ::rtl::math::approxFloor(GetDoubleWithDefault( 2.0 ));
7675cdf0e10cSrcweir if (fDec < -15.0 || fDec > 15.0)
7676cdf0e10cSrcweir {
7677cdf0e10cSrcweir PushIllegalArgument();
7678cdf0e10cSrcweir return;
7679cdf0e10cSrcweir }
7680cdf0e10cSrcweir }
7681cdf0e10cSrcweir else
7682cdf0e10cSrcweir fDec = 2.0;
7683cdf0e10cSrcweir double fVal = GetDouble();
7684cdf0e10cSrcweir double fFac;
7685cdf0e10cSrcweir if ( fDec != 0.0 )
7686cdf0e10cSrcweir fFac = pow( (double)10, fDec );
7687cdf0e10cSrcweir else
7688cdf0e10cSrcweir fFac = 1.0;
7689cdf0e10cSrcweir if (fVal < 0.0)
7690cdf0e10cSrcweir fVal = ceil(fVal*fFac-0.5)/fFac;
7691cdf0e10cSrcweir else
7692cdf0e10cSrcweir fVal = floor(fVal*fFac+0.5)/fFac;
7693cdf0e10cSrcweir Color* pColor = NULL;
7694cdf0e10cSrcweir String sFormatString;
7695cdf0e10cSrcweir if (fDec < 0.0)
7696cdf0e10cSrcweir fDec = 0.0;
7697cdf0e10cSrcweir sal_uLong nIndex = pFormatter->GetStandardFormat(
7698cdf0e10cSrcweir NUMBERFORMAT_NUMBER,
7699cdf0e10cSrcweir ScGlobal::eLnge);
7700cdf0e10cSrcweir pFormatter->GenerateFormat(sFormatString,
7701cdf0e10cSrcweir nIndex,
7702cdf0e10cSrcweir ScGlobal::eLnge,
7703cdf0e10cSrcweir bThousand, // mit Tausenderpunkt
7704cdf0e10cSrcweir sal_False, // nicht rot
7705cdf0e10cSrcweir (sal_uInt16) fDec,// Nachkommastellen
7706cdf0e10cSrcweir 1); // 1 Vorkommanull
7707cdf0e10cSrcweir if (!pFormatter->GetPreviewString(sFormatString,
7708cdf0e10cSrcweir fVal,
7709cdf0e10cSrcweir aStr,
7710cdf0e10cSrcweir &pColor,
7711cdf0e10cSrcweir ScGlobal::eLnge))
7712cdf0e10cSrcweir PushIllegalArgument();
7713cdf0e10cSrcweir else
7714cdf0e10cSrcweir PushString(aStr);
7715cdf0e10cSrcweir }
7716cdf0e10cSrcweir }
7717cdf0e10cSrcweir
7718cdf0e10cSrcweir
ScFind()7719cdf0e10cSrcweir void ScInterpreter::ScFind()
7720cdf0e10cSrcweir {
7721cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScFind" );
7722cdf0e10cSrcweir sal_uInt8 nParamCount = GetByte();
7723cdf0e10cSrcweir if ( MustHaveParamCount( nParamCount, 2, 3 ) )
7724cdf0e10cSrcweir {
7725cdf0e10cSrcweir double fAnz;
7726cdf0e10cSrcweir if (nParamCount == 3)
7727cdf0e10cSrcweir fAnz = GetDouble();
7728cdf0e10cSrcweir else
7729cdf0e10cSrcweir fAnz = 1.0;
7730cdf0e10cSrcweir String sStr = GetString();
7731cdf0e10cSrcweir if( fAnz < 1.0 || fAnz > (double) sStr.Len() )
7732cdf0e10cSrcweir PushNoValue();
7733cdf0e10cSrcweir else
7734cdf0e10cSrcweir {
7735cdf0e10cSrcweir xub_StrLen nPos = sStr.Search( GetString(), (xub_StrLen) fAnz - 1 );
7736cdf0e10cSrcweir if (nPos == STRING_NOTFOUND)
7737cdf0e10cSrcweir PushNoValue();
7738cdf0e10cSrcweir else
7739cdf0e10cSrcweir PushDouble((double)(nPos + 1));
7740cdf0e10cSrcweir }
7741cdf0e10cSrcweir }
7742cdf0e10cSrcweir }
7743cdf0e10cSrcweir
7744cdf0e10cSrcweir
ScExact()7745cdf0e10cSrcweir void ScInterpreter::ScExact()
7746cdf0e10cSrcweir {
7747cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScExact" );
7748cdf0e10cSrcweir nFuncFmtType = NUMBERFORMAT_LOGICAL;
7749cdf0e10cSrcweir if ( MustHaveParamCount( GetByte(), 2 ) )
7750cdf0e10cSrcweir {
7751cdf0e10cSrcweir String s1( GetString() );
7752cdf0e10cSrcweir String s2( GetString() );
7753cdf0e10cSrcweir PushInt( s1 == s2 );
7754cdf0e10cSrcweir }
7755cdf0e10cSrcweir }
7756cdf0e10cSrcweir
7757cdf0e10cSrcweir
ScLeft()7758cdf0e10cSrcweir void ScInterpreter::ScLeft()
7759cdf0e10cSrcweir {
7760cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScLeft" );
7761cdf0e10cSrcweir sal_uInt8 nParamCount = GetByte();
7762cdf0e10cSrcweir if ( MustHaveParamCount( nParamCount, 1, 2 ) )
7763cdf0e10cSrcweir {
7764cdf0e10cSrcweir xub_StrLen n;
7765cdf0e10cSrcweir if (nParamCount == 2)
7766cdf0e10cSrcweir {
7767cdf0e10cSrcweir double nVal = ::rtl::math::approxFloor(GetDouble());
7768cdf0e10cSrcweir if ( nVal < 0.0 || nVal > STRING_MAXLEN )
7769cdf0e10cSrcweir {
7770cdf0e10cSrcweir PushIllegalArgument();
7771cdf0e10cSrcweir return ;
7772cdf0e10cSrcweir }
7773cdf0e10cSrcweir else
7774cdf0e10cSrcweir n = (xub_StrLen) nVal;
7775cdf0e10cSrcweir }
7776cdf0e10cSrcweir else
7777cdf0e10cSrcweir n = 1;
7778cdf0e10cSrcweir String aStr( GetString() );
7779cdf0e10cSrcweir aStr.Erase( n );
7780cdf0e10cSrcweir PushString( aStr );
7781cdf0e10cSrcweir }
7782cdf0e10cSrcweir }
7783cdf0e10cSrcweir
778439c2db0bSWang Lei typedef struct {
778539c2db0bSWang Lei UBlockCode from;
778639c2db0bSWang Lei UBlockCode to;
778739c2db0bSWang Lei } UBlockScript;
778839c2db0bSWang Lei
778939c2db0bSWang Lei static UBlockScript scriptList[] = {
779039c2db0bSWang Lei {UBLOCK_HANGUL_JAMO, UBLOCK_HANGUL_JAMO},
779139c2db0bSWang Lei {UBLOCK_CJK_RADICALS_SUPPLEMENT, UBLOCK_HANGUL_SYLLABLES},
779239c2db0bSWang Lei {UBLOCK_CJK_COMPATIBILITY_IDEOGRAPHS,UBLOCK_CJK_RADICALS_SUPPLEMENT },
779339c2db0bSWang Lei {UBLOCK_IDEOGRAPHIC_DESCRIPTION_CHARACTERS,UBLOCK_CJK_COMPATIBILITY_IDEOGRAPHS},
779439c2db0bSWang Lei {UBLOCK_CJK_COMPATIBILITY_FORMS, UBLOCK_CJK_COMPATIBILITY_FORMS},
779539c2db0bSWang Lei {UBLOCK_HALFWIDTH_AND_FULLWIDTH_FORMS, UBLOCK_HALFWIDTH_AND_FULLWIDTH_FORMS},
779639c2db0bSWang Lei {UBLOCK_CJK_UNIFIED_IDEOGRAPHS_EXTENSION_B, UBLOCK_CJK_COMPATIBILITY_IDEOGRAPHS_SUPPLEMENT},
779739c2db0bSWang Lei {UBLOCK_CJK_STROKES, UBLOCK_CJK_STROKES}
779839c2db0bSWang Lei };
779939c2db0bSWang Lei #define scriptListCount sizeof (scriptList) / sizeof (UBlockScript)
lcl_getScriptClass(sal_uInt32 currentChar)780039c2db0bSWang Lei bool SAL_CALL lcl_getScriptClass(sal_uInt32 currentChar)
780139c2db0bSWang Lei {
780239c2db0bSWang Lei // for the locale of ja-JP, character U+0x005c and U+0x20ac should be ScriptType::Asian
780339c2db0bSWang Lei if( (currentChar == 0x005c || currentChar == 0x20ac) &&
780439c2db0bSWang Lei (MsLangId::getSystemLanguage() == LANGUAGE_JAPANESE) )
780539c2db0bSWang Lei return true;
780639c2db0bSWang Lei sal_uInt16 i;
780739c2db0bSWang Lei static sal_Int16 nRet = 0;
780839c2db0bSWang Lei UBlockCode block = (UBlockCode)ublock_getCode((sal_uInt32)currentChar);
780939c2db0bSWang Lei for ( i = 0; i < scriptListCount; i++) {
781039c2db0bSWang Lei if (block <= scriptList[i].to) break;
781139c2db0bSWang Lei }
781239c2db0bSWang Lei nRet = (i < scriptListCount && block >= scriptList[i].from);
781339c2db0bSWang Lei return nRet;
781439c2db0bSWang Lei }
IsDBCS(sal_Unicode ch)781539c2db0bSWang Lei bool IsDBCS(sal_Unicode ch)
781639c2db0bSWang Lei {
781739c2db0bSWang Lei return lcl_getScriptClass(ch);
781839c2db0bSWang Lei }
getLengthB(String & str)781939c2db0bSWang Lei sal_Int32 getLengthB(String &str)
782039c2db0bSWang Lei {
7821a845386bSAndre Fischer xub_StrLen index = 0;
782239c2db0bSWang Lei sal_Int32 length = 0;
782339c2db0bSWang Lei if(0 == str.Len())
782439c2db0bSWang Lei return 0;
782539c2db0bSWang Lei while(index < str.Len()){
782639c2db0bSWang Lei if(IsDBCS(str.GetChar(index)))
782739c2db0bSWang Lei length += 2;
782839c2db0bSWang Lei else
782939c2db0bSWang Lei length++;
783039c2db0bSWang Lei index++;
783139c2db0bSWang Lei }
783239c2db0bSWang Lei return length;
783339c2db0bSWang Lei }
ScLenB()783439c2db0bSWang Lei void ScInterpreter::ScLenB()
783539c2db0bSWang Lei {
783639c2db0bSWang Lei RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "luzhang", "ScInterpreter::ScLenB" );
783739c2db0bSWang Lei String aStr( GetString() );
783839c2db0bSWang Lei PushDouble( getLengthB(aStr) );
783939c2db0bSWang Lei }
lcl_RightB(String & aStr,sal_Int32 n)784039c2db0bSWang Lei void lcl_RightB(String &aStr, sal_Int32 n)
784139c2db0bSWang Lei {
784239c2db0bSWang Lei if( n < getLengthB(aStr) )
784339c2db0bSWang Lei {
784439c2db0bSWang Lei sal_Int32 index = aStr.Len();
784539c2db0bSWang Lei while(index-- >= 0)
784639c2db0bSWang Lei {
784739c2db0bSWang Lei if(0 == n)
784839c2db0bSWang Lei {
784939c2db0bSWang Lei aStr.Erase( 0, index + 1);
785039c2db0bSWang Lei break;
785139c2db0bSWang Lei }
785239c2db0bSWang Lei if(-1 == n)
785339c2db0bSWang Lei {
785439c2db0bSWang Lei aStr.Erase( 0, index + 2 );
785539c2db0bSWang Lei aStr.InsertAscii(" ", 0);
785639c2db0bSWang Lei break;
785739c2db0bSWang Lei }
785839c2db0bSWang Lei if(IsDBCS(aStr.GetChar(index)))
785939c2db0bSWang Lei n -= 2;
786039c2db0bSWang Lei else
786139c2db0bSWang Lei n--;
786239c2db0bSWang Lei }
786339c2db0bSWang Lei }
786439c2db0bSWang Lei }
ScRightB()786539c2db0bSWang Lei void ScInterpreter::ScRightB()
786639c2db0bSWang Lei {
786739c2db0bSWang Lei RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "luzhang", "ScInterpreter::ScRightB" );
786839c2db0bSWang Lei sal_uInt8 nParamCount = GetByte();
786939c2db0bSWang Lei if ( MustHaveParamCount( nParamCount, 1, 2 ) )
787039c2db0bSWang Lei {
787139c2db0bSWang Lei sal_Int32 n;
787239c2db0bSWang Lei if (nParamCount == 2)
787339c2db0bSWang Lei {
787439c2db0bSWang Lei double nVal = ::rtl::math::approxFloor(GetDouble());
787539c2db0bSWang Lei if ( nVal < 0.0 || nVal > STRING_MAXLEN )
787639c2db0bSWang Lei {
787739c2db0bSWang Lei PushIllegalArgument();
787839c2db0bSWang Lei return ;
787939c2db0bSWang Lei }
788039c2db0bSWang Lei else
788139c2db0bSWang Lei n = (xub_StrLen) nVal;
788239c2db0bSWang Lei }
788339c2db0bSWang Lei else
788439c2db0bSWang Lei n = 1;
788539c2db0bSWang Lei String aStr( GetString() );
788639c2db0bSWang Lei lcl_RightB(aStr, n);
788739c2db0bSWang Lei PushString( aStr );
788839c2db0bSWang Lei }
788939c2db0bSWang Lei }
lcl_LeftB(String & aStr,sal_Int32 n)789039c2db0bSWang Lei void lcl_LeftB(String &aStr, sal_Int32 n)
789139c2db0bSWang Lei {
789239c2db0bSWang Lei if( n < getLengthB(aStr) )
789339c2db0bSWang Lei {
789439c2db0bSWang Lei sal_Int32 index = -1;
789539c2db0bSWang Lei while(index++ < aStr.Len())
789639c2db0bSWang Lei {
789739c2db0bSWang Lei if(0 == n)
789839c2db0bSWang Lei {
789939c2db0bSWang Lei aStr.Erase( index );
790039c2db0bSWang Lei break;
790139c2db0bSWang Lei }
790239c2db0bSWang Lei if(-1 == n)
790339c2db0bSWang Lei {
790439c2db0bSWang Lei aStr.Erase( index - 1 );
790539c2db0bSWang Lei aStr.InsertAscii(" ");
790639c2db0bSWang Lei break;
790739c2db0bSWang Lei }
790839c2db0bSWang Lei if(IsDBCS(aStr.GetChar(index)))
790939c2db0bSWang Lei n -= 2;
791039c2db0bSWang Lei else
791139c2db0bSWang Lei n--;
791239c2db0bSWang Lei }
791339c2db0bSWang Lei }
791439c2db0bSWang Lei }
ScLeftB()791539c2db0bSWang Lei void ScInterpreter::ScLeftB()
791639c2db0bSWang Lei {
791739c2db0bSWang Lei RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "luzhang", "ScInterpreter::ScLeftB" );
791839c2db0bSWang Lei sal_uInt8 nParamCount = GetByte();
791939c2db0bSWang Lei if ( MustHaveParamCount( nParamCount, 1, 2 ) )
792039c2db0bSWang Lei {
792139c2db0bSWang Lei sal_Int32 n;
792239c2db0bSWang Lei if (nParamCount == 2)
792339c2db0bSWang Lei {
792439c2db0bSWang Lei double nVal = ::rtl::math::approxFloor(GetDouble());
792539c2db0bSWang Lei if ( nVal < 0.0 || nVal > STRING_MAXLEN )
792639c2db0bSWang Lei {
792739c2db0bSWang Lei PushIllegalArgument();
792839c2db0bSWang Lei return ;
792939c2db0bSWang Lei }
793039c2db0bSWang Lei else
793139c2db0bSWang Lei n = (xub_StrLen) nVal;
793239c2db0bSWang Lei }
793339c2db0bSWang Lei else
793439c2db0bSWang Lei n = 1;
793539c2db0bSWang Lei String aStr( GetString() );
793639c2db0bSWang Lei lcl_LeftB(aStr, n);
793739c2db0bSWang Lei PushString( aStr );
793839c2db0bSWang Lei }
793939c2db0bSWang Lei }
ScMidB()794039c2db0bSWang Lei void ScInterpreter::ScMidB()
794139c2db0bSWang Lei {
794239c2db0bSWang Lei RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "luzhang", "ScInterpreter::ScMidB" );
794339c2db0bSWang Lei if ( MustHaveParamCount( GetByte(), 3 ) )
794439c2db0bSWang Lei {
794539c2db0bSWang Lei double fAnz = ::rtl::math::approxFloor(GetDouble());
794639c2db0bSWang Lei double fAnfang = ::rtl::math::approxFloor(GetDouble());
794739c2db0bSWang Lei String rStr( GetString() );
794839c2db0bSWang Lei if (fAnfang < 1.0 || fAnz < 0.0 || fAnfang > double(STRING_MAXLEN) || fAnz > double(STRING_MAXLEN))
794939c2db0bSWang Lei PushIllegalArgument();
795039c2db0bSWang Lei else
795139c2db0bSWang Lei {
795239c2db0bSWang Lei
795339c2db0bSWang Lei lcl_LeftB(rStr, (xub_StrLen)fAnfang + (xub_StrLen)fAnz - 1);
795439c2db0bSWang Lei sal_Int32 nCnt = getLengthB(rStr) - (xub_StrLen)fAnfang + 1;
795539c2db0bSWang Lei lcl_RightB(rStr, nCnt>0 ? nCnt:0);
795639c2db0bSWang Lei PushString(rStr);
795739c2db0bSWang Lei }
795839c2db0bSWang Lei }
795939c2db0bSWang Lei }
7960cdf0e10cSrcweir
ScRight()7961cdf0e10cSrcweir void ScInterpreter::ScRight()
7962cdf0e10cSrcweir {
7963cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScRight" );
7964cdf0e10cSrcweir sal_uInt8 nParamCount = GetByte();
7965cdf0e10cSrcweir if ( MustHaveParamCount( nParamCount, 1, 2 ) )
7966cdf0e10cSrcweir {
7967cdf0e10cSrcweir xub_StrLen n;
7968cdf0e10cSrcweir if (nParamCount == 2)
7969cdf0e10cSrcweir {
7970cdf0e10cSrcweir double nVal = ::rtl::math::approxFloor(GetDouble());
7971cdf0e10cSrcweir if ( nVal < 0.0 || nVal > STRING_MAXLEN )
7972cdf0e10cSrcweir {
7973cdf0e10cSrcweir PushIllegalArgument();
7974cdf0e10cSrcweir return ;
7975cdf0e10cSrcweir }
7976cdf0e10cSrcweir else
7977cdf0e10cSrcweir n = (xub_StrLen) nVal;
7978cdf0e10cSrcweir }
7979cdf0e10cSrcweir else
7980cdf0e10cSrcweir n = 1;
7981cdf0e10cSrcweir String aStr( GetString() );
7982cdf0e10cSrcweir if( n < aStr.Len() )
7983cdf0e10cSrcweir aStr.Erase( 0, aStr.Len() - n );
7984cdf0e10cSrcweir PushString( aStr );
7985cdf0e10cSrcweir }
7986cdf0e10cSrcweir }
7987cdf0e10cSrcweir
7988cdf0e10cSrcweir
ScSearch()7989cdf0e10cSrcweir void ScInterpreter::ScSearch()
7990cdf0e10cSrcweir {
7991cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScSearch" );
7992cdf0e10cSrcweir double fAnz;
7993cdf0e10cSrcweir sal_uInt8 nParamCount = GetByte();
7994cdf0e10cSrcweir if ( MustHaveParamCount( nParamCount, 2, 3 ) )
7995cdf0e10cSrcweir {
7996cdf0e10cSrcweir if (nParamCount == 3)
7997cdf0e10cSrcweir {
7998cdf0e10cSrcweir fAnz = ::rtl::math::approxFloor(GetDouble());
7999cdf0e10cSrcweir if (fAnz > double(STRING_MAXLEN))
8000cdf0e10cSrcweir {
8001cdf0e10cSrcweir PushIllegalArgument();
8002cdf0e10cSrcweir return;
8003cdf0e10cSrcweir }
8004cdf0e10cSrcweir }
8005cdf0e10cSrcweir else
8006cdf0e10cSrcweir fAnz = 1.0;
8007cdf0e10cSrcweir String sStr = GetString();
8008cdf0e10cSrcweir String SearchStr = GetString();
8009cdf0e10cSrcweir xub_StrLen nPos = (xub_StrLen) fAnz - 1;
8010cdf0e10cSrcweir xub_StrLen nEndPos = sStr.Len();
8011cdf0e10cSrcweir if( nPos >= nEndPos )
8012cdf0e10cSrcweir PushNoValue();
8013cdf0e10cSrcweir else
8014cdf0e10cSrcweir {
8015cdf0e10cSrcweir utl::SearchParam::SearchType eSearchType =
8016cdf0e10cSrcweir (MayBeRegExp( SearchStr, pDok ) ?
8017cdf0e10cSrcweir utl::SearchParam::SRCH_REGEXP : utl::SearchParam::SRCH_NORMAL);
8018cdf0e10cSrcweir utl::SearchParam sPar(SearchStr, eSearchType, sal_False, sal_False, sal_False);
8019cdf0e10cSrcweir utl::TextSearch sT( sPar, *ScGlobal::pCharClass );
8020cdf0e10cSrcweir int nBool = sT.SearchFrwrd(sStr, &nPos, &nEndPos);
8021cdf0e10cSrcweir if (!nBool)
8022cdf0e10cSrcweir PushNoValue();
8023cdf0e10cSrcweir else
8024cdf0e10cSrcweir PushDouble((double)(nPos) + 1);
8025cdf0e10cSrcweir }
8026cdf0e10cSrcweir }
8027cdf0e10cSrcweir }
8028cdf0e10cSrcweir
8029cdf0e10cSrcweir
ScMid()8030cdf0e10cSrcweir void ScInterpreter::ScMid()
8031cdf0e10cSrcweir {
8032cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScMid" );
8033cdf0e10cSrcweir if ( MustHaveParamCount( GetByte(), 3 ) )
8034cdf0e10cSrcweir {
8035cdf0e10cSrcweir double fAnz = ::rtl::math::approxFloor(GetDouble());
8036cdf0e10cSrcweir double fAnfang = ::rtl::math::approxFloor(GetDouble());
8037cdf0e10cSrcweir const String& rStr = GetString();
8038cdf0e10cSrcweir if (fAnfang < 1.0 || fAnz < 0.0 || fAnfang > double(STRING_MAXLEN) || fAnz > double(STRING_MAXLEN))
8039cdf0e10cSrcweir PushIllegalArgument();
8040cdf0e10cSrcweir else
8041cdf0e10cSrcweir PushString(rStr.Copy( (xub_StrLen) fAnfang - 1, (xub_StrLen) fAnz ));
8042cdf0e10cSrcweir }
8043cdf0e10cSrcweir }
8044cdf0e10cSrcweir
8045cdf0e10cSrcweir
ScText()8046cdf0e10cSrcweir void ScInterpreter::ScText()
8047cdf0e10cSrcweir {
8048cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScText" );
8049cdf0e10cSrcweir if ( MustHaveParamCount( GetByte(), 2 ) )
8050cdf0e10cSrcweir {
8051cdf0e10cSrcweir String sFormatString = GetString();
8052cdf0e10cSrcweir String aStr;
8053cdf0e10cSrcweir bool bString = false;
8054cdf0e10cSrcweir double fVal = 0.0;
8055cdf0e10cSrcweir switch (GetStackType())
8056cdf0e10cSrcweir {
8057cdf0e10cSrcweir case svError:
8058cdf0e10cSrcweir PopError();
8059cdf0e10cSrcweir break;
8060cdf0e10cSrcweir case svDouble:
8061cdf0e10cSrcweir fVal = PopDouble();
8062cdf0e10cSrcweir break;
8063cdf0e10cSrcweir default:
8064cdf0e10cSrcweir {
8065cdf0e10cSrcweir FormulaTokenRef xTok( PopToken());
8066cdf0e10cSrcweir if (!nGlobalError)
8067cdf0e10cSrcweir {
8068cdf0e10cSrcweir PushTempToken( xTok);
8069cdf0e10cSrcweir // Temporarily override the ConvertStringToValue()
8070cdf0e10cSrcweir // error for GetCellValue() / GetCellValueOrZero()
8071cdf0e10cSrcweir sal_uInt16 nSErr = mnStringNoValueError;
8072cdf0e10cSrcweir mnStringNoValueError = errNotNumericString;
8073cdf0e10cSrcweir fVal = GetDouble();
8074cdf0e10cSrcweir mnStringNoValueError = nSErr;
8075cdf0e10cSrcweir if (nGlobalError == errNotNumericString)
8076cdf0e10cSrcweir {
8077cdf0e10cSrcweir // Not numeric.
8078cdf0e10cSrcweir nGlobalError = 0;
8079cdf0e10cSrcweir PushTempToken( xTok);
8080cdf0e10cSrcweir aStr = GetString();
8081cdf0e10cSrcweir bString = true;
8082cdf0e10cSrcweir }
8083cdf0e10cSrcweir }
8084cdf0e10cSrcweir }
8085cdf0e10cSrcweir }
8086cdf0e10cSrcweir if (nGlobalError)
8087cdf0e10cSrcweir PushError( nGlobalError);
8088cdf0e10cSrcweir else
8089cdf0e10cSrcweir {
8090cdf0e10cSrcweir String aResult;
8091cdf0e10cSrcweir Color* pColor = NULL;
8092cdf0e10cSrcweir LanguageType eCellLang;
8093cdf0e10cSrcweir const ScPatternAttr* pPattern = pDok->GetPattern(
8094cdf0e10cSrcweir aPos.Col(), aPos.Row(), aPos.Tab() );
8095cdf0e10cSrcweir if ( pPattern )
8096cdf0e10cSrcweir eCellLang = ((const SvxLanguageItem&)
8097cdf0e10cSrcweir pPattern->GetItem( ATTR_LANGUAGE_FORMAT )).GetValue();
8098cdf0e10cSrcweir else
8099cdf0e10cSrcweir eCellLang = ScGlobal::eLnge;
8100cdf0e10cSrcweir if (bString)
8101cdf0e10cSrcweir {
8102cdf0e10cSrcweir if (!pFormatter->GetPreviewString( sFormatString, aStr,
8103cdf0e10cSrcweir aResult, &pColor, eCellLang))
8104cdf0e10cSrcweir PushIllegalArgument();
8105cdf0e10cSrcweir else
8106cdf0e10cSrcweir PushString( aResult);
8107cdf0e10cSrcweir }
8108cdf0e10cSrcweir else
8109cdf0e10cSrcweir {
8110cdf0e10cSrcweir if (!pFormatter->GetPreviewStringGuess( sFormatString, fVal,
8111cdf0e10cSrcweir aResult, &pColor, eCellLang))
8112cdf0e10cSrcweir PushIllegalArgument();
8113cdf0e10cSrcweir else
8114cdf0e10cSrcweir PushString( aResult);
8115cdf0e10cSrcweir }
8116cdf0e10cSrcweir }
8117cdf0e10cSrcweir }
8118cdf0e10cSrcweir }
8119cdf0e10cSrcweir
8120cdf0e10cSrcweir
ScSubstitute()8121cdf0e10cSrcweir void ScInterpreter::ScSubstitute()
8122cdf0e10cSrcweir {
8123cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScSubstitute" );
8124cdf0e10cSrcweir sal_uInt8 nParamCount = GetByte();
8125cdf0e10cSrcweir if ( MustHaveParamCount( nParamCount, 3, 4 ) )
8126cdf0e10cSrcweir {
8127cdf0e10cSrcweir xub_StrLen nAnz;
8128cdf0e10cSrcweir if (nParamCount == 4)
8129cdf0e10cSrcweir {
8130cdf0e10cSrcweir double fAnz = ::rtl::math::approxFloor(GetDouble());
8131cdf0e10cSrcweir if( fAnz < 1 || fAnz > STRING_MAXLEN )
8132cdf0e10cSrcweir {
8133cdf0e10cSrcweir PushIllegalArgument();
8134cdf0e10cSrcweir return;
8135cdf0e10cSrcweir }
8136cdf0e10cSrcweir else
8137cdf0e10cSrcweir nAnz = (xub_StrLen) fAnz;
8138cdf0e10cSrcweir }
8139cdf0e10cSrcweir else
8140cdf0e10cSrcweir nAnz = 0;
8141cdf0e10cSrcweir String sNewStr = GetString();
8142cdf0e10cSrcweir String sOldStr = GetString();
8143cdf0e10cSrcweir String sStr = GetString();
8144cdf0e10cSrcweir xub_StrLen nPos = 0;
8145cdf0e10cSrcweir xub_StrLen nCount = 0;
8146cdf0e10cSrcweir xub_StrLen nNewLen = sNewStr.Len();
8147cdf0e10cSrcweir xub_StrLen nOldLen = sOldStr.Len();
8148cdf0e10cSrcweir while( sal_True )
8149cdf0e10cSrcweir {
8150cdf0e10cSrcweir nPos = sStr.Search( sOldStr, nPos );
8151cdf0e10cSrcweir if (nPos != STRING_NOTFOUND)
8152cdf0e10cSrcweir {
8153cdf0e10cSrcweir nCount++;
8154cdf0e10cSrcweir if( !nAnz || nCount == nAnz )
8155cdf0e10cSrcweir {
8156cdf0e10cSrcweir sStr.Erase(nPos,nOldLen);
8157cdf0e10cSrcweir if ( CheckStringResultLen( sStr, sNewStr ) )
8158cdf0e10cSrcweir {
8159cdf0e10cSrcweir sStr.Insert(sNewStr,nPos);
8160cdf0e10cSrcweir nPos = sal::static_int_cast<xub_StrLen>( nPos + nNewLen );
8161cdf0e10cSrcweir }
8162cdf0e10cSrcweir else
8163cdf0e10cSrcweir break;
8164cdf0e10cSrcweir }
8165cdf0e10cSrcweir else
8166cdf0e10cSrcweir nPos++;
8167cdf0e10cSrcweir }
8168cdf0e10cSrcweir else
8169cdf0e10cSrcweir break;
8170cdf0e10cSrcweir }
8171cdf0e10cSrcweir PushString( sStr );
8172cdf0e10cSrcweir }
8173cdf0e10cSrcweir }
8174cdf0e10cSrcweir
8175cdf0e10cSrcweir
ScRept()8176cdf0e10cSrcweir void ScInterpreter::ScRept()
8177cdf0e10cSrcweir {
8178cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScRept" );
8179cdf0e10cSrcweir if ( MustHaveParamCount( GetByte(), 2 ) )
8180cdf0e10cSrcweir {
8181cdf0e10cSrcweir double fAnz = ::rtl::math::approxFloor(GetDouble());
8182cdf0e10cSrcweir String aStr( GetString() );
8183cdf0e10cSrcweir if ( fAnz < 0.0 )
8184cdf0e10cSrcweir PushIllegalArgument();
8185cdf0e10cSrcweir else if ( fAnz * aStr.Len() > STRING_MAXLEN )
8186cdf0e10cSrcweir {
8187cdf0e10cSrcweir PushError( errStringOverflow );
8188cdf0e10cSrcweir }
8189cdf0e10cSrcweir else if ( fAnz == 0.0 )
8190cdf0e10cSrcweir PushString( EMPTY_STRING );
8191cdf0e10cSrcweir else
8192cdf0e10cSrcweir {
8193cdf0e10cSrcweir xub_StrLen n = (xub_StrLen) fAnz;
8194cdf0e10cSrcweir const xub_StrLen nLen = aStr.Len();
8195cdf0e10cSrcweir String aRes;
8196cdf0e10cSrcweir const sal_Unicode* const pSrc = aStr.GetBuffer();
8197cdf0e10cSrcweir sal_Unicode* pDst = aRes.AllocBuffer( n * nLen );
8198cdf0e10cSrcweir while( n-- )
8199cdf0e10cSrcweir {
8200cdf0e10cSrcweir memcpy( pDst, pSrc, nLen * sizeof(sal_Unicode) );
8201cdf0e10cSrcweir pDst += nLen;
8202cdf0e10cSrcweir }
8203cdf0e10cSrcweir PushString( aRes );
8204cdf0e10cSrcweir }
8205cdf0e10cSrcweir }
8206cdf0e10cSrcweir }
8207cdf0e10cSrcweir
8208cdf0e10cSrcweir
ScConcat()8209cdf0e10cSrcweir void ScInterpreter::ScConcat()
8210cdf0e10cSrcweir {
8211cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScConcat" );
8212cdf0e10cSrcweir sal_uInt8 nParamCount = GetByte();
8213cdf0e10cSrcweir String aRes;
8214cdf0e10cSrcweir while( nParamCount-- > 0)
8215cdf0e10cSrcweir {
8216cdf0e10cSrcweir const String& rStr = GetString();
8217cdf0e10cSrcweir aRes.Insert( rStr, 0 );
8218cdf0e10cSrcweir }
8219cdf0e10cSrcweir PushString( aRes );
8220cdf0e10cSrcweir }
8221cdf0e10cSrcweir
8222cdf0e10cSrcweir
ScErrorType()8223cdf0e10cSrcweir void ScInterpreter::ScErrorType()
8224cdf0e10cSrcweir {
8225cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScErrorType" );
8226cdf0e10cSrcweir sal_uInt16 nErr;
8227cdf0e10cSrcweir sal_uInt16 nOldError = nGlobalError;
8228cdf0e10cSrcweir nGlobalError = 0;
8229cdf0e10cSrcweir switch ( GetStackType() )
8230cdf0e10cSrcweir {
8231cdf0e10cSrcweir case svRefList :
8232cdf0e10cSrcweir {
8233cdf0e10cSrcweir FormulaTokenRef x = PopToken();
8234cdf0e10cSrcweir if (nGlobalError)
8235cdf0e10cSrcweir nErr = nGlobalError;
8236cdf0e10cSrcweir else
8237cdf0e10cSrcweir {
8238cdf0e10cSrcweir const ScRefList* pRefList = static_cast<ScToken*>(x.get())->GetRefList();
8239cdf0e10cSrcweir size_t n = pRefList->size();
8240cdf0e10cSrcweir if (!n)
8241cdf0e10cSrcweir nErr = errNoRef;
8242cdf0e10cSrcweir else if (n > 1)
8243cdf0e10cSrcweir nErr = errNoValue;
8244cdf0e10cSrcweir else
8245cdf0e10cSrcweir {
8246cdf0e10cSrcweir ScRange aRange;
8247cdf0e10cSrcweir DoubleRefToRange( (*pRefList)[0], aRange);
8248cdf0e10cSrcweir if (nGlobalError)
8249cdf0e10cSrcweir nErr = nGlobalError;
8250cdf0e10cSrcweir else
8251cdf0e10cSrcweir {
8252cdf0e10cSrcweir ScAddress aAdr;
8253cdf0e10cSrcweir if ( DoubleRefToPosSingleRef( aRange, aAdr ) )
8254cdf0e10cSrcweir nErr = pDok->GetErrCode( aAdr );
8255cdf0e10cSrcweir else
8256cdf0e10cSrcweir nErr = nGlobalError;
8257cdf0e10cSrcweir }
8258cdf0e10cSrcweir }
8259cdf0e10cSrcweir }
8260cdf0e10cSrcweir }
8261cdf0e10cSrcweir break;
8262cdf0e10cSrcweir case svDoubleRef :
8263cdf0e10cSrcweir {
8264cdf0e10cSrcweir ScRange aRange;
8265cdf0e10cSrcweir PopDoubleRef( aRange );
8266cdf0e10cSrcweir if ( nGlobalError )
8267cdf0e10cSrcweir nErr = nGlobalError;
8268cdf0e10cSrcweir else
8269cdf0e10cSrcweir {
8270cdf0e10cSrcweir ScAddress aAdr;
8271cdf0e10cSrcweir if ( DoubleRefToPosSingleRef( aRange, aAdr ) )
8272cdf0e10cSrcweir nErr = pDok->GetErrCode( aAdr );
8273cdf0e10cSrcweir else
8274cdf0e10cSrcweir nErr = nGlobalError;
8275cdf0e10cSrcweir }
8276cdf0e10cSrcweir }
8277cdf0e10cSrcweir break;
8278cdf0e10cSrcweir case svSingleRef :
8279cdf0e10cSrcweir {
8280cdf0e10cSrcweir ScAddress aAdr;
8281cdf0e10cSrcweir PopSingleRef( aAdr );
8282cdf0e10cSrcweir if ( nGlobalError )
8283cdf0e10cSrcweir nErr = nGlobalError;
8284cdf0e10cSrcweir else
8285cdf0e10cSrcweir nErr = pDok->GetErrCode( aAdr );
8286cdf0e10cSrcweir }
8287cdf0e10cSrcweir break;
8288cdf0e10cSrcweir default:
8289cdf0e10cSrcweir PopError();
8290cdf0e10cSrcweir nErr = nGlobalError;
8291cdf0e10cSrcweir }
8292cdf0e10cSrcweir if ( nErr )
8293cdf0e10cSrcweir {
8294cdf0e10cSrcweir nGlobalError = 0;
8295cdf0e10cSrcweir PushDouble( nErr );
8296cdf0e10cSrcweir }
8297cdf0e10cSrcweir else
8298cdf0e10cSrcweir {
8299cdf0e10cSrcweir nGlobalError = nOldError;
8300cdf0e10cSrcweir PushNA();
8301cdf0e10cSrcweir }
8302cdf0e10cSrcweir }
8303cdf0e10cSrcweir
8304cdf0e10cSrcweir
MayBeRegExp(const String & rStr,const ScDocument * pDoc)8305cdf0e10cSrcweir sal_Bool ScInterpreter::MayBeRegExp( const String& rStr, const ScDocument* pDoc )
8306cdf0e10cSrcweir {
8307cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::MayBeRegExp" );
8308cdf0e10cSrcweir if ( pDoc && !pDoc->GetDocOptions().IsFormulaRegexEnabled() )
8309cdf0e10cSrcweir return sal_False;
8310cdf0e10cSrcweir if ( !rStr.Len() || (rStr.Len() == 1 && rStr.GetChar(0) != '.') )
8311cdf0e10cSrcweir return sal_False; // einzelnes Metazeichen kann keine RegExp sein
8312cdf0e10cSrcweir static const sal_Unicode cre[] = { '.','*','+','?','[',']','^','$','\\','<','>','(',')','|', 0 };
8313cdf0e10cSrcweir const sal_Unicode* p1 = rStr.GetBuffer();
8314cdf0e10cSrcweir sal_Unicode c1;
8315cdf0e10cSrcweir while ( ( c1 = *p1++ ) != 0 )
8316cdf0e10cSrcweir {
8317cdf0e10cSrcweir const sal_Unicode* p2 = cre;
8318cdf0e10cSrcweir while ( *p2 )
8319cdf0e10cSrcweir {
8320cdf0e10cSrcweir if ( c1 == *p2++ )
8321cdf0e10cSrcweir return sal_True;
8322cdf0e10cSrcweir }
8323cdf0e10cSrcweir }
8324cdf0e10cSrcweir return sal_False;
8325cdf0e10cSrcweir }
8326cdf0e10cSrcweir
lcl_LookupQuery(ScAddress & o_rResultPos,ScDocument * pDoc,const ScQueryParam & rParam,const ScQueryEntry & rEntry)8327cdf0e10cSrcweir static bool lcl_LookupQuery( ScAddress & o_rResultPos, ScDocument * pDoc,
8328cdf0e10cSrcweir const ScQueryParam & rParam, const ScQueryEntry & rEntry )
8329cdf0e10cSrcweir {
8330cdf0e10cSrcweir bool bFound = false;
8331cdf0e10cSrcweir ScQueryCellIterator aCellIter( pDoc, rParam.nTab, rParam, sal_False);
8332cdf0e10cSrcweir if (rEntry.eOp != SC_EQUAL)
8333cdf0e10cSrcweir {
8334cdf0e10cSrcweir // range lookup <= or >=
8335cdf0e10cSrcweir SCCOL nCol;
8336cdf0e10cSrcweir SCROW nRow;
8337cdf0e10cSrcweir bFound = aCellIter.FindEqualOrSortedLastInRange( nCol, nRow);
8338cdf0e10cSrcweir if (bFound)
8339cdf0e10cSrcweir {
8340cdf0e10cSrcweir o_rResultPos.SetCol( nCol);
8341cdf0e10cSrcweir o_rResultPos.SetRow( nRow);
8342cdf0e10cSrcweir }
8343cdf0e10cSrcweir }
8344cdf0e10cSrcweir else if (aCellIter.GetFirst())
8345cdf0e10cSrcweir {
8346cdf0e10cSrcweir // EQUAL
8347cdf0e10cSrcweir bFound = true;
8348cdf0e10cSrcweir o_rResultPos.SetCol( aCellIter.GetCol());
8349cdf0e10cSrcweir o_rResultPos.SetRow( aCellIter.GetRow());
8350cdf0e10cSrcweir }
8351cdf0e10cSrcweir return bFound;
8352cdf0e10cSrcweir }
8353cdf0e10cSrcweir
8354cdf0e10cSrcweir #define erDEBUG_LOOKUPCACHE 0
8355cdf0e10cSrcweir #if erDEBUG_LOOKUPCACHE
8356cdf0e10cSrcweir #include <cstdio>
8357cdf0e10cSrcweir using ::std::fprintf;
8358cdf0e10cSrcweir using ::std::fflush;
8359cdf0e10cSrcweir static struct LookupCacheDebugCounter
8360cdf0e10cSrcweir {
8361cdf0e10cSrcweir unsigned long nMiss;
8362cdf0e10cSrcweir unsigned long nHit;
LookupCacheDebugCounterLookupCacheDebugCounter8363cdf0e10cSrcweir LookupCacheDebugCounter() : nMiss(0), nHit(0) {}
~LookupCacheDebugCounterLookupCacheDebugCounter8364cdf0e10cSrcweir ~LookupCacheDebugCounter()
8365cdf0e10cSrcweir {
8366cdf0e10cSrcweir fprintf( stderr, "\nmiss: %lu, hit: %lu, total: %lu, hit/miss: %lu, hit/total %lu%\n",
8367cdf0e10cSrcweir nMiss, nHit, nHit+nMiss, (nMiss>0 ? nHit/nMiss : 0),
8368cdf0e10cSrcweir ((nHit+nMiss)>0 ? (100*nHit)/(nHit+nMiss) : 0));
8369cdf0e10cSrcweir fflush( stderr);
8370cdf0e10cSrcweir }
8371cdf0e10cSrcweir } aLookupCacheDebugCounter;
8372cdf0e10cSrcweir #endif
8373cdf0e10cSrcweir
LookupQueryWithCache(ScAddress & o_rResultPos,const ScQueryParam & rParam) const8374cdf0e10cSrcweir bool ScInterpreter::LookupQueryWithCache( ScAddress & o_rResultPos,
8375cdf0e10cSrcweir const ScQueryParam & rParam ) const
8376cdf0e10cSrcweir {
8377cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::LookupQueryWithCache" );
8378cdf0e10cSrcweir bool bFound = false;
8379cdf0e10cSrcweir const ScQueryEntry& rEntry = rParam.GetEntry(0);
8380cdf0e10cSrcweir bool bColumnsMatch = (rParam.nCol1 == rEntry.nField);
8381cdf0e10cSrcweir DBG_ASSERT( bColumnsMatch, "ScInterpreter::LookupQueryWithCache: columns don't match");
8382cdf0e10cSrcweir if (!bColumnsMatch)
8383cdf0e10cSrcweir bFound = lcl_LookupQuery( o_rResultPos, pDok, rParam, rEntry);
8384cdf0e10cSrcweir else
8385cdf0e10cSrcweir {
8386cdf0e10cSrcweir ScRange aLookupRange( rParam.nCol1, rParam.nRow1, rParam.nTab,
8387cdf0e10cSrcweir rParam.nCol2, rParam.nRow2, rParam.nTab);
8388cdf0e10cSrcweir ScLookupCache& rCache = pDok->GetLookupCache( aLookupRange);
8389cdf0e10cSrcweir ScLookupCache::QueryCriteria aCriteria( rEntry);
8390cdf0e10cSrcweir ScLookupCache::Result eCacheResult = rCache.lookup( o_rResultPos,
8391cdf0e10cSrcweir aCriteria, aPos);
8392cdf0e10cSrcweir switch (eCacheResult)
8393cdf0e10cSrcweir {
8394cdf0e10cSrcweir case ScLookupCache::NOT_CACHED :
8395cdf0e10cSrcweir case ScLookupCache::CRITERIA_DIFFERENT :
8396cdf0e10cSrcweir #if erDEBUG_LOOKUPCACHE
8397cdf0e10cSrcweir ++aLookupCacheDebugCounter.nMiss;
8398cdf0e10cSrcweir #if erDEBUG_LOOKUPCACHE > 1
8399cdf0e10cSrcweir fprintf( stderr, "miss %d,%d,%d\n", (int)aPos.Col(), (int)aPos.Row(), (int)aPos.Tab());
8400cdf0e10cSrcweir #endif
8401cdf0e10cSrcweir #endif
8402cdf0e10cSrcweir bFound = lcl_LookupQuery( o_rResultPos, pDok, rParam, rEntry);
8403cdf0e10cSrcweir if (eCacheResult == ScLookupCache::NOT_CACHED)
8404cdf0e10cSrcweir rCache.insert( o_rResultPos, aCriteria, aPos, bFound);
8405cdf0e10cSrcweir break;
8406cdf0e10cSrcweir case ScLookupCache::FOUND :
8407cdf0e10cSrcweir #if erDEBUG_LOOKUPCACHE
8408cdf0e10cSrcweir ++aLookupCacheDebugCounter.nHit;
8409cdf0e10cSrcweir #if erDEBUG_LOOKUPCACHE > 1
8410cdf0e10cSrcweir fprintf( stderr, "hit %d,%d,%d\n", (int)aPos.Col(), (int)aPos.Row(), (int)aPos.Tab());
8411cdf0e10cSrcweir #endif
8412cdf0e10cSrcweir #endif
8413cdf0e10cSrcweir bFound = true;
8414cdf0e10cSrcweir break;
8415cdf0e10cSrcweir case ScLookupCache::NOT_AVAILABLE :
8416cdf0e10cSrcweir ; // nothing, bFound remains FALSE
8417cdf0e10cSrcweir break;
8418cdf0e10cSrcweir }
8419cdf0e10cSrcweir }
8420cdf0e10cSrcweir return bFound;
8421cdf0e10cSrcweir }
8422