Update ooo320-m1
[ooovba.git] / oox / source / xls / sharedformulabuffer.cxx
blobc6dccfaaab3f3ce4de41e991a9a846a1ef0ca98b
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;
51 namespace oox {
52 namespace xls {
54 // ============================================================================
56 namespace {
58 bool operator==( const CellAddress& rAddr1, const CellAddress& rAddr2 )
60 return
61 (rAddr1.Sheet == rAddr2.Sheet) &&
62 (rAddr1.Column == rAddr2.Column) &&
63 (rAddr1.Row == rAddr2.Row);
66 bool lclContains( const CellRangeAddress& rRange, const CellAddress& rAddr )
68 return
69 (rRange.Sheet == rAddr.Sheet) &&
70 (rRange.StartColumn <= rAddr.Column) && (rAddr.Column <= rRange.EndColumn) &&
71 (rRange.StartRow <= rAddr.Row) && (rAddr.Row <= rRange.EndRow);
74 } // namespace
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 );
109 if( xTokens.is() )
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 )
121 BinRange aRange;
122 rStrm >> aRange;
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 );
132 if( xTokens.is() )
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 )
144 BinRange aRange;
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 );
155 if( xTokens.is() )
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;
192 return xNamedRange;
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 );
202 return true;
204 return false;
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 // ============================================================================
216 } // namespace xls
217 } // namespace oox