22#include <com/sun/star/sheet/ComplexReference.hpp>
23#include <com/sun/star/sheet/ExternalReference.hpp>
24#include <com/sun/star/sheet/ReferenceFlags.hpp>
25#include <com/sun/star/sheet/SingleReference.hpp>
26#include <com/sun/star/table/CellAddress.hpp>
27#include <osl/diagnose.h>
30#include <oox/token/properties.hxx>
42using namespace ::com::sun::star::sheet::ReferenceFlags;
58 if( rTokens.hasElements() )
60 const ApiToken* pToken = rTokens.getConstArray();
83 if( (orFuncToken.OpCode ==
OPCODE_BAD) && orFuncToken.Data.has< OUString >() )
91 if( (orFuncToken.OpCode ==
OPCODE_EXTERNAL) && (!pLibFuncInfo->maExtProgName.isEmpty()) )
92 orFuncToken.Data <<= pLibFuncInfo->maExtProgName;
94 orFuncToken.Data.clear();
110 if( (pFuncInfo->mnApiOpCode ==
OPCODE_EXTERNAL) && !pFuncInfo->maExtProgName.isEmpty() )
111 orFuncToken.Data <<= pFuncInfo->maExtProgName;
113 else if( (pFuncInfo->mnApiOpCode ==
OPCODE_BAD) && !pFuncInfo->maOoxFuncName.isEmpty() )
114 orFuncToken.Data <<= pFuncInfo->maOoxFuncName;
120 orFuncToken = rECToken;
123 if( (rECToken.OpCode ==
OPCODE_NAME) && rECToken.Data.has< sal_Int32 >() )
126 if( !aDefName.isEmpty() )
129 orFuncToken.Data <<= aDefName;
138 while( pToken < pTokenEnd )
158 OSL_ENSURE( (pToken < pTokenEnd) && (pToken->OpCode ==
OPCODE_OPEN),
"FormulaFinalizer::processParameters - OPCODE_OPEN expected" );
159 if( (pToken < pTokenEnd) && (pToken->OpCode ==
OPCODE_OPEN) )
167 OSL_ENSURE( aParams.size() >= 2,
"FormulaFinalizer::processParameters - missing tokens" );
168 size_t nParamCount = aParams.size() - 1;
170 if( (nParamCount == 1) &&
isEmptyParameter( aParams[ 0 ] + 1, aParams[ 1 ] ) )
179 ParameterPosVector::const_iterator aPosIt = aParams.begin();
192 pRealFuncInfo = pECFuncInfo;
206 size_t nLastValidCount = 0;
207 for(
size_t nParam = 0; nParam < nParamCount; ++nParam, ++aPosIt, ++aParamInfoIt )
216 const ApiToken* pParamBegin = *aPosIt + 1;
217 const ApiToken* pParamEnd = *(aPosIt + 1);
226 while( (pParamBegin < pParamEnd) && (pParamBegin->OpCode ==
OPCODE_SPACES) )
233 OSL_ENSURE( (pParamBegin == pParamEnd) || (pParamBegin->OpCode ==
OPCODE_MISSING),
"FormulaFinalizer::processParameters - OPCODE_MISSING expected" );
234 if( pParamBegin < pParamEnd ) ++pParamBegin;
236 while( (pParamBegin < pParamEnd) && (pParamBegin->OpCode ==
OPCODE_SPACES) )
254 nLastValidCount = nParam + 1;
283 if( (rFuncNameToken.OpCode ==
OPCODE_EXTERNAL) && !rFuncNameToken.Data.hasValue() )
291 while( (pToken < pTokenEnd) && (pToken->OpCode ==
OPCODE_SPACES) ) ++pToken;
292 if( (pToken < pTokenEnd) && (pToken->OpCode ==
OPCODE_MISSING) ) ++pToken;
293 while( (pToken < pTokenEnd) && (pToken->OpCode ==
OPCODE_SPACES) ) ++pToken;
294 return pToken == pTokenEnd;
299 const ApiToken* pSingleToken =
nullptr;
301 while( (pToken < pTokenEnd) && (pToken->OpCode ==
OPCODE_SPACES) ) ++pToken;
303 if( pToken < pTokenEnd ) pSingleToken = pToken++;
305 while( (pToken < pTokenEnd) && (pToken->OpCode ==
OPCODE_SPACES) ) ++pToken;
307 return (pToken == pTokenEnd) ? pSingleToken :
nullptr;
313 OSL_ENSURE( (pToken < pTokenEnd) && (pToken->OpCode ==
OPCODE_OPEN),
"skipParentheses - OPCODE_OPEN expected" );
315 while( (pToken < pTokenEnd) && (pToken->OpCode !=
OPCODE_CLOSE) )
323 OSL_ENSURE( ((pToken < pTokenEnd) && (pToken->OpCode ==
OPCODE_CLOSE)) || ((pTokenEnd - 1)->OpCode ==
OPCODE_BAD),
"skipParentheses - OPCODE_CLOSE expected" );
324 return (pToken < pTokenEnd) ? (pToken + 1) : pTokenEnd;
331 OSL_ENSURE( (pToken < pTokenEnd) && (pToken->OpCode ==
OPCODE_OPEN),
"FormulaFinalizer::findParameters - OPCODE_OPEN expected" );
332 rParams.push_back( pToken++ );
335 while( (pToken < pTokenEnd) && (pToken->OpCode !=
OPCODE_CLOSE) )
340 rParams.push_back( pToken++ );
346 OSL_ENSURE( ((pToken < pTokenEnd) && (pToken->OpCode ==
OPCODE_CLOSE)) || ((pTokenEnd - 1)->OpCode ==
OPCODE_BAD),
"FormulaFinalizer::findParameters - OPCODE_CLOSE expected" );
347 rParams.push_back( pToken );
348 return (pToken < pTokenEnd) ? (pToken + 1) : pTokenEnd;
359 if( (nParam == 1) || (nParam == 2) )
376 if (nParam == 2 && nParamCount < 3)
390 if( nParamCount == 1 )
402 bool bValid = (rToken.OpCode !=
OPCODE_MACRO) || rToken.Data.hasValue();
426 const OUString& rFormulaString );
467 template<
typename Type >
469 template<
typename Type >
481 template<
typename Type >
483 template<
typename Type >
492 template<
typename Type >
499 bool pushDdeLinkOperand(
const OUString& rDdeServer,
const OUString& rDdeTopic,
const OUString& rDdeItem );
514 static void initReference3d( SingleReference& orApiRef, sal_Int32 nSheet,
bool bSameSheet );
519 void convertReference3d( SingleReference& orApiRef, sal_Int32 nSheet,
bool bSameSheet,
const BinSingleRef2d& rRef,
bool bDeleted,
bool bRelativeAsOffset )
const;
551 mnMaxApiCol( rParent.getAddressConverter().getMaxApiAddress().
Col() ),
552 mnMaxApiRow( rParent.getAddressConverter().getMaxApiAddress().
Row() ),
553 mnMaxXlsCol( rParent.getAddressConverter().getMaxXlsAddress().
Col() ),
554 mnMaxXlsRow( rParent.getAddressConverter().getMaxXlsAddress().
Row() ),
555 mbRelativeAsOffset( false ),
556 mb2dRefsAs3dRefs( false ),
557 mbSpecialTokens( false )
570 OSL_FAIL(
"FormulaParserImpl::importOoxFormula - not implemented" );
576 SAL_WARN(
"sc.filter",
"FormulaParserImpl::importBiff12Formula - not implemented" );
619 if( aTokens.hasElements() )
621 ApiToken* pToken = aTokens.getArray();
643 OSL_ENSURE(
nCount >= 0,
"FormulaParserImpl::appendSpaces - negative count" );
645 orSpaces.emplace_back(
nCount, bLineFeed );
683 for(
const auto& rSpace : *pSpaces )
685 return pSpaces ? pSpaces->size() : 0;
691 for(
const auto& rSpace : *pSpaces )
693 return pSpaces ? pSpaces->size() : 0;
699 "FormulaParserImpl::getOperandSize - invalid parameters" );
710 OSL_ENSURE( !
maOperandSizeStack.empty(),
"FormulaParserImpl::popOperandSize - invalid call" );
719 "FormulaParserImpl::getOperandToken - invalid parameters" );
721 for(
auto aEnd =
maOperandSizeStack.cend(), aIt = aEnd - 1 + nOpIndex; aIt != aEnd; ++aIt )
734template<
typename Type >
816 for(
size_t nParam = 1; bOk && (nParam < nParamCount); ++nParam )
845template<
typename Type >
855 return pushValueOperand< double >( bValue ? 1.0 : 0.0 );
885 SingleReference aApiRef;
892 ComplexReference aApiRef;
897template<
typename Type >
902 ExternalReference aApiExtRef;
904 aApiExtRef.Reference <<= rApiRef;
915 ComplexReference aApiRef;
919 SingleReference aApiRef;
926 ComplexReference aApiRef;
940 if( !rxDefName || rxDefName->getModelName().isEmpty() )
942 if( rxDefName->isMacroFunction() )
944 if( rxDefName->getTokenIndex() >= 0 )
981 OUString aDdeServer, aDdeTopic, aDdeItem;
982 if( rxExtName->getDdeLinkData( aDdeServer, aDdeTopic, aDdeItem ) )
1040 orApiRef.Flags = SHEET_RELATIVE;
1043 orApiRef.RelativeSheet = 0;
1049 orApiRef.Flags = SHEET_3D;
1053 orApiRef.Flags |= SHEET_DELETED;
1055 else if( bSameSheet )
1057 OSL_ENSURE( nSheet == 0,
"FormulaParserImpl::initReference3d - invalid sheet index" );
1058 orApiRef.Flags |= SHEET_RELATIVE;
1059 orApiRef.RelativeSheet = 0;
1063 orApiRef.Sheet = nSheet;
1071 orApiRef.Column = 0;
1074 orApiRef.Flags |= COLUMN_DELETED | ROW_DELETED;
1081 (rRef.
mbColRel ? orApiRef.RelativeColumn : orApiRef.Column) = rRef.
mnCol;
1082 (rRef.
mbRowRel ? orApiRef.RelativeRow : orApiRef.Row) = rRef.
mnRow;
1084 if( !bRelativeAsOffset )
1096 convertReference( orApiRef.Reference1, rRef1, bDeleted, bRelativeAsOffset );
1097 convertReference( orApiRef.Reference2, rRef2, bDeleted, bRelativeAsOffset );
1100 if( !bDeleted && !rRef1.
mbColRel && !rRef2.
mbColRel && (orApiRef.Reference1.Column == 0) && (orApiRef.Reference2.Column ==
mnMaxXlsCol) )
1102 if( !bDeleted && !rRef1.
mbRowRel && !rRef2.
mbRowRel && (orApiRef.Reference1.Row == 0) && (orApiRef.Reference2.Row ==
mnMaxXlsRow) )
1118 setFlag( orApiRef.Reference2.Flags, SHEET_3D,
false );
1144 sal_Int32 nBracketOpen = rTokenData.indexOf(
'[' );
1145 sal_Int32 nBracketClose = rTokenData.indexOf(
']' );
1146 sal_Int32 nExclamation = rTokenData.indexOf(
'!' );
1147 if( (0 == nBracketOpen) && (nBracketOpen + 1 < nBracketClose) && (nBracketClose + 1 == nExclamation) && (nExclamation + 1 < rTokenData.getLength()) )
1149 sal_Int32 nRefId =
o3tl::toInt32(rTokenData.subView( nBracketOpen + 1, nBracketClose - nBracketOpen - 1 ));
1153 OUString aFuncName = rTokenData.copy( nExclamation + 1 ).toAsciiUpperCase();
1165 return pDefName->getCalcName();
1176 explicit OoxFormulaParserImpl(
const FormulaParser& rParent );
1180 const OUString& rFormulaString )
override;
1195 bool importAreaToken(
SequenceInputStream& rStrm,
bool bDeleted,
bool bRelativeAsOffset );
1196 bool importRef3dToken(
SequenceInputStream& rStrm,
bool bDeleted,
bool bRelativeAsOffset );
1197 bool importArea3dToken(
SequenceInputStream& rStrm,
bool bDeleted,
bool bRelativeAsOffset );
1213 bool pushBiff12Name( sal_Int32 nNameId );
1214 bool pushBiff12ExtName( sal_Int32 nRefId, sal_Int32 nNameId );
1215 bool pushBiff12Function( sal_uInt16 nFuncId );
1216 bool pushBiff12Function( sal_uInt16 nFuncId,
sal_uInt8 nParamCount );
1226OoxFormulaParserImpl::OoxFormulaParserImpl(
const FormulaParser& rParent ) :
1227 FormulaParserImpl( rParent ),
1228 maApiParser( rParent.getBaseFilter().getModelFactory(), rParent ),
1238 maApiParser.getParserProperties().setProperty( PROP_ExternalLinks, getExternalLinks().getLinkInfos() );
1241 return finalizeTokenArray(
maApiParser.parseFormula( rFormulaString, rBaseAddr ) );
1246 initializeImport( rBaseAddr, eType );
1248 sal_Int32 nFmlaSize =
rStrm.readInt32();
1249 sal_Int64 nFmlaPos =
rStrm.tell();
1250 sal_Int64 nFmlaEndPos = nFmlaPos + nFmlaSize;
1252 rStrm.seek( nFmlaEndPos );
1253 sal_Int32 nAddDataSize =
rStrm.readInt32();
1255 sal_Int64 nAddDataEndPos =
mnAddDataPos + nAddDataSize;
1256 rStrm.seek( nFmlaPos );
1258 bool bOk = (nFmlaSize >= 0) && (nAddDataSize >= 0);
1259 bool bRelativeAsOffset = mbRelativeAsOffset;
1261 while( bOk && !
rStrm.isEof() && (
rStrm.tell() < nFmlaEndPos) )
1264 nTokenId =
rStrm.readuChar();
1274 case BIFF_TOKID_ADD: bOk = pushBinaryOperator( OPCODE_ADD );
break;
1275 case BIFF_TOKID_SUB: bOk = pushBinaryOperator( OPCODE_SUB );
break;
1276 case BIFF_TOKID_MUL: bOk = pushBinaryOperator( OPCODE_MULT );
break;
1277 case BIFF_TOKID_DIV: bOk = pushBinaryOperator( OPCODE_DIV );
break;
1280 case BIFF_TOKID_LT: bOk = pushBinaryOperator( OPCODE_LESS );
break;
1281 case BIFF_TOKID_LE: bOk = pushBinaryOperator( OPCODE_LESS_EQUAL );
break;
1282 case BIFF_TOKID_EQ: bOk = pushBinaryOperator( OPCODE_EQUAL );
break;
1283 case BIFF_TOKID_GE: bOk = pushBinaryOperator( OPCODE_GREATER_EQUAL );
break;
1284 case BIFF_TOKID_GT: bOk = pushBinaryOperator( OPCODE_GREATER );
break;
1285 case BIFF_TOKID_NE: bOk = pushBinaryOperator( OPCODE_NOT_EQUAL );
break;
1286 case BIFF_TOKID_ISECT: bOk = pushBinaryOperator( OPCODE_INTERSECT );
break;
1289 case BIFF_TOKID_UPLUS: bOk = pushUnaryPreOperator( OPCODE_PLUS_SIGN );
break;
1294 case BIFF_TOKID_STR: bOk = pushValueOperand( BiffHelper::readString( rStrm,
false ) );
break;
1301 default: bOk =
false;
1313 case BIFF_TOKID_REF: bOk = importRefToken( rStrm,
false,
false );
break;
1314 case BIFF_TOKID_AREA: bOk = importAreaToken( rStrm,
false,
false );
break;
1321 case BIFF_TOKID_REFN: bOk = importRefToken( rStrm,
false,
true );
break;
1326 case BIFF_TOKID_REF3D: bOk = importRef3dToken( rStrm,
false, bRelativeAsOffset );
break;
1327 case BIFF_TOKID_AREA3D: bOk = importArea3dToken( rStrm,
false, bRelativeAsOffset );
break;
1328 case BIFF_TOKID_REFERR3D: bOk = importRef3dToken( rStrm,
true, bRelativeAsOffset );
break;
1330 default: bOk =
false;
1338 aFinalTokens = finalizeImport();
1341 if( (nFmlaSize >= 0) && (nAddDataSize >= 0) )
1342 rStrm.seek( nAddDataEndPos );
1345 return aFinalTokens;
1350bool OoxFormulaParserImpl::importAttrToken( SequenceInputStream& rStrm )
1375 bOk = importSpaceToken( rStrm );
1383bool OoxFormulaParserImpl::importSpaceToken( SequenceInputStream& rStrm )
1392 appendLeadingSpaces( nCount,
false );
1395 appendLeadingSpaces( nCount,
true );
1398 appendOpeningSpaces( nCount,
false );
1401 appendOpeningSpaces( nCount,
true );
1404 appendClosingSpaces( nCount,
false );
1407 appendClosingSpaces( nCount,
true );
1413bool OoxFormulaParserImpl::importTableToken( SequenceInputStream& rStrm )
1415 sal_uInt16 nFlags, nTableId, nCol1, nCol2;
1417 nFlags =
rStrm.readuInt16();
1418 nTableId =
rStrm.readuInt16();
1420 nCol1 =
rStrm.readuInt16();
1421 nCol2 =
rStrm.readuInt16();
1422 TableRef xTable = getTables().getTable( nTableId );
1423 sal_Int32 nTokenIndex = xTable ? xTable->getTokenIndex() : -1;
1424 if( nTokenIndex >= 0 )
1426 sal_Int32 nWidth = xTable->getWidth();
1427 sal_Int32 nHeight = xTable->getHeight();
1428 sal_Int32 nStartCol = 0;
1429 sal_Int32 nEndCol = nWidth - 1;
1430 sal_Int32 nStartRow = 0;
1431 sal_Int32 nEndRow = nHeight - 1;
1432 bool bFixedStartRow =
true;
1433 bool bFixedHeight =
false;
1437 bool bValidRef = !bSingleCol || !bColRange;
1438 OSL_ENSURE( bValidRef,
"OoxFormulaParserImpl::importTableToken - illegal combination of single column and column range" );
1442 nStartCol = nEndCol = nCol1;
1443 else if( bColRange )
1444 { nStartCol = nCol1; nEndCol = nCol2; }
1445 bValidRef = (nStartCol <= nEndCol) && (nEndCol < nWidth);
1446 OSL_ENSURE( bValidRef,
"OoxFormulaParserImpl::importTableToken - invalid column range" );
1457 sal_Int32 nStartDataRow = xTable->getHeaderRows();
1458 sal_Int32 nEndDataRow = nEndRow - xTable->getTotalsRows();
1459 bValidRef = (nStartRow <= nStartDataRow) && (nStartDataRow <= nEndDataRow) && (nEndDataRow <= nEndRow);
1460 OSL_ENSURE( bValidRef,
"OoxFormulaParserImpl::importTableToken - invalid data row range" );
1465 bValidRef = !bHeaderRows && !bDataRows && !bTotalsRows && !bThisRow;
1466 OSL_ENSURE( bValidRef,
"OoxFormulaParserImpl::importTableToken - unexpected flags in [#All] table token" );
1468 else if( bHeaderRows )
1470 bValidRef = !bTotalsRows && !bThisRow;
1471 OSL_ENSURE( bValidRef,
"OoxFormulaParserImpl::importTableToken - unexpected flags in [#Headers] table token" );
1472 nEndRow = bDataRows ? nEndDataRow : (nStartDataRow - 1);
1473 bFixedHeight = !bDataRows;
1475 else if( bDataRows )
1477 bValidRef = !bThisRow;
1478 OSL_ENSURE( bValidRef,
"OoxFormulaParserImpl::importTableToken - unexpected flags in [#Data] table token" );
1479 nStartRow = nStartDataRow;
1480 if( !bTotalsRows ) nEndRow = nEndDataRow;
1482 else if( bTotalsRows )
1484 bValidRef = !bThisRow;
1485 OSL_ENSURE( bValidRef,
"OoxFormulaParserImpl::importTableToken - unexpected flags in [#Totals] table token" );
1486 nStartRow = nEndDataRow + 1;
1487 bFixedStartRow =
false;
1488 bFixedHeight = !bDataRows;
1492 nStartRow = nEndRow = maBaseAddr.Row() - xTable->getRange().aStart.Row();
1493 bFixedHeight =
true;
1498 nStartRow = nStartDataRow;
1499 nEndRow = nEndDataRow;
1503 bValidRef = (0 <= nStartRow) && (nStartRow <= nEndRow) && (nEndRow < nHeight);
1508 if( (nStartCol == 0) && (nEndCol + 1 == nWidth) && (nStartRow == 0) && (nEndRow + 1 == nHeight) )
1509 return pushValueOperand( nTokenIndex, OPCODE_DBAREA );
1511 const FunctionInfo* pRowsInfo = getFuncInfoFromBiff12FuncId(
BIFF_FUNC_ROWS );
1512 const FunctionInfo* pColumnsInfo = getFuncInfoFromBiff12FuncId(
BIFF_FUNC_COLUMNS );
1514 pRowsInfo && pColumnsInfo &&
1515 pushValueOperandToken( nTokenIndex, OPCODE_DBAREA ) &&
1517 pushValueOperandToken< double >( nStartRow ) :
1518 (pushValueOperandToken( nTokenIndex, OPCODE_DBAREA ) &&
1519 pushFunctionOperatorToken( *pRowsInfo, 1 ) &&
1520 pushValueOperandToken< double >( nHeight - nStartRow ) &&
1521 pushBinaryOperatorToken( OPCODE_SUB ))) &&
1522 pushValueOperandToken< double >( nStartCol ) &&
1524 pushValueOperandToken< double >( nEndRow - nStartRow + 1 ) :
1525 (pushValueOperandToken( nTokenIndex, OPCODE_DBAREA ) &&
1526 pushFunctionOperatorToken( *pRowsInfo, 1 ) &&
1527 (((nStartRow == 0) && (nEndRow + 1 == nHeight)) ||
1528 (pushValueOperandToken< double >( nHeight - (nEndRow - nStartRow + 1) ) &&
1529 pushBinaryOperatorToken( OPCODE_SUB ))))) &&
1530 (((nStartCol == 0) && (nEndCol + 1 == nWidth)) ?
1531 (pushValueOperandToken( nTokenIndex, OPCODE_DBAREA ) &&
1532 pushFunctionOperatorToken( *pColumnsInfo, 1 )) :
1533 pushValueOperandToken< double >( nEndCol - nStartCol + 1 )) &&
1540bool OoxFormulaParserImpl::importArrayToken( SequenceInputStream& rStrm )
1545 pushOperand( OPCODE_ARRAY_OPEN );
1546 size_t nOpSize = popOperandSize();
1547 size_t nOldArraySize = getFormulaSize();
1550 swapStreamPosition( rStrm );
1551 sal_Int32 nRows =
rStrm.readInt32();
1552 sal_Int32 nCols =
rStrm.readInt32();
1553 OSL_ENSURE( (nCols > 0) && (nRows > 0),
"OoxFormulaParserImpl::importArrayToken - empty array" );
1556 for( sal_Int32 nRow = 0; !
rStrm.isEof() && (nRow < nRows); ++nRow )
1559 appendRawToken( OPCODE_ARRAY_ROWSEP );
1560 for( sal_Int32 nCol = 0; !
rStrm.isEof() && (nCol < nCols); ++nCol )
1563 appendRawToken( OPCODE_ARRAY_COLSEP );
1564 switch(
rStrm.readuInt8() )
1567 appendRawToken( OPCODE_PUSH ) <<=
rStrm.readDouble();
1570 appendRawToken( OPCODE_PUSH ) <<= BiffHelper::readString( rStrm,
false );
1576 appendRawToken( OPCODE_PUSH ) <<= BiffHelper::calcDoubleFromError(
rStrm.readuInt8() );
1580 OSL_FAIL(
"OoxFormulaParserImpl::importArrayToken - unknown data type" );
1581 appendRawToken( OPCODE_PUSH ) <<= BiffHelper::calcDoubleFromError(
BIFF_ERR_NA );
1585 swapStreamPosition( rStrm );
1588 appendRawToken( OPCODE_ARRAY_CLOSE );
1589 pushOperandSize( nOpSize + getFormulaSize() - nOldArraySize );
1593bool OoxFormulaParserImpl::importRefToken( SequenceInputStream& rStrm,
bool bDeleted,
bool bRelativeAsOffset )
1595 BinSingleRef2d aRef;
1596 aRef.readBiff12Data( rStrm, bRelativeAsOffset );
1597 return pushReferenceOperand( aRef, bDeleted, bRelativeAsOffset );
1600bool OoxFormulaParserImpl::importAreaToken( SequenceInputStream& rStrm,
bool bDeleted,
bool bRelativeAsOffset )
1602 BinComplexRef2d aRef;
1603 aRef.readBiff12Data( rStrm, bRelativeAsOffset );
1604 return pushReferenceOperand( aRef, bDeleted, bRelativeAsOffset );
1607bool OoxFormulaParserImpl::importRef3dToken( SequenceInputStream& rStrm,
bool bDeleted,
bool bRelativeAsOffset )
1609 LinkSheetRange aSheetRange = readSheetRange( rStrm );
1610 BinSingleRef2d aRef;
1611 aRef.readBiff12Data( rStrm, bRelativeAsOffset );
1612 return pushReferenceOperand( aSheetRange, aRef, bDeleted, bRelativeAsOffset );
1615bool OoxFormulaParserImpl::importArea3dToken( SequenceInputStream& rStrm,
bool bDeleted,
bool bRelativeAsOffset )
1617 LinkSheetRange aSheetRange = readSheetRange( rStrm );
1618 BinComplexRef2d aRef;
1619 aRef.readBiff12Data( rStrm, bRelativeAsOffset );
1620 return pushReferenceOperand( aSheetRange, aRef, bDeleted, bRelativeAsOffset );
1623bool OoxFormulaParserImpl::importMemAreaToken( SequenceInputStream& rStrm,
bool bAddData )
1627 skipMemAreaAddData( rStrm );
1631bool OoxFormulaParserImpl::importMemFuncToken( SequenceInputStream& rStrm )
1637bool OoxFormulaParserImpl::importNameToken( SequenceInputStream& rStrm )
1639 return pushBiff12Name(
rStrm.readInt32() );
1642bool OoxFormulaParserImpl::importNameXToken( SequenceInputStream& rStrm )
1644 sal_Int32 nRefId =
rStrm.readInt16();
1645 sal_Int32 nNameId =
rStrm.readInt32();
1646 return pushBiff12ExtName( nRefId, nNameId );
1649bool OoxFormulaParserImpl::importFuncToken( SequenceInputStream& rStrm )
1652 nFuncId =
rStrm.readuInt16();
1653 return pushBiff12Function( nFuncId );
1656bool OoxFormulaParserImpl::importFuncVarToken( SequenceInputStream& rStrm )
1660 nParamCount =
rStrm.readuChar();
1661 nFuncId =
rStrm.readuInt16();
1662 return pushBiff12Function( nFuncId, nParamCount );
1665bool OoxFormulaParserImpl::importExpToken( SequenceInputStream& rStrm )
1667 BinAddress aBaseAddr;
1668 aBaseAddr.mnRow =
rStrm.readInt32();
1669 swapStreamPosition( rStrm );
1670 aBaseAddr.mnCol =
rStrm.readInt32();
1671 swapStreamPosition( rStrm );
1672 return pushSpecialTokenOperand( aBaseAddr );
1675LinkSheetRange OoxFormulaParserImpl::readSheetRange( SequenceInputStream& rStrm )
1677 return getExternalLinks().getSheetRange(
rStrm.readInt16() );
1680void OoxFormulaParserImpl::swapStreamPosition( SequenceInputStream& rStrm )
1682 sal_Int64 nRecPos =
rStrm.tell();
1687void OoxFormulaParserImpl::skipMemAreaAddData( SequenceInputStream& rStrm )
1689 swapStreamPosition( rStrm );
1691 swapStreamPosition( rStrm );
1696bool OoxFormulaParserImpl::pushBiff12Name( sal_Int32 nNameId )
1699 return pushDefinedNameOperand( getDefinedNames().getByIndex( nNameId - 1 ) );
1702bool OoxFormulaParserImpl::pushBiff12ExtName( sal_Int32 nRefId, sal_Int32 nNameId )
1704 if(
const ExternalLink* pExtLink = getExternalLinks().getExternalLink( nRefId ).
get() )
1706 if( pExtLink->getLinkType() == ExternalLinkType::Self )
1707 return pushBiff12Name( nNameId );
1710 return pushExternalNameOperand( xExtName, *pExtLink );
1715bool OoxFormulaParserImpl::pushBiff12Function( sal_uInt16 nFuncId )
1717 if(
const FunctionInfo* pFuncInfo = getFuncInfoFromBiff12FuncId( nFuncId ) )
1718 if( pFuncInfo->mnMinParamCount == pFuncInfo->mnMaxParamCount )
1719 return pushFunctionOperator( *pFuncInfo, pFuncInfo->mnMinParamCount );
1720 return pushFunctionOperator( OPCODE_NONAME, 0 );
1723bool OoxFormulaParserImpl::pushBiff12Function( sal_uInt16 nFuncId,
sal_uInt8 nParamCount )
1727 if(
const FunctionInfo* pFuncInfo = getFuncInfoFromBiff12FuncId( nFuncId ) )
1728 return pushFunctionOperator( *pFuncInfo, nParamCount );
1729 return pushFunctionOperator( OPCODE_NONAME, nParamCount );
1736bool lclExtractRefId( sal_Int32& rnRefId, OUString& rRemainder, std::u16string_view aFormulaString )
1738 if( (aFormulaString.size() >= 4) && (aFormulaString[ 0 ] ==
'[') )
1740 size_t nBracketClose = aFormulaString.find(
']', 1 );
1741 if( nBracketClose != std::u16string_view::npos && nBracketClose >= 2 )
1743 rnRefId =
o3tl::toInt32(aFormulaString.substr( 1, nBracketClose - 1 ));
1744 rRemainder = aFormulaString.substr( nBracketClose + 1 );
1745 return !rRemainder.isEmpty();
1756 mxImpl.reset(
new OoxFormulaParserImpl( *
this ) );
1765 return mxImpl->importOoxFormula( rBaseAddress, rFormulaString );
1775 sal_Int32 nRefId = -1;
1776 OUString aRemainder;
1777 if( lclExtractRefId( nRefId, aRemainder, aFormulaString ) && (aRemainder.getLength() >= 3) &&
1778 (aRemainder[ 0 ] ==
'!') && (aRemainder[ 1 ] ==
'\'') && (aRemainder[ aRemainder.getLength() - 1 ] ==
'\'') )
1779 return mxImpl->resolveOleTarget( nRefId,
false );
1785 OUString aTargetLink;
1786 sal_Int32 nFmlaSize =
rStrm.readInt32();
1787 sal_Int64 nFmlaEndPos =
rStrm.tell() + ::std::max< sal_Int32 >( nFmlaSize, 0 );
1788 if( (nFmlaSize == 7) && (
rStrm.getRemaining() >= 7) )
1791 sal_Int16 nRefId =
rStrm.readInt16();
1794 aTargetLink =
mxImpl->resolveOleTarget( nRefId,
true );
1796 rStrm.seek( nFmlaEndPos );
1824 OUString aRemainder(aFormulaString);
1825 if (aRemainder.indexOf(
'!') == -1)
1828 sal_Int32 nRefId = -1;
1829 if( lclExtractRefId( nRefId, aRemainder, aFormulaString ) && (aRemainder.getLength() > 1) && (aRemainder[ 0 ] ==
'!') )
1842 OSL_ENSURE( pExtLink,
"FormulaParser::importMacroName - missing link" );
1847 OUString aMacroName = aRemainder.copy( 1 );
1849 if( !pDefName || pDefName->
isVBName() )
OUString getAbsoluteUrl(const OUString &rUrl) const
A vector of formula tokens with additional convenience functions.
ApiTokenSequence toSequence() const
Converts to a sequence.
css::uno::Any & append(sal_Int32 nOpCode)
Appends a new token with the passed op-code, returns its data field.
void push_back(const ApiToken &rToken)
static double calcDoubleFromError(sal_uInt8 nErrorCode)
Converts the passed BIFF error to a double containing the respective Calc error code.
Base class for defined names and external names.
const OUString & getModelName() const
Returns the original name as imported from or exported to the file.
bool isVBName() const
Returns true, if this defined name is a reference to a VBA macro.
DefinedNameRef getByModelName(const OUString &rModelName, sal_Int16 nCalcSheet=-1) const
Returns a defined name by its model name.
ExternalLinkRef getExternalLink(sal_Int32 nRefId, bool bUseRefSheets=true) const
Returns the external link for the passed reference identifier.
ExternalLinkType getLinkType() const
Returns the type of this external link.
FunctionLibraryType getFuncLibraryType() const
Returns the type of the external library if this is a library link.
const OUString & getTargetUrl() const
Returns the target URL of this external link.
Iterator working on the mpParamInfos member of the FunctionInfo struct.
bool isCalcOnlyParam() const
bool isExcelOnlyParam() const
const FunctionInfo * getFuncInfoFromBiff12FuncId(sal_uInt16 nFuncId) const
Returns the function info for a BIFF12 function index, or 0 on error.
const FunctionInfo * getFuncInfoFromOoxFuncName(const OUString &rFuncName) const
Returns the function info for an OOXML function name, or 0 on error.
Contains indexes for a range of sheets in the spreadsheet document.
sal_Int32 getLastSheet() const
bool isExternal() const
Returns true, if the sheet range points to an external document.
sal_Int32 getFirstSheet() const
sal_Int32 getDocLinkIndex() const
bool is3dRange() const
Returns true, if the sheet indexes are valid and different.
bool isSameSheet() const
Returns true, if the sheet indexes are valid and different.
Provides access to API op-codes for all available formula tokens and to function info structs for all...
const FunctionInfo * getFuncInfoFromApiToken(const ApiToken &rToken) const
Returns the function info for an API token, or 0 on error.
Helper class to provide access to global workbook data.
DefinedNamesBuffer & getDefinedNames() const
Returns the defined names read from the workbook globals.
::oox::core::FilterBase & getBaseFilter() const
Returns the base filter object (base class of all filters).
ExternalLinkBuffer & getExternalLinks() const
Returns the external links read from the external links substream.
#define SAL_WARN_IF(condition, area, stream)
#define SAL_WARN(area, stream)
sal_Int32 toInt32(std::u16string_view str, sal_Int16 radix=10)
const sal_uInt8 BIFF_TOKID_MEMFUNC
Constant reference subexpression without result.
const sal_uInt8 BIFF_TOKID_LT
String concatenation operator.
const sal_uInt8 BIFF_TOKID_LIST
Intersection operator.
const sal_uInt16 BIFF_FUNC_EXTERNCALL
Function identifier of the OFFSET function.
css::sheet::FormulaToken ApiToken
const sal_uInt8 BIFF_TOK_ATTR_CHOOSE
Start of true condition in IF function.
const sal_uInt8 BIFF_TOKID_GE
Equal operator.
const sal_uInt8 BIFF_TOKID_RANGE
List operator.
const sal_uInt16 BIFF_FUNC_SUM
Function identifier of the IF function.
const sal_uInt8 BIFF_TOK_ATTR_SKIP
Jump array of CHOOSE function.
const sal_uInt8 BIFF_TOKID_REFN
Deleted 2D area reference.
const sal_uInt8 BIFF_TOKID_UMINUS
Unary plus.
const sal_uInt8 BIFF_TOK_ATTR_SPACE_BR
Spaces before next token.
std::shared_ptr< ExternalName > ExternalNameRef
const sal_uInt16 BIFF_FUNC_COLUMNS
Function identifier of the ROWS function.
const sal_uInt16 BIFF12_TOK_TABLE_COLRANGE
Table reference: Single column.
const sal_uInt8 BIFF_TOKID_NAMEX
const sal_uInt16 BIFF_FUNC_TRUE
Function identifier of the SUM function.
const sal_uInt8 BIFF_TOKID_AREAERR
Deleted 2D cell reference.
const sal_uInt8 BIFF_TOKID_NE
Greater than operator.
const sal_uInt8 BIFF_TOK_ATTR_VOLATILE
TRUE value of a tBool token.
const sal_uInt16 BIFF12_TOK_TABLE_DATA
Table reference: Special [#Headers] range.
const sal_uInt8 BIFF_TOKID_REF3D
External reference.
css::uno::Sequence< ApiToken > ApiTokenSequence
const sal_uInt8 BIFF_TOK_ATTR_ASSIGN
SUM function with one parameter.
const sal_uInt8 BIFF_TOKID_REFERR
Variable reference subexpression.
const sal_uInt16 BIFF12_TOK_TABLE_TOTALS
Table reference: Special [#Data] range.
const sal_uInt8 BIFF_TOKID_AREAN
Relative 2D cell reference (in names).
const sal_uInt8 BIFF_TOKID_ATTR
Natural language reference (NLR).
const sal_uInt8 BIFF_TOKID_EXP
Placeholder for invalid token id.
const sal_uInt8 BIFF_TOKID_ISECT
Not equal operator.
const sal_uInt8 BIFF_ERR_NA
css::beans::Pair< css::table::CellAddress, sal_Bool > ApiSpecialTokenInfo
Contains the base address and type of a special token representing an array formula or a shared formu...
std::shared_ptr< Table > TableRef
const sal_uInt8 BIFF_TOKID_SUB
Addition operator.
const sal_uInt8 BIFF_TOKID_NAME
Function, variable number of arguments.
FormulaType
Function identifier of the WEEKNUM function.
@ CondFormat
Shared formula definition.
@ Validation
Condition of a conditional format rule.
@ Array
Simple cell formula, or reference to a shared formula name.
@ SharedFormula
Array (matrix) formula.
const sal_uInt16 BIFF_FUNC_FLOOR
BIFF function id of the EXTERN.CALL function.
const sal_uInt8 BIFF_TOKID_INT
Boolean constant.
const sal_uInt8 BIFF_TOKID_MEMNOMEM
Deleted reference subexpression.
const sal_uInt8 BIFF_TOKID_FUNCVAR
Function, fixed number of arguments.
const sal_uInt16 BIFF12_TOK_TABLE_HEADERS
Table reference: Special [#All] range.
const sal_uInt8 BIFF_TOKID_MUL
Subtraction operator.
const sal_uInt8 BIFF_TOK_ATTR_SPACE
BASIC style assignment.
const sal_uInt8 BIFF_TOKID_GT
Greater than or equal operator.
const sal_uInt8 BIFF_TOK_ATTR_SPACE_BR_CLOSE
Spaces before closing parenthesis.
const sal_uInt8 BIFF_TOK_ARRAY_DOUBLE
Deleted 3D area reference.
const sal_uInt8 BIFF_TOKID_AREAERR3D
Deleted 3D cell reference.
const sal_uInt8 BIFF_TOKID_REFERR3D
3D area reference.
const sal_uInt8 BIFF_TOKID_MEMAREAN
Relative 2D area reference (in names).
const sal_uInt8 BIFF_TOKID_AREA
2D cell reference.
const sal_uInt8 BIFF_TOK_ATTR_IFERROR
Leading spaces and volatile formula.
const sal_uInt8 BIFF_TOK_ATTR_SPACE_VOLATILE
Spaces in formula representation.
const sal_uInt8 BIFF_TOKID_LE
Less than operator.
const sal_uInt8 BIFF_TOKID_ERR
End of a sheet reference (BIFF2-BIFF4).
const sal_uInt8 BIFF_TOKID_AREA3D
3D cell reference.
std::shared_ptr< DefinedName > DefinedNameRef
const sal_uInt8 BIFF_TOKID_EQ
Less than or equal operator.
const sal_uInt8 BIFF_TOKID_CONCAT
Power operator.
const sal_uInt8 BIFF_TOKID_PAREN
Percent sign.
const sal_uInt8 BIFF_TOK_ARRAY_BOOL
String value in an array.
@ Library
Just for round-tripping (FIXME: Functionality not actually implemented after all.)
@ External
Link refers to the current sheet.
@ DDE
Link refers to an external add-in.
const sal_uInt8 BIFF_TOKID_PERCENT
Unary minus.
const sal_uInt8 BIFF_TOKID_MISSARG
Parentheses.
const sal_uInt8 BIFF_TOKCLASS_VAL
20-3F: Reference class tokens.
const sal_uInt8 BIFF_TOKID_MEMERR
Constant reference subexpression.
const sal_uInt8 BIFF_TOKID_REF
Defined name.
const sal_uInt8 BIFF_TOKID_FUNC
Array constant.
const sal_uInt16 BIFF_FUNC_OFFSET
Function identifier of the COLUMNS function.
const sal_uInt16 BIFF12_TOK_TABLE_THISROW
Table reference: Special [#Totals] range.
const sal_uInt8 BIFF_TOKID_MASK
This bit must be null for a valid token identifier.
const sal_uInt8 BIFF_TOK_ARRAY_ERROR
Boolean value in an array.
const sal_uInt8 BIFF_TOK_ATTR_SPACE_BR_OPEN
Spaces before opening parenthesis.
const sal_uInt8 BIFF_ERR_NAME
const sal_uInt16 BIFF_FUNC_CEILING
Function identifier of the FLOOR function.
const sal_uInt16 BIFF_FUNC_FALSE
Function identifier of the TRUE function.
const sal_uInt8 BIFF_TOK_ATTR_SPACE_SP
Start of condition in IFERROR function (BIFF12 only).
const sal_uInt16 BIFF_FUNC_IF
Maximum parameter count for BIFF2-BIFF8 files.
const sal_uInt8 BIFF_TOKID_UPLUS
Range operator.
const sal_uInt8 BIFF_TOK_ATTR_SPACE_SP_OPEN
Line breaks before next token.
const sal_uInt8 BIFF_TOKID_NLR
String constant.
const sal_uInt8 BIFF_TOKID_MEMAREA
2D area reference.
const sal_uInt8 BIFF_TOKID_DIV
Multiplication operator.
const sal_uInt16 BIFF12_TOK_TABLE_ALL
Table reference: Range of columns.
const sal_uInt8 BIFF_TOK_ATTR_SPACE_SP_CLOSE
Line breaks before opening parenthesis.
const sal_uInt8 BIFF_TOKID_ADD
Multiple operation reference.
const sal_uInt8 BIFF_ERR_REF
const sal_uInt8 BIFF_TOKID_NUM
Integer constant.
const sal_uInt8 BIFF_TOK_ATTR_IF
Volatile function.
const sal_uInt16 BIFF_FUNC_ROWS
Function identifier of the FALSE function.
const sal_uInt8 BIFF_TOKID_BOOL
Error constant.
const sal_uInt8 BIFF_TOK_ARRAY_STRING
Double value in an array.
const sal_uInt8 BIFF_TOK_BOOL_FALSE
Error code in an array.
const sal_uInt8 BIFF_TOKCLASS_MASK
Maximum size of a token array.
const sal_uInt8 BIFF_TOKID_STR
Missing argument.
const sal_uInt8 BIFF_TOK_FUNCVAR_COUNTMASK
User prompt for macro commands.
const sal_uInt16 BIFF_TOK_FUNCVAR_CMD
Spaces before formula (BIFF3).
const sal_uInt8 BIFF_TOK_ATTR_SUM
Skip tokens.
const sal_uInt8 BIFF_TOKID_POWER
Division operator.
const sal_uInt16 BIFF_FUNC_WEEKNUM
Function identifier of the HYPERLINK function.
const sal_uInt8 BIFF_TOKID_MEMNOMEMN
Reference subexpression (in names).
const sal_uInt16 BIFF12_TOK_TABLE_COLUMN
True = row is relative.
const sal_uInt8 BIFF_TOKID_ARRAY
Floating-point constant.
const sal_uInt8 BIFF_TOKCLASS_NONE
void setFlag(Type &ornBitField, Type nMask, bool bSet=true)
bool getFlag(Type nBitField, Type nMask)
css::uno::Reference< css::linguistic2::XProofreadingIterator > get(css::uno::Reference< css::uno::XComponentContext > const &context)
Contains all API op-codes needed to build formulas with tokens.
sal_Int32 OPCODE_MISSING
Op-code for common value operands.
sal_Int32 OPCODE_NAME
Spaces between other formula tokens.
sal_Int32 OPCODE_ARRAY_OPEN
Function parameter separator.
sal_Int32 OPCODE_DDE
Natural language reference.
sal_Int32 OPCODE_SEP
Closing parenthesis.
sal_Int32 OPCODE_CLOSE
Opening parenthesis.
sal_Int32 OPCODE_BAD
Macro function call.
sal_Int32 OPCODE_OPEN
Function style #NAME? error.
sal_Int32 OPCODE_MACRO
DDE link function.
sal_Int32 OPCODE_NONAME
Bad token (unknown name, formula error).
sal_Int32 OPCODE_SPACES
Placeholder for a missing function parameter.
sal_Int32 OPCODE_ARRAY_CLOSE
Opening brace for constant arrays.
sal_Int32 OPCODE_EXTERNAL
Internal: function name unknown to mapper.
sal_Int32 OPCODE_PUSH
External function call (e.g. add-ins).
A 2D cell address struct for binary filters.
A 2D formula cell range reference struct with relative flags.
BinSingleRef2d maRef2
Start (top-left) cell address.
A 2D formula cell reference struct with relative flags.
bool mbRowRel
True = relative column reference.
sal_Int32 mnRow
Column index.
Represents information for a spreadsheet function.
sal_uInt16 mnBiffFuncId
BIFF12 function identifier.
OUString maExtProgName
Expected macro name in EXTERN.CALL function.
sal_Int32 mnApiOpCode
The external library this function is part of.
OUString maOoxFuncName
ODF function name.
sal_uInt16 mnBiff12FuncId
API function opcode.