1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 24 #include "oox/xls/ooxformulaparser.hxx" 25 26 #include <com/sun/star/uno/XComponentContext.hpp> 27 #include "oox/xls/formulaparser.hxx" 28 29 namespace oox { 30 namespace xls { 31 32 // ============================================================================ 33 34 using namespace ::com::sun::star::lang; 35 using namespace ::com::sun::star::sheet; 36 using namespace ::com::sun::star::table; 37 using namespace ::com::sun::star::uno; 38 39 using ::rtl::OUString; 40 41 // ============================================================================ 42 43 class OOXMLFormulaParserImpl : private FormulaFinalizer 44 { 45 public: 46 explicit OOXMLFormulaParserImpl( const Reference< XMultiServiceFactory >& rxModelFactory ); 47 48 Sequence< FormulaToken > parseFormula( const OUString& rFormula, const CellAddress& rReferencePos ); 49 50 protected: 51 virtual const FunctionInfo* resolveBadFuncName( const OUString& rTokenData ) const; 52 53 private: 54 ApiParserWrapper maApiParser; 55 }; 56 57 // ---------------------------------------------------------------------------- 58 59 OOXMLFormulaParserImpl::OOXMLFormulaParserImpl( const Reference< XMultiServiceFactory >& rxModelFactory ) : 60 FormulaFinalizer( OpCodeProvider( rxModelFactory, FILTER_OOXML, BIFF_UNKNOWN, true ) ), 61 maApiParser( rxModelFactory, *this ) 62 { 63 } 64 65 Sequence< FormulaToken > OOXMLFormulaParserImpl::parseFormula( const OUString& rFormula, const CellAddress& rReferencePos ) 66 { 67 return finalizeTokenArray( maApiParser.parseFormula( rFormula, rReferencePos ) ); 68 } 69 70 const FunctionInfo* OOXMLFormulaParserImpl::resolveBadFuncName( const OUString& rTokenData ) const 71 { 72 /* Try to parse calls to library functions. The format of such a function 73 call is assumed to be 74 "'<path-to-office-install>\Library\<libname>'!<funcname>". */ 75 76 // the string has to start with an apostroph (followed by the library URL) 77 if( (rTokenData.getLength() >= 6) && (rTokenData[ 0 ] == '\'') ) 78 { 79 // library URL and function name are separated by an exclamation mark 80 sal_Int32 nExclamPos = rTokenData.lastIndexOf( '!' ); 81 if( (1 < nExclamPos) && (nExclamPos + 1 < rTokenData.getLength()) && (rTokenData[ nExclamPos - 1 ] == '\'') ) 82 { 83 // find the last backslash that separates library path and name 84 sal_Int32 nFileSep = rTokenData.lastIndexOf( '\\', nExclamPos - 2 ); 85 if( nFileSep > 1 ) 86 { 87 // find preceding backslash that separates the last directory name 88 sal_Int32 nDirSep = rTokenData.lastIndexOf( '\\', nFileSep - 1 ); 89 // function library is located in a directory called 'library' 90 if( (nDirSep > 0) && rTokenData.matchIgnoreAsciiCaseAsciiL( RTL_CONSTASCII_STRINGPARAM( "\\LIBRARY\\" ), nDirSep ) ) 91 { 92 // try to find a function info for the function name 93 OUString aFuncName = rTokenData.copy( nExclamPos + 1 ).toAsciiUpperCase(); 94 const FunctionInfo* pFuncInfo = getFuncInfoFromOoxFuncName( aFuncName ); 95 if( pFuncInfo && (pFuncInfo->meFuncLibType != FUNCLIB_UNKNOWN) ) 96 { 97 // check that the name of the library matches 98 OUString aLibName = rTokenData.copy( nFileSep + 1, nExclamPos - nFileSep - 2 ); 99 if( pFuncInfo->meFuncLibType == getFuncLibTypeFromLibraryName( aLibName ) ) 100 return pFuncInfo; 101 } 102 } 103 } 104 } 105 } 106 return 0; 107 } 108 109 // ============================================================================ 110 111 class OOXMLFormulaPrinterImpl : public OpCodeProvider 112 { 113 public: 114 explicit OOXMLFormulaPrinterImpl( const Reference< XMultiServiceFactory >& rxModelFactory ); 115 116 private: 117 ApiParserWrapper maApiParser; 118 }; 119 120 // ---------------------------------------------------------------------------- 121 122 OOXMLFormulaPrinterImpl::OOXMLFormulaPrinterImpl( const Reference< XMultiServiceFactory >& rxModelFactory ) : 123 OpCodeProvider( rxModelFactory, FILTER_OOXML, BIFF_UNKNOWN, false ), 124 maApiParser( rxModelFactory, *this ) 125 { 126 } 127 128 // ============================================================================ 129 130 Sequence< OUString > OOXMLFormulaParser_getSupportedServiceNames() 131 { 132 Sequence< OUString > aServiceNames( 1 ); 133 aServiceNames[ 0 ] = CREATE_OUSTRING( "com.sun.star.sheet.FilterFormulaParser" ); 134 return aServiceNames; 135 } 136 137 OUString OOXMLFormulaParser_getImplementationName() 138 { 139 return CREATE_OUSTRING( "com.sun.star.comp.oox.xls.FormulaParser" ); 140 } 141 142 Reference< XInterface > SAL_CALL OOXMLFormulaParser_createInstance( const Reference< XComponentContext >& ) throw( Exception ) 143 { 144 return static_cast< ::cppu::OWeakObject* >( new OOXMLFormulaParser ); 145 } 146 147 // ============================================================================ 148 149 OOXMLFormulaParser::OOXMLFormulaParser() 150 { 151 } 152 153 OOXMLFormulaParser::~OOXMLFormulaParser() 154 { 155 } 156 157 // com.sun.star.lang.XServiceInfo interface ----------------------------------- 158 159 OUString SAL_CALL OOXMLFormulaParser::getImplementationName() throw( RuntimeException ) 160 { 161 return OOXMLFormulaParser_getImplementationName(); 162 } 163 164 sal_Bool SAL_CALL OOXMLFormulaParser::supportsService( const OUString& rService ) throw( RuntimeException ) 165 { 166 const Sequence< OUString > aServices( OOXMLFormulaParser_getSupportedServiceNames() ); 167 const OUString* pArray = aServices.getConstArray(); 168 const OUString* pArrayEnd = pArray + aServices.getLength(); 169 return ::std::find( pArray, pArrayEnd, rService ) != pArrayEnd; 170 } 171 172 Sequence< OUString > SAL_CALL OOXMLFormulaParser::getSupportedServiceNames() throw( RuntimeException ) 173 { 174 return OOXMLFormulaParser_getSupportedServiceNames(); 175 } 176 177 // com.sun.star.lang.XInitialization interface -------------------------------- 178 179 void SAL_CALL OOXMLFormulaParser::initialize( const Sequence< Any >& rArgs ) throw( Exception, RuntimeException ) 180 { 181 OSL_ENSURE( rArgs.hasElements(), "OOXMLFormulaParser::initialize - missing arguments" ); 182 if( !rArgs.hasElements() ) 183 throw RuntimeException(); 184 mxComponent.set( rArgs[ 0 ], UNO_QUERY_THROW ); 185 } 186 187 // com.sun.star.sheet.XFilterFormulaParser interface -------------------------- 188 189 OUString SAL_CALL OOXMLFormulaParser::getSupportedNamespace() throw( RuntimeException ) 190 { 191 return CREATE_OUSTRING( "http://schemas.microsoft.com/office/excel/formula" ); 192 } 193 194 // com.sun.star.sheet.XFormulaParser interface -------------------------------- 195 196 Sequence< FormulaToken > SAL_CALL OOXMLFormulaParser::parseFormula( 197 const OUString& rFormula, const CellAddress& rReferencePos ) throw( RuntimeException ) 198 { 199 if( !mxParserImpl ) 200 { 201 Reference< XMultiServiceFactory > xModelFactory( mxComponent, UNO_QUERY_THROW ); 202 mxParserImpl.reset( new OOXMLFormulaParserImpl( xModelFactory ) ); 203 } 204 return mxParserImpl->parseFormula( rFormula, rReferencePos ); 205 } 206 207 OUString SAL_CALL OOXMLFormulaParser::printFormula( 208 const Sequence< FormulaToken >& /*rTokens*/, const CellAddress& /*rReferencePos*/ ) throw( RuntimeException ) 209 { 210 // not implemented 211 throw RuntimeException(); 212 } 213 214 // ============================================================================ 215 216 } // namespace xls 217 } // namespace oox 218