1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: formulaparser.cxx,v $
10 * $Revision: 1.5.20.5 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 #include "oox/xls/formulaparser.hxx"
32 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
33 #include <com/sun/star/sheet/ComplexReference.hpp>
34 #include <com/sun/star/sheet/ExternalReference.hpp>
35 #include <com/sun/star/sheet/FormulaToken.hpp>
36 #include <com/sun/star/sheet/ReferenceFlags.hpp>
37 #include <com/sun/star/sheet/SingleReference.hpp>
38 #include "properties.hxx"
39 #include "oox/helper/recordinputstream.hxx"
40 #include "oox/core/filterbase.hxx"
41 #include "oox/xls/addressconverter.hxx"
42 #include "oox/xls/biffinputstream.hxx"
43 #include "oox/xls/defnamesbuffer.hxx"
44 #include "oox/xls/externallinkbuffer.hxx"
45 #include "oox/xls/tablebuffer.hxx"
46 #include "oox/xls/worksheethelper.hxx"
48 using ::rtl::OUString
;
49 using ::com::sun::star::uno::Any
;
50 using ::com::sun::star::uno::Reference
;
51 using ::com::sun::star::uno::Sequence
;
52 using ::com::sun::star::uno::Exception
;
53 using ::com::sun::star::uno::UNO_QUERY
;
54 using ::com::sun::star::uno::UNO_QUERY_THROW
;
55 using ::com::sun::star::table::CellAddress
;
56 using ::com::sun::star::table::CellRangeAddress
;
57 using ::com::sun::star::sheet::ComplexReference
;
58 using ::com::sun::star::sheet::ExternalReference
;
59 using ::com::sun::star::sheet::SingleReference
;
60 using ::com::sun::star::sheet::XFormulaParser
;
61 using namespace ::com::sun::star::sheet::ReferenceFlags
;
66 // ============================================================================
70 sal_uInt16
lclReadFmlaSize( BiffInputStream
& rStrm
, BiffType eBiff
, const sal_uInt16
* pnFmlaSize
)
72 return pnFmlaSize
? *pnFmlaSize
: ((eBiff
== BIFF2
) ? rStrm
.readuInt8() : rStrm
.readuInt16());
77 // formula finalizer ==========================================================
79 FormulaFinalizer::FormulaFinalizer( const OpCodeProvider
& rOpCodeProv
) :
80 OpCodeProvider( rOpCodeProv
),
81 ApiOpCodes( getOpCodes() )
83 maTokens
.reserve( 0x2000 );
86 ApiTokenSequence
FormulaFinalizer::finalizeTokenArray( const ApiTokenSequence
& rTokens
)
89 if( rTokens
.hasElements() )
91 const ApiToken
* pToken
= rTokens
.getConstArray();
92 processTokens( pToken
, pToken
+ rTokens
.getLength() );
94 return ContainerHelper::vectorToSequence( maTokens
);
97 const FunctionInfo
* FormulaFinalizer::resolveBadFuncName( const OUString
& ) const
102 OUString
FormulaFinalizer::resolveDefinedName( sal_Int32
) const
107 const FunctionInfo
* FormulaFinalizer::getFunctionInfo( ApiToken
& orFuncToken
)
109 // first, try to find a regular function info from token op-code
110 if( const FunctionInfo
* pRegFuncInfo
= getFuncInfoFromApiToken( orFuncToken
) )
113 // try to recognize a function from an external library
114 if( (orFuncToken
.OpCode
== OPCODE_BAD
) && orFuncToken
.Data
.has
< OUString
>() )
116 // virtual call to resolveBadFuncName()
117 if( const FunctionInfo
* pLibFuncInfo
= resolveBadFuncName( orFuncToken
.Data
.get
< OUString
>() ) )
119 // write function op-code to the OPCODE_BAD token
120 orFuncToken
.OpCode
= pLibFuncInfo
->mnApiOpCode
;
121 // if it is an external function, insert programmatic function name
122 if( (orFuncToken
.OpCode
== OPCODE_EXTERNAL
) && (pLibFuncInfo
->maExtProgName
.getLength() > 0) )
123 orFuncToken
.Data
<<= pLibFuncInfo
->maExtProgName
;
125 orFuncToken
.Data
.clear(); // clear string from OPCODE_BAD
130 // no success - return null
135 const FunctionInfo
* FormulaFinalizer::getExternCallInfo( ApiToken
& orFuncToken
, const ApiToken
& rECToken
)
137 // try to resolve the passed token to a supported sheet function
138 if( const FunctionInfo
* pFuncInfo
= getFuncInfoFromApiToken( rECToken
) )
140 orFuncToken
.OpCode
= pFuncInfo
->mnApiOpCode
;
141 // programmatic add-in function name
142 if( (pFuncInfo
->mnApiOpCode
== OPCODE_EXTERNAL
) && (pFuncInfo
->maExtProgName
.getLength() > 0) )
143 orFuncToken
.Data
<<= pFuncInfo
->maExtProgName
;
144 // name of unsupported function, convert to OPCODE_BAD to preserve the name
145 else if( (pFuncInfo
->mnApiOpCode
== OPCODE_BAD
) && (pFuncInfo
->maOoxFuncName
.getLength() > 0) )
146 orFuncToken
.Data
<<= pFuncInfo
->maOoxFuncName
;
150 // macro call or unknown function name, move data to function token
151 if( (rECToken
.OpCode
== OPCODE_MACRO
) || (rECToken
.OpCode
== OPCODE_BAD
) )
152 orFuncToken
= rECToken
;
154 // defined name used as function call, convert to OPCODE_BAD to preserve the name
155 if( (rECToken
.OpCode
== OPCODE_NAME
) && rECToken
.Data
.has
< sal_Int32
>() )
157 OUString aDefName
= resolveDefinedName( rECToken
.Data
.get
< sal_Int32
>() );
158 if( aDefName
.getLength() > 0 )
160 orFuncToken
.OpCode
= OPCODE_BAD
;
161 orFuncToken
.Data
<<= aDefName
;
168 void FormulaFinalizer::processTokens( const ApiToken
* pToken
, const ApiToken
* pTokenEnd
)
170 while( pToken
< pTokenEnd
)
172 // push the current token into the vector
173 bool bValid
= appendFinalToken( *pToken
);
174 // try to process a function
175 if( const FunctionInfo
* pFuncInfo
= bValid
? getFunctionInfo( maTokens
.back() ) : 0 )
176 pToken
= processParameters( *pFuncInfo
, pToken
+ 1, pTokenEnd
);
177 // otherwise, go to next token
183 const ApiToken
* FormulaFinalizer::processParameters(
184 const FunctionInfo
& rFuncInfo
, const ApiToken
* pToken
, const ApiToken
* pTokenEnd
)
186 // remember position of the token containing the function op-code
187 size_t nFuncNameIdx
= maTokens
.size() - 1;
189 // process a function, if an OPCODE_OPEN token is following
190 OSL_ENSURE( (pToken
< pTokenEnd
) && (pToken
->OpCode
== OPCODE_OPEN
), "FormulaFinalizer::processParameters - OPCODE_OPEN expected" );
191 if( (pToken
< pTokenEnd
) && (pToken
->OpCode
== OPCODE_OPEN
) )
193 // append the OPCODE_OPEN token to the vector
194 maTokens
.append( OPCODE_OPEN
);
196 // store positions of OPCODE_OPEN, parameter separators, and OPCODE_CLOSE
197 ParameterPosVector aParams
;
198 pToken
= findParameters( aParams
, pToken
, pTokenEnd
);
199 OSL_ENSURE( aParams
.size() >= 2, "FormulaFinalizer::processParameters - missing tokens" );
200 size_t nParamCount
= aParams
.size() - 1;
202 if( (nParamCount
== 1) && isEmptyParameter( aParams
[ 0 ] + 1, aParams
[ 1 ] ) )
204 /* Empty pair of parentheses -> function call without parameters,
205 process parameter, there might be spaces between parentheses. */
206 processTokens( aParams
[ 0 ] + 1, aParams
[ 1 ] );
210 const FunctionInfo
* pRealFuncInfo
= &rFuncInfo
;
211 ParameterPosVector::const_iterator aPosIt
= aParams
.begin();
213 /* Preprocess EXTERN.CALL functions. The actual function name is
214 contained as reference to a defined name in the first (hidden)
216 if( rFuncInfo
.mnBiffFuncId
== BIFF_FUNC_EXTERNCALL
)
218 ApiToken
& rFuncToken
= maTokens
[ nFuncNameIdx
];
219 rFuncToken
.OpCode
= OPCODE_NONAME
;
221 // try to initialize function token from first parameter
222 if( const ApiToken
* pECToken
= getSingleToken( *aPosIt
+ 1, *(aPosIt
+ 1) ) )
223 if( const FunctionInfo
* pECFuncInfo
= getExternCallInfo( rFuncToken
, *pECToken
) )
224 pRealFuncInfo
= pECFuncInfo
;
226 /* On success (something has been inserted into rFuncToken),
227 skip the first parameter. */
228 if( rFuncToken
.OpCode
!= OPCODE_NONAME
)
235 // process all parameters
236 FunctionParamInfoIterator
aParamInfoIt( *pRealFuncInfo
);
237 size_t nLastValidSize
= maTokens
.size();
238 size_t nLastValidCount
= 0;
239 for( size_t nParam
= 0; nParam
< nParamCount
; ++nParam
, ++aPosIt
, ++aParamInfoIt
)
241 // add embedded Calc-only parameters
242 if( aParamInfoIt
.isCalcOnlyParam() )
244 appendCalcOnlyParameter( *pRealFuncInfo
, nParam
);
245 while( aParamInfoIt
.isCalcOnlyParam() ) ++aParamInfoIt
;
248 const ApiToken
* pParamBegin
= *aPosIt
+ 1;
249 const ApiToken
* pParamEnd
= *(aPosIt
+ 1);
250 bool bIsEmpty
= isEmptyParameter( pParamBegin
, pParamEnd
);
252 if( !aParamInfoIt
.isExcelOnlyParam() )
254 // replace empty second and third parameter in IF function with zeros
255 if( (pRealFuncInfo
->mnOobFuncId
== OOBIN_FUNC_IF
) && ((nParam
== 1) || (nParam
== 2)) && bIsEmpty
)
257 maTokens
.append
< double >( OPCODE_PUSH
, 0.0 );
262 // process all tokens of the parameter
263 processTokens( pParamBegin
, pParamEnd
);
265 // append parameter separator token
266 maTokens
.append( OPCODE_SEP
);
269 /* #84453# Update size of new token sequence with valid parameters
270 to be able to remove trailing optional empty parameters. */
271 if( !bIsEmpty
|| (nParam
< pRealFuncInfo
->mnMinParamCount
) )
273 nLastValidSize
= maTokens
.size();
274 nLastValidCount
= nParam
+ 1;
278 // #84453# remove trailing optional empty parameters
279 maTokens
.resize( nLastValidSize
);
281 // add trailing Calc-only parameters
282 if( aParamInfoIt
.isCalcOnlyParam() )
283 appendCalcOnlyParameter( *pRealFuncInfo
, nLastValidCount
);
285 // add optional parameters that are required in Calc
286 appendRequiredParameters( *pRealFuncInfo
, nLastValidCount
);
288 // remove last parameter separator token
289 if( maTokens
.back().OpCode
== OPCODE_SEP
)
293 /* Append the OPCODE_CLOSE token to the vector, but only if there is
294 no OPCODE_BAD token at the end, this token already contains the
295 trailing closing parentheses. */
296 if( (pTokenEnd
- 1)->OpCode
!= OPCODE_BAD
)
297 maTokens
.append( OPCODE_CLOSE
);
300 /* Replace OPCODE_EXTERNAL with OPCODE_NONAME to get #NAME! error in cell,
301 if no matching add-in function was found. */
302 ApiToken
& rFuncNameToken
= maTokens
[ nFuncNameIdx
];
303 if( (rFuncNameToken
.OpCode
== OPCODE_EXTERNAL
) && !rFuncNameToken
.Data
.hasValue() )
304 rFuncNameToken
.OpCode
= OPCODE_NONAME
;
309 bool FormulaFinalizer::isEmptyParameter( const ApiToken
* pToken
, const ApiToken
* pTokenEnd
) const
311 while( (pToken
< pTokenEnd
) && (pToken
->OpCode
== OPCODE_SPACES
) ) ++pToken
;
312 if( (pToken
< pTokenEnd
) && (pToken
->OpCode
== OPCODE_MISSING
) ) ++pToken
;
313 while( (pToken
< pTokenEnd
) && (pToken
->OpCode
== OPCODE_SPACES
) ) ++pToken
;
314 return pToken
== pTokenEnd
;
317 const ApiToken
* FormulaFinalizer::getSingleToken( const ApiToken
* pToken
, const ApiToken
* pTokenEnd
) const
319 const ApiToken
* pSingleToken
= 0;
320 // skip leading whitespace tokens
321 while( (pToken
< pTokenEnd
) && (pToken
->OpCode
== OPCODE_SPACES
) ) ++pToken
;
322 // remember first non-whitespace token
323 if( pToken
< pTokenEnd
) pSingleToken
= pToken
++;
324 // skip trailing whitespace tokens
325 while( (pToken
< pTokenEnd
) && (pToken
->OpCode
== OPCODE_SPACES
) ) ++pToken
;
326 // return null, if other non-whitespace tokens follow
327 return (pToken
== pTokenEnd
) ? pSingleToken
: 0;
330 const ApiToken
* FormulaFinalizer::skipParentheses( const ApiToken
* pToken
, const ApiToken
* pTokenEnd
) const
332 // skip tokens between OPCODE_OPEN and OPCODE_CLOSE
333 OSL_ENSURE( (pToken
< pTokenEnd
) && (pToken
->OpCode
== OPCODE_OPEN
), "skipParentheses - OPCODE_OPEN expected" );
335 while( (pToken
< pTokenEnd
) && (pToken
->OpCode
!= OPCODE_CLOSE
) )
337 if( pToken
->OpCode
== OPCODE_OPEN
)
338 pToken
= skipParentheses( pToken
, pTokenEnd
);
342 // skip the OPCODE_CLOSE token
343 OSL_ENSURE( ((pToken
< pTokenEnd
) && (pToken
->OpCode
== OPCODE_CLOSE
)) || ((pTokenEnd
- 1)->OpCode
== OPCODE_BAD
), "skipParentheses - OPCODE_CLOSE expected" );
344 return (pToken
< pTokenEnd
) ? (pToken
+ 1) : pTokenEnd
;
347 const ApiToken
* FormulaFinalizer::findParameters( ParameterPosVector
& rParams
,
348 const ApiToken
* pToken
, const ApiToken
* pTokenEnd
) const
350 // push position of OPCODE_OPEN
351 OSL_ENSURE( (pToken
< pTokenEnd
) && (pToken
->OpCode
== OPCODE_OPEN
), "FormulaFinalizer::findParameters - OPCODE_OPEN expected" );
352 rParams
.push_back( pToken
++ );
354 // find positions of parameter separators
355 while( (pToken
< pTokenEnd
) && (pToken
->OpCode
!= OPCODE_CLOSE
) )
357 if( pToken
->OpCode
== OPCODE_OPEN
)
358 pToken
= skipParentheses( pToken
, pTokenEnd
);
359 else if( pToken
->OpCode
== OPCODE_SEP
)
360 rParams
.push_back( pToken
++ );
365 // push position of OPCODE_CLOSE
366 OSL_ENSURE( ((pToken
< pTokenEnd
) && (pToken
->OpCode
== OPCODE_CLOSE
)) || ((pTokenEnd
- 1)->OpCode
== OPCODE_BAD
), "FormulaFinalizer::findParameters - OPCODE_CLOSE expected" );
367 rParams
.push_back( pToken
);
368 return (pToken
< pTokenEnd
) ? (pToken
+ 1) : pTokenEnd
;
371 void FormulaFinalizer::appendCalcOnlyParameter( const FunctionInfo
& rFuncInfo
, size_t nParam
)
373 (void)nParam
; // prevent 'unused' warning
374 switch( rFuncInfo
.mnOobFuncId
)
376 case OOBIN_FUNC_FLOOR
:
377 case OOBIN_FUNC_CEILING
:
378 OSL_ENSURE( nParam
== 2, "FormulaFinalizer::appendCalcOnlyParameter - unexpected parameter index" );
379 maTokens
.append
< double >( OPCODE_PUSH
, 1.0 );
380 maTokens
.append( OPCODE_SEP
);
385 void FormulaFinalizer::appendRequiredParameters( const FunctionInfo
& rFuncInfo
, size_t nParamCount
)
387 switch( rFuncInfo
.mnOobFuncId
)
389 case OOBIN_FUNC_WEEKNUM
:
390 if( nParamCount
== 1 )
392 maTokens
.append
< double >( OPCODE_PUSH
, 1.0 );
393 maTokens
.append( OPCODE_SEP
);
399 bool FormulaFinalizer::appendFinalToken( const ApiToken
& rToken
)
401 // replace OPCODE_MACRO without macro name with #NAME? error code
402 bool bValid
= (rToken
.OpCode
!= OPCODE_MACRO
) || rToken
.Data
.hasValue();
405 maTokens
.push_back( rToken
);
409 maTokens
.append( OPCODE_ARRAY_OPEN
);
410 maTokens
.append( OPCODE_PUSH
, BiffHelper::calcDoubleFromError( BIFF_ERR_NAME
) );
411 maTokens
.append( OPCODE_ARRAY_CLOSE
);
416 // parser implementation base =================================================
418 class FormulaParserImpl
: public FormulaFinalizer
, public WorkbookHelper
421 explicit FormulaParserImpl( const FormulaParser
& rParent
);
423 /** Converts an XML formula string. */
424 virtual void importOoxFormula(
425 FormulaContext
& rContext
,
426 const OUString
& rFormulaString
);
428 /** Imports and converts a OOBIN token array from the passed stream. */
429 virtual void importOobFormula(
430 FormulaContext
& rContext
,
431 RecordInputStream
& rStrm
);
433 /** Imports and converts a BIFF token array from the passed stream. */
434 virtual void importBiffFormula(
435 FormulaContext
& rContext
,
436 BiffInputStream
& rStrm
, const sal_uInt16
* pnFmlaSize
);
438 /** Finalizes the passed token array after import (e.g. adjusts function
439 parameters) and sets the formula using the passed context. */
441 FormulaContext
& rContext
,
442 const ApiTokenSequence
& rTokens
);
444 /** Tries to resolve the passed ref-id to an OLE target URL. */
445 OUString
resolveOleTarget( sal_Int32 nRefId
) const;
448 typedef ::std::pair
< sal_Int32
, bool > WhiteSpace
;
449 typedef ::std::vector
< WhiteSpace
> WhiteSpaceVec
;
451 /** Sets the current formula context used for import. */
452 inline FormulaContext
& getFormulaContext() const { return *mpContext
; }
454 /** Sets the current formula context used for import. */
455 void initializeImport( FormulaContext
& rContext
);
456 /** Finalizes the passed token array after import. */
457 void finalizeImport( const ApiTokenSequence
& rTokens
);
458 /** Finalizes the internal token storage after import. */
459 void finalizeImport();
461 /** Inserts a shared formula using the current formula context and passed base address. */
462 void setSharedFormula( const BinAddress
& rBaseAddr
);
464 // token array ------------------------------------------------------------
467 static void appendSpaces( WhiteSpaceVec
& orSpaces
, sal_Int32 nCount
, bool bLineFeed
);
468 void appendLeadingSpaces( sal_Int32 nCount
, bool bLineFeed
);
469 void appendOpeningSpaces( sal_Int32 nCount
, bool bLineFeed
);
470 void appendClosingSpaces( sal_Int32 nCount
, bool bLineFeed
);
472 size_t getFormulaSize() const;
473 Any
& appendRawToken( sal_Int32 nOpCode
);
474 Any
& insertRawToken( sal_Int32 nOpCode
, size_t nIndexFromEnd
);
475 size_t appendWhiteSpaceTokens( const WhiteSpaceVec
* pSpaces
);
476 size_t insertWhiteSpaceTokens( const WhiteSpaceVec
* pSpaces
, size_t nIndexFromEnd
);
478 size_t getOperandSize( size_t nOpCountFromEnd
, size_t nOpIndex
) const;
479 void pushOperandSize( size_t nSize
);
480 size_t popOperandSize();
482 ApiToken
& getOperandToken( size_t nOpCountFromEnd
, size_t nOpIndex
, size_t nTokenIndex
);
483 void removeOperand( size_t nOpCountFromEnd
, size_t nOpIndex
);
484 void removeLastOperands( size_t nOpCountFromEnd
);
486 bool pushOperandToken( sal_Int32 nOpCode
, const WhiteSpaceVec
* pSpaces
= 0 );
487 bool pushAnyOperandToken( const Any
& rAny
, sal_Int32 nOpCode
, const WhiteSpaceVec
* pSpaces
= 0 );
488 template< typename Type
>
489 bool pushValueOperandToken( const Type
& rValue
, sal_Int32 nOpCode
, const WhiteSpaceVec
* pSpaces
= 0 );
490 template< typename Type
>
491 inline bool pushValueOperandToken( const Type
& rValue
, const WhiteSpaceVec
* pSpaces
= 0 )
492 { return pushValueOperandToken( rValue
, OPCODE_PUSH
, pSpaces
); }
493 bool pushParenthesesOperandToken( const WhiteSpaceVec
* pOpeningSpaces
= 0, const WhiteSpaceVec
* pClosingSpaces
= 0 );
494 bool pushUnaryPreOperatorToken( sal_Int32 nOpCode
, const WhiteSpaceVec
* pSpaces
= 0 );
495 bool pushUnaryPostOperatorToken( sal_Int32 nOpCode
, const WhiteSpaceVec
* pSpaces
= 0 );
496 bool pushBinaryOperatorToken( sal_Int32 nOpCode
, const WhiteSpaceVec
* pSpaces
= 0 );
497 bool pushParenthesesOperatorToken( const WhiteSpaceVec
* pOpeningSpaces
= 0, const WhiteSpaceVec
* pClosingSpaces
= 0 );
498 bool pushFunctionOperatorToken( sal_Int32 nOpCode
, size_t nParamCount
, const WhiteSpaceVec
* pLeadingSpaces
= 0, const WhiteSpaceVec
* pClosingSpaces
= 0 );
499 bool pushFunctionOperatorToken( const FunctionInfo
& rFuncInfo
, size_t nParamCount
, const WhiteSpaceVec
* pLeadingSpaces
= 0, const WhiteSpaceVec
* pClosingSpaces
= 0 );
501 bool pushOperand( sal_Int32 nOpCode
);
502 bool pushAnyOperand( const Any
& rAny
, sal_Int32 nOpCode
);
503 template< typename Type
>
504 bool pushValueOperand( const Type
& rValue
, sal_Int32 nOpCode
);
505 template< typename Type
>
506 inline bool pushValueOperand( const Type
& rValue
)
507 { return pushValueOperand( rValue
, OPCODE_PUSH
); }
508 bool pushBoolOperand( bool bValue
);
509 bool pushErrorOperand( double fEncodedError
);
510 bool pushBiffBoolOperand( sal_uInt8 nValue
);
511 bool pushBiffErrorOperand( sal_uInt8 nErrorCode
);
512 bool pushParenthesesOperand();
513 bool pushReferenceOperand( const BinSingleRef2d
& rRef
, bool bDeleted
, bool bRelativeAsOffset
);
514 bool pushReferenceOperand( const BinComplexRef2d
& rRef
, bool bDeleted
, bool bRelativeAsOffset
);
515 template< typename Type
>
516 bool pushReferenceOperand( const LinkSheetRange
& rSheetRange
, const Type
& rApiRef
);
517 bool pushReferenceOperand( const LinkSheetRange
& rSheetRange
, const BinSingleRef2d
& rRef
, bool bDeleted
, bool bRelativeAsOffset
);
518 bool pushReferenceOperand( const LinkSheetRange
& rSheetRange
, const BinComplexRef2d
& rRef
, bool bDeleted
, bool bRelativeAsOffset
);
519 bool pushNlrOperand( const BinSingleRef2d
& rRef
);
520 bool pushEmbeddedRefOperand( const DefinedNameBase
& rName
, bool bPushBadToken
);
521 bool pushDefinedNameOperand( const DefinedNameRef
& rxDefName
);
522 bool pushExternalFuncOperand( const FunctionInfo
& rFuncInfo
);
523 bool pushDdeLinkOperand( const OUString
& rDdeServer
, const OUString
& rDdeTopic
, const OUString
& rDdeItem
);
524 bool pushExternalNameOperand( const ExternalNameRef
& rxExtName
, const ExternalLink
& rExtLink
);
526 bool pushUnaryPreOperator( sal_Int32 nOpCode
);
527 bool pushUnaryPostOperator( sal_Int32 nOpCode
);
528 bool pushBinaryOperator( sal_Int32 nOpCode
);
529 bool pushParenthesesOperator();
530 bool pushFunctionOperator( sal_Int32 nOpCode
, size_t nParamCount
);
531 bool pushFunctionOperator( const FunctionInfo
& rFuncInfo
, size_t nParamCount
);
534 // reference conversion ---------------------------------------------------
536 void initReference2d( SingleReference
& orApiRef
) const;
537 void initReference3d( SingleReference
& orApiRef
, sal_Int32 nSheet
, bool bSameSheet
) const;
538 void convertColRow( SingleReference
& orApiRef
, const BinSingleRef2d
& rRef
, bool bRelativeAsOffset
) const;
539 void convertReference( SingleReference
& orApiRef
, const BinSingleRef2d
& rRef
, bool bDeleted
, bool bRelativeAsOffset
) const;
540 void convertReference( ComplexReference
& orApiRef
, const BinSingleRef2d
& rRef1
, const BinSingleRef2d
& rRef2
, bool bDeleted
, bool bRelativeAsOffset
) const;
541 void convertReference2d( SingleReference
& orApiRef
, const BinSingleRef2d
& rRef
, bool bDeleted
, bool bRelativeAsOffset
) const;
542 void convertReference2d( ComplexReference
& orApiRef
, const BinSingleRef2d
& rRef1
, const BinSingleRef2d
& rRef2
, bool bDeleted
, bool bRelativeAsOffset
) const;
543 void convertReference3d( SingleReference
& orApiRef
, sal_Int32 nSheet
, bool bSameSheet
, const BinSingleRef2d
& rRef
, bool bDeleted
, bool bRelativeAsOffset
) const;
544 void convertReference3d( ComplexReference
& orApiRef
, const LinkSheetRange
& rSheetRange
, const BinSingleRef2d
& rRef1
, const BinSingleRef2d
& rRef2
, bool bDeleted
, bool bRelativeAsOffset
) const;
547 // finalize token sequence ------------------------------------------------
549 virtual const FunctionInfo
* resolveBadFuncName( const OUString
& rTokenData
) const;
550 virtual ::rtl::OUString
resolveDefinedName( sal_Int32 nTokenIndex
) const;
553 const sal_Int32 mnMaxApiCol
; /// Maximum column index in own document.
554 const sal_Int32 mnMaxApiRow
; /// Maximum row index in own document.
555 const sal_Int32 mnMaxXlsCol
; /// Maximum column index in imported document.
556 const sal_Int32 mnMaxXlsRow
; /// Maximum row index in imported document.
559 typedef ::std::vector
< size_t > SizeTypeVector
;
561 ApiTokenVector maTokenStorage
; /// Raw unordered token storage.
562 SizeTypeVector maTokenIndexes
; /// Indexes into maTokenStorage.
563 SizeTypeVector maOperandSizeStack
; /// Stack with token sizes per operand.
564 WhiteSpaceVec maLeadingSpaces
; /// List of whitespaces before next token.
565 WhiteSpaceVec maOpeningSpaces
; /// List of whitespaces before opening parenthesis.
566 WhiteSpaceVec maClosingSpaces
; /// List of whitespaces before closing parenthesis.
567 FormulaContext
* mpContext
; /// Current formula context.
570 // ----------------------------------------------------------------------------
572 FormulaParserImpl::FormulaParserImpl( const FormulaParser
& rParent
) :
573 FormulaFinalizer( rParent
),
574 WorkbookHelper( rParent
),
575 mnMaxApiCol( rParent
.getAddressConverter().getMaxApiAddress().Column
),
576 mnMaxApiRow( rParent
.getAddressConverter().getMaxApiAddress().Row
),
577 mnMaxXlsCol( rParent
.getAddressConverter().getMaxXlsAddress().Column
),
578 mnMaxXlsRow( rParent
.getAddressConverter().getMaxXlsAddress().Row
),
581 // reserve enough space to make resize(), push_back() etc. cheap
582 maTokenStorage
.reserve( 0x2000 );
583 maTokenIndexes
.reserve( 0x2000 );
584 maOperandSizeStack
.reserve( 256 );
585 maLeadingSpaces
.reserve( 256 );
586 maOpeningSpaces
.reserve( 256 );
587 maClosingSpaces
.reserve( 256 );
590 void FormulaParserImpl::importOoxFormula( FormulaContext
&, const OUString
& )
592 OSL_ENSURE( false, "FormulaParserImpl::importOoxFormula - not implemented" );
595 void FormulaParserImpl::importOobFormula( FormulaContext
&, RecordInputStream
& )
597 OSL_ENSURE( false, "FormulaParserImpl::importOobFormula - not implemented" );
600 void FormulaParserImpl::importBiffFormula( FormulaContext
&, BiffInputStream
&, const sal_uInt16
* )
602 OSL_ENSURE( false, "FormulaParserImpl::importBiffFormula - not implemented" );
605 void FormulaParserImpl::setFormula( FormulaContext
& rContext
, const ApiTokenSequence
& rTokens
)
607 initializeImport( rContext
);
608 finalizeImport( rTokens
);
611 OUString
FormulaParserImpl::resolveOleTarget( sal_Int32 nRefId
) const
613 const ExternalLink
* pExtLink
= getExternalLinks().getExternalLink( nRefId
).get();
614 OSL_ENSURE( pExtLink
&& (pExtLink
->getLinkType() == LINKTYPE_OLE
), "FormulaParserImpl::resolveOleTarget - missing or wrong link" );
615 if( pExtLink
&& (pExtLink
->getLinkType() == LINKTYPE_OLE
) )
616 return getBaseFilter().getAbsoluteUrl( pExtLink
->getTargetUrl() );
620 void FormulaParserImpl::initializeImport( FormulaContext
& rContext
)
622 maTokenStorage
.clear();
623 maTokenIndexes
.clear();
624 maOperandSizeStack
.clear();
625 mpContext
= &rContext
;
628 void FormulaParserImpl::finalizeImport( const ApiTokenSequence
& rTokens
)
630 ApiTokenSequence aFinalTokens
= finalizeTokenArray( rTokens
);
631 if( aFinalTokens
.hasElements() )
632 mpContext
->setTokens( aFinalTokens
);
635 void FormulaParserImpl::finalizeImport()
637 ApiTokenSequence
aTokens( static_cast< sal_Int32
>( maTokenIndexes
.size() ) );
638 if( aTokens
.hasElements() )
640 ApiToken
* pToken
= aTokens
.getArray();
641 for( SizeTypeVector::const_iterator aIt
= maTokenIndexes
.begin(), aEnd
= maTokenIndexes
.end(); aIt
!= aEnd
; ++aIt
, ++pToken
)
642 *pToken
= maTokenStorage
[ *aIt
];
644 finalizeImport( aTokens
);
647 void FormulaParserImpl::setSharedFormula( const BinAddress
& rBaseAddr
)
649 CellAddress aApiBaseAddr
;
650 if( getAddressConverter().convertToCellAddress( aApiBaseAddr
, rBaseAddr
, mpContext
->getBaseAddress().Sheet
, false ) )
651 mpContext
->setSharedFormula( aApiBaseAddr
);
654 // token array ----------------------------------------------------------------
656 bool FormulaParserImpl::resetSpaces()
658 maLeadingSpaces
.clear();
659 maOpeningSpaces
.clear();
660 maClosingSpaces
.clear();
664 void FormulaParserImpl::appendSpaces( WhiteSpaceVec
& orSpaces
, sal_Int32 nCount
, bool bLineFeed
)
666 OSL_ENSURE( nCount
>= 0, "FormulaParserImpl::appendSpaces - negative count" );
668 orSpaces
.push_back( WhiteSpace( nCount
, bLineFeed
) );
671 void FormulaParserImpl::appendLeadingSpaces( sal_Int32 nCount
, bool bLineFeed
)
673 appendSpaces( maLeadingSpaces
, nCount
, bLineFeed
);
676 void FormulaParserImpl::appendOpeningSpaces( sal_Int32 nCount
, bool bLineFeed
)
678 appendSpaces( maOpeningSpaces
, nCount
, bLineFeed
);
681 void FormulaParserImpl::appendClosingSpaces( sal_Int32 nCount
, bool bLineFeed
)
683 appendSpaces( maClosingSpaces
, nCount
, bLineFeed
);
686 size_t FormulaParserImpl::getFormulaSize() const
688 return maTokenIndexes
.size();
691 Any
& FormulaParserImpl::appendRawToken( sal_Int32 nOpCode
)
693 maTokenIndexes
.push_back( maTokenStorage
.size() );
694 return maTokenStorage
.append( nOpCode
);
697 Any
& FormulaParserImpl::insertRawToken( sal_Int32 nOpCode
, size_t nIndexFromEnd
)
699 maTokenIndexes
.insert( maTokenIndexes
.end() - nIndexFromEnd
, maTokenStorage
.size() );
700 return maTokenStorage
.append( nOpCode
);
703 size_t FormulaParserImpl::appendWhiteSpaceTokens( const WhiteSpaceVec
* pSpaces
)
705 if( pSpaces
&& !pSpaces
->empty() )
706 for( WhiteSpaceVec::const_iterator aIt
= pSpaces
->begin(), aEnd
= pSpaces
->end(); aIt
!= aEnd
; ++aIt
)
707 appendRawToken( OPCODE_SPACES
) <<= aIt
->first
;
708 return pSpaces
? pSpaces
->size() : 0;
711 size_t FormulaParserImpl::insertWhiteSpaceTokens( const WhiteSpaceVec
* pSpaces
, size_t nIndexFromEnd
)
713 if( pSpaces
&& !pSpaces
->empty() )
714 for( WhiteSpaceVec::const_iterator aIt
= pSpaces
->begin(), aEnd
= pSpaces
->end(); aIt
!= aEnd
; ++aIt
)
715 insertRawToken( OPCODE_SPACES
, nIndexFromEnd
) <<= aIt
->first
;
716 return pSpaces
? pSpaces
->size() : 0;
719 size_t FormulaParserImpl::getOperandSize( size_t nOpCountFromEnd
, size_t nOpIndex
) const
721 OSL_ENSURE( (nOpIndex
< nOpCountFromEnd
) && (nOpCountFromEnd
<= maOperandSizeStack
.size()),
722 "FormulaParserImpl::getOperandSize - invalid parameters" );
723 return maOperandSizeStack
[ maOperandSizeStack
.size() - nOpCountFromEnd
+ nOpIndex
];
726 void FormulaParserImpl::pushOperandSize( size_t nSize
)
728 maOperandSizeStack
.push_back( nSize
);
731 size_t FormulaParserImpl::popOperandSize()
733 OSL_ENSURE( !maOperandSizeStack
.empty(), "FormulaParserImpl::popOperandSize - invalid call" );
734 size_t nOpSize
= maOperandSizeStack
.back();
735 maOperandSizeStack
.pop_back();
739 ApiToken
& FormulaParserImpl::getOperandToken( size_t nOpCountFromEnd
, size_t nOpIndex
, size_t nTokenIndex
)
741 OSL_ENSURE( getOperandSize( nOpCountFromEnd
, nOpIndex
) > nTokenIndex
,
742 "FormulaParserImpl::getOperandToken - invalid parameters" );
743 SizeTypeVector::const_iterator aIndexIt
= maTokenIndexes
.end();
744 for( SizeTypeVector::const_iterator aEnd
= maOperandSizeStack
.end(), aIt
= aEnd
- nOpCountFromEnd
+ nOpIndex
; aIt
!= aEnd
; ++aIt
)
746 return maTokenStorage
[ *(aIndexIt
+ nTokenIndex
) ];
749 void FormulaParserImpl::removeOperand( size_t nOpCountFromEnd
, size_t nOpIndex
)
751 OSL_ENSURE( (nOpIndex
< nOpCountFromEnd
) && (nOpCountFromEnd
<= maOperandSizeStack
.size()),
752 "FormulaParserImpl::removeOperand - invalid parameters" );
753 // remove indexes into token storage, but do not touch storage itself
754 SizeTypeVector::iterator aSizeEnd
= maOperandSizeStack
.end();
755 SizeTypeVector::iterator aSizeIt
= aSizeEnd
- nOpCountFromEnd
+ nOpIndex
;
756 size_t nRemainingSize
= 0;
757 for( SizeTypeVector::iterator aIt
= aSizeIt
+ 1; aIt
!= aSizeEnd
; ++aIt
)
758 nRemainingSize
+= *aIt
;
759 maTokenIndexes
.erase( maTokenIndexes
.end() - nRemainingSize
- *aSizeIt
, maTokenIndexes
.end() - nRemainingSize
);
760 maOperandSizeStack
.erase( aSizeIt
);
763 void FormulaParserImpl::removeLastOperands( size_t nOpCountFromEnd
)
765 for( size_t nOpIndex
= 0; nOpIndex
< nOpCountFromEnd
; ++nOpIndex
)
766 removeOperand( 1, 0 );
769 bool FormulaParserImpl::pushOperandToken( sal_Int32 nOpCode
, const WhiteSpaceVec
* pSpaces
)
771 size_t nSpacesSize
= appendWhiteSpaceTokens( pSpaces
);
772 appendRawToken( nOpCode
);
773 pushOperandSize( nSpacesSize
+ 1 );
777 bool FormulaParserImpl::pushAnyOperandToken( const Any
& rAny
, sal_Int32 nOpCode
, const WhiteSpaceVec
* pSpaces
)
779 size_t nSpacesSize
= appendWhiteSpaceTokens( pSpaces
);
780 appendRawToken( nOpCode
) = rAny
;
781 pushOperandSize( nSpacesSize
+ 1 );
785 template< typename Type
>
786 bool FormulaParserImpl::pushValueOperandToken( const Type
& rValue
, sal_Int32 nOpCode
, const WhiteSpaceVec
* pSpaces
)
788 size_t nSpacesSize
= appendWhiteSpaceTokens( pSpaces
);
789 appendRawToken( nOpCode
) <<= rValue
;
790 pushOperandSize( nSpacesSize
+ 1 );
794 bool FormulaParserImpl::pushParenthesesOperandToken( const WhiteSpaceVec
* pOpeningSpaces
, const WhiteSpaceVec
* pClosingSpaces
)
796 size_t nSpacesSize
= appendWhiteSpaceTokens( pOpeningSpaces
);
797 appendRawToken( OPCODE_OPEN
);
798 nSpacesSize
+= appendWhiteSpaceTokens( pClosingSpaces
);
799 appendRawToken( OPCODE_CLOSE
);
800 pushOperandSize( nSpacesSize
+ 2 );
804 bool FormulaParserImpl::pushUnaryPreOperatorToken( sal_Int32 nOpCode
, const WhiteSpaceVec
* pSpaces
)
806 bool bOk
= maOperandSizeStack
.size() >= 1;
809 size_t nOpSize
= popOperandSize();
810 size_t nSpacesSize
= insertWhiteSpaceTokens( pSpaces
, nOpSize
);
811 insertRawToken( nOpCode
, nOpSize
);
812 pushOperandSize( nOpSize
+ nSpacesSize
+ 1 );
817 bool FormulaParserImpl::pushUnaryPostOperatorToken( sal_Int32 nOpCode
, const WhiteSpaceVec
* pSpaces
)
819 bool bOk
= maOperandSizeStack
.size() >= 1;
822 size_t nOpSize
= popOperandSize();
823 size_t nSpacesSize
= appendWhiteSpaceTokens( pSpaces
);
824 appendRawToken( nOpCode
);
825 pushOperandSize( nOpSize
+ nSpacesSize
+ 1 );
830 bool FormulaParserImpl::pushBinaryOperatorToken( sal_Int32 nOpCode
, const WhiteSpaceVec
* pSpaces
)
832 bool bOk
= maOperandSizeStack
.size() >= 2;
835 size_t nOp2Size
= popOperandSize();
836 size_t nOp1Size
= popOperandSize();
837 size_t nSpacesSize
= insertWhiteSpaceTokens( pSpaces
, nOp2Size
);
838 insertRawToken( nOpCode
, nOp2Size
);
839 pushOperandSize( nOp1Size
+ nSpacesSize
+ 1 + nOp2Size
);
844 bool FormulaParserImpl::pushParenthesesOperatorToken( const WhiteSpaceVec
* pOpeningSpaces
, const WhiteSpaceVec
* pClosingSpaces
)
846 bool bOk
= maOperandSizeStack
.size() >= 1;
849 size_t nOpSize
= popOperandSize();
850 size_t nSpacesSize
= insertWhiteSpaceTokens( pOpeningSpaces
, nOpSize
);
851 insertRawToken( OPCODE_OPEN
, nOpSize
);
852 nSpacesSize
+= appendWhiteSpaceTokens( pClosingSpaces
);
853 appendRawToken( OPCODE_CLOSE
);
854 pushOperandSize( nOpSize
+ nSpacesSize
+ 2 );
859 bool FormulaParserImpl::pushFunctionOperatorToken( sal_Int32 nOpCode
, size_t nParamCount
, const WhiteSpaceVec
* pLeadingSpaces
, const WhiteSpaceVec
* pClosingSpaces
)
861 /* #i70925# if there are not enough tokens available on token stack, do
862 not exit with error, but reduce parameter count. */
863 nParamCount
= ::std::min( maOperandSizeStack
.size(), nParamCount
);
865 // convert all parameters on stack to a single operand separated with OPCODE_SEP
867 for( size_t nParam
= 1; bOk
&& (nParam
< nParamCount
); ++nParam
)
868 bOk
= pushBinaryOperatorToken( OPCODE_SEP
);
870 // add function parentheses and function name
872 ((nParamCount
> 0) ? pushParenthesesOperatorToken( 0, pClosingSpaces
) : pushParenthesesOperandToken( 0, pClosingSpaces
)) &&
873 pushUnaryPreOperatorToken( nOpCode
, pLeadingSpaces
);
876 bool FormulaParserImpl::pushFunctionOperatorToken( const FunctionInfo
& rFuncInfo
, size_t nParamCount
, const WhiteSpaceVec
* pLeadingSpaces
, const WhiteSpaceVec
* pClosingSpaces
)
878 bool bOk
= pushFunctionOperatorToken( rFuncInfo
.mnApiOpCode
, nParamCount
, pLeadingSpaces
, pClosingSpaces
);
881 // create an external add-in call for the passed built-in function
882 if( (rFuncInfo
.mnApiOpCode
== OPCODE_EXTERNAL
) && (rFuncInfo
.maExtProgName
.getLength() > 0) )
883 getOperandToken( 1, 0, 0 ).Data
<<= rFuncInfo
.maExtProgName
;
884 // create a bad token with unsupported function name
885 else if( (rFuncInfo
.mnApiOpCode
== OPCODE_BAD
) && (rFuncInfo
.maOoxFuncName
.getLength() > 0) )
886 getOperandToken( 1, 0, 0 ).Data
<<= rFuncInfo
.maOoxFuncName
;
891 bool FormulaParserImpl::pushOperand( sal_Int32 nOpCode
)
893 return pushOperandToken( nOpCode
, &maLeadingSpaces
) && resetSpaces();
896 bool FormulaParserImpl::pushAnyOperand( const Any
& rAny
, sal_Int32 nOpCode
)
898 return pushAnyOperandToken( rAny
, nOpCode
, &maLeadingSpaces
) && resetSpaces();
901 template< typename Type
>
902 bool FormulaParserImpl::pushValueOperand( const Type
& rValue
, sal_Int32 nOpCode
)
904 return pushValueOperandToken( rValue
, nOpCode
, &maLeadingSpaces
) && resetSpaces();
907 bool FormulaParserImpl::pushBoolOperand( bool bValue
)
909 if( const FunctionInfo
* pFuncInfo
= getFuncInfoFromOobFuncId( bValue
? OOBIN_FUNC_TRUE
: OOBIN_FUNC_FALSE
) )
910 return pushFunctionOperator( pFuncInfo
->mnApiOpCode
, 0 );
911 return pushValueOperand
< double >( bValue
? 1.0 : 0.0 );
914 bool FormulaParserImpl::pushErrorOperand( double fEncodedError
)
916 // HACK: enclose all error codes into an 1x1 matrix
917 // start token array with opening brace and leading spaces
918 pushOperand( OPCODE_ARRAY_OPEN
);
919 size_t nOpSize
= popOperandSize();
920 size_t nOldArraySize
= maTokenIndexes
.size();
921 // push a double containing the Calc error code
922 appendRawToken( OPCODE_PUSH
) <<= fEncodedError
;
923 // close token array and set resulting operand size
924 appendRawToken( OPCODE_ARRAY_CLOSE
);
925 pushOperandSize( nOpSize
+ maTokenIndexes
.size() - nOldArraySize
);
929 bool FormulaParserImpl::pushBiffBoolOperand( sal_uInt8 nValue
)
931 return pushBoolOperand( nValue
!= BIFF_TOK_BOOL_FALSE
);
934 bool FormulaParserImpl::pushBiffErrorOperand( sal_uInt8 nErrorCode
)
936 return pushErrorOperand( BiffHelper::calcDoubleFromError( nErrorCode
) );
939 bool FormulaParserImpl::pushParenthesesOperand()
941 return pushParenthesesOperandToken( &maOpeningSpaces
, &maClosingSpaces
) && resetSpaces();
944 bool FormulaParserImpl::pushReferenceOperand( const BinSingleRef2d
& rRef
, bool bDeleted
, bool bRelativeAsOffset
)
946 SingleReference aApiRef
;
947 convertReference2d( aApiRef
, rRef
, bDeleted
, bRelativeAsOffset
);
948 return pushValueOperand( aApiRef
);
951 bool FormulaParserImpl::pushReferenceOperand( const BinComplexRef2d
& rRef
, bool bDeleted
, bool bRelativeAsOffset
)
953 ComplexReference aApiRef
;
954 convertReference2d( aApiRef
, rRef
.maRef1
, rRef
.maRef2
, bDeleted
, bRelativeAsOffset
);
955 return pushValueOperand( aApiRef
);
958 template< typename Type
>
959 bool FormulaParserImpl::pushReferenceOperand( const LinkSheetRange
& rSheetRange
, const Type
& rApiRef
)
961 if( rSheetRange
.isExternal() )
963 ExternalReference aApiExtRef
;
964 aApiExtRef
.Index
= rSheetRange
.getDocLinkIndex();
965 aApiExtRef
.Reference
<<= rApiRef
;
966 return pushValueOperand( aApiExtRef
);
968 return pushValueOperand( rApiRef
);
971 bool FormulaParserImpl::pushReferenceOperand( const LinkSheetRange
& rSheetRange
, const BinSingleRef2d
& rRef
, bool bDeleted
, bool bRelativeAsOffset
)
973 if( rSheetRange
.is3dRange() )
975 // single-cell-range over several sheets, needs to create a ComplexReference
976 ComplexReference aApiRef
;
977 convertReference3d( aApiRef
, rSheetRange
, rRef
, rRef
, bDeleted
, bRelativeAsOffset
);
978 return pushReferenceOperand( rSheetRange
, aApiRef
);
980 SingleReference aApiRef
;
981 convertReference3d( aApiRef
, rSheetRange
.getFirstSheet(), rSheetRange
.isSameSheet(), rRef
, bDeleted
, bRelativeAsOffset
);
982 return pushReferenceOperand( rSheetRange
, aApiRef
);
985 bool FormulaParserImpl::pushReferenceOperand( const LinkSheetRange
& rSheetRange
, const BinComplexRef2d
& rRef
, bool bDeleted
, bool bRelativeAsOffset
)
987 ComplexReference aApiRef
;
988 convertReference3d( aApiRef
, rSheetRange
, rRef
.maRef1
, rRef
.maRef2
, bDeleted
, bRelativeAsOffset
);
989 return pushReferenceOperand( rSheetRange
, aApiRef
);
992 bool FormulaParserImpl::pushNlrOperand( const BinSingleRef2d
& rRef
)
994 SingleReference aApiRef
;
995 convertReference2d( aApiRef
, rRef
, false, false );
996 return pushValueOperand( aApiRef
, OPCODE_NLR
);
999 bool FormulaParserImpl::pushEmbeddedRefOperand( const DefinedNameBase
& rName
, bool bPushBadToken
)
1001 Any aRefAny
= rName
.getReference( mpContext
->getBaseAddress() );
1002 if( aRefAny
.hasValue() )
1003 return pushAnyOperand( aRefAny
, OPCODE_PUSH
);
1004 if( bPushBadToken
&& (rName
.getModelName().getLength() > 0) && (rName
.getModelName()[ 0 ] >= ' ') )
1005 return pushValueOperand( rName
.getModelName(), OPCODE_BAD
);
1006 return pushBiffErrorOperand( BIFF_ERR_NAME
);
1009 bool FormulaParserImpl::pushDefinedNameOperand( const DefinedNameRef
& rxDefName
)
1011 if( !rxDefName
|| (rxDefName
->getModelName().getLength() == 0) )
1012 return pushBiffErrorOperand( BIFF_ERR_NAME
);
1013 if( rxDefName
->isMacroFunction() )
1014 return pushValueOperand( rxDefName
->getModelName(), OPCODE_MACRO
);
1015 if( rxDefName
->getTokenIndex() >= 0 )
1016 return pushValueOperand( rxDefName
->getTokenIndex(), OPCODE_NAME
);
1017 return pushEmbeddedRefOperand( *rxDefName
, true );
1020 bool FormulaParserImpl::pushExternalFuncOperand( const FunctionInfo
& rFuncInfo
)
1022 return (rFuncInfo
.mnApiOpCode
== OPCODE_EXTERNAL
) ?
1023 pushValueOperand( rFuncInfo
.maExtProgName
, OPCODE_EXTERNAL
) :
1024 pushOperand( rFuncInfo
.mnApiOpCode
);
1027 bool FormulaParserImpl::pushDdeLinkOperand( const OUString
& rDdeServer
, const OUString
& rDdeTopic
, const OUString
& rDdeItem
)
1029 // create the function call DDE("server";"topic";"item")
1031 pushValueOperandToken( rDdeServer
) &&
1032 pushValueOperandToken( rDdeTopic
) &&
1033 pushValueOperandToken( rDdeItem
) &&
1034 pushFunctionOperator( OPCODE_DDE
, 3 );
1037 bool FormulaParserImpl::pushExternalNameOperand( const ExternalNameRef
& rxExtName
, const ExternalLink
& rExtLink
)
1039 if( rxExtName
.get() ) switch( rExtLink
.getLinkType() )
1041 case LINKTYPE_INTERNAL
:
1042 case LINKTYPE_EXTERNAL
:
1043 return pushEmbeddedRefOperand( *rxExtName
, false );
1045 case LINKTYPE_ANALYSIS
:
1046 // TODO: need support for localized addin function names
1047 if( const FunctionInfo
* pFuncInfo
= getFuncInfoFromOoxFuncName( rxExtName
->getUpcaseModelName() ) )
1048 return pushExternalFuncOperand( *pFuncInfo
);
1051 case LINKTYPE_LIBRARY
:
1052 if( const FunctionInfo
* pFuncInfo
= getFuncInfoFromOoxFuncName( rxExtName
->getUpcaseModelName() ) )
1053 if( (pFuncInfo
->meFuncLibType
!= FUNCLIB_UNKNOWN
) && (pFuncInfo
->meFuncLibType
== rExtLink
.getFuncLibraryType()) )
1054 return pushExternalFuncOperand( *pFuncInfo
);
1059 OUString aDdeServer
, aDdeTopic
, aDdeItem
;
1060 if( rxExtName
->getDdeLinkData( aDdeServer
, aDdeTopic
, aDdeItem
) )
1061 return pushDdeLinkOperand( aDdeServer
, aDdeTopic
, aDdeItem
);
1066 OSL_ENSURE( rExtLink
.getLinkType() != LINKTYPE_SELF
, "FormulaParserImpl::pushExternalNameOperand - invalid call" );
1068 return pushBiffErrorOperand( BIFF_ERR_NAME
);
1071 bool FormulaParserImpl::pushUnaryPreOperator( sal_Int32 nOpCode
)
1073 return pushUnaryPreOperatorToken( nOpCode
, &maLeadingSpaces
) && resetSpaces();
1076 bool FormulaParserImpl::pushUnaryPostOperator( sal_Int32 nOpCode
)
1078 return pushUnaryPostOperatorToken( nOpCode
, &maLeadingSpaces
) && resetSpaces();
1081 bool FormulaParserImpl::pushBinaryOperator( sal_Int32 nOpCode
)
1083 return pushBinaryOperatorToken( nOpCode
, &maLeadingSpaces
) && resetSpaces();
1086 bool FormulaParserImpl::pushParenthesesOperator()
1088 return pushParenthesesOperatorToken( &maOpeningSpaces
, &maClosingSpaces
) && resetSpaces();
1091 bool FormulaParserImpl::pushFunctionOperator( sal_Int32 nOpCode
, size_t nParamCount
)
1093 return pushFunctionOperatorToken( nOpCode
, nParamCount
, &maLeadingSpaces
, &maClosingSpaces
) && resetSpaces();
1096 bool FormulaParserImpl::pushFunctionOperator( const FunctionInfo
& rFuncInfo
, size_t nParamCount
)
1098 return pushFunctionOperatorToken( rFuncInfo
, nParamCount
, &maLeadingSpaces
, &maClosingSpaces
) && resetSpaces();
1101 // reference conversion -------------------------------------------------------
1103 void FormulaParserImpl::initReference2d( SingleReference
& orApiRef
) const
1105 if( mpContext
->is2dRefsAs3dRefs() )
1107 initReference3d( orApiRef
, mpContext
->getBaseAddress().Sheet
, false );
1111 orApiRef
.Flags
= SHEET_RELATIVE
;
1112 // #i10184# absolute sheet index needed for relative references in shared formulas
1113 orApiRef
.Sheet
= mpContext
->getBaseAddress().Sheet
;
1114 orApiRef
.RelativeSheet
= 0;
1118 void FormulaParserImpl::initReference3d( SingleReference
& orApiRef
, sal_Int32 nSheet
, bool bSameSheet
) const
1120 orApiRef
.Flags
= SHEET_3D
;
1124 orApiRef
.Flags
|= SHEET_DELETED
;
1126 else if( bSameSheet
)
1128 OSL_ENSURE( nSheet
== 0, "FormulaParserImpl::initReference3d - invalid sheet index" );
1129 orApiRef
.Flags
|= SHEET_RELATIVE
;
1130 orApiRef
.RelativeSheet
= 0;
1134 orApiRef
.Sheet
= nSheet
;
1138 void FormulaParserImpl::convertReference( SingleReference
& orApiRef
, const BinSingleRef2d
& rRef
, bool bDeleted
, bool bRelativeAsOffset
) const
1142 orApiRef
.Column
= 0;
1144 // no explicit information about whether row or column is deleted
1145 orApiRef
.Flags
|= COLUMN_DELETED
| ROW_DELETED
;
1149 // column/row indexes and flags
1150 setFlag( orApiRef
.Flags
, COLUMN_RELATIVE
, rRef
.mbColRel
);
1151 setFlag( orApiRef
.Flags
, ROW_RELATIVE
, rRef
.mbRowRel
);
1152 (rRef
.mbColRel
? orApiRef
.RelativeColumn
: orApiRef
.Column
) = rRef
.mnCol
;
1153 (rRef
.mbRowRel
? orApiRef
.RelativeRow
: orApiRef
.Row
) = rRef
.mnRow
;
1154 // convert absolute indexes to relative offsets used in API
1155 if( !bRelativeAsOffset
)
1158 orApiRef
.RelativeColumn
-= mpContext
->getBaseAddress().Column
;
1160 orApiRef
.RelativeRow
-= mpContext
->getBaseAddress().Row
;
1165 void FormulaParserImpl::convertReference( ComplexReference
& orApiRef
, const BinSingleRef2d
& rRef1
, const BinSingleRef2d
& rRef2
, bool bDeleted
, bool bRelativeAsOffset
) const
1167 convertReference( orApiRef
.Reference1
, rRef1
, bDeleted
, bRelativeAsOffset
);
1168 convertReference( orApiRef
.Reference2
, rRef2
, bDeleted
, bRelativeAsOffset
);
1169 /* Handle references to complete rows or columns (e.g. $1:$2 or C:D),
1170 need to expand or shrink to limits of own document. */
1171 if( !bDeleted
&& !rRef1
.mbColRel
&& !rRef2
.mbColRel
&& (orApiRef
.Reference1
.Column
== 0) && (orApiRef
.Reference2
.Column
== mnMaxXlsCol
) )
1172 orApiRef
.Reference2
.Column
= mnMaxApiCol
;
1173 if( !bDeleted
&& !rRef1
.mbRowRel
&& !rRef2
.mbRowRel
&& (orApiRef
.Reference1
.Row
== 0) && (orApiRef
.Reference2
.Row
== mnMaxXlsRow
) )
1174 orApiRef
.Reference2
.Row
= mnMaxApiRow
;
1177 void FormulaParserImpl::convertReference2d( SingleReference
& orApiRef
, const BinSingleRef2d
& rRef
, bool bDeleted
, bool bRelativeAsOffset
) const
1179 initReference2d( orApiRef
);
1180 convertReference( orApiRef
, rRef
, bDeleted
, bRelativeAsOffset
);
1183 void FormulaParserImpl::convertReference2d( ComplexReference
& orApiRef
, const BinSingleRef2d
& rRef1
, const BinSingleRef2d
& rRef2
, bool bDeleted
, bool bRelativeAsOffset
) const
1185 initReference2d( orApiRef
.Reference1
);
1186 initReference2d( orApiRef
.Reference2
);
1187 convertReference( orApiRef
, rRef1
, rRef2
, bDeleted
, bRelativeAsOffset
);
1188 // remove sheet name from second part of reference
1189 setFlag( orApiRef
.Reference2
.Flags
, SHEET_3D
, false );
1192 void FormulaParserImpl::convertReference3d( SingleReference
& orApiRef
, sal_Int32 nSheet
, bool bSameSheet
, const BinSingleRef2d
& rRef
, bool bDeleted
, bool bRelativeAsOffset
) const
1194 initReference3d( orApiRef
, nSheet
, bSameSheet
);
1195 convertReference( orApiRef
, rRef
, bDeleted
, bRelativeAsOffset
);
1198 void FormulaParserImpl::convertReference3d( ComplexReference
& orApiRef
, const LinkSheetRange
& rSheetRange
, const BinSingleRef2d
& rRef1
, const BinSingleRef2d
& rRef2
, bool bDeleted
, bool bRelativeAsOffset
) const
1200 bool bSameSheet
= rSheetRange
.isSameSheet();
1201 initReference3d( orApiRef
.Reference1
, rSheetRange
.getFirstSheet(), bSameSheet
);
1202 initReference3d( orApiRef
.Reference2
, rSheetRange
.getLastSheet(), bSameSheet
);
1203 convertReference( orApiRef
, rRef1
, rRef2
, bDeleted
, bRelativeAsOffset
);
1204 // remove sheet name from second part of reference
1205 setFlag( orApiRef
.Reference2
.Flags
, SHEET_3D
, rSheetRange
.is3dRange() );
1208 // finalize token sequence ----------------------------------------------------
1210 const FunctionInfo
* FormulaParserImpl::resolveBadFuncName( const OUString
& rTokenData
) const
1212 /* Try to parse calls to library functions. The format of such a function
1213 call is "[n]!funcname", n>0 being the link identifier of the function
1214 library spreadsheet file. */
1215 sal_Int32 nBracketOpen
= rTokenData
.indexOf( '[' );
1216 sal_Int32 nBracketClose
= rTokenData
.indexOf( ']' );
1217 sal_Int32 nExclamation
= rTokenData
.indexOf( '!' );
1218 if( (0 == nBracketOpen
) && (nBracketOpen
+ 1 < nBracketClose
) && (nBracketClose
+ 1 == nExclamation
) && (nExclamation
+ 1 < rTokenData
.getLength()) )
1220 sal_Int32 nRefId
= rTokenData
.copy( nBracketOpen
+ 1, nBracketClose
- nBracketOpen
- 1 ).toInt32();
1221 const ExternalLink
* pExtLink
= getExternalLinks().getExternalLink( nRefId
).get();
1222 if( pExtLink
&& (pExtLink
->getLinkType() == LINKTYPE_LIBRARY
) )
1224 OUString aFuncName
= rTokenData
.copy( nExclamation
+ 1 ).toAsciiUpperCase();
1225 if( const FunctionInfo
* pFuncInfo
= getFuncInfoFromOoxFuncName( aFuncName
) )
1226 if( (pFuncInfo
->meFuncLibType
!= FUNCLIB_UNKNOWN
) && (pFuncInfo
->meFuncLibType
== pExtLink
->getFuncLibraryType()) )
1233 OUString
FormulaParserImpl::resolveDefinedName( sal_Int32 nTokenIndex
) const
1235 if( const DefinedName
* pDefName
= getDefinedNames().getByTokenIndex( nTokenIndex
).get() )
1236 return pDefName
->getCalcName();
1240 // OOX parser implementation ==================================================
1242 class OoxFormulaParserImpl
: public FormulaParserImpl
1245 explicit OoxFormulaParserImpl( const FormulaParser
& rParent
);
1247 virtual void importOoxFormula(
1248 FormulaContext
& rContext
,
1249 const OUString
& rFormulaString
);
1251 virtual void importOobFormula(
1252 FormulaContext
& rContext
,
1253 RecordInputStream
& rStrm
);
1256 // import token contents and create API formula token ---------------------
1258 bool importAttrToken( RecordInputStream
& rStrm
);
1259 bool importSpaceToken( RecordInputStream
& rStrm
);
1260 bool importTableToken( RecordInputStream
& rStrm
);
1261 bool importArrayToken( RecordInputStream
& rStrm
);
1262 bool importRefToken( RecordInputStream
& rStrm
, bool bDeleted
, bool bRelativeAsOffset
);
1263 bool importAreaToken( RecordInputStream
& rStrm
, bool bDeleted
, bool bRelativeAsOffset
);
1264 bool importRef3dToken( RecordInputStream
& rStrm
, bool bDeleted
, bool bRelativeAsOffset
);
1265 bool importArea3dToken( RecordInputStream
& rStrm
, bool bDeleted
, bool bRelativeAsOffset
);
1266 bool importMemAreaToken( RecordInputStream
& rStrm
, bool bAddData
);
1267 bool importMemFuncToken( RecordInputStream
& rStrm
);
1268 bool importNameToken( RecordInputStream
& rStrm
);
1269 bool importNameXToken( RecordInputStream
& rStrm
);
1270 bool importFuncToken( RecordInputStream
& rStrm
);
1271 bool importFuncVarToken( RecordInputStream
& rStrm
);
1272 bool importExpToken( RecordInputStream
& rStrm
);
1274 LinkSheetRange
readSheetRange( RecordInputStream
& rStrm
);
1276 void swapStreamPosition( RecordInputStream
& rStrm
);
1277 void skipMemAreaAddData( RecordInputStream
& rStrm
);
1279 // convert BIN token and push API operand or operator ---------------------
1281 bool pushOobName( sal_Int32 nNameId
);
1282 bool pushOobExtName( sal_Int32 nRefId
, sal_Int32 nNameId
);
1283 bool pushOobFunction( sal_uInt16 nFuncId
);
1284 bool pushOobFunction( sal_uInt16 nFuncId
, sal_uInt8 nParamCount
);
1287 ApiParserWrapper maApiParser
; /// Wrapper for the API formula parser object.
1288 sal_Int64 mnAddDataPos
; /// Current stream position for additional data (tExp, tArray, tMemArea).
1289 bool mbNeedExtRefs
; /// True = parser needs initialization of external reference info.
1292 // ----------------------------------------------------------------------------
1294 OoxFormulaParserImpl::OoxFormulaParserImpl( const FormulaParser
& rParent
) :
1295 FormulaParserImpl( rParent
),
1296 maApiParser( rParent
.getDocumentFactory(), rParent
),
1298 mbNeedExtRefs( true )
1302 void OoxFormulaParserImpl::importOoxFormula( FormulaContext
& rContext
, const OUString
& rFormulaString
)
1306 maApiParser
.getParserProperties().setProperty( PROP_ExternalLinks
, getExternalLinks().getLinkInfos() );
1307 mbNeedExtRefs
= false;
1309 initializeImport( rContext
);
1310 finalizeImport( maApiParser
.parseFormula( rFormulaString
, rContext
.getBaseAddress() ) );
1313 void OoxFormulaParserImpl::importOobFormula( FormulaContext
& rContext
, RecordInputStream
& rStrm
)
1315 initializeImport( rContext
);
1317 sal_Int32 nFmlaSize
= rStrm
.readInt32();
1318 sal_Int64 nFmlaPos
= rStrm
.tell();
1319 sal_Int64 nFmlaEndPos
= nFmlaPos
+ nFmlaSize
;
1321 rStrm
.seek( nFmlaEndPos
);
1322 sal_Int32 nAddDataSize
= rStrm
.readInt32();
1323 mnAddDataPos
= rStrm
.tell();
1324 sal_Int64 nAddDataEndPos
= mnAddDataPos
+ nAddDataSize
;
1325 rStrm
.seek( nFmlaPos
);
1327 bool bOk
= (nFmlaSize
>= 0) && (nAddDataSize
>= 0);
1328 bool bRelativeAsOffset
= getFormulaContext().isRelativeAsOffset();
1330 while( bOk
&& !rStrm
.isEof() && (rStrm
.tell() < nFmlaEndPos
) )
1334 sal_uInt8 nTokenClass
= nTokenId
& BIFF_TOKCLASS_MASK
;
1335 sal_uInt8 nBaseId
= nTokenId
& BIFF_TOKID_MASK
;
1337 if( nTokenClass
== BIFF_TOKCLASS_NONE
)
1342 case BIFF_TOKID_EXP
: bOk
= importExpToken( rStrm
); break;
1343 case BIFF_TOKID_ADD
: bOk
= pushBinaryOperator( OPCODE_ADD
); break;
1344 case BIFF_TOKID_SUB
: bOk
= pushBinaryOperator( OPCODE_SUB
); break;
1345 case BIFF_TOKID_MUL
: bOk
= pushBinaryOperator( OPCODE_MULT
); break;
1346 case BIFF_TOKID_DIV
: bOk
= pushBinaryOperator( OPCODE_DIV
); break;
1347 case BIFF_TOKID_POWER
: bOk
= pushBinaryOperator( OPCODE_POWER
); break;
1348 case BIFF_TOKID_CONCAT
: bOk
= pushBinaryOperator( OPCODE_CONCAT
); break;
1349 case BIFF_TOKID_LT
: bOk
= pushBinaryOperator( OPCODE_LESS
); break;
1350 case BIFF_TOKID_LE
: bOk
= pushBinaryOperator( OPCODE_LESS_EQUAL
); break;
1351 case BIFF_TOKID_EQ
: bOk
= pushBinaryOperator( OPCODE_EQUAL
); break;
1352 case BIFF_TOKID_GE
: bOk
= pushBinaryOperator( OPCODE_GREATER_EQUAL
); break;
1353 case BIFF_TOKID_GT
: bOk
= pushBinaryOperator( OPCODE_GREATER
); break;
1354 case BIFF_TOKID_NE
: bOk
= pushBinaryOperator( OPCODE_NOT_EQUAL
); break;
1355 case BIFF_TOKID_ISECT
: bOk
= pushBinaryOperator( OPCODE_INTERSECT
); break;
1356 case BIFF_TOKID_LIST
: bOk
= pushBinaryOperator( OPCODE_LIST
); break;
1357 case BIFF_TOKID_RANGE
: bOk
= pushBinaryOperator( OPCODE_RANGE
); break;
1358 case BIFF_TOKID_UPLUS
: bOk
= pushUnaryPreOperator( OPCODE_PLUS_SIGN
); break;
1359 case BIFF_TOKID_UMINUS
: bOk
= pushUnaryPreOperator( OPCODE_MINUS_SIGN
); break;
1360 case BIFF_TOKID_PERCENT
: bOk
= pushUnaryPostOperator( OPCODE_PERCENT
); break;
1361 case BIFF_TOKID_PAREN
: bOk
= pushParenthesesOperator(); break;
1362 case BIFF_TOKID_MISSARG
: bOk
= pushOperand( OPCODE_MISSING
); break;
1363 case BIFF_TOKID_STR
: bOk
= pushValueOperand( rStrm
.readString( false ) ); break;
1364 case BIFF_TOKID_NLR
: bOk
= importTableToken( rStrm
); break;
1365 case BIFF_TOKID_ATTR
: bOk
= importAttrToken( rStrm
); break;
1366 case BIFF_TOKID_ERR
: bOk
= pushBiffErrorOperand( rStrm
.readuInt8() ); break;
1367 case BIFF_TOKID_BOOL
: bOk
= pushBiffBoolOperand( rStrm
.readuInt8() ); break;
1368 case BIFF_TOKID_INT
: bOk
= pushValueOperand
< double >( rStrm
.readuInt16() ); break;
1369 case BIFF_TOKID_NUM
: bOk
= pushValueOperand( rStrm
.readDouble() ); break;
1370 default: bOk
= false;
1375 // classified tokens
1378 case BIFF_TOKID_ARRAY
: bOk
= importArrayToken( rStrm
); break;
1379 case BIFF_TOKID_FUNC
: bOk
= importFuncToken( rStrm
); break;
1380 case BIFF_TOKID_FUNCVAR
: bOk
= importFuncVarToken( rStrm
); break;
1381 case BIFF_TOKID_NAME
: bOk
= importNameToken( rStrm
); break;
1382 case BIFF_TOKID_REF
: bOk
= importRefToken( rStrm
, false, false ); break;
1383 case BIFF_TOKID_AREA
: bOk
= importAreaToken( rStrm
, false, false ); break;
1384 case BIFF_TOKID_MEMAREA
: bOk
= importMemAreaToken( rStrm
, true ); break;
1385 case BIFF_TOKID_MEMERR
: bOk
= importMemAreaToken( rStrm
, false ); break;
1386 case BIFF_TOKID_MEMNOMEM
: bOk
= importMemAreaToken( rStrm
, false ); break;
1387 case BIFF_TOKID_MEMFUNC
: bOk
= importMemFuncToken( rStrm
); break;
1388 case BIFF_TOKID_REFERR
: bOk
= importRefToken( rStrm
, true, false ); break;
1389 case BIFF_TOKID_AREAERR
: bOk
= importAreaToken( rStrm
, true, false ); break;
1390 case BIFF_TOKID_REFN
: bOk
= importRefToken( rStrm
, false, true ); break;
1391 case BIFF_TOKID_AREAN
: bOk
= importAreaToken( rStrm
, false, true ); break;
1392 case BIFF_TOKID_MEMAREAN
: bOk
= importMemFuncToken( rStrm
); break;
1393 case BIFF_TOKID_MEMNOMEMN
: bOk
= importMemFuncToken( rStrm
); break;
1394 case BIFF_TOKID_NAMEX
: bOk
= importNameXToken( rStrm
); break;
1395 case BIFF_TOKID_REF3D
: bOk
= importRef3dToken( rStrm
, false, bRelativeAsOffset
); break;
1396 case BIFF_TOKID_AREA3D
: bOk
= importArea3dToken( rStrm
, false, bRelativeAsOffset
); break;
1397 case BIFF_TOKID_REFERR3D
: bOk
= importRef3dToken( rStrm
, true, bRelativeAsOffset
); break;
1398 case BIFF_TOKID_AREAERR3D
: bOk
= importArea3dToken( rStrm
, true, bRelativeAsOffset
); break;
1399 default: bOk
= false;
1404 // build and finalize the token sequence
1405 if( bOk
&& (rStrm
.tell() == nFmlaEndPos
) && (mnAddDataPos
== nAddDataEndPos
) )
1408 // seek behind token array
1409 if( (nFmlaSize
>= 0) && (nAddDataSize
>= 0) )
1410 rStrm
.seek( nAddDataEndPos
);
1413 // import token contents and create API formula token -------------------------
1415 bool OoxFormulaParserImpl::importAttrToken( RecordInputStream
& rStrm
)
1420 // equal flags in BIFF and OOBIN
1423 case 0: // sometimes, tAttrSkip tokens miss the type flag
1424 case OOBIN_TOK_ATTR_VOLATILE
:
1425 case OOBIN_TOK_ATTR_IF
:
1426 case OOBIN_TOK_ATTR_SKIP
:
1427 case OOBIN_TOK_ATTR_ASSIGN
:
1428 case OOBIN_TOK_ATTR_IFERROR
:
1431 case OOBIN_TOK_ATTR_CHOOSE
:
1432 rStrm
.skip( 2 * rStrm
.readuInt16() + 2 );
1434 case OOBIN_TOK_ATTR_SUM
:
1436 bOk
= pushOobFunction( OOBIN_FUNC_SUM
, 1 );
1438 case OOBIN_TOK_ATTR_SPACE
:
1439 case OOBIN_TOK_ATTR_SPACE_VOLATILE
:
1440 bOk
= importSpaceToken( rStrm
);
1448 bool OoxFormulaParserImpl::importSpaceToken( RecordInputStream
& rStrm
)
1450 // equal constants in BIFF and OOX
1451 sal_uInt8 nType
, nCount
;
1452 rStrm
>> nType
>> nCount
;
1455 case BIFF_TOK_ATTR_SPACE_SP
:
1456 appendLeadingSpaces( nCount
, false );
1458 case BIFF_TOK_ATTR_SPACE_BR
:
1459 appendLeadingSpaces( nCount
, true );
1461 case BIFF_TOK_ATTR_SPACE_SP_OPEN
:
1462 appendOpeningSpaces( nCount
, false );
1464 case BIFF_TOK_ATTR_SPACE_BR_OPEN
:
1465 appendOpeningSpaces( nCount
, true );
1467 case BIFF_TOK_ATTR_SPACE_SP_CLOSE
:
1468 appendClosingSpaces( nCount
, false );
1470 case BIFF_TOK_ATTR_SPACE_BR_CLOSE
:
1471 appendClosingSpaces( nCount
, true );
1477 bool OoxFormulaParserImpl::importTableToken( RecordInputStream
& rStrm
)
1479 sal_uInt16 nFlags
, nTableId
, nCol1
, nCol2
;
1481 rStrm
>> nFlags
>> nTableId
;
1483 rStrm
>> nCol1
>> nCol2
;
1484 TableRef xTable
= getTables().getTable( nTableId
);
1485 sal_Int32 nTokenIndex
= xTable
.get() ? xTable
->getTokenIndex() : -1;
1486 if( nTokenIndex
>= 0 )
1488 sal_Int32 nWidth
= xTable
->getWidth();
1489 sal_Int32 nHeight
= xTable
->getHeight();
1490 sal_Int32 nStartCol
= 0;
1491 sal_Int32 nEndCol
= nWidth
- 1;
1492 sal_Int32 nStartRow
= 0;
1493 sal_Int32 nEndRow
= nHeight
- 1;
1494 bool bFixedStartRow
= true;
1495 bool bFixedHeight
= false;
1497 bool bSingleCol
= getFlag( nFlags
, OOBIN_TOK_TABLE_COLUMN
);
1498 bool bColRange
= getFlag( nFlags
, OOBIN_TOK_TABLE_COLRANGE
);
1499 bool bValidRef
= !bSingleCol
|| !bColRange
;
1500 OSL_ENSURE( bValidRef
, "OoxFormulaParserImpl::importTableToken - illegal combination of single column and column range" );
1504 nStartCol
= nEndCol
= nCol1
;
1505 else if( bColRange
)
1506 { nStartCol
= nCol1
; nEndCol
= nCol2
; }
1507 bValidRef
= (nStartCol
<= nEndCol
) && (nEndCol
< nWidth
);
1508 OSL_ENSURE( bValidRef
, "OoxFormulaParserImpl::importTableToken - invalid column range" );
1513 bool bAllRows
= getFlag( nFlags
, OOBIN_TOK_TABLE_ALL
);
1514 bool bHeaderRows
= getFlag( nFlags
, OOBIN_TOK_TABLE_HEADERS
);
1515 bool bDataRows
= getFlag( nFlags
, OOBIN_TOK_TABLE_DATA
);
1516 bool bTotalsRows
= getFlag( nFlags
, OOBIN_TOK_TABLE_TOTALS
);
1517 bool bThisRow
= getFlag( nFlags
, OOBIN_TOK_TABLE_THISROW
);
1519 sal_Int32 nStartDataRow
= xTable
->getHeaderRows();
1520 sal_Int32 nEndDataRow
= nEndRow
- xTable
->getTotalsRows();
1521 bValidRef
= (nStartRow
<= nStartDataRow
) && (nStartDataRow
<= nEndDataRow
) && (nEndDataRow
<= nEndRow
);
1522 OSL_ENSURE( bValidRef
, "OoxFormulaParserImpl::importTableToken - invalid data row range" );
1527 bValidRef
= !bHeaderRows
&& !bDataRows
&& !bTotalsRows
&& !bThisRow
;
1528 OSL_ENSURE( bValidRef
, "OoxFormulaParserImpl::importTableToken - unexpected flags in [#All] table token" );
1530 else if( bHeaderRows
)
1532 bValidRef
= !bTotalsRows
&& !bThisRow
;
1533 OSL_ENSURE( bValidRef
, "OoxFormulaParserImpl::importTableToken - unexpected flags in [#Headers] table token" );
1534 nEndRow
= bDataRows
? nEndDataRow
: (nStartDataRow
- 1);
1535 bFixedHeight
= !bDataRows
;
1537 else if( bDataRows
)
1539 bValidRef
= !bThisRow
;
1540 OSL_ENSURE( bValidRef
, "OoxFormulaParserImpl::importTableToken - unexpected flags in [#Data] table token" );
1541 nStartRow
= nStartDataRow
;
1542 if( !bTotalsRows
) nEndRow
= nEndDataRow
;
1544 else if( bTotalsRows
)
1546 bValidRef
= !bThisRow
;
1547 OSL_ENSURE( bValidRef
, "OoxFormulaParserImpl::importTableToken - unexpected flags in [#Totals] table token" );
1548 nStartRow
= nEndDataRow
+ 1;
1549 bFixedStartRow
= false;
1550 bFixedHeight
= !bDataRows
;
1554 nStartRow
= nEndRow
= getFormulaContext().getBaseAddress().Row
- xTable
->getRange().StartRow
;
1555 bFixedHeight
= true;
1559 // nothing is the same as [#Data]
1560 nStartRow
= nStartDataRow
;
1561 nEndRow
= nEndDataRow
;
1565 bValidRef
= (0 <= nStartRow
) && (nStartRow
<= nEndRow
) && (nEndRow
< nHeight
);
1569 // push single database area token, if table token refers to entire table
1570 if( (nStartCol
== 0) && (nEndCol
+ 1 == nWidth
) && (nStartRow
== 0) && (nEndRow
+ 1 == nHeight
) )
1571 return pushValueOperand( nTokenIndex
, OPCODE_DBAREA
);
1572 // create an OFFSET function call to refer to a subrange of the table
1573 const FunctionInfo
* pRowsInfo
= getFuncInfoFromOobFuncId( OOBIN_FUNC_ROWS
);
1574 const FunctionInfo
* pColumnsInfo
= getFuncInfoFromOobFuncId( OOBIN_FUNC_COLUMNS
);
1576 pRowsInfo
&& pColumnsInfo
&&
1577 pushValueOperandToken( nTokenIndex
, OPCODE_DBAREA
) &&
1579 pushValueOperandToken
< double >( nStartRow
) :
1580 (pushValueOperandToken( nTokenIndex
, OPCODE_DBAREA
) &&
1581 pushFunctionOperatorToken( *pRowsInfo
, 1 ) &&
1582 pushValueOperandToken
< double >( nHeight
- nStartRow
) &&
1583 pushBinaryOperatorToken( OPCODE_SUB
))) &&
1584 pushValueOperandToken
< double >( nStartCol
) &&
1586 pushValueOperandToken
< double >( nEndRow
- nStartRow
+ 1 ) :
1587 (pushValueOperandToken( nTokenIndex
, OPCODE_DBAREA
) &&
1588 pushFunctionOperatorToken( *pRowsInfo
, 1 ) &&
1589 (((nStartRow
== 0) && (nEndRow
+ 1 == nHeight
)) ||
1590 (pushValueOperandToken
< double >( nHeight
- (nEndRow
- nStartRow
+ 1) ) &&
1591 pushBinaryOperatorToken( OPCODE_SUB
))))) &&
1592 (((nStartCol
== 0) && (nEndCol
+ 1 == nWidth
)) ?
1593 (pushValueOperandToken( nTokenIndex
, OPCODE_DBAREA
) &&
1594 pushFunctionOperatorToken( *pColumnsInfo
, 1 )) :
1595 pushValueOperandToken
< double >( nEndCol
- nStartCol
+ 1 )) &&
1596 pushOobFunction( OOBIN_FUNC_OFFSET
, 5 );
1599 return pushBiffErrorOperand( BIFF_ERR_REF
);
1602 bool OoxFormulaParserImpl::importArrayToken( RecordInputStream
& rStrm
)
1606 // start token array with opening brace and leading spaces
1607 pushOperand( OPCODE_ARRAY_OPEN
);
1608 size_t nOpSize
= popOperandSize();
1609 size_t nOldArraySize
= getFormulaSize();
1612 swapStreamPosition( rStrm
);
1613 sal_Int32 nRows
= rStrm
.readInt32();
1614 sal_Int32 nCols
= rStrm
.readInt32();
1615 OSL_ENSURE( (nCols
> 0) && (nRows
> 0), "OoxFormulaParserImpl::importArrayToken - empty array" );
1617 // read array values and build token array
1618 for( sal_Int32 nRow
= 0; !rStrm
.isEof() && (nRow
< nRows
); ++nRow
)
1621 appendRawToken( OPCODE_ARRAY_ROWSEP
);
1622 for( sal_Int32 nCol
= 0; !rStrm
.isEof() && (nCol
< nCols
); ++nCol
)
1625 appendRawToken( OPCODE_ARRAY_COLSEP
);
1626 switch( rStrm
.readuInt8() )
1628 case OOBIN_TOK_ARRAY_DOUBLE
:
1629 appendRawToken( OPCODE_PUSH
) <<= rStrm
.readDouble();
1631 case OOBIN_TOK_ARRAY_STRING
:
1632 appendRawToken( OPCODE_PUSH
) <<= rStrm
.readString( false );
1634 case OOBIN_TOK_ARRAY_BOOL
:
1635 appendRawToken( OPCODE_PUSH
) <<= static_cast< double >( (rStrm
.readuInt8() == BIFF_TOK_BOOL_FALSE
) ? 0.0 : 1.0 );
1637 case OOBIN_TOK_ARRAY_ERROR
:
1638 appendRawToken( OPCODE_PUSH
) <<= BiffHelper::calcDoubleFromError( rStrm
.readuInt8() );
1642 OSL_ENSURE( false, "OoxFormulaParserImpl::importArrayToken - unknown data type" );
1643 appendRawToken( OPCODE_PUSH
) <<= BiffHelper::calcDoubleFromError( BIFF_ERR_NA
);
1647 swapStreamPosition( rStrm
);
1649 // close token array and set resulting operand size
1650 appendRawToken( OPCODE_ARRAY_CLOSE
);
1651 pushOperandSize( nOpSize
+ getFormulaSize() - nOldArraySize
);
1655 bool OoxFormulaParserImpl::importRefToken( RecordInputStream
& rStrm
, bool bDeleted
, bool bRelativeAsOffset
)
1657 BinSingleRef2d aRef
;
1658 aRef
.readOobData( rStrm
, bRelativeAsOffset
);
1659 return pushReferenceOperand( aRef
, bDeleted
, bRelativeAsOffset
);
1662 bool OoxFormulaParserImpl::importAreaToken( RecordInputStream
& rStrm
, bool bDeleted
, bool bRelativeAsOffset
)
1664 BinComplexRef2d aRef
;
1665 aRef
.readOobData( rStrm
, bRelativeAsOffset
);
1666 return pushReferenceOperand( aRef
, bDeleted
, bRelativeAsOffset
);
1669 bool OoxFormulaParserImpl::importRef3dToken( RecordInputStream
& rStrm
, bool bDeleted
, bool bRelativeAsOffset
)
1671 LinkSheetRange aSheetRange
= readSheetRange( rStrm
);
1672 BinSingleRef2d aRef
;
1673 aRef
.readOobData( rStrm
, bRelativeAsOffset
);
1674 return pushReferenceOperand( aSheetRange
, aRef
, bDeleted
, bRelativeAsOffset
);
1677 bool OoxFormulaParserImpl::importArea3dToken( RecordInputStream
& rStrm
, bool bDeleted
, bool bRelativeAsOffset
)
1679 LinkSheetRange aSheetRange
= readSheetRange( rStrm
);
1680 BinComplexRef2d aRef
;
1681 aRef
.readOobData( rStrm
, bRelativeAsOffset
);
1682 return pushReferenceOperand( aSheetRange
, aRef
, bDeleted
, bRelativeAsOffset
);
1685 bool OoxFormulaParserImpl::importMemAreaToken( RecordInputStream
& rStrm
, bool bAddData
)
1689 skipMemAreaAddData( rStrm
);
1693 bool OoxFormulaParserImpl::importMemFuncToken( RecordInputStream
& rStrm
)
1699 bool OoxFormulaParserImpl::importNameToken( RecordInputStream
& rStrm
)
1701 return pushOobName( rStrm
.readInt32() );
1704 bool OoxFormulaParserImpl::importNameXToken( RecordInputStream
& rStrm
)
1706 sal_Int32 nRefId
= rStrm
.readInt16();
1707 sal_Int32 nNameId
= rStrm
.readInt32();
1708 return pushOobExtName( nRefId
, nNameId
);
1711 bool OoxFormulaParserImpl::importFuncToken( RecordInputStream
& rStrm
)
1715 return pushOobFunction( nFuncId
);
1718 bool OoxFormulaParserImpl::importFuncVarToken( RecordInputStream
& rStrm
)
1720 sal_uInt8 nParamCount
;
1722 rStrm
>> nParamCount
>> nFuncId
;
1723 return pushOobFunction( nFuncId
, nParamCount
);
1726 bool OoxFormulaParserImpl::importExpToken( RecordInputStream
& rStrm
)
1728 BinAddress aBaseAddr
;
1729 rStrm
>> aBaseAddr
.mnRow
;
1730 swapStreamPosition( rStrm
);
1731 rStrm
>> aBaseAddr
.mnCol
;
1732 swapStreamPosition( rStrm
);
1733 setSharedFormula( aBaseAddr
);
1734 // formula has been set, exit parser by returning false
1738 LinkSheetRange
OoxFormulaParserImpl::readSheetRange( RecordInputStream
& rStrm
)
1740 return getExternalLinks().getSheetRange( rStrm
.readInt16() );
1743 void OoxFormulaParserImpl::swapStreamPosition( RecordInputStream
& rStrm
)
1745 sal_Int64 nRecPos
= rStrm
.tell();
1746 rStrm
.seek( mnAddDataPos
);
1747 mnAddDataPos
= nRecPos
;
1750 void OoxFormulaParserImpl::skipMemAreaAddData( RecordInputStream
& rStrm
)
1752 swapStreamPosition( rStrm
);
1753 rStrm
.skip( 16 * rStrm
.readInt32() );
1754 swapStreamPosition( rStrm
);
1757 // convert BIN token and push API operand or operator -------------------------
1759 bool OoxFormulaParserImpl::pushOobName( sal_Int32 nNameId
)
1761 // one-based in OOBIN formulas
1762 return pushDefinedNameOperand( getDefinedNames().getByIndex( nNameId
- 1 ) );
1765 bool OoxFormulaParserImpl::pushOobExtName( sal_Int32 nRefId
, sal_Int32 nNameId
)
1767 if( const ExternalLink
* pExtLink
= getExternalLinks().getExternalLink( nRefId
).get() )
1769 if( pExtLink
->getLinkType() == LINKTYPE_SELF
)
1770 return pushOobName( nNameId
);
1771 // external name indexes are one-based in OOBIN
1772 ExternalNameRef xExtName
= pExtLink
->getNameByIndex( nNameId
- 1 );
1773 return pushExternalNameOperand( xExtName
, *pExtLink
);
1775 return pushBiffErrorOperand( BIFF_ERR_NAME
);
1778 bool OoxFormulaParserImpl::pushOobFunction( sal_uInt16 nFuncId
)
1780 if( const FunctionInfo
* pFuncInfo
= getFuncInfoFromOobFuncId( nFuncId
) )
1781 if( pFuncInfo
->mnMinParamCount
== pFuncInfo
->mnMaxParamCount
)
1782 return pushFunctionOperator( *pFuncInfo
, pFuncInfo
->mnMinParamCount
);
1783 return pushFunctionOperator( OPCODE_NONAME
, 0 );
1786 bool OoxFormulaParserImpl::pushOobFunction( sal_uInt16 nFuncId
, sal_uInt8 nParamCount
)
1788 if( getFlag( nFuncId
, BIFF_TOK_FUNCVAR_CMD
) )
1789 nParamCount
&= BIFF_TOK_FUNCVAR_COUNTMASK
;
1790 if( const FunctionInfo
* pFuncInfo
= getFuncInfoFromOobFuncId( nFuncId
) )
1791 return pushFunctionOperator( *pFuncInfo
, nParamCount
);
1792 return pushFunctionOperator( OPCODE_NONAME
, nParamCount
);
1795 // BIFF parser implementation =================================================
1799 /** A natural language reference struct with relative flag. */
1802 sal_Int32 mnCol
; /// Column index.
1803 sal_Int32 mnRow
; /// Row index.
1804 bool mbRel
; /// True = relative column/row reference.
1808 void readBiff8Data( BiffInputStream
& rStrm
);
1811 BiffNlr::BiffNlr() :
1818 void BiffNlr::readBiff8Data( BiffInputStream
& rStrm
)
1820 sal_uInt16 nRow
, nCol
;
1821 rStrm
>> nRow
>> nCol
;
1822 mnCol
= nCol
& BIFF_TOK_NLR_MASK
;
1824 mbRel
= getFlag( nCol
, BIFF_TOK_NLR_REL
);
1827 bool lclIsValidNlrStack( const BinAddress
& rAddr1
, const BinAddress
& rAddr2
, bool bRow
)
1830 ((rAddr1
.mnRow
== rAddr2
.mnRow
) && (rAddr1
.mnCol
+ 1 == rAddr2
.mnCol
)) :
1831 ((rAddr1
.mnCol
== rAddr2
.mnCol
) && (rAddr1
.mnRow
+ 1 == rAddr2
.mnRow
));
1834 bool lclIsValidNlrRange( const BiffNlr
& rNlr
, const BinRange
& rRange
, bool bRow
)
1837 ((rNlr
.mnRow
== rRange
.maFirst
.mnRow
) && (rNlr
.mnCol
+ 1 == rRange
.maFirst
.mnCol
) && (rRange
.maFirst
.mnRow
== rRange
.maLast
.mnRow
)) :
1838 ((rNlr
.mnCol
== rRange
.maFirst
.mnCol
) && (rNlr
.mnRow
+ 1 == rRange
.maFirst
.mnRow
) && (rRange
.maFirst
.mnCol
== rRange
.maLast
.mnCol
));
1843 // ----------------------------------------------------------------------------
1845 class BiffFormulaParserImpl
: public FormulaParserImpl
1848 explicit BiffFormulaParserImpl( const FormulaParser
& rParent
);
1850 virtual void importBiffFormula(
1851 FormulaContext
& rContext
,
1852 BiffInputStream
& rStrm
, const sal_uInt16
* pnFmlaSize
);
1855 // import token contents and create API formula token ---------------------
1857 bool importTokenNotAvailable( BiffInputStream
& rStrm
);
1858 bool importRefTokenNotAvailable( BiffInputStream
& rStrm
, bool bDeleted
, bool bRelativeAsOffset
);
1859 bool importStrToken2( BiffInputStream
& rStrm
);
1860 bool importStrToken8( BiffInputStream
& rStrm
);
1861 bool importAttrToken( BiffInputStream
& rStrm
);
1862 bool importSpaceToken3( BiffInputStream
& rStrm
);
1863 bool importSpaceToken4( BiffInputStream
& rStrm
);
1864 bool importSheetToken2( BiffInputStream
& rStrm
);
1865 bool importSheetToken3( BiffInputStream
& rStrm
);
1866 bool importEndSheetToken2( BiffInputStream
& rStrm
);
1867 bool importEndSheetToken3( BiffInputStream
& rStrm
);
1868 bool importNlrToken( BiffInputStream
& rStrm
);
1869 bool importArrayToken( BiffInputStream
& rStrm
);
1870 bool importRefToken2( BiffInputStream
& rStrm
, bool bDeleted
, bool bRelativeAsOffset
);
1871 bool importRefToken8( BiffInputStream
& rStrm
, bool bDeleted
, bool bRelativeAsOffset
);
1872 bool importAreaToken2( BiffInputStream
& rStrm
, bool bDeleted
, bool bRelativeAsOffset
);
1873 bool importAreaToken8( BiffInputStream
& rStrm
, bool bDeleted
, bool bRelativeAsOffset
);
1874 bool importRef3dToken5( BiffInputStream
& rStrm
, bool bDeleted
, bool bRelativeAsOffset
);
1875 bool importRef3dToken8( BiffInputStream
& rStrm
, bool bDeleted
, bool bRelativeAsOffset
);
1876 bool importArea3dToken5( BiffInputStream
& rStrm
, bool bDeleted
, bool bRelativeAsOffset
);
1877 bool importArea3dToken8( BiffInputStream
& rStrm
, bool bDeleted
, bool bRelativeAsOffset
);
1878 bool importMemAreaToken( BiffInputStream
& rStrm
, bool bAddData
);
1879 bool importMemFuncToken( BiffInputStream
& rStrm
);
1880 bool importNameToken( BiffInputStream
& rStrm
);
1881 bool importNameXToken( BiffInputStream
& rStrm
);
1882 bool importFuncToken2( BiffInputStream
& rStrm
);
1883 bool importFuncToken4( BiffInputStream
& rStrm
);
1884 bool importFuncVarToken2( BiffInputStream
& rStrm
);
1885 bool importFuncVarToken4( BiffInputStream
& rStrm
);
1886 bool importFuncCEToken( BiffInputStream
& rStrm
);
1887 bool importExpToken5( BiffInputStream
& rStrm
);
1889 bool importNlrAddrToken( BiffInputStream
& rStrm
, bool bRow
);
1890 bool importNlrRangeToken( BiffInputStream
& rStrm
);
1891 bool importNlrSAddrToken( BiffInputStream
& rStrm
, bool bRow
);
1892 bool importNlrSRangeToken( BiffInputStream
& rStrm
);
1893 bool importNlrErrToken( BiffInputStream
& rStrm
, sal_uInt16 nSkip
);
1895 sal_Int32
readRefId( BiffInputStream
& rStrm
);
1896 sal_uInt16
readNameId( BiffInputStream
& rStrm
);
1897 LinkSheetRange
readSheetRange5( BiffInputStream
& rStrm
);
1898 LinkSheetRange
readSheetRange8( BiffInputStream
& rStrm
);
1900 void swapStreamPosition( BiffInputStream
& rStrm
);
1901 void skipMemAreaAddData( BiffInputStream
& rStrm
);
1902 bool readNlrSAddrAddData( BiffNlr
& orNlr
, BiffInputStream
& rStrm
, bool bRow
);
1903 bool readNlrSRangeAddData( BiffNlr
& orNlr
, bool& orbIsRow
, BiffInputStream
& rStrm
);
1905 // convert BIFF token and push API operand or operator --------------------
1907 bool pushBiffReference( const BinSingleRef2d
& rRef
, bool bDeleted
, bool bRelativeAsOffset
);
1908 bool pushBiffReference( const BinComplexRef2d
& rRef
, bool bDeleted
, bool bRelativeAsOffset
);
1909 bool pushBiffNlrAddr( const BiffNlr
& rNlr
, bool bRow
);
1910 bool pushBiffNlrRange( const BiffNlr
& rNlr
, const BinRange
& rRange
);
1911 bool pushBiffNlrSAddr( const BiffNlr
& rNlr
, bool bRow
);
1912 bool pushBiffNlrSRange( const BiffNlr
& rNlr
, const BinRange
& rRange
, bool bRow
);
1913 bool pushBiffName( sal_uInt16 nNameId
);
1914 bool pushBiffExtName( sal_Int32 nRefId
, sal_uInt16 nNameId
);
1915 bool pushBiffFunction( sal_uInt16 nFuncId
);
1916 bool pushBiffFunction( sal_uInt16 nFuncId
, sal_uInt8 nParamCount
);
1918 // ------------------------------------------------------------------------
1920 typedef bool (BiffFormulaParserImpl::*ImportTokenFunc
)( BiffInputStream
& );
1921 typedef bool (BiffFormulaParserImpl::*ImportRefTokenFunc
)( BiffInputStream
&, bool, bool );
1923 ImportTokenFunc mpImportStrToken
; /// Pointer to tStr import function (string constant).
1924 ImportTokenFunc mpImportSpaceToken
; /// Pointer to tAttrSpace import function (spaces/line breaks).
1925 ImportTokenFunc mpImportSheetToken
; /// Pointer to tSheet import function (external reference).
1926 ImportTokenFunc mpImportEndSheetToken
; /// Pointer to tEndSheet import function (end of external reference).
1927 ImportTokenFunc mpImportNlrToken
; /// Pointer to tNlr import function (natural language reference).
1928 ImportRefTokenFunc mpImportRefToken
; /// Pointer to tRef import function (2d cell reference).
1929 ImportRefTokenFunc mpImportAreaToken
; /// Pointer to tArea import function (2d area reference).
1930 ImportRefTokenFunc mpImportRef3dToken
; /// Pointer to tRef3d import function (3d cell reference).
1931 ImportRefTokenFunc mpImportArea3dToken
; /// Pointer to tArea3d import function (3d area reference).
1932 ImportTokenFunc mpImportNameXToken
; /// Pointer to tNameX import function (external name).
1933 ImportTokenFunc mpImportFuncToken
; /// Pointer to tFunc import function (function with fixed parameter count).
1934 ImportTokenFunc mpImportFuncVarToken
; /// Pointer to tFuncVar import function (function with variable parameter count).
1935 ImportTokenFunc mpImportFuncCEToken
; /// Pointer to tFuncCE import function (command macro call).
1936 ImportTokenFunc mpImportExpToken
; /// Pointer to tExp import function (array/shared formula).
1937 sal_Int64 mnAddDataPos
; /// Current stream position for additional data (tArray, tMemArea, tNlr).
1938 sal_Int32 mnCurrRefId
; /// Current ref-id from tSheet token (BIFF2-BIFF4 only).
1939 sal_uInt16 mnAttrDataSize
; /// Size of one tAttr data element.
1940 sal_uInt16 mnArraySize
; /// Size of tArray data.
1941 sal_uInt16 mnNameSize
; /// Size of tName data.
1942 sal_uInt16 mnMemAreaSize
; /// Size of tMemArea data.
1943 sal_uInt16 mnMemFuncSize
; /// Size of tMemFunc data.
1944 sal_uInt16 mnRefIdSize
; /// Size of unused data following a reference identifier.
1947 // ----------------------------------------------------------------------------
1949 BiffFormulaParserImpl::BiffFormulaParserImpl( const FormulaParser
& rParent
) :
1950 FormulaParserImpl( rParent
),
1957 mpImportStrToken
= &BiffFormulaParserImpl::importStrToken2
;
1958 mpImportSpaceToken
= &BiffFormulaParserImpl::importTokenNotAvailable
;
1959 mpImportSheetToken
= &BiffFormulaParserImpl::importSheetToken2
;
1960 mpImportEndSheetToken
= &BiffFormulaParserImpl::importEndSheetToken2
;
1961 mpImportNlrToken
= &BiffFormulaParserImpl::importTokenNotAvailable
;
1962 mpImportRefToken
= &BiffFormulaParserImpl::importRefToken2
;
1963 mpImportAreaToken
= &BiffFormulaParserImpl::importAreaToken2
;
1964 mpImportRef3dToken
= &BiffFormulaParserImpl::importRefTokenNotAvailable
;
1965 mpImportArea3dToken
= &BiffFormulaParserImpl::importRefTokenNotAvailable
;
1966 mpImportNameXToken
= &BiffFormulaParserImpl::importTokenNotAvailable
;
1967 mpImportFuncToken
= &BiffFormulaParserImpl::importFuncToken2
;
1968 mpImportFuncVarToken
= &BiffFormulaParserImpl::importFuncVarToken2
;
1969 mpImportFuncCEToken
= &BiffFormulaParserImpl::importFuncCEToken
;
1970 mpImportExpToken
= &BiffFormulaParserImpl::importTokenNotAvailable
;
1979 mpImportStrToken
= &BiffFormulaParserImpl::importStrToken2
;
1980 mpImportSpaceToken
= &BiffFormulaParserImpl::importSpaceToken3
;
1981 mpImportSheetToken
= &BiffFormulaParserImpl::importSheetToken3
;
1982 mpImportEndSheetToken
= &BiffFormulaParserImpl::importEndSheetToken3
;
1983 mpImportNlrToken
= &BiffFormulaParserImpl::importTokenNotAvailable
;
1984 mpImportRefToken
= &BiffFormulaParserImpl::importRefToken2
;
1985 mpImportAreaToken
= &BiffFormulaParserImpl::importAreaToken2
;
1986 mpImportRef3dToken
= &BiffFormulaParserImpl::importRefTokenNotAvailable
;
1987 mpImportArea3dToken
= &BiffFormulaParserImpl::importRefTokenNotAvailable
;
1988 mpImportNameXToken
= &BiffFormulaParserImpl::importTokenNotAvailable
;
1989 mpImportFuncToken
= &BiffFormulaParserImpl::importFuncToken2
;
1990 mpImportFuncVarToken
= &BiffFormulaParserImpl::importFuncVarToken2
;
1991 mpImportFuncCEToken
= &BiffFormulaParserImpl::importFuncCEToken
;
1992 mpImportExpToken
= &BiffFormulaParserImpl::importTokenNotAvailable
;
2001 mpImportStrToken
= &BiffFormulaParserImpl::importStrToken2
;
2002 mpImportSpaceToken
= &BiffFormulaParserImpl::importSpaceToken4
;
2003 mpImportSheetToken
= &BiffFormulaParserImpl::importSheetToken3
;
2004 mpImportEndSheetToken
= &BiffFormulaParserImpl::importEndSheetToken3
;
2005 mpImportNlrToken
= &BiffFormulaParserImpl::importTokenNotAvailable
;
2006 mpImportRefToken
= &BiffFormulaParserImpl::importRefToken2
;
2007 mpImportAreaToken
= &BiffFormulaParserImpl::importAreaToken2
;
2008 mpImportRef3dToken
= &BiffFormulaParserImpl::importRefTokenNotAvailable
;
2009 mpImportArea3dToken
= &BiffFormulaParserImpl::importRefTokenNotAvailable
;
2010 mpImportNameXToken
= &BiffFormulaParserImpl::importTokenNotAvailable
;
2011 mpImportFuncToken
= &BiffFormulaParserImpl::importFuncToken4
;
2012 mpImportFuncVarToken
= &BiffFormulaParserImpl::importFuncVarToken4
;
2013 mpImportFuncCEToken
= &BiffFormulaParserImpl::importTokenNotAvailable
;
2014 mpImportExpToken
= &BiffFormulaParserImpl::importTokenNotAvailable
;
2023 mpImportStrToken
= &BiffFormulaParserImpl::importStrToken2
;
2024 mpImportSpaceToken
= &BiffFormulaParserImpl::importSpaceToken4
;
2025 mpImportSheetToken
= &BiffFormulaParserImpl::importTokenNotAvailable
;
2026 mpImportEndSheetToken
= &BiffFormulaParserImpl::importTokenNotAvailable
;
2027 mpImportNlrToken
= &BiffFormulaParserImpl::importTokenNotAvailable
;
2028 mpImportRefToken
= &BiffFormulaParserImpl::importRefToken2
;
2029 mpImportAreaToken
= &BiffFormulaParserImpl::importAreaToken2
;
2030 mpImportRef3dToken
= &BiffFormulaParserImpl::importRef3dToken5
;
2031 mpImportArea3dToken
= &BiffFormulaParserImpl::importArea3dToken5
;
2032 mpImportNameXToken
= &BiffFormulaParserImpl::importNameXToken
;
2033 mpImportFuncToken
= &BiffFormulaParserImpl::importFuncToken4
;
2034 mpImportFuncVarToken
= &BiffFormulaParserImpl::importFuncVarToken4
;
2035 mpImportFuncCEToken
= &BiffFormulaParserImpl::importTokenNotAvailable
;
2036 mpImportExpToken
= &BiffFormulaParserImpl::importExpToken5
;
2045 mpImportStrToken
= &BiffFormulaParserImpl::importStrToken8
;
2046 mpImportSpaceToken
= &BiffFormulaParserImpl::importSpaceToken4
;
2047 mpImportSheetToken
= &BiffFormulaParserImpl::importTokenNotAvailable
;
2048 mpImportEndSheetToken
= &BiffFormulaParserImpl::importTokenNotAvailable
;
2049 mpImportNlrToken
= &BiffFormulaParserImpl::importNlrToken
;
2050 mpImportRefToken
= &BiffFormulaParserImpl::importRefToken8
;
2051 mpImportAreaToken
= &BiffFormulaParserImpl::importAreaToken8
;
2052 mpImportRef3dToken
= &BiffFormulaParserImpl::importRef3dToken8
;
2053 mpImportArea3dToken
= &BiffFormulaParserImpl::importArea3dToken8
;
2054 mpImportNameXToken
= &BiffFormulaParserImpl::importNameXToken
;
2055 mpImportFuncToken
= &BiffFormulaParserImpl::importFuncToken4
;
2056 mpImportFuncVarToken
= &BiffFormulaParserImpl::importFuncVarToken4
;
2057 mpImportFuncCEToken
= &BiffFormulaParserImpl::importTokenNotAvailable
;
2058 mpImportExpToken
= &BiffFormulaParserImpl::importExpToken5
;
2066 case BIFF_UNKNOWN
: break;
2070 void BiffFormulaParserImpl::importBiffFormula( FormulaContext
& rContext
,
2071 BiffInputStream
& rStrm
, const sal_uInt16
* pnFmlaSize
)
2073 initializeImport( rContext
);
2076 sal_uInt16 nFmlaSize
= lclReadFmlaSize( rStrm
, getBiff(), pnFmlaSize
);
2077 sal_Int64 nEndPos
= mnAddDataPos
= rStrm
.tell() + nFmlaSize
;
2078 bool bRelativeAsOffset
= getFormulaContext().isRelativeAsOffset();
2081 while( bOk
&& !rStrm
.isEof() && (rStrm
.tell() < nEndPos
) )
2085 sal_uInt8 nTokenClass
= nTokenId
& BIFF_TOKCLASS_MASK
;
2086 sal_uInt8 nBaseId
= nTokenId
& BIFF_TOKID_MASK
;
2088 bOk
= !getFlag( nTokenId
, BIFF_TOKFLAG_INVALID
);
2091 if( nTokenClass
== BIFF_TOKCLASS_NONE
)
2096 case BIFF_TOKID_EXP
: bOk
= (this->*mpImportExpToken
)( rStrm
); break;
2097 case BIFF_TOKID_TBL
: bOk
= false; /* multiple op. will be set externally */ break;
2098 case BIFF_TOKID_ADD
: bOk
= pushBinaryOperator( OPCODE_ADD
); break;
2099 case BIFF_TOKID_SUB
: bOk
= pushBinaryOperator( OPCODE_SUB
); break;
2100 case BIFF_TOKID_MUL
: bOk
= pushBinaryOperator( OPCODE_MULT
); break;
2101 case BIFF_TOKID_DIV
: bOk
= pushBinaryOperator( OPCODE_DIV
); break;
2102 case BIFF_TOKID_POWER
: bOk
= pushBinaryOperator( OPCODE_POWER
); break;
2103 case BIFF_TOKID_CONCAT
: bOk
= pushBinaryOperator( OPCODE_CONCAT
); break;
2104 case BIFF_TOKID_LT
: bOk
= pushBinaryOperator( OPCODE_LESS
); break;
2105 case BIFF_TOKID_LE
: bOk
= pushBinaryOperator( OPCODE_LESS_EQUAL
); break;
2106 case BIFF_TOKID_EQ
: bOk
= pushBinaryOperator( OPCODE_EQUAL
); break;
2107 case BIFF_TOKID_GE
: bOk
= pushBinaryOperator( OPCODE_GREATER_EQUAL
); break;
2108 case BIFF_TOKID_GT
: bOk
= pushBinaryOperator( OPCODE_GREATER
); break;
2109 case BIFF_TOKID_NE
: bOk
= pushBinaryOperator( OPCODE_NOT_EQUAL
); break;
2110 case BIFF_TOKID_ISECT
: bOk
= pushBinaryOperator( OPCODE_INTERSECT
); break;
2111 case BIFF_TOKID_LIST
: bOk
= pushBinaryOperator( OPCODE_LIST
); break;
2112 case BIFF_TOKID_RANGE
: bOk
= pushBinaryOperator( OPCODE_RANGE
); break;
2113 case BIFF_TOKID_UPLUS
: bOk
= pushUnaryPreOperator( OPCODE_PLUS_SIGN
); break;
2114 case BIFF_TOKID_UMINUS
: bOk
= pushUnaryPreOperator( OPCODE_MINUS_SIGN
); break;
2115 case BIFF_TOKID_PERCENT
: bOk
= pushUnaryPostOperator( OPCODE_PERCENT
); break;
2116 case BIFF_TOKID_PAREN
: bOk
= pushParenthesesOperator(); break;
2117 case BIFF_TOKID_MISSARG
: bOk
= pushOperand( OPCODE_MISSING
); break;
2118 case BIFF_TOKID_STR
: bOk
= (this->*mpImportStrToken
)( rStrm
); break;
2119 case BIFF_TOKID_NLR
: bOk
= (this->*mpImportNlrToken
)( rStrm
); break;
2120 case BIFF_TOKID_ATTR
: bOk
= importAttrToken( rStrm
); break;
2121 case BIFF_TOKID_SHEET
: bOk
= (this->*mpImportSheetToken
)( rStrm
); break;
2122 case BIFF_TOKID_ENDSHEET
: bOk
= (this->*mpImportEndSheetToken
)( rStrm
); break;
2123 case BIFF_TOKID_ERR
: bOk
= pushBiffErrorOperand( rStrm
.readuInt8() ); break;
2124 case BIFF_TOKID_BOOL
: bOk
= pushBiffBoolOperand( rStrm
.readuInt8() ); break;
2125 case BIFF_TOKID_INT
: bOk
= pushValueOperand
< double >( rStrm
.readuInt16() ); break;
2126 case BIFF_TOKID_NUM
: bOk
= pushValueOperand( rStrm
.readDouble() ); break;
2127 default: bOk
= false;
2132 // classified tokens
2135 case BIFF_TOKID_ARRAY
: bOk
= importArrayToken( rStrm
); break;
2136 case BIFF_TOKID_FUNC
: bOk
= (this->*mpImportFuncToken
)( rStrm
); break;
2137 case BIFF_TOKID_FUNCVAR
: bOk
= (this->*mpImportFuncVarToken
)( rStrm
); break;
2138 case BIFF_TOKID_NAME
: bOk
= importNameToken( rStrm
); break;
2139 case BIFF_TOKID_REF
: bOk
= (this->*mpImportRefToken
)( rStrm
, false, false ); break;
2140 case BIFF_TOKID_AREA
: bOk
= (this->*mpImportAreaToken
)( rStrm
, false, false ); break;
2141 case BIFF_TOKID_MEMAREA
: bOk
= importMemAreaToken( rStrm
, true ); break;
2142 case BIFF_TOKID_MEMERR
: bOk
= importMemAreaToken( rStrm
, false ); break;
2143 case BIFF_TOKID_MEMNOMEM
: bOk
= importMemAreaToken( rStrm
, false ); break;
2144 case BIFF_TOKID_MEMFUNC
: bOk
= importMemFuncToken( rStrm
); break;
2145 case BIFF_TOKID_REFERR
: bOk
= (this->*mpImportRefToken
)( rStrm
, true, false ); break;
2146 case BIFF_TOKID_AREAERR
: bOk
= (this->*mpImportAreaToken
)( rStrm
, true, false ); break;
2147 case BIFF_TOKID_REFN
: bOk
= (this->*mpImportRefToken
)( rStrm
, false, true ); break;
2148 case BIFF_TOKID_AREAN
: bOk
= (this->*mpImportAreaToken
)( rStrm
, false, true ); break;
2149 case BIFF_TOKID_MEMAREAN
: bOk
= importMemFuncToken( rStrm
); break;
2150 case BIFF_TOKID_MEMNOMEMN
: bOk
= importMemFuncToken( rStrm
); break;
2151 case BIFF_TOKID_FUNCCE
: bOk
= (this->*mpImportFuncCEToken
)( rStrm
); break;
2152 case BIFF_TOKID_NAMEX
: bOk
= (this->*mpImportNameXToken
)( rStrm
); break;
2153 case BIFF_TOKID_REF3D
: bOk
= (this->*mpImportRef3dToken
)( rStrm
, false, bRelativeAsOffset
); break;
2154 case BIFF_TOKID_AREA3D
: bOk
= (this->*mpImportArea3dToken
)( rStrm
, false, bRelativeAsOffset
); break;
2155 case BIFF_TOKID_REFERR3D
: bOk
= (this->*mpImportRef3dToken
)( rStrm
, true, bRelativeAsOffset
); break;
2156 case BIFF_TOKID_AREAERR3D
: bOk
= (this->*mpImportArea3dToken
)( rStrm
, true, bRelativeAsOffset
); break;
2157 default: bOk
= false;
2163 // build and finalize the token sequence
2164 if( bOk
&& (rStrm
.tell() == nEndPos
) )
2167 // seek behind additional token data of tArray, tMemArea, tNlr tokens
2168 rStrm
.seek( mnAddDataPos
);
2171 // import token contents and create API formula token -------------------------
2173 bool BiffFormulaParserImpl::importTokenNotAvailable( BiffInputStream
& )
2175 // dummy function for pointer-to-member-function
2179 bool BiffFormulaParserImpl::importRefTokenNotAvailable( BiffInputStream
&, bool, bool )
2181 // dummy function for pointer-to-member-function
2185 bool BiffFormulaParserImpl::importStrToken2( BiffInputStream
& rStrm
)
2187 return pushValueOperand( rStrm
.readByteStringUC( false, getTextEncoding(), getFormulaContext().isNulCharsAllowed() ) );
2190 bool BiffFormulaParserImpl::importStrToken8( BiffInputStream
& rStrm
)
2192 // read flags field for empty strings also
2193 return pushValueOperand( rStrm
.readUniStringBody( rStrm
.readuInt8(), getFormulaContext().isNulCharsAllowed() ) );
2196 bool BiffFormulaParserImpl::importAttrToken( BiffInputStream
& rStrm
)
2203 case 0: // sometimes, tAttrSkip tokens miss the type flag
2204 case BIFF_TOK_ATTR_VOLATILE
:
2205 case BIFF_TOK_ATTR_IF
:
2206 case BIFF_TOK_ATTR_SKIP
:
2207 case BIFF_TOK_ATTR_ASSIGN
:
2208 rStrm
.skip( mnAttrDataSize
);
2210 case BIFF_TOK_ATTR_CHOOSE
:
2211 rStrm
.skip( mnAttrDataSize
* (1 + ((getBiff() == BIFF2
) ? rStrm
.readuInt8() : rStrm
.readuInt16())) );
2213 case BIFF_TOK_ATTR_SUM
:
2214 rStrm
.skip( mnAttrDataSize
);
2215 bOk
= pushBiffFunction( BIFF_FUNC_SUM
, 1 );
2217 case BIFF_TOK_ATTR_SPACE
:
2218 case BIFF_TOK_ATTR_SPACE_VOLATILE
:
2219 bOk
= (this->*mpImportSpaceToken
)( rStrm
);
2227 bool BiffFormulaParserImpl::importSpaceToken3( BiffInputStream
& rStrm
)
2233 bool BiffFormulaParserImpl::importSpaceToken4( BiffInputStream
& rStrm
)
2235 sal_uInt8 nType
, nCount
;
2236 rStrm
>> nType
>> nCount
;
2239 case BIFF_TOK_ATTR_SPACE_SP
:
2240 appendLeadingSpaces( nCount
, false );
2242 case BIFF_TOK_ATTR_SPACE_BR
:
2243 appendLeadingSpaces( nCount
, true );
2245 case BIFF_TOK_ATTR_SPACE_SP_OPEN
:
2246 appendOpeningSpaces( nCount
, false );
2248 case BIFF_TOK_ATTR_SPACE_BR_OPEN
:
2249 appendOpeningSpaces( nCount
, true );
2251 case BIFF_TOK_ATTR_SPACE_SP_CLOSE
:
2252 appendClosingSpaces( nCount
, false );
2254 case BIFF_TOK_ATTR_SPACE_BR_CLOSE
:
2255 appendClosingSpaces( nCount
, true );
2261 bool BiffFormulaParserImpl::importSheetToken2( BiffInputStream
& rStrm
)
2264 mnCurrRefId
= readRefId( rStrm
);
2268 bool BiffFormulaParserImpl::importSheetToken3( BiffInputStream
& rStrm
)
2271 mnCurrRefId
= readRefId( rStrm
);
2275 bool BiffFormulaParserImpl::importEndSheetToken2( BiffInputStream
& rStrm
)
2282 bool BiffFormulaParserImpl::importEndSheetToken3( BiffInputStream
& rStrm
)
2289 bool BiffFormulaParserImpl::importNlrToken( BiffInputStream
& rStrm
)
2296 case BIFF_TOK_NLR_ERR
: bOk
= importNlrErrToken( rStrm
, 4 ); break;
2297 case BIFF_TOK_NLR_ROWR
: bOk
= importNlrAddrToken( rStrm
, true ); break;
2298 case BIFF_TOK_NLR_COLR
: bOk
= importNlrAddrToken( rStrm
, false ); break;
2299 case BIFF_TOK_NLR_ROWV
: bOk
= importNlrAddrToken( rStrm
, true ); break;
2300 case BIFF_TOK_NLR_COLV
: bOk
= importNlrAddrToken( rStrm
, false ); break;
2301 case BIFF_TOK_NLR_RANGE
: bOk
= importNlrRangeToken( rStrm
); break;
2302 case BIFF_TOK_NLR_SRANGE
: bOk
= importNlrSRangeToken( rStrm
); break;
2303 case BIFF_TOK_NLR_SROWR
: bOk
= importNlrSAddrToken( rStrm
, true ); break;
2304 case BIFF_TOK_NLR_SCOLR
: bOk
= importNlrSAddrToken( rStrm
, false ); break;
2305 case BIFF_TOK_NLR_SROWV
: bOk
= importNlrSAddrToken( rStrm
, true ); break;
2306 case BIFF_TOK_NLR_SCOLV
: bOk
= importNlrSAddrToken( rStrm
, false ); break;
2307 case BIFF_TOK_NLR_RANGEERR
: bOk
= importNlrErrToken( rStrm
, 13 ); break;
2308 case BIFF_TOK_NLR_SXNAME
: bOk
= importNlrErrToken( rStrm
, 4 ); break;
2309 default: bOk
= false;
2314 bool BiffFormulaParserImpl::importArrayToken( BiffInputStream
& rStrm
)
2316 rStrm
.skip( mnArraySize
);
2318 // start token array with opening brace and leading spaces
2319 pushOperand( OPCODE_ARRAY_OPEN
);
2320 size_t nOpSize
= popOperandSize();
2321 size_t nOldArraySize
= getFormulaSize();
2322 bool bBiff8
= getBiff() == BIFF8
;
2323 bool bNulChars
= getFormulaContext().isNulCharsAllowed();
2326 swapStreamPosition( rStrm
);
2327 sal_uInt16 nCols
= rStrm
.readuInt8();
2328 sal_uInt16 nRows
= rStrm
.readuInt16();
2329 if( bBiff8
) { ++nCols
; ++nRows
; } else if( nCols
== 0 ) nCols
= 256;
2330 OSL_ENSURE( (nCols
> 0) && (nRows
> 0), "BiffFormulaParserImpl::importArrayToken - empty array" );
2332 // read array values and build token array
2333 for( sal_uInt16 nRow
= 0; !rStrm
.isEof() && (nRow
< nRows
); ++nRow
)
2336 appendRawToken( OPCODE_ARRAY_ROWSEP
);
2337 for( sal_uInt16 nCol
= 0; !rStrm
.isEof() && (nCol
< nCols
); ++nCol
)
2340 appendRawToken( OPCODE_ARRAY_COLSEP
);
2341 switch( rStrm
.readuInt8() )
2343 case BIFF_DATATYPE_EMPTY
:
2344 appendRawToken( OPCODE_PUSH
) <<= OUString();
2347 case BIFF_DATATYPE_DOUBLE
:
2348 appendRawToken( OPCODE_PUSH
) <<= rStrm
.readDouble();
2350 case BIFF_DATATYPE_STRING
:
2351 appendRawToken( OPCODE_PUSH
) <<= bBiff8
?
2352 rStrm
.readUniString( bNulChars
) :
2353 rStrm
.readByteStringUC( false, getTextEncoding(), bNulChars
);
2355 case BIFF_DATATYPE_BOOL
:
2356 appendRawToken( OPCODE_PUSH
) <<= static_cast< double >( (rStrm
.readuInt8() == BIFF_TOK_BOOL_FALSE
) ? 0.0 : 1.0 );
2359 case BIFF_DATATYPE_ERROR
:
2360 appendRawToken( OPCODE_PUSH
) <<= BiffHelper::calcDoubleFromError( rStrm
.readuInt8() );
2364 OSL_ENSURE( false, "BiffFormulaParserImpl::importArrayToken - unknown data type" );
2365 appendRawToken( OPCODE_PUSH
) <<= BiffHelper::calcDoubleFromError( BIFF_ERR_NA
);
2369 swapStreamPosition( rStrm
);
2371 // close token array and set resulting operand size
2372 appendRawToken( OPCODE_ARRAY_CLOSE
);
2373 pushOperandSize( nOpSize
+ getFormulaSize() - nOldArraySize
);
2377 bool BiffFormulaParserImpl::importRefToken2( BiffInputStream
& rStrm
, bool bDeleted
, bool bRelativeAsOffset
)
2379 BinSingleRef2d aRef
;
2380 aRef
.readBiff2Data( rStrm
, bRelativeAsOffset
);
2381 return pushBiffReference( aRef
, bDeleted
, bRelativeAsOffset
);
2384 bool BiffFormulaParserImpl::importRefToken8( BiffInputStream
& rStrm
, bool bDeleted
, bool bRelativeAsOffset
)
2386 BinSingleRef2d aRef
;
2387 aRef
.readBiff8Data( rStrm
, bRelativeAsOffset
);
2388 return pushBiffReference( aRef
, bDeleted
, bRelativeAsOffset
);
2391 bool BiffFormulaParserImpl::importAreaToken2( BiffInputStream
& rStrm
, bool bDeleted
, bool bRelativeAsOffset
)
2393 BinComplexRef2d aRef
;
2394 aRef
.readBiff2Data( rStrm
, bRelativeAsOffset
);
2395 return pushBiffReference( aRef
, bDeleted
, bRelativeAsOffset
);
2398 bool BiffFormulaParserImpl::importAreaToken8( BiffInputStream
& rStrm
, bool bDeleted
, bool bRelativeAsOffset
)
2400 BinComplexRef2d aRef
;
2401 aRef
.readBiff8Data( rStrm
, bRelativeAsOffset
);
2402 return pushBiffReference( aRef
, bDeleted
, bRelativeAsOffset
);
2405 bool BiffFormulaParserImpl::importRef3dToken5( BiffInputStream
& rStrm
, bool bDeleted
, bool bRelativeAsOffset
)
2407 LinkSheetRange aSheetRange
= readSheetRange5( rStrm
);
2408 BinSingleRef2d aRef
;
2409 aRef
.readBiff2Data( rStrm
, bRelativeAsOffset
);
2410 return pushReferenceOperand( aSheetRange
, aRef
, bDeleted
, bRelativeAsOffset
);
2413 bool BiffFormulaParserImpl::importRef3dToken8( BiffInputStream
& rStrm
, bool bDeleted
, bool bRelativeAsOffset
)
2415 LinkSheetRange aSheetRange
= readSheetRange8( rStrm
);
2416 BinSingleRef2d aRef
;
2417 aRef
.readBiff8Data( rStrm
, bRelativeAsOffset
);
2418 return pushReferenceOperand( aSheetRange
, aRef
, bDeleted
, bRelativeAsOffset
);
2421 bool BiffFormulaParserImpl::importArea3dToken5( BiffInputStream
& rStrm
, bool bDeleted
, bool bRelativeAsOffset
)
2423 LinkSheetRange aSheetRange
= readSheetRange5( rStrm
);
2424 BinComplexRef2d aRef
;
2425 aRef
.readBiff2Data( rStrm
, bRelativeAsOffset
);
2426 return pushReferenceOperand( aSheetRange
, aRef
, bDeleted
, bRelativeAsOffset
);
2429 bool BiffFormulaParserImpl::importArea3dToken8( BiffInputStream
& rStrm
, bool bDeleted
, bool bRelativeAsOffset
)
2431 LinkSheetRange aSheetRange
= readSheetRange8( rStrm
);
2432 BinComplexRef2d aRef
;
2433 aRef
.readBiff8Data( rStrm
, bRelativeAsOffset
);
2434 return pushReferenceOperand( aSheetRange
, aRef
, bDeleted
, bRelativeAsOffset
);
2437 bool BiffFormulaParserImpl::importMemAreaToken( BiffInputStream
& rStrm
, bool bAddData
)
2439 rStrm
.skip( mnMemAreaSize
);
2441 skipMemAreaAddData( rStrm
);
2445 bool BiffFormulaParserImpl::importMemFuncToken( BiffInputStream
& rStrm
)
2447 rStrm
.skip( mnMemFuncSize
);
2451 bool BiffFormulaParserImpl::importNameToken( BiffInputStream
& rStrm
)
2453 sal_uInt16 nNameId
= readNameId( rStrm
);
2454 return (mnCurrRefId
> 0) ? pushBiffExtName( mnCurrRefId
, nNameId
) : pushBiffName( nNameId
);
2457 bool BiffFormulaParserImpl::importNameXToken( BiffInputStream
& rStrm
)
2459 sal_Int32 nRefId
= readRefId( rStrm
);
2460 sal_uInt16 nNameId
= readNameId( rStrm
);
2461 return pushBiffExtName( nRefId
, nNameId
);
2464 bool BiffFormulaParserImpl::importFuncToken2( BiffInputStream
& rStrm
)
2468 return pushBiffFunction( nFuncId
);
2471 bool BiffFormulaParserImpl::importFuncToken4( BiffInputStream
& rStrm
)
2475 return pushBiffFunction( nFuncId
);
2478 bool BiffFormulaParserImpl::importFuncVarToken2( BiffInputStream
& rStrm
)
2480 sal_uInt8 nParamCount
, nFuncId
;
2481 rStrm
>> nParamCount
>> nFuncId
;
2482 return pushBiffFunction( nFuncId
, nParamCount
);
2485 bool BiffFormulaParserImpl::importFuncVarToken4( BiffInputStream
& rStrm
)
2487 sal_uInt8 nParamCount
;
2489 rStrm
>> nParamCount
>> nFuncId
;
2490 return pushBiffFunction( nFuncId
, nParamCount
& BIFF_TOK_FUNCVAR_COUNTMASK
);
2493 bool BiffFormulaParserImpl::importFuncCEToken( BiffInputStream
& rStrm
)
2495 sal_uInt8 nParamCount
, nFuncId
;
2496 rStrm
>> nParamCount
>> nFuncId
;
2497 sal_uInt16 nCmdId
= nFuncId
;
2498 setFlag( nCmdId
, BIFF_TOK_FUNCVAR_CMD
);
2499 return pushBiffFunction( nCmdId
, nParamCount
);
2502 bool BiffFormulaParserImpl::importExpToken5( BiffInputStream
& rStrm
)
2504 BinAddress aBaseAddr
;
2505 aBaseAddr
.read( rStrm
);
2506 setSharedFormula( aBaseAddr
);
2507 // formula has been set, exit parser by returning false
2511 bool BiffFormulaParserImpl::importNlrAddrToken( BiffInputStream
& rStrm
, bool bRow
)
2514 aNlr
.readBiff8Data( rStrm
);
2515 return pushBiffNlrAddr( aNlr
, bRow
);
2518 bool BiffFormulaParserImpl::importNlrRangeToken( BiffInputStream
& rStrm
)
2521 aNlr
.readBiff8Data( rStrm
);
2525 return pushBiffNlrRange( aNlr
, aRange
);
2528 bool BiffFormulaParserImpl::importNlrSAddrToken( BiffInputStream
& rStrm
, bool bRow
)
2532 return readNlrSAddrAddData( aNlr
, rStrm
, bRow
) ? pushBiffNlrSAddr( aNlr
, bRow
) : pushBiffErrorOperand( BIFF_ERR_REF
);
2535 bool BiffFormulaParserImpl::importNlrSRangeToken( BiffInputStream
& rStrm
)
2542 return readNlrSRangeAddData( aNlr
, bRow
, rStrm
) ? pushBiffNlrSRange( aNlr
, aRange
, bRow
) : pushBiffErrorOperand( BIFF_ERR_REF
);
2545 bool BiffFormulaParserImpl::importNlrErrToken( BiffInputStream
& rStrm
, sal_uInt16 nIgnore
)
2547 rStrm
.skip( nIgnore
);
2548 return pushBiffErrorOperand( BIFF_ERR_NAME
);
2551 sal_Int32
BiffFormulaParserImpl::readRefId( BiffInputStream
& rStrm
)
2555 rStrm
.skip( mnRefIdSize
);
2559 sal_uInt16
BiffFormulaParserImpl::readNameId( BiffInputStream
& rStrm
)
2563 rStrm
.skip( mnNameSize
);
2567 LinkSheetRange
BiffFormulaParserImpl::readSheetRange5( BiffInputStream
& rStrm
)
2569 sal_Int32 nRefId
= readRefId( rStrm
);
2570 sal_Int16 nTab1
, nTab2
;
2571 rStrm
>> nTab1
>> nTab2
;
2572 return getExternalLinks().getSheetRange( nRefId
, nTab1
, nTab2
);
2575 LinkSheetRange
BiffFormulaParserImpl::readSheetRange8( BiffInputStream
& rStrm
)
2577 return getExternalLinks().getSheetRange( readRefId( rStrm
) );
2580 void BiffFormulaParserImpl::swapStreamPosition( BiffInputStream
& rStrm
)
2582 sal_Int64 nRecPos
= rStrm
.tell();
2583 rStrm
.seek( mnAddDataPos
);
2584 mnAddDataPos
= nRecPos
;
2587 void BiffFormulaParserImpl::skipMemAreaAddData( BiffInputStream
& rStrm
)
2589 swapStreamPosition( rStrm
);
2590 sal_Int32 nCount
= rStrm
.readuInt16();
2591 rStrm
.skip( ((getBiff() == BIFF8
) ? 8 : 6) * nCount
);
2592 swapStreamPosition( rStrm
);
2595 bool BiffFormulaParserImpl::readNlrSAddrAddData( BiffNlr
& orNlr
, BiffInputStream
& rStrm
, bool bRow
)
2598 return readNlrSRangeAddData( orNlr
, bIsRow
, rStrm
) && (bIsRow
== bRow
);
2601 bool BiffFormulaParserImpl::readNlrSRangeAddData( BiffNlr
& orNlr
, bool& orbIsRow
, BiffInputStream
& rStrm
)
2603 swapStreamPosition( rStrm
);
2604 // read number of cell addresses and relative flag
2607 bool bRel
= getFlag( nCount
, BIFF_TOK_NLR_ADDREL
);
2608 nCount
&= BIFF_TOK_NLR_ADDMASK
;
2609 sal_Int64 nEndPos
= rStrm
.tell() + 4 * nCount
;
2610 // read list of cell addresses
2611 bool bValid
= false;
2614 // detect column/row orientation
2615 BinAddress aAddr1
, aAddr2
;
2616 rStrm
>> aAddr1
>> aAddr2
;
2617 orbIsRow
= aAddr1
.mnRow
== aAddr2
.mnRow
;
2618 bValid
= lclIsValidNlrStack( aAddr1
, aAddr2
, orbIsRow
);
2619 // read and verify additional cell positions
2620 for( sal_uInt32 nIndex
= 2; bValid
&& (nIndex
< nCount
); ++nIndex
)
2624 bValid
= !rStrm
.isEof() && lclIsValidNlrStack( aAddr1
, aAddr2
, orbIsRow
);
2626 // check that last imported position (aAddr2) is not at the end of the sheet
2627 bValid
= bValid
&& (orbIsRow
? (aAddr2
.mnCol
< mnMaxApiCol
) : (aAddr2
.mnRow
< mnMaxApiRow
));
2628 // fill the NLR struct with the last imported position
2631 orNlr
.mnCol
= aAddr2
.mnCol
;
2632 orNlr
.mnRow
= aAddr2
.mnRow
;
2636 // seek to end of additional data for this token
2637 rStrm
.seek( nEndPos
);
2638 swapStreamPosition( rStrm
);
2643 // convert BIFF token and push API operand or operator ------------------------
2645 bool BiffFormulaParserImpl::pushBiffReference( const BinSingleRef2d
& rRef
, bool bDeleted
, bool bRelativeAsOffset
)
2647 return (mnCurrRefId
> 0) ?
2648 pushReferenceOperand( getExternalLinks().getSheetRange( mnCurrRefId
, 0, 0 ), rRef
, bDeleted
, bRelativeAsOffset
) :
2649 pushReferenceOperand( rRef
, bDeleted
, bRelativeAsOffset
);
2652 bool BiffFormulaParserImpl::pushBiffReference( const BinComplexRef2d
& rRef
, bool bDeleted
, bool bRelativeAsOffset
)
2654 return (mnCurrRefId
> 0) ?
2655 pushReferenceOperand( getExternalLinks().getSheetRange( mnCurrRefId
, 0, 0 ), rRef
, bDeleted
, bRelativeAsOffset
) :
2656 pushReferenceOperand( rRef
, bDeleted
, bRelativeAsOffset
);
2659 bool BiffFormulaParserImpl::pushBiffNlrAddr( const BiffNlr
& rNlr
, bool bRow
)
2661 BinSingleRef2d aRef
;
2662 aRef
.mnCol
= rNlr
.mnCol
;
2663 aRef
.mnRow
= rNlr
.mnRow
;
2664 aRef
.mbColRel
= !bRow
;
2665 aRef
.mbRowRel
= bRow
;
2666 return pushNlrOperand( aRef
);
2669 bool BiffFormulaParserImpl::pushBiffNlrRange( const BiffNlr
& rNlr
, const BinRange
& rRange
)
2671 bool bRow
= rNlr
.mnRow
== rRange
.maFirst
.mnRow
;
2672 return lclIsValidNlrRange( rNlr
, rRange
, bRow
) ?
2673 pushBiffNlrAddr( rNlr
, bRow
) : pushBiffErrorOperand( BIFF_ERR_REF
);
2676 bool BiffFormulaParserImpl::pushBiffNlrSAddr( const BiffNlr
& rNlr
, bool bRow
)
2679 aRange
.maFirst
.mnCol
= rNlr
.mnCol
+ (bRow
? 1 : 0);
2680 aRange
.maFirst
.mnRow
= rNlr
.mnRow
+ (bRow
? 0 : 1);
2681 aRange
.maLast
.mnCol
= bRow
? mnMaxApiCol
: rNlr
.mnCol
;
2682 aRange
.maLast
.mnRow
= bRow
? rNlr
.mnRow
: mnMaxApiRow
;
2683 return pushBiffNlrSRange( rNlr
, aRange
, bRow
);
2686 bool BiffFormulaParserImpl::pushBiffNlrSRange( const BiffNlr
& rNlr
, const BinRange
& rRange
, bool bRow
)
2688 if( lclIsValidNlrRange( rNlr
, rRange
, bRow
) )
2690 BinComplexRef2d aRef
;
2691 aRef
.maRef1
.mnCol
= rRange
.maFirst
.mnCol
;
2692 aRef
.maRef1
.mnRow
= rRange
.maFirst
.mnRow
;
2693 aRef
.maRef2
.mnCol
= rRange
.maLast
.mnCol
;
2694 aRef
.maRef2
.mnRow
= rRange
.maLast
.mnRow
;
2695 aRef
.maRef1
.mbColRel
= aRef
.maRef2
.mbColRel
= !bRow
&& rNlr
.mbRel
;
2696 aRef
.maRef1
.mbRowRel
= aRef
.maRef2
.mbRowRel
= bRow
&& rNlr
.mbRel
;
2697 return pushReferenceOperand( aRef
, false, false );
2699 return pushBiffErrorOperand( BIFF_ERR_REF
);
2702 bool BiffFormulaParserImpl::pushBiffName( sal_uInt16 nNameId
)
2704 // one-based in BIFF formulas
2705 return pushDefinedNameOperand( getDefinedNames().getByIndex( static_cast< sal_Int32
>( nNameId
) - 1 ) );
2708 bool BiffFormulaParserImpl::pushBiffExtName( sal_Int32 nRefId
, sal_uInt16 nNameId
)
2710 if( const ExternalLink
* pExtLink
= getExternalLinks().getExternalLink( nRefId
).get() )
2712 if( pExtLink
->getLinkType() == LINKTYPE_SELF
)
2713 return pushBiffName( nNameId
);
2714 // external name indexes are one-based in BIFF
2715 ExternalNameRef xExtName
= pExtLink
->getNameByIndex( static_cast< sal_Int32
>( nNameId
) - 1 );
2716 return pushExternalNameOperand( xExtName
, *pExtLink
);
2718 return pushBiffErrorOperand( BIFF_ERR_NAME
);
2721 bool BiffFormulaParserImpl::pushBiffFunction( sal_uInt16 nFuncId
)
2723 if( const FunctionInfo
* pFuncInfo
= getFuncInfoFromBiffFuncId( nFuncId
) )
2724 if( pFuncInfo
->mnMinParamCount
== pFuncInfo
->mnMaxParamCount
)
2725 return pushFunctionOperator( *pFuncInfo
, pFuncInfo
->mnMinParamCount
);
2726 return pushFunctionOperator( OPCODE_NONAME
, 0 );
2729 bool BiffFormulaParserImpl::pushBiffFunction( sal_uInt16 nFuncId
, sal_uInt8 nParamCount
)
2731 if( getFlag( nFuncId
, BIFF_TOK_FUNCVAR_CMD
) )
2732 nParamCount
&= BIFF_TOK_FUNCVAR_COUNTMASK
;
2733 if( const FunctionInfo
* pFuncInfo
= getFuncInfoFromBiffFuncId( nFuncId
) )
2734 return pushFunctionOperator( *pFuncInfo
, nParamCount
);
2735 return pushFunctionOperator( OPCODE_NONAME
, nParamCount
);
2738 // ============================================================================
2740 FormulaParser::FormulaParser( const WorkbookHelper
& rHelper
) :
2741 FormulaProcessorBase( rHelper
)
2743 switch( getFilterType() )
2745 case FILTER_OOX
: mxImpl
.reset( new OoxFormulaParserImpl( *this ) ); break;
2746 case FILTER_BIFF
: mxImpl
.reset( new BiffFormulaParserImpl( *this ) ); break;
2747 case FILTER_UNKNOWN
: break;
2751 FormulaParser::~FormulaParser()
2755 void FormulaParser::importFormula( FormulaContext
& rContext
, const OUString
& rFormulaString
) const
2757 OOX_LOADSAVE_TIMER( IMPORTFORMULA
);
2758 mxImpl
->importOoxFormula( rContext
, rFormulaString
);
2761 void FormulaParser::importFormula( FormulaContext
& rContext
, RecordInputStream
& rStrm
) const
2763 OOX_LOADSAVE_TIMER( IMPORTFORMULA
);
2764 mxImpl
->importOobFormula( rContext
, rStrm
);
2767 void FormulaParser::importFormula( FormulaContext
& rContext
, BiffInputStream
& rStrm
, const sal_uInt16
* pnFmlaSize
) const
2769 OOX_LOADSAVE_TIMER( IMPORTFORMULA
);
2770 mxImpl
->importBiffFormula( rContext
, rStrm
, pnFmlaSize
);
2773 void FormulaParser::convertErrorToFormula( FormulaContext
& rContext
, sal_uInt8 nErrorCode
) const
2775 ApiTokenSequence
aTokens( 3 );
2776 // HACK: enclose all error codes into an 1x1 matrix
2777 aTokens
[ 0 ].OpCode
= OPCODE_ARRAY_OPEN
;
2778 aTokens
[ 1 ].OpCode
= OPCODE_PUSH
;
2779 aTokens
[ 1 ].Data
<<= BiffHelper::calcDoubleFromError( nErrorCode
);
2780 aTokens
[ 2 ].OpCode
= OPCODE_ARRAY_CLOSE
;
2781 mxImpl
->setFormula( rContext
, aTokens
);
2784 void FormulaParser::convertNameToFormula( FormulaContext
& rContext
, sal_Int32 nTokenIndex
) const
2786 if( nTokenIndex
>= 0 )
2788 ApiTokenSequence
aTokens( 1 );
2789 aTokens
[ 0 ].OpCode
= OPCODE_NAME
;
2790 aTokens
[ 0 ].Data
<<= nTokenIndex
;
2791 mxImpl
->setFormula( rContext
, aTokens
);
2794 convertErrorToFormula( rContext
, BIFF_ERR_REF
);
2797 void FormulaParser::convertNumberToHyperlink( FormulaContext
& rContext
, const OUString
& rUrl
, double fValue
) const
2799 OSL_ENSURE( rUrl
.getLength() > 0, "FormulaParser::convertNumberToHyperlink - missing URL" );
2800 if( const FunctionInfo
* pFuncInfo
= getFuncInfoFromOobFuncId( OOBIN_FUNC_HYPERLINK
) )
2802 ApiTokenSequence
aTokens( 6 );
2803 aTokens
[ 0 ].OpCode
= pFuncInfo
->mnApiOpCode
;
2804 aTokens
[ 1 ].OpCode
= OPCODE_OPEN
;
2805 aTokens
[ 2 ].OpCode
= OPCODE_PUSH
;
2806 aTokens
[ 2 ].Data
<<= rUrl
;
2807 aTokens
[ 3 ].OpCode
= OPCODE_SEP
;
2808 aTokens
[ 4 ].OpCode
= OPCODE_PUSH
;
2809 aTokens
[ 4 ].Data
<<= fValue
;
2810 aTokens
[ 5 ].OpCode
= OPCODE_CLOSE
;
2811 mxImpl
->setFormula( rContext
, aTokens
);
2815 OUString
FormulaParser::importOleTargetLink( const OUString
& rFormulaString
)
2817 // obviously, this would overburden our formula parser, so we parse it manually
2818 OUString aTargetLink
;
2819 sal_Int32 nFmlaLen
= rFormulaString
.getLength();
2820 if( (nFmlaLen
>= 8) && (rFormulaString
[ 0 ] == '[') )
2822 // passed string is trimmed already
2823 sal_Int32 nBracketClose
= rFormulaString
.indexOf( ']' );
2824 sal_Int32 nExclamation
= rFormulaString
.indexOf( '!' );
2825 if( (nBracketClose
>= 2) &&
2826 (nBracketClose
+ 1 == nExclamation
) &&
2827 (rFormulaString
[ nExclamation
+ 1 ] == '\'') &&
2828 (rFormulaString
[ nFmlaLen
- 1 ] == '\'') )
2830 sal_Int32 nRefId
= rFormulaString
.copy( 1, nBracketClose
- 1 ).toInt32();
2831 aTargetLink
= mxImpl
->resolveOleTarget( nRefId
);
2837 OUString
FormulaParser::importOleTargetLink( RecordInputStream
& rStrm
)
2839 OUString aTargetLink
;
2840 sal_Int32 nFmlaSize
= rStrm
.readInt32();
2841 sal_Int64 nFmlaEndPos
= rStrm
.tell() + ::std::max
< sal_Int32
>( nFmlaSize
, 0 );
2842 if( (nFmlaSize
== 7) && (rStrm
.getRemaining() >= 7) )
2847 rStrm
>> nToken
>> nRefId
>> nNameId
;
2848 if( nToken
== (BIFF_TOKCLASS_VAL
|BIFF_TOKID_NAMEX
) )
2849 aTargetLink
= mxImpl
->resolveOleTarget( nRefId
);
2851 rStrm
.seek( nFmlaEndPos
);
2855 OUString
FormulaParser::importOleTargetLink( BiffInputStream
& rStrm
, const sal_uInt16
* pnFmlaSize
) const
2857 OUString aTargetLink
;
2858 sal_uInt16 nFmlaSize
= lclReadFmlaSize( rStrm
, getBiff(), pnFmlaSize
);
2859 rStrm
.skip( nFmlaSize
);
2863 // ============================================================================