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: sharedformulabuffer.cxx,v $
10 * $Revision: 1.4.20.1 $
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/sharedformulabuffer.hxx"
32 #include <rtl/ustrbuf.hxx>
33 #include <com/sun/star/sheet/XFormulaTokens.hpp>
34 #include "properties.hxx"
35 #include "oox/helper/propertyset.hxx"
36 #include "oox/helper/recordinputstream.hxx"
37 #include "oox/xls/addressconverter.hxx"
38 #include "oox/xls/biffinputstream.hxx"
39 #include "oox/xls/formulaparser.hxx"
41 using ::rtl::OUString
;
42 using ::rtl::OUStringBuffer
;
43 using ::com::sun::star::uno::Reference
;
44 using ::com::sun::star::uno::Exception
;
45 using ::com::sun::star::uno::UNO_QUERY
;
46 using ::com::sun::star::table::CellAddress
;
47 using ::com::sun::star::table::CellRangeAddress
;
48 using ::com::sun::star::sheet::XFormulaTokens
;
49 using ::com::sun::star::sheet::XNamedRange
;
54 // ============================================================================
58 bool operator==( const CellAddress
& rAddr1
, const CellAddress
& rAddr2
)
61 (rAddr1
.Sheet
== rAddr2
.Sheet
) &&
62 (rAddr1
.Column
== rAddr2
.Column
) &&
63 (rAddr1
.Row
== rAddr2
.Row
);
66 bool lclContains( const CellRangeAddress
& rRange
, const CellAddress
& rAddr
)
69 (rRange
.Sheet
== rAddr
.Sheet
) &&
70 (rRange
.StartColumn
<= rAddr
.Column
) && (rAddr
.Column
<= rRange
.EndColumn
) &&
71 (rRange
.StartRow
<= rAddr
.Row
) && (rAddr
.Row
<= rRange
.EndRow
);
76 // ============================================================================
78 ExtCellFormulaContext::ExtCellFormulaContext( const WorksheetHelper
& rHelper
,
79 const Reference
< XFormulaTokens
>& rxTokens
, const CellAddress
& rCellPos
) :
80 SimpleFormulaContext( rxTokens
, false, false ),
81 WorksheetHelper( rHelper
)
83 setBaseAddress( rCellPos
);
86 void ExtCellFormulaContext::setSharedFormula( const CellAddress
& rBaseAddr
)
88 getSharedFormulas().setSharedFormulaCell( *this, rBaseAddr
);
91 // ============================================================================
93 SharedFormulaBuffer::SharedFormulaBuffer( const WorksheetHelper
& rHelper
) :
94 WorksheetHelper( rHelper
)
98 void SharedFormulaBuffer::importSharedFmla( const OUString
& rFormula
, const OUString
& rSharedRange
, sal_Int32 nSharedId
, const CellAddress
& rBaseAddr
)
100 CellRangeAddress aFmlaRange
;
101 if( getAddressConverter().convertToCellRange( aFmlaRange
, rSharedRange
, getSheetIndex(), true, true ) )
103 // create the defined name representing the shared formula
104 OSL_ENSURE( lclContains( aFmlaRange
, rBaseAddr
), "SharedFormulaBuffer::importSharedFmla - invalid range for shared formula" );
105 BinAddress
aMapKey( nSharedId
, 0 );
106 Reference
< XNamedRange
> xNamedRange
= createDefinedName( aMapKey
);
107 // convert the formula definition
108 Reference
< XFormulaTokens
> xTokens( xNamedRange
, UNO_QUERY
);
111 SimpleFormulaContext
aContext( xTokens
, true, false );
112 aContext
.setBaseAddress( rBaseAddr
);
113 getFormulaParser().importFormula( aContext
, rFormula
);
114 updateCachedCell( rBaseAddr
, aMapKey
);
119 void SharedFormulaBuffer::importSharedFmla( RecordInputStream
& rStrm
, const CellAddress
& rBaseAddr
)
123 CellRangeAddress aFmlaRange
;
124 if( getAddressConverter().convertToCellRange( aFmlaRange
, aRange
, getSheetIndex(), true, true ) )
126 // create the defined name representing the shared formula
127 OSL_ENSURE( lclContains( aFmlaRange
, rBaseAddr
), "SharedFormulaBuffer::importSharedFmla - invalid range for shared formula" );
128 BinAddress
aMapKey( rBaseAddr
);
129 Reference
< XNamedRange
> xNamedRange
= createDefinedName( aMapKey
);
130 // load the formula definition
131 Reference
< XFormulaTokens
> xTokens( xNamedRange
, UNO_QUERY
);
134 SimpleFormulaContext
aContext( xTokens
, true, false );
135 aContext
.setBaseAddress( rBaseAddr
);
136 getFormulaParser().importFormula( aContext
, rStrm
);
137 updateCachedCell( rBaseAddr
, aMapKey
);
142 void SharedFormulaBuffer::importSharedFmla( BiffInputStream
& rStrm
, const CellAddress
& rBaseAddr
)
145 aRange
.read( rStrm
, false ); // always 8bit column indexes
146 CellRangeAddress aFmlaRange
;
147 if( getAddressConverter().convertToCellRange( aFmlaRange
, aRange
, getSheetIndex(), true, true ) )
149 // create the defined name representing the shared formula
150 OSL_ENSURE( lclContains( aFmlaRange
, rBaseAddr
), "SharedFormulaBuffer::importSharedFmla - invalid range for shared formula" );
151 BinAddress
aMapKey( rBaseAddr
);
152 Reference
< XNamedRange
> xNamedRange
= createDefinedName( aMapKey
);
153 // load the formula definition
154 Reference
< XFormulaTokens
> xTokens( xNamedRange
, UNO_QUERY
);
157 rStrm
.skip( 2 ); // flags
158 SimpleFormulaContext
aContext( xTokens
, true, false );
159 aContext
.setBaseAddress( rBaseAddr
);
160 getFormulaParser().importFormula( aContext
, rStrm
);
161 updateCachedCell( rBaseAddr
, aMapKey
);
166 void SharedFormulaBuffer::setSharedFormulaCell( ExtCellFormulaContext
& rContext
, const CellAddress
& rBaseAddr
)
168 if( !implSetSharedFormulaCell( rContext
, BinAddress( rBaseAddr
) ) )
169 if( rContext
.getBaseAddress() == rBaseAddr
)
170 mxLastContext
.reset( new ExtCellFormulaContext( rContext
) );
173 void SharedFormulaBuffer::setSharedFormulaCell( ExtCellFormulaContext
& rContext
, sal_Int32 nSharedId
)
175 implSetSharedFormulaCell( rContext
, BinAddress( nSharedId
, 0 ) );
178 Reference
< XNamedRange
> SharedFormulaBuffer::createDefinedName( const BinAddress
& rMapKey
)
180 OSL_ENSURE( maIndexMap
.count( rMapKey
) == 0, "SharedFormulaBuffer::createDefinedName - shared formula exists already" );
181 // create the defined name representing the shared formula
182 OUString aName
= OUStringBuffer().appendAscii( "__shared_" ).
183 append( static_cast< sal_Int32
>( getSheetIndex() + 1 ) ).
184 append( sal_Unicode( '_' ) ).append( rMapKey
.mnRow
).
185 append( sal_Unicode( '_' ) ).append( rMapKey
.mnCol
).makeStringAndClear();
186 Reference
< XNamedRange
> xNamedRange
= createNamedRangeObject( aName
);
187 PropertySet
aNameProps( xNamedRange
);
188 aNameProps
.setProperty( PROP_IsSharedFormula
, true );
189 sal_Int32 nTokenIndex
= -1;
190 if( aNameProps
.getProperty( nTokenIndex
, PROP_TokenIndex
) && (nTokenIndex
>= 0) )
191 maIndexMap
[ rMapKey
] = nTokenIndex
;
195 bool SharedFormulaBuffer::implSetSharedFormulaCell( ExtCellFormulaContext
& rContext
, const BinAddress
& rMapKey
)
197 TokenIndexMap::const_iterator aIt
= maIndexMap
.find( rMapKey
);
198 sal_Int32 nTokenIndex
= (aIt
== maIndexMap
.end()) ? -1 : aIt
->second
;
199 if( nTokenIndex
>= 0 )
201 getFormulaParser().convertNameToFormula( rContext
, nTokenIndex
);
207 void SharedFormulaBuffer::updateCachedCell( const CellAddress
& rBaseAddr
, const BinAddress
& rMapKey
)
209 if( mxLastContext
.get() && (mxLastContext
->getBaseAddress() == rBaseAddr
) )
210 implSetSharedFormulaCell( *mxLastContext
, rMapKey
);
211 mxLastContext
.reset();
214 // ============================================================================