merge the formfield patch from ooo-build
[ooovba.git] / oox / source / xls / sheetdatacontext.cxx
blobcd741f9649ffcf63cb82012705f136971e50b147
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: sheetdatacontext.cxx,v $
10 * $Revision: 1.5.4.3 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 #include "oox/xls/sheetdatacontext.hxx"
32 #include <com/sun/star/table/CellContentType.hpp>
33 #include <com/sun/star/table/XCell.hpp>
34 #include <com/sun/star/table/XCellRange.hpp>
35 #include <com/sun/star/sheet/XFormulaTokens.hpp>
36 #include <com/sun/star/sheet/XArrayFormulaTokens.hpp>
37 #include <com/sun/star/text/XText.hpp>
38 #include "oox/helper/attributelist.hxx"
39 #include "oox/helper/propertyset.hxx"
40 #include "oox/helper/recordinputstream.hxx"
41 #include "oox/xls/addressconverter.hxx"
42 #include "oox/xls/biffinputstream.hxx"
43 #include "oox/xls/formulaparser.hxx"
44 #include "oox/xls/richstringcontext.hxx"
45 #include "oox/xls/sharedformulabuffer.hxx"
46 #include "oox/xls/unitconverter.hxx"
48 using ::rtl::OUString;
49 using ::com::sun::star::uno::Reference;
50 using ::com::sun::star::uno::Exception;
51 using ::com::sun::star::uno::UNO_QUERY;
52 using ::com::sun::star::uno::UNO_QUERY_THROW;
53 using ::com::sun::star::table::CellAddress;
54 using ::com::sun::star::table::CellRangeAddress;
55 using ::com::sun::star::table::CellContentType_EMPTY;
56 using ::com::sun::star::table::XCell;
57 using ::com::sun::star::table::XCellRange;
58 using ::com::sun::star::sheet::XFormulaTokens;
59 using ::com::sun::star::sheet::XArrayFormulaTokens;
60 using ::com::sun::star::text::XText;
61 using ::oox::core::ContextHandlerRef;
63 namespace oox {
64 namespace xls {
66 // ============================================================================
68 namespace {
70 // record constants -----------------------------------------------------------
72 const sal_uInt32 OOBIN_CELL_SHOWPHONETIC = 0x01000000;
74 const sal_uInt8 OOBIN_DATATABLE_ROW = 0x01;
75 const sal_uInt8 OOBIN_DATATABLE_2D = 0x02;
76 const sal_uInt8 OOBIN_DATATABLE_REF1DEL = 0x04;
77 const sal_uInt8 OOBIN_DATATABLE_REF2DEL = 0x08;
79 const sal_uInt16 OOBIN_ROW_THICKTOP = 0x0001;
80 const sal_uInt16 OOBIN_ROW_THICKBOTTOM = 0x0002;
81 const sal_uInt16 OOBIN_ROW_COLLAPSED = 0x0800;
82 const sal_uInt16 OOBIN_ROW_HIDDEN = 0x1000;
83 const sal_uInt16 OOBIN_ROW_CUSTOMHEIGHT = 0x2000;
84 const sal_uInt16 OOBIN_ROW_CUSTOMFORMAT = 0x4000;
85 const sal_uInt8 OOBIN_ROW_SHOWPHONETIC = 0x01;
87 const sal_uInt8 BIFF_BOOLERR_BOOL = 0;
88 const sal_uInt8 BIFF_BOOLERR_ERROR = 1;
90 const sal_uInt16 BIFF_DATATABLE_ROW = 0x0004;
91 const sal_uInt16 BIFF_DATATABLE_2D = 0x0008;
92 const sal_uInt16 BIFF_DATATABLE_REF1DEL = 0x0010;
93 const sal_uInt16 BIFF_DATATABLE_REF2DEL = 0x0020;
95 const sal_uInt8 BIFF_FORMULA_RES_STRING = 0; /// Result is a string.
96 const sal_uInt8 BIFF_FORMULA_RES_BOOL = 1; /// Result is Boolean value.
97 const sal_uInt8 BIFF_FORMULA_RES_ERROR = 2; /// Result is error code.
98 const sal_uInt8 BIFF_FORMULA_RES_EMPTY = 3; /// Result is empty cell (BIFF8 only).
99 const sal_uInt16 BIFF_FORMULA_SHARED = 0x0008; /// Shared formula cell.
101 const sal_uInt8 BIFF2_ROW_CUSTOMFORMAT = 0x01;
102 const sal_uInt16 BIFF_ROW_DEFAULTHEIGHT = 0x8000;
103 const sal_uInt16 BIFF_ROW_HEIGHTMASK = 0x7FFF;
104 const sal_uInt32 BIFF_ROW_COLLAPSED = 0x00000010;
105 const sal_uInt32 BIFF_ROW_HIDDEN = 0x00000020;
106 const sal_uInt32 BIFF_ROW_CUSTOMHEIGHT = 0x00000040;
107 const sal_uInt32 BIFF_ROW_CUSTOMFORMAT = 0x00000080;
108 const sal_uInt32 BIFF_ROW_THICKTOP = 0x10000000;
109 const sal_uInt32 BIFF_ROW_THICKBOTTOM = 0x20000000;
110 const sal_uInt32 BIFF_ROW_SHOWPHONETIC = 0x40000000;
112 const sal_Int32 BIFF2_XF_EXTENDED_IDS = 63;
113 const sal_uInt8 BIFF2_XF_MASK = 0x3F;
115 // ----------------------------------------------------------------------------
117 /** Formula context for cell formulas. */
118 class CellFormulaContext : public SimpleFormulaContext
120 public:
121 explicit CellFormulaContext(
122 const Reference< XFormulaTokens >& rxTokens,
123 const CellAddress& rCellPos );
126 CellFormulaContext::CellFormulaContext( const Reference< XFormulaTokens >& rxTokens, const CellAddress& rCellPos ) :
127 SimpleFormulaContext( rxTokens, false, false )
129 setBaseAddress( rCellPos );
132 // ----------------------------------------------------------------------------
134 /** Uses the XArrayFormulaTokens interface to set a token sequence. */
135 class ArrayFormulaContext : public FormulaContext
137 public:
138 explicit ArrayFormulaContext(
139 const Reference< XArrayFormulaTokens >& rxTokens,
140 const CellRangeAddress& rArrayRange );
142 virtual void setTokens( const ApiTokenSequence& rTokens );
144 private:
145 Reference< XArrayFormulaTokens > mxTokens;
148 ArrayFormulaContext::ArrayFormulaContext(
149 const Reference< XArrayFormulaTokens >& rxTokens, const CellRangeAddress& rArrayRange ) :
150 FormulaContext( false, false ),
151 mxTokens( rxTokens )
153 OSL_ENSURE( mxTokens.is(), "ArrayFormulaContext::ArrayFormulaContext - missing XArrayFormulaTokens interface" );
154 setBaseAddress( CellAddress( rArrayRange.Sheet, rArrayRange.StartColumn, rArrayRange.StartRow ) );
157 void ArrayFormulaContext::setTokens( const ApiTokenSequence& rTokens )
159 mxTokens->setArrayTokens( rTokens );
162 // ----------------------------------------------------------------------------
164 } // namespace
166 // ============================================================================
168 OoxSheetDataContext::OoxSheetDataContext( OoxWorksheetFragmentBase& rFragment ) :
169 OoxWorksheetContextBase( rFragment )
173 // oox.core.ContextHandler2Helper interface -----------------------------------
175 ContextHandlerRef OoxSheetDataContext::onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs )
177 OOX_LOADSAVE_TIMER( ONCREATESHEETCONTEXT );
178 switch( getCurrentElement() )
180 case XLS_TOKEN( sheetData ):
181 if( nElement == XLS_TOKEN( row ) ) { importRow( rAttribs ); return this; }
182 break;
184 case XLS_TOKEN( row ):
185 if( nElement == XLS_TOKEN( c ) ) { importCell( rAttribs ); return this; }
186 break;
188 case XLS_TOKEN( c ):
189 if( maCurrCell.mxCell.is() ) switch( nElement )
191 case XLS_TOKEN( is ):
192 mxInlineStr.reset( new RichString( *this ) );
193 return new OoxRichStringContext( *this, mxInlineStr );
194 case XLS_TOKEN( v ):
195 return this;
196 case XLS_TOKEN( f ):
197 importFormula( rAttribs );
198 return this;
200 break;
202 return 0;
205 void OoxSheetDataContext::onEndElement( const OUString& rChars )
207 OOX_LOADSAVE_TIMER( ONENDSHEETELEMENT );
208 switch( getCurrentElement() )
210 case XLS_TOKEN( v ):
211 maCurrCell.maValueStr = rChars;
212 maCurrCell.mbHasValueStr = true;
213 break;
215 case XLS_TOKEN( f ):
216 if( maCurrCell.mxCell.is() ) try
218 switch( maCurrCell.mnFormulaType )
220 case XML_normal:
221 if( rChars.getLength() > 0 )
223 Reference< XFormulaTokens > xTokens( maCurrCell.mxCell, UNO_QUERY_THROW );
224 CellFormulaContext aContext( xTokens, maCurrCell.maAddress );
225 getFormulaParser().importFormula( aContext, rChars );
227 break;
229 case XML_array:
230 if( (maCurrCell.maFormulaRef.getLength() > 0) && (rChars.getLength() > 0) )
232 CellRangeAddress aArrayRange;
233 Reference< XArrayFormulaTokens > xTokens( getCellRange( maCurrCell.maFormulaRef, &aArrayRange ), UNO_QUERY_THROW );
234 ArrayFormulaContext aContext( xTokens, aArrayRange );
235 getFormulaParser().importFormula( aContext, rChars );
237 break;
239 case XML_shared:
240 if( maCurrCell.mnSharedId >= 0 )
242 if( rChars.getLength() > 0 )
243 getSharedFormulas().importSharedFmla( rChars, maCurrCell.maFormulaRef, maCurrCell.mnSharedId, maCurrCell.maAddress );
244 Reference< XFormulaTokens > xTokens( maCurrCell.mxCell, UNO_QUERY_THROW );
245 ExtCellFormulaContext aContext( *this, xTokens, maCurrCell.maAddress );
246 getSharedFormulas().setSharedFormulaCell( aContext, maCurrCell.mnSharedId );
248 break;
250 case XML_dataTable:
251 if( maCurrCell.maFormulaRef.getLength() > 0 )
253 CellRangeAddress aTableRange;
254 if( getAddressConverter().convertToCellRange( aTableRange, maCurrCell.maFormulaRef, getSheetIndex(), true, true ) )
255 setTableOperation( aTableRange, maTableData );
257 break;
259 default:
260 OSL_ENSURE( false, "OoxSheetDataContext::onEndElement - unknown formula type" );
263 catch( Exception& )
266 break;
268 case XLS_TOKEN( c ):
269 if( maCurrCell.mxCell.is() )
271 if( maCurrCell.mxCell->getType() == CellContentType_EMPTY )
273 if( maCurrCell.mbHasValueStr )
275 // implemented in WorksheetHelper class
276 setCell( maCurrCell );
278 else if( (maCurrCell.mnCellType == XML_inlineStr) && mxInlineStr.get() )
280 // convert font settings
281 mxInlineStr->finalizeImport();
282 // write string to cell
283 Reference< XText > xText( maCurrCell.mxCell, UNO_QUERY );
284 if( xText.is() )
285 mxInlineStr->convert( xText, maCurrCell.mnXfId );
287 else
289 // empty cell, update cell type
290 maCurrCell.mnCellType = XML_TOKEN_INVALID;
294 // store the cell formatting data
295 setCellFormat( maCurrCell );
297 break;
301 ContextHandlerRef OoxSheetDataContext::onCreateRecordContext( sal_Int32 nRecId, RecordInputStream& rStrm )
303 switch( getCurrentElement() )
305 case OOBIN_ID_SHEETDATA:
306 switch( nRecId )
308 case OOBIN_ID_ROW: importRow( rStrm ); return this;
310 break;
312 case OOBIN_ID_ROW:
313 switch( nRecId )
315 case OOBIN_ID_ARRAY: importArray( rStrm ); break;
316 case OOBIN_ID_CELL_BOOL: importCellBool( rStrm, CELLTYPE_VALUE ); break;
317 case OOBIN_ID_CELL_BLANK: importCellBlank( rStrm, CELLTYPE_VALUE ); break;
318 case OOBIN_ID_CELL_DOUBLE: importCellDouble( rStrm, CELLTYPE_VALUE ); break;
319 case OOBIN_ID_CELL_ERROR: importCellError( rStrm, CELLTYPE_VALUE ); break;
320 case OOBIN_ID_CELL_RK: importCellRk( rStrm, CELLTYPE_VALUE ); break;
321 case OOBIN_ID_CELL_RSTRING: importCellRString( rStrm, CELLTYPE_VALUE ); break;
322 case OOBIN_ID_CELL_SI: importCellSi( rStrm, CELLTYPE_VALUE ); break;
323 case OOBIN_ID_CELL_STRING: importCellString( rStrm, CELLTYPE_VALUE ); break;
324 case OOBIN_ID_DATATABLE: importDataTable( rStrm ); break;
325 case OOBIN_ID_FORMULA_BOOL: importCellBool( rStrm, CELLTYPE_FORMULA ); break;
326 case OOBIN_ID_FORMULA_DOUBLE: importCellDouble( rStrm, CELLTYPE_FORMULA ); break;
327 case OOBIN_ID_FORMULA_ERROR: importCellError( rStrm, CELLTYPE_FORMULA ); break;
328 case OOBIN_ID_FORMULA_STRING: importCellString( rStrm, CELLTYPE_FORMULA ); break;
329 case OOBIN_ID_MULTCELL_BOOL: importCellBool( rStrm, CELLTYPE_MULTI ); break;
330 case OOBIN_ID_MULTCELL_BLANK: importCellBlank( rStrm, CELLTYPE_MULTI ); break;
331 case OOBIN_ID_MULTCELL_DOUBLE: importCellDouble( rStrm, CELLTYPE_MULTI ); break;
332 case OOBIN_ID_MULTCELL_ERROR: importCellError( rStrm, CELLTYPE_MULTI ); break;
333 case OOBIN_ID_MULTCELL_RK: importCellRk( rStrm, CELLTYPE_MULTI ); break;
334 case OOBIN_ID_MULTCELL_RSTRING: importCellRString( rStrm, CELLTYPE_MULTI ); break;
335 case OOBIN_ID_MULTCELL_SI: importCellSi( rStrm, CELLTYPE_MULTI ); break;
336 case OOBIN_ID_MULTCELL_STRING: importCellString( rStrm, CELLTYPE_MULTI ); break;
337 case OOBIN_ID_SHAREDFMLA: importSharedFmla( rStrm ); break;
339 break;
341 return 0;
344 // private --------------------------------------------------------------------
346 void OoxSheetDataContext::importRow( const AttributeList& rAttribs )
348 OOX_LOADSAVE_TIMER( IMPORTROW );
349 RowModel aModel;
350 aModel.mnFirstRow = aModel.mnLastRow = rAttribs.getInteger( XML_r, -1 );
351 aModel.mfHeight = rAttribs.getDouble( XML_ht, -1.0 );
352 aModel.mnXfId = rAttribs.getInteger( XML_s, -1 );
353 aModel.mnLevel = rAttribs.getInteger( XML_outlineLevel, 0 );
354 aModel.mbCustomHeight = rAttribs.getBool( XML_customHeight, false );
355 aModel.mbCustomFormat = rAttribs.getBool( XML_customFormat, false );
356 aModel.mbShowPhonetic = rAttribs.getBool( XML_ph, false );
357 aModel.mbHidden = rAttribs.getBool( XML_hidden, false );
358 aModel.mbCollapsed = rAttribs.getBool( XML_collapsed, false );
359 aModel.mbThickTop = rAttribs.getBool( XML_thickTop, false );
360 aModel.mbThickBottom = rAttribs.getBool( XML_thickBot, false );
361 // set row properties in the current sheet
362 setRowModel( aModel );
365 void OoxSheetDataContext::importCell( const AttributeList& rAttribs )
367 OOX_LOADSAVE_TIMER( IMPORTCELL );
368 maCurrCell.reset();
369 maCurrCell.mxCell = getCell( rAttribs.getString( XML_r, OUString() ), &maCurrCell.maAddress );
370 maCurrCell.mnCellType = rAttribs.getToken( XML_t, XML_n );
371 maCurrCell.mnXfId = rAttribs.getInteger( XML_s, -1 );
372 maCurrCell.mbShowPhonetic = rAttribs.getBool( XML_ph, false );
373 mxInlineStr.reset();
376 void OoxSheetDataContext::importFormula( const AttributeList& rAttribs )
378 maCurrCell.maFormulaRef = rAttribs.getString( XML_ref, OUString() );
379 maCurrCell.mnFormulaType = rAttribs.getToken( XML_t, XML_normal );
380 maCurrCell.mnSharedId = rAttribs.getInteger( XML_si, -1 );
381 maTableData.maRef1 = rAttribs.getString( XML_r1, OUString() );
382 maTableData.maRef2 = rAttribs.getString( XML_r2, OUString() );
383 maTableData.mb2dTable = rAttribs.getBool( XML_dt2D, false );
384 maTableData.mbRowTable = rAttribs.getBool( XML_dtr, false );
385 maTableData.mbRef1Deleted = rAttribs.getBool( XML_del1, false );
386 maTableData.mbRef2Deleted = rAttribs.getBool( XML_del2, false );
389 void OoxSheetDataContext::importCellHeader( RecordInputStream& rStrm, CellType eCellType )
391 maCurrCell.reset();
393 switch( eCellType )
395 case CELLTYPE_VALUE:
396 case CELLTYPE_FORMULA: rStrm >> maCurrPos.mnCol; break;
397 case CELLTYPE_MULTI: ++maCurrPos.mnCol; break;
400 sal_uInt32 nXfId;
401 rStrm >> nXfId;
403 maCurrCell.mxCell = getCell( maCurrPos, &maCurrCell.maAddress );
404 maCurrCell.mnXfId = extractValue< sal_Int32 >( nXfId, 0, 24 );
405 maCurrCell.mbShowPhonetic = getFlag( nXfId, OOBIN_CELL_SHOWPHONETIC );
408 void OoxSheetDataContext::importCellBool( RecordInputStream& rStrm, CellType eCellType )
410 importCellHeader( rStrm, eCellType );
411 maCurrCell.mnCellType = XML_b;
412 if( maCurrCell.mxCell.is() && (maCurrCell.mxCell->getType() == CellContentType_EMPTY) )
414 bool bValue = rStrm.readuInt8() != 0;
415 if( eCellType == CELLTYPE_FORMULA )
417 importCellFormula( rStrm );
419 else
421 setBooleanCell( maCurrCell.mxCell, bValue );
422 // #108770# set 'Standard' number format for all Boolean cells
423 maCurrCell.mnNumFmtId = 0;
426 setCellFormat( maCurrCell );
429 void OoxSheetDataContext::importCellBlank( RecordInputStream& rStrm, CellType eCellType )
431 OSL_ENSURE( eCellType != CELLTYPE_FORMULA, "OoxSheetDataContext::importCellBlank - no formula cells supported" );
432 importCellHeader( rStrm, eCellType );
433 setCellFormat( maCurrCell );
436 void OoxSheetDataContext::importCellDouble( RecordInputStream& rStrm, CellType eCellType )
438 importCellHeader( rStrm, eCellType );
439 maCurrCell.mnCellType = XML_n;
440 if( maCurrCell.mxCell.is() && (maCurrCell.mxCell->getType() == CellContentType_EMPTY) )
442 double fValue = rStrm.readDouble();
443 if( eCellType == CELLTYPE_FORMULA )
444 importCellFormula( rStrm );
445 else
446 maCurrCell.mxCell->setValue( fValue );
448 setCellFormat( maCurrCell );
451 void OoxSheetDataContext::importCellError( RecordInputStream& rStrm, CellType eCellType )
453 importCellHeader( rStrm, eCellType );
454 maCurrCell.mnCellType = XML_e;
455 if( maCurrCell.mxCell.is() && (maCurrCell.mxCell->getType() == CellContentType_EMPTY) )
457 sal_uInt8 nErrorCode = rStrm.readuInt8();
458 if( eCellType == CELLTYPE_FORMULA )
459 importCellFormula( rStrm );
460 else
461 setErrorCell( maCurrCell.mxCell, nErrorCode );
463 setCellFormat( maCurrCell );
466 void OoxSheetDataContext::importCellRk( RecordInputStream& rStrm, CellType eCellType )
468 OSL_ENSURE( eCellType != CELLTYPE_FORMULA, "OoxSheetDataContext::importCellRk - no formula cells supported" );
469 importCellHeader( rStrm, eCellType );
470 maCurrCell.mnCellType = XML_n;
471 if( maCurrCell.mxCell.is() && (maCurrCell.mxCell->getType() == CellContentType_EMPTY) )
472 maCurrCell.mxCell->setValue( BiffHelper::calcDoubleFromRk( rStrm.readInt32() ) );
473 setCellFormat( maCurrCell );
476 void OoxSheetDataContext::importCellRString( RecordInputStream& rStrm, CellType eCellType )
478 OSL_ENSURE( eCellType != CELLTYPE_FORMULA, "OoxSheetDataContext::importCellRString - no formula cells supported" );
479 importCellHeader( rStrm, eCellType );
480 maCurrCell.mnCellType = XML_inlineStr;
481 Reference< XText > xText( maCurrCell.mxCell, UNO_QUERY );
482 if( xText.is() && (maCurrCell.mxCell->getType() == CellContentType_EMPTY) )
484 RichString aString( *this );
485 aString.importString( rStrm, true );
486 aString.finalizeImport();
487 aString.convert( xText, maCurrCell.mnXfId );
489 setCellFormat( maCurrCell );
492 void OoxSheetDataContext::importCellSi( RecordInputStream& rStrm, CellType eCellType )
494 OSL_ENSURE( eCellType != CELLTYPE_FORMULA, "OoxSheetDataContext::importCellSi - no formula cells supported" );
495 importCellHeader( rStrm, eCellType );
496 maCurrCell.mnCellType = XML_s;
497 if( maCurrCell.mxCell.is() && (maCurrCell.mxCell->getType() == CellContentType_EMPTY) )
498 setSharedStringCell( maCurrCell.mxCell, rStrm.readInt32(), maCurrCell.mnXfId );
499 setCellFormat( maCurrCell );
502 void OoxSheetDataContext::importCellString( RecordInputStream& rStrm, CellType eCellType )
504 importCellHeader( rStrm, eCellType );
505 maCurrCell.mnCellType = XML_inlineStr;
506 Reference< XText > xText( maCurrCell.mxCell, UNO_QUERY );
507 if( xText.is() && (maCurrCell.mxCell->getType() == CellContentType_EMPTY) )
509 RichString aString( *this );
510 aString.importString( rStrm, false );
511 aString.finalizeImport();
512 if( eCellType == CELLTYPE_FORMULA )
513 importCellFormula( rStrm );
514 else
515 aString.convert( xText, maCurrCell.mnXfId );
517 setCellFormat( maCurrCell );
520 void OoxSheetDataContext::importCellFormula( RecordInputStream& rStrm )
522 rStrm.skip( 2 );
523 Reference< XFormulaTokens > xTokens( maCurrCell.mxCell, UNO_QUERY );
524 if( xTokens.is() )
526 ExtCellFormulaContext aContext( *this, xTokens, maCurrCell.maAddress );
527 getFormulaParser().importFormula( aContext, rStrm );
531 void OoxSheetDataContext::importRow( RecordInputStream& rStrm )
533 RowModel aModel;
535 sal_uInt16 nHeight, nFlags1;
536 sal_uInt8 nFlags2;
537 rStrm >> maCurrPos.mnRow >> aModel.mnXfId >> nHeight >> nFlags1 >> nFlags2;
539 // row index is 0-based in OOBIN, but RowModel expects 1-based
540 aModel.mnFirstRow = aModel.mnLastRow = maCurrPos.mnRow + 1;
541 // row height is in twips in OOBIN, convert to points
542 aModel.mfHeight = nHeight / 20.0;
543 aModel.mnLevel = extractValue< sal_Int32 >( nFlags1, 8, 3 );
544 aModel.mbCustomHeight = getFlag( nFlags1, OOBIN_ROW_CUSTOMHEIGHT );
545 aModel.mbCustomFormat = getFlag( nFlags1, OOBIN_ROW_CUSTOMFORMAT );
546 aModel.mbShowPhonetic = getFlag( nFlags2, OOBIN_ROW_SHOWPHONETIC );
547 aModel.mbHidden = getFlag( nFlags1, OOBIN_ROW_HIDDEN );
548 aModel.mbCollapsed = getFlag( nFlags1, OOBIN_ROW_COLLAPSED );
549 aModel.mbThickTop = getFlag( nFlags1, OOBIN_ROW_THICKTOP );
550 aModel.mbThickBottom = getFlag( nFlags1, OOBIN_ROW_THICKBOTTOM );
551 // set row properties in the current sheet
552 setRowModel( aModel );
555 void OoxSheetDataContext::importArray( RecordInputStream& rStrm )
557 BinRange aRange;
558 rStrm >> aRange;
559 CellRangeAddress aArrayRange;
560 Reference< XCellRange > xRange = getCellRange( aRange, &aArrayRange );
561 Reference< XArrayFormulaTokens > xTokens( xRange, UNO_QUERY );
562 if( xRange.is() && xTokens.is() )
564 rStrm.skip( 1 );
565 ArrayFormulaContext aContext( xTokens, aArrayRange );
566 getFormulaParser().importFormula( aContext, rStrm );
570 void OoxSheetDataContext::importSharedFmla( RecordInputStream& rStrm )
572 getSharedFormulas().importSharedFmla( rStrm, maCurrCell.maAddress );
575 void OoxSheetDataContext::importDataTable( RecordInputStream& rStrm )
577 BinRange aRange;
578 rStrm >> aRange;
579 CellRangeAddress aTableRange;
580 if( getAddressConverter().convertToCellRange( aTableRange, aRange, getSheetIndex(), true, true ) )
582 DataTableModel aModel;
583 BinAddress aRef1, aRef2;
584 sal_uInt8 nFlags;
585 rStrm >> aRef1 >> aRef2 >> nFlags;
586 aModel.maRef1 = FormulaProcessorBase::generateAddress2dString( aRef1, false );
587 aModel.maRef2 = FormulaProcessorBase::generateAddress2dString( aRef2, false );
588 aModel.mbRowTable = getFlag( nFlags, OOBIN_DATATABLE_ROW );
589 aModel.mb2dTable = getFlag( nFlags, OOBIN_DATATABLE_2D );
590 aModel.mbRef1Deleted = getFlag( nFlags, OOBIN_DATATABLE_REF1DEL );
591 aModel.mbRef2Deleted = getFlag( nFlags, OOBIN_DATATABLE_REF2DEL );
592 setTableOperation( aTableRange, aModel );
596 // ============================================================================
598 BiffSheetDataContext::BiffSheetDataContext( const BiffWorksheetFragmentBase& rParent ) :
599 BiffWorksheetContextBase( rParent ),
600 mnBiff2XfId( 0 )
602 mnArrayIgnoreSize = (getBiff() == BIFF2) ? 1 : ((getBiff() <= BIFF4) ? 2 : 6);
603 switch( getBiff() )
605 case BIFF2:
606 mnFormulaIgnoreSize = 9; // double formula result, 1 byte flags
607 mnArrayIgnoreSize = 1; // recalc-always flag
608 break;
609 case BIFF3:
610 case BIFF4:
611 mnFormulaIgnoreSize = 10; // double formula result, 2 byte flags
612 mnArrayIgnoreSize = 2; // 2 byte flags
613 break;
614 case BIFF5:
615 case BIFF8:
616 mnFormulaIgnoreSize = 14; // double formula result, 2 byte flags, 4 bytes nothing
617 mnArrayIgnoreSize = 6; // 2 byte flags, 4 bytes nothing
618 break;
619 case BIFF_UNKNOWN: break;
623 void BiffSheetDataContext::importRecord()
625 sal_uInt16 nRecId = mrStrm.getRecId();
626 switch( nRecId )
628 // records in all BIFF versions
629 case BIFF2_ID_ARRAY: // #i72713#
630 case BIFF3_ID_ARRAY: importArray(); break;
631 case BIFF2_ID_BLANK:
632 case BIFF3_ID_BLANK: importBlank(); break;
633 case BIFF2_ID_BOOLERR:
634 case BIFF3_ID_BOOLERR: importBoolErr(); break;
635 case BIFF2_ID_INTEGER: importInteger(); break;
636 case BIFF_ID_IXFE: mrStrm >> mnBiff2XfId; break;
637 case BIFF2_ID_LABEL:
638 case BIFF3_ID_LABEL: importLabel(); break;
639 case BIFF2_ID_NUMBER:
640 case BIFF3_ID_NUMBER: importNumber(); break;
641 case BIFF_ID_RK: importRk(); break;
643 // BIFF specific records
644 default: switch( getBiff() )
646 case BIFF2: switch( nRecId )
648 case BIFF2_ID_DATATABLE: importDataTable(); break;
649 case BIFF2_ID_DATATABLE2: importDataTable(); break;
650 case BIFF2_ID_FORMULA: importFormula(); break;
651 case BIFF2_ID_ROW: importRow(); break;
653 break;
655 case BIFF3: switch( nRecId )
657 case BIFF3_ID_DATATABLE: importDataTable(); break;
658 case BIFF3_ID_FORMULA: importFormula(); break;
659 case BIFF3_ID_ROW: importRow(); break;
661 break;
663 case BIFF4: switch( nRecId )
665 case BIFF3_ID_DATATABLE: importDataTable(); break;
666 case BIFF4_ID_FORMULA: importFormula(); break;
667 case BIFF3_ID_ROW: importRow(); break;
669 break;
671 case BIFF5: switch( nRecId )
673 case BIFF3_ID_DATATABLE: importDataTable(); break;
674 case BIFF3_ID_FORMULA:
675 case BIFF4_ID_FORMULA:
676 case BIFF5_ID_FORMULA: importFormula(); break;
677 case BIFF_ID_MULTBLANK: importMultBlank(); break;
678 case BIFF_ID_MULTRK: importMultRk(); break;
679 case BIFF3_ID_ROW: importRow(); break;
680 case BIFF_ID_RSTRING: importLabel(); break;
681 case BIFF_ID_SHAREDFMLA: importSharedFmla(); break;
683 break;
685 case BIFF8: switch( nRecId )
687 case BIFF3_ID_DATATABLE: importDataTable(); break;
688 case BIFF3_ID_FORMULA:
689 case BIFF4_ID_FORMULA:
690 case BIFF5_ID_FORMULA: importFormula(); break;
691 case BIFF_ID_LABELSST: importLabelSst(); break;
692 case BIFF_ID_MULTBLANK: importMultBlank(); break;
693 case BIFF_ID_MULTRK: importMultRk(); break;
694 case BIFF3_ID_ROW: importRow(); break;
695 case BIFF_ID_RSTRING: importLabel(); break;
696 case BIFF_ID_SHAREDFMLA: importSharedFmla(); break;
698 break;
700 case BIFF_UNKNOWN: break;
705 // private --------------------------------------------------------------------
707 void BiffSheetDataContext::setCurrCell( const BinAddress& rAddr )
709 maCurrCell.reset();
710 maCurrCell.mxCell = getCell( rAddr, &maCurrCell.maAddress );
713 void BiffSheetDataContext::importXfId( bool bBiff2 )
715 if( bBiff2 )
717 sal_uInt8 nBiff2XfId;
718 mrStrm >> nBiff2XfId;
719 mrStrm.skip( 2 );
720 maCurrCell.mnXfId = nBiff2XfId & BIFF2_XF_MASK;
721 if( maCurrCell.mnXfId == BIFF2_XF_EXTENDED_IDS )
722 maCurrCell.mnXfId = mnBiff2XfId;
724 else
726 maCurrCell.mnXfId = mrStrm.readuInt16();
730 void BiffSheetDataContext::importCellHeader( bool bBiff2 )
732 BinAddress aAddr;
733 mrStrm >> aAddr;
734 setCurrCell( aAddr );
735 importXfId( bBiff2 );
738 void BiffSheetDataContext::importBlank()
740 importCellHeader( mrStrm.getRecId() == BIFF2_ID_BLANK );
741 setCellFormat( maCurrCell );
744 void BiffSheetDataContext::importBoolErr()
746 importCellHeader( mrStrm.getRecId() == BIFF2_ID_BOOLERR );
747 if( maCurrCell.mxCell.is() )
749 sal_uInt8 nValue, nType;
750 mrStrm >> nValue >> nType;
751 switch( nType )
753 case BIFF_BOOLERR_BOOL:
754 maCurrCell.mnCellType = XML_b;
755 setBooleanCell( maCurrCell.mxCell, nValue != 0 );
756 // #108770# set 'Standard' number format for all Boolean cells
757 maCurrCell.mnNumFmtId = 0;
758 break;
759 case BIFF_BOOLERR_ERROR:
760 maCurrCell.mnCellType = XML_e;
761 setErrorCell( maCurrCell.mxCell, nValue );
762 break;
763 default:
764 OSL_ENSURE( false, "BiffSheetDataContext::importBoolErr - unknown cell type" );
767 setCellFormat( maCurrCell );
770 void BiffSheetDataContext::importFormula()
772 importCellHeader( getBiff() == BIFF2 );
773 maCurrCell.mnCellType = XML_n;
774 Reference< XFormulaTokens > xTokens( maCurrCell.mxCell, UNO_QUERY );
775 if( xTokens.is() )
777 mrStrm.skip( mnFormulaIgnoreSize );
778 ExtCellFormulaContext aContext( *this, xTokens, maCurrCell.maAddress );
779 getFormulaParser().importFormula( aContext, mrStrm );
781 setCellFormat( maCurrCell );
784 void BiffSheetDataContext::importInteger()
786 importCellHeader( true );
787 maCurrCell.mnCellType = XML_n;
788 if( maCurrCell.mxCell.is() )
789 maCurrCell.mxCell->setValue( mrStrm.readuInt16() );
790 setCellFormat( maCurrCell );
793 void BiffSheetDataContext::importLabel()
795 bool bBiff2Xf = mrStrm.getRecId() == BIFF2_ID_LABEL;
796 importCellHeader( bBiff2Xf );
797 maCurrCell.mnCellType = XML_inlineStr;
798 Reference< XText > xText( maCurrCell.mxCell, UNO_QUERY );
799 if( xText.is() )
801 /* the deep secrets of BIFF type and record identifier...
802 record id BIFF -> XF type String type
803 0x0004 2-7 -> 3 byte 8-bit length, byte string
804 0x0004 8 -> 3 byte 16-bit length, unicode string
805 0x0204 2-7 -> 2 byte 16-bit length, byte string
806 0x0204 8 -> 2 byte 16-bit length, unicode string */
808 RichString aString( *this );
809 if( getBiff() == BIFF8 )
811 aString.importUniString( mrStrm );
813 else
815 // #i63105# use text encoding from FONT record
816 rtl_TextEncoding eTextEnc = getTextEncoding();
817 if( const Font* pFont = getStyles().getFontFromCellXf( maCurrCell.mnXfId ).get() )
818 eTextEnc = pFont->getFontEncoding();
819 BiffStringFlags nFlags = bBiff2Xf ? BIFF_STR_8BITLENGTH : BIFF_STR_DEFAULT;
820 setFlag( nFlags, BIFF_STR_EXTRAFONTS, mrStrm.getRecId() == BIFF_ID_RSTRING );
821 aString.importByteString( mrStrm, eTextEnc, nFlags );
823 aString.finalizeImport();
824 aString.convert( xText, maCurrCell.mnXfId );
826 setCellFormat( maCurrCell );
829 void BiffSheetDataContext::importLabelSst()
831 importCellHeader( false );
832 maCurrCell.mnCellType = XML_s;
833 if( maCurrCell.mxCell.is() )
834 setSharedStringCell( maCurrCell.mxCell, mrStrm.readInt32(), maCurrCell.mnXfId );
835 setCellFormat( maCurrCell );
838 void BiffSheetDataContext::importMultBlank()
840 BinAddress aAddr;
841 for( mrStrm >> aAddr; mrStrm.getRemaining() > 2; ++aAddr.mnCol )
843 setCurrCell( aAddr );
844 importXfId( false );
845 setCellFormat( maCurrCell );
849 void BiffSheetDataContext::importMultRk()
851 BinAddress aAddr;
852 for( mrStrm >> aAddr; mrStrm.getRemaining() > 2; ++aAddr.mnCol )
854 setCurrCell( aAddr );
855 maCurrCell.mnCellType = XML_n;
856 importXfId( false );
857 sal_Int32 nRkValue = mrStrm.readInt32();
858 if( maCurrCell.mxCell.is() )
859 maCurrCell.mxCell->setValue( BiffHelper::calcDoubleFromRk( nRkValue ) );
860 setCellFormat( maCurrCell );
864 void BiffSheetDataContext::importNumber()
866 importCellHeader( mrStrm.getRecId() == BIFF2_ID_NUMBER );
867 maCurrCell.mnCellType = XML_n;
868 if( maCurrCell.mxCell.is() )
869 maCurrCell.mxCell->setValue( mrStrm.readDouble() );
870 setCellFormat( maCurrCell );
873 void BiffSheetDataContext::importRk()
875 importCellHeader( false );
876 maCurrCell.mnCellType = XML_n;
877 if( maCurrCell.mxCell.is() )
878 maCurrCell.mxCell->setValue( BiffHelper::calcDoubleFromRk( mrStrm.readInt32() ) );
879 setCellFormat( maCurrCell );
882 void BiffSheetDataContext::importRow()
884 RowModel aModel;
886 sal_uInt16 nRow, nHeight;
887 mrStrm >> nRow;
888 mrStrm.skip( 4 );
889 mrStrm >> nHeight;
890 if( getBiff() == BIFF2 )
892 mrStrm.skip( 2 );
893 aModel.mbCustomFormat = mrStrm.readuInt8() == BIFF2_ROW_CUSTOMFORMAT;
894 if( aModel.mbCustomFormat )
896 mrStrm.skip( 5 );
897 aModel.mnXfId = mrStrm.readuInt16();
900 else
902 mrStrm.skip( 4 );
903 sal_uInt32 nFlags = mrStrm.readuInt32();
904 aModel.mnXfId = extractValue< sal_Int32 >( nFlags, 16, 12 );
905 aModel.mnLevel = extractValue< sal_Int32 >( nFlags, 0, 3 );
906 aModel.mbCustomFormat = getFlag( nFlags, BIFF_ROW_CUSTOMFORMAT );
907 aModel.mbCustomHeight = getFlag( nFlags, BIFF_ROW_CUSTOMHEIGHT );
908 aModel.mbShowPhonetic = getFlag( nFlags, BIFF_ROW_SHOWPHONETIC );
909 aModel.mbHidden = getFlag( nFlags, BIFF_ROW_HIDDEN );
910 aModel.mbCollapsed = getFlag( nFlags, BIFF_ROW_COLLAPSED );
911 aModel.mbThickTop = getFlag( nFlags, BIFF_ROW_THICKTOP );
912 aModel.mbThickBottom = getFlag( nFlags, BIFF_ROW_THICKBOTTOM );
915 // row index is 0-based in BIFF, but RowModel expects 1-based
916 aModel.mnFirstRow = aModel.mnLastRow = nRow + 1;
917 // row height is in twips in BIFF, convert to points
918 aModel.mfHeight = (nHeight & BIFF_ROW_HEIGHTMASK) / 20.0;
919 // set row properties in the current sheet
920 setRowModel( aModel );
923 void BiffSheetDataContext::importArray()
925 BinRange aRange;
926 aRange.read( mrStrm, false ); // columns always 8-bit
927 CellRangeAddress aArrayRange;
928 Reference< XCellRange > xRange = getCellRange( aRange, &aArrayRange );
929 Reference< XArrayFormulaTokens > xTokens( xRange, UNO_QUERY );
930 if( xRange.is() && xTokens.is() )
932 mrStrm.skip( mnArrayIgnoreSize );
933 ArrayFormulaContext aContext( xTokens, aArrayRange );
934 getFormulaParser().importFormula( aContext, mrStrm );
938 void BiffSheetDataContext::importSharedFmla()
940 getSharedFormulas().importSharedFmla( mrStrm, maCurrCell.maAddress );
943 void BiffSheetDataContext::importDataTable()
945 BinRange aRange;
946 aRange.read( mrStrm, false ); // columns always 8-bit
947 CellRangeAddress aTableRange;
948 if( getAddressConverter().convertToCellRange( aTableRange, aRange, getSheetIndex(), true, true ) )
950 DataTableModel aModel;
951 BinAddress aRef1, aRef2;
952 switch( mrStrm.getRecId() )
954 case BIFF2_ID_DATATABLE:
955 mrStrm.skip( 1 );
956 aModel.mbRowTable = mrStrm.readuInt8() != 0;
957 aModel.mb2dTable = false;
958 mrStrm >> aRef1;
959 break;
960 case BIFF2_ID_DATATABLE2:
961 mrStrm.skip( 2 );
962 aModel.mb2dTable = true;
963 mrStrm >> aRef1 >> aRef2;
964 break;
965 case BIFF3_ID_DATATABLE:
967 sal_uInt16 nFlags;
968 mrStrm >> nFlags >> aRef1 >> aRef2;
969 aModel.mbRowTable = getFlag( nFlags, BIFF_DATATABLE_ROW );
970 aModel.mb2dTable = getFlag( nFlags, BIFF_DATATABLE_2D );
971 aModel.mbRef1Deleted = getFlag( nFlags, BIFF_DATATABLE_REF1DEL );
972 aModel.mbRef2Deleted = getFlag( nFlags, BIFF_DATATABLE_REF2DEL );
974 break;
975 default:
976 OSL_ENSURE( false, "BiffSheetDataContext::importDataTable - unknown record id" );
978 aModel.maRef1 = FormulaProcessorBase::generateAddress2dString( aRef1, false );
979 aModel.maRef2 = FormulaProcessorBase::generateAddress2dString( aRef2, false );
980 setTableOperation( aTableRange, aModel );
984 // ============================================================================
986 } // namespace xls
987 } // namespace oox