1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 #include "oox/xls/worksheetfragment.hxx"
25
26 #include "oox/core/filterbase.hxx"
27 #include "oox/core/relations.hxx"
28 #include "oox/helper/attributelist.hxx"
29 #include "oox/xls/addressconverter.hxx"
30 #include "oox/xls/autofilterbuffer.hxx"
31 #include "oox/xls/autofiltercontext.hxx"
32 #include "oox/xls/biffinputstream.hxx"
33 #include "oox/xls/commentsfragment.hxx"
34 #include "oox/xls/condformatcontext.hxx"
35 #include "oox/xls/drawingfragment.hxx"
36 #include "oox/xls/drawingmanager.hxx"
37 #include "oox/xls/externallinkbuffer.hxx"
38 #include "oox/xls/pagesettings.hxx"
39 #include "oox/xls/pivottablefragment.hxx"
40 #include "oox/xls/querytablefragment.hxx"
41 #include "oox/xls/scenariobuffer.hxx"
42 #include "oox/xls/scenariocontext.hxx"
43 #include "oox/xls/sheetdatabuffer.hxx"
44 #include "oox/xls/sheetdatacontext.hxx"
45 #include "oox/xls/tablefragment.hxx"
46 #include "oox/xls/viewsettings.hxx"
47 #include "oox/xls/workbooksettings.hxx"
48 #include "oox/xls/worksheetsettings.hxx"
49
50 namespace oox {
51 namespace xls {
52
53 // ============================================================================
54
55 using namespace ::com::sun::star::table;
56 using namespace ::com::sun::star::uno;
57 using namespace ::oox::core;
58
59 using ::rtl::OUString;
60 using ::rtl::OUStringBuffer;
61
62 // ============================================================================
63
64 namespace {
65
66 const sal_uInt16 BIFF_COLINFO_HIDDEN = 0x0001;
67 const sal_uInt16 BIFF_COLINFO_SHOWPHONETIC = 0x0008;
68 const sal_uInt16 BIFF_COLINFO_COLLAPSED = 0x1000;
69
70 const sal_uInt16 BIFF_DEFROW_CUSTOMHEIGHT = 0x0001;
71 const sal_uInt16 BIFF_DEFROW_HIDDEN = 0x0002;
72 const sal_uInt16 BIFF_DEFROW_THICKTOP = 0x0004;
73 const sal_uInt16 BIFF_DEFROW_THICKBOTTOM = 0x0008;
74 const sal_uInt16 BIFF2_DEFROW_DEFHEIGHT = 0x8000;
75 const sal_uInt16 BIFF2_DEFROW_MASK = 0x7FFF;
76
77 const sal_uInt32 BIFF_DATAVAL_STRINGLIST = 0x00000080;
78 const sal_uInt32 BIFF_DATAVAL_ALLOWBLANK = 0x00000100;
79 const sal_uInt32 BIFF_DATAVAL_NODROPDOWN = 0x00000200;
80 const sal_uInt32 BIFF_DATAVAL_SHOWINPUT = 0x00040000;
81 const sal_uInt32 BIFF_DATAVAL_SHOWERROR = 0x00080000;
82
83 const sal_uInt32 BIFF_SHRFEATHEAD_SHEETPROT = 2;
84
85 const sal_Int32 BIFF12_OLEOBJECT_CONTENT = 1;
86 const sal_Int32 BIFF12_OLEOBJECT_ICON = 4;
87 const sal_Int32 BIFF12_OLEOBJECT_ALWAYS = 1;
88 const sal_Int32 BIFF12_OLEOBJECT_ONCALL = 3;
89 const sal_uInt16 BIFF12_OLEOBJECT_LINKED = 0x0001;
90 const sal_uInt16 BIFF12_OLEOBJECT_AUTOLOAD = 0x0002;
91
92 } // namespace
93
94 // ============================================================================
95
DataValidationsContext(WorksheetFragmentBase & rFragment)96 DataValidationsContext::DataValidationsContext( WorksheetFragmentBase& rFragment ) :
97 WorksheetContextBase( rFragment )
98 {
99 }
100
onCreateContext(sal_Int32 nElement,const AttributeList & rAttribs)101 ContextHandlerRef DataValidationsContext::onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs )
102 {
103 switch( getCurrentElement() )
104 {
105 case XLS_TOKEN( dataValidations ):
106 if( nElement == XLS_TOKEN( dataValidation ) )
107 {
108 importDataValidation( rAttribs );
109 return this;
110 }
111 break;
112 case XLS_TOKEN( dataValidation ):
113 switch( nElement )
114 {
115 case XLS_TOKEN( formula1 ):
116 case XLS_TOKEN( formula2 ):
117 return this; // collect formulas in onCharacters()
118 }
119 break;
120 }
121 return 0;
122 }
123
onCharacters(const OUString & rChars)124 void DataValidationsContext::onCharacters( const OUString& rChars )
125 {
126 if( mxValModel.get() ) switch( getCurrentElement() )
127 {
128 case XLS_TOKEN( formula1 ):
129 mxValModel->maTokens1 = getFormulaParser().importFormula( mxValModel->maRanges.getBaseAddress(), rChars );
130 // process string list of a list validation (convert to list of string tokens)
131 if( mxValModel->mnType == XML_list )
132 getFormulaParser().convertStringToStringList( mxValModel->maTokens1, ',', true );
133 break;
134 case XLS_TOKEN( formula2 ):
135 mxValModel->maTokens2 = getFormulaParser().importFormula( mxValModel->maRanges.getBaseAddress(), rChars );
136 break;
137 }
138 }
139
onEndElement()140 void DataValidationsContext::onEndElement()
141 {
142 if( isCurrentElement( XLS_TOKEN( dataValidation ) ) && mxValModel.get() )
143 {
144 setValidation( *mxValModel );
145 mxValModel.reset();
146 }
147 }
148
149
onCreateRecordContext(sal_Int32 nRecId,SequenceInputStream & rStrm)150 ContextHandlerRef DataValidationsContext::onCreateRecordContext( sal_Int32 nRecId, SequenceInputStream& rStrm )
151 {
152 if( nRecId == BIFF12_ID_DATAVALIDATION )
153 importDataValidation( rStrm );
154 return 0;
155 }
156
importDataValidation(const AttributeList & rAttribs)157 void DataValidationsContext::importDataValidation( const AttributeList& rAttribs )
158 {
159 mxValModel.reset( new ValidationModel );
160 getAddressConverter().convertToCellRangeList( mxValModel->maRanges, rAttribs.getString( XML_sqref, OUString() ), getSheetIndex(), true );
161 mxValModel->msRef = rAttribs.getString( XML_sqref, OUString() );
162 mxValModel->maInputTitle = rAttribs.getXString( XML_promptTitle, OUString() );
163 mxValModel->maInputMessage = rAttribs.getXString( XML_prompt, OUString() );
164 mxValModel->maErrorTitle = rAttribs.getXString( XML_errorTitle, OUString() );
165 mxValModel->maErrorMessage = rAttribs.getXString( XML_error, OUString() );
166 mxValModel->mnType = rAttribs.getToken( XML_type, XML_none );
167 mxValModel->mnOperator = rAttribs.getToken( XML_operator, XML_between );
168 mxValModel->mnErrorStyle = rAttribs.getToken( XML_errorStyle, XML_stop );
169 mxValModel->mbShowInputMsg = rAttribs.getBool( XML_showInputMessage, false );
170 mxValModel->mbShowErrorMsg = rAttribs.getBool( XML_showErrorMessage, false );
171 /* The attribute showDropDown@dataValidation is in fact a "suppress
172 dropdown" flag, as it was in the BIFF format! ECMA specification
173 and attribute name are plain wrong! */
174 mxValModel->mbNoDropDown = rAttribs.getBool( XML_showDropDown, false );
175 mxValModel->mbAllowBlank = rAttribs.getBool( XML_allowBlank, false );
176 }
177
importDataValidation(SequenceInputStream & rStrm)178 void DataValidationsContext::importDataValidation( SequenceInputStream& rStrm )
179 {
180 ValidationModel aModel;
181
182 sal_uInt32 nFlags;
183 BinRangeList aRanges;
184 rStrm >> nFlags >> aRanges >> aModel.maErrorTitle >> aModel.maErrorMessage >> aModel.maInputTitle >> aModel.maInputMessage;
185
186 // equal flags in all BIFFs
187 aModel.setBiffType( extractValue< sal_uInt8 >( nFlags, 0, 4 ) );
188 aModel.setBiffOperator( extractValue< sal_uInt8 >( nFlags, 20, 4 ) );
189 aModel.setBiffErrorStyle( extractValue< sal_uInt8 >( nFlags, 4, 3 ) );
190 aModel.mbAllowBlank = getFlag( nFlags, BIFF_DATAVAL_ALLOWBLANK );
191 aModel.mbNoDropDown = getFlag( nFlags, BIFF_DATAVAL_NODROPDOWN );
192 aModel.mbShowInputMsg = getFlag( nFlags, BIFF_DATAVAL_SHOWINPUT );
193 aModel.mbShowErrorMsg = getFlag( nFlags, BIFF_DATAVAL_SHOWERROR );
194
195 // cell range list
196 getAddressConverter().convertToCellRangeList( aModel.maRanges, aRanges, getSheetIndex(), true );
197
198 // condition formula(s)
199 FormulaParser& rParser = getFormulaParser();
200 CellAddress aBaseAddr = aModel.maRanges.getBaseAddress();
201 aModel.maTokens1 = rParser.importFormula( aBaseAddr, FORMULATYPE_VALIDATION, rStrm );
202 aModel.maTokens2 = rParser.importFormula( aBaseAddr, FORMULATYPE_VALIDATION, rStrm );
203 // process string list of a list validation (convert to list of string tokens)
204 if( (aModel.mnType == XML_list) && getFlag( nFlags, BIFF_DATAVAL_STRINGLIST ) )
205 rParser.convertStringToStringList( aModel.maTokens1, ',', true );
206
207 // set validation data
208 setValidation( aModel );
209 }
210
211 // ============================================================================
212
WorksheetFragment(const WorksheetHelper & rHelper,const OUString & rFragmentPath)213 WorksheetFragment::WorksheetFragment( const WorksheetHelper& rHelper, const OUString& rFragmentPath ) :
214 WorksheetFragmentBase( rHelper, rFragmentPath )
215 {
216 // import data tables related to this worksheet
217 RelationsRef xTableRels = getRelations().getRelationsFromType( CREATE_OFFICEDOC_RELATION_TYPE( "table" ) );
218 for( Relations::const_iterator aIt = xTableRels->begin(), aEnd = xTableRels->end(); aIt != aEnd; ++aIt )
219 importOoxFragment( new TableFragment( *this, getFragmentPathFromRelation( aIt->second ) ) );
220
221 // import comments related to this worksheet
222 OUString aCommentsFragmentPath = getFragmentPathFromFirstType( CREATE_OFFICEDOC_RELATION_TYPE( "comments" ) );
223 if( aCommentsFragmentPath.getLength() > 0 )
224 importOoxFragment( new CommentsFragment( *this, aCommentsFragmentPath ) );
225 }
226
onCreateContext(sal_Int32 nElement,const AttributeList & rAttribs)227 ContextHandlerRef WorksheetFragment::onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs )
228 {
229 switch( getCurrentElement() )
230 {
231 case XML_ROOT_CONTEXT: switch( getSheetType() )
232 {
233 case SHEETTYPE_WORKSHEET: return (nElement == XLS_TOKEN( worksheet )) ? this : 0;
234 case SHEETTYPE_CHARTSHEET: return 0;
235 case SHEETTYPE_MACROSHEET: return (nElement == XM_TOKEN( macrosheet )) ? this : 0;
236 case SHEETTYPE_DIALOGSHEET: return (nElement == XLS_TOKEN( dialogsheet )) ? this : 0;
237 case SHEETTYPE_MODULESHEET: return 0;
238 case SHEETTYPE_EMPTYSHEET: return 0;
239 }
240 break;
241
242 case XLS_TOKEN( worksheet ):
243 case XM_TOKEN( macrosheet ):
244 case XLS_TOKEN( dialogsheet ):
245 switch( nElement )
246 {
247 case XLS_TOKEN( sheetData ): return new SheetDataContext( *this );
248 case XLS_TOKEN( conditionalFormatting ): return new CondFormatContext( *this );
249 case XLS_TOKEN( dataValidations ): return new DataValidationsContext( *this );
250 case XLS_TOKEN( autoFilter ): return new AutoFilterContext( *this, getAutoFilters().createAutoFilter() );
251 case XLS_TOKEN( scenarios ): return new ScenariosContext( *this );
252
253 case XLS_TOKEN( sheetViews ):
254 case XLS_TOKEN( cols ):
255 case XLS_TOKEN( mergeCells ):
256 case XLS_TOKEN( hyperlinks ):
257 case XLS_TOKEN( rowBreaks ):
258 case XLS_TOKEN( colBreaks ):
259 case XLS_TOKEN( oleObjects ):
260 case XLS_TOKEN( controls ): return this;
261
262 case XLS_TOKEN( sheetPr ): getWorksheetSettings().importSheetPr( rAttribs ); return this;
263 case XLS_TOKEN( dimension ): importDimension( rAttribs ); break;
264 case XLS_TOKEN( sheetFormatPr ): importSheetFormatPr( rAttribs ); break;
265 case XLS_TOKEN( sheetProtection ): getWorksheetSettings().importSheetProtection( rAttribs ); break;
266 case XLS_TOKEN( phoneticPr ): getWorksheetSettings().importPhoneticPr( rAttribs ); break;
267 case XLS_TOKEN( printOptions ): getPageSettings().importPrintOptions( rAttribs ); break;
268 case XLS_TOKEN( pageMargins ): getPageSettings().importPageMargins( rAttribs ); break;
269 case XLS_TOKEN( pageSetup ): getPageSettings().importPageSetup( getRelations(), rAttribs ); break;
270 case XLS_TOKEN( headerFooter ): getPageSettings().importHeaderFooter( rAttribs ); return this;
271 case XLS_TOKEN( picture ): getPageSettings().importPicture( getRelations(), rAttribs ); break;
272 case XLS_TOKEN( drawing ): importDrawing( rAttribs ); break;
273 case XLS_TOKEN( legacyDrawing ): importLegacyDrawing( rAttribs ); break;
274 }
275 break;
276
277 case XLS_TOKEN( sheetPr ):
278 switch( nElement )
279 {
280 case XLS_TOKEN( tabColor ): getWorksheetSettings().importTabColor( rAttribs ); break;
281 case XLS_TOKEN( outlinePr ): getWorksheetSettings().importOutlinePr( rAttribs ); break;
282 case XLS_TOKEN( pageSetUpPr ): importPageSetUpPr( rAttribs ); break;
283 }
284 break;
285
286 case XLS_TOKEN( sheetViews ):
287 switch( nElement )
288 {
289 case XLS_TOKEN( sheetView ): getSheetViewSettings().importSheetView( rAttribs ); return this;
290 }
291 break;
292 case XLS_TOKEN( sheetView ):
293 switch( nElement )
294 {
295 case XLS_TOKEN( pane ): getSheetViewSettings().importPane( rAttribs ); break;
296 case XLS_TOKEN( selection ): getSheetViewSettings().importSelection( rAttribs ); break;
297 }
298 break;
299
300 case XLS_TOKEN( cols ):
301 if( nElement == XLS_TOKEN( col ) ) importCol( rAttribs );
302 break;
303 case XLS_TOKEN( mergeCells ):
304 if( nElement == XLS_TOKEN( mergeCell ) ) importMergeCell( rAttribs );
305 break;
306 case XLS_TOKEN( hyperlinks ):
307 if( nElement == XLS_TOKEN( hyperlink ) ) importHyperlink( rAttribs );
308 break;
309 case XLS_TOKEN( rowBreaks ):
310 if( nElement == XLS_TOKEN( brk ) ) importBrk( rAttribs, true );
311 break;
312 case XLS_TOKEN( colBreaks ):
313 if( nElement == XLS_TOKEN( brk ) ) importBrk( rAttribs, false );
314 break;
315
316 case XLS_TOKEN( headerFooter ):
317 switch( nElement )
318 {
319 case XLS_TOKEN( firstHeader ):
320 case XLS_TOKEN( firstFooter ):
321 case XLS_TOKEN( oddHeader ):
322 case XLS_TOKEN( oddFooter ):
323 case XLS_TOKEN( evenHeader ):
324 case XLS_TOKEN( evenFooter ): return this; // collect h/f contents in onCharacters()
325 }
326 break;
327
328 case XLS_TOKEN( oleObjects ):
329 if( nElement == XLS_TOKEN( oleObject ) ) importOleObject( rAttribs );
330 break;
331 case XLS_TOKEN( controls ):
332 if( nElement == XLS_TOKEN( control ) ) importControl( rAttribs );
333 break;
334 }
335 return 0;
336 }
337
onCharacters(const OUString & rChars)338 void WorksheetFragment::onCharacters( const OUString& rChars )
339 {
340 switch( getCurrentElement() )
341 {
342 case XLS_TOKEN( firstHeader ):
343 case XLS_TOKEN( firstFooter ):
344 case XLS_TOKEN( oddHeader ):
345 case XLS_TOKEN( oddFooter ):
346 case XLS_TOKEN( evenHeader ):
347 case XLS_TOKEN( evenFooter ):
348 getPageSettings().importHeaderFooterCharacters( rChars, getCurrentElement() );
349 break;
350 }
351 }
352
onCreateRecordContext(sal_Int32 nRecId,SequenceInputStream & rStrm)353 ContextHandlerRef WorksheetFragment::onCreateRecordContext( sal_Int32 nRecId, SequenceInputStream& rStrm )
354 {
355 switch( getCurrentElement() )
356 {
357 case XML_ROOT_CONTEXT:
358 if( nRecId == BIFF12_ID_WORKSHEET ) return this;
359 break;
360
361 case BIFF12_ID_WORKSHEET:
362 switch( nRecId )
363 {
364 case BIFF12_ID_SHEETDATA: return new SheetDataContext( *this );
365 case BIFF12_ID_CONDFORMATTING: return new CondFormatContext( *this );
366 case BIFF12_ID_DATAVALIDATIONS: return new DataValidationsContext( *this );
367 case BIFF12_ID_AUTOFILTER: return new AutoFilterContext( *this, getAutoFilters().createAutoFilter() );
368 case BIFF12_ID_SCENARIOS: return new ScenariosContext( *this );
369
370 case BIFF12_ID_SHEETVIEWS:
371 case BIFF12_ID_COLS:
372 case BIFF12_ID_MERGECELLS:
373 case BIFF12_ID_ROWBREAKS:
374 case BIFF12_ID_COLBREAKS:
375 case BIFF12_ID_OLEOBJECTS:
376 case BIFF12_ID_CONTROLS: return this;
377
378 case BIFF12_ID_SHEETPR: getWorksheetSettings().importSheetPr( rStrm ); break;
379 case BIFF12_ID_DIMENSION: importDimension( rStrm ); break;
380 case BIFF12_ID_SHEETFORMATPR: importSheetFormatPr( rStrm ); break;
381 case BIFF12_ID_HYPERLINK: importHyperlink( rStrm ); break;
382 case BIFF12_ID_PAGEMARGINS: getPageSettings().importPageMargins( rStrm ); break;
383 case BIFF12_ID_PAGESETUP: getPageSettings().importPageSetup( getRelations(), rStrm ); break;
384 case BIFF12_ID_PRINTOPTIONS: getPageSettings().importPrintOptions( rStrm ); break;
385 case BIFF12_ID_HEADERFOOTER: getPageSettings().importHeaderFooter( rStrm ); break;
386 case BIFF12_ID_PICTURE: getPageSettings().importPicture( getRelations(), rStrm ); break;
387 case BIFF12_ID_SHEETPROTECTION: getWorksheetSettings().importSheetProtection( rStrm ); break;
388 case BIFF12_ID_PHONETICPR: getWorksheetSettings().importPhoneticPr( rStrm ); break;
389 case BIFF12_ID_DRAWING: importDrawing( rStrm ); break;
390 case BIFF12_ID_LEGACYDRAWING: importLegacyDrawing( rStrm ); break;
391 }
392 break;
393
394 case BIFF12_ID_SHEETVIEWS:
395 switch( nRecId )
396 {
397 case BIFF12_ID_SHEETVIEW: getSheetViewSettings().importSheetView( rStrm ); return this;
398 }
399 break;
400 case BIFF12_ID_SHEETVIEW:
401 switch( nRecId )
402 {
403 case BIFF12_ID_PANE: getSheetViewSettings().importPane( rStrm ); break;
404 case BIFF12_ID_SELECTION: getSheetViewSettings().importSelection( rStrm ); break;
405 }
406 break;
407
408 case BIFF12_ID_COLS:
409 if( nRecId == BIFF12_ID_COL ) importCol( rStrm );
410 break;
411 case BIFF12_ID_MERGECELLS:
412 if( nRecId == BIFF12_ID_MERGECELL ) importMergeCell( rStrm );
413 break;
414 case BIFF12_ID_ROWBREAKS:
415 if( nRecId == BIFF12_ID_BRK ) importBrk( rStrm, true );
416 break;
417 case BIFF12_ID_COLBREAKS:
418 if( nRecId == BIFF12_ID_BRK ) importBrk( rStrm, false );
419 break;
420 case BIFF12_ID_OLEOBJECTS:
421 if( nRecId == BIFF12_ID_OLEOBJECT ) importOleObject( rStrm );
422 break;
423 case BIFF12_ID_CONTROLS:
424 if( nRecId == BIFF12_ID_CONTROL ) importControl( rStrm );
425 break;
426 }
427 return 0;
428 }
429
getRecordInfos() const430 const RecordInfo* WorksheetFragment::getRecordInfos() const
431 {
432 static const RecordInfo spRecInfos[] =
433 {
434 { BIFF12_ID_AUTOFILTER, BIFF12_ID_AUTOFILTER + 1 },
435 { BIFF12_ID_CFRULE, BIFF12_ID_CFRULE + 1 },
436 { BIFF12_ID_COLBREAKS, BIFF12_ID_COLBREAKS + 1 },
437 { BIFF12_ID_COLORSCALE, BIFF12_ID_COLORSCALE + 1 },
438 { BIFF12_ID_COLS, BIFF12_ID_COLS + 1 },
439 { BIFF12_ID_CONDFORMATTING, BIFF12_ID_CONDFORMATTING + 1 },
440 { BIFF12_ID_CONTROLS, BIFF12_ID_CONTROLS + 2 },
441 { BIFF12_ID_CUSTOMFILTERS, BIFF12_ID_CUSTOMFILTERS + 1 },
442 { BIFF12_ID_CUSTOMSHEETVIEW, BIFF12_ID_CUSTOMSHEETVIEW + 1 },
443 { BIFF12_ID_CUSTOMSHEETVIEWS, BIFF12_ID_CUSTOMSHEETVIEWS + 3 },
444 { BIFF12_ID_DATABAR, BIFF12_ID_DATABAR + 1 },
445 { BIFF12_ID_DATAVALIDATIONS, BIFF12_ID_DATAVALIDATIONS + 1 },
446 { BIFF12_ID_DISCRETEFILTERS, BIFF12_ID_DISCRETEFILTERS + 1 },
447 { BIFF12_ID_FILTERCOLUMN, BIFF12_ID_FILTERCOLUMN + 1 },
448 { BIFF12_ID_HEADERFOOTER, BIFF12_ID_HEADERFOOTER + 1 },
449 { BIFF12_ID_ICONSET, BIFF12_ID_ICONSET + 1 },
450 { BIFF12_ID_MERGECELLS, BIFF12_ID_MERGECELLS + 1 },
451 { BIFF12_ID_OLEOBJECTS, BIFF12_ID_OLEOBJECTS + 2 },
452 { BIFF12_ID_ROW, -1 },
453 { BIFF12_ID_ROWBREAKS, BIFF12_ID_ROWBREAKS + 1 },
454 { BIFF12_ID_SCENARIO, BIFF12_ID_SCENARIO + 1 },
455 { BIFF12_ID_SCENARIOS, BIFF12_ID_SCENARIOS + 1 },
456 { BIFF12_ID_SHEETDATA, BIFF12_ID_SHEETDATA + 1 },
457 { BIFF12_ID_SHEETVIEW, BIFF12_ID_SHEETVIEW + 1 },
458 { BIFF12_ID_SHEETVIEWS, BIFF12_ID_SHEETVIEWS + 1 },
459 { BIFF12_ID_TABLEPARTS, BIFF12_ID_TABLEPARTS + 2 },
460 { BIFF12_ID_WORKSHEET, BIFF12_ID_WORKSHEET + 1 },
461 { -1, -1 }
462 };
463 return spRecInfos;
464 }
465
initializeImport()466 void WorksheetFragment::initializeImport()
467 {
468 // initial processing in base class WorksheetHelper
469 initializeWorksheetImport();
470
471 // import query table fragments related to this worksheet
472 RelationsRef xQueryRels = getRelations().getRelationsFromType( CREATE_OFFICEDOC_RELATION_TYPE( "queryTable" ) );
473 for( Relations::const_iterator aIt = xQueryRels->begin(), aEnd = xQueryRels->end(); aIt != aEnd; ++aIt )
474 importOoxFragment( new QueryTableFragment( *this, getFragmentPathFromRelation( aIt->second ) ) );
475
476 // import pivot table fragments related to this worksheet
477 RelationsRef xPivotRels = getRelations().getRelationsFromType( CREATE_OFFICEDOC_RELATION_TYPE( "pivotTable" ) );
478 for( Relations::const_iterator aIt = xPivotRels->begin(), aEnd = xPivotRels->end(); aIt != aEnd; ++aIt )
479 importOoxFragment( new PivotTableFragment( *this, getFragmentPathFromRelation( aIt->second ) ) );
480 }
481
finalizeImport()482 void WorksheetFragment::finalizeImport()
483 {
484 // final processing in base class WorksheetHelper
485 finalizeWorksheetImport();
486 }
487
488 // private --------------------------------------------------------------------
489
importPageSetUpPr(const AttributeList & rAttribs)490 void WorksheetFragment::importPageSetUpPr( const AttributeList& rAttribs )
491 {
492 // for whatever reason, this flag is still stored separated from the page settings
493 getPageSettings().setFitToPagesMode( rAttribs.getBool( XML_fitToPage, false ) );
494 }
495
importDimension(const AttributeList & rAttribs)496 void WorksheetFragment::importDimension( const AttributeList& rAttribs )
497 {
498 CellRangeAddress aRange;
499 getAddressConverter().convertToCellRangeUnchecked( aRange, rAttribs.getString( XML_ref, OUString() ), getSheetIndex() );
500 /* OOXML stores the used area, if existing, or "A1" if the sheet is empty.
501 In case of "A1", the dimension at the WorksheetHelper object will not
502 be set. If the cell A1 exists, the used area will be updated while
503 importing the cell. */
504 if( (aRange.EndColumn > 0) || (aRange.EndRow > 0) )
505 extendUsedArea( aRange );
506 }
507
importSheetFormatPr(const AttributeList & rAttribs)508 void WorksheetFragment::importSheetFormatPr( const AttributeList& rAttribs )
509 {
510 // default column settings
511 setBaseColumnWidth( rAttribs.getInteger( XML_baseColWidth, 8 ) );
512 setDefaultColumnWidth( rAttribs.getDouble( XML_defaultColWidth, 0.0 ) );
513 // default row settings
514 setDefaultRowSettings(
515 rAttribs.getDouble( XML_defaultRowHeight, 0.0 ),
516 rAttribs.getBool( XML_customHeight, false ),
517 rAttribs.getBool( XML_zeroHeight, false ),
518 rAttribs.getBool( XML_thickTop, false ),
519 rAttribs.getBool( XML_thickBottom, false ) );
520 }
521
importCol(const AttributeList & rAttribs)522 void WorksheetFragment::importCol( const AttributeList& rAttribs )
523 {
524 ColumnModel aModel;
525 aModel.maRange.mnFirst = rAttribs.getInteger( XML_min, -1 );
526 aModel.maRange.mnLast = rAttribs.getInteger( XML_max, -1 );
527 aModel.mfWidth = rAttribs.getDouble( XML_width, 0.0 );
528 aModel.mnXfId = rAttribs.getInteger( XML_style, -1 );
529 aModel.mnLevel = rAttribs.getInteger( XML_outlineLevel, 0 );
530 aModel.mbShowPhonetic = rAttribs.getBool( XML_phonetic, false );
531 aModel.mbHidden = rAttribs.getBool( XML_hidden, false );
532 aModel.mbCollapsed = rAttribs.getBool( XML_collapsed, false );
533 // set column properties in the current sheet
534 setColumnModel( aModel );
535 }
536
importMergeCell(const AttributeList & rAttribs)537 void WorksheetFragment::importMergeCell( const AttributeList& rAttribs )
538 {
539 CellRangeAddress aRange;
540 if( getAddressConverter().convertToCellRange( aRange, rAttribs.getString( XML_ref, OUString() ), getSheetIndex(), true, true ) )
541 getSheetData().setMergedRange( aRange );
542 }
543
importHyperlink(const AttributeList & rAttribs)544 void WorksheetFragment::importHyperlink( const AttributeList& rAttribs )
545 {
546 HyperlinkModel aModel;
547 if( getAddressConverter().convertToCellRange( aModel.maRange, rAttribs.getString( XML_ref, OUString() ), getSheetIndex(), true, true ) )
548 {
549 aModel.maTarget = getRelations().getExternalTargetFromRelId( rAttribs.getString( R_TOKEN( id ), OUString() ) );
550 aModel.maLocation = rAttribs.getXString( XML_location, OUString() );
551 aModel.maDisplay = rAttribs.getXString( XML_display, OUString() );
552 aModel.maTooltip = rAttribs.getXString( XML_tooltip, OUString() );
553 setHyperlink( aModel );
554 }
555 }
556
importBrk(const AttributeList & rAttribs,bool bRowBreak)557 void WorksheetFragment::importBrk( const AttributeList& rAttribs, bool bRowBreak )
558 {
559 PageBreakModel aModel;
560 aModel.mnColRow = rAttribs.getInteger( XML_id, 0 );
561 aModel.mnMin = rAttribs.getInteger( XML_id, 0 );
562 aModel.mnMax = rAttribs.getInteger( XML_id, 0 );
563 aModel.mbManual = rAttribs.getBool( XML_man, false );
564 setPageBreak( aModel, bRowBreak );
565 }
566
importDrawing(const AttributeList & rAttribs)567 void WorksheetFragment::importDrawing( const AttributeList& rAttribs )
568 {
569 setDrawingPath( getFragmentPathFromRelId( rAttribs.getString( R_TOKEN( id ), OUString() ) ) );
570 }
571
importLegacyDrawing(const AttributeList & rAttribs)572 void WorksheetFragment::importLegacyDrawing( const AttributeList& rAttribs )
573 {
574 setVmlDrawingPath( getFragmentPathFromRelId( rAttribs.getString( R_TOKEN( id ), OUString() ) ) );
575 }
576
importOleObject(const AttributeList & rAttribs)577 void WorksheetFragment::importOleObject( const AttributeList& rAttribs )
578 {
579 ::oox::vml::OleObjectInfo aInfo;
580 aInfo.setShapeId( rAttribs.getInteger( XML_shapeId, 0 ) );
581 OSL_ENSURE( rAttribs.hasAttribute( XML_link ) != rAttribs.hasAttribute( R_TOKEN( id ) ),
582 "WorksheetFragment::importOleObject - OLE object must be either linked or embedded" );
583 aInfo.mbLinked = rAttribs.hasAttribute( XML_link );
584 if( aInfo.mbLinked )
585 aInfo.maTargetLink = getFormulaParser().importOleTargetLink( rAttribs.getString( XML_link, OUString() ) );
586 else if( rAttribs.hasAttribute( R_TOKEN( id ) ) )
587 importEmbeddedOleData( aInfo.maEmbeddedData, rAttribs.getString( R_TOKEN( id ), OUString() ) );
588 aInfo.maProgId = rAttribs.getString( XML_progId, OUString() );
589 aInfo.mbShowAsIcon = rAttribs.getToken( XML_dvAspect, XML_DVASPECT_CONTENT ) == XML_DVASPECT_ICON;
590 aInfo.mbAutoUpdate = rAttribs.getToken( XML_oleUpdate, XML_OLEUPDATE_ONCALL ) == XML_OLEUPDATE_ALWAYS;
591 aInfo.mbAutoLoad = rAttribs.getBool( XML_autoLoad, false );
592 getVmlDrawing().registerOleObject( aInfo );
593 }
594
importControl(const AttributeList & rAttribs)595 void WorksheetFragment::importControl( const AttributeList& rAttribs )
596 {
597 ::oox::vml::ControlInfo aInfo;
598 aInfo.setShapeId( rAttribs.getInteger( XML_shapeId, 0 ) );
599 aInfo.maFragmentPath = getFragmentPathFromRelId( rAttribs.getString( R_TOKEN( id ), OUString() ) );
600 aInfo.maName = rAttribs.getString( XML_name, OUString() );
601 getVmlDrawing().registerControl( aInfo );
602 }
603
importDimension(SequenceInputStream & rStrm)604 void WorksheetFragment::importDimension( SequenceInputStream& rStrm )
605 {
606 BinRange aBinRange;
607 aBinRange.read( rStrm );
608 CellRangeAddress aRange;
609 getAddressConverter().convertToCellRangeUnchecked( aRange, aBinRange, getSheetIndex() );
610 /* BIFF12 stores the used area, if existing, or "A1" if the sheet is
611 empty. In case of "A1", the dimension at the WorksheetHelper object
612 will not be set. If the cell A1 exists, the used area will be updated
613 while importing the cell. */
614 if( (aRange.EndColumn > 0) || (aRange.EndRow > 0) )
615 extendUsedArea( aRange );
616 }
617
importSheetFormatPr(SequenceInputStream & rStrm)618 void WorksheetFragment::importSheetFormatPr( SequenceInputStream& rStrm )
619 {
620 sal_Int32 nDefaultWidth;
621 sal_uInt16 nBaseWidth, nDefaultHeight, nFlags;
622 rStrm >> nDefaultWidth >> nBaseWidth >> nDefaultHeight >> nFlags;
623
624 // base column with
625 setBaseColumnWidth( nBaseWidth );
626 // default width is stored as 1/256th of a character in BIFF12, convert to entire character
627 setDefaultColumnWidth( static_cast< double >( nDefaultWidth ) / 256.0 );
628 // row height is in twips in BIFF12, convert to points; equal flags in all BIFFs
629 setDefaultRowSettings(
630 nDefaultHeight / 20.0,
631 getFlag( nFlags, BIFF_DEFROW_CUSTOMHEIGHT ),
632 getFlag( nFlags, BIFF_DEFROW_HIDDEN ),
633 getFlag( nFlags, BIFF_DEFROW_THICKTOP ),
634 getFlag( nFlags, BIFF_DEFROW_THICKBOTTOM ) );
635 }
636
importCol(SequenceInputStream & rStrm)637 void WorksheetFragment::importCol( SequenceInputStream& rStrm )
638 {
639 ColumnModel aModel;
640
641 sal_Int32 nWidth;
642 sal_uInt16 nFlags;
643 rStrm >> aModel.maRange.mnFirst >> aModel.maRange.mnLast >> nWidth >> aModel.mnXfId >> nFlags;
644
645 // column indexes are 0-based in BIFF12, but ColumnModel expects 1-based
646 ++aModel.maRange.mnFirst;
647 ++aModel.maRange.mnLast;
648 // width is stored as 1/256th of a character in BIFF12, convert to entire character
649 aModel.mfWidth = static_cast< double >( nWidth ) / 256.0;
650 // equal flags in all BIFFs
651 aModel.mnLevel = extractValue< sal_Int32 >( nFlags, 8, 3 );
652 aModel.mbShowPhonetic = getFlag( nFlags, BIFF_COLINFO_SHOWPHONETIC );
653 aModel.mbHidden = getFlag( nFlags, BIFF_COLINFO_HIDDEN );
654 aModel.mbCollapsed = getFlag( nFlags, BIFF_COLINFO_COLLAPSED );
655 // set column properties in the current sheet
656 setColumnModel( aModel );
657 }
658
importMergeCell(SequenceInputStream & rStrm)659 void WorksheetFragment::importMergeCell( SequenceInputStream& rStrm )
660 {
661 BinRange aBinRange;
662 rStrm >> aBinRange;
663 CellRangeAddress aRange;
664 if( getAddressConverter().convertToCellRange( aRange, aBinRange, getSheetIndex(), true, true ) )
665 getSheetData().setMergedRange( aRange );
666 }
667
importHyperlink(SequenceInputStream & rStrm)668 void WorksheetFragment::importHyperlink( SequenceInputStream& rStrm )
669 {
670 BinRange aBinRange;
671 rStrm >> aBinRange;
672 HyperlinkModel aModel;
673 if( getAddressConverter().convertToCellRange( aModel.maRange, aBinRange, getSheetIndex(), true, true ) )
674 {
675 aModel.maTarget = getRelations().getExternalTargetFromRelId( BiffHelper::readString( rStrm ) );
676 rStrm >> aModel.maLocation >> aModel.maTooltip >> aModel.maDisplay;
677 setHyperlink( aModel );
678 }
679 }
680
importBrk(SequenceInputStream & rStrm,bool bRowBreak)681 void WorksheetFragment::importBrk( SequenceInputStream& rStrm, bool bRowBreak )
682 {
683 PageBreakModel aModel;
684 sal_Int32 nManual;
685 rStrm >> aModel.mnColRow >> aModel.mnMin >> aModel.mnMax >> nManual;
686 aModel.mbManual = nManual != 0;
687 setPageBreak( aModel, bRowBreak );
688 }
689
importDrawing(SequenceInputStream & rStrm)690 void WorksheetFragment::importDrawing( SequenceInputStream& rStrm )
691 {
692 setDrawingPath( getFragmentPathFromRelId( BiffHelper::readString( rStrm ) ) );
693 }
694
importLegacyDrawing(SequenceInputStream & rStrm)695 void WorksheetFragment::importLegacyDrawing( SequenceInputStream& rStrm )
696 {
697 setVmlDrawingPath( getFragmentPathFromRelId( BiffHelper::readString( rStrm ) ) );
698 }
699
importOleObject(SequenceInputStream & rStrm)700 void WorksheetFragment::importOleObject( SequenceInputStream& rStrm )
701 {
702 ::oox::vml::OleObjectInfo aInfo;
703 sal_Int32 nAspect, nUpdateMode, nShapeId;
704 sal_uInt16 nFlags;
705 rStrm >> nAspect >> nUpdateMode >> nShapeId >> nFlags >> aInfo.maProgId;
706 aInfo.mbLinked = getFlag( nFlags, BIFF12_OLEOBJECT_LINKED );
707 if( aInfo.mbLinked )
708 aInfo.maTargetLink = getFormulaParser().importOleTargetLink( rStrm );
709 else
710 importEmbeddedOleData( aInfo.maEmbeddedData, BiffHelper::readString( rStrm ) );
711 aInfo.setShapeId( nShapeId );
712 aInfo.mbShowAsIcon = nAspect == BIFF12_OLEOBJECT_ICON;
713 aInfo.mbAutoUpdate = nUpdateMode == BIFF12_OLEOBJECT_ALWAYS;
714 aInfo.mbAutoLoad = getFlag( nFlags, BIFF12_OLEOBJECT_AUTOLOAD );
715 getVmlDrawing().registerOleObject( aInfo );
716 }
717
importControl(SequenceInputStream & rStrm)718 void WorksheetFragment::importControl( SequenceInputStream& rStrm )
719 {
720 ::oox::vml::ControlInfo aInfo;
721 aInfo.setShapeId( rStrm.readInt32() );
722 aInfo.maFragmentPath = getFragmentPathFromRelId( BiffHelper::readString( rStrm ) );
723 rStrm >> aInfo.maName;
724 getVmlDrawing().registerControl( aInfo );
725 }
726
importEmbeddedOleData(StreamDataSequence & orEmbeddedData,const OUString & rRelId)727 void WorksheetFragment::importEmbeddedOleData( StreamDataSequence& orEmbeddedData, const OUString& rRelId )
728 {
729 OUString aFragmentPath = getFragmentPathFromRelId( rRelId );
730 if( aFragmentPath.getLength() > 0 )
731 getBaseFilter().importBinaryData( orEmbeddedData, aFragmentPath );
732 }
733
734 // ============================================================================
735
BiffWorksheetFragment(const WorksheetHelper & rHelper,const BiffWorkbookFragmentBase & rParent)736 BiffWorksheetFragment::BiffWorksheetFragment( const WorksheetHelper& rHelper, const BiffWorkbookFragmentBase& rParent ) :
737 BiffWorksheetFragmentBase( rHelper, rParent )
738 {
739 }
740
~BiffWorksheetFragment()741 BiffWorksheetFragment::~BiffWorksheetFragment()
742 {
743 }
744
importFragment()745 bool BiffWorksheetFragment::importFragment()
746 {
747 // initial processing in base class WorksheetHelper
748 initializeWorksheetImport();
749
750 // create a SheetDataContext object that implements cell import
751 BiffSheetDataContext aSheetData( *this );
752
753 WorkbookSettings& rWorkbookSett = getWorkbookSettings();
754 WorksheetSettings& rWorksheetSett = getWorksheetSettings();
755 SheetViewSettings& rSheetViewSett = getSheetViewSettings();
756 CondFormatBuffer& rCondFormats = getCondFormats();
757 PageSettings& rPageSett = getPageSettings();
758 BiffSheetDrawing& rDrawing = getBiffDrawing();
759
760 // process all record in this sheet fragment
761 BiffInputStream& rStrm = getInputStream();
762 while( rStrm.startNextRecord() && (rStrm.getRecId() != BIFF_ID_EOF) )
763 {
764 if( BiffHelper::isBofRecord( rStrm ) )
765 {
766 // skip unknown embedded fragments (BOF/EOF blocks)
767 skipFragment();
768 }
769 else
770 {
771 // cache base stream position to detect if record is already processed
772 sal_Int64 nStrmPos = rStrm.tellBase();
773 sal_uInt16 nRecId = rStrm.getRecId();
774
775 switch( nRecId )
776 {
777 // records in all BIFF versions
778 case BIFF_ID_BOTTOMMARGIN: rPageSett.importBottomMargin( rStrm ); break;
779 case BIFF_ID_CALCCOUNT: rWorkbookSett.importCalcCount( rStrm ); break;
780 case BIFF_ID_CALCMODE: rWorkbookSett.importCalcMode( rStrm ); break;
781 case BIFF_ID_DEFCOLWIDTH: importDefColWidth( rStrm ); break;
782 case BIFF_ID_DELTA: rWorkbookSett.importDelta( rStrm ); break;
783 case BIFF2_ID_DIMENSION: importDimension( rStrm ); break;
784 case BIFF3_ID_DIMENSION: importDimension( rStrm ); break;
785 case BIFF_ID_FOOTER: rPageSett.importFooter( rStrm ); break;
786 case BIFF_ID_HEADER: rPageSett.importHeader( rStrm ); break;
787 case BIFF_ID_HORPAGEBREAKS: importPageBreaks( rStrm, true ); break;
788 case BIFF_ID_ITERATION: rWorkbookSett.importIteration( rStrm ); break;
789 case BIFF_ID_LEFTMARGIN: rPageSett.importLeftMargin( rStrm ); break;
790 case BIFF_ID_NOTE: importNote( rStrm ); break;
791 case BIFF_ID_PANE: rSheetViewSett.importPane( rStrm ); break;
792 case BIFF_ID_PASSWORD: rWorksheetSett.importPassword( rStrm ); break;
793 case BIFF_ID_PRINTGRIDLINES: rPageSett.importPrintGridLines( rStrm ); break;
794 case BIFF_ID_PRINTHEADERS: rPageSett.importPrintHeaders( rStrm ); break;
795 case BIFF_ID_PROTECT: rWorksheetSett.importProtect( rStrm ); break;
796 case BIFF_ID_REFMODE: rWorkbookSett.importRefMode( rStrm ); break;
797 case BIFF_ID_RIGHTMARGIN: rPageSett.importRightMargin( rStrm ); break;
798 case BIFF_ID_SELECTION: rSheetViewSett.importSelection( rStrm ); break;
799 case BIFF_ID_TOPMARGIN: rPageSett.importTopMargin( rStrm ); break;
800 case BIFF_ID_VERPAGEBREAKS: importPageBreaks( rStrm, false ); break;
801
802 // BIFF specific records
803 default: switch( getBiff() )
804 {
805 case BIFF2: switch( nRecId )
806 {
807 case BIFF_ID_COLUMNDEFAULT: importColumnDefault( rStrm ); break;
808 case BIFF_ID_COLWIDTH: importColWidth( rStrm ); break;
809 case BIFF2_ID_DEFROWHEIGHT: importDefRowHeight( rStrm ); break;
810 case BIFF2_ID_WINDOW2: rSheetViewSett.importWindow2( rStrm ); break;
811 }
812 break;
813
814 case BIFF3: switch( nRecId )
815 {
816 case BIFF_ID_COLINFO: importColInfo( rStrm ); break;
817 case BIFF_ID_DEFCOLWIDTH: importDefColWidth( rStrm ); break;
818 case BIFF3_ID_DEFROWHEIGHT: importDefRowHeight( rStrm ); break;
819 case BIFF_ID_HCENTER: rPageSett.importHorCenter( rStrm ); break;
820 case BIFF_ID_OBJ: rDrawing.importObj( rStrm ); break;
821 case BIFF_ID_OBJECTPROTECT: rWorksheetSett.importObjectProtect( rStrm ); break;
822 case BIFF_ID_SAVERECALC: rWorkbookSett.importSaveRecalc( rStrm ); break;
823 case BIFF_ID_SHEETPR: rWorksheetSett.importSheetPr( rStrm ); break;
824 case BIFF_ID_UNCALCED: rWorkbookSett.importUncalced( rStrm ); break;
825 case BIFF_ID_VCENTER: rPageSett.importVerCenter( rStrm ); break;
826 case BIFF3_ID_WINDOW2: rSheetViewSett.importWindow2( rStrm ); break;
827 }
828 break;
829
830 case BIFF4: switch( nRecId )
831 {
832 case BIFF_ID_COLINFO: importColInfo( rStrm ); break;
833 case BIFF3_ID_DEFROWHEIGHT: importDefRowHeight( rStrm ); break;
834 case BIFF_ID_HCENTER: rPageSett.importHorCenter( rStrm ); break;
835 case BIFF_ID_OBJ: rDrawing.importObj( rStrm ); break;
836 case BIFF_ID_OBJECTPROTECT: rWorksheetSett.importObjectProtect( rStrm ); break;
837 case BIFF_ID_PAGESETUP: rPageSett.importPageSetup( rStrm ); break;
838 case BIFF_ID_SAVERECALC: rWorkbookSett.importSaveRecalc( rStrm ); break;
839 case BIFF_ID_SHEETPR: rWorksheetSett.importSheetPr( rStrm ); break;
840 case BIFF_ID_STANDARDWIDTH: importStandardWidth( rStrm ); break;
841 case BIFF_ID_UNCALCED: rWorkbookSett.importUncalced( rStrm ); break;
842 case BIFF_ID_VCENTER: rPageSett.importVerCenter( rStrm ); break;
843 case BIFF3_ID_WINDOW2: rSheetViewSett.importWindow2( rStrm ); break;
844 }
845 break;
846
847 case BIFF5: switch( nRecId )
848 {
849 case BIFF_ID_AUTOFILTER: importAutoFilter( rStrm ); break;
850 case BIFF_ID_COLINFO: importColInfo( rStrm ); break;
851 case BIFF3_ID_DEFROWHEIGHT: importDefRowHeight( rStrm ); break;
852 case BIFF_ID_HCENTER: rPageSett.importHorCenter( rStrm ); break;
853 case BIFF_ID_MERGEDCELLS: importMergedCells( rStrm ); break; // #i62300# also in BIFF5
854 case BIFF_ID_OBJ: rDrawing.importObj( rStrm ); break;
855 case BIFF_ID_OBJECTPROTECT: rWorksheetSett.importObjectProtect( rStrm ); break;
856 case BIFF_ID_PAGESETUP: rPageSett.importPageSetup( rStrm ); break;
857 case BIFF_ID_PTDEFINITION: importPTDefinition( rStrm ); break;
858 case BIFF_ID_SAVERECALC: rWorkbookSett.importSaveRecalc( rStrm ); break;
859 case BIFF_ID_SCENPROTECT: rWorksheetSett.importScenProtect( rStrm ); break;
860 case BIFF_ID_SCL: rSheetViewSett.importScl( rStrm ); break;
861 case BIFF_ID_SHEETPR: rWorksheetSett.importSheetPr( rStrm ); break;
862 case BIFF_ID_STANDARDWIDTH: importStandardWidth( rStrm ); break;
863 case BIFF_ID_UNCALCED: rWorkbookSett.importUncalced( rStrm ); break;
864 case BIFF_ID_VCENTER: rPageSett.importVerCenter( rStrm ); break;
865 case BIFF3_ID_WINDOW2: rSheetViewSett.importWindow2( rStrm ); break;
866 }
867 break;
868
869 case BIFF8: switch( nRecId )
870 {
871 case BIFF_ID_AUTOFILTER: importAutoFilter( rStrm ); break;
872 case BIFF_ID_CFHEADER: rCondFormats.importCfHeader( rStrm ); break;
873 case BIFF_ID_CODENAME: rWorksheetSett.importCodeName( rStrm ); break;
874 case BIFF_ID_COLINFO: importColInfo( rStrm ); break;
875 case BIFF_ID_DATAVALIDATION: importDataValidation( rStrm ); break;
876 case BIFF_ID_DATAVALIDATIONS: importDataValidations( rStrm ); break;
877 case BIFF3_ID_DEFROWHEIGHT: importDefRowHeight( rStrm ); break;
878 case BIFF_ID_HCENTER: rPageSett.importHorCenter( rStrm ); break;
879 case BIFF_ID_HYPERLINK: importHyperlink( rStrm ); break;
880 case BIFF_ID_LABELRANGES: importLabelRanges( rStrm ); break;
881 case BIFF_ID_MERGEDCELLS: importMergedCells( rStrm ); break;
882 case BIFF_ID_OBJ: rDrawing.importObj( rStrm ); break;
883 case BIFF_ID_OBJECTPROTECT: rWorksheetSett.importObjectProtect( rStrm ); break;
884 case BIFF_ID_PAGESETUP: rPageSett.importPageSetup( rStrm ); break;
885 case BIFF_ID_PHONETICPR: rWorksheetSett.importPhoneticPr( rStrm ); break;
886 case BIFF_ID_PICTURE: rPageSett.importPicture( rStrm ); break;
887 case BIFF_ID_PTDEFINITION: importPTDefinition( rStrm ); break;
888 case BIFF_ID_QUERYTABLE: importQueryTable( rStrm ); break;
889 case BIFF_ID_SAVERECALC: rWorkbookSett.importSaveRecalc( rStrm ); break;
890 case BIFF_ID_SCENARIOS: importScenarios( rStrm ); break;
891 case BIFF_ID_SCENPROTECT: rWorksheetSett.importScenProtect( rStrm ); break;
892 case BIFF_ID_SCL: rSheetViewSett.importScl( rStrm ); break;
893 case BIFF_ID_SHEETEXT: rWorksheetSett.importSheetExt( rStrm ); break;
894 case BIFF_ID_SHEETPR: rWorksheetSett.importSheetPr( rStrm ); break;
895 case BIFF_ID_SHAREDFEATHEAD: importSharedFeatHead( rStrm ); break;
896 case BIFF_ID_STANDARDWIDTH: importStandardWidth( rStrm ); break;
897 case BIFF_ID_UNCALCED: rWorkbookSett.importUncalced( rStrm ); break;
898 case BIFF_ID_VCENTER: rPageSett.importVerCenter( rStrm ); break;
899 case BIFF3_ID_WINDOW2: rSheetViewSett.importWindow2( rStrm ); break;
900 }
901 break;
902
903 case BIFF_UNKNOWN: break;
904 }
905 }
906
907 // record not processed, try record context objects
908 if( rStrm.tellBase() == nStrmPos )
909 {
910 // first, try cell table records
911 aSheetData.importRecord( rStrm );
912 // handle another open record context
913 if( mxContext.get() )
914 {
915 // if it was a cell table record, forget the other record context
916 if( rStrm.tellBase() == nStrmPos )
917 mxContext->importRecord( rStrm );
918 else
919 mxContext.reset();
920 }
921 }
922 }
923 }
924
925 // final processing in base class WorksheetHelper
926 finalizeWorksheetImport();
927 return rStrm.getRecId() == BIFF_ID_EOF;
928 }
929
930 // private --------------------------------------------------------------------
931
importAutoFilter(BiffInputStream & rStrm)932 void BiffWorksheetFragment::importAutoFilter( BiffInputStream& rStrm )
933 {
934 mxContext.reset( new BiffAutoFilterContext( *this, getAutoFilters().createAutoFilter() ) );
935 mxContext->importRecord( rStrm );
936 }
937
importColInfo(BiffInputStream & rStrm)938 void BiffWorksheetFragment::importColInfo( BiffInputStream& rStrm )
939 {
940 sal_uInt16 nFirstCol, nLastCol, nWidth, nXfId, nFlags;
941 rStrm >> nFirstCol >> nLastCol >> nWidth >> nXfId >> nFlags;
942
943 ColumnModel aModel;
944 // column indexes are 0-based in BIFF, but ColumnModel expects 1-based
945 aModel.maRange.mnFirst = static_cast< sal_Int32 >( nFirstCol ) + 1;
946 aModel.maRange.mnLast = static_cast< sal_Int32 >( nLastCol ) + 1;
947 // width is stored as 1/256th of a character in BIFF, convert to entire character
948 aModel.mfWidth = static_cast< double >( nWidth ) / 256.0;
949 aModel.mnXfId = nXfId;
950 aModel.mnLevel = extractValue< sal_Int32 >( nFlags, 8, 3 );
951 aModel.mbShowPhonetic = getFlag( nFlags, BIFF_COLINFO_SHOWPHONETIC );
952 aModel.mbHidden = getFlag( nFlags, BIFF_COLINFO_HIDDEN );
953 aModel.mbCollapsed = getFlag( nFlags, BIFF_COLINFO_COLLAPSED );
954 // set column properties in the current sheet
955 setColumnModel( aModel );
956 }
957
importColumnDefault(BiffInputStream & rStrm)958 void BiffWorksheetFragment::importColumnDefault( BiffInputStream& rStrm )
959 {
960 sal_uInt16 nFirstCol, nLastCol, nXfId;
961 rStrm >> nFirstCol >> nLastCol >> nXfId;
962 setDefaultColumnFormat( nFirstCol, nLastCol, nXfId );
963 }
964
importColWidth(BiffInputStream & rStrm)965 void BiffWorksheetFragment::importColWidth( BiffInputStream& rStrm )
966 {
967 sal_uInt8 nFirstCol, nLastCol;
968 sal_uInt16 nWidth;
969 rStrm >> nFirstCol >> nLastCol >> nWidth;
970
971 ColumnModel aModel;
972 // column indexes are 0-based in BIFF, but ColumnModel expects 1-based
973 aModel.maRange.mnFirst = static_cast< sal_Int32 >( nFirstCol ) + 1;
974 aModel.maRange.mnLast = static_cast< sal_Int32 >( nLastCol ) + 1;
975 // width is stored as 1/256th of a character in BIFF, convert to entire character
976 aModel.mfWidth = static_cast< double >( nWidth ) / 256.0;
977 // set column properties in the current sheet
978 setColumnModel( aModel );
979 }
980
importDefColWidth(BiffInputStream & rStrm)981 void BiffWorksheetFragment::importDefColWidth( BiffInputStream& rStrm )
982 {
983 /* Stored as entire number of characters without padding pixels, which
984 will be added in setBaseColumnWidth(). Call has no effect, if a
985 width has already been set from the STANDARDWIDTH record. */
986 setBaseColumnWidth( rStrm.readuInt16() );
987 }
988
importDefRowHeight(BiffInputStream & rStrm)989 void BiffWorksheetFragment::importDefRowHeight( BiffInputStream& rStrm )
990 {
991 sal_uInt16 nFlags = BIFF_DEFROW_CUSTOMHEIGHT, nHeight;
992 if( getBiff() != BIFF2 )
993 rStrm >> nFlags;
994 rStrm >> nHeight;
995 if( getBiff() == BIFF2 )
996 nHeight &= BIFF2_DEFROW_MASK;
997 // row height is in twips in BIFF, convert to points
998 setDefaultRowSettings(
999 nHeight / 20.0,
1000 getFlag( nFlags, BIFF_DEFROW_CUSTOMHEIGHT ),
1001 getFlag( nFlags, BIFF_DEFROW_HIDDEN ),
1002 getFlag( nFlags, BIFF_DEFROW_THICKTOP ),
1003 getFlag( nFlags, BIFF_DEFROW_THICKBOTTOM ) );
1004 }
1005
importDataValidations(BiffInputStream & rStrm)1006 void BiffWorksheetFragment::importDataValidations( BiffInputStream& rStrm )
1007 {
1008 sal_Int32 nObjId;
1009 rStrm.skip( 10 );
1010 rStrm >> nObjId;
1011 //! TODO: invalidate object id in drawing object manager
1012 }
1013
1014 namespace {
1015
lclReadDataValMessage(BiffInputStream & rStrm)1016 OUString lclReadDataValMessage( BiffInputStream& rStrm )
1017 {
1018 // empty strings are single NUL characters (string length is 1)
1019 OUString aMessage = rStrm.readUniString( true );
1020 if( (aMessage.getLength() == 1) && (aMessage[ 0 ] == 0) )
1021 aMessage = OUString();
1022 return aMessage;
1023 }
1024
lclReadDataValFormula(BiffInputStream & rStrm,FormulaParser & rParser)1025 ApiTokenSequence lclReadDataValFormula( BiffInputStream& rStrm, FormulaParser& rParser )
1026 {
1027 sal_uInt16 nFmlaSize = rStrm.readuInt16();
1028 rStrm.skip( 2 );
1029 return rParser.importFormula( CellAddress(), FORMULATYPE_VALIDATION, rStrm, &nFmlaSize );
1030 }
1031
1032 } // namespace
1033
importDataValidation(BiffInputStream & rStrm)1034 void BiffWorksheetFragment::importDataValidation( BiffInputStream& rStrm )
1035 {
1036 ValidationModel aModel;
1037
1038 // flags
1039 sal_uInt32 nFlags;
1040 rStrm >> nFlags;
1041 aModel.setBiffType( extractValue< sal_uInt8 >( nFlags, 0, 4 ) );
1042 aModel.setBiffOperator( extractValue< sal_uInt8 >( nFlags, 20, 4 ) );
1043 aModel.setBiffErrorStyle( extractValue< sal_uInt8 >( nFlags, 4, 3 ) );
1044 aModel.mbAllowBlank = getFlag( nFlags, BIFF_DATAVAL_ALLOWBLANK );
1045 aModel.mbNoDropDown = getFlag( nFlags, BIFF_DATAVAL_NODROPDOWN );
1046 aModel.mbShowInputMsg = getFlag( nFlags, BIFF_DATAVAL_SHOWINPUT );
1047 aModel.mbShowErrorMsg = getFlag( nFlags, BIFF_DATAVAL_SHOWERROR );
1048
1049 // message strings
1050 aModel.maInputTitle = lclReadDataValMessage( rStrm );
1051 aModel.maErrorTitle = lclReadDataValMessage( rStrm );
1052 aModel.maInputMessage = lclReadDataValMessage( rStrm );
1053 aModel.maErrorMessage = lclReadDataValMessage( rStrm );
1054
1055 // condition formula(s)
1056 FormulaParser& rParser = getFormulaParser();
1057 aModel.maTokens1 = lclReadDataValFormula( rStrm, rParser );
1058 aModel.maTokens2 = lclReadDataValFormula( rStrm, rParser );
1059 // process string list of a list validation (convert to list of string tokens)
1060 if( (aModel.mnType == XML_list) && getFlag( nFlags, BIFF_DATAVAL_STRINGLIST ) )
1061 rParser.convertStringToStringList( aModel.maTokens1, '\0', true );
1062
1063 // cell range list
1064 BinRangeList aRanges;
1065 rStrm >> aRanges;
1066 getAddressConverter().convertToCellRangeList( aModel.maRanges, aRanges, getSheetIndex(), true );
1067
1068 // set validation data
1069 setValidation( aModel );
1070 }
1071
importDimension(BiffInputStream & rStrm)1072 void BiffWorksheetFragment::importDimension( BiffInputStream& rStrm )
1073 {
1074 // 32-bit row indexes in BIFF8
1075 bool bInt32Rows = (rStrm.getRecId() == BIFF3_ID_DIMENSION) && (getBiff() == BIFF8);
1076 BinRange aBinRange;
1077 aBinRange.read( rStrm, true, bInt32Rows );
1078 /* BIFF stores the used area with end column and end row increased by 1
1079 (first unused column and row). */
1080 if( (aBinRange.maFirst.mnCol < aBinRange.maLast.mnCol) && (aBinRange.maFirst.mnRow < aBinRange.maLast.mnRow) )
1081 {
1082 // reduce range to used area
1083 --aBinRange.maLast.mnCol;
1084 --aBinRange.maLast.mnRow;
1085 CellRangeAddress aRange;
1086 getAddressConverter().convertToCellRangeUnchecked( aRange, aBinRange, getSheetIndex() );
1087 extendUsedArea( aRange );
1088 }
1089 }
1090
importHyperlink(BiffInputStream & rStrm)1091 void BiffWorksheetFragment::importHyperlink( BiffInputStream& rStrm )
1092 {
1093 HyperlinkModel aModel;
1094
1095 // read cell range for the hyperlink
1096 BinRange aBiffRange;
1097 rStrm >> aBiffRange;
1098 // #i80006# Excel silently ignores invalid hi-byte of column index (TODO: everywhere?)
1099 aBiffRange.maFirst.mnCol &= 0xFF;
1100 aBiffRange.maLast.mnCol &= 0xFF;
1101 if( !getAddressConverter().convertToCellRange( aModel.maRange, aBiffRange, getSheetIndex(), true, true ) )
1102 return;
1103
1104 // try to read the StdHlink data
1105 if( !::oox::ole::OleHelper::importStdHlink( aModel, rStrm, true ) )
1106 return;
1107
1108 // try to read the optional following SCREENTIP record
1109 if( (rStrm.getNextRecId() == BIFF_ID_SCREENTIP) && rStrm.startNextRecord() )
1110 {
1111 rStrm.skip( 2 ); // repeated record id
1112 // the cell range, again
1113 rStrm >> aBiffRange;
1114 CellRangeAddress aRange;
1115 if( getAddressConverter().convertToCellRange( aRange, aBiffRange, getSheetIndex(), true, true ) &&
1116 (aRange.StartColumn == aModel.maRange.StartColumn) &&
1117 (aRange.StartRow == aModel.maRange.StartRow) &&
1118 (aRange.EndColumn == aModel.maRange.EndColumn) &&
1119 (aRange.EndRow == aModel.maRange.EndRow) )
1120 {
1121 /* This time, we have no string length, no flag field, and a
1122 null-terminated 16-bit character array. */
1123 aModel.maTooltip = rStrm.readNulUnicodeArray();
1124 }
1125 }
1126
1127 // store the hyperlink settings
1128 setHyperlink( aModel );
1129 }
1130
importLabelRanges(BiffInputStream & rStrm)1131 void BiffWorksheetFragment::importLabelRanges( BiffInputStream& rStrm )
1132 {
1133 BinRangeList aBiffRowRanges, aBiffColRanges;
1134 rStrm >> aBiffRowRanges >> aBiffColRanges;
1135 ApiCellRangeList aColRanges, aRowRanges;
1136 getAddressConverter().convertToCellRangeList( aColRanges, aBiffColRanges, getSheetIndex(), true );
1137 getAddressConverter().convertToCellRangeList( aRowRanges, aBiffRowRanges, getSheetIndex(), true );
1138 setLabelRanges( aColRanges, aRowRanges );
1139 }
1140
importMergedCells(BiffInputStream & rStrm)1141 void BiffWorksheetFragment::importMergedCells( BiffInputStream& rStrm )
1142 {
1143 BinRangeList aBiffRanges;
1144 rStrm >> aBiffRanges;
1145 ApiCellRangeList aRanges;
1146 getAddressConverter().convertToCellRangeList( aRanges, aBiffRanges, getSheetIndex(), true );
1147 for( ApiCellRangeList::const_iterator aIt = aRanges.begin(), aEnd = aRanges.end(); aIt != aEnd; ++aIt )
1148 getSheetData().setMergedRange( *aIt );
1149 }
1150
importNote(BiffInputStream & rStrm)1151 void BiffWorksheetFragment::importNote( BiffInputStream& rStrm )
1152 {
1153 getComments().createComment()->importNote( rStrm );
1154 }
1155
importPageBreaks(BiffInputStream & rStrm,bool bRowBreak)1156 void BiffWorksheetFragment::importPageBreaks( BiffInputStream& rStrm, bool bRowBreak )
1157 {
1158 PageBreakModel aModel;
1159 aModel.mbManual = true; // only manual breaks stored in BIFF
1160 bool bBiff8 = getBiff() == BIFF8; // skip start/end columns or rows in BIFF8
1161
1162 sal_uInt16 nCount;
1163 rStrm >> nCount;
1164 for( sal_uInt16 nIndex = 0; !rStrm.isEof() && (nIndex < nCount); ++nIndex )
1165 {
1166 aModel.mnColRow = rStrm.readuInt16();
1167 setPageBreak( aModel, bRowBreak );
1168 if( bBiff8 )
1169 rStrm.skip( 4 );
1170 }
1171 }
1172
importPTDefinition(BiffInputStream & rStrm)1173 void BiffWorksheetFragment::importPTDefinition( BiffInputStream& rStrm )
1174 {
1175 mxContext.reset( new BiffPivotTableContext( *this ) );
1176 mxContext->importRecord( rStrm );
1177 }
1178
importQueryTable(BiffInputStream & rStrm)1179 void BiffWorksheetFragment::importQueryTable( BiffInputStream& rStrm )
1180 {
1181 mxContext.reset( new BiffQueryTableContext( *this ) );
1182 mxContext->importRecord( rStrm );
1183 }
1184
importScenarios(BiffInputStream & rStrm)1185 void BiffWorksheetFragment::importScenarios( BiffInputStream& rStrm )
1186 {
1187 getScenarios().createSheetScenarios( getSheetIndex() ).importScenarios( rStrm );
1188 }
1189
importSharedFeatHead(BiffInputStream & rStrm)1190 void BiffWorksheetFragment::importSharedFeatHead( BiffInputStream& rStrm )
1191 {
1192 rStrm.skip( 12 );
1193 sal_uInt16 nType = rStrm.readuInt16();
1194 rStrm.skip( 5 );
1195 switch( nType )
1196 {
1197 case BIFF_SHRFEATHEAD_SHEETPROT:
1198 if( rStrm.getRemaining() >= 4 )
1199 getWorksheetSettings().importSheetProtection( rStrm );
1200 break;
1201 }
1202 }
1203
importStandardWidth(BiffInputStream & rStrm)1204 void BiffWorksheetFragment::importStandardWidth( BiffInputStream& rStrm )
1205 {
1206 sal_uInt16 nWidth;
1207 rStrm >> nWidth;
1208 // width is stored as 1/256th of a character in BIFF, convert to entire character
1209 double fWidth = static_cast< double >( nWidth ) / 256.0;
1210 // set as default width, will override the width from DEFCOLWIDTH record
1211 setDefaultColumnWidth( fWidth );
1212 }
1213
1214 // ============================================================================
1215
1216 } // namespace xls
1217 } // namespace oox
1218