summaryrefslogtreecommitdiff
path: root/oox/inc/oox/xls/formulaparser.hxx
blob: 599a8af7bf46750c1969d8de8d3649f5fbf836f4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2000, 2010 Oracle and/or its affiliates.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

#ifndef OOX_XLS_FORMULAPARSER_HXX
#define OOX_XLS_FORMULAPARSER_HXX

#include "oox/xls/formulabase.hxx"

namespace oox {
namespace xls {

// formula finalizer ==========================================================

/** A generic formula token array finalizer.

    After building a formula token array from alien binary file formats, or
    parsing an XML formula string using the com.sun.star.sheet.FormulaParser
    service, the token array is still not ready to be put into the spreadsheet
    document. There may be functions with a wrong number of parameters (missing
    but required parameters, or unsupported parameters) or intermediate tokens
    used to encode references to macro functions or add-in functions. This
    helper processes a passed token array and builds a new compatible token
    array.

    Derived classes may add more functionality by overwriting the virtual
    functions.
 */
class FormulaFinalizer : public OpCodeProvider, protected ApiOpCodes
{
public:
    explicit            FormulaFinalizer( const OpCodeProvider& rOpCodeProv );

    /** Finalizes and returns the passed token array. */
    ApiTokenSequence    finalizeTokenArray( const ApiTokenSequence& rTokens );

protected:
    /** Derived classed may try to find a function info struct from the passed
        string extracted from an OPCODE_BAD token.

        @param rTokenData  The string that has been found in an OPCODE_BAD
            token preceding the function parentheses.
     */
    virtual const FunctionInfo* resolveBadFuncName( const ::rtl::OUString& rTokenData ) const;

    /** Derived classed may try to find the name of a defined name with the
        passed index extracted from an OPCODE_NAME token.

        @param nTokenIndex  The index of the defined name that has been found
            in an OPCODE_NAME token preceding the function parentheses.
     */
    virtual ::rtl::OUString resolveDefinedName( sal_Int32 nTokenIndex ) const;

private:
    typedef ::std::vector< const ApiToken* > ParameterPosVector;

    const FunctionInfo* getFunctionInfo( ApiToken& orFuncToken );
    const FunctionInfo* getExternCallInfo( ApiToken& orFuncToken, const ApiToken& rECToken );

    void                processTokens( const ApiToken* pToken, const ApiToken* pTokenEnd );
    const ApiToken*     processParameters( const FunctionInfo& rFuncInfo, const ApiToken* pToken, const ApiToken* pTokenEnd );

    bool                isEmptyParameter( const ApiToken* pToken, const ApiToken* pTokenEnd ) const;
    const ApiToken*     getSingleToken( const ApiToken* pToken, const ApiToken* pTokenEnd ) const;
    const ApiToken*     skipParentheses( const ApiToken* pToken, const ApiToken* pTokenEnd ) const;
    const ApiToken*     findParameters( ParameterPosVector& rParams, const ApiToken* pToken, const ApiToken* pTokenEnd ) const;
    void                appendCalcOnlyParameter( const FunctionInfo& rFuncInfo, size_t nParam );
    void                appendRequiredParameters( const FunctionInfo& rFuncInfo, size_t nParamCount );

    bool                appendFinalToken( const ApiToken& rToken );

private:
    ApiTokenVector      maTokens;
};

// ============================================================================

class FormulaParserImpl;

/** Import formula parser for OOX and BIFF filters.

    This class implements formula import for the OOX and BIFF filter. One
    instance is contained in the global filter data to prevent construction and
    destruction of internal buffers for every imported formula.
 */
class FormulaParser : public FormulaProcessorBase
{
public:
    explicit            FormulaParser( const WorkbookHelper& rHelper );
    virtual             ~FormulaParser();

    /** Converts an XML formula string. */
    void                importFormula(
                            FormulaContext& rContext,
                            const ::rtl::OUString& rFormulaString ) const;

    /** Imports and converts a OOBIN token array from the passed stream. */
    void                importFormula(
                            FormulaContext& rContext,
                            RecordInputStream& rStrm ) const;

    /** Imports and converts a BIFF token array from the passed stream.
        @param pnFmlaSize  Size of the token array. If null is passed, reads
        it from stream (1 byte in BIFF2, 2 bytes otherwise) first. */
    void                importFormula(
                            FormulaContext& rContext,
                            BiffInputStream& rStrm,
                            const sal_uInt16* pnFmlaSize = 0 ) const;

    /** Converts the passed BIFF error code to a similar formula. */
    void                convertErrorToFormula(
                            FormulaContext& rContext,
                            sal_uInt8 nErrorCode ) const;

    /** Converts the passed token index of a defined name to a formula calling that name. */
    void                convertNameToFormula(
                            FormulaContext& rContext,
                            sal_Int32 nTokenIndex ) const;

    /** Converts the passed number into a HYPERLINK formula with the passed URL. */
    void                convertNumberToHyperlink(
                            FormulaContext& rContext,
                            const ::rtl::OUString& rUrl,
                            double fValue ) const;

    /** Converts the passed XML formula to an OLE link target. */
    ::rtl::OUString     importOleTargetLink( const ::rtl::OUString& rFormulaString );

    /** Imports and converts an OLE link target from the passed stream. */
    ::rtl::OUString     importOleTargetLink( RecordInputStream& rStrm );

    /** Imports and converts an OLE link target from the passed stream. */
    ::rtl::OUString     importOleTargetLink(
                            BiffInputStream& rStrm,
                            const sal_uInt16* pnFmlaSize = 0 ) const;

    /** Converts the passed formula to a macro name for a drawing shape. */
    ::rtl::OUString     importMacroName( const ::rtl::OUString& rFormulaString );

private:
    ::std::auto_ptr< FormulaParserImpl > mxImpl;
};

// ============================================================================

} // namespace xls
} // namespace oox

#endif