LibreOffice Module sc (master)  1
ooxformulaparser.cxx
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  * Licensed to the Apache Software Foundation (ASF) under one or more
12  * contributor license agreements. See the NOTICE file distributed
13  * with this work for additional information regarding copyright
14  * ownership. The ASF licenses this file to you under the Apache
15  * License, Version 2.0 (the "License"); you may not use this file
16  * except in compliance with the License. You may obtain a copy of
17  * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 
20 #include <ooxformulaparser.hxx>
21 
22 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
23 #include <com/sun/star/lang/XComponent.hpp>
24 #include <osl/diagnose.h>
26 #include <formulaparser.hxx>
27 
28 namespace com::sun::star::uno { class XComponentContext; }
29 
30 namespace oox::xls {
31 
32 using namespace ::com::sun::star::lang;
33 using namespace ::com::sun::star::sheet;
34 using namespace ::com::sun::star::table;
35 using namespace ::com::sun::star::uno;
36 
38 {
39 public:
40  explicit OOXMLFormulaParserImpl( const Reference< XMultiServiceFactory >& rxModelFactory );
41 
42  Sequence< FormulaToken > parseFormula( const OUString& rFormula, const ScAddress& rReferencePos );
43 
44 protected:
45  virtual const FunctionInfo* resolveBadFuncName( const OUString& rTokenData ) const override;
46 
47 private:
49 };
50 
51 OOXMLFormulaParserImpl::OOXMLFormulaParserImpl( const Reference< XMultiServiceFactory >& rxModelFactory ) :
52  FormulaFinalizer( OpCodeProvider( rxModelFactory, true ) ),
53  maApiParser( rxModelFactory, *this )
54 {
55 }
56 
57 Sequence< FormulaToken > OOXMLFormulaParserImpl::parseFormula( const OUString& rFormula, const ScAddress& rReferencePos )
58 {
59  return finalizeTokenArray( maApiParser.parseFormula( rFormula, rReferencePos ) );
60 }
61 
62 const FunctionInfo* OOXMLFormulaParserImpl::resolveBadFuncName( const OUString& rTokenData ) const
63 {
64  /* Try to parse calls to library functions. The format of such a function
65  call is assumed to be
66  "'<path-to-office-install>\Library<libname>'!<funcname>". */
67 
68  // the string has to start with an apostroph (followed by the library URL)
69  if( (rTokenData.getLength() >= 6) && (rTokenData[ 0 ] == '\'') )
70  {
71  // library URL and function name are separated by an exclamation mark
72  sal_Int32 nExclamPos = rTokenData.lastIndexOf( '!' );
73  if( (1 < nExclamPos) && (nExclamPos + 1 < rTokenData.getLength()) && (rTokenData[ nExclamPos - 1 ] == '\'') )
74  {
75  // find the last backslash that separates library path and name
76  sal_Int32 nFileSep = rTokenData.lastIndexOf( '\\', nExclamPos - 2 );
77  if( nFileSep > 1 )
78  {
79  // find preceding backslash that separates the last directory name
80  sal_Int32 nDirSep = rTokenData.lastIndexOf( '\\', nFileSep - 1 );
81  // function library is located in a directory called 'library'
82  if( (nDirSep > 0) && rTokenData.matchIgnoreAsciiCase( "\\LIBRARY\\", nDirSep ) )
83  {
84  // try to find a function info for the function name
85  OUString aFuncName = rTokenData.copy( nExclamPos + 1 ).toAsciiUpperCase();
86  const FunctionInfo* pFuncInfo = getFuncInfoFromOoxFuncName( aFuncName );
87  if( pFuncInfo && (pFuncInfo->meFuncLibType != FUNCLIB_UNKNOWN) )
88  {
89  // check that the name of the library matches
90  OUString aLibName = rTokenData.copy( nFileSep + 1, nExclamPos - nFileSep - 2 );
91  if( pFuncInfo->meFuncLibType == getFuncLibTypeFromLibraryName( aLibName ) )
92  return pFuncInfo;
93  }
94  }
95  }
96  }
97  }
98  return nullptr;
99 }
100 
102 {
103 }
104 
106 {
107 }
108 
109 // com.sun.star.lang.XServiceInfo interface -----------------------------------
111 {
112  return "com.sun.star.comp.oox.xls.FormulaParser";
113 }
114 
115 sal_Bool SAL_CALL OOXMLFormulaParser::supportsService( const OUString& rService )
116 {
117  return cppu::supportsService(this, rService);
118 }
119 
121 {
122  return { "com.sun.star.sheet.FilterFormulaParser" };
123 }
124 
125 // com.sun.star.lang.XInitialization interface --------------------------------
126 
127 void SAL_CALL OOXMLFormulaParser::initialize( const Sequence< Any >& rArgs )
128 {
129  OSL_ENSURE( rArgs.hasElements(), "OOXMLFormulaParser::initialize - missing arguments" );
130  if( !rArgs.hasElements() )
131  throw RuntimeException();
132  mxComponent.set( rArgs[ 0 ], UNO_QUERY_THROW );
133 }
134 
135 // com.sun.star.sheet.XFilterFormulaParser interface --------------------------
136 
138 {
139  return "http://schemas.microsoft.com/office/excel/formula";
140 }
141 
142 // com.sun.star.sheet.XFormulaParser interface --------------------------------
143 
144 Sequence< FormulaToken > SAL_CALL OOXMLFormulaParser::parseFormula(
145  const OUString& rFormula, const CellAddress& rReferencePos )
146 {
147  if( !mxParserImpl )
148  {
149  Reference< XMultiServiceFactory > xModelFactory( mxComponent, UNO_QUERY_THROW );
150  mxParserImpl = std::make_shared<OOXMLFormulaParserImpl>( xModelFactory );
151  }
152  return mxParserImpl->parseFormula( rFormula,
153  ScAddress(rReferencePos.Column, rReferencePos.Row, rReferencePos.Sheet) );
154 }
155 
157  const Sequence< FormulaToken >& /*rTokens*/, const CellAddress& /*rReferencePos*/ )
158 {
159  // not implemented
160  throw RuntimeException();
161 }
162 
163 } // namespace oox::xls
164 
165 
166 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
168  css::uno::Sequence<css::uno::Any> const &)
169 {
170  return cppu::acquire(new oox::xls::OOXMLFormulaParser());
171 }
172 
173 
174 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
virtual OUString SAL_CALL printFormula(const css::uno::Sequence< css::sheet::FormulaToken > &rTokens, const css::table::CellAddress &rReferencePos) override
OOXMLFormulaParserImpl(const Reference< XMultiServiceFactory > &rxModelFactory)
ApiParserWrapper maApiParser
Represents information for a spreadsheet function.
virtual OUString SAL_CALL getSupportedNamespace() override
const FunctionInfo * getFuncInfoFromOoxFuncName(const OUString &rFuncName) const
Returns the function info for an OOXML function name, or 0 on error.
bool CPPUHELPER_DLLPUBLIC supportsService(css::lang::XServiceInfo *implementation, rtl::OUString const &name)
SAL_DLLPUBLIC_EXPORT css::uno::XInterface * com_sun_star_comp_oox_xls_FormulaParser_get_implementation(css::uno::XComponentContext *, css::uno::Sequence< css::uno::Any > const &)
A generic formula token array finalizer.
Provides access to API op-codes for all available formula tokens and to function info structs for all...
virtual void SAL_CALL initialize(const css::uno::Sequence< css::uno::Any > &rArgs) override
virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override
virtual sal_Bool SAL_CALL supportsService(const OUString &rService) override
ApiTokenSequence finalizeTokenArray(const ApiTokenSequence &rTokens)
Finalizes and returns the passed token array.
unsigned char sal_Bool
virtual css::uno::Sequence< css::sheet::FormulaToken > SAL_CALL parseFormula(const OUString &rFormula, const css::table::CellAddress &rReferencePos) override
virtual ~OOXMLFormulaParser() override
FunctionLibraryType meFuncLibType
Programmatic function name for external functions.
static FunctionLibraryType getFuncLibTypeFromLibraryName(const OUString &rLibraryName)
Returns the library type associated with the passed URL of a function library (function add-in)...
ApiTokenSequence parseFormula(const OUString &rFormula, const ScAddress &rRefPos)
Calls the XFormulaParser::parseFormula() function of the API parser.
OOXML formula parser/compiler service for usage in ODF filters.
Sequence< FormulaToken > parseFormula(const OUString &rFormula, const ScAddress &rReferencePos)
virtual const FunctionInfo * resolveBadFuncName(const OUString &rTokenData) const override
Derived classed may try to find a function info struct from the passed string extracted from an OPCOD...
A wrapper around the FormulaParser service provided by the Calc document.
css::uno::Reference< css::lang::XComponent > mxComponent
virtual OUString SAL_CALL getImplementationName() override