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