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
;
66 // ============================================================================
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
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
138 explicit ArrayFormulaContext(
139 const Reference
< XArrayFormulaTokens
>& rxTokens
,
140 const CellRangeAddress
& rArrayRange
);
142 virtual void setTokens( const ApiTokenSequence
& rTokens
);
145 Reference
< XArrayFormulaTokens
> mxTokens
;
148 ArrayFormulaContext::ArrayFormulaContext(
149 const Reference
< XArrayFormulaTokens
>& rxTokens
, const CellRangeAddress
& rArrayRange
) :
150 FormulaContext( false, false ),
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 // ----------------------------------------------------------------------------
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; }
184 case XLS_TOKEN( row
):
185 if( nElement
== XLS_TOKEN( c
) ) { importCell( rAttribs
); return this; }
189 if( maCurrCell
.mxCell
.is() ) switch( nElement
)
191 case XLS_TOKEN( is
):
192 mxInlineStr
.reset( new RichString( *this ) );
193 return new OoxRichStringContext( *this, mxInlineStr
);
197 importFormula( rAttribs
);
205 void OoxSheetDataContext::onEndElement( const OUString
& rChars
)
207 OOX_LOADSAVE_TIMER( ONENDSHEETELEMENT
);
208 switch( getCurrentElement() )
211 maCurrCell
.maValueStr
= rChars
;
212 maCurrCell
.mbHasValueStr
= true;
216 if( maCurrCell
.mxCell
.is() ) try
218 switch( maCurrCell
.mnFormulaType
)
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
);
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
);
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
);
251 if( maCurrCell
.maFormulaRef
.getLength() > 0 )
253 CellRangeAddress aTableRange
;
254 if( getAddressConverter().convertToCellRange( aTableRange
, maCurrCell
.maFormulaRef
, getSheetIndex(), true, true ) )
255 setTableOperation( aTableRange
, maTableData
);
260 OSL_ENSURE( false, "OoxSheetDataContext::onEndElement - unknown formula type" );
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
);
285 mxInlineStr
->convert( xText
, maCurrCell
.mnXfId
);
289 // empty cell, update cell type
290 maCurrCell
.mnCellType
= XML_TOKEN_INVALID
;
294 // store the cell formatting data
295 setCellFormat( maCurrCell
);
301 ContextHandlerRef
OoxSheetDataContext::onCreateRecordContext( sal_Int32 nRecId
, RecordInputStream
& rStrm
)
303 switch( getCurrentElement() )
305 case OOBIN_ID_SHEETDATA
:
308 case OOBIN_ID_ROW
: importRow( rStrm
); return this;
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;
344 // private --------------------------------------------------------------------
346 void OoxSheetDataContext::importRow( const AttributeList
& rAttribs
)
348 OOX_LOADSAVE_TIMER( IMPORTROW
);
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
);
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 );
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
)
396 case CELLTYPE_FORMULA
: rStrm
>> maCurrPos
.mnCol
; break;
397 case CELLTYPE_MULTI
: ++maCurrPos
.mnCol
; break;
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
);
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
);
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
);
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
);
515 aString
.convert( xText
, maCurrCell
.mnXfId
);
517 setCellFormat( maCurrCell
);
520 void OoxSheetDataContext::importCellFormula( RecordInputStream
& rStrm
)
523 Reference
< XFormulaTokens
> xTokens( maCurrCell
.mxCell
, UNO_QUERY
);
526 ExtCellFormulaContext
aContext( *this, xTokens
, maCurrCell
.maAddress
);
527 getFormulaParser().importFormula( aContext
, rStrm
);
531 void OoxSheetDataContext::importRow( RecordInputStream
& rStrm
)
535 sal_uInt16 nHeight
, nFlags1
;
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
)
559 CellRangeAddress aArrayRange
;
560 Reference
< XCellRange
> xRange
= getCellRange( aRange
, &aArrayRange
);
561 Reference
< XArrayFormulaTokens
> xTokens( xRange
, UNO_QUERY
);
562 if( xRange
.is() && xTokens
.is() )
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
)
579 CellRangeAddress aTableRange
;
580 if( getAddressConverter().convertToCellRange( aTableRange
, aRange
, getSheetIndex(), true, true ) )
582 DataTableModel aModel
;
583 BinAddress aRef1
, aRef2
;
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
),
602 mnArrayIgnoreSize
= (getBiff() == BIFF2
) ? 1 : ((getBiff() <= BIFF4
) ? 2 : 6);
606 mnFormulaIgnoreSize
= 9; // double formula result, 1 byte flags
607 mnArrayIgnoreSize
= 1; // recalc-always flag
611 mnFormulaIgnoreSize
= 10; // double formula result, 2 byte flags
612 mnArrayIgnoreSize
= 2; // 2 byte flags
616 mnFormulaIgnoreSize
= 14; // double formula result, 2 byte flags, 4 bytes nothing
617 mnArrayIgnoreSize
= 6; // 2 byte flags, 4 bytes nothing
619 case BIFF_UNKNOWN
: break;
623 void BiffSheetDataContext::importRecord()
625 sal_uInt16 nRecId
= mrStrm
.getRecId();
628 // records in all BIFF versions
629 case BIFF2_ID_ARRAY
: // #i72713#
630 case BIFF3_ID_ARRAY
: importArray(); break;
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;
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;
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;
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;
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;
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;
700 case BIFF_UNKNOWN
: break;
705 // private --------------------------------------------------------------------
707 void BiffSheetDataContext::setCurrCell( const BinAddress
& rAddr
)
710 maCurrCell
.mxCell
= getCell( rAddr
, &maCurrCell
.maAddress
);
713 void BiffSheetDataContext::importXfId( bool bBiff2
)
717 sal_uInt8 nBiff2XfId
;
718 mrStrm
>> nBiff2XfId
;
720 maCurrCell
.mnXfId
= nBiff2XfId
& BIFF2_XF_MASK
;
721 if( maCurrCell
.mnXfId
== BIFF2_XF_EXTENDED_IDS
)
722 maCurrCell
.mnXfId
= mnBiff2XfId
;
726 maCurrCell
.mnXfId
= mrStrm
.readuInt16();
730 void BiffSheetDataContext::importCellHeader( bool bBiff2
)
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
;
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;
759 case BIFF_BOOLERR_ERROR
:
760 maCurrCell
.mnCellType
= XML_e
;
761 setErrorCell( maCurrCell
.mxCell
, nValue
);
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
);
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
);
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
);
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()
841 for( mrStrm
>> aAddr
; mrStrm
.getRemaining() > 2; ++aAddr
.mnCol
)
843 setCurrCell( aAddr
);
845 setCellFormat( maCurrCell
);
849 void BiffSheetDataContext::importMultRk()
852 for( mrStrm
>> aAddr
; mrStrm
.getRemaining() > 2; ++aAddr
.mnCol
)
854 setCurrCell( aAddr
);
855 maCurrCell
.mnCellType
= XML_n
;
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()
886 sal_uInt16 nRow
, nHeight
;
890 if( getBiff() == BIFF2
)
893 aModel
.mbCustomFormat
= mrStrm
.readuInt8() == BIFF2_ROW_CUSTOMFORMAT
;
894 if( aModel
.mbCustomFormat
)
897 aModel
.mnXfId
= mrStrm
.readuInt16();
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()
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()
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
:
956 aModel
.mbRowTable
= mrStrm
.readuInt8() != 0;
957 aModel
.mb2dTable
= false;
960 case BIFF2_ID_DATATABLE2
:
962 aModel
.mb2dTable
= true;
963 mrStrm
>> aRef1
>> aRef2
;
965 case BIFF3_ID_DATATABLE
:
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
);
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 // ============================================================================