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: ooxformulaparser.cxx,v $
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/ooxformulaparser.hxx"
32 #include <com/sun/star/uno/XComponentContext.hpp>
33 #include "oox/xls/formulaparser.hxx"
35 using ::rtl::OUString
;
36 using ::com::sun::star::uno::Any
;
37 using ::com::sun::star::uno::Exception
;
38 using ::com::sun::star::uno::Reference
;
39 using ::com::sun::star::uno::RuntimeException
;
40 using ::com::sun::star::uno::Sequence
;
41 using ::com::sun::star::uno::UNO_QUERY_THROW
;
42 using ::com::sun::star::uno::XComponentContext
;
43 using ::com::sun::star::uno::XInterface
;
44 using ::com::sun::star::lang::XMultiServiceFactory
;
45 using ::com::sun::star::table::CellAddress
;
46 using ::com::sun::star::sheet::FormulaToken
;
51 // ============================================================================
53 class OOXMLFormulaParserImpl
: private FormulaFinalizer
56 explicit OOXMLFormulaParserImpl( const Reference
< XMultiServiceFactory
>& rxFactory
);
58 Sequence
< FormulaToken
> parseFormula( const OUString
& rFormula
, const CellAddress
& rReferencePos
);
61 virtual const FunctionInfo
* resolveBadFuncName( const OUString
& rTokenData
) const;
64 ApiParserWrapper maApiParser
;
67 // ----------------------------------------------------------------------------
69 OOXMLFormulaParserImpl::OOXMLFormulaParserImpl( const Reference
< XMultiServiceFactory
>& rxFactory
) :
70 FormulaFinalizer( OpCodeProvider( rxFactory
, FILTER_OOX
, BIFF_UNKNOWN
, true ) ),
71 maApiParser( rxFactory
, *this )
75 Sequence
< FormulaToken
> OOXMLFormulaParserImpl::parseFormula( const OUString
& rFormula
, const CellAddress
& rReferencePos
)
77 return finalizeTokenArray( maApiParser
.parseFormula( rFormula
, rReferencePos
) );
80 const FunctionInfo
* OOXMLFormulaParserImpl::resolveBadFuncName( const OUString
& rTokenData
) const
82 /* Try to parse calls to library functions. The format of such a function
84 "'<path-to-office-install>\Library\<libname>'!<funcname>". */
86 // the string has to start with an apostroph (followed by the library URL)
87 if( (rTokenData
.getLength() >= 6) && (rTokenData
[ 0 ] == '\'') )
89 // library URL and function name are separated by an exclamation mark
90 sal_Int32 nExclamPos
= rTokenData
.lastIndexOf( '!' );
91 if( (1 < nExclamPos
) && (nExclamPos
+ 1 < rTokenData
.getLength()) && (rTokenData
[ nExclamPos
- 1 ] == '\'') )
93 // find the last backslash that separates library path and name
94 sal_Int32 nFileSep
= rTokenData
.lastIndexOf( '\\', nExclamPos
- 2 );
97 // find preceding backslash that separates the last directory name
98 sal_Int32 nDirSep
= rTokenData
.lastIndexOf( '\\', nFileSep
- 1 );
99 // function library is located in a directory called 'library'
100 if( (nDirSep
> 0) && rTokenData
.matchIgnoreAsciiCaseAsciiL( RTL_CONSTASCII_STRINGPARAM( "\\LIBRARY\\" ), nDirSep
) )
102 // try to find a function info for the function name
103 OUString aFuncName
= rTokenData
.copy( nExclamPos
+ 1 ).toAsciiUpperCase();
104 const FunctionInfo
* pFuncInfo
= getFuncInfoFromOoxFuncName( aFuncName
);
105 if( pFuncInfo
&& (pFuncInfo
->meFuncLibType
!= FUNCLIB_UNKNOWN
) )
107 // check that the name of the library matches
108 OUString aLibName
= rTokenData
.copy( nFileSep
+ 1, nExclamPos
- nFileSep
- 2 );
109 if( pFuncInfo
->meFuncLibType
== getFuncLibTypeFromLibraryName( aLibName
) )
119 // ============================================================================
121 class OOXMLFormulaPrinterImpl
: public OpCodeProvider
124 explicit OOXMLFormulaPrinterImpl( const Reference
< XMultiServiceFactory
>& rxFactory
);
127 ApiParserWrapper maApiParser
;
130 // ----------------------------------------------------------------------------
132 OOXMLFormulaPrinterImpl::OOXMLFormulaPrinterImpl( const Reference
< XMultiServiceFactory
>& rxFactory
) :
133 OpCodeProvider( rxFactory
, FILTER_OOX
, BIFF_UNKNOWN
, false ),
134 maApiParser( rxFactory
, *this )
138 // ============================================================================
140 Sequence
< OUString
> OOXMLFormulaParser_getSupportedServiceNames()
142 Sequence
< OUString
> aServiceNames( 1 );
143 aServiceNames
[ 0 ] = CREATE_OUSTRING( "com.sun.star.sheet.FilterFormulaParser" );
144 return aServiceNames
;
147 OUString
OOXMLFormulaParser_getImplementationName()
149 return CREATE_OUSTRING( "com.sun.star.comp.oox.OOXMLFormulaParser" );
152 Reference
< XInterface
> SAL_CALL
OOXMLFormulaParser_createInstance( const Reference
< XComponentContext
>& ) throw( Exception
)
154 return static_cast< ::cppu::OWeakObject
* >( new OOXMLFormulaParser
);
157 // ============================================================================
159 OOXMLFormulaParser::OOXMLFormulaParser()
163 OOXMLFormulaParser::~OOXMLFormulaParser()
167 // com.sun.star.lang.XServiceInfo interface -----------------------------------
169 OUString SAL_CALL
OOXMLFormulaParser::getImplementationName() throw( RuntimeException
)
171 return OOXMLFormulaParser_getImplementationName();
174 sal_Bool SAL_CALL
OOXMLFormulaParser::supportsService( const OUString
& rService
) throw( RuntimeException
)
176 const Sequence
< OUString
> aServices( OOXMLFormulaParser_getSupportedServiceNames() );
177 const OUString
* pArray
= aServices
.getConstArray();
178 const OUString
* pArrayEnd
= pArray
+ aServices
.getLength();
179 return ::std::find( pArray
, pArrayEnd
, rService
) != pArrayEnd
;
182 Sequence
< OUString
> SAL_CALL
OOXMLFormulaParser::getSupportedServiceNames() throw( RuntimeException
)
184 return OOXMLFormulaParser_getSupportedServiceNames();
187 // com.sun.star.lang.XInitialization interface --------------------------------
189 void SAL_CALL
OOXMLFormulaParser::initialize( const Sequence
< Any
>& rArgs
) throw( Exception
, RuntimeException
)
191 OSL_ENSURE( rArgs
.hasElements(), "OOXMLFormulaParser::initialize - missing arguments" );
192 if( !rArgs
.hasElements() )
193 throw RuntimeException();
194 mxComponent
.set( rArgs
[ 0 ], UNO_QUERY_THROW
);
197 // com.sun.star.sheet.XFilterFormulaParser interface --------------------------
199 OUString SAL_CALL
OOXMLFormulaParser::getSupportedNamespace() throw( RuntimeException
)
201 return CREATE_OUSTRING( "http://schemas.microsoft.com/office/excel/formula" );
204 // com.sun.star.sheet.XFormulaParser interface --------------------------------
206 Sequence
< FormulaToken
> SAL_CALL
OOXMLFormulaParser::parseFormula(
207 const OUString
& rFormula
, const CellAddress
& rReferencePos
) throw( RuntimeException
)
211 Reference
< XMultiServiceFactory
> xFactory( mxComponent
, UNO_QUERY_THROW
);
212 mxParserImpl
.reset( new OOXMLFormulaParserImpl( xFactory
) );
214 return mxParserImpl
->parseFormula( rFormula
, rReferencePos
);
217 OUString SAL_CALL
OOXMLFormulaParser::printFormula(
218 const Sequence
< FormulaToken
>& /*rTokens*/, const CellAddress
& /*rReferencePos*/ ) throw( RuntimeException
)
221 throw RuntimeException();
224 // ============================================================================