Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : : *
6 : : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
12 : : * OpenOffice.org is free software: you can redistribute it and/or modify
13 : : * it under the terms of the GNU Lesser General Public License version 3
14 : : * only, as published by the Free Software Foundation.
15 : : *
16 : : * OpenOffice.org is distributed in the hope that it will be useful,
17 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : : * GNU Lesser General Public License version 3 for more details
20 : : * (a copy is included in the LICENSE file that accompanied this code).
21 : : *
22 : : * You should have received a copy of the GNU Lesser General Public License
23 : : * version 3 along with OpenOffice.org. If not, see
24 : : * <http://www.openoffice.org/license.html>
25 : : * for a copy of the LGPLv3 License.
26 : : *
27 : : ************************************************************************/
28 : :
29 : : #include "workbookfragment.hxx"
30 : :
31 : : #include <com/sun/star/table/CellAddress.hpp>
32 : : #include <com/sun/star/sheet/XCalculatable.hpp>
33 : : #include "oox/core/filterbase.hxx"
34 : : #include "oox/drawingml/themefragmenthandler.hxx"
35 : : #include "oox/helper/attributelist.hxx"
36 : : #include "oox/helper/progressbar.hxx"
37 : : #include "oox/helper/propertyset.hxx"
38 : : #include "oox/ole/olestorage.hxx"
39 : : #include "biffinputstream.hxx"
40 : : #include "chartsheetfragment.hxx"
41 : : #include "connectionsfragment.hxx"
42 : : #include "externallinkbuffer.hxx"
43 : : #include "externallinkfragment.hxx"
44 : : #include "pivotcachebuffer.hxx"
45 : : #include "sharedstringsbuffer.hxx"
46 : : #include "sharedstringsfragment.hxx"
47 : : #include "stylesfragment.hxx"
48 : : #include "tablebuffer.hxx"
49 : : #include "themebuffer.hxx"
50 : : #include "viewsettings.hxx"
51 : : #include "workbooksettings.hxx"
52 : : #include "worksheetbuffer.hxx"
53 : : #include "worksheetfragment.hxx"
54 : :
55 : : namespace oox {
56 : : namespace xls {
57 : :
58 : : // ============================================================================
59 : :
60 : : using namespace ::com::sun::star::io;
61 : : using namespace ::com::sun::star::table;
62 : : using namespace ::com::sun::star::uno;
63 : : using namespace ::com::sun::star::sheet;
64 : : using namespace ::oox::core;
65 : :
66 : : using ::oox::drawingml::ThemeFragmentHandler;
67 : : using ::rtl::OUString;
68 : :
69 : : // ============================================================================
70 : :
71 : : namespace {
72 : :
73 : : const double PROGRESS_LENGTH_GLOBALS = 0.1; /// 10% of progress bar for globals import.
74 : :
75 : : } // namespace
76 : :
77 : : // ============================================================================
78 : :
79 : 24 : WorkbookFragment::WorkbookFragment( const WorkbookHelper& rHelper, const OUString& rFragmentPath ) :
80 [ + - ]: 24 : WorkbookFragmentBase( rHelper, rFragmentPath )
81 : : {
82 : 24 : }
83 : :
84 : 285 : ContextHandlerRef WorkbookFragment::onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs )
85 : : {
86 [ + + + + : 285 : switch( getCurrentElement() )
- + - - ]
87 : : {
88 : : case XML_ROOT_CONTEXT:
89 [ + - ]: 24 : if( nElement == XLS_TOKEN( workbook ) ) return this;
90 : 0 : break;
91 : :
92 : : case XLS_TOKEN( workbook ):
93 [ + - + + : 144 : switch( nElement )
- + ]
94 : : {
95 : : case XLS_TOKEN( sheets ):
96 : : case XLS_TOKEN( bookViews ):
97 : : case XLS_TOKEN( externalReferences ):
98 : : case XLS_TOKEN( definedNames ):
99 : 54 : case XLS_TOKEN( pivotCaches ): return this;
100 : :
101 : 0 : case XLS_TOKEN( fileSharing ): getWorkbookSettings().importFileSharing( rAttribs ); break;
102 : 24 : case XLS_TOKEN( workbookPr ): getWorkbookSettings().importWorkbookPr( rAttribs ); break;
103 : 24 : case XLS_TOKEN( calcPr ): getWorkbookSettings().importCalcPr( rAttribs ); break;
104 : 0 : case XLS_TOKEN( oleSize ): getViewSettings().importOleSize( rAttribs ); break;
105 : : }
106 : 90 : break;
107 : :
108 : : case XLS_TOKEN( sheets ):
109 [ + - ]: 60 : if( nElement == XLS_TOKEN( sheet ) ) getWorksheets().importSheet( rAttribs );
110 : 60 : break;
111 : : case XLS_TOKEN( bookViews ):
112 [ + - ]: 24 : if( nElement == XLS_TOKEN( workbookView ) ) getViewSettings().importWorkbookView( rAttribs );
113 : 24 : break;
114 : : case XLS_TOKEN( externalReferences ):
115 [ # # ]: 0 : if( nElement == XLS_TOKEN( externalReference ) ) importExternalReference( rAttribs );
116 : 0 : break;
117 : : case XLS_TOKEN( definedNames ):
118 [ + - ]: 33 : if( nElement == XLS_TOKEN( definedName ) ) { importDefinedName( rAttribs ); return this; } // collect formula
119 : 0 : break;
120 : : case XLS_TOKEN( pivotCaches ):
121 [ # # ]: 0 : if( nElement == XLS_TOKEN( pivotCache ) ) importPivotCache( rAttribs );
122 : 0 : break;
123 : : }
124 : 285 : return 0;
125 : : }
126 : :
127 : 33 : void WorkbookFragment::onCharacters( const OUString& rChars )
128 : : {
129 [ + - ][ + - ]: 33 : if( isCurrentElement( XLS_TOKEN( definedName ) ) && mxCurrName.get() )
[ + - ]
130 : 33 : mxCurrName->setFormula( rChars );
131 : 33 : }
132 : :
133 : 0 : ContextHandlerRef WorkbookFragment::onCreateRecordContext( sal_Int32 nRecId, SequenceInputStream& rStrm )
134 : : {
135 [ # # # # : 0 : switch( getCurrentElement() )
# # # ]
136 : : {
137 : : case XML_ROOT_CONTEXT:
138 [ # # ]: 0 : if( nRecId == BIFF12_ID_WORKBOOK ) return this;
139 : 0 : break;
140 : :
141 : : case BIFF12_ID_WORKBOOK:
142 [ # # # # : 0 : switch( nRecId )
# # # ]
143 : : {
144 : : case BIFF12_ID_SHEETS:
145 : : case BIFF12_ID_BOOKVIEWS:
146 : : case BIFF12_ID_EXTERNALREFS:
147 : 0 : case BIFF12_ID_PIVOTCACHES: return this;
148 : :
149 : 0 : case BIFF12_ID_FILESHARING: getWorkbookSettings().importFileSharing( rStrm ); break;
150 : 0 : case BIFF12_ID_WORKBOOKPR: getWorkbookSettings().importWorkbookPr( rStrm ); break;
151 : 0 : case BIFF12_ID_CALCPR: getWorkbookSettings().importCalcPr( rStrm ); break;
152 : 0 : case BIFF12_ID_OLESIZE: getViewSettings().importOleSize( rStrm ); break;
153 : 0 : case BIFF12_ID_DEFINEDNAME: getDefinedNames().importDefinedName( rStrm ); break;
154 : : }
155 : 0 : break;
156 : :
157 : : case BIFF12_ID_SHEETS:
158 [ # # ]: 0 : if( nRecId == BIFF12_ID_SHEET ) getWorksheets().importSheet( rStrm );
159 : 0 : break;
160 : : case BIFF12_ID_BOOKVIEWS:
161 [ # # ]: 0 : if( nRecId == BIFF12_ID_WORKBOOKVIEW ) getViewSettings().importWorkbookView( rStrm );
162 : 0 : break;
163 : :
164 : : case BIFF12_ID_EXTERNALREFS:
165 [ # # # # : 0 : switch( nRecId )
# # ]
166 : : {
167 : 0 : case BIFF12_ID_EXTERNALREF: importExternalRef( rStrm ); break;
168 : 0 : case BIFF12_ID_EXTERNALSELF: getExternalLinks().importExternalSelf( rStrm ); break;
169 : 0 : case BIFF12_ID_EXTERNALSAME: getExternalLinks().importExternalSame( rStrm ); break;
170 : 0 : case BIFF12_ID_EXTERNALADDIN: getExternalLinks().importExternalAddin( rStrm ); break;
171 : 0 : case BIFF12_ID_EXTERNALSHEETS: getExternalLinks().importExternalSheets( rStrm ); break;
172 : : }
173 : 0 : break;
174 : :
175 : : case BIFF12_ID_PIVOTCACHES:
176 [ # # ]: 0 : if( nRecId == BIFF12_ID_PIVOTCACHE ) importPivotCache( rStrm );
177 : : }
178 : 0 : return 0;
179 : : }
180 : :
181 : 0 : const RecordInfo* WorkbookFragment::getRecordInfos() const
182 : : {
183 : : static const RecordInfo spRecInfos[] =
184 : : {
185 : : { BIFF12_ID_BOOKVIEWS, BIFF12_ID_BOOKVIEWS + 1 },
186 : : { BIFF12_ID_EXTERNALREFS, BIFF12_ID_EXTERNALREFS + 1 },
187 : : { BIFF12_ID_FUNCTIONGROUPS, BIFF12_ID_FUNCTIONGROUPS + 2 },
188 : : { BIFF12_ID_PIVOTCACHE, BIFF12_ID_PIVOTCACHE + 1 },
189 : : { BIFF12_ID_PIVOTCACHES, BIFF12_ID_PIVOTCACHES + 1 },
190 : : { BIFF12_ID_SHEETS, BIFF12_ID_SHEETS + 1 },
191 : : { BIFF12_ID_WORKBOOK, BIFF12_ID_WORKBOOK + 1 },
192 : : { -1, -1 }
193 : : };
194 : 0 : return spRecInfos;
195 : : }
196 : :
197 : 24 : void WorkbookFragment::finalizeImport()
198 : : {
199 [ + - ][ + - ]: 24 : ISegmentProgressBarRef xGlobalSegment = getProgressBar().createSegment( PROGRESS_LENGTH_GLOBALS );
200 : :
201 : : // read the theme substream
202 [ + - ][ + - ]: 24 : OUString aThemeFragmentPath = getFragmentPathFromFirstType( CREATE_OFFICEDOC_RELATION_TYPE( "theme" ) );
203 [ + + ]: 24 : if( !aThemeFragmentPath.isEmpty() )
204 [ + - ][ + - ]: 6 : importOoxFragment( new ThemeFragmentHandler( getFilter(), aThemeFragmentPath, getTheme() ) );
[ + - ][ + - ]
205 [ + - ]: 24 : xGlobalSegment->setPosition( 0.25 );
206 : :
207 : : // read the styles substream (requires finalized theme buffer)
208 [ + - ][ + - ]: 24 : OUString aStylesFragmentPath = getFragmentPathFromFirstType( CREATE_OFFICEDOC_RELATION_TYPE( "styles" ) );
209 [ + - ]: 24 : if( !aStylesFragmentPath.isEmpty() )
210 [ + - ][ + - ]: 24 : importOoxFragment( new StylesFragment( *this, aStylesFragmentPath ) );
211 [ + - ]: 24 : xGlobalSegment->setPosition( 0.5 );
212 : :
213 : : // read the shared string table substream (requires finalized styles buffer)
214 [ + - ][ + - ]: 24 : OUString aSstFragmentPath = getFragmentPathFromFirstType( CREATE_OFFICEDOC_RELATION_TYPE( "sharedStrings" ) );
215 [ + + ]: 24 : if( !aSstFragmentPath.isEmpty() )
216 [ + - ][ + - ]: 18 : importOoxFragment( new SharedStringsFragment( *this, aSstFragmentPath ) );
217 [ + - ]: 24 : xGlobalSegment->setPosition( 0.75 );
218 : :
219 : : // read the connections substream
220 [ + - ][ + - ]: 24 : OUString aConnFragmentPath = getFragmentPathFromFirstType( CREATE_OFFICEDOC_RELATION_TYPE( "connections" ) );
221 [ - + ]: 24 : if( !aConnFragmentPath.isEmpty() )
222 [ # # ][ # # ]: 0 : importOoxFragment( new ConnectionsFragment( *this, aConnFragmentPath ) );
223 [ + - ]: 24 : xGlobalSegment->setPosition( 1.0 );
224 : :
225 : :
226 : : /* Create fragments for all sheets, before importing them. Needed to do
227 : : some preprocessing in the fragment constructors, e.g. loading the table
228 : : fragments for all sheets that are needed before the cell formulas are
229 : : loaded. Additionally, the instances of the WorkbookGlobals structures
230 : : have to be stored for every sheet. */
231 : : typedef ::std::pair< WorksheetGlobalsRef, FragmentHandlerRef > SheetFragmentHandler;
232 : : typedef ::std::vector< SheetFragmentHandler > SheetFragmentVector;
233 [ + - ]: 24 : SheetFragmentVector aSheetFragments;
234 [ + - ]: 24 : WorksheetBuffer& rWorksheets = getWorksheets();
235 [ + - ]: 24 : sal_Int32 nWorksheetCount = rWorksheets.getWorksheetCount();
236 [ + + ]: 84 : for( sal_Int32 nWorksheet = 0; nWorksheet < nWorksheetCount; ++nWorksheet )
237 : : {
238 [ + - ]: 60 : sal_Int16 nCalcSheet = rWorksheets.getCalcSheetIndex( nWorksheet );
239 [ + - ][ + - ]: 60 : const Relation* pRelation = getRelations().getRelationFromRelId( rWorksheets.getWorksheetRelId( nWorksheet ) );
[ + - ]
240 [ + - ][ + - ]: 60 : if( (nCalcSheet >= 0) && pRelation )
241 : : {
242 : : // get fragment path of the sheet
243 [ + - ]: 60 : OUString aFragmentPath = getFragmentPathFromRelation( *pRelation );
244 : : OSL_ENSURE( !aFragmentPath.isEmpty(), "WorkbookFragment::finalizeImport - cannot access sheet fragment" );
245 [ + - ]: 60 : if( !aFragmentPath.isEmpty() )
246 : : {
247 : : // leave space for formula processing ( calcuate the segments as
248 : : // if there is an extra sheet )
249 [ + - ][ + - ]: 60 : double fSegmentLength = getProgressBar().getFreeLength() / (nWorksheetCount - ( nWorksheet - 1) );
250 [ + - ][ + - ]: 60 : ISegmentProgressBarRef xSheetSegment = getProgressBar().createSegment( fSegmentLength );
251 : :
252 : : // get the sheet type according to the relations type
253 : 60 : WorksheetType eSheetType = SHEETTYPE_EMPTYSHEET;
254 [ + - ][ + - ]: 60 : if( pRelation->maType == CREATE_OFFICEDOC_RELATION_TYPE( "worksheet" ) )
255 : 60 : eSheetType = SHEETTYPE_WORKSHEET;
256 [ # # ][ # # ]: 0 : else if( pRelation->maType == CREATE_OFFICEDOC_RELATION_TYPE( "chartsheet" ) )
257 : 0 : eSheetType = SHEETTYPE_CHARTSHEET;
258 [ # # ]: 0 : else if( (pRelation->maType == CREATE_MSOFFICE_RELATION_TYPE( "xlMacrosheet" )) ||
[ # # # # ]
[ # # ]
[ # # # # ]
259 [ # # ][ # # ]: 0 : (pRelation->maType == CREATE_MSOFFICE_RELATION_TYPE( "xlIntlMacrosheet" )) )
[ # # ]
260 : 0 : eSheetType = SHEETTYPE_MACROSHEET;
261 [ # # ][ # # ]: 0 : else if( pRelation->maType == CREATE_OFFICEDOC_RELATION_TYPE( "dialogsheet" ) )
262 : 0 : eSheetType = SHEETTYPE_DIALOGSHEET;
263 : : OSL_ENSURE( eSheetType != SHEETTYPE_EMPTYSHEET, "WorkbookFragment::finalizeImport - unknown sheet type" );
264 [ + - ]: 60 : if( eSheetType != SHEETTYPE_EMPTYSHEET )
265 : : {
266 : : // create the WorksheetGlobals object
267 [ + - ]: 60 : WorksheetGlobalsRef xSheetGlob = WorksheetHelper::constructGlobals( *this, xSheetSegment, eSheetType, nCalcSheet );
268 : : OSL_ENSURE( xSheetGlob.get(), "WorkbookFragment::finalizeImport - missing sheet in document" );
269 [ + - ]: 60 : if( xSheetGlob.get() )
270 : : {
271 : : // create the sheet fragment handler
272 : 60 : ::rtl::Reference< WorksheetFragmentBase > xFragment;
273 [ + - - ]: 60 : switch( eSheetType )
274 : : {
275 : : case SHEETTYPE_WORKSHEET:
276 : : case SHEETTYPE_MACROSHEET:
277 : : case SHEETTYPE_DIALOGSHEET:
278 [ + - ][ + - ]: 60 : xFragment.set( new WorksheetFragment( *xSheetGlob, aFragmentPath ) );
[ + - ]
279 : 60 : break;
280 : : case SHEETTYPE_CHARTSHEET:
281 [ # # ][ # # ]: 0 : xFragment.set( new ChartsheetFragment( *xSheetGlob, aFragmentPath ) );
[ # # ]
282 : 0 : break;
283 : : default:
284 : : OSL_ENSURE( false, "WorkbookFragment::finalizeImport - unexpected sheet type" );
285 : : }
286 : :
287 : : // insert the fragment into the map
288 [ + - ]: 60 : if( xFragment.is() )
289 [ + - ][ + - ]: 60 : aSheetFragments.push_back( SheetFragmentHandler( xSheetGlob, xFragment.get() ) );
[ + - ]
290 [ + - ]: 60 : }
291 [ + - ]: 60 : }
292 : 60 : }
293 : : }
294 : : }
295 : :
296 : : // create all defined names and database ranges
297 [ + - ][ + - ]: 24 : getDefinedNames().finalizeImport();
298 [ + - ][ + - ]: 24 : getTables().finalizeImport();
299 : : // load all worksheets
300 [ + - ][ + + ]: 84 : for( SheetFragmentVector::iterator aIt = aSheetFragments.begin(), aEnd = aSheetFragments.end(); aIt != aEnd; ++aIt )
301 : : {
302 : : // import the sheet fragment
303 [ + - ]: 60 : importOoxFragment( aIt->second );
304 : : // delete fragment object and WorkbookGlobals object, will free all allocated sheet buffers
305 : 60 : aIt->second.clear();
306 [ + - ]: 60 : aIt->first.reset();
307 : : }
308 : :
309 : : // open the VBA project storage
310 [ + - ][ + - ]: 24 : OUString aVbaFragmentPath = getFragmentPathFromFirstType( CREATE_MSOFFICE_RELATION_TYPE( "vbaProject" ) );
311 [ - + ]: 24 : if( !aVbaFragmentPath.isEmpty() )
312 : : {
313 [ # # ][ # # ]: 0 : Reference< XInputStream > xInStrm = getBaseFilter().openInputStream( aVbaFragmentPath );
314 [ # # ]: 0 : if( xInStrm.is() )
315 [ # # ][ # # ]: 0 : setVbaProjectStorage( StorageRef( new ::oox::ole::OleStorage( getBaseFilter().getComponentContext(), xInStrm, false ) ) );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
316 : : }
317 : :
318 : : // final conversions, e.g. calculation settings and view settings
319 [ + - ]: 24 : finalizeWorkbookImport();
320 : :
321 : : // Recalculate (only changed ones)
322 [ + - ][ + - ]: 24 : Reference< XCalculatable > xCalculatable( getDocument(), UNO_QUERY );
323 [ + - ]: 24 : if( xCalculatable.is() )
324 [ + - ][ + - ]: 24 : xCalculatable->calculate();
[ + - ]
325 : 24 : }
326 : :
327 : : // private --------------------------------------------------------------------
328 : :
329 : 0 : void WorkbookFragment::importExternalReference( const AttributeList& rAttribs )
330 : : {
331 [ # # ]: 0 : if( ExternalLink* pExtLink = getExternalLinks().importExternalReference( rAttribs ).get() )
332 : 0 : importExternalLinkFragment( *pExtLink );
333 : 0 : }
334 : :
335 : 33 : void WorkbookFragment::importDefinedName( const AttributeList& rAttribs )
336 : : {
337 [ + - ]: 33 : mxCurrName = getDefinedNames().importDefinedName( rAttribs );
338 : 33 : }
339 : :
340 : 0 : void WorkbookFragment::importPivotCache( const AttributeList& rAttribs )
341 : : {
342 [ # # ]: 0 : sal_Int32 nCacheId = rAttribs.getInteger( XML_cacheId, -1 );
343 [ # # ]: 0 : OUString aRelId = rAttribs.getString( R_TOKEN( id ), OUString() );
344 [ # # ]: 0 : importPivotCacheDefFragment( aRelId, nCacheId );
345 : 0 : }
346 : :
347 : 0 : void WorkbookFragment::importExternalRef( SequenceInputStream& rStrm )
348 : : {
349 [ # # ]: 0 : if( ExternalLink* pExtLink = getExternalLinks().importExternalRef( rStrm ).get() )
350 : 0 : importExternalLinkFragment( *pExtLink );
351 : 0 : }
352 : :
353 : 0 : void WorkbookFragment::importPivotCache( SequenceInputStream& rStrm )
354 : : {
355 [ # # ]: 0 : sal_Int32 nCacheId = rStrm.readInt32();
356 [ # # ]: 0 : OUString aRelId = BiffHelper::readString( rStrm );
357 [ # # ]: 0 : importPivotCacheDefFragment( aRelId, nCacheId );
358 : 0 : }
359 : :
360 : 0 : void WorkbookFragment::importExternalLinkFragment( ExternalLink& rExtLink )
361 : : {
362 [ # # ]: 0 : OUString aFragmentPath = getFragmentPathFromRelId( rExtLink.getRelId() );
363 [ # # ]: 0 : if( !aFragmentPath.isEmpty() )
364 [ # # ][ # # ]: 0 : importOoxFragment( new ExternalLinkFragment( *this, aFragmentPath, rExtLink ) );
365 : 0 : }
366 : :
367 : 0 : void WorkbookFragment::importPivotCacheDefFragment( const OUString& rRelId, sal_Int32 nCacheId )
368 : : {
369 : : // pivot caches will be imported on demand, here we just store the fragment path in the buffer
370 [ # # ][ # # ]: 0 : getPivotCaches().registerPivotCacheFragment( nCacheId, getFragmentPathFromRelId( rRelId ) );
371 : 0 : }
372 : :
373 : : } // namespace xls
374 [ + - ][ + - ]: 24 : } // namespace oox
375 : :
376 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|