/************************************************************************* * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * Copyright 2000, 2010 Oracle and/or its affiliates. * * OpenOffice.org - a multi-platform office productivity suite * * This file is part of OpenOffice.org. * * OpenOffice.org is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 * only, as published by the Free Software Foundation. * * OpenOffice.org is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License version 3 for more details * (a copy is included in the LICENSE file that accompanied this code). * * You should have received a copy of the GNU Lesser General Public License * version 3 along with OpenOffice.org. If not, see * * for a copy of the LGPLv3 License. * ************************************************************************/ #include "oox/xls/worksheetfragment.hxx" #include "oox/core/filterbase.hxx" #include "oox/core/relations.hxx" #include "oox/helper/attributelist.hxx" #include "oox/xls/addressconverter.hxx" #include "oox/xls/autofilterbuffer.hxx" #include "oox/xls/autofiltercontext.hxx" #include "oox/xls/biffinputstream.hxx" #include "oox/xls/commentsfragment.hxx" #include "oox/xls/condformatcontext.hxx" #include "oox/xls/drawingfragment.hxx" #include "oox/xls/drawingmanager.hxx" #include "oox/xls/externallinkbuffer.hxx" #include "oox/xls/pagesettings.hxx" #include "oox/xls/pivottablefragment.hxx" #include "oox/xls/querytablefragment.hxx" #include "oox/xls/scenariobuffer.hxx" #include "oox/xls/scenariocontext.hxx" #include "oox/xls/sheetdatabuffer.hxx" #include "oox/xls/sheetdatacontext.hxx" #include "oox/xls/tablefragment.hxx" #include "oox/xls/viewsettings.hxx" #include "oox/xls/workbooksettings.hxx" #include "oox/xls/worksheetsettings.hxx" namespace oox { namespace xls { // ============================================================================ using namespace ::com::sun::star::table; using namespace ::com::sun::star::uno; using namespace ::oox::core; using ::rtl::OUString; using ::rtl::OUStringBuffer; // ============================================================================ namespace { const sal_uInt16 BIFF_COLINFO_HIDDEN = 0x0001; const sal_uInt16 BIFF_COLINFO_SHOWPHONETIC = 0x0008; const sal_uInt16 BIFF_COLINFO_COLLAPSED = 0x1000; const sal_uInt16 BIFF_DEFROW_CUSTOMHEIGHT = 0x0001; const sal_uInt16 BIFF_DEFROW_HIDDEN = 0x0002; const sal_uInt16 BIFF_DEFROW_THICKTOP = 0x0004; const sal_uInt16 BIFF_DEFROW_THICKBOTTOM = 0x0008; const sal_uInt16 BIFF2_DEFROW_DEFHEIGHT = 0x8000; const sal_uInt16 BIFF2_DEFROW_MASK = 0x7FFF; const sal_uInt32 BIFF_DATAVAL_STRINGLIST = 0x00000080; const sal_uInt32 BIFF_DATAVAL_ALLOWBLANK = 0x00000100; const sal_uInt32 BIFF_DATAVAL_NODROPDOWN = 0x00000200; const sal_uInt32 BIFF_DATAVAL_SHOWINPUT = 0x00040000; const sal_uInt32 BIFF_DATAVAL_SHOWERROR = 0x00080000; const sal_uInt32 BIFF_SHRFEATHEAD_SHEETPROT = 2; const sal_Int32 BIFF12_OLEOBJECT_CONTENT = 1; const sal_Int32 BIFF12_OLEOBJECT_ICON = 4; const sal_Int32 BIFF12_OLEOBJECT_ALWAYS = 1; const sal_Int32 BIFF12_OLEOBJECT_ONCALL = 3; const sal_uInt16 BIFF12_OLEOBJECT_LINKED = 0x0001; const sal_uInt16 BIFF12_OLEOBJECT_AUTOLOAD = 0x0002; } // namespace // ============================================================================ DataValidationsContext::DataValidationsContext( WorksheetFragmentBase& rFragment ) : WorksheetContextBase( rFragment ) { } ContextHandlerRef DataValidationsContext::onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs ) { switch( getCurrentElement() ) { case XLS_TOKEN( dataValidations ): if( nElement == XLS_TOKEN( dataValidation ) ) { importDataValidation( rAttribs ); return this; } break; case XLS_TOKEN( dataValidation ): switch( nElement ) { case XLS_TOKEN( formula1 ): case XLS_TOKEN( formula2 ): return this; // collect formulas in onCharacters() } break; } return 0; } void DataValidationsContext::onCharacters( const OUString& rChars ) { if( mxValModel.get() ) switch( getCurrentElement() ) { case XLS_TOKEN( formula1 ): mxValModel->maTokens1 = getFormulaParser().importFormula( mxValModel->maRanges.getBaseAddress(), rChars ); // process string list of a list validation (convert to list of string tokens) if( mxValModel->mnType == XML_list ) getFormulaParser().convertStringToStringList( mxValModel->maTokens1, ',', true ); break; case XLS_TOKEN( formula2 ): mxValModel->maTokens2 = getFormulaParser().importFormula( mxValModel->maRanges.getBaseAddress(), rChars ); break; } } void DataValidationsContext::onEndElement() { if( isCurrentElement( XLS_TOKEN( dataValidation ) ) && mxValModel.get() ) { setValidation( *mxValModel ); mxValModel.reset(); } } ContextHandlerRef DataValidationsContext::onCreateRecordContext( sal_Int32 nRecId, SequenceInputStream& rStrm ) { if( nRecId == BIFF12_ID_DATAVALIDATION ) importDataValidation( rStrm ); return 0; } void DataValidationsContext::importDataValidation( const AttributeList& rAttribs ) { mxValModel.reset( new ValidationModel ); getAddressConverter().convertToCellRangeList( mxValModel->maRanges, rAttribs.getString( XML_sqref, OUString() ), getSheetIndex(), true ); mxValModel->maInputTitle = rAttribs.getXString( XML_promptTitle, OUString() ); mxValModel->maInputMessage = rAttribs.getXString( XML_prompt, OUString() ); mxValModel->maErrorTitle = rAttribs.getXString( XML_errorTitle, OUString() ); mxValModel->maErrorMessage = rAttribs.getXString( XML_error, OUString() ); mxValModel->mnType = rAttribs.getToken( XML_type, XML_none ); mxValModel->mnOperator = rAttribs.getToken( XML_operator, XML_between ); mxValModel->mnErrorStyle = rAttribs.getToken( XML_errorStyle, XML_stop ); mxValModel->mbShowInputMsg = rAttribs.getBool( XML_showInputMessage, false ); mxValModel->mbShowErrorMsg = rAttribs.getBool( XML_showErrorMessage, false ); /* The attribute showDropDown@dataValidation is in fact a "suppress dropdown" flag, as it was in the BIFF format! ECMA specification and attribute name are plain wrong! */ mxValModel->mbNoDropDown = rAttribs.getBool( XML_showDropDown, false ); mxValModel->mbAllowBlank = rAttribs.getBool( XML_allowBlank, false ); } void DataValidationsContext::importDataValidation( SequenceInputStream& rStrm ) { ValidationModel aModel; sal_uInt32 nFlags; BinRangeList aRanges; rStrm >> nFlags >> aRanges >> aModel.maErrorTitle >> aModel.maErrorMessage >> aModel.maInputTitle >> aModel.maInputMessage; // equal flags in all BIFFs aModel.setBiffType( extractValue< sal_uInt8 >( nFlags, 0, 4 ) ); aModel.setBiffOperator( extractValue< sal_uInt8 >( nFlags, 20, 4 ) ); aModel.setBiffErrorStyle( extractValue< sal_uInt8 >( nFlags, 4, 3 ) ); aModel.mbAllowBlank = getFlag( nFlags, BIFF_DATAVAL_ALLOWBLANK ); aModel.mbNoDropDown = getFlag( nFlags, BIFF_DATAVAL_NODROPDOWN ); aModel.mbShowInputMsg = getFlag( nFlags, BIFF_DATAVAL_SHOWINPUT ); aModel.mbShowErrorMsg = getFlag( nFlags, BIFF_DATAVAL_SHOWERROR ); // cell range list getAddressConverter().convertToCellRangeList( aModel.maRanges, aRanges, getSheetIndex(), true ); // condition formula(s) FormulaParser& rParser = getFormulaParser(); CellAddress aBaseAddr = aModel.maRanges.getBaseAddress(); aModel.maTokens1 = rParser.importFormula( aBaseAddr, FORMULATYPE_VALIDATION, rStrm ); aModel.maTokens2 = rParser.importFormula( aBaseAddr, FORMULATYPE_VALIDATION, rStrm ); // process string list of a list validation (convert to list of string tokens) if( (aModel.mnType == XML_list) && getFlag( nFlags, BIFF_DATAVAL_STRINGLIST ) ) rParser.convertStringToStringList( aModel.maTokens1, ',', true ); // set validation data setValidation( aModel ); } // ============================================================================ WorksheetFragment::WorksheetFragment( const WorksheetHelper& rHelper, const OUString& rFragmentPath ) : WorksheetFragmentBase( rHelper, rFragmentPath ) { // import data tables related to this worksheet RelationsRef xTableRels = getRelations().getRelationsFromType( CREATE_OFFICEDOC_RELATION_TYPE( "table" ) ); for( Relations::const_iterator aIt = xTableRels->begin(), aEnd = xTableRels->end(); aIt != aEnd; ++aIt ) importOoxFragment( new TableFragment( *this, getFragmentPathFromRelation( aIt->second ) ) ); // import comments related to this worksheet OUString aCommentsFragmentPath = getFragmentPathFromFirstType( CREATE_OFFICEDOC_RELATION_TYPE( "comments" ) ); if( aCommentsFragmentPath.getLength() > 0 ) importOoxFragment( new CommentsFragment( *this, aCommentsFragmentPath ) ); } ContextHandlerRef WorksheetFragment::onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs ) { switch( getCurrentElement() ) { case XML_ROOT_CONTEXT: switch( getSheetType() ) { case SHEETTYPE_WORKSHEET: return (nElement == XLS_TOKEN( worksheet )) ? this : 0; case SHEETTYPE_CHARTSHEET: return 0; case SHEETTYPE_MACROSHEET: return (nElement == XM_TOKEN( macrosheet )) ? this : 0; case SHEETTYPE_DIALOGSHEET: return (nElement == XLS_TOKEN( dialogsheet )) ? this : 0; case SHEETTYPE_MODULESHEET: return 0; case SHEETTYPE_EMPTYSHEET: return 0; } break; case XLS_TOKEN( worksheet ): case XM_TOKEN( macrosheet ): case XLS_TOKEN( dialogsheet ): switch( nElement ) { case XLS_TOKEN( sheetData ): return new SheetDataContext( *this ); case XLS_TOKEN( conditionalFormatting ): return new CondFormatContext( *this ); case XLS_TOKEN( dataValidations ): return new DataValidationsContext( *this ); case XLS_TOKEN( autoFilter ): return new AutoFilterContext( *this, getAutoFilters().createAutoFilter() ); case XLS_TOKEN( scenarios ): return new ScenariosContext( *this ); case XLS_TOKEN( sheetViews ): case XLS_TOKEN( cols ): case XLS_TOKEN( mergeCells ): case XLS_TOKEN( hyperlinks ): case XLS_TOKEN( rowBreaks ): case XLS_TOKEN( colBreaks ): case XLS_TOKEN( oleObjects ): case XLS_TOKEN( controls ): return this; case XLS_TOKEN( sheetPr ): getWorksheetSettings().importSheetPr( rAttribs ); return this; case XLS_TOKEN( dimension ): importDimension( rAttribs ); break; case XLS_TOKEN( sheetFormatPr ): importSheetFormatPr( rAttribs ); break; case XLS_TOKEN( sheetProtection ): getWorksheetSettings().importSheetProtection( rAttribs ); break; case XLS_TOKEN( phoneticPr ): getWorksheetSettings().importPhoneticPr( rAttribs ); break; case XLS_TOKEN( printOptions ): getPageSettings().importPrintOptions( rAttribs ); break; case XLS_TOKEN( pageMargins ): getPageSettings().importPageMargins( rAttribs ); break; case XLS_TOKEN( pageSetup ): getPageSettings().importPageSetup( getRelations(), rAttribs ); break; case XLS_TOKEN( headerFooter ): getPageSettings().importHeaderFooter( rAttribs ); return this; case XLS_TOKEN( picture ): getPageSettings().importPicture( getRelations(), rAttribs ); break; case XLS_TOKEN( drawing ): importDrawing( rAttribs ); break; case XLS_TOKEN( legacyDrawing ): importLegacyDrawing( rAttribs ); break; } break; case XLS_TOKEN( sheetPr ): switch( nElement ) { case XLS_TOKEN( tabColor ): getWorksheetSettings().importTabColor( rAttribs ); break; case XLS_TOKEN( outlinePr ): getWorksheetSettings().importOutlinePr( rAttribs ); break; case XLS_TOKEN( pageSetUpPr ): importPageSetUpPr( rAttribs ); break; } break; case XLS_TOKEN( sheetViews ): switch( nElement ) { case XLS_TOKEN( sheetView ): getSheetViewSettings().importSheetView( rAttribs ); return this; } break; case XLS_TOKEN( sheetView ): switch( nElement ) { case XLS_TOKEN( pane ): getSheetViewSettings().importPane( rAttribs ); break; case XLS_TOKEN( selection ): getSheetViewSettings().importSelection( rAttribs ); break; } break; case XLS_TOKEN( cols ): if( nElement == XLS_TOKEN( col ) ) importCol( rAttribs ); break; case XLS_TOKEN( mergeCells ): if( nElement == XLS_TOKEN( mergeCell ) ) importMergeCell( rAttribs ); break; case XLS_TOKEN( hyperlinks ): if( nElement == XLS_TOKEN( hyperlink ) ) importHyperlink( rAttribs ); break; case XLS_TOKEN( rowBreaks ): if( nElement == XLS_TOKEN( brk ) ) importBrk( rAttribs, true ); break; case XLS_TOKEN( colBreaks ): if( nElement == XLS_TOKEN( brk ) ) importBrk( rAttribs, false ); break; case XLS_TOKEN( headerFooter ): switch( nElement ) { case XLS_TOKEN( firstHeader ): case XLS_TOKEN( firstFooter ): case XLS_TOKEN( oddHeader ): case XLS_TOKEN( oddFooter ): case XLS_TOKEN( evenHeader ): case XLS_TOKEN( evenFooter ): return this; // collect h/f contents in onCharacters() } break; case XLS_TOKEN( oleObjects ): if( nElement == XLS_TOKEN( oleObject ) ) importOleObject( rAttribs ); break; case XLS_TOKEN( controls ): if( nElement == XLS_TOKEN( control ) ) importControl( rAttribs ); break; } return 0; } void WorksheetFragment::onCharacters( const OUString& rChars ) { switch( getCurrentElement() ) { case XLS_TOKEN( firstHeader ): case XLS_TOKEN( firstFooter ): case XLS_TOKEN( oddHeader ): case XLS_TOKEN( oddFooter ): case XLS_TOKEN( evenHeader ): case XLS_TOKEN( evenFooter ): getPageSettings().importHeaderFooterCharacters( rChars, getCurrentElement() ); break; } } ContextHandlerRef WorksheetFragment::onCreateRecordContext( sal_Int32 nRecId, SequenceInputStream& rStrm ) { switch( getCurrentElement() ) { case XML_ROOT_CONTEXT: if( nRecId == BIFF12_ID_WORKSHEET ) return this; break; case BIFF12_ID_WORKSHEET: switch( nRecId ) { case BIFF12_ID_SHEETDATA: return new SheetDataContext( *this ); case BIFF12_ID_CONDFORMATTING: return new CondFormatContext( *this ); case BIFF12_ID_DATAVALIDATIONS: return new DataValidationsContext( *this ); case BIFF12_ID_AUTOFILTER: return new AutoFilterContext( *this, getAutoFilters().createAutoFilter() ); case BIFF12_ID_SCENARIOS: return new ScenariosContext( *this ); case BIFF12_ID_SHEETVIEWS: case BIFF12_ID_COLS: case BIFF12_ID_MERGECELLS: case BIFF12_ID_ROWBREAKS: case BIFF12_ID_COLBREAKS: case BIFF12_ID_OLEOBJECTS: case BIFF12_ID_CONTROLS: return this; case BIFF12_ID_SHEETPR: getWorksheetSettings().importSheetPr( rStrm ); break; case BIFF12_ID_DIMENSION: importDimension( rStrm ); break; case BIFF12_ID_SHEETFORMATPR: importSheetFormatPr( rStrm ); break; case BIFF12_ID_HYPERLINK: importHyperlink( rStrm ); break; case BIFF12_ID_PAGEMARGINS: getPageSettings().importPageMargins( rStrm ); break; case BIFF12_ID_PAGESETUP: getPageSettings().importPageSetup( getRelations(), rStrm ); break; case BIFF12_ID_PRINTOPTIONS: getPageSettings().importPrintOptions( rStrm ); break; case BIFF12_ID_HEADERFOOTER: getPageSettings().importHeaderFooter( rStrm ); break; case BIFF12_ID_PICTURE: getPageSettings().importPicture( getRelations(), rStrm ); break; case BIFF12_ID_SHEETPROTECTION: getWorksheetSettings().importSheetProtection( rStrm ); break; case BIFF12_ID_PHONETICPR: getWorksheetSettings().importPhoneticPr( rStrm ); break; case BIFF12_ID_DRAWING: importDrawing( rStrm ); break; case BIFF12_ID_LEGACYDRAWING: importLegacyDrawing( rStrm ); break; } break; case BIFF12_ID_SHEETVIEWS: switch( nRecId ) { case BIFF12_ID_SHEETVIEW: getSheetViewSettings().importSheetView( rStrm ); return this; } break; case BIFF12_ID_SHEETVIEW: switch( nRecId ) { case BIFF12_ID_PANE: getSheetViewSettings().importPane( rStrm ); break; case BIFF12_ID_SELECTION: getSheetViewSettings().importSelection( rStrm ); break; } break; case BIFF12_ID_COLS: if( nRecId == BIFF12_ID_COL ) importCol( rStrm ); break; case BIFF12_ID_MERGECELLS: if( nRecId == BIFF12_ID_MERGECELL ) importMergeCell( rStrm ); break; case BIFF12_ID_ROWBREAKS: if( nRecId == BIFF12_ID_BRK ) importBrk( rStrm, true ); break; case BIFF12_ID_COLBREAKS: if( nRecId == BIFF12_ID_BRK ) importBrk( rStrm, false ); break; case BIFF12_ID_OLEOBJECTS: if( nRecId == BIFF12_ID_OLEOBJECT ) importOleObject( rStrm ); break; case BIFF12_ID_CONTROLS: if( nRecId == BIFF12_ID_CONTROL ) importControl( rStrm ); break; } return 0; } const RecordInfo* WorksheetFragment::getRecordInfos() const { static const RecordInfo spRecInfos[] = { { BIFF12_ID_AUTOFILTER, BIFF12_ID_AUTOFILTER + 1 }, { BIFF12_ID_CFRULE, BIFF12_ID_CFRULE + 1 }, { BIFF12_ID_COLBREAKS, BIFF12_ID_COLBREAKS + 1 }, { BIFF12_ID_COLORSCALE, BIFF12_ID_COLORSCALE + 1 }, { BIFF12_ID_COLS, BIFF12_ID_COLS + 1 }, { BIFF12_ID_CONDFORMATTING, BIFF12_ID_CONDFORMATTING + 1 }, { BIFF12_ID_CONTROLS, BIFF12_ID_CONTROLS + 2 }, { BIFF12_ID_CUSTOMFILTERS, BIFF12_ID_CUSTOMFILTERS + 1 }, { BIFF12_ID_CUSTOMSHEETVIEW, BIFF12_ID_CUSTOMSHEETVIEW + 1 }, { BIFF12_ID_CUSTOMSHEETVIEWS, BIFF12_ID_CUSTOMSHEETVIEWS + 3 }, { BIFF12_ID_DATABAR, BIFF12_ID_DATABAR + 1 }, { BIFF12_ID_DATAVALIDATIONS, BIFF12_ID_DATAVALIDATIONS + 1 }, { BIFF12_ID_DISCRETEFILTERS, BIFF12_ID_DISCRETEFILTERS + 1 }, { BIFF12_ID_FILTERCOLUMN, BIFF12_ID_FILTERCOLUMN + 1 }, { BIFF12_ID_HEADERFOOTER, BIFF12_ID_HEADERFOOTER + 1 }, { BIFF12_ID_ICONSET, BIFF12_ID_ICONSET + 1 }, { BIFF12_ID_MERGECELLS, BIFF12_ID_MERGECELLS + 1 }, { BIFF12_ID_OLEOBJECTS, BIFF12_ID_OLEOBJECTS + 2 }, { BIFF12_ID_ROW, -1 }, { BIFF12_ID_ROWBREAKS, BIFF12_ID_ROWBREAKS + 1 }, { BIFF12_ID_SCENARIO, BIFF12_ID_SCENARIO + 1 }, { BIFF12_ID_SCENARIOS, BIFF12_ID_SCENARIOS + 1 }, { BIFF12_ID_SHEETDATA, BIFF12_ID_SHEETDATA + 1 }, { BIFF12_ID_SHEETVIEW, BIFF12_ID_SHEETVIEW + 1 }, { BIFF12_ID_SHEETVIEWS, BIFF12_ID_SHEETVIEWS + 1 }, { BIFF12_ID_TABLEPARTS, BIFF12_ID_TABLEPARTS + 2 }, { BIFF12_ID_WORKSHEET, BIFF12_ID_WORKSHEET + 1 }, { -1, -1 } }; return spRecInfos; } void WorksheetFragment::initializeImport() { // initial processing in base class WorksheetHelper initializeWorksheetImport(); // import query table fragments related to this worksheet RelationsRef xQueryRels = getRelations().getRelationsFromType( CREATE_OFFICEDOC_RELATION_TYPE( "queryTable" ) ); for( Relations::const_iterator aIt = xQueryRels->begin(), aEnd = xQueryRels->end(); aIt != aEnd; ++aIt ) importOoxFragment( new QueryTableFragment( *this, getFragmentPathFromRelation( aIt->second ) ) ); // import pivot table fragments related to this worksheet RelationsRef xPivotRels = getRelations().getRelationsFromType( CREATE_OFFICEDOC_RELATION_TYPE( "pivotTable" ) ); for( Relations::const_iterator aIt = xPivotRels->begin(), aEnd = xPivotRels->end(); aIt != aEnd; ++aIt ) importOoxFragment( new PivotTableFragment( *this, getFragmentPathFromRelation( aIt->second ) ) ); } void WorksheetFragment::finalizeImport() { // final processing in base class WorksheetHelper finalizeWorksheetImport(); } // private -------------------------------------------------------------------- void WorksheetFragment::importPageSetUpPr( const AttributeList& rAttribs ) { // for whatever reason, this flag is still stored separated from the page settings getPageSettings().setFitToPagesMode( rAttribs.getBool( XML_fitToPage, false ) ); } void WorksheetFragment::importDimension( const AttributeList& rAttribs ) { CellRangeAddress aRange; getAddressConverter().convertToCellRangeUnchecked( aRange, rAttribs.getString( XML_ref, OUString() ), getSheetIndex() ); /* OOXML stores the used area, if existing, or "A1" if the sheet is empty. In case of "A1", the dimension at the WorksheetHelper object will not be set. If the cell A1 exists, the used area will be updated while importing the cell. */ if( (aRange.EndColumn > 0) || (aRange.EndRow > 0) ) extendUsedArea( aRange ); } void WorksheetFragment::importSheetFormatPr( const AttributeList& rAttribs ) { // default column settings setBaseColumnWidth( rAttribs.getInteger( XML_baseColWidth, 8 ) ); setDefaultColumnWidth( rAttribs.getDouble( XML_defaultColWidth, 0.0 ) ); // default row settings setDefaultRowSettings( rAttribs.getDouble( XML_defaultRowHeight, 0.0 ), rAttribs.getBool( XML_customHeight, false ), rAttribs.getBool( XML_zeroHeight, false ), rAttribs.getBool( XML_thickTop, false ), rAttribs.getBool( XML_thickBottom, false ) ); } void WorksheetFragment::importCol( const AttributeList& rAttribs ) { ColumnModel aModel; aModel.maRange.mnFirst = rAttribs.getInteger( XML_min, -1 ); aModel.maRange.mnLast = rAttribs.getInteger( XML_max, -1 ); aModel.mfWidth = rAttribs.getDouble( XML_width, 0.0 ); aModel.mnXfId = rAttribs.getInteger( XML_style, -1 ); aModel.mnLevel = rAttribs.getInteger( XML_outlineLevel, 0 ); aModel.mbShowPhonetic = rAttribs.getBool( XML_phonetic, false ); aModel.mbHidden = rAttribs.getBool( XML_hidden, false ); aModel.mbCollapsed = rAttribs.getBool( XML_collapsed, false ); // set column properties in the current sheet setColumnModel( aModel ); } void WorksheetFragment::importMergeCell( const AttributeList& rAttribs ) { CellRangeAddress aRange; if( getAddressConverter().convertToCellRange( aRange, rAttribs.getString( XML_ref, OUString() ), getSheetIndex(), true, true ) ) getSheetData().setMergedRange( aRange ); } void WorksheetFragment::importHyperlink( const AttributeList& rAttribs ) { HyperlinkModel aModel; if( getAddressConverter().convertToCellRange( aModel.maRange, rAttribs.getString( XML_ref, OUString() ), getSheetIndex(), true, true ) ) { aModel.maTarget = getRelations().getExternalTargetFromRelId( rAttribs.getString( R_TOKEN( id ), OUString() ) ); aModel.maLocation = rAttribs.getXString( XML_location, OUString() ); aModel.maDisplay = rAttribs.getXString( XML_display, OUString() ); aModel.maTooltip = rAttribs.getXString( XML_tooltip, OUString() ); setHyperlink( aModel ); } } void WorksheetFragment::importBrk( const AttributeList& rAttribs, bool bRowBreak ) { PageBreakModel aModel; aModel.mnColRow = rAttribs.getInteger( XML_id, 0 ); aModel.mnMin = rAttribs.getInteger( XML_id, 0 ); aModel.mnMax = rAttribs.getInteger( XML_id, 0 ); aModel.mbManual = rAttribs.getBool( XML_man, false ); setPageBreak( aModel, bRowBreak ); } void WorksheetFragment::importDrawing( const AttributeList& rAttribs ) { setDrawingPath( getFragmentPathFromRelId( rAttribs.getString( R_TOKEN( id ), OUString() ) ) ); } void WorksheetFragment::importLegacyDrawing( const AttributeList& rAttribs ) { setVmlDrawingPath( getFragmentPathFromRelId( rAttribs.getString( R_TOKEN( id ), OUString() ) ) ); } void WorksheetFragment::importOleObject( const AttributeList& rAttribs ) { ::oox::vml::OleObjectInfo aInfo; aInfo.setShapeId( rAttribs.getInteger( XML_shapeId, 0 ) ); OSL_ENSURE( rAttribs.hasAttribute( XML_link ) != rAttribs.hasAttribute( R_TOKEN( id ) ), "WorksheetFragment::importOleObject - OLE object must be either linked or embedded" ); aInfo.mbLinked = rAttribs.hasAttribute( XML_link ); if( aInfo.mbLinked ) aInfo.maTargetLink = getFormulaParser().importOleTargetLink( rAttribs.getString( XML_link, OUString() ) ); else if( rAttribs.hasAttribute( R_TOKEN( id ) ) ) importEmbeddedOleData( aInfo.maEmbeddedData, rAttribs.getString( R_TOKEN( id ), OUString() ) ); aInfo.maProgId = rAttribs.getString( XML_progId, OUString() ); aInfo.mbShowAsIcon = rAttribs.getToken( XML_dvAspect, XML_DVASPECT_CONTENT ) == XML_DVASPECT_ICON; aInfo.mbAutoUpdate = rAttribs.getToken( XML_oleUpdate, XML_OLEUPDATE_ONCALL ) == XML_OLEUPDATE_ALWAYS; aInfo.mbAutoLoad = rAttribs.getBool( XML_autoLoad, false ); getVmlDrawing().registerOleObject( aInfo ); } void WorksheetFragment::importControl( const AttributeList& rAttribs ) { ::oox::vml::ControlInfo aInfo; aInfo.setShapeId( rAttribs.getInteger( XML_shapeId, 0 ) ); aInfo.maFragmentPath = getFragmentPathFromRelId( rAttribs.getString( R_TOKEN( id ), OUString() ) ); aInfo.maName = rAttribs.getString( XML_name, OUString() ); getVmlDrawing().registerControl( aInfo ); } void WorksheetFragment::importDimension( SequenceInputStream& rStrm ) { BinRange aBinRange; aBinRange.read( rStrm ); CellRangeAddress aRange; getAddressConverter().convertToCellRangeUnchecked( aRange, aBinRange, getSheetIndex() ); /* BIFF12 stores the used area, if existing, or "A1" if the sheet is empty. In case of "A1", the dimension at the WorksheetHelper object will not be set. If the cell A1 exists, the used area will be updated while importing the cell. */ if( (aRange.EndColumn > 0) || (aRange.EndRow > 0) ) extendUsedArea( aRange ); } void WorksheetFragment::importSheetFormatPr( SequenceInputStream& rStrm ) { sal_Int32 nDefaultWidth; sal_uInt16 nBaseWidth, nDefaultHeight, nFlags; rStrm >> nDefaultWidth >> nBaseWidth >> nDefaultHeight >> nFlags; // base column with setBaseColumnWidth( nBaseWidth ); // default width is stored as 1/256th of a character in BIFF12, convert to entire character setDefaultColumnWidth( static_cast< double >( nDefaultWidth ) / 256.0 ); // row height is in twips in BIFF12, convert to points; equal flags in all BIFFs setDefaultRowSettings( nDefaultHeight / 20.0, getFlag( nFlags, BIFF_DEFROW_CUSTOMHEIGHT ), getFlag( nFlags, BIFF_DEFROW_HIDDEN ), getFlag( nFlags, BIFF_DEFROW_THICKTOP ), getFlag( nFlags, BIFF_DEFROW_THICKBOTTOM ) ); } void WorksheetFragment::importCol( SequenceInputStream& rStrm ) { ColumnModel aModel; sal_Int32 nWidth; sal_uInt16 nFlags; rStrm >> aModel.maRange.mnFirst >> aModel.maRange.mnLast >> nWidth >> aModel.mnXfId >> nFlags; // column indexes are 0-based in BIFF12, but ColumnModel expects 1-based ++aModel.maRange.mnFirst; ++aModel.maRange.mnLast; // width is stored as 1/256th of a character in BIFF12, convert to entire character aModel.mfWidth = static_cast< double >( nWidth ) / 256.0; // equal flags in all BIFFs aModel.mnLevel = extractValue< sal_Int32 >( nFlags, 8, 3 ); aModel.mbShowPhonetic = getFlag( nFlags, BIFF_COLINFO_SHOWPHONETIC ); aModel.mbHidden = getFlag( nFlags, BIFF_COLINFO_HIDDEN ); aModel.mbCollapsed = getFlag( nFlags, BIFF_COLINFO_COLLAPSED ); // set column properties in the current sheet setColumnModel( aModel ); } void WorksheetFragment::importMergeCell( SequenceInputStream& rStrm ) { BinRange aBinRange; rStrm >> aBinRange; CellRangeAddress aRange; if( getAddressConverter().convertToCellRange( aRange, aBinRange, getSheetIndex(), true, true ) ) getSheetData().setMergedRange( aRange ); } void WorksheetFragment::importHyperlink( SequenceInputStream& rStrm ) { BinRange aBinRange; rStrm >> aBinRange; HyperlinkModel aModel; if( getAddressConverter().convertToCellRange( aModel.maRange, aBinRange, getSheetIndex(), true, true ) ) { aModel.maTarget = getRelations().getExternalTargetFromRelId( BiffHelper::readString( rStrm ) ); rStrm >> aModel.maLocation >> aModel.maTooltip >> aModel.maDisplay; setHyperlink( aModel ); } } void WorksheetFragment::importBrk( SequenceInputStream& rStrm, bool bRowBreak ) { PageBreakModel aModel; sal_Int32 nManual; rStrm >> aModel.mnColRow >> aModel.mnMin >> aModel.mnMax >> nManual; aModel.mbManual = nManual != 0; setPageBreak( aModel, bRowBreak ); } void WorksheetFragment::importDrawing( SequenceInputStream& rStrm ) { setDrawingPath( getFragmentPathFromRelId( BiffHelper::readString( rStrm ) ) ); } void WorksheetFragment::importLegacyDrawing( SequenceInputStream& rStrm ) { setVmlDrawingPath( getFragmentPathFromRelId( BiffHelper::readString( rStrm ) ) ); } void WorksheetFragment::importOleObject( SequenceInputStream& rStrm ) { ::oox::vml::OleObjectInfo aInfo; sal_Int32 nAspect, nUpdateMode, nShapeId; sal_uInt16 nFlags; rStrm >> nAspect >> nUpdateMode >> nShapeId >> nFlags >> aInfo.maProgId; aInfo.mbLinked = getFlag( nFlags, BIFF12_OLEOBJECT_LINKED ); if( aInfo.mbLinked ) aInfo.maTargetLink = getFormulaParser().importOleTargetLink( rStrm ); else importEmbeddedOleData( aInfo.maEmbeddedData, BiffHelper::readString( rStrm ) ); aInfo.setShapeId( nShapeId ); aInfo.mbShowAsIcon = nAspect == BIFF12_OLEOBJECT_ICON; aInfo.mbAutoUpdate = nUpdateMode == BIFF12_OLEOBJECT_ALWAYS; aInfo.mbAutoLoad = getFlag( nFlags, BIFF12_OLEOBJECT_AUTOLOAD ); getVmlDrawing().registerOleObject( aInfo ); } void WorksheetFragment::importControl( SequenceInputStream& rStrm ) { ::oox::vml::ControlInfo aInfo; aInfo.setShapeId( rStrm.readInt32() ); aInfo.maFragmentPath = getFragmentPathFromRelId( BiffHelper::readString( rStrm ) ); rStrm >> aInfo.maName; getVmlDrawing().registerControl( aInfo ); } void WorksheetFragment::importEmbeddedOleData( StreamDataSequence& orEmbeddedData, const OUString& rRelId ) { OUString aFragmentPath = getFragmentPathFromRelId( rRelId ); if( aFragmentPath.getLength() > 0 ) getBaseFilter().importBinaryData( orEmbeddedData, aFragmentPath ); } // ============================================================================ BiffWorksheetFragment::BiffWorksheetFragment( const WorksheetHelper& rHelper, const BiffWorkbookFragmentBase& rParent ) : BiffWorksheetFragmentBase( rHelper, rParent ) { } BiffWorksheetFragment::~BiffWorksheetFragment() { } bool BiffWorksheetFragment::importFragment() { // initial processing in base class WorksheetHelper initializeWorksheetImport(); // create a SheetDataContext object that implements cell import BiffSheetDataContext aSheetData( *this ); WorkbookSettings& rWorkbookSett = getWorkbookSettings(); WorksheetSettings& rWorksheetSett = getWorksheetSettings(); SheetViewSettings& rSheetViewSett = getSheetViewSettings(); CondFormatBuffer& rCondFormats = getCondFormats(); PageSettings& rPageSett = getPageSettings(); BiffSheetDrawing& rDrawing = getBiffDrawing(); // process all record in this sheet fragment BiffInputStream& rStrm = getInputStream(); while( rStrm.startNextRecord() && (rStrm.getRecId() != BIFF_ID_EOF) ) { if( BiffHelper::isBofRecord( rStrm ) ) { // skip unknown embedded fragments (BOF/EOF blocks) skipFragment(); } else { // cache base stream position to detect if record is already processed sal_Int64 nStrmPos = rStrm.tellBase(); sal_uInt16 nRecId = rStrm.getRecId(); switch( nRecId ) { // records in all BIFF versions case BIFF_ID_BOTTOMMARGIN: rPageSett.importBottomMargin( rStrm ); break; case BIFF_ID_CALCCOUNT: rWorkbookSett.importCalcCount( rStrm ); break; case BIFF_ID_CALCMODE: rWorkbookSett.importCalcMode( rStrm ); break; case BIFF_ID_DEFCOLWIDTH: importDefColWidth( rStrm ); break; case BIFF_ID_DELTA: rWorkbookSett.importDelta( rStrm ); break; case BIFF2_ID_DIMENSION: importDimension( rStrm ); break; case BIFF3_ID_DIMENSION: importDimension( rStrm ); break; case BIFF_ID_FOOTER: rPageSett.importFooter( rStrm ); break; case BIFF_ID_HEADER: rPageSett.importHeader( rStrm ); break; case BIFF_ID_HORPAGEBREAKS: importPageBreaks( rStrm, true ); break; case BIFF_ID_ITERATION: rWorkbookSett.importIteration( rStrm ); break; case BIFF_ID_LEFTMARGIN: rPageSett.importLeftMargin( rStrm ); break; case BIFF_ID_NOTE: importNote( rStrm ); break; case BIFF_ID_PANE: rSheetViewSett.importPane( rStrm ); break; case BIFF_ID_PASSWORD: rWorksheetSett.importPassword( rStrm ); break; case BIFF_ID_PRINTGRIDLINES: rPageSett.importPrintGridLines( rStrm ); break; case BIFF_ID_PRINTHEADERS: rPageSett.importPrintHeaders( rStrm ); break; case BIFF_ID_PROTECT: rWorksheetSett.importProtect( rStrm ); break; case BIFF_ID_REFMODE: rWorkbookSett.importRefMode( rStrm ); break; case BIFF_ID_RIGHTMARGIN: rPageSett.importRightMargin( rStrm ); break; case BIFF_ID_SELECTION: rSheetViewSett.importSelection( rStrm ); break; case BIFF_ID_TOPMARGIN: rPageSett.importTopMargin( rStrm ); break; case BIFF_ID_VERPAGEBREAKS: importPageBreaks( rStrm, false ); break; // BIFF specific records default: switch( getBiff() ) { case BIFF2: switch( nRecId ) { case BIFF_ID_COLUMNDEFAULT: importColumnDefault( rStrm ); break; case BIFF_ID_COLWIDTH: importColWidth( rStrm ); break; case BIFF2_ID_DEFROWHEIGHT: importDefRowHeight( rStrm ); break; case BIFF2_ID_WINDOW2: rSheetViewSett.importWindow2( rStrm ); break; } break; case BIFF3: switch( nRecId ) { case BIFF_ID_COLINFO: importColInfo( rStrm ); break; case BIFF_ID_DEFCOLWIDTH: importDefColWidth( rStrm ); break; case BIFF3_ID_DEFROWHEIGHT: importDefRowHeight( rStrm ); break; case BIFF_ID_HCENTER: rPageSett.importHorCenter( rStrm ); break; case BIFF_ID_OBJ: rDrawing.importObj( rStrm ); break; case BIFF_ID_OBJECTPROTECT: rWorksheetSett.importObjectProtect( rStrm ); break; case BIFF_ID_SAVERECALC: rWorkbookSett.importSaveRecalc( rStrm ); break; case BIFF_ID_SHEETPR: rWorksheetSett.importSheetPr( rStrm ); break; case BIFF_ID_UNCALCED: rWorkbookSett.importUncalced( rStrm ); break; case BIFF_ID_VCENTER: rPageSett.importVerCenter( rStrm ); break; case BIFF3_ID_WINDOW2: rSheetViewSett.importWindow2( rStrm ); break; } break; case BIFF4: switch( nRecId ) { case BIFF_ID_COLINFO: importColInfo( rStrm ); break; case BIFF3_ID_DEFROWHEIGHT: importDefRowHeight( rStrm ); break; case BIFF_ID_HCENTER: rPageSett.importHorCenter( rStrm ); break; case BIFF_ID_OBJ: rDrawing.importObj( rStrm ); break; case BIFF_ID_OBJECTPROTECT: rWorksheetSett.importObjectProtect( rStrm ); break; case BIFF_ID_PAGESETUP: rPageSett.importPageSetup( rStrm ); break; case BIFF_ID_SAVERECALC: rWorkbookSett.importSaveRecalc( rStrm ); break; case BIFF_ID_SHEETPR: rWorksheetSett.importSheetPr( rStrm ); break; case BIFF_ID_STANDARDWIDTH: importStandardWidth( rStrm ); break; case BIFF_ID_UNCALCED: rWorkbookSett.importUncalced( rStrm ); break; case BIFF_ID_VCENTER: rPageSett.importVerCenter( rStrm ); break; case BIFF3_ID_WINDOW2: rSheetViewSett.importWindow2( rStrm ); break; } break; case BIFF5: switch( nRecId ) { case BIFF_ID_AUTOFILTER: importAutoFilter( rStrm ); break; case BIFF_ID_COLINFO: importColInfo( rStrm ); break; case BIFF3_ID_DEFROWHEIGHT: importDefRowHeight( rStrm ); break; case BIFF_ID_HCENTER: rPageSett.importHorCenter( rStrm ); break; case BIFF_ID_MERGEDCELLS: importMergedCells( rStrm ); break; // #i62300# also in BIFF5 case BIFF_ID_OBJ: rDrawing.importObj( rStrm ); break; case BIFF_ID_OBJECTPROTECT: rWorksheetSett.importObjectProtect( rStrm ); break; case BIFF_ID_PAGESETUP: rPageSett.importPageSetup( rStrm ); break; case BIFF_ID_PTDEFINITION: importPTDefinition( rStrm ); break; case BIFF_ID_SAVERECALC: rWorkbookSett.importSaveRecalc( rStrm ); break; case BIFF_ID_SCENPROTECT: rWorksheetSett.importScenProtect( rStrm ); break; case BIFF_ID_SCL: rSheetViewSett.importScl( rStrm ); break; case BIFF_ID_SHEETPR: rWorksheetSett.importSheetPr( rStrm ); break; case BIFF_ID_STANDARDWIDTH: importStandardWidth( rStrm ); break; case BIFF_ID_UNCALCED: rWorkbookSett.importUncalced( rStrm ); break; case BIFF_ID_VCENTER: rPageSett.importVerCenter( rStrm ); break; case BIFF3_ID_WINDOW2: rSheetViewSett.importWindow2( rStrm ); break; } break; case BIFF8: switch( nRecId ) { case BIFF_ID_AUTOFILTER: importAutoFilter( rStrm ); break; case BIFF_ID_CFHEADER: rCondFormats.importCfHeader( rStrm ); break; case BIFF_ID_CODENAME: rWorksheetSett.importCodeName( rStrm ); break; case BIFF_ID_COLINFO: importColInfo( rStrm ); break; case BIFF_ID_DATAVALIDATION: importDataValidation( rStrm ); break; case BIFF_ID_DATAVALIDATIONS: importDataValidations( rStrm ); break; case BIFF3_ID_DEFROWHEIGHT: importDefRowHeight( rStrm ); break; case BIFF_ID_HCENTER: rPageSett.importHorCenter( rStrm ); break; case BIFF_ID_HYPERLINK: importHyperlink( rStrm ); break; case BIFF_ID_LABELRANGES: importLabelRanges( rStrm ); break; case BIFF_ID_MERGEDCELLS: importMergedCells( rStrm ); break; case BIFF_ID_OBJ: rDrawing.importObj( rStrm ); break; case BIFF_ID_OBJECTPROTECT: rWorksheetSett.importObjectProtect( rStrm ); break; case BIFF_ID_PAGESETUP: rPageSett.importPageSetup( rStrm ); break; case BIFF_ID_PHONETICPR: rWorksheetSett.importPhoneticPr( rStrm ); break; case BIFF_ID_PICTURE: rPageSett.importPicture( rStrm ); break; case BIFF_ID_PTDEFINITION: importPTDefinition( rStrm ); break; case BIFF_ID_QUERYTABLE: importQueryTable( rStrm ); break; case BIFF_ID_SAVERECALC: rWorkbookSett.importSaveRecalc( rStrm ); break; case BIFF_ID_SCENARIOS: importScenarios( rStrm ); break; case BIFF_ID_SCENPROTECT: rWorksheetSett.importScenProtect( rStrm ); break; case BIFF_ID_SCL: rSheetViewSett.importScl( rStrm ); break; case BIFF_ID_SHEETEXT: rWorksheetSett.importSheetExt( rStrm ); break; case BIFF_ID_SHEETPR: rWorksheetSett.importSheetPr( rStrm ); break; case BIFF_ID_SHAREDFEATHEAD: importSharedFeatHead( rStrm ); break; case BIFF_ID_STANDARDWIDTH: importStandardWidth( rStrm ); break; case BIFF_ID_UNCALCED: rWorkbookSett.importUncalced( rStrm ); break; case BIFF_ID_VCENTER: rPageSett.importVerCenter( rStrm ); break; case BIFF3_ID_WINDOW2: rSheetViewSett.importWindow2( rStrm ); break; } break; case BIFF_UNKNOWN: break; } } // record not processed, try record context objects if( rStrm.tellBase() == nStrmPos ) { // first, try cell table records aSheetData.importRecord( rStrm ); // handle another open record context if( mxContext.get() ) { // if it was a cell table record, forget the other record context if( rStrm.tellBase() == nStrmPos ) mxContext->importRecord( rStrm ); else mxContext.reset(); } } } } // final processing in base class WorksheetHelper finalizeWorksheetImport(); return rStrm.getRecId() == BIFF_ID_EOF; } // private -------------------------------------------------------------------- void BiffWorksheetFragment::importAutoFilter( BiffInputStream& rStrm ) { mxContext.reset( new BiffAutoFilterContext( *this, getAutoFilters().createAutoFilter() ) ); mxContext->importRecord( rStrm ); } void BiffWorksheetFragment::importColInfo( BiffInputStream& rStrm ) { sal_uInt16 nFirstCol, nLastCol, nWidth, nXfId, nFlags; rStrm >> nFirstCol >> nLastCol >> nWidth >> nXfId >> nFlags; ColumnModel aModel; // column indexes are 0-based in BIFF, but ColumnModel expects 1-based aModel.maRange.mnFirst = static_cast< sal_Int32 >( nFirstCol ) + 1; aModel.maRange.mnLast = static_cast< sal_Int32 >( nLastCol ) + 1; // width is stored as 1/256th of a character in BIFF, convert to entire character aModel.mfWidth = static_cast< double >( nWidth ) / 256.0; aModel.mnXfId = nXfId; aModel.mnLevel = extractValue< sal_Int32 >( nFlags, 8, 3 ); aModel.mbShowPhonetic = getFlag( nFlags, BIFF_COLINFO_SHOWPHONETIC ); aModel.mbHidden = getFlag( nFlags, BIFF_COLINFO_HIDDEN ); aModel.mbCollapsed = getFlag( nFlags, BIFF_COLINFO_COLLAPSED ); // set column properties in the current sheet setColumnModel( aModel ); } void BiffWorksheetFragment::importColumnDefault( BiffInputStream& rStrm ) { sal_uInt16 nFirstCol, nLastCol, nXfId; rStrm >> nFirstCol >> nLastCol >> nXfId; setDefaultColumnFormat( nFirstCol, nLastCol, nXfId ); } void BiffWorksheetFragment::importColWidth( BiffInputStream& rStrm ) { sal_uInt8 nFirstCol, nLastCol; sal_uInt16 nWidth; rStrm >> nFirstCol >> nLastCol >> nWidth; ColumnModel aModel; // column indexes are 0-based in BIFF, but ColumnModel expects 1-based aModel.maRange.mnFirst = static_cast< sal_Int32 >( nFirstCol ) + 1; aModel.maRange.mnLast = static_cast< sal_Int32 >( nLastCol ) + 1; // width is stored as 1/256th of a character in BIFF, convert to entire character aModel.mfWidth = static_cast< double >( nWidth ) / 256.0; // set column properties in the current sheet setColumnModel( aModel ); } void BiffWorksheetFragment::importDefColWidth( BiffInputStream& rStrm ) { /* Stored as entire number of characters without padding pixels, which will be added in setBaseColumnWidth(). Call has no effect, if a width has already been set from the STANDARDWIDTH record. */ setBaseColumnWidth( rStrm.readuInt16() ); } void BiffWorksheetFragment::importDefRowHeight( BiffInputStream& rStrm ) { sal_uInt16 nFlags = BIFF_DEFROW_CUSTOMHEIGHT, nHeight; if( getBiff() != BIFF2 ) rStrm >> nFlags; rStrm >> nHeight; if( getBiff() == BIFF2 ) nHeight &= BIFF2_DEFROW_MASK; // row height is in twips in BIFF, convert to points setDefaultRowSettings( nHeight / 20.0, getFlag( nFlags, BIFF_DEFROW_CUSTOMHEIGHT ), getFlag( nFlags, BIFF_DEFROW_HIDDEN ), getFlag( nFlags, BIFF_DEFROW_THICKTOP ), getFlag( nFlags, BIFF_DEFROW_THICKBOTTOM ) ); } void BiffWorksheetFragment::importDataValidations( BiffInputStream& rStrm ) { sal_Int32 nObjId; rStrm.skip( 10 ); rStrm >> nObjId; //! TODO: invalidate object id in drawing object manager } namespace { OUString lclReadDataValMessage( BiffInputStream& rStrm ) { // empty strings are single NUL characters (string length is 1) OUString aMessage = rStrm.readUniString( true ); if( (aMessage.getLength() == 1) && (aMessage[ 0 ] == 0) ) aMessage = OUString(); return aMessage; } ApiTokenSequence lclReadDataValFormula( BiffInputStream& rStrm, FormulaParser& rParser ) { sal_uInt16 nFmlaSize = rStrm.readuInt16(); rStrm.skip( 2 ); return rParser.importFormula( CellAddress(), FORMULATYPE_VALIDATION, rStrm, &nFmlaSize ); } } // namespace void BiffWorksheetFragment::importDataValidation( BiffInputStream& rStrm ) { ValidationModel aModel; // flags sal_uInt32 nFlags; rStrm >> nFlags; aModel.setBiffType( extractValue< sal_uInt8 >( nFlags, 0, 4 ) ); aModel.setBiffOperator( extractValue< sal_uInt8 >( nFlags, 20, 4 ) ); aModel.setBiffErrorStyle( extractValue< sal_uInt8 >( nFlags, 4, 3 ) ); aModel.mbAllowBlank = getFlag( nFlags, BIFF_DATAVAL_ALLOWBLANK ); aModel.mbNoDropDown = getFlag( nFlags, BIFF_DATAVAL_NODROPDOWN ); aModel.mbShowInputMsg = getFlag( nFlags, BIFF_DATAVAL_SHOWINPUT ); aModel.mbShowErrorMsg = getFlag( nFlags, BIFF_DATAVAL_SHOWERROR ); // message strings aModel.maInputTitle = lclReadDataValMessage( rStrm ); aModel.maErrorTitle = lclReadDataValMessage( rStrm ); aModel.maInputMessage = lclReadDataValMessage( rStrm ); aModel.maErrorMessage = lclReadDataValMessage( rStrm ); // condition formula(s) FormulaParser& rParser = getFormulaParser(); aModel.maTokens1 = lclReadDataValFormula( rStrm, rParser ); aModel.maTokens2 = lclReadDataValFormula( rStrm, rParser ); // process string list of a list validation (convert to list of string tokens) if( (aModel.mnType == XML_list) && getFlag( nFlags, BIFF_DATAVAL_STRINGLIST ) ) rParser.convertStringToStringList( aModel.maTokens1, '\0', true ); // cell range list BinRangeList aRanges; rStrm >> aRanges; getAddressConverter().convertToCellRangeList( aModel.maRanges, aRanges, getSheetIndex(), true ); // set validation data setValidation( aModel ); } void BiffWorksheetFragment::importDimension( BiffInputStream& rStrm ) { // 32-bit row indexes in BIFF8 bool bInt32Rows = (rStrm.getRecId() == BIFF3_ID_DIMENSION) && (getBiff() == BIFF8); BinRange aBinRange; aBinRange.read( rStrm, true, bInt32Rows ); /* BIFF stores the used area with end column and end row increased by 1 (first unused column and row). */ if( (aBinRange.maFirst.mnCol < aBinRange.maLast.mnCol) && (aBinRange.maFirst.mnRow < aBinRange.maLast.mnRow) ) { // reduce range to used area --aBinRange.maLast.mnCol; --aBinRange.maLast.mnRow; CellRangeAddress aRange; getAddressConverter().convertToCellRangeUnchecked( aRange, aBinRange, getSheetIndex() ); extendUsedArea( aRange ); } } void BiffWorksheetFragment::importHyperlink( BiffInputStream& rStrm ) { HyperlinkModel aModel; // read cell range for the hyperlink BinRange aBiffRange; rStrm >> aBiffRange; // #i80006# Excel silently ignores invalid hi-byte of column index (TODO: everywhere?) aBiffRange.maFirst.mnCol &= 0xFF; aBiffRange.maLast.mnCol &= 0xFF; if( !getAddressConverter().convertToCellRange( aModel.maRange, aBiffRange, getSheetIndex(), true, true ) ) return; // try to read the StdHlink data if( !::oox::ole::OleHelper::importStdHlink( aModel, rStrm, true ) ) return; // try to read the optional following SCREENTIP record if( (rStrm.getNextRecId() == BIFF_ID_SCREENTIP) && rStrm.startNextRecord() ) { rStrm.skip( 2 ); // repeated record id // the cell range, again rStrm >> aBiffRange; CellRangeAddress aRange; if( getAddressConverter().convertToCellRange( aRange, aBiffRange, getSheetIndex(), true, true ) && (aRange.StartColumn == aModel.maRange.StartColumn) && (aRange.StartRow == aModel.maRange.StartRow) && (aRange.EndColumn == aModel.maRange.EndColumn) && (aRange.EndRow == aModel.maRange.EndRow) ) { /* This time, we have no string length, no flag field, and a null-terminated 16-bit character array. */ aModel.maTooltip = rStrm.readNulUnicodeArray(); } } // store the hyperlink settings setHyperlink( aModel ); } void BiffWorksheetFragment::importLabelRanges( BiffInputStream& rStrm ) { BinRangeList aBiffRowRanges, aBiffColRanges; rStrm >> aBiffRowRanges >> aBiffColRanges; ApiCellRangeList aColRanges, aRowRanges; getAddressConverter().convertToCellRangeList( aColRanges, aBiffColRanges, getSheetIndex(), true ); getAddressConverter().convertToCellRangeList( aRowRanges, aBiffRowRanges, getSheetIndex(), true ); setLabelRanges( aColRanges, aRowRanges ); } void BiffWorksheetFragment::importMergedCells( BiffInputStream& rStrm ) { BinRangeList aBiffRanges; rStrm >> aBiffRanges; ApiCellRangeList aRanges; getAddressConverter().convertToCellRangeList( aRanges, aBiffRanges, getSheetIndex(), true ); for( ApiCellRangeList::const_iterator aIt = aRanges.begin(), aEnd = aRanges.end(); aIt != aEnd; ++aIt ) getSheetData().setMergedRange( *aIt ); } void BiffWorksheetFragment::importNote( BiffInputStream& rStrm ) { getComments().createComment()->importNote( rStrm ); } void BiffWorksheetFragment::importPageBreaks( BiffInputStream& rStrm, bool bRowBreak ) { PageBreakModel aModel; aModel.mbManual = true; // only manual breaks stored in BIFF bool bBiff8 = getBiff() == BIFF8; // skip start/end columns or rows in BIFF8 sal_uInt16 nCount; rStrm >> nCount; for( sal_uInt16 nIndex = 0; !rStrm.isEof() && (nIndex < nCount); ++nIndex ) { aModel.mnColRow = rStrm.readuInt16(); setPageBreak( aModel, bRowBreak ); if( bBiff8 ) rStrm.skip( 4 ); } } void BiffWorksheetFragment::importPTDefinition( BiffInputStream& rStrm ) { mxContext.reset( new BiffPivotTableContext( *this ) ); mxContext->importRecord( rStrm ); } void BiffWorksheetFragment::importQueryTable( BiffInputStream& rStrm ) { mxContext.reset( new BiffQueryTableContext( *this ) ); mxContext->importRecord( rStrm ); } void BiffWorksheetFragment::importScenarios( BiffInputStream& rStrm ) { getScenarios().createSheetScenarios( getSheetIndex() ).importScenarios( rStrm ); } void BiffWorksheetFragment::importSharedFeatHead( BiffInputStream& rStrm ) { rStrm.skip( 12 ); sal_uInt16 nType = rStrm.readuInt16(); rStrm.skip( 5 ); switch( nType ) { case BIFF_SHRFEATHEAD_SHEETPROT: if( rStrm.getRemaining() >= 4 ) getWorksheetSettings().importSheetProtection( rStrm ); break; } } void BiffWorksheetFragment::importStandardWidth( BiffInputStream& rStrm ) { sal_uInt16 nWidth; rStrm >> nWidth; // width is stored as 1/256th of a character in BIFF, convert to entire character double fWidth = static_cast< double >( nWidth ) / 256.0; // set as default width, will override the width from DEFCOLWIDTH record setDefaultColumnWidth( fWidth ); } // ============================================================================ } // namespace xls } // namespace oox