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 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include "worksheetfragment.hxx"
21 :
22 : #include <oox/core/filterbase.hxx>
23 : #include <oox/core/relations.hxx>
24 : #include <oox/helper/attributelist.hxx>
25 : #include "addressconverter.hxx"
26 : #include "autofilterbuffer.hxx"
27 : #include "autofiltercontext.hxx"
28 : #include "biffinputstream.hxx"
29 : #include "commentsfragment.hxx"
30 : #include "condformatcontext.hxx"
31 : #include "drawingfragment.hxx"
32 : #include "drawingmanager.hxx"
33 : #include "externallinkbuffer.hxx"
34 : #include "pagesettings.hxx"
35 : #include "pivottablefragment.hxx"
36 : #include "querytablefragment.hxx"
37 : #include "scenariobuffer.hxx"
38 : #include "scenariocontext.hxx"
39 : #include "sheetdatabuffer.hxx"
40 : #include "sheetdatacontext.hxx"
41 : #include "tablefragment.hxx"
42 : #include "extlstcontext.hxx"
43 : #include "viewsettings.hxx"
44 : #include "workbooksettings.hxx"
45 : #include "worksheetsettings.hxx"
46 :
47 : namespace oox {
48 : namespace xls {
49 :
50 : using namespace ::com::sun::star::table;
51 : using namespace ::com::sun::star::uno;
52 : using namespace ::oox::core;
53 :
54 : namespace {
55 :
56 : const sal_uInt16 BIFF_COLINFO_HIDDEN = 0x0001;
57 : const sal_uInt16 BIFF_COLINFO_SHOWPHONETIC = 0x0008;
58 : const sal_uInt16 BIFF_COLINFO_COLLAPSED = 0x1000;
59 :
60 : const sal_uInt16 BIFF_DEFROW_CUSTOMHEIGHT = 0x0001;
61 : const sal_uInt16 BIFF_DEFROW_HIDDEN = 0x0002;
62 : const sal_uInt16 BIFF_DEFROW_THICKTOP = 0x0004;
63 : const sal_uInt16 BIFF_DEFROW_THICKBOTTOM = 0x0008;
64 :
65 : const sal_uInt32 BIFF_DATAVAL_STRINGLIST = 0x00000080;
66 : const sal_uInt32 BIFF_DATAVAL_ALLOWBLANK = 0x00000100;
67 : const sal_uInt32 BIFF_DATAVAL_NODROPDOWN = 0x00000200;
68 : const sal_uInt32 BIFF_DATAVAL_SHOWINPUT = 0x00040000;
69 : const sal_uInt32 BIFF_DATAVAL_SHOWERROR = 0x00080000;
70 :
71 : const sal_Int32 BIFF12_OLEOBJECT_ICON = 4;
72 : const sal_Int32 BIFF12_OLEOBJECT_ALWAYS = 1;
73 : const sal_uInt16 BIFF12_OLEOBJECT_LINKED = 0x0001;
74 : const sal_uInt16 BIFF12_OLEOBJECT_AUTOLOAD = 0x0002;
75 :
76 : } // namespace
77 :
78 0 : DataValidationsContext::DataValidationsContext( WorksheetFragmentBase& rFragment ) :
79 0 : WorksheetContextBase( rFragment )
80 : {
81 0 : }
82 :
83 0 : ContextHandlerRef DataValidationsContext::onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs )
84 : {
85 0 : switch( getCurrentElement() )
86 : {
87 : case XLS_TOKEN( dataValidations ):
88 0 : if( nElement == XLS_TOKEN( dataValidation ) )
89 : {
90 0 : importDataValidation( rAttribs );
91 0 : return this;
92 : }
93 0 : break;
94 : case XLS_TOKEN( dataValidation ):
95 0 : switch( nElement )
96 : {
97 : case XLS_TOKEN( formula1 ):
98 : case XLS_TOKEN( formula2 ):
99 0 : return this; // collect formulas in onCharacters()
100 : }
101 0 : break;
102 : }
103 0 : return 0;
104 : }
105 :
106 0 : void DataValidationsContext::onCharacters( const OUString& rChars )
107 : {
108 0 : if( mxValModel.get() ) switch( getCurrentElement() )
109 : {
110 : case XLS_TOKEN( formula1 ):
111 0 : mxValModel->maTokens1 = getFormulaParser().importFormula( mxValModel->maRanges.getBaseAddress(), rChars );
112 : // process string list of a list validation (convert to list of string tokens)
113 0 : if( mxValModel->mnType == XML_list )
114 0 : getFormulaParser().convertStringToStringList( mxValModel->maTokens1, ',', true );
115 0 : break;
116 : case XLS_TOKEN( formula2 ):
117 0 : mxValModel->maTokens2 = getFormulaParser().importFormula( mxValModel->maRanges.getBaseAddress(), rChars );
118 0 : break;
119 : }
120 0 : }
121 :
122 0 : void DataValidationsContext::onEndElement()
123 : {
124 0 : if( isCurrentElement( XLS_TOKEN( dataValidation ) ) && mxValModel.get() )
125 : {
126 0 : setValidation( *mxValModel );
127 0 : mxValModel.reset();
128 : }
129 0 : }
130 :
131 0 : ContextHandlerRef DataValidationsContext::onCreateRecordContext( sal_Int32 nRecId, SequenceInputStream& rStrm )
132 : {
133 0 : if( nRecId == BIFF12_ID_DATAVALIDATION )
134 0 : importDataValidation( rStrm );
135 0 : return 0;
136 : }
137 :
138 0 : void DataValidationsContext::importDataValidation( const AttributeList& rAttribs )
139 : {
140 0 : mxValModel.reset( new ValidationModel );
141 0 : getAddressConverter().convertToCellRangeList( mxValModel->maRanges, rAttribs.getString( XML_sqref, OUString() ), getSheetIndex(), true );
142 0 : mxValModel->msRef = rAttribs.getString( XML_sqref, OUString() );
143 0 : mxValModel->maInputTitle = rAttribs.getXString( XML_promptTitle, OUString() );
144 0 : mxValModel->maInputMessage = rAttribs.getXString( XML_prompt, OUString() );
145 0 : mxValModel->maErrorTitle = rAttribs.getXString( XML_errorTitle, OUString() );
146 0 : mxValModel->maErrorMessage = rAttribs.getXString( XML_error, OUString() );
147 0 : mxValModel->mnType = rAttribs.getToken( XML_type, XML_none );
148 0 : mxValModel->mnOperator = rAttribs.getToken( XML_operator, XML_between );
149 0 : mxValModel->mnErrorStyle = rAttribs.getToken( XML_errorStyle, XML_stop );
150 0 : mxValModel->mbShowInputMsg = rAttribs.getBool( XML_showInputMessage, false );
151 0 : mxValModel->mbShowErrorMsg = rAttribs.getBool( XML_showErrorMessage, false );
152 : /* The attribute showDropDown@dataValidation is in fact a "suppress
153 : dropdown" flag, as it was in the BIFF format! ECMA specification
154 : and attribute name are plain wrong! */
155 0 : mxValModel->mbNoDropDown = rAttribs.getBool( XML_showDropDown, false );
156 0 : mxValModel->mbAllowBlank = rAttribs.getBool( XML_allowBlank, false );
157 0 : }
158 :
159 0 : void DataValidationsContext::importDataValidation( SequenceInputStream& rStrm )
160 : {
161 0 : ValidationModel aModel;
162 :
163 : sal_uInt32 nFlags;
164 0 : BinRangeList aRanges;
165 0 : nFlags = rStrm.readuInt32();
166 0 : rStrm >> aRanges >> aModel.maErrorTitle >> aModel.maErrorMessage >> aModel.maInputTitle >> aModel.maInputMessage;
167 :
168 : // equal flags in all BIFFs
169 0 : aModel.setBiffType( extractValue< sal_uInt8 >( nFlags, 0, 4 ) );
170 0 : aModel.setBiffOperator( extractValue< sal_uInt8 >( nFlags, 20, 4 ) );
171 0 : aModel.setBiffErrorStyle( extractValue< sal_uInt8 >( nFlags, 4, 3 ) );
172 0 : aModel.mbAllowBlank = getFlag( nFlags, BIFF_DATAVAL_ALLOWBLANK );
173 0 : aModel.mbNoDropDown = getFlag( nFlags, BIFF_DATAVAL_NODROPDOWN );
174 0 : aModel.mbShowInputMsg = getFlag( nFlags, BIFF_DATAVAL_SHOWINPUT );
175 0 : aModel.mbShowErrorMsg = getFlag( nFlags, BIFF_DATAVAL_SHOWERROR );
176 :
177 : // cell range list
178 0 : getAddressConverter().convertToCellRangeList( aModel.maRanges, aRanges, getSheetIndex(), true );
179 :
180 : // condition formula(s)
181 0 : FormulaParser& rParser = getFormulaParser();
182 0 : CellAddress aBaseAddr = aModel.maRanges.getBaseAddress();
183 0 : aModel.maTokens1 = rParser.importFormula( aBaseAddr, FORMULATYPE_VALIDATION, rStrm );
184 0 : aModel.maTokens2 = rParser.importFormula( aBaseAddr, FORMULATYPE_VALIDATION, rStrm );
185 : // process string list of a list validation (convert to list of string tokens)
186 0 : if( (aModel.mnType == XML_list) && getFlag( nFlags, BIFF_DATAVAL_STRINGLIST ) )
187 0 : rParser.convertStringToStringList( aModel.maTokens1, ',', true );
188 :
189 : // set validation data
190 0 : setValidation( aModel );
191 0 : }
192 :
193 269 : WorksheetFragment::WorksheetFragment( const WorksheetHelper& rHelper, const OUString& rFragmentPath ) :
194 269 : WorksheetFragmentBase( rHelper, rFragmentPath )
195 : {
196 : // import data tables related to this worksheet
197 269 : RelationsRef xTableRels = getRelations().getRelationsFromTypeFromOfficeDoc( "table" );
198 269 : for( ::std::map< OUString, Relation >::const_iterator aIt = xTableRels->begin(), aEnd = xTableRels->end(); aIt != aEnd; ++aIt )
199 0 : importOoxFragment( new TableFragment( *this, getFragmentPathFromRelation( aIt->second ) ) );
200 :
201 : // import comments related to this worksheet
202 538 : OUString aCommentsFragmentPath = getFragmentPathFromFirstTypeFromOfficeDoc( "comments" );
203 269 : if( !aCommentsFragmentPath.isEmpty() )
204 272 : importOoxFragment( new CommentsFragment( *this, aCommentsFragmentPath ) );
205 269 : }
206 :
207 3384 : ContextHandlerRef WorksheetFragment::onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs )
208 : {
209 3384 : switch( getCurrentElement() )
210 : {
211 266 : case XML_ROOT_CONTEXT: switch( getSheetType() )
212 : {
213 266 : case SHEETTYPE_WORKSHEET: return (nElement == XLS_TOKEN( worksheet )) ? this : 0;
214 0 : case SHEETTYPE_CHARTSHEET: return 0;
215 0 : case SHEETTYPE_MACROSHEET: return (nElement == XM_TOKEN( macrosheet )) ? this : 0;
216 0 : case SHEETTYPE_DIALOGSHEET: return (nElement == XLS_TOKEN( dialogsheet )) ? this : 0;
217 0 : case SHEETTYPE_MODULESHEET: return 0;
218 0 : case SHEETTYPE_EMPTYSHEET: return 0;
219 : }
220 0 : break;
221 :
222 : case XLS_TOKEN( worksheet ):
223 : case XM_TOKEN( macrosheet ):
224 : case XLS_TOKEN( dialogsheet ):
225 2100 : switch( nElement )
226 : {
227 266 : case XLS_TOKEN( sheetData ): return new SheetDataContext( *this );
228 67 : case XLS_TOKEN( conditionalFormatting ): return new CondFormatContext( *this );
229 0 : case XLS_TOKEN( dataValidations ): return new DataValidationsContext( *this );
230 1 : case XLS_TOKEN( autoFilter ): return new AutoFilterContext( *this, getAutoFilters().createAutoFilter() );
231 0 : case XLS_TOKEN( scenarios ): return new ScenariosContext( *this );
232 7 : case XLS_TOKEN( extLst ): return new ExtLstGlobalContext( *this );
233 :
234 : case XLS_TOKEN( sheetViews ):
235 : case XLS_TOKEN( cols ):
236 : case XLS_TOKEN( mergeCells ):
237 : case XLS_TOKEN( hyperlinks ):
238 : case XLS_TOKEN( rowBreaks ):
239 : case XLS_TOKEN( colBreaks ):
240 : case XLS_TOKEN( oleObjects ):
241 399 : case XLS_TOKEN( controls ): return this;
242 :
243 117 : case XLS_TOKEN( sheetPr ): getWorksheetSettings().importSheetPr( rAttribs ); return this;
244 266 : case XLS_TOKEN( dimension ): importDimension( rAttribs ); break;
245 254 : case XLS_TOKEN( sheetFormatPr ): importSheetFormatPr( rAttribs ); break;
246 4 : case XLS_TOKEN( sheetProtection ): getWorksheetSettings().importSheetProtection( rAttribs ); break;
247 1 : case XLS_TOKEN( protectedRanges ): WorksheetSettings::importProtectedRanges( rAttribs ); return this;
248 12 : case XLS_TOKEN( phoneticPr ): getWorksheetSettings().importPhoneticPr( rAttribs ); break;
249 101 : case XLS_TOKEN( printOptions ): getPageSettings().importPrintOptions( rAttribs ); break;
250 266 : case XLS_TOKEN( pageMargins ): getPageSettings().importPageMargins( rAttribs ); break;
251 123 : case XLS_TOKEN( pageSetup ): getPageSettings().importPageSetup( getRelations(), rAttribs ); break;
252 117 : case XLS_TOKEN( headerFooter ): getPageSettings().importHeaderFooter( rAttribs ); return this;
253 0 : case XLS_TOKEN( picture ): getPageSettings().importPicture( getRelations(), rAttribs ); break;
254 93 : case XLS_TOKEN( drawing ): importDrawing( rAttribs ); break;
255 3 : case XLS_TOKEN( legacyDrawing ): importLegacyDrawing( rAttribs ); break;
256 : }
257 1125 : break;
258 :
259 : case XLS_TOKEN( sheetPr ):
260 118 : switch( nElement )
261 : {
262 18 : case XLS_TOKEN( tabColor ): getWorksheetSettings().importTabColor( rAttribs ); break;
263 0 : case XLS_TOKEN( outlinePr ): getWorksheetSettings().importOutlinePr( rAttribs ); break;
264 100 : case XLS_TOKEN( pageSetUpPr ): importPageSetUpPr( rAttribs ); break;
265 : }
266 118 : break;
267 :
268 : case XLS_TOKEN( sheetViews ):
269 266 : switch( nElement )
270 : {
271 266 : case XLS_TOKEN( sheetView ): getSheetViewSettings().importSheetView( rAttribs ); return this;
272 : }
273 0 : break;
274 : case XLS_TOKEN( sheetView ):
275 192 : switch( nElement )
276 : {
277 0 : case XLS_TOKEN( pane ): getSheetViewSettings().importPane( rAttribs ); break;
278 192 : case XLS_TOKEN( selection ): getSheetViewSettings().importSelection( rAttribs ); break;
279 : }
280 192 : break;
281 :
282 : case XLS_TOKEN( cols ):
283 210 : if( nElement == XLS_TOKEN( col ) ) importCol( rAttribs );
284 210 : break;
285 : case XLS_TOKEN( mergeCells ):
286 14 : if( nElement == XLS_TOKEN( mergeCell ) ) importMergeCell( rAttribs );
287 14 : break;
288 : case XLS_TOKEN( hyperlinks ):
289 3 : if( nElement == XLS_TOKEN( hyperlink ) ) importHyperlink( rAttribs );
290 3 : break;
291 : case XLS_TOKEN( rowBreaks ):
292 0 : if( nElement == XLS_TOKEN( brk ) ) importBrk( rAttribs, true );
293 0 : break;
294 : case XLS_TOKEN( colBreaks ):
295 0 : if( nElement == XLS_TOKEN( brk ) ) importBrk( rAttribs, false );
296 0 : break;
297 :
298 : case XLS_TOKEN( protectedRanges ):
299 5 : switch( nElement )
300 : {
301 5 : case XLS_TOKEN( protectedRange ): getWorksheetSettings().importProtectedRange( rAttribs ); return this;
302 : }
303 0 : break;
304 :
305 : case XLS_TOKEN( headerFooter ):
306 210 : switch( nElement )
307 : {
308 : case XLS_TOKEN( firstHeader ):
309 : case XLS_TOKEN( firstFooter ):
310 : case XLS_TOKEN( oddHeader ):
311 : case XLS_TOKEN( oddFooter ):
312 : case XLS_TOKEN( evenHeader ):
313 210 : case XLS_TOKEN( evenFooter ): return this; // collect h/f contents in onCharacters()
314 : }
315 0 : break;
316 : // Only process an oleObject or control if outside a mc:AlternateContent
317 : // element OR if within a mc:Fallback. I suppose ideally we
318 : // should process the stuff within 'mc:Choice'
319 : case XLS_TOKEN( controls ):
320 : case XLS_TOKEN( oleObjects ):
321 0 : if ( getCurrentElement() == XLS_TOKEN( controls ) )
322 : {
323 0 : if( aMceState.empty() || ( !aMceState.empty() && aMceState.back() == MCE_STARTED ) )
324 : {
325 0 : if ( getCurrentElement() == XLS_TOKEN( oleObjects ) ) importOleObject( rAttribs );
326 : else
327 0 : importControl( rAttribs );
328 : }
329 0 : else if ( !aMceState.empty() && aMceState.back() == MCE_FOUND_CHOICE )
330 : {
331 : // reset the handling within 'Choice'
332 : // this will force attempted handling in Fallback
333 0 : aMceState.back() = MCE_STARTED;
334 : }
335 : }
336 0 : break;
337 : }
338 1662 : return 0;
339 : }
340 :
341 82 : void WorksheetFragment::onCharacters( const OUString& rChars )
342 : {
343 82 : switch( getCurrentElement() )
344 : {
345 : case XLS_TOKEN( firstHeader ):
346 : case XLS_TOKEN( firstFooter ):
347 : case XLS_TOKEN( oddHeader ):
348 : case XLS_TOKEN( oddFooter ):
349 : case XLS_TOKEN( evenHeader ):
350 : case XLS_TOKEN( evenFooter ):
351 82 : getPageSettings().importHeaderFooterCharacters( rChars, getCurrentElement() );
352 82 : break;
353 : }
354 82 : }
355 :
356 53 : ContextHandlerRef WorksheetFragment::onCreateRecordContext( sal_Int32 nRecId, SequenceInputStream& rStrm )
357 : {
358 53 : switch( getCurrentElement() )
359 : {
360 : case XML_ROOT_CONTEXT:
361 3 : if( nRecId == BIFF12_ID_WORKSHEET ) return this;
362 0 : break;
363 :
364 : case BIFF12_ID_WORKSHEET:
365 41 : switch( nRecId )
366 : {
367 3 : case BIFF12_ID_SHEETDATA: return new SheetDataContext( *this );
368 0 : case BIFF12_ID_CONDFORMATTING: return new CondFormatContext( *this );
369 0 : case BIFF12_ID_DATAVALIDATIONS: return new DataValidationsContext( *this );
370 0 : case BIFF12_ID_AUTOFILTER: return new AutoFilterContext( *this, getAutoFilters().createAutoFilter() );
371 0 : case BIFF12_ID_SCENARIOS: return new ScenariosContext( *this );
372 :
373 : case BIFF12_ID_SHEETVIEWS:
374 : case BIFF12_ID_COLS:
375 : case BIFF12_ID_MERGECELLS:
376 : case BIFF12_ID_ROWBREAKS:
377 : case BIFF12_ID_COLBREAKS:
378 : case BIFF12_ID_OLEOBJECTS:
379 6 : case BIFF12_ID_CONTROLS: return this;
380 :
381 3 : case BIFF12_ID_SHEETPR: getWorksheetSettings().importSheetPr( rStrm ); break;
382 3 : case BIFF12_ID_DIMENSION: importDimension( rStrm ); break;
383 3 : case BIFF12_ID_SHEETFORMATPR: importSheetFormatPr( rStrm ); break;
384 0 : case BIFF12_ID_HYPERLINK: importHyperlink( rStrm ); break;
385 3 : case BIFF12_ID_PAGEMARGINS: getPageSettings().importPageMargins( rStrm ); break;
386 1 : case BIFF12_ID_PAGESETUP: getPageSettings().importPageSetup( getRelations(), rStrm ); break;
387 3 : case BIFF12_ID_PRINTOPTIONS: getPageSettings().importPrintOptions( rStrm ); break;
388 2 : case BIFF12_ID_HEADERFOOTER: getPageSettings().importHeaderFooter( rStrm ); break;
389 0 : case BIFF12_ID_PICTURE: getPageSettings().importPicture( getRelations(), rStrm ); break;
390 3 : case BIFF12_ID_SHEETPROTECTION: getWorksheetSettings().importSheetProtection( rStrm ); break;
391 0 : case BIFF12_ID_PHONETICPR: getWorksheetSettings().importPhoneticPr( rStrm ); break;
392 1 : case BIFF12_ID_DRAWING: importDrawing( rStrm ); break;
393 1 : case BIFF12_ID_LEGACYDRAWING: importLegacyDrawing( rStrm ); break;
394 : }
395 32 : break;
396 :
397 : case BIFF12_ID_SHEETVIEWS:
398 3 : switch( nRecId )
399 : {
400 3 : case BIFF12_ID_SHEETVIEW: getSheetViewSettings().importSheetView( rStrm ); return this;
401 : }
402 0 : break;
403 : case BIFF12_ID_SHEETVIEW:
404 3 : switch( nRecId )
405 : {
406 0 : case BIFF12_ID_PANE: getSheetViewSettings().importPane( rStrm ); break;
407 3 : case BIFF12_ID_SELECTION: getSheetViewSettings().importSelection( rStrm ); break;
408 : }
409 3 : break;
410 :
411 : case BIFF12_ID_COLS:
412 2 : if( nRecId == BIFF12_ID_COL ) importCol( rStrm );
413 2 : break;
414 : case BIFF12_ID_MERGECELLS:
415 1 : if( nRecId == BIFF12_ID_MERGECELL ) importMergeCell( rStrm );
416 1 : break;
417 : case BIFF12_ID_ROWBREAKS:
418 0 : if( nRecId == BIFF12_ID_BRK ) importBrk( rStrm, true );
419 0 : break;
420 : case BIFF12_ID_COLBREAKS:
421 0 : if( nRecId == BIFF12_ID_BRK ) importBrk( rStrm, false );
422 0 : break;
423 : case BIFF12_ID_OLEOBJECTS:
424 0 : if( nRecId == BIFF12_ID_OLEOBJECT ) importOleObject( rStrm );
425 0 : break;
426 : case BIFF12_ID_CONTROLS:
427 0 : if( nRecId == BIFF12_ID_CONTROL ) importControl( rStrm );
428 0 : break;
429 : }
430 38 : return 0;
431 : }
432 :
433 3 : const RecordInfo* WorksheetFragment::getRecordInfos() const
434 : {
435 : static const RecordInfo spRecInfos[] =
436 : {
437 : { BIFF12_ID_AUTOFILTER, BIFF12_ID_AUTOFILTER + 1 },
438 : { BIFF12_ID_CFRULE, BIFF12_ID_CFRULE + 1 },
439 : { BIFF12_ID_COLBREAKS, BIFF12_ID_COLBREAKS + 1 },
440 : { BIFF12_ID_COLORSCALE, BIFF12_ID_COLORSCALE + 1 },
441 : { BIFF12_ID_COLS, BIFF12_ID_COLS + 1 },
442 : { BIFF12_ID_CONDFORMATTING, BIFF12_ID_CONDFORMATTING + 1 },
443 : { BIFF12_ID_CONTROLS, BIFF12_ID_CONTROLS + 2 },
444 : { BIFF12_ID_CUSTOMFILTERS, BIFF12_ID_CUSTOMFILTERS + 1 },
445 : { BIFF12_ID_CUSTOMSHEETVIEW, BIFF12_ID_CUSTOMSHEETVIEW + 1 },
446 : { BIFF12_ID_CUSTOMSHEETVIEWS, BIFF12_ID_CUSTOMSHEETVIEWS + 3 },
447 : { BIFF12_ID_DATABAR, BIFF12_ID_DATABAR + 1 },
448 : { BIFF12_ID_DATAVALIDATIONS, BIFF12_ID_DATAVALIDATIONS + 1 },
449 : { BIFF12_ID_DISCRETEFILTERS, BIFF12_ID_DISCRETEFILTERS + 1 },
450 : { BIFF12_ID_FILTERCOLUMN, BIFF12_ID_FILTERCOLUMN + 1 },
451 : { BIFF12_ID_HEADERFOOTER, BIFF12_ID_HEADERFOOTER + 1 },
452 : { BIFF12_ID_ICONSET, BIFF12_ID_ICONSET + 1 },
453 : { BIFF12_ID_MERGECELLS, BIFF12_ID_MERGECELLS + 1 },
454 : { BIFF12_ID_OLEOBJECTS, BIFF12_ID_OLEOBJECTS + 2 },
455 : { BIFF12_ID_ROW, -1 },
456 : { BIFF12_ID_ROWBREAKS, BIFF12_ID_ROWBREAKS + 1 },
457 : { BIFF12_ID_SCENARIO, BIFF12_ID_SCENARIO + 1 },
458 : { BIFF12_ID_SCENARIOS, BIFF12_ID_SCENARIOS + 1 },
459 : { BIFF12_ID_SHEETDATA, BIFF12_ID_SHEETDATA + 1 },
460 : { BIFF12_ID_SHEETVIEW, BIFF12_ID_SHEETVIEW + 1 },
461 : { BIFF12_ID_SHEETVIEWS, BIFF12_ID_SHEETVIEWS + 1 },
462 : { BIFF12_ID_TABLEPARTS, BIFF12_ID_TABLEPARTS + 2 },
463 : { BIFF12_ID_WORKSHEET, BIFF12_ID_WORKSHEET + 1 },
464 : { -1, -1 }
465 : };
466 3 : return spRecInfos;
467 : }
468 :
469 269 : void WorksheetFragment::initializeImport()
470 : {
471 : // initial processing in base class WorksheetHelper
472 269 : initializeWorksheetImport();
473 :
474 : // import query table fragments related to this worksheet
475 269 : RelationsRef xQueryRels = getRelations().getRelationsFromTypeFromOfficeDoc( "queryTable" );
476 269 : for( ::std::map< OUString, Relation >::const_iterator aIt = xQueryRels->begin(), aEnd = xQueryRels->end(); aIt != aEnd; ++aIt )
477 0 : importOoxFragment( new QueryTableFragment( *this, getFragmentPathFromRelation( aIt->second ) ) );
478 :
479 : // import pivot table fragments related to this worksheet
480 538 : RelationsRef xPivotRels = getRelations().getRelationsFromTypeFromOfficeDoc( "pivotTable" );
481 273 : for( ::std::map< OUString, Relation >::const_iterator aIt = xPivotRels->begin(), aEnd = xPivotRels->end(); aIt != aEnd; ++aIt )
482 273 : importOoxFragment( new PivotTableFragment( *this, getFragmentPathFromRelation( aIt->second ) ) );
483 269 : }
484 :
485 269 : void WorksheetFragment::finalizeImport()
486 : {
487 : // final processing in base class WorksheetHelper
488 269 : finalizeWorksheetImport();
489 269 : }
490 :
491 : // private --------------------------------------------------------------------
492 :
493 100 : void WorksheetFragment::importPageSetUpPr( const AttributeList& rAttribs )
494 : {
495 : // for whatever reason, this flag is still stored separated from the page settings
496 100 : getPageSettings().setFitToPagesMode( rAttribs.getBool( XML_fitToPage, false ) );
497 100 : }
498 :
499 266 : void WorksheetFragment::importDimension( const AttributeList& rAttribs )
500 : {
501 266 : CellRangeAddress aRange;
502 266 : AddressConverter::convertToCellRangeUnchecked( aRange, rAttribs.getString( XML_ref, OUString() ), getSheetIndex() );
503 : /* OOXML stores the used area, if existing, or "A1" if the sheet is empty.
504 : In case of "A1", the dimension at the WorksheetHelper object will not
505 : be set. If the cell A1 exists, the used area will be updated while
506 : importing the cell. */
507 266 : if( (aRange.EndColumn > 0) || (aRange.EndRow > 0) )
508 : {
509 150 : extendUsedArea( aRange );
510 : }
511 266 : }
512 :
513 254 : void WorksheetFragment::importSheetFormatPr( const AttributeList& rAttribs )
514 : {
515 : // default column settings
516 254 : setBaseColumnWidth( rAttribs.getInteger( XML_baseColWidth, 8 ) );
517 254 : setDefaultColumnWidth( rAttribs.getDouble( XML_defaultColWidth, 0.0 ) );
518 : // default row settings
519 : setDefaultRowSettings(
520 : rAttribs.getDouble( XML_defaultRowHeight, 0.0 ),
521 254 : rAttribs.getBool( XML_customHeight, false ),
522 254 : rAttribs.getBool( XML_zeroHeight, false ),
523 254 : rAttribs.getBool( XML_thickTop, false ),
524 1016 : rAttribs.getBool( XML_thickBottom, false ) );
525 254 : }
526 :
527 210 : void WorksheetFragment::importCol( const AttributeList& rAttribs )
528 : {
529 210 : ColumnModel aModel;
530 210 : aModel.maRange.mnFirst = rAttribs.getInteger( XML_min, -1 );
531 210 : aModel.maRange.mnLast = rAttribs.getInteger( XML_max, -1 );
532 210 : aModel.mfWidth = rAttribs.getDouble( XML_width, 0.0 );
533 210 : aModel.mnXfId = rAttribs.getInteger( XML_style, -1 );
534 210 : aModel.mnLevel = rAttribs.getInteger( XML_outlineLevel, 0 );
535 210 : aModel.mbShowPhonetic = rAttribs.getBool( XML_phonetic, false );
536 210 : aModel.mbHidden = rAttribs.getBool( XML_hidden, false );
537 210 : aModel.mbCollapsed = rAttribs.getBool( XML_collapsed, false );
538 : // set column properties in the current sheet
539 210 : setColumnModel( aModel );
540 210 : }
541 :
542 14 : void WorksheetFragment::importMergeCell( const AttributeList& rAttribs )
543 : {
544 14 : CellRangeAddress aRange;
545 14 : if( getAddressConverter().convertToCellRange( aRange, rAttribs.getString( XML_ref, OUString() ), getSheetIndex(), true, true ) )
546 14 : getSheetData().setMergedRange( aRange );
547 14 : }
548 :
549 3 : void WorksheetFragment::importHyperlink( const AttributeList& rAttribs )
550 : {
551 3 : HyperlinkModel aModel;
552 3 : if( getAddressConverter().convertToCellRange( aModel.maRange, rAttribs.getString( XML_ref, OUString() ), getSheetIndex(), true, true ) )
553 : {
554 3 : aModel.maTarget = getRelations().getExternalTargetFromRelId( rAttribs.getString( R_TOKEN( id ), OUString() ) );
555 3 : aModel.maLocation = rAttribs.getXString( XML_location, OUString() );
556 3 : aModel.maDisplay = rAttribs.getXString( XML_display, OUString() );
557 3 : aModel.maTooltip = rAttribs.getXString( XML_tooltip, OUString() );
558 3 : setHyperlink( aModel );
559 3 : }
560 3 : }
561 :
562 0 : void WorksheetFragment::importBrk( const AttributeList& rAttribs, bool bRowBreak )
563 : {
564 0 : PageBreakModel aModel;
565 0 : aModel.mnColRow = rAttribs.getInteger( XML_id, 0 );
566 0 : aModel.mnMin = rAttribs.getInteger( XML_min, aModel.mnColRow );
567 0 : aModel.mnMax = rAttribs.getInteger( XML_max, aModel.mnColRow );
568 0 : aModel.mbManual = rAttribs.getBool( XML_man, false );
569 0 : setPageBreak( aModel, bRowBreak );
570 0 : }
571 :
572 93 : void WorksheetFragment::importDrawing( const AttributeList& rAttribs )
573 : {
574 93 : setDrawingPath( getFragmentPathFromRelId( rAttribs.getString( R_TOKEN( id ), OUString() ) ) );
575 93 : }
576 :
577 3 : void WorksheetFragment::importLegacyDrawing( const AttributeList& rAttribs )
578 : {
579 3 : setVmlDrawingPath( getFragmentPathFromRelId( rAttribs.getString( R_TOKEN( id ), OUString() ) ) );
580 3 : }
581 :
582 0 : void WorksheetFragment::importOleObject( const AttributeList& rAttribs )
583 : {
584 0 : ::oox::vml::OleObjectInfo aInfo;
585 0 : aInfo.setShapeId( rAttribs.getInteger( XML_shapeId, 0 ) );
586 : OSL_ENSURE( rAttribs.hasAttribute( XML_link ) != rAttribs.hasAttribute( R_TOKEN( id ) ),
587 : "WorksheetFragment::importOleObject - OLE object must be either linked or embedded" );
588 0 : aInfo.mbLinked = rAttribs.hasAttribute( XML_link );
589 0 : if( aInfo.mbLinked )
590 0 : aInfo.maTargetLink = getFormulaParser().importOleTargetLink( rAttribs.getString( XML_link, OUString() ) );
591 0 : else if( rAttribs.hasAttribute( R_TOKEN( id ) ) )
592 0 : importEmbeddedOleData( aInfo.maEmbeddedData, rAttribs.getString( R_TOKEN( id ), OUString() ) );
593 0 : aInfo.maProgId = rAttribs.getString( XML_progId, OUString() );
594 0 : aInfo.mbShowAsIcon = rAttribs.getToken( XML_dvAspect, XML_DVASPECT_CONTENT ) == XML_DVASPECT_ICON;
595 0 : aInfo.mbAutoUpdate = rAttribs.getToken( XML_oleUpdate, XML_OLEUPDATE_ONCALL ) == XML_OLEUPDATE_ALWAYS;
596 0 : aInfo.mbAutoLoad = rAttribs.getBool( XML_autoLoad, false );
597 0 : getVmlDrawing().registerOleObject( aInfo );
598 0 : }
599 :
600 0 : void WorksheetFragment::importControl( const AttributeList& rAttribs )
601 : {
602 0 : ::oox::vml::ControlInfo aInfo;
603 0 : aInfo.setShapeId( rAttribs.getInteger( XML_shapeId, 0 ) );
604 0 : aInfo.maFragmentPath = getFragmentPathFromRelId( rAttribs.getString( R_TOKEN( id ), OUString() ) );
605 0 : aInfo.maName = rAttribs.getString( XML_name, OUString() );
606 0 : getVmlDrawing().registerControl( aInfo );
607 0 : }
608 :
609 3 : void WorksheetFragment::importDimension( SequenceInputStream& rStrm )
610 : {
611 3 : BinRange aBinRange;
612 3 : aBinRange.read( rStrm );
613 3 : CellRangeAddress aRange;
614 3 : AddressConverter::convertToCellRangeUnchecked( aRange, aBinRange, getSheetIndex() );
615 : /* BIFF12 stores the used area, if existing, or "A1" if the sheet is
616 : empty. In case of "A1", the dimension at the WorksheetHelper object
617 : will not be set. If the cell A1 exists, the used area will be updated
618 : while importing the cell. */
619 3 : if( (aRange.EndColumn > 0) || (aRange.EndRow > 0) )
620 2 : extendUsedArea( aRange );
621 3 : }
622 :
623 3 : void WorksheetFragment::importSheetFormatPr( SequenceInputStream& rStrm )
624 : {
625 : sal_Int32 nDefaultWidth;
626 : sal_uInt16 nBaseWidth, nDefaultHeight, nFlags;
627 3 : nDefaultWidth = rStrm.readInt32();
628 3 : nBaseWidth = rStrm.readuInt16();
629 3 : nDefaultHeight = rStrm.readuInt16();
630 3 : nFlags = rStrm.readuInt16();
631 :
632 : // base column with
633 3 : setBaseColumnWidth( nBaseWidth );
634 : // default width is stored as 1/256th of a character in BIFF12, convert to entire character
635 3 : setDefaultColumnWidth( static_cast< double >( nDefaultWidth ) / 256.0 );
636 : // row height is in twips in BIFF12, convert to points; equal flags in all BIFFs
637 : setDefaultRowSettings(
638 : nDefaultHeight / 20.0,
639 3 : getFlag( nFlags, BIFF_DEFROW_CUSTOMHEIGHT ),
640 3 : getFlag( nFlags, BIFF_DEFROW_HIDDEN ),
641 3 : getFlag( nFlags, BIFF_DEFROW_THICKTOP ),
642 12 : getFlag( nFlags, BIFF_DEFROW_THICKBOTTOM ) );
643 3 : }
644 :
645 2 : void WorksheetFragment::importCol( SequenceInputStream& rStrm )
646 : {
647 2 : ColumnModel aModel;
648 :
649 : sal_Int32 nWidth;
650 : sal_uInt16 nFlags;
651 2 : aModel.maRange.mnFirst = rStrm.readInt32();
652 2 : aModel.maRange.mnLast = rStrm.readInt32();
653 2 : nWidth = rStrm.readInt32();
654 2 : aModel.mnXfId = rStrm.readInt32();
655 2 : nFlags = rStrm.readuInt16();
656 :
657 : // column indexes are 0-based in BIFF12, but ColumnModel expects 1-based
658 2 : ++aModel.maRange.mnFirst;
659 2 : ++aModel.maRange.mnLast;
660 : // width is stored as 1/256th of a character in BIFF12, convert to entire character
661 2 : aModel.mfWidth = static_cast< double >( nWidth ) / 256.0;
662 : // equal flags in all BIFFs
663 2 : aModel.mnLevel = extractValue< sal_Int32 >( nFlags, 8, 3 );
664 2 : aModel.mbShowPhonetic = getFlag( nFlags, BIFF_COLINFO_SHOWPHONETIC );
665 2 : aModel.mbHidden = getFlag( nFlags, BIFF_COLINFO_HIDDEN );
666 2 : aModel.mbCollapsed = getFlag( nFlags, BIFF_COLINFO_COLLAPSED );
667 : // set column properties in the current sheet
668 2 : setColumnModel( aModel );
669 2 : }
670 :
671 1 : void WorksheetFragment::importMergeCell( SequenceInputStream& rStrm )
672 : {
673 1 : BinRange aBinRange;
674 1 : rStrm >> aBinRange;
675 1 : CellRangeAddress aRange;
676 1 : if( getAddressConverter().convertToCellRange( aRange, aBinRange, getSheetIndex(), true, true ) )
677 1 : getSheetData().setMergedRange( aRange );
678 1 : }
679 :
680 0 : void WorksheetFragment::importHyperlink( SequenceInputStream& rStrm )
681 : {
682 0 : BinRange aBinRange;
683 0 : rStrm >> aBinRange;
684 0 : HyperlinkModel aModel;
685 0 : if( getAddressConverter().convertToCellRange( aModel.maRange, aBinRange, getSheetIndex(), true, true ) )
686 : {
687 0 : aModel.maTarget = getRelations().getExternalTargetFromRelId( BiffHelper::readString( rStrm ) );
688 0 : rStrm >> aModel.maLocation >> aModel.maTooltip >> aModel.maDisplay;
689 0 : setHyperlink( aModel );
690 0 : }
691 0 : }
692 :
693 0 : void WorksheetFragment::importBrk( SequenceInputStream& rStrm, bool bRowBreak )
694 : {
695 0 : PageBreakModel aModel;
696 : sal_Int32 nManual;
697 0 : aModel.mnColRow = rStrm.readInt32();
698 0 : aModel.mnMin = rStrm.readInt32();
699 0 : aModel.mnMax = rStrm.readInt32();
700 0 : nManual = rStrm.readInt32();
701 0 : aModel.mbManual = nManual != 0;
702 0 : setPageBreak( aModel, bRowBreak );
703 0 : }
704 :
705 1 : void WorksheetFragment::importDrawing( SequenceInputStream& rStrm )
706 : {
707 1 : setDrawingPath( getFragmentPathFromRelId( BiffHelper::readString( rStrm ) ) );
708 1 : }
709 :
710 1 : void WorksheetFragment::importLegacyDrawing( SequenceInputStream& rStrm )
711 : {
712 1 : setVmlDrawingPath( getFragmentPathFromRelId( BiffHelper::readString( rStrm ) ) );
713 1 : }
714 :
715 0 : void WorksheetFragment::importOleObject( SequenceInputStream& rStrm )
716 : {
717 0 : ::oox::vml::OleObjectInfo aInfo;
718 : sal_Int32 nAspect, nUpdateMode, nShapeId;
719 : sal_uInt16 nFlags;
720 0 : nAspect = rStrm.readInt32();
721 0 : nUpdateMode = rStrm.readInt32();
722 0 : nShapeId = rStrm.readInt32();
723 0 : nFlags = rStrm.readuInt16();
724 0 : rStrm >> aInfo.maProgId;
725 0 : aInfo.mbLinked = getFlag( nFlags, BIFF12_OLEOBJECT_LINKED );
726 0 : if( aInfo.mbLinked )
727 0 : aInfo.maTargetLink = getFormulaParser().importOleTargetLink( rStrm );
728 : else
729 0 : importEmbeddedOleData( aInfo.maEmbeddedData, BiffHelper::readString( rStrm ) );
730 0 : aInfo.setShapeId( nShapeId );
731 0 : aInfo.mbShowAsIcon = nAspect == BIFF12_OLEOBJECT_ICON;
732 0 : aInfo.mbAutoUpdate = nUpdateMode == BIFF12_OLEOBJECT_ALWAYS;
733 0 : aInfo.mbAutoLoad = getFlag( nFlags, BIFF12_OLEOBJECT_AUTOLOAD );
734 0 : getVmlDrawing().registerOleObject( aInfo );
735 0 : }
736 :
737 0 : void WorksheetFragment::importControl( SequenceInputStream& rStrm )
738 : {
739 0 : ::oox::vml::ControlInfo aInfo;
740 0 : aInfo.setShapeId( rStrm.readInt32() );
741 0 : aInfo.maFragmentPath = getFragmentPathFromRelId( BiffHelper::readString( rStrm ) );
742 0 : rStrm >> aInfo.maName;
743 0 : getVmlDrawing().registerControl( aInfo );
744 0 : }
745 :
746 0 : void WorksheetFragment::importEmbeddedOleData( StreamDataSequence& orEmbeddedData, const OUString& rRelId )
747 : {
748 0 : OUString aFragmentPath = getFragmentPathFromRelId( rRelId );
749 0 : if( !aFragmentPath.isEmpty() )
750 0 : getBaseFilter().importBinaryData( orEmbeddedData, aFragmentPath );
751 0 : }
752 :
753 : } // namespace xls
754 30 : } // namespace oox
755 :
756 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|