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