Line data Source code
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 :
10 : #include "formulabuffer.hxx"
11 : #include "formulaparser.hxx"
12 : #include <com/sun/star/sheet/XFormulaTokens.hpp>
13 : #include <com/sun/star/sheet/XArrayFormulaTokens.hpp>
14 : #include <com/sun/star/container/XIndexAccess.hpp>
15 : #include <com/sun/star/sheet/XSpreadsheetDocument.hpp>
16 : #include <com/sun/star/table/XCell2.hpp>
17 : #include "formulacell.hxx"
18 : #include "document.hxx"
19 : #include "convuno.hxx"
20 :
21 : #include "rangelst.hxx"
22 : #include "autonamecache.hxx"
23 : #include "tokenuno.hxx"
24 : #include "tokenarray.hxx"
25 :
26 : namespace oox {
27 : namespace xls {
28 :
29 : using namespace ::com::sun::star::uno;
30 : using namespace ::com::sun::star::table;
31 : using namespace ::com::sun::star::sheet;
32 : using namespace ::com::sun::star::container;
33 :
34 21 : FormulaBuffer::FormulaBuffer( const WorkbookHelper& rHelper ) : WorkbookHelper( rHelper )
35 : {
36 21 : }
37 :
38 0 : Reference< XCellRange > FormulaBuffer::getRange( const CellRangeAddress& rRange)
39 : {
40 0 : Reference< XCellRange > xRange;
41 : try
42 : {
43 0 : xRange = mxCurrSheet->getCellRangeByPosition( rRange.StartColumn, rRange.StartRow, rRange.EndColumn, rRange.EndRow );
44 : }
45 0 : catch( Exception& )
46 : {
47 : }
48 0 : return xRange;
49 : }
50 :
51 21 : void FormulaBuffer::finalizeImport()
52 : {
53 21 : ISegmentProgressBarRef xFormulaBar = getProgressBar().createSegment( getProgressBar().getFreeLength() );
54 :
55 21 : ScDocument& rDoc = getScDocument();
56 42 : Reference< XIndexAccess > xSheets( getDocument()->getSheets(), UNO_QUERY_THROW );
57 21 : rDoc.SetAutoNameCache( new ScAutoNameCache( &rDoc ) );
58 64 : for ( sal_Int16 nTab = 0, nElem = xSheets->getCount(); nTab < nElem; ++nTab )
59 : {
60 43 : double fPosition = static_cast< double> (nTab + 1) /static_cast<double>(nElem);
61 43 : xFormulaBar->setPosition( fPosition );
62 43 : mxCurrSheet = getSheetFromDoc( nTab );
63 : // process shared Formula
64 43 : SheetToFormulaEntryMap::iterator sharedIt = sharedFormulas.find( nTab );
65 43 : if ( sharedIt != sharedFormulas.end() )
66 : {
67 : // shared id ( to create the special shared names from )
68 1 : std::vector<SharedFormulaEntry>& rSharedFormulas = sharedIt->second;
69 2 : for ( std::vector<SharedFormulaEntry>::iterator it = rSharedFormulas.begin(), it_end = rSharedFormulas.end(); it != it_end; ++it )
70 : {
71 1 : createSharedFormula( it->maAddress, it->mnSharedId, it->maTokenStr );
72 : }
73 : }
74 : // now process any defined shared formulae
75 43 : SheetToSharedFormulaid::iterator formulDescIt = sharedFormulaIds.find( nTab );
76 43 : SheetToSharedIdToTokenIndex::iterator tokensIt = tokenIndexes.find( nTab );
77 43 : if ( formulDescIt != sharedFormulaIds.end() && tokensIt != tokenIndexes.end() )
78 : {
79 1 : SharedIdToTokenIndex& rTokenIdMap = tokensIt->second;
80 1 : std::vector< SharedFormulaDesc >& rVector = formulDescIt->second;
81 18 : for ( std::vector< SharedFormulaDesc >::iterator it = rVector.begin(), it_end = rVector.end(); it != it_end; ++it )
82 : {
83 : // see if we have a
84 : // resolved tokenId
85 17 : CellAddress& rAddress = it->first;
86 17 : sal_Int32& rnSharedId = it->second;
87 17 : SharedIdToTokenIndex::iterator itTokenId = rTokenIdMap.find( rnSharedId );
88 17 : if ( itTokenId != rTokenIdMap.end() )
89 : {
90 17 : ApiTokenSequence aTokens = getFormulaParser().convertNameToFormula( itTokenId->second );
91 17 : applyCellFormula( rDoc, aTokens, rAddress );
92 : }
93 : }
94 : }
95 :
96 43 : FormulaDataMap::iterator cellIt = cellFormulas.find( nTab );
97 43 : if ( cellIt != cellFormulas.end() )
98 : {
99 6 : applyCellFormulas( cellIt->second );
100 : }
101 :
102 43 : ArrayFormulaDataMap::iterator itArray = cellArrayFormulas.find( nTab );
103 43 : if ( itArray != cellArrayFormulas.end() )
104 : {
105 0 : applyArrayFormulas( itArray->second );
106 : }
107 :
108 43 : FormulaValueMap::iterator itValues = cellFormulaValues.find( nTab );
109 43 : if ( itValues != cellFormulaValues.end() )
110 : {
111 5 : std::vector< ValueAddressPair > & rVector = itValues->second;
112 5 : applyCellFormulaValues( rVector );
113 : }
114 : }
115 21 : rDoc.SetAutoNameCache( NULL );
116 42 : xFormulaBar->setPosition( 1.0 );
117 21 : }
118 :
119 42 : void FormulaBuffer::applyCellFormula( ScDocument& rDoc, const ApiTokenSequence& rTokens, const ::com::sun::star::table::CellAddress& rAddress )
120 : {
121 42 : ScTokenArray aTokenArray;
122 42 : ScAddress aCellPos;
123 42 : ScUnoConversion::FillScAddress( aCellPos, rAddress );
124 42 : ScTokenConversion::ConvertToTokenArray( rDoc, aTokenArray, rTokens );
125 42 : ScFormulaCell* pNewCell = new ScFormulaCell( &rDoc, aCellPos, &aTokenArray );
126 42 : pNewCell->StartListeningTo( &rDoc );
127 42 : rDoc.EnsureTable(aCellPos.Tab());
128 42 : rDoc.SetFormulaCell(aCellPos, pNewCell);
129 42 : }
130 :
131 6 : void FormulaBuffer::applyCellFormulas( const std::vector< TokenAddressItem >& rVector )
132 : {
133 6 : ScDocument& rDoc = getScDocument();
134 31 : for ( std::vector< TokenAddressItem >::const_iterator it = rVector.begin(), it_end = rVector.end(); it != it_end; ++it )
135 : {
136 25 : const ::com::sun::star::table::CellAddress& rAddress = it->maCellAddress;
137 25 : ApiTokenSequence aTokens = getFormulaParser().importFormula( rAddress, it->maTokenStr );
138 25 : applyCellFormula( rDoc, aTokens, rAddress );
139 25 : }
140 6 : }
141 :
142 5 : void FormulaBuffer::applyCellFormulaValues( const std::vector< ValueAddressPair >& rVector )
143 : {
144 5 : ScDocument& rDoc = getScDocument();
145 28 : for ( std::vector< ValueAddressPair >::const_iterator it = rVector.begin(), it_end = rVector.end(); it != it_end; ++it )
146 : {
147 23 : ScAddress aCellPos;
148 23 : ScUnoConversion::FillScAddress( aCellPos, it->first );
149 23 : ScFormulaCell* pCell = rDoc.GetFormulaCell(aCellPos);
150 23 : if (pCell)
151 : {
152 23 : pCell->SetHybridDouble( it->second );
153 23 : pCell->ResetDirty();
154 23 : pCell->SetChanged(false);
155 : }
156 : }
157 5 : }
158 : // bound to need this somewhere else, if so probably need to move it to
159 : // worksheethelper or somewhere else more suitable
160 0 : void StartCellListening( sal_Int16 nSheet, sal_Int32 nRow, sal_Int32 nCol, ScDocument& rDoc )
161 : {
162 0 : ScAddress aCellPos;
163 0 : CellAddress aAddress;
164 0 : aAddress.Sheet = nSheet;
165 0 : aAddress.Row = nRow;
166 0 : aAddress.Column = nCol;
167 0 : ScUnoConversion::FillScAddress( aCellPos, aAddress );
168 0 : ScFormulaCell* pFCell = rDoc.GetFormulaCell( aCellPos );
169 0 : if ( pFCell )
170 0 : pFCell->StartListeningTo( &rDoc );
171 0 : }
172 :
173 0 : void FormulaBuffer::applyArrayFormulas( const std::vector< TokenRangeAddressItem >& rVector )
174 : {
175 0 : ScDocument& rDoc = getScDocument();
176 0 : for ( std::vector< TokenRangeAddressItem >::const_iterator it = rVector.begin(), it_end = rVector.end(); it != it_end; ++it )
177 : {
178 0 : Reference< XArrayFormulaTokens > xTokens( getRange( it->maCellRangeAddress ), UNO_QUERY );
179 : OSL_ENSURE( xTokens.is(), "SheetDataBuffer::finalizeArrayFormula - missing formula token interface" );
180 0 : ApiTokenSequence aTokens = getFormulaParser().importFormula( it->maTokenAndAddress.maCellAddress, it->maTokenAndAddress.maTokenStr );
181 0 : if( xTokens.is() )
182 : {
183 0 : xTokens->setArrayTokens( aTokens );
184 : // set dependencies, add listeners on the cells in array
185 0 : for ( sal_Int32 nCol = it->maCellRangeAddress.StartColumn; nCol <= it->maCellRangeAddress.EndColumn; ++nCol )
186 : {
187 0 : for ( sal_Int32 nRow = it->maCellRangeAddress.StartRow; nRow <= it->maCellRangeAddress.EndRow; ++nRow )
188 : {
189 0 : StartCellListening( it->maCellRangeAddress.Sheet, nRow, nCol, rDoc );
190 : }
191 : }
192 : }
193 0 : }
194 0 : }
195 :
196 1 : void FormulaBuffer::createSharedFormulaMapEntry( const ::com::sun::star::table::CellAddress& rAddress, sal_Int32 nSharedId, const OUString& rTokens )
197 : {
198 1 : std::vector<SharedFormulaEntry>& rSharedFormulas = sharedFormulas[ rAddress.Sheet ];
199 1 : SharedFormulaEntry aEntry( rAddress, rTokens, nSharedId );
200 1 : rSharedFormulas.push_back( aEntry );
201 1 : }
202 :
203 25 : void FormulaBuffer::setCellFormula( const ::com::sun::star::table::CellAddress& rAddress, const OUString& rTokenStr )
204 : {
205 25 : cellFormulas[ rAddress.Sheet ].push_back( TokenAddressItem( rTokenStr, rAddress ) );
206 25 : }
207 :
208 17 : void FormulaBuffer::setCellFormula( const ::com::sun::star::table::CellAddress& rAddress, sal_Int32 nSharedId )
209 : {
210 17 : sharedFormulaIds[ rAddress.Sheet ].push_back( SharedFormulaDesc( rAddress, nSharedId ) );
211 17 : }
212 :
213 0 : void FormulaBuffer::setCellArrayFormula( const ::com::sun::star::table::CellRangeAddress& rRangeAddress, const ::com::sun::star::table::CellAddress& rTokenAddress, const OUString& rTokenStr )
214 : {
215 :
216 0 : TokenAddressItem tokenPair( rTokenStr, rTokenAddress );
217 0 : cellArrayFormulas[ rRangeAddress.Sheet ].push_back( TokenRangeAddressItem( tokenPair, rRangeAddress ) );
218 0 : }
219 :
220 23 : void FormulaBuffer::setCellFormulaValue( const ::com::sun::star::table::CellAddress& rAddress, double fValue )
221 : {
222 23 : cellFormulaValues[ rAddress.Sheet ].push_back( ValueAddressPair( rAddress, fValue ) );
223 23 : }
224 :
225 1 : void FormulaBuffer::createSharedFormula( const ::com::sun::star::table::CellAddress& rAddress, sal_Int32 nSharedId, const OUString& rTokenStr )
226 : {
227 1 : ApiTokenSequence aTokens = getFormulaParser().importFormula( rAddress, rTokenStr );
228 2 : OUString aName = OUStringBuffer().appendAscii( RTL_CONSTASCII_STRINGPARAM( "__shared_" ) ).
229 2 : append( static_cast< sal_Int32 >( rAddress.Sheet + 1 ) ).
230 1 : append( sal_Unicode( '_' ) ).append( nSharedId ).
231 4 : append( OUString("_0") ).makeStringAndClear();
232 1 : ScRangeData* pScRangeData = createNamedRangeObject( aName, aTokens, 0 );
233 :
234 1 : pScRangeData->SetType(RT_SHARED);
235 1 : sal_Int32 nTokenIndex = static_cast< sal_Int32 >( pScRangeData->GetIndex() );
236 :
237 : // store the token index in the map
238 2 : tokenIndexes[ rAddress.Sheet ][ nSharedId ] = nTokenIndex;
239 1 : }
240 : } // namespace xls
241 15 : } // namespace oox
242 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|