diff options
-rw-r--r-- | sc/source/filter/excel/xecontent.cxx | 18 | ||||
-rw-r--r-- | sc/source/filter/excel/xeextlst.cxx | 3 | ||||
-rw-r--r-- | sc/source/filter/excel/xeformula.cxx | 9 | ||||
-rw-r--r-- | sc/source/filter/excel/xeroot.cxx | 51 | ||||
-rw-r--r-- | sc/source/filter/excel/xestream.cxx | 24 | ||||
-rw-r--r-- | sc/source/filter/excel/xetable.cxx | 3 | ||||
-rw-r--r-- | sc/source/filter/inc/formulabase.hxx | 6 | ||||
-rw-r--r-- | sc/source/filter/inc/xeroot.hxx | 5 | ||||
-rw-r--r-- | sc/source/filter/inc/xestream.hxx | 4 | ||||
-rw-r--r-- | sc/source/filter/oox/formulabase.cxx | 36 | ||||
-rw-r--r-- | sc/source/filter/xcl97/XclExpChangeTrack.cxx | 3 |
11 files changed, 136 insertions, 26 deletions
diff --git a/sc/source/filter/excel/xecontent.cxx b/sc/source/filter/excel/xecontent.cxx index a58f1b0120c6..5a46ad52cd07 100644 --- a/sc/source/filter/excel/xecontent.cxx +++ b/sc/source/filter/excel/xecontent.cxx @@ -931,12 +931,14 @@ void XclExpCFImpl::SaveXml( XclExpXmlStream& rStrm ) if(!IsTextRule(eOperation) && !IsTopBottomRule(eOperation)) { rWorksheet->startElement( XML_formula, FSEND ); - rWorksheet->write(XclXmlUtils::ToOUString( GetRoot().GetDoc(), mrFormatEntry.GetValidSrcPos(), mrFormatEntry.CreateTokenArry( 0 ) )); + rWorksheet->write(XclXmlUtils::ToOUString( GetRoot().GetDoc(), mrFormatEntry.GetValidSrcPos(), + mrFormatEntry.CreateTokenArry( 0 ), GetRoot().GetOpCodeMap() )); rWorksheet->endElement( XML_formula ); if (bFmla2) { rWorksheet->startElement( XML_formula, FSEND ); - rWorksheet->write(XclXmlUtils::ToOUString( GetRoot().GetDoc(), mrFormatEntry.GetValidSrcPos(), mrFormatEntry.CreateTokenArry( 1 ) )); + rWorksheet->write(XclXmlUtils::ToOUString( GetRoot().GetDoc(), mrFormatEntry.GetValidSrcPos(), + mrFormatEntry.CreateTokenArry( 1 ), GetRoot().GetOpCodeMap() )); rWorksheet->endElement( XML_formula ); } } @@ -1076,7 +1078,8 @@ void XclExpCfvo::SaveXml( XclExpXmlStream& rStrm ) rtl::OString aValue; if(mrEntry.GetType() == COLORSCALE_FORMULA) { - rtl::OUString aFormula = XclXmlUtils::ToOUString( GetRoot().GetDoc(), maSrcPos, mrEntry.GetFormula()->Clone() ); + rtl::OUString aFormula = XclXmlUtils::ToOUString( GetRoot().GetDoc(), maSrcPos, + mrEntry.GetFormula()->Clone(), GetRoot().GetOpCodeMap() ); aValue = rtl::OUStringToOString(aFormula, RTL_TEXTENCODING_UTF8 ); } else @@ -1582,14 +1585,16 @@ XclExpDV::XclExpDV( const XclExpRoot& rRoot, sal_uLong nScHandle ) : Formula compiler supports this by offering two different functions CreateDataValFormula() and CreateListValFormula(). */ mxTokArr1 = rFmlaComp.CreateFormula( EXC_FMLATYPE_LISTVAL, *xScTokArr ); - msFormula1 = XclXmlUtils::ToOUString( GetDoc(), pValData->GetSrcPos(), xScTokArr.get() ); + msFormula1 = XclXmlUtils::ToOUString( GetDoc(), pValData->GetSrcPos(), + xScTokArr.get(), GetRoot().GetOpCodeMap() ); } } else { // no list validation -> convert the formula mxTokArr1 = rFmlaComp.CreateFormula( EXC_FMLATYPE_DATAVAL, *xScTokArr ); - msFormula1 = XclXmlUtils::ToOUString( GetDoc(), pValData->GetSrcPos(), xScTokArr.get() ); + msFormula1 = XclXmlUtils::ToOUString( GetDoc(), pValData->GetSrcPos(), + xScTokArr.get(), GetRoot().GetOpCodeMap() ); } } @@ -1598,7 +1603,8 @@ XclExpDV::XclExpDV( const XclExpRoot& rRoot, sal_uLong nScHandle ) : if( xScTokArr.get() ) { mxTokArr2 = rFmlaComp.CreateFormula( EXC_FMLATYPE_DATAVAL, *xScTokArr ); - msFormula2 = XclXmlUtils::ToOUString( GetDoc(), pValData->GetSrcPos(), xScTokArr.get() ); + msFormula2 = XclXmlUtils::ToOUString( GetDoc(), pValData->GetSrcPos(), + xScTokArr.get(), GetRoot().GetOpCodeMap() ); } } else diff --git a/sc/source/filter/excel/xeextlst.cxx b/sc/source/filter/excel/xeextlst.cxx index 53ab66ba2ec5..1992b3271f79 100644 --- a/sc/source/filter/excel/xeextlst.cxx +++ b/sc/source/filter/excel/xeextlst.cxx @@ -58,7 +58,8 @@ XclExpExtCfvo::XclExpExtCfvo( const XclExpRoot& rRoot, const ScColorScaleEntry& { if( rEntry.GetType() == COLORSCALE_FORMULA ) { - rtl::OUString aFormula = XclXmlUtils::ToOUString( GetRoot().GetDoc(), rSrcPos, rEntry.GetFormula()->Clone() ); + rtl::OUString aFormula = XclXmlUtils::ToOUString( GetRoot().GetDoc(), rSrcPos, + rEntry.GetFormula()->Clone(), GetRoot().GetOpCodeMap() ); maValue = rtl::OUStringToOString(aFormula, RTL_TEXTENCODING_UTF8 ); } else diff --git a/sc/source/filter/excel/xeformula.cxx b/sc/source/filter/excel/xeformula.cxx index d450dfed4b76..603ee9da59d8 100644 --- a/sc/source/filter/excel/xeformula.cxx +++ b/sc/source/filter/excel/xeformula.cxx @@ -1633,7 +1633,14 @@ void XclExpFmlaCompImpl::AppendDefaultParam( XclExpFuncData& rFuncData ) { OSL_ENSURE( rFuncData.IsMacroFunc(), "XclExpFmlaCompImpl::AppendDefaultParam - unknown opcode" ); if( rFuncData.IsMacroFunc() ) - AppendMacroCallToken( rFuncData.GetExtFuncData() ); + { + // Do not write the OOXML <definedName> element for new _xlfn. + // prefixed functions. + if (GetOutput() == EXC_OUTPUT_XML_2007) + AppendNameToken( 0, 0); // dummy to keep parameter count valid + else + AppendMacroCallToken( rFuncData.GetExtFuncData() ); + } else AppendMissingToken(); // to keep parameter count valid } diff --git a/sc/source/filter/excel/xeroot.cxx b/sc/source/filter/excel/xeroot.cxx index a3815544f8ed..785a62079064 100644 --- a/sc/source/filter/excel/xeroot.cxx +++ b/sc/source/filter/excel/xeroot.cxx @@ -44,6 +44,9 @@ #include "document.hxx" #include "scextopt.hxx" +#include "formulabase.hxx" +#include <com/sun/star/sheet/FormulaOpCodeMapEntry.hpp> + using namespace ::com::sun::star; // Global data ================================================================ @@ -164,6 +167,12 @@ XclExpPivotTableManager& XclExpRoot::GetPivotTableManager() const return *mrExpData.mxPTableMgr; } +ScCompiler::OpCodeMapPtr XclExpRoot::GetOpCodeMap() const +{ + OSL_ENSURE( mrExpData.mxPTableMgr, "XclExpRoot::GetOpCodeMap - missing object (wrong BIFF?)" ); + return mrExpData.mxOpCodeMap; +} + void XclExpRoot::InitializeConvert() { mrExpData.mxTabInfo.reset( new XclExpTabInfo( GetRoot() ) ); @@ -199,6 +208,48 @@ void XclExpRoot::InitializeGlobals() mrExpData.mxDxfs.reset( new XclExpDxfs( GetRoot() ) ); } + if( GetOutput() == EXC_OUTPUT_XML_2007 ) + { + do + { + ScDocument& rDoc = GetDoc(); + // Pass the model factory to OpCodeProvider, not the process + // service factory, otherwise a FormulaOpCodeMapperObj would be + // instanciated intead of a ScFormulaOpCodeMapperObj and the + // ScCompiler virtuals not be called! Which would be the case with + // the current (2013-01-24) rDoc.GetServiceManager() + const SfxObjectShell* pShell = rDoc.GetDocumentShell(); + if (!pShell) + { + SAL_WARN( "sc", "XclExpRoot::InitializeGlobals - no object shell"); + break; + } + uno::Reference< lang::XComponent > xComponent( pShell->GetModel(), uno::UNO_QUERY); + if (!xComponent.is()) + { + SAL_WARN( "sc", "XclExpRoot::InitializeGlobals - no component"); + break; + } + uno::Reference< lang::XMultiServiceFactory > xModelFactory( xComponent, uno::UNO_QUERY); + // OOXML is also BIFF8 function-wise + oox::xls::OpCodeProvider aOpCodeProvider( xModelFactory, + oox::xls::FILTER_OOXML, oox::xls::BIFF8, false, true); + // Compiler mocks about non-matching ctor or conversion from + // Sequence<...> to Sequence<const ...> if directly created or passed, + // conversion through Any works around. + uno::Any aAny( aOpCodeProvider.getOoxParserMap()); + uno::Sequence< const sheet::FormulaOpCodeMapEntry > aOpCodeMapping; + if (!(aAny >>= aOpCodeMapping)) + { + SAL_WARN( "sc", "XclExpRoot::InitializeGlobals - no OpCodeMap"); + break; + } + ScCompiler aCompiler( &rDoc, ScAddress()); + aCompiler.SetGrammar( rDoc.GetGrammar()); + mrExpData.mxOpCodeMap = aCompiler.CreateOpCodeMap( aOpCodeMapping, true); + } while(0); + } + GetXFBuffer().Initialize(); GetNameManager().Initialize(); } diff --git a/sc/source/filter/excel/xestream.cxx b/sc/source/filter/excel/xestream.cxx index 9df58112cf23..c625aed68362 100644 --- a/sc/source/filter/excel/xestream.cxx +++ b/sc/source/filter/excel/xestream.cxx @@ -849,13 +849,27 @@ OUString XclXmlUtils::ToOUString( const String& s ) return OUString( s.GetBuffer(), s.Len() ); } -OUString XclXmlUtils::ToOUString( ScDocument& rDocument, const ScAddress& rAddress, ScTokenArray* pTokenArray ) +OUString XclXmlUtils::ToOUString( ScDocument& rDocument, const ScAddress& rAddress, + ScTokenArray* pTokenArray, const FormulaCompiler::OpCodeMapPtr & xOpCodeMap ) { ScCompiler aCompiler( &rDocument, rAddress, *pTokenArray); - aCompiler.SetGrammar(FormulaGrammar::GRAM_ENGLISH_XL_A1); - String s; - aCompiler.CreateStringFromTokenArray( s ); - return ToOUString( s ); + if (xOpCodeMap) + { + aCompiler.SetFormulaLanguage( xOpCodeMap ); + /* TODO: The correct ref convention would be CONV_XL_OOX but that would + * need aCompiler.SetExternalLinks() and so far we don't have the links + * mapping. */ + aCompiler.SetRefConvention( formula::FormulaGrammar::CONV_XL_A1 ); + } + else + { + SAL_WARN( "sc", "XclXmlUtils::ToOUString - no opcodemap, dumb fallback to PODF"); + aCompiler.SetGrammar(FormulaGrammar::GRAM_ENGLISH_XL_A1); + } + + OUStringBuffer aBuffer( pTokenArray->GetLen() * 5 ); + aCompiler.CreateStringFromTokenArray( aBuffer ); + return aBuffer.makeStringAndClear(); } OUString XclXmlUtils::ToOUString( const XclExpString& s ) diff --git a/sc/source/filter/excel/xetable.cxx b/sc/source/filter/excel/xetable.cxx index 69e2fef78555..ec54e15a4630 100644 --- a/sc/source/filter/excel/xetable.cxx +++ b/sc/source/filter/excel/xetable.cxx @@ -900,7 +900,8 @@ void XclExpFormulaCell::SaveXml( XclExpXmlStream& rStrm ) // OOXTODO: XML_si, uint // OOXTODO: XML_bx bool FSEND ); - rWorksheet->writeEscaped( XclXmlUtils::ToOUString( *mrScFmlaCell.GetDocument(), mrScFmlaCell.aPos, mrScFmlaCell.GetCode() ) ); + rWorksheet->writeEscaped( XclXmlUtils::ToOUString( *mrScFmlaCell.GetDocument(), mrScFmlaCell.aPos, + mrScFmlaCell.GetCode(), rStrm.GetRoot().GetOpCodeMap() ) ); rWorksheet->endElement( XML_f ); if( strcmp( sType, "inlineStr" ) == 0 ) { diff --git a/sc/source/filter/inc/formulabase.hxx b/sc/source/filter/inc/formulabase.hxx index bd5c44557214..22e3ab2f1c45 100644 --- a/sc/source/filter/inc/formulabase.hxx +++ b/sc/source/filter/inc/formulabase.hxx @@ -539,7 +539,8 @@ struct FunctionProviderImpl; class FunctionProvider // not derived from WorkbookHelper to make it usable in file dumpers { public: - explicit FunctionProvider( FilterType eFilter, BiffType eBiff, bool bImportFilter ); + explicit FunctionProvider( FilterType eFilter, BiffType eBiff, bool bImportFilter, + bool bCallerKnowsAboutMacroExport ); virtual ~FunctionProvider(); /** Returns the function info for an OOXML function name, or 0 on error. */ @@ -580,7 +581,8 @@ class OpCodeProvider : public FunctionProvider // not derived from WorkbookHelpe public: explicit OpCodeProvider( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& rxModelFactory, - FilterType eFilter, BiffType eBiff, bool bImportFilter ); + FilterType eFilter, BiffType eBiff, bool bImportFilter, + bool bCallerKnowsAboutMacroExport = false ); virtual ~OpCodeProvider(); /** Returns the structure containing all token op-codes for operators and diff --git a/sc/source/filter/inc/xeroot.hxx b/sc/source/filter/inc/xeroot.hxx index cce5d1f6298e..5eb6e5371eb3 100644 --- a/sc/source/filter/inc/xeroot.hxx +++ b/sc/source/filter/inc/xeroot.hxx @@ -23,6 +23,7 @@ #include <com/sun/star/beans/NamedValue.hpp> #include "xlroot.hxx" +#include "compiler.hxx" #include <boost/shared_ptr.hpp> // Forward declarations of objects in public use ============================== @@ -89,6 +90,8 @@ struct XclExpRootData : public XclRootData XclExpPTableMgrRef mxPTableMgr; /// All pivot tables and pivot caches. XclExpDxfsRef mxDxfs; /// All delta formatting entries + ScCompiler::OpCodeMapPtr mxOpCodeMap; /// mapping between op-codes and names + bool mbRelUrl; /// true = Store URLs relative. explicit XclExpRootData( XclBiff eBiff, SfxMedium& rMedium, @@ -142,6 +145,8 @@ public: XclExpPivotTableManager& GetPivotTableManager() const; /** Returns the differential formatting list */ XclExpDxfs& GetDxfs() const; + /** Returns the op-code mapping */ + ScCompiler::OpCodeMapPtr GetOpCodeMap() const; /** Is called when export filter starts to create the Excel document (all BIFF versions). */ void InitializeConvert(); diff --git a/sc/source/filter/inc/xestream.hxx b/sc/source/filter/inc/xestream.hxx index 3c22bda1c096..9f0f91ae5451 100644 --- a/sc/source/filter/inc/xestream.hxx +++ b/sc/source/filter/inc/xestream.hxx @@ -34,6 +34,7 @@ #include "xlstream.hxx" #include "xestring.hxx" +#include "compiler.hxx" #include <filter/msfilter/mscodec.hxx> #include <vector> @@ -286,7 +287,8 @@ public: static ::rtl::OUString ToOUString( const char* s ); static ::rtl::OUString ToOUString( const ScfUInt16Vec& rBuffer, sal_Int32 nStart = 0, sal_Int32 nLength = -1 ); static ::rtl::OUString ToOUString( const String& s ); - static ::rtl::OUString ToOUString( ScDocument& rDocument, const ScAddress& rAddress, ScTokenArray* pTokenArray ); + static ::rtl::OUString ToOUString( ScDocument& rDocument, const ScAddress& rAddress, + ScTokenArray* pTokenArray, const ScCompiler::OpCodeMapPtr & xOpCodeMap ); static ::rtl::OUString ToOUString( const XclExpString& s ); static const char* ToPsz( bool b ); diff --git a/sc/source/filter/oox/formulabase.cxx b/sc/source/filter/oox/formulabase.cxx index f14061c41386..ebbad4585865 100644 --- a/sc/source/filter/oox/formulabase.cxx +++ b/sc/source/filter/oox/formulabase.cxx @@ -209,6 +209,12 @@ const sal_uInt16 FUNCFLAG_MACROFUNC = 0x0040; /// Function is a macro- const sal_uInt16 FUNCFLAG_MACROCMD = 0x0080; /// Function is a macro-sheet command. const sal_uInt16 FUNCFLAG_ALWAYSVAR = 0x0100; /// Function is always represented by a tFuncVar token. const sal_uInt16 FUNCFLAG_PARAMPAIRS = 0x0200; /// Optional parameters are expected to appear in pairs. +const sal_uInt16 FUNCFLAG_MACROCALL_FN = 0x0400; /** Function is stored as macro call in Excel (_xlfn. prefix) + for OOXML. OOXML name MUST exist. Do not use without + FUNCFLAG_MACROCALL. */ +const sal_uInt16 FUNCFLAG_MACROCALL_NEW = FUNCFLAG_MACROCALL | FUNCFLAG_MACROCALL_FN; /** New Excel functions not + defined in OOXML, _xlfn. prefix in all formats. OOXML name + must exist. */ /// Converts a function library index (value of enum FunctionLibraryType) to function flags. #define FUNCLIB_TO_FUNCFLAGS( funclib_index ) static_cast< sal_uInt16 >( static_cast< sal_uInt8 >( funclib_index ) << 12 ) @@ -722,7 +728,7 @@ static const FunctionData saFuncTableOox[] = /* FIXME: BIFF12 function identifer available? Where to obtain? */ static const FunctionData saFuncTable2013[] = { - { "IFNA", "IFNA", NOID, NOID, 2, 2, V, { VO, RO }, FUNCFLAG_MACROCALL }, + { "IFNA", "IFNA", NOID, NOID, 2, 2, V, { VO, RO }, FUNCFLAG_MACROCALL_NEW }, }; /** Functions defined by OpenFormula, but not supported by Calc or by Excel. */ @@ -825,7 +831,8 @@ struct FunctionProviderImpl FuncIdMap maBiffFuncs; /// Maps BIFF2-BIFF8 function indexes to function data. FuncNameMap maMacroFuncs; /// Maps macro function names to function data. - explicit FunctionProviderImpl( FilterType eFilter, BiffType eBiff, bool bImportFilter ); + explicit FunctionProviderImpl( FilterType eFilter, BiffType eBiff, bool bImportFilter, + bool bCallerKnowsAboutMacroExport ); private: /** Creates and inserts a function info struct from the passed function data. */ @@ -839,9 +846,16 @@ private: // ---------------------------------------------------------------------------- -FunctionProviderImpl::FunctionProviderImpl( FilterType eFilter, BiffType eBiff, bool bImportFilter ) +FunctionProviderImpl::FunctionProviderImpl( FilterType eFilter, BiffType eBiff, bool bImportFilter, + bool bCallerKnowsAboutMacroExport ) { - OSL_ENSURE( bImportFilter, "FunctionProviderImpl::FunctionProviderImpl - need special handling for macro call functions" ); + // NOTE: this warning is only applicable if called for not yet existing + // external export filter, not the Calc internal conversion from binary to + // OOXML that also uses this mapping. Which is the only reason for + // bCallerKnowsAboutMacroExport, to suppress this warning then. + OSL_ENSURE( bImportFilter || bCallerKnowsAboutMacroExport, + "FunctionProviderImpl::FunctionProviderImpl - need special handling for macro call functions" ); + (void)bCallerKnowsAboutMacroExport; sal_uInt8 nMaxParam = 0; switch( eFilter ) { @@ -890,6 +904,11 @@ void FunctionProviderImpl::initFunc( const FunctionData& rFuncData, sal_uInt8 nM OSL_ENSURE( !xFuncInfo->maOoxFuncName.isEmpty(), "FunctionProviderImpl::initFunc - missing OOXML function name" ); OSL_ENSURE( !getFlag( rFuncData.mnFlags, FUNCFLAG_MACROCALLODF ), "FunctionProviderImpl::initFunc - unexpected flag FUNCFLAG_MACROCALLODF" ); xFuncInfo->maBiffMacroName = "_xlfn." + xFuncInfo->maOoxFuncName; + if( getFlag( rFuncData.mnFlags, FUNCFLAG_MACROCALL_FN ) ) + { + xFuncInfo->maOoxFuncName = "_xlfn." + xFuncInfo->maOoxFuncName; + //! From here on maOoxFuncName contains the _xlfn. prefix! + } } else if( getFlag( rFuncData.mnFlags, FUNCFLAG_MACROCALLODF ) ) { @@ -936,8 +955,9 @@ void FunctionProviderImpl::initFuncs( const FunctionData* pBeg, const FunctionDa // ---------------------------------------------------------------------------- -FunctionProvider::FunctionProvider( FilterType eFilter, BiffType eBiff, bool bImportFilter ) : - mxFuncImpl( new FunctionProviderImpl( eFilter, eBiff, bImportFilter ) ) +FunctionProvider::FunctionProvider( FilterType eFilter, BiffType eBiff, bool bImportFilter, + bool bCallerKnowsAboutMacroExport ) : + mxFuncImpl( new FunctionProviderImpl( eFilter, eBiff, bImportFilter, bCallerKnowsAboutMacroExport ) ) { } @@ -1269,8 +1289,8 @@ bool OpCodeProviderImpl::initFuncOpCodes( const ApiTokenMap& rIntFuncTokenMap, c // ---------------------------------------------------------------------------- OpCodeProvider::OpCodeProvider( const Reference< XMultiServiceFactory >& rxModelFactory, - FilterType eFilter, BiffType eBiff, bool bImportFilter ) : - FunctionProvider( eFilter, eBiff, bImportFilter ), + FilterType eFilter, BiffType eBiff, bool bImportFilter, bool bCallerKnowsAboutMacroExport ) : + FunctionProvider( eFilter, eBiff, bImportFilter, bCallerKnowsAboutMacroExport ), mxOpCodeImpl( new OpCodeProviderImpl( getFuncs(), rxModelFactory ) ) { } diff --git a/sc/source/filter/xcl97/XclExpChangeTrack.cxx b/sc/source/filter/xcl97/XclExpChangeTrack.cxx index 830172e02bc5..1c50a5cb1f9d 100644 --- a/sc/source/filter/xcl97/XclExpChangeTrack.cxx +++ b/sc/source/filter/xcl97/XclExpChangeTrack.cxx @@ -981,7 +981,8 @@ static void lcl_WriteCell( XclExpXmlStream& rStrm, sal_Int32 nElement, const ScA FSEND ); pStream->writeEscaped( XclXmlUtils::ToOUString( *pData->mpFormulaCell->GetDocument(), - pData->mpFormulaCell->aPos, pData->mpFormulaCell->GetCode() ) ); + pData->mpFormulaCell->aPos, pData->mpFormulaCell->GetCode(), + rStrm.GetRoot().GetOpCodeMap() ) ); pStream->endElement( XML_f ); break; case EXC_CHTR_TYPE_STRING: |