summaryrefslogtreecommitdiff
path: root/oox/source
diff options
context:
space:
mode:
authorJens-Heiner Rechtien <hr@openoffice.org>2009-01-06 13:57:48 +0000
committerJens-Heiner Rechtien <hr@openoffice.org>2009-01-06 13:57:48 +0000
commit730272a2d67e99c0195ea42c26022ffbd489e994 (patch)
tree2268883449c5ccd3242d5c58cb0d59bc55420ecc /oox/source
parent75ab7be7fc7114e775442305bd1fb26a36975acc (diff)
CWS-TOOLING: integrate CWS odff05
2008-12-11 04:17:37 +0100 er r265237 : #i94555# AppendIntToken for GAMMADIST, Excel needs 4 parameters; also use AppendIntToken instead of AppendNumToken for POISSON 2008-12-11 04:04:27 +0100 er r265236 : #i96837# make cumulative parameter of POISSON optional; patch from <lvyue> with slight modifications 2008-12-11 03:35:03 +0100 er r265235 : #i96835# make base parameter of LOG() optional also in UI; patch from <lvyue> 2008-12-11 03:15:30 +0100 er r265234 : #i94555# patch from <regina>, ODFF: Add GAMMA, CHISQDIST, CHISQINV. Make the 'cumulative' parameter of GAMMADIST optional. Adapt the domain of CHIDIST to allow negative x. Remove the constraint "degrees of freedom < 1.0E5" from CHIDIST and CHIINV. Plus a mechanism to write the now optional parameter of GAMMADIST to PODF and ODFF if omitted, for backwards compatibility. 2008-12-10 18:14:16 +0100 er r265214 : DBG_... need semicolon 2008-12-05 00:49:55 +0100 er r264881 : WaE unxlngi6: declaration of 'pFuncInfo' shadows a previous local 2008-12-05 00:26:05 +0100 er r264879 : #i91547# BETADIST with optional density/cumulative parameter and much better precision; patch from <regina> 2008-12-04 22:51:40 +0100 er r264877 : #i91602# add expm1() and log1p() replacements; based on a patch from <regina> 2008-12-01 16:07:35 +0100 dr r264614 : #i93789# import of EUROCONVERT from XLSX/XLSB 2008-11-28 13:15:01 +0100 dr r264543 : #i93789# new sheet function EUROCONVERT + XLS import/export, patch contributed by lvyue 2008-11-26 14:54:23 +0100 er r264397 : CWS-TOOLING: rebase CWS odff05 to trunk@264325 (milestone: DEV300:m36) 2008-11-20 14:23:33 +0100 er r264053 : CWS-TOOLING: rebase CWS odff05 to trunk@263288 (milestone: DEV300:m35) 2008-11-19 18:07:43 +0100 er r264012 : merged from trunk 2008-11-19 17:51:36 +0100 er r264011 : migrate CWS odff05 to SVN
Diffstat (limited to 'oox/source')
-rw-r--r--oox/source/xls/addressconverter.cxx27
-rw-r--r--oox/source/xls/defnamesbuffer.cxx9
-rw-r--r--oox/source/xls/externallinkbuffer.cxx89
-rw-r--r--oox/source/xls/formulabase.cxx31
-rw-r--r--oox/source/xls/formulaparser.cxx106
-rw-r--r--oox/source/xls/workbookfragment.cxx4
6 files changed, 206 insertions, 60 deletions
diff --git a/oox/source/xls/addressconverter.cxx b/oox/source/xls/addressconverter.cxx
index 16d57b3c80ff..60f46771f3de 100644
--- a/oox/source/xls/addressconverter.cxx
+++ b/oox/source/xls/addressconverter.cxx
@@ -93,7 +93,7 @@ const sal_Unicode BIFF_URL_PARENT = '\x04'; /// Parent directory.
const sal_Unicode BIFF_URL_RAW = '\x05'; /// Unencoded URL.
const sal_Unicode BIFF_URL_INSTALL = '\x06'; /// Application installation directory.
const sal_Unicode BIFF_URL_INSTALL2 = '\x07'; /// Alternative application installation directory.
-const sal_Unicode BIFF_URL_ADDIN = '\x08'; /// Add-in installation directory.
+const sal_Unicode BIFF_URL_LIBRARY = '\x08'; /// Library directory in application installation.
const sal_Unicode BIFF4_URL_SHEET = '\x09'; /// BIFF4 internal sheet.
const sal_Unicode BIFF_URL_UNC = '@'; /// UNC path root.
@@ -385,13 +385,13 @@ bool lclAppendUrlChar( OUStringBuffer& orUrl, sal_Unicode cChar, bool bEncodeSpe
} // namespace
-bool AddressConverter::parseBiffTargetUrl(
- OUString& orClassName, OUString& orTargetUrl, OUString& orSheetName, bool& orbSameSheet,
- const OUString& rBiffTargetUrl )
+BiffTargetType AddressConverter::parseBiffTargetUrl(
+ OUString& orClassName, OUString& orTargetUrl, OUString& orSheetName, const OUString& rBiffTargetUrl )
{
OUStringBuffer aTargetUrl;
OUStringBuffer aSheetName;
- orbSameSheet = false;
+ // default target type: some URL with/without sheet name, may be overridden below
+ BiffTargetType eTargetType = BIFF_TARGETTYPE_URL;
enum
{
@@ -419,8 +419,10 @@ bool AddressConverter::parseBiffTargetUrl(
case STATE_START:
if( (cChar == mcUrlThisWorkbook) || (cChar == mcUrlThisSheet) || (cChar == mcUrlSameSheet) )
{
- if( pcChar + 1 < pcEnd ) eState = STATE_ERROR;
- orbSameSheet = cChar == mcUrlSameSheet;
+ if( pcChar + 1 < pcEnd )
+ eState = STATE_ERROR;
+ if( cChar == mcUrlSameSheet )
+ eTargetType = BIFF_TARGETTYPE_SAMESHEET;
}
else if( cChar == mcUrlExternal )
eState = (pcChar + 1 < pcEnd) ? STATE_ENCODED_PATH_START : STATE_ERROR;
@@ -446,8 +448,11 @@ bool AddressConverter::parseBiffTargetUrl(
eState = STATE_UNSUPPORTED;
else if( cChar == BIFF_URL_INSTALL2 )
eState = STATE_UNSUPPORTED;
- else if( cChar == BIFF_URL_ADDIN )
- eState = STATE_UNSUPPORTED;
+ else if( cChar == BIFF_URL_LIBRARY )
+ {
+ eState = STATE_ENCODED_PATH;
+ eTargetType = BIFF_TARGETTYPE_LIBRARY;
+ }
else if( (getBiff() == BIFF4) && (cChar == BIFF4_URL_SHEET) )
eState = STATE_SHEETNAME;
else if( cChar == '[' )
@@ -496,6 +501,7 @@ bool AddressConverter::parseBiffTargetUrl(
{
orClassName = aTargetUrl.makeStringAndClear();
eState = STATE_DDE_OLE;
+ eTargetType = BIFF_TARGETTYPE_DDE_OLE;
}
else if( cChar == '[' )
eState = STATE_FILENAME;
@@ -535,7 +541,8 @@ bool AddressConverter::parseBiffTargetUrl(
OSL_ENSURE( (eState != STATE_ERROR) && (pcChar == pcEnd),
OStringBuffer( "AddressConverter::parseBiffTargetUrl - parser error in target \"" ).
append( OUStringToOString( rBiffTargetUrl, RTL_TEXTENCODING_UTF8 ) ).append( '"' ).getStr() );
- return (eState != STATE_ERROR) && (eState != STATE_UNSUPPORTED) && (pcChar == pcEnd);
+ bool bParserOk = (eState != STATE_ERROR) && (eState != STATE_UNSUPPORTED) && (pcChar == pcEnd);
+ return bParserOk ? eTargetType : BIFF_TARGETTYPE_UNKNOWN;
}
// ----------------------------------------------------------------------------
diff --git a/oox/source/xls/defnamesbuffer.cxx b/oox/source/xls/defnamesbuffer.cxx
index 1bd0b0d039a6..b9197ea6edb2 100644
--- a/oox/source/xls/defnamesbuffer.cxx
+++ b/oox/source/xls/defnamesbuffer.cxx
@@ -142,11 +142,18 @@ DefinedNameBase::DefinedNameBase( const WorkbookHelper& rHelper, sal_Int32 nLoca
maOoxData.mnSheet = nLocalSheet;
}
+const OUString& DefinedNameBase::getUpcaseOoxName() const
+{
+ if( maUpOoxName.getLength() == 0 )
+ maUpOoxName = maOoxData.maName.toAsciiUpperCase();
+ return maUpOoxName;
+}
+
Any DefinedNameBase::getReference( const CellAddress& rBaseAddress ) const
{
if( maRefAny.hasValue() && (maOoxData.maName.getLength() >= 2) && (maOoxData.maName[ 0 ] == '\x01') )
{
- sal_Unicode cFlagsChar = maOoxData.maName.toAsciiUpperCase()[ 1 ];
+ sal_Unicode cFlagsChar = getUpcaseOoxName()[ 1 ];
if( ('A' <= cFlagsChar) && (cFlagsChar <= 'P') )
{
sal_uInt16 nFlags = static_cast< sal_uInt16 >( cFlagsChar - 'A' );
diff --git a/oox/source/xls/externallinkbuffer.cxx b/oox/source/xls/externallinkbuffer.cxx
index 00653a60ddd5..f05d28ce799c 100644
--- a/oox/source/xls/externallinkbuffer.cxx
+++ b/oox/source/xls/externallinkbuffer.cxx
@@ -62,6 +62,7 @@ using ::com::sun::star::sheet::XDDELinks;
using ::com::sun::star::sheet::XDDELinkResults;
using ::com::sun::star::sheet::XExternalDocLinks;
using ::com::sun::star::sheet::XExternalSheetCache;
+using ::oox::core::Relation;
using ::oox::core::Relations;
namespace oox {
@@ -435,7 +436,8 @@ void LinkSheetRange::setExternalRange( sal_Int32 nDocLink, sal_Int32 nFirst, sal
ExternalLink::ExternalLink( const WorkbookHelper& rHelper ) :
WorkbookHelper( rHelper ),
- meLinkType( LINKTYPE_UNKNOWN )
+ meLinkType( LINKTYPE_UNKNOWN ),
+ meFuncLibType( FUNCLIB_UNKNOWN )
{
}
@@ -446,8 +448,7 @@ void ExternalLink::importExternalReference( const AttributeList& rAttribs )
void ExternalLink::importExternalBook( const Relations& rRelations, const AttributeList& rAttribs )
{
- OUString aTargetUrl = rRelations.getTargetFromRelId( rAttribs.getString( R_TOKEN( id ), OUString() ) );
- setExternalTargetUrl( aTargetUrl );
+ parseExternalReference( rRelations, rAttribs.getString( R_TOKEN( id ), OUString() ) );
}
void ExternalLink::importSheetName( const AttributeList& rAttribs )
@@ -513,10 +514,7 @@ void ExternalLink::importExternalBook( const Relations& rRelations, RecordInputS
switch( rStrm.readuInt16() )
{
case OOBIN_EXTERNALBOOK_BOOK:
- {
- OUString aTargetUrl = rRelations.getTargetFromRelId( rStrm.readString() );
- setExternalTargetUrl( aTargetUrl );
- }
+ parseExternalReference( rRelations, rStrm.readString() );
break;
case OOBIN_EXTERNALBOOK_DDE:
{
@@ -540,8 +538,9 @@ void ExternalLink::importExternalBook( const Relations& rRelations, RecordInputS
void ExternalLink::importExtSheetNames( RecordInputStream& rStrm )
{
// load external sheet names and create the sheet caches in the Calc document
- OSL_ENSURE( meLinkType == LINKTYPE_EXTERNAL, "ExternalLink::importExtSheetNames - invalid link type" );
- if( meLinkType == LINKTYPE_EXTERNAL )
+ OSL_ENSURE( (meLinkType == LINKTYPE_EXTERNAL) || (meLinkType == LINKTYPE_LIBRARY),
+ "ExternalLink::importExtSheetNames - invalid link type" );
+ if( meLinkType == LINKTYPE_EXTERNAL ) // ignore sheets of external libraries
for( sal_Int32 nSheet = 0, nCount = rStrm.readInt32(); !rStrm.isEof() && (nSheet < nCount); ++nSheet )
insertExternalSheet( rStrm.readString() );
}
@@ -659,6 +658,11 @@ ExternalLinkInfo ExternalLink::getLinkInfo() const
return aLinkInfo;
}
+FunctionLibraryType ExternalLink::getFuncLibraryType() const
+{
+ return (meLinkType == LINKTYPE_LIBRARY) ? meFuncLibType : FUNCLIB_UNKNOWN;
+}
+
sal_Int32 ExternalLink::getSheetIndex( sal_Int32 nTabId ) const
{
OSL_ENSURE( (nTabId == 0) || (getFilterType() == FILTER_OOX) || (getBiff() == BIFF8),
@@ -743,11 +747,25 @@ ExternalNameRef ExternalLink::getNameByIndex( sal_Int32 nIndex ) const
// private --------------------------------------------------------------------
-void ExternalLink::setExternalTargetUrl( const OUString& rTargetUrl )
+#define OOX_TARGETTYPE_EXTLINK CREATE_OFFICEDOC_RELATIONSTYPE( "externalLinkPath" )
+#define OOX_TARGETTYPE_LIBRARY CREATE_MSOFFICE_RELATIONSTYPE( "xlExternalLinkPath/xlLibrary" )
+
+void ExternalLink::setExternalTargetUrl( const OUString& rTargetUrl, const OUString& rTargetType )
{
+ meLinkType = LINKTYPE_UNKNOWN;
+ if( rTargetType == OOX_TARGETTYPE_EXTLINK )
+ {
maTargetUrl = getBaseFilter().getAbsoluteUrl( rTargetUrl );
- meLinkType = (maTargetUrl.getLength() > 0) ? LINKTYPE_EXTERNAL : LINKTYPE_UNKNOWN;
- OSL_ENSURE( meLinkType == LINKTYPE_EXTERNAL, "ExternalLink::setExternalTargetUrl - empty target URL" );
+ if( maTargetUrl.getLength() > 0 )
+ meLinkType = LINKTYPE_EXTERNAL;
+ }
+ else if( rTargetType == OOX_TARGETTYPE_LIBRARY )
+ {
+ meLinkType = LINKTYPE_LIBRARY;
+ if( rTargetUrl.equalsIgnoreAsciiCaseAscii( "EUROTOOL.XLA" ) || rTargetUrl.equalsIgnoreAsciiCaseAscii( "EUROTOOL.XLAM" ) )
+ meFuncLibType = FUNCLIB_EUROTOOL;
+ }
+ OSL_ENSURE( meLinkType != LINKTYPE_UNKNOWN, "ExternalLink::setExternalTargetUrl - empty target URL or unknown target type" );
// create the external document link API object that will contain the sheet caches
if( meLinkType == LINKTYPE_EXTERNAL )
@@ -766,34 +784,51 @@ void ExternalLink::setDdeOleTargetUrl( const OUString& rClassName, const OUStrin
OSL_ENSURE( meLinkType == eLinkType, "ExternalLink::setDdeOleTargetUrl - missing classname or target" );
}
+void ExternalLink::parseExternalReference( const Relations& rRelations, const OUString& rRelId )
+{
+ if( const Relation* pRelation = rRelations.getRelationFromRelId( rRelId ) )
+ setExternalTargetUrl( pRelation->maTarget, pRelation->maType );
+}
+
OUString ExternalLink::parseBiffTargetUrl( const OUString& rBiffTargetUrl )
{
- OUString aClassName, aTargetUrl, aSheetName;
- bool bSameSheet = false;
meLinkType = LINKTYPE_UNKNOWN;
- if( getAddressConverter().parseBiffTargetUrl( aClassName, aTargetUrl, aSheetName, bSameSheet, rBiffTargetUrl ) )
- {
- if( aClassName.getLength() > 0 )
+
+ OUString aClassName, aTargetUrl, aSheetName;
+ switch( getAddressConverter().parseBiffTargetUrl( aClassName, aTargetUrl, aSheetName, rBiffTargetUrl ) )
{
- setDdeOleTargetUrl( aClassName, aTargetUrl, LINKTYPE_MAYBE_DDE_OLE );
- }
- else if( aTargetUrl.getLength() == 0 )
+ case BIFF_TARGETTYPE_URL:
+ if( aTargetUrl.getLength() == 0 )
{
- meLinkType = (aSheetName.getLength() > 0) ? LINKTYPE_INTERNAL : (bSameSheet ? LINKTYPE_SAME : LINKTYPE_SELF);
+ meLinkType = (aSheetName.getLength() > 0) ? LINKTYPE_INTERNAL : LINKTYPE_SELF;
}
else if( (aTargetUrl.getLength() == 1) && (aTargetUrl[ 0 ] == ':') )
{
if( getBiff() >= BIFF4 )
meLinkType = LINKTYPE_ANALYSIS;
}
- else if( (aTargetUrl.getLength() == 1) && (aTargetUrl[ 0 ] == ' ') )
+ else if( (aTargetUrl.getLength() > 1) || (aTargetUrl[ 0 ] != ' ') )
{
- meLinkType = LINKTYPE_UNKNOWN;
- }
- else
- {
- setExternalTargetUrl( aTargetUrl );
+ setExternalTargetUrl( aTargetUrl, OOX_TARGETTYPE_EXTLINK );
}
+ break;
+
+ case BIFF_TARGETTYPE_SAMESHEET:
+ OSL_ENSURE( (aTargetUrl.getLength() == 0) && (aSheetName.getLength() == 0), "ExternalLink::parseBiffTargetUrl - unexpected target or sheet name" );
+ meLinkType = LINKTYPE_SAME;
+ break;
+
+ case BIFF_TARGETTYPE_LIBRARY:
+ OSL_ENSURE( aSheetName.getLength() == 0, "ExternalLink::parseBiffTargetUrl - unexpected sheet name" );
+ setExternalTargetUrl( aTargetUrl, OOX_TARGETTYPE_LIBRARY );
+ break;
+
+ case BIFF_TARGETTYPE_DDE_OLE:
+ setDdeOleTargetUrl( aClassName, aTargetUrl, LINKTYPE_MAYBE_DDE_OLE );
+ break;
+
+ case BIFF_TARGETTYPE_UNKNOWN:
+ break;
}
return aSheetName;
}
diff --git a/oox/source/xls/formulabase.cxx b/oox/source/xls/formulabase.cxx
index 87c1fc67adf7..6696c211e61d 100644
--- a/oox/source/xls/formulabase.cxx
+++ b/oox/source/xls/formulabase.cxx
@@ -227,14 +227,17 @@ namespace {
const size_t FUNCINFO_CLASSCOUNT = 5; /// Number of token class entries.
-const sal_uInt8 FUNCFLAG_VOLATILE = 0x01; /// Result is volatile (e.g. NOW() function).
-const sal_uInt8 FUNCFLAG_IMPORTONLY = 0x02; /// Only used in import filter.
-const sal_uInt8 FUNCFLAG_EXPORTONLY = 0x04; /// Only used in export filter.
-const sal_uInt8 FUNCFLAG_MACROCALL = 0x08; /// Function is simulated by macro call in Excel.
-const sal_uInt8 FUNCFLAG_EXTERNAL = 0x10; /// Function is external in Calc.
-const sal_uInt8 FUNCFLAG_MACROFUNC = 0x20; /// Function is a macro sheet function.
-const sal_uInt8 FUNCFLAG_MACROCMD = 0x40; /// Function is a macro sheet command.
-const sal_uInt8 FUNCFLAG_ALWAYSVAR = 0x80; /// Function is always represented by a tFuncVar token.
+const sal_uInt16 FUNCFLAG_VOLATILE = 0x0001; /// Result is volatile (e.g. NOW() function).
+const sal_uInt16 FUNCFLAG_IMPORTONLY = 0x0002; /// Only used in import filter.
+const sal_uInt16 FUNCFLAG_EXPORTONLY = 0x0004; /// Only used in export filter.
+const sal_uInt16 FUNCFLAG_MACROCALL = 0x0008; /// Function is simulated by macro call in Excel.
+const sal_uInt16 FUNCFLAG_EXTERNAL = 0x0010; /// Function is external in Calc.
+const sal_uInt16 FUNCFLAG_MACROFUNC = 0x0020; /// Function is a macro-sheet function.
+const sal_uInt16 FUNCFLAG_MACROCMD = 0x0040; /// Function is a macro-sheet command.
+const sal_uInt16 FUNCFLAG_ALWAYSVAR = 0x0080; /// Function is always represented by a tFuncVar token.
+
+const sal_uInt16 FUNCFLAG_FUNCLIBMASK = 0xF000; /// Mask for function library bits.
+const sal_uInt16 FUNCFLAG_EUROTOOL = 0x1000; /// Function is part of the EuroTool add-in.
typedef ::boost::shared_ptr< FunctionInfo > FunctionInfoRef;
@@ -248,7 +251,7 @@ struct FunctionData
sal_uInt8 mnMaxParamCount; /// Maximum number of parameters.
sal_uInt8 mnRetClass; /// BIFF token class of the return value.
sal_uInt8 mpnParamClass[ FUNCINFO_CLASSCOUNT ]; /// Expected BIFF token classes of parameters.
- sal_uInt8 mnFlags; /// Additional flags.
+ sal_uInt16 mnFlags; /// Additional flags.
inline bool isSupported( bool bImportFilter ) const;
};
@@ -632,7 +635,6 @@ static const FunctionData saFuncTableBiff4[] =
{ "MULTINOMIAL", "MULTINOMIAL", 474, NOID, 1, MX, V, { R }, FUNCFLAG_EXTERNAL },
{ "LCM", "LCM", 475, NOID, 1, MX, V, { R }, FUNCFLAG_EXTERNAL }, // Calc: builtin and add-in
{ "FVSCHEDULE", "FVSCHEDULE", 476, NOID, 2, 2, V, { V, A }, FUNCFLAG_EXTERNAL },
-// { "EUROCONVERT", "EUROCONVERT", NOID, NOID, 3, 5, V, { V }, FUNCFLAG_EXTERNAL }, // Euro conversion add-in
// *** macro sheet commands ***
@@ -664,6 +666,10 @@ static const FunctionData saFuncTableBiff5[] =
{ 0, "NUMBERSTRING", 353, 353, 2, 2, V, { V }, FUNCFLAG_IMPORTONLY }, // not supported in Calc, missing in OOX spec
{ "ROMAN", "ROMAN", 354, 354, 1, 2, V, { V }, 0 },
+ // *** EuroTool add-in ***
+
+ { "EUROCONVERT", "EUROCONVERT", NOID, NOID, 3, 5, V, { V }, FUNCFLAG_EUROTOOL },
+
// *** macro sheet commands ***
{ 0, "ADD.CHART.AUTOFORMAT", 390, 390, 0, 2, V, { V }, FUNCFLAG_MACROCMD },
@@ -868,6 +874,11 @@ void FunctionProvider::initFunc( const FunctionData& rFuncData, sal_uInt8 nMaxPa
xFuncInfo->maOoxFuncName = OUString::createFromAscii( rFuncData.mpcOoxFuncName );
if( getFlag( rFuncData.mnFlags, FUNCFLAG_MACROCALL ) )
xFuncInfo->maBiffMacroName = CREATE_OUSTRING( "_xlfn." ) + xFuncInfo->maOoxFuncName;
+ switch( rFuncData.mnFlags & FUNCFLAG_FUNCLIBMASK )
+ {
+ case FUNCFLAG_EUROTOOL: xFuncInfo->meFuncLibType = FUNCLIB_EUROTOOL; break;
+ default: xFuncInfo->meFuncLibType = FUNCLIB_UNKNOWN;
+ }
xFuncInfo->mnApiOpCode = -1;
xFuncInfo->mnOobFuncId = rFuncData.mnOobFuncId;
xFuncInfo->mnBiffFuncId = rFuncData.mnBiffFuncId;
diff --git a/oox/source/xls/formulaparser.cxx b/oox/source/xls/formulaparser.cxx
index dff1b42dc991..161802b6c63c 100644
--- a/oox/source/xls/formulaparser.cxx
+++ b/oox/source/xls/formulaparser.cxx
@@ -169,8 +169,9 @@ protected:
bool pushNlrOperand( const BinSingleRef2d& rRef );
bool pushEmbeddedRefOperand( const DefinedNameBase& rName, bool bPushBadToken );
bool pushDefinedNameOperand( const DefinedNameRef& rxDefName );
+ bool pushExternalFuncOperand( const FunctionInfo& rFuncInfo );
bool pushDdeLinkOperand( const OUString& rDdeServer, const OUString& rDdeTopic, const OUString& rDdeItem );
- bool pushExternalNameOperand( const ExternalNameRef& rxExtName, ExternalLinkType eLinkType );
+ bool pushExternalNameOperand( const ExternalNameRef& rxExtName, const ExternalLink& rExtLink );
bool pushUnaryPreOperator( sal_Int32 nOpCode );
bool pushUnaryPostOperator( sal_Int32 nOpCode );
@@ -199,6 +200,7 @@ private:
void processTokens( const ApiToken* pToken, const ApiToken* pTokenEnd );
const ApiToken* processParameters( const FunctionInfo& rFuncInfo, const ApiToken* pToken, const ApiToken* pTokenEnd );
+ const FunctionInfo* getFuncInfoFromLibFuncName( const ApiToken& rToken ) const;
bool isEmptyParameter( const ApiToken* pToken, const ApiToken* pTokenEnd ) const;
const ApiToken* getExternCallToken( const ApiToken* pToken, const ApiToken* pTokenEnd ) const;
const FunctionInfo* convertExternCallParam( ApiToken& orFuncToken, const ApiToken& rECToken ) const;
@@ -669,6 +671,13 @@ bool FormulaParserImpl::pushDefinedNameOperand( const DefinedNameRef& rxDefName
return pushEmbeddedRefOperand( *rxDefName, true );
}
+bool FormulaParserImpl::pushExternalFuncOperand( const FunctionInfo& rFuncInfo )
+{
+ return (rFuncInfo.mnApiOpCode == OPCODE_EXTERNAL) ?
+ pushValueOperand( rFuncInfo.maExtProgName, OPCODE_EXTERNAL ) :
+ pushOperand( rFuncInfo.mnApiOpCode );
+}
+
bool FormulaParserImpl::pushDdeLinkOperand( const OUString& rDdeServer, const OUString& rDdeTopic, const OUString& rDdeItem )
{
// create the function call DDE("server";"topic";"item")
@@ -679,9 +688,9 @@ bool FormulaParserImpl::pushDdeLinkOperand( const OUString& rDdeServer, const OU
pushFunctionOperator( OPCODE_DDE, 3 );
}
-bool FormulaParserImpl::pushExternalNameOperand( const ExternalNameRef& rxExtName, ExternalLinkType eLinkType )
+bool FormulaParserImpl::pushExternalNameOperand( const ExternalNameRef& rxExtName, const ExternalLink& rExtLink )
{
- if( rxExtName.get() ) switch( eLinkType )
+ if( rxExtName.get() ) switch( rExtLink.getLinkType() )
{
case LINKTYPE_INTERNAL:
case LINKTYPE_EXTERNAL:
@@ -689,8 +698,14 @@ bool FormulaParserImpl::pushExternalNameOperand( const ExternalNameRef& rxExtNam
case LINKTYPE_ANALYSIS:
// TODO: need support for localized addin function names
- if( const FunctionInfo* pFuncInfo = getFuncInfoFromOoxFuncName( rxExtName->getOoxName() ) )
- return pushValueOperand( pFuncInfo->maExtProgName, OPCODE_EXTERNAL );
+ if( const FunctionInfo* pFuncInfo = getFuncInfoFromOoxFuncName( rxExtName->getUpcaseOoxName() ) )
+ return pushExternalFuncOperand( *pFuncInfo );
+ break;
+
+ case LINKTYPE_LIBRARY:
+ if( const FunctionInfo* pFuncInfo = getFuncInfoFromOoxFuncName( rxExtName->getUpcaseOoxName() ) )
+ if( (pFuncInfo->meFuncLibType != FUNCLIB_UNKNOWN) && (pFuncInfo->meFuncLibType == rExtLink.getFuncLibraryType()) )
+ return pushExternalFuncOperand( *pFuncInfo );
break;
case LINKTYPE_DDE:
@@ -702,7 +717,7 @@ bool FormulaParserImpl::pushExternalNameOperand( const ExternalNameRef& rxExtNam
break;
default:
- OSL_ENSURE( eLinkType != LINKTYPE_SELF, "FormulaParserImpl::pushExternalNameOperand - invalid call" );
+ OSL_ENSURE( rExtLink.getLinkType() != LINKTYPE_SELF, "FormulaParserImpl::pushExternalNameOperand - invalid call" );
}
return pushBiffErrorOperand( BIFF_ERR_NAME );
}
@@ -852,17 +867,65 @@ void FormulaParserImpl::processTokens( const ApiToken* pToken, const ApiToken* p
{
// push the current token into the vector
appendFinalToken( *pToken );
- // try to process a function, otherwise go to next token
- if( const FunctionInfo* pFuncInfo = getFuncInfoFromApiToken( *pToken ) )
+ const FunctionInfo* pFuncInfo;
+ // try to process a function
+ if( (pFuncInfo = getFuncInfoFromApiToken( *pToken )) != 0 )
+ {
+ pToken = processParameters( *pFuncInfo, pToken + 1, pTokenEnd );
+ }
+ // try to process a function from an external library
+ else if( (pFuncInfo = getFuncInfoFromLibFuncName( *pToken )) != 0 )
+ {
+ ApiToken& rFuncToken = maTokenStorage.back();
+ rFuncToken.OpCode = pFuncInfo->mnApiOpCode;
+ if( (rFuncToken.OpCode == OPCODE_EXTERNAL) && (pFuncInfo->maExtProgName.getLength() > 0) )
+ rFuncToken.Data <<= pFuncInfo->maExtProgName;
+ else
+ rFuncToken.Data.clear(); // clear string from OPCODE_BAD
pToken = processParameters( *pFuncInfo, pToken + 1, pTokenEnd );
+ }
+ // otherwise, go to next token
else
+ {
++pToken;
+ }
}
}
+namespace {
+
+bool lclTokenHasChar( const ApiToken& rToken, sal_Int32 nOpCode, sal_Unicode cChar )
+{
+ return (rToken.OpCode == nOpCode) && rToken.Data.has< OUString >() && (rToken.Data.get< OUString >() == OUString( cChar ));
+}
+
+bool lclTokenHasDouble( const ApiToken& rToken, sal_Int32 nOpCode )
+{
+ return (rToken.OpCode == nOpCode) && rToken.Data.has< double >();
+}
+
+} // namespace
+
const ApiToken* FormulaParserImpl::processParameters(
const FunctionInfo& rFuncInfo, const ApiToken* pToken, const ApiToken* pTokenEnd )
{
+ /* OOXML import of library functions pushes the external reference "[n]!"
+ as BAD/PUSH/BAD/BAD tokens in front of the function name. Try to find
+ and remove them here. TODO: This will change with CWS mooxlsc, there,
+ the reference ID and function name are passed together in a BAD token,
+ see getFuncInfoFromLibFuncName(). */
+ if( (rFuncInfo.meFuncLibType != FUNCLIB_UNKNOWN) && (maTokenStorage.size() >= 5) )
+ {
+ sal_Size nSize = maTokenStorage.size();
+ if( lclTokenHasChar( maTokenStorage[ nSize - 5 ], OPCODE_BAD, '[' ) &&
+ lclTokenHasDouble( maTokenStorage[ nSize - 4 ], OPCODE_PUSH ) &&
+ lclTokenHasChar( maTokenStorage[ nSize - 3 ], OPCODE_BAD, ']' ) &&
+ lclTokenHasChar( maTokenStorage[ nSize - 2 ], OPCODE_BAD, '!' ) )
+ {
+ maTokenStorage.erase( maTokenStorage.end() - 5, maTokenStorage.end() - 1 );
+ }
+ }
+
// remember position of the token containing the function op-code
size_t nFuncNameIdx = maTokenStorage.size() - 1;
@@ -980,6 +1043,29 @@ const ApiToken* FormulaParserImpl::processParameters(
return pToken;
}
+const FunctionInfo* FormulaParserImpl::getFuncInfoFromLibFuncName( const ApiToken& rToken ) const
+{
+ // try to parse calls to library functions
+ if( (rToken.OpCode == OPCODE_BAD) && rToken.Data.has< OUString >() )
+ {
+ // format of the function call is "[n]!funcname", n being the link to the library
+ OUString aString = rToken.Data.get< OUString >();
+ sal_Int32 nBracketOpen = aString.indexOf( '[' );
+ sal_Int32 nBracketClose = aString.indexOf( ']' );
+ sal_Int32 nExclamation = aString.indexOf( '!' );
+ if( (0 == nBracketOpen) && (nBracketOpen + 1 < nBracketClose) && (nBracketClose + 1 == nExclamation) && (nExclamation + 1 < aString.getLength()) )
+ {
+ sal_Int32 nRefId = aString.copy( nBracketOpen + 1, nBracketClose - nBracketOpen - 1 ).toInt32();
+ const ExternalLink* pExtLink = getExternalLinks().getExternalLink( nRefId ).get();
+ if( pExtLink && (pExtLink->getLinkType() == LINKTYPE_LIBRARY) )
+ if( const FunctionInfo* pFuncInfo = getFuncInfoFromOoxFuncName( aString.copy( nExclamation + 1 ).toAsciiUpperCase() ) )
+ if( (pFuncInfo->meFuncLibType != FUNCLIB_UNKNOWN) && (pFuncInfo->meFuncLibType == pExtLink->getFuncLibraryType()) )
+ return pFuncInfo;
+ }
+ }
+ return 0;
+}
+
bool FormulaParserImpl::isEmptyParameter( const ApiToken* pToken, const ApiToken* pTokenEnd ) const
{
while( (pToken < pTokenEnd) && (pToken->OpCode == OPCODE_SPACES) ) ++pToken;
@@ -1666,7 +1752,7 @@ bool OoxFormulaParserImpl::pushOobExtName( sal_Int32 nRefId, sal_Int32 nNameId )
return pushOobName( nNameId );
// external name indexes are one-based in OOBIN
ExternalNameRef xExtName = pExtLink->getNameByIndex( nNameId - 1 );
- return pushExternalNameOperand( xExtName, pExtLink->getLinkType() );
+ return pushExternalNameOperand( xExtName, *pExtLink );
}
return pushBiffErrorOperand( BIFF_ERR_NAME );
}
@@ -2603,7 +2689,7 @@ bool BiffFormulaParserImpl::pushBiffExtName( sal_Int32 nRefId, sal_uInt16 nNameI
return pushBiffName( nNameId );
// external name indexes are one-based in BIFF
ExternalNameRef xExtName = pExtLink->getNameByIndex( static_cast< sal_Int32 >( nNameId ) - 1 );
- return pushExternalNameOperand( xExtName, pExtLink->getLinkType() );
+ return pushExternalNameOperand( xExtName, *pExtLink );
}
return pushBiffErrorOperand( BIFF_ERR_NAME );
}
diff --git a/oox/source/xls/workbookfragment.cxx b/oox/source/xls/workbookfragment.cxx
index 44be166e6580..d14c20f2ef0f 100644
--- a/oox/source/xls/workbookfragment.cxx
+++ b/oox/source/xls/workbookfragment.cxx
@@ -258,8 +258,8 @@ void OoxWorkbookFragment::finalizeImport()
{
xFragment.set( new OoxChartsheetFragment( *this, aFragmentPath, xSheetSegment, nSheet ) );
}
- else if( (pRelation->maType == CREATE_OUSTRING( "http://schemas.microsoft.com/office/2006/relationships/xlMacrosheet" )) ||
- (pRelation->maType == CREATE_OUSTRING( "http://schemas.microsoft.com/office/2006/relationships/xlIntlMacrosheet" )) )
+ else if( (pRelation->maType == CREATE_MSOFFICE_RELATIONSTYPE( "xlMacrosheet" )) ||
+ (pRelation->maType == CREATE_MSOFFICE_RELATIONSTYPE( "xlIntlMacrosheet" )) )
{
xFragment.set( new OoxWorksheetFragment( *this, aFragmentPath, xSheetSegment, SHEETTYPE_MACROSHEET, nSheet ) );
}