Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * Copyright 2012 LibreOffice contributors.
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 "cell.hxx"
18 : #include "document.hxx"
19 : #include "convuno.hxx"
20 :
21 : #include "rangelst.hxx"
22 : #include "autonamecache.hxx"
23 : #include "tokenuno.hxx"
24 :
25 : namespace oox {
26 : namespace xls {
27 :
28 : using namespace ::com::sun::star::uno;
29 : using namespace ::com::sun::star::table;
30 : using namespace ::com::sun::star::uno;
31 : using namespace ::com::sun::star::sheet;
32 : using namespace ::com::sun::star::container;
33 :
34 11 : FormulaBuffer::FormulaBuffer( const WorkbookHelper& rHelper ) : WorkbookHelper( rHelper )
35 : {
36 11 : }
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 11 : void FormulaBuffer::finalizeImport()
52 : {
53 11 : ISegmentProgressBarRef xFormulaBar = getProgressBar().createSegment( getProgressBar().getFreeLength() );
54 :
55 11 : ScDocument& rDoc = getScDocument();
56 11 : Reference< XIndexAccess > xSheets( getDocument()->getSheets(), UNO_QUERY_THROW );
57 11 : rDoc.SetAutoNameCache( new ScAutoNameCache( &rDoc ) );
58 36 : for ( sal_Int16 nTab = 0, nElem = xSheets->getCount(); nTab < nElem; ++nTab )
59 : {
60 25 : double fPosition = static_cast< double> (nTab + 1) /static_cast<double>(nElem);
61 25 : xFormulaBar->setPosition( fPosition );
62 25 : mxCurrSheet = getSheetFromDoc( nTab );
63 : // process shared Formula
64 25 : SheetToFormulaEntryMap::iterator sharedIt = sharedFormulas.find( nTab );
65 25 : 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 25 : SheetToSharedFormulaid::iterator formulDescIt = sharedFormulaIds.find( nTab );
76 25 : SheetToSharedIdToTokenIndex::iterator tokensIt = tokenIndexes.find( nTab );
77 25 : if ( formulDescIt != sharedFormulaIds.end() && tokensIt != tokenIndexes.end() )
78 : {
79 1 : SharedIdToTokenIndex& rTokenIdMap = tokensIt->second;
80 1 : std::vector< SharedFormulaDesc >& rVector = formulDescIt->second;
81 8 : 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 7 : CellAddress& rAddress = it->first;
86 7 : sal_Int32& rnSharedId = it->second;
87 7 : SharedIdToTokenIndex::iterator itTokenId = rTokenIdMap.find( rnSharedId );
88 7 : if ( itTokenId != rTokenIdMap.end() )
89 : {
90 7 : ApiTokenSequence aTokens = getFormulaParser().convertNameToFormula( itTokenId->second );
91 7 : applyCellFormula( rDoc, aTokens, rAddress );
92 : }
93 : }
94 : }
95 :
96 25 : FormulaDataMap::iterator cellIt = cellFormulas.find( nTab );
97 25 : if ( cellIt != cellFormulas.end() )
98 : {
99 7 : applyCellFormulas( cellIt->second );
100 : }
101 :
102 25 : ArrayFormulaDataMap::iterator itArray = cellArrayFormulas.find( nTab );
103 25 : if ( itArray != cellArrayFormulas.end() )
104 : {
105 0 : applyArrayFormulas( itArray->second );
106 : }
107 :
108 25 : FormulaValueMap::iterator itValues = cellFormulaValues.find( nTab );
109 25 : if ( itValues != cellFormulaValues.end() )
110 : {
111 5 : std::vector< ValueAddressPair > & rVector = itValues->second;
112 5 : applyCellFormulaValues( rVector );
113 : }
114 : }
115 11 : rDoc.SetAutoNameCache( NULL );
116 11 : xFormulaBar->setPosition( 1.0 );
117 11 : }
118 :
119 34 : void FormulaBuffer::applyCellFormula( ScDocument& rDoc, const ApiTokenSequence& rTokens, const ::com::sun::star::table::CellAddress& rAddress )
120 : {
121 34 : ScTokenArray aTokenArray;
122 34 : ScAddress aCellPos;
123 34 : ScUnoConversion::FillScAddress( aCellPos, rAddress );
124 34 : ScTokenConversion::ConvertToTokenArray( rDoc, aTokenArray, rTokens );
125 34 : ScBaseCell* pNewCell = new ScFormulaCell( &rDoc, aCellPos, &aTokenArray );
126 34 : rDoc.PutCell( aCellPos, pNewCell, sal_True );
127 34 : }
128 :
129 7 : void FormulaBuffer::applyCellFormulas( const std::vector< TokenAddressItem >& rVector )
130 : {
131 7 : ScDocument& rDoc = getScDocument();
132 34 : for ( std::vector< TokenAddressItem >::const_iterator it = rVector.begin(), it_end = rVector.end(); it != it_end; ++it )
133 : {
134 27 : const ::com::sun::star::table::CellAddress& rAddress = it->maCellAddress;
135 27 : ApiTokenSequence aTokens = getFormulaParser().importFormula( rAddress, it->maTokenStr );
136 27 : applyCellFormula( rDoc, aTokens, rAddress );
137 27 : }
138 7 : }
139 :
140 5 : void FormulaBuffer::applyCellFormulaValues( const std::vector< ValueAddressPair >& rVector )
141 : {
142 5 : ScDocument& rDoc = getScDocument();
143 28 : for ( std::vector< ValueAddressPair >::const_iterator it = rVector.begin(), it_end = rVector.end(); it != it_end; ++it )
144 : {
145 23 : ScAddress aCellPos;
146 23 : ScUnoConversion::FillScAddress( aCellPos, it->first );
147 23 : ScBaseCell* pBaseCell = rDoc.GetCell( aCellPos );
148 : SAL_WARN_IF( !pBaseCell, "sc", "why is the formula not imported? bug?");
149 23 : if ( pBaseCell && pBaseCell->GetCellType() == CELLTYPE_FORMULA )
150 : {
151 23 : ScFormulaCell* pCell = static_cast< ScFormulaCell* >( pBaseCell );
152 23 : pCell->SetHybridDouble( it->second );
153 23 : pCell->ResetDirty();
154 23 : pCell->ResetChanged();
155 : }
156 : }
157 5 : }
158 :
159 0 : void FormulaBuffer::applyArrayFormulas( const std::vector< TokenRangeAddressItem >& rVector )
160 : {
161 0 : for ( std::vector< TokenRangeAddressItem >::const_iterator it = rVector.begin(), it_end = rVector.end(); it != it_end; ++it )
162 : {
163 0 : Reference< XArrayFormulaTokens > xTokens( getRange( it->maCellRangeAddress ), UNO_QUERY );
164 : OSL_ENSURE( xTokens.is(), "SheetDataBuffer::finalizeArrayFormula - missing formula token interface" );
165 0 : ApiTokenSequence aTokens = getFormulaParser().importFormula( it->maTokenAndAddress.maCellAddress, it->maTokenAndAddress.maTokenStr );
166 0 : if( xTokens.is() )
167 0 : xTokens->setArrayTokens( aTokens );
168 0 : }
169 0 : }
170 :
171 1 : void FormulaBuffer::createSharedFormulaMapEntry( const ::com::sun::star::table::CellAddress& rAddress, sal_Int32 nSharedId, const rtl::OUString& rTokens )
172 : {
173 1 : std::vector<SharedFormulaEntry>& rSharedFormulas = sharedFormulas[ rAddress.Sheet ];
174 1 : SharedFormulaEntry aEntry( rAddress, rTokens, nSharedId );
175 1 : rSharedFormulas.push_back( aEntry );
176 1 : }
177 :
178 27 : void FormulaBuffer::setCellFormula( const ::com::sun::star::table::CellAddress& rAddress, const rtl::OUString& rTokenStr )
179 : {
180 27 : cellFormulas[ rAddress.Sheet ].push_back( TokenAddressItem( rTokenStr, rAddress ) );
181 27 : }
182 :
183 7 : void FormulaBuffer::setCellFormula( const ::com::sun::star::table::CellAddress& rAddress, sal_Int32 nSharedId )
184 : {
185 7 : sharedFormulaIds[ rAddress.Sheet ].push_back( SharedFormulaDesc( rAddress, nSharedId ) );
186 7 : }
187 :
188 0 : void FormulaBuffer::setCellArrayFormula( const ::com::sun::star::table::CellRangeAddress& rRangeAddress, const ::com::sun::star::table::CellAddress& rTokenAddress, const rtl::OUString& rTokenStr )
189 : {
190 :
191 0 : TokenAddressItem tokenPair( rTokenStr, rTokenAddress );
192 0 : cellArrayFormulas[ rRangeAddress.Sheet ].push_back( TokenRangeAddressItem( tokenPair, rRangeAddress ) );
193 0 : }
194 :
195 23 : void FormulaBuffer::setCellFormulaValue( const ::com::sun::star::table::CellAddress& rAddress, double fValue )
196 : {
197 23 : cellFormulaValues[ rAddress.Sheet ].push_back( ValueAddressPair( rAddress, fValue ) );
198 23 : }
199 :
200 1 : void FormulaBuffer::createSharedFormula( const ::com::sun::star::table::CellAddress& rAddress, sal_Int32 nSharedId, const rtl::OUString& rTokenStr )
201 : {
202 1 : ApiTokenSequence aTokens = getFormulaParser().importFormula( rAddress, rTokenStr );
203 2 : rtl::OUString aName = rtl::OUStringBuffer().appendAscii( RTL_CONSTASCII_STRINGPARAM( "__shared_" ) ).
204 2 : append( static_cast< sal_Int32 >( rAddress.Sheet + 1 ) ).
205 1 : append( sal_Unicode( '_' ) ).append( nSharedId ).
206 3 : append( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("_0") ) ).makeStringAndClear();
207 1 : ScRangeData* pScRangeData = createNamedRangeObject( aName, aTokens, 0 );
208 :
209 1 : pScRangeData->SetType(RT_SHARED);
210 1 : sal_Int32 nTokenIndex = static_cast< sal_Int32 >( pScRangeData->GetIndex() );
211 :
212 : // store the token index in the map
213 1 : tokenIndexes[ rAddress.Sheet ][ nSharedId ] = nTokenIndex;
214 1 : }
215 : } // namespace xls
216 9 : } // namespace oox
217 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|