/************************************************************** * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * *************************************************************/ // MARKER(update_precomp.py): autogen include statement, do not remove #include "precompiled_scfilt.hxx" #include "imp_op.hxx" #include #include "scitems.hxx" #include #include #include #include #include #include #include #include #include #include #include #include #include "docuno.hxx" #include "cell.hxx" #include "document.hxx" #include "rangenam.hxx" #include "compiler.hxx" #include "patattr.hxx" #include "attrib.hxx" #include "globstr.hrc" #include "global.hxx" #include "markdata.hxx" #include "olinetab.hxx" #include "stlsheet.hxx" #include "stlpool.hxx" #include "compiler.hxx" #include "viewopti.hxx" #include "docoptio.hxx" #include "scextopt.hxx" #include "editutil.hxx" #include "filtopt.hxx" #include "scerrors.hxx" #include "unonames.hxx" #include "paramisc.hxx" #include "postit.hxx" #include "fapihelper.hxx" #include "xltools.hxx" #include "xltable.hxx" #include "xlview.hxx" #include "xltracer.hxx" #include "xihelper.hxx" #include "xipage.hxx" #include "xiview.hxx" #include "xilink.hxx" #include "xiescher.hxx" #include "xicontent.hxx" #include "excimp8.hxx" #include "excform.hxx" #if defined( WNT ) #include #else #include #endif using namespace ::com::sun::star; const double ImportExcel::fExcToTwips = ( double ) TWIPS_PER_CHAR / 256.0; ImportTyp::ImportTyp( ScDocument* pDoc, CharSet eQ ) { eQuellChar = eQ; pD = pDoc; } ImportTyp::~ImportTyp() { } FltError ImportTyp::Read() { return eERR_INTERN; } ImportExcel::ImportExcel( XclImpRootData& rImpData, SvStream& rStrm ): ImportTyp( &rImpData.mrDoc, rImpData.meTextEnc ), XclImpRoot( rImpData ), maStrm( rStrm, GetRoot() ), aIn( maStrm ), maScOleSize( ScAddress::INITIALIZE_INVALID ), mnLastRefIdx( 0 ), mnIxfeIndex( 0 ), mbBiff2HasXfs( false ), mbBiff2HasXfsValid( false ) { nBdshtTab = 0; // Root-Daten fuellen - nach new's ohne Root als Parameter pExcRoot = &GetOldRoot(); pExcRoot->pIR = this; // ExcRoot -> XclImpRoot pExcRoot->eDateiTyp = BiffX; pExcRoot->pExtSheetBuff = new ExtSheetBuffer( pExcRoot ); //&aExtSheetBuff; pExcRoot->pShrfmlaBuff = new ShrfmlaBuffer( pExcRoot ); //&aShrfrmlaBuff; pExcRoot->pExtNameBuff = new ExtNameBuff ( *this ); pExtNameBuff = new NameBuffer( pExcRoot ); //#94039# prevent empty rootdata pExtNameBuff->SetBase( 1 ); pOutlineListBuffer = new XclImpOutlineListBuffer( ); // ab Biff8 pFormConv = pExcRoot->pFmlaConverter = new ExcelToSc( GetRoot() ); bTabTruncated = sal_False; // Excel-Dokument per Default auf 31.12.1899, entspricht Excel-Einstellungen mit 1.1.1900 ScDocOptions aOpt = pD->GetDocOptions(); aOpt.SetDate( 30, 12, 1899 ); pD->SetDocOptions( aOpt ); pD->GetFormatTable()->ChangeNullDate( 30, 12, 1899 ); ScDocOptions aDocOpt( pD->GetDocOptions() ); aDocOpt.SetIgnoreCase( sal_True ); // always in Excel aDocOpt.SetFormulaRegexEnabled( sal_False ); // regular expressions? what's that? aDocOpt.SetLookUpColRowNames( sal_False ); // default: no natural language refs pD->SetDocOptions( aDocOpt ); } ImportExcel::~ImportExcel( void ) { GetDoc().SetSrcCharSet( GetTextEncoding() ); delete pExtNameBuff; delete pOutlineListBuffer; delete pFormConv; } void ImportExcel::ReadFileSharing() { sal_uInt16 nRecommendReadOnly, nPasswordHash; maStrm >> nRecommendReadOnly >> nPasswordHash; if( (nRecommendReadOnly != 0) || (nPasswordHash != 0) ) { if( SfxItemSet* pItemSet = GetMedium().GetItemSet() ) pItemSet->Put( SfxBoolItem( SID_DOC_READONLY, sal_True ) ); if( SfxObjectShell* pShell = GetDocShell() ) { if( nRecommendReadOnly != 0 ) pShell->SetLoadReadonly( sal_True ); if( nPasswordHash != 0 ) pShell->SetModifyPasswordHash( nPasswordHash ); } } } sal_uInt16 ImportExcel::ReadXFIndex( const ScAddress& rScPos, bool bBiff2 ) { sal_uInt16 nXFIdx = 0; if( bBiff2 ) { /* #i71453# On first call, check if the file contains XF records (by trying to access the first XF with index 0). If there are no XFs, the explicit formatting information contained in each cell record will be used instead. */ if( !mbBiff2HasXfsValid ) { mbBiff2HasXfsValid = true; mbBiff2HasXfs = GetXFBuffer().GetXF( 0 ) != 0; } // read formatting information (includes the XF identifier) sal_uInt8 nFlags1, nFlags2, nFlags3; maStrm >> nFlags1 >> nFlags2 >> nFlags3; /* If the file contains XFs, extract and set the XF identifier, otherwise get the explicit formatting. */ if( mbBiff2HasXfs ) { nXFIdx = ::extract_value< sal_uInt16 >( nFlags1, 0, 6 ); /* If the identifier is equal to 63, then the real identifier is contained in the preceding IXFE record (stored in mnBiff2XfId). */ if( nXFIdx == 63 ) nXFIdx = mnIxfeIndex; } else { /* Let the XclImpXF class do the conversion of the imported formatting. The XF buffer is empty, therefore will not do any conversion based on the XF index later on. */ XclImpXF::ApplyPatternForBiff2CellFormat( GetRoot(), rScPos, nFlags1, nFlags2, nFlags3 ); } } else aIn >> nXFIdx; return nXFIdx; } void ImportExcel::ReadDimensions() { XclRange aXclUsedArea( ScAddress::UNINITIALIZED ); if( (maStrm.GetRecId() == EXC_ID2_DIMENSIONS) || (GetBiff() <= EXC_BIFF5) ) { maStrm >> aXclUsedArea; if( (aXclUsedArea.GetColCount() > 1) && (aXclUsedArea.GetRowCount() > 1) ) { // Excel stores first unused row/column index --aXclUsedArea.maLast.mnCol; --aXclUsedArea.maLast.mnRow; // create the Calc range SCTAB nScTab = GetCurrScTab(); ScRange& rScUsedArea = GetExtDocOptions().GetOrCreateTabSettings( nScTab ).maUsedArea; GetAddressConverter().ConvertRange( rScUsedArea, aXclUsedArea, nScTab, nScTab, false ); // if any error occurs in ConvertRange(), rScUsedArea keeps untouched } } else { sal_uInt32 nXclRow1, nXclRow2; maStrm >> nXclRow1 >> nXclRow2 >> aXclUsedArea.maFirst.mnCol >> aXclUsedArea.maLast.mnCol; if( (nXclRow1 < nXclRow2) && (aXclUsedArea.GetColCount() > 1) && (nXclRow1 <= static_cast< sal_uInt32 >( GetScMaxPos().Row() )) ) { // Excel stores first unused row/column index --nXclRow2; --aXclUsedArea.maLast.mnCol; // convert row indexes to 16-bit values aXclUsedArea.maFirst.mnRow = static_cast< sal_uInt16 >( nXclRow1 ); aXclUsedArea.maLast.mnRow = limit_cast< sal_uInt16 >( nXclRow2, aXclUsedArea.maFirst.mnRow, SAL_MAX_UINT16 ); // create the Calc range SCTAB nScTab = GetCurrScTab(); ScRange& rScUsedArea = GetExtDocOptions().GetOrCreateTabSettings( nScTab ).maUsedArea; GetAddressConverter().ConvertRange( rScUsedArea, aXclUsedArea, nScTab, nScTab, false ); // if any error occurs in ConvertRange(), rScUsedArea keeps untouched } } } void ImportExcel::ReadBlank() { XclAddress aXclPos; aIn >> aXclPos; ScAddress aScPos( ScAddress::UNINITIALIZED ); if( GetAddressConverter().ConvertAddress( aScPos, aXclPos, GetCurrScTab(), true ) ) { sal_uInt16 nXFIdx = ReadXFIndex( aScPos, maStrm.GetRecId() == EXC_ID2_BLANK ); GetXFRangeBuffer().SetBlankXF( aScPos, nXFIdx ); } } void ImportExcel::ReadInteger() { XclAddress aXclPos; maStrm >> aXclPos; ScAddress aScPos( ScAddress::UNINITIALIZED ); if( GetAddressConverter().ConvertAddress( aScPos, aXclPos, GetCurrScTab(), true ) ) { sal_uInt16 nXFIdx = ReadXFIndex( aScPos, true ); sal_uInt16 nValue; maStrm >> nValue; GetXFRangeBuffer().SetXF( aScPos, nXFIdx ); GetDoc().PutCell( aScPos, new ScValueCell( nValue ) ); } } void ImportExcel::ReadNumber() { XclAddress aXclPos; maStrm >> aXclPos; ScAddress aScPos( ScAddress::UNINITIALIZED ); if( GetAddressConverter().ConvertAddress( aScPos, aXclPos, GetCurrScTab(), true ) ) { sal_uInt16 nXFIdx = ReadXFIndex( aScPos, maStrm.GetRecId() == EXC_ID2_NUMBER ); double fValue; maStrm >> fValue; GetXFRangeBuffer().SetXF( aScPos, nXFIdx ); GetDoc().PutCell( aScPos, new ScValueCell( fValue ) ); } } void ImportExcel::ReadLabel() { XclAddress aXclPos; maStrm >> aXclPos; ScAddress aScPos( ScAddress::UNINITIALIZED ); if( GetAddressConverter().ConvertAddress( aScPos, aXclPos, GetCurrScTab(), true ) ) { /* Record ID BIFF XF type String type 0x0004 2-7 3 byte 8-bit length, byte string 0x0004 8 3 byte 16-bit length, unicode string 0x0204 2-7 2 byte 16-bit length, byte string 0x0204 8 2 byte 16-bit length, unicode string */ bool bBiff2 = maStrm.GetRecId() == EXC_ID2_LABEL; sal_uInt16 nXFIdx = ReadXFIndex( aScPos, bBiff2 ); XclStrFlags nFlags = (bBiff2 && (GetBiff() <= EXC_BIFF5)) ? EXC_STR_8BITLENGTH : EXC_STR_DEFAULT; XclImpString aString; // #i63105# use text encoding from FONT record rtl_TextEncoding eOldTextEnc = GetTextEncoding(); if( const XclImpFont* pFont = GetXFBuffer().GetFont( nXFIdx ) ) SetTextEncoding( pFont->GetFontEncoding() ); aString.Read( maStrm, nFlags ); SetTextEncoding( eOldTextEnc ); GetXFRangeBuffer().SetXF( aScPos, nXFIdx ); if( ScBaseCell* pCell = XclImpStringHelper::CreateCell( GetRoot(), aString, nXFIdx ) ) GetDoc().PutCell( aScPos, pCell ); } } void ImportExcel::ReadBoolErr() { XclAddress aXclPos; maStrm >> aXclPos; ScAddress aScPos( ScAddress::UNINITIALIZED ); if( GetAddressConverter().ConvertAddress( aScPos, aXclPos, GetCurrScTab(), true ) ) { sal_uInt16 nXFIdx = ReadXFIndex( aScPos, maStrm.GetRecId() == EXC_ID2_BOOLERR ); sal_uInt8 nValue, nType; maStrm >> nValue >> nType; if( nType == EXC_BOOLERR_BOOL ) GetXFRangeBuffer().SetBoolXF( aScPos, nXFIdx ); else GetXFRangeBuffer().SetXF( aScPos, nXFIdx ); double fValue; const ScTokenArray* pScTokArr = ErrorToFormula( nType, nValue, fValue ); ScFormulaCell* pCell = new ScFormulaCell( pD, aScPos, pScTokArr ); pCell->SetHybridDouble( fValue ); GetDoc().PutCell( aScPos, pCell ); } } void ImportExcel::ReadRk() { XclAddress aXclPos; maStrm >> aXclPos; ScAddress aScPos( ScAddress::UNINITIALIZED ); if( GetAddressConverter().ConvertAddress( aScPos, aXclPos, GetCurrScTab(), true ) ) { sal_uInt16 nXFIdx = ReadXFIndex( aScPos, false ); sal_Int32 nRk; maStrm >> nRk; GetXFRangeBuffer().SetXF( aScPos, nXFIdx ); GetDoc().PutCell( aScPos, new ScValueCell( XclTools::GetDoubleFromRK( nRk ) ) ); } } void ImportExcel::Window1() { GetDocViewSettings().ReadWindow1( maStrm ); } void ImportExcel::Row25( void ) { sal_uInt16 nRow, nRowHeight; aIn >> nRow; aIn.Ignore( 4 ); // Mic und Mac ueberspringen if( ValidRow( nRow ) ) { aIn >> nRowHeight; // direkt in Twips angegeben aIn.Ignore( 2 ); if( GetBiff() == EXC_BIFF2 ) {// -------------------- BIFF2 pColRowBuff->SetHeight( nRow, nRowHeight ); } else {// -------------------- BIFF5 sal_uInt16 nGrbit; aIn.Ignore( 2 ); // reserved aIn >> nGrbit; sal_uInt8 nLevel = ::extract_value< sal_uInt8 >( nGrbit, 0, 3 ); pRowOutlineBuff->SetLevel( nRow, nLevel, ::get_flag( nGrbit, EXC_ROW_COLLAPSED ), ::get_flag( nGrbit, EXC_ROW_HIDDEN ) ); pColRowBuff->SetRowSettings( nRow, nRowHeight, nGrbit ); } } } void ImportExcel::Bof2( void ) { sal_uInt16 nSubType; maStrm.DisableDecryption(); maStrm.Ignore( 2 ); maStrm >> nSubType; if( nSubType == 0x0020 ) // Chart pExcRoot->eDateiTyp = Biff2C; else if( nSubType == 0x0040 ) // Macro pExcRoot->eDateiTyp = Biff2M; else // #i51490# Excel interprets invalid indexes as worksheet pExcRoot->eDateiTyp = Biff2; } void ImportExcel::Eof( void ) { // POST: darf nur nach einer GUELTIGEN Tabelle gerufen werden! EndSheet(); IncCurrScTab(); } void ImportExcel::SheetPassword( void ) { if (GetRoot().GetBiff() != EXC_BIFF8) return; GetRoot().GetSheetProtectBuffer().ReadPasswordHash( aIn, GetCurrScTab() ); } void ImportExcel::Externsheet( void ) { String aUrl, aTabName; bool bSameWorkBook; String aEncodedUrl( aIn.ReadByteString( false ) ); XclImpUrlHelper::DecodeUrl( aUrl, aTabName, bSameWorkBook, *pExcRoot->pIR, aEncodedUrl ); mnLastRefIdx = pExcRoot->pExtSheetBuff->Add( aUrl, aTabName, bSameWorkBook ); } void ImportExcel:: WinProtection( void ) { if (GetRoot().GetBiff() != EXC_BIFF8) return; GetRoot().GetDocProtectBuffer().ReadWinProtect( aIn ); } void ImportExcel::Columndefault( void ) {// Default Cell Attributes sal_uInt16 nColMic, nColMac; sal_uInt8 nOpt0; aIn >> nColMic >> nColMac; DBG_ASSERT( aIn.GetRecLeft() == (sal_Size)(nColMac - nColMic) * 3 + 2, "ImportExcel::Columndefault - wrong record size" ); nColMac--; if( nColMac > MAXCOL ) nColMac = static_cast(MAXCOL); for( sal_uInt16 nCol = nColMic ; nCol <= nColMac ; nCol++ ) { aIn >> nOpt0; aIn.Ignore( 2 ); // nur 0. Attribut-Byte benutzt if( nOpt0 & 0x80 ) // Col hidden? pColRowBuff->HideCol( nCol ); } } void ImportExcel::Array25( void ) { sal_uInt16 nFirstRow, nLastRow, nFormLen; sal_uInt8 nFirstCol, nLastCol; aIn >> nFirstRow >> nLastRow >> nFirstCol >> nLastCol; if( GetBiff() == EXC_BIFF2 ) {// BIFF2 aIn.Ignore( 1 ); nFormLen = aIn.ReaduInt8(); } else {// BIFF5 aIn.Ignore( 6 ); aIn >> nFormLen; } if( ValidColRow( nLastCol, nLastRow ) ) { // jetzt steht Lesemarke auf Formel, Laenge in nFormLen const ScTokenArray* pErgebnis; pFormConv->Reset( ScAddress( static_cast(nFirstCol), static_cast(nFirstRow), GetCurrScTab() ) ); pFormConv->Convert( pErgebnis, maStrm, nFormLen, true, FT_CellFormula); DBG_ASSERT( pErgebnis, "*ImportExcel::Array25(): ScTokenArray ist NULL!" ); ScMarkData aMarkData; aMarkData.SelectOneTable( GetCurrScTab() ); pD->InsertMatrixFormula( static_cast(nFirstCol), static_cast(nFirstRow), static_cast(nLastCol), static_cast(nLastRow), aMarkData, EMPTY_STRING, pErgebnis ); } } void ImportExcel::Rec1904( void ) { sal_uInt16 n1904; aIn >> n1904; if( n1904 ) {// 1904 date system ScDocOptions aOpt = pD->GetDocOptions(); aOpt.SetDate( 1, 1, 1904 ); pD->SetDocOptions( aOpt ); pD->GetFormatTable()->ChangeNullDate( 1, 1, 1904 ); } } void ImportExcel::Externname25( void ) { sal_uInt32 nRes; sal_uInt16 nOpt; aIn >> nOpt >> nRes; String aName( aIn.ReadByteString( sal_False ) ); if( ( nOpt & 0x0001 ) || ( ( nOpt & 0xFFFE ) == 0x0000 ) ) {// external name ScfTools::ConvertToScDefinedName( aName ); pExcRoot->pExtNameBuff->AddName( aName, mnLastRefIdx ); } else if( nOpt & 0x0010 ) {// ole link pExcRoot->pExtNameBuff->AddOLE( aName, mnLastRefIdx, nRes ); // nRes is storage ID } else {// dde link pExcRoot->pExtNameBuff->AddDDE( aName, mnLastRefIdx ); } } void ImportExcel::Colwidth( void ) {// Column Width sal_uInt8 nColFirst, nColLast; sal_uInt16 nColWidth; aIn >> nColFirst >> nColLast >> nColWidth; //! TODO: add a check for the unlikely case of changed MAXCOL (-> XclImpAddressConverter) // if( nColLast > MAXCOL ) // nColLast = static_cast(MAXCOL); sal_uInt16 nScWidth = XclTools::GetScColumnWidth( nColWidth, GetCharWidth() ); pColRowBuff->SetWidthRange( nColFirst, nColLast, nScWidth ); } void ImportExcel::Defrowheight2( void ) { sal_uInt16 nDefHeight; maStrm >> nDefHeight; nDefHeight &= 0x7FFF; pColRowBuff->SetDefHeight( nDefHeight, EXC_DEFROW_UNSYNCED ); } void ImportExcel::SheetProtect( void ) { if (GetRoot().GetBiff() != EXC_BIFF8) return; GetRoot().GetSheetProtectBuffer().ReadProtect( aIn, GetCurrScTab() ); } void ImportExcel::DocProtect( void ) { if (GetRoot().GetBiff() != EXC_BIFF8) return; GetRoot().GetDocProtectBuffer().ReadDocProtect( aIn ); } void ImportExcel::DocPasssword( void ) { if (GetRoot().GetBiff() != EXC_BIFF8) return; GetRoot().GetDocProtectBuffer().ReadPasswordHash( aIn ); } void ImportExcel::Codepage( void ) { SetCodePage( maStrm.ReaduInt16() ); } void ImportExcel::Ixfe( void ) { maStrm >> mnIxfeIndex; } void ImportExcel::DefColWidth( void ) { // stored as entire characters -> convert to 1/256 of characters (as in COLINFO) double fDefWidth = 256.0 * maStrm.ReaduInt16(); // #i3006# additional space for default width - Excel adds space depending on font size long nFontHt = GetFontBuffer().GetAppFontData().mnHeight; fDefWidth += XclTools::GetXclDefColWidthCorrection( nFontHt ); sal_uInt16 nScWidth = XclTools::GetScColumnWidth( limit_cast< sal_uInt16 >( fDefWidth ), GetCharWidth() ); pColRowBuff->SetDefWidth( nScWidth ); } void ImportExcel::Builtinfmtcnt( void ) { } void ImportExcel::Colinfo( void ) {// Column Formatting Information sal_uInt16 nColFirst, nColLast, nColWidth, nXF; sal_uInt16 nOpt; aIn >> nColFirst >> nColLast >> nColWidth >> nXF >> nOpt; if( nColFirst > MAXCOL ) return; if( nColLast > MAXCOL ) nColLast = static_cast(MAXCOL); bool bHidden = ::get_flag( nOpt, EXC_COLINFO_HIDDEN ); bool bCollapsed = ::get_flag( nOpt, EXC_COLINFO_COLLAPSED ); sal_uInt8 nLevel = ::extract_value< sal_uInt8 >( nOpt, 8, 3 ); pColOutlineBuff->SetLevelRange( nColFirst, nColLast, nLevel, bCollapsed, bHidden ); if( bHidden ) pColRowBuff->HideColRange( nColFirst, nColLast ); sal_uInt16 nScWidth = XclTools::GetScColumnWidth( nColWidth, GetCharWidth() ); pColRowBuff->SetWidthRange( nColFirst, nColLast, nScWidth ); pColRowBuff->SetDefaultXF( nColFirst, nColLast, nXF ); } void ImportExcel::Wsbool( void ) { sal_uInt16 nFlags; aIn >> nFlags; pRowOutlineBuff->SetButtonMode( ::get_flag( nFlags, EXC_WSBOOL_ROWBELOW ) ); pColOutlineBuff->SetButtonMode( ::get_flag( nFlags, EXC_WSBOOL_COLBELOW ) ); GetPageSettings().SetFitToPages( ::get_flag( nFlags, EXC_WSBOOL_FITTOPAGE ) ); } void ImportExcel::Boundsheet( void ) { sal_uInt16 nGrbit = 0; if( GetBiff() == EXC_BIFF5 ) { aIn.DisableDecryption(); maSheetOffsets.push_back( aIn.ReaduInt32() ); aIn.EnableDecryption(); aIn >> nGrbit; } String aName( aIn.ReadByteString( sal_False ) ); SCTAB nScTab = static_cast< SCTAB >( nBdshtTab ); if( nScTab > 0 ) { DBG_ASSERT( !pD->HasTable( nScTab ), "ImportExcel::Boundsheet - sheet exists already" ); pD->MakeTable( nScTab ); } if( ( nGrbit & 0x0001 ) || ( nGrbit & 0x0002 ) ) pD->SetVisible( nScTab, sal_False ); if( !pD->RenameTab( nScTab, aName ) ) { pD->CreateValidTabName( aName ); pD->RenameTab( nScTab, aName ); } nBdshtTab++; } void ImportExcel::Country( void ) { sal_uInt16 nUICountry, nDocCountry; maStrm >> nUICountry >> nDocCountry; // Store system language in XclRoot LanguageType eLanguage = ::msfilter::ConvertCountryToLanguage( static_cast< ::msfilter::CountryId >( nDocCountry ) ); if( eLanguage != LANGUAGE_DONTKNOW ) SetDocLanguage( eLanguage ); // Set Excel UI language in add-in name translator eLanguage = ::msfilter::ConvertCountryToLanguage( static_cast< ::msfilter::CountryId >( nUICountry ) ); if( eLanguage != LANGUAGE_DONTKNOW ) SetUILanguage( eLanguage ); } void ImportExcel::ReadUsesElfs() { if( maStrm.ReaduInt16() != 0 ) { ScDocOptions aDocOpt = GetDoc().GetDocOptions(); aDocOpt.SetLookUpColRowNames( sal_True ); GetDoc().SetDocOptions( aDocOpt ); } } void ImportExcel::Hideobj( void ) { sal_uInt16 nHide; ScVObjMode eOle, eChart, eDraw; aIn >> nHide; ScViewOptions aOpts( pD->GetViewOptions() ); switch( nHide ) { case 1: // Placeholders eOle = VOBJ_MODE_SHOW; // in Excel 97 werden nur Charts als Platzhalter angezeigt eChart = VOBJ_MODE_SHOW; //#i80528# VOBJ_MODE_DUMMY replaced by VOBJ_MODE_SHOW now eDraw = VOBJ_MODE_SHOW; break; case 2: // Hide all eOle = VOBJ_MODE_HIDE; eChart = VOBJ_MODE_HIDE; eDraw = VOBJ_MODE_HIDE; break; default: // Show all eOle = VOBJ_MODE_SHOW; eChart = VOBJ_MODE_SHOW; eDraw = VOBJ_MODE_SHOW; break; } aOpts.SetObjMode( VOBJ_TYPE_OLE, eOle ); aOpts.SetObjMode( VOBJ_TYPE_CHART, eChart ); aOpts.SetObjMode( VOBJ_TYPE_DRAW, eDraw ); pD->SetViewOptions( aOpts ); } void ImportExcel::Bundleheader( void ) { } void ImportExcel::Standardwidth( void ) { sal_uInt16 nScWidth = XclTools::GetScColumnWidth( maStrm.ReaduInt16(), GetCharWidth() ); pColRowBuff->SetDefWidth( nScWidth, sal_True ); } void ImportExcel::Shrfmla( void ) { sal_uInt16 nFirstRow, nLastRow, nLenExpr; sal_uInt8 nFirstCol, nLastCol; aIn >> nFirstRow >> nLastRow >> nFirstCol >> nLastCol; aIn.Ignore( 2 ); aIn >> nLenExpr; // jetzt steht Lesemarke an der Formel const ScTokenArray* pErgebnis; pFormConv->Reset(); pFormConv->Convert( pErgebnis, maStrm, nLenExpr, true, FT_SharedFormula ); DBG_ASSERT( pErgebnis, "+ImportExcel::Shrfmla(): ScTokenArray ist NULL!" ); pExcRoot->pShrfmlaBuff->Store( ScRange( static_cast(nFirstCol), static_cast(nFirstRow), GetCurrScTab(), static_cast(nLastCol), static_cast(nLastRow), GetCurrScTab()), *pErgebnis ); } void ImportExcel::Mulrk( void ) { XclAddress aXclPos; sal_uInt16 nXF; sal_Int32 nRkNum; aIn >> aXclPos; for( XclAddress aCurrXclPos( aXclPos ); (aXclPos.mnCol <= aCurrXclPos.mnCol) && (aIn.GetRecLeft() > 2); ++aCurrXclPos.mnCol ) { aIn >> nXF >> nRkNum; ScAddress aScPos( ScAddress::UNINITIALIZED ); if( GetAddressConverter().ConvertAddress( aScPos, aCurrXclPos, GetCurrScTab(), true ) ) { GetXFRangeBuffer().SetXF( aScPos, nXF ); GetDoc().PutCell( aScPos, new ScValueCell( XclTools::GetDoubleFromRK( nRkNum ) ) ); } } } void ImportExcel::Mulblank( void ) { XclAddress aXclPos; sal_uInt16 nXF; aIn >> aXclPos; for( XclAddress aCurrXclPos( aXclPos ); (aXclPos.mnCol <= aCurrXclPos.mnCol) && (aIn.GetRecLeft() > 2); ++aCurrXclPos.mnCol ) { aIn >> nXF; ScAddress aScPos( ScAddress::UNINITIALIZED ); if( GetAddressConverter().ConvertAddress( aScPos, aCurrXclPos, GetCurrScTab(), true ) ) GetXFRangeBuffer().SetBlankXF( aScPos, nXF ); } } void ImportExcel::Rstring( void ) { XclAddress aXclPos; sal_uInt16 nXFIdx; aIn >> aXclPos >> nXFIdx; ScAddress aScPos( ScAddress::UNINITIALIZED ); if( GetAddressConverter().ConvertAddress( aScPos, aXclPos, GetCurrScTab(), true ) ) { // unformatted Unicode string with separate formatting information XclImpString aString; // #i63105# use text encoding from FONT record rtl_TextEncoding eOldTextEnc = GetTextEncoding(); if( const XclImpFont* pFont = GetXFBuffer().GetFont( nXFIdx ) ) SetTextEncoding( pFont->GetFontEncoding() ); aString.Read( maStrm ); SetTextEncoding( eOldTextEnc ); // character formatting runs if( !aString.IsRich() ) aString.ReadFormats( maStrm ); GetXFRangeBuffer().SetXF( aScPos, nXFIdx ); if( ScBaseCell* pCell = XclImpStringHelper::CreateCell( *this, aString, nXFIdx ) ) GetDoc().PutCell( aScPos, pCell ); } } void ImportExcel::Cellmerging() { XclImpAddressConverter& rAddrConv = GetAddressConverter(); SCTAB nScTab = GetCurrScTab(); sal_uInt16 nCount; maStrm >> nCount; for( sal_uInt16 nIdx = 0; (nIdx < nCount) && (maStrm.GetRecLeft() >= 8); ++nIdx ) { XclRange aXclRange; maStrm >> aXclRange; // 16-bit rows and columns ScRange aScRange( ScAddress::UNINITIALIZED ); if( rAddrConv.ConvertRange( aScRange, aXclRange, nScTab, nScTab, true ) ) GetXFRangeBuffer().SetMerge( aScRange.aStart.Col(), aScRange.aStart.Row(), aScRange.aEnd.Col(), aScRange.aEnd.Row() ); } } void ImportExcel::Olesize( void ) { XclRange aXclOleSize( ScAddress::UNINITIALIZED ); maStrm.Ignore( 2 ); aXclOleSize.Read( maStrm, false ); SCTAB nScTab = GetCurrScTab(); GetAddressConverter().ConvertRange( maScOleSize, aXclOleSize, nScTab, nScTab, false ); } void ImportExcel::Row34( void ) { sal_uInt16 nRow, nRowHeight, nGrbit, nXF; aIn >> nRow; aIn.Ignore( 4 ); // Mic und Mac ueberspringen SCROW nScRow = static_cast< SCROW >( nRow ); if( ValidRow( nScRow ) ) { aIn >> nRowHeight; // direkt in Twips angegeben aIn.Ignore( 4 ); aIn >> nGrbit >> nXF; sal_uInt8 nLevel = ::extract_value< sal_uInt8 >( nGrbit, 0, 3 ); pRowOutlineBuff->SetLevel( nScRow, nLevel, ::get_flag( nGrbit, EXC_ROW_COLLAPSED ), ::get_flag( nGrbit, EXC_ROW_HIDDEN ) ); pColRowBuff->SetRowSettings( nScRow, nRowHeight, nGrbit ); if( nGrbit & EXC_ROW_USEDEFXF ) GetXFRangeBuffer().SetRowDefXF( nScRow, nXF & EXC_ROW_XFMASK ); } } void ImportExcel::Bof3( void ) { sal_uInt16 nSubType; maStrm.DisableDecryption(); maStrm.Ignore( 2 ); maStrm >> nSubType; DBG_ASSERT( nSubType != 0x0100, "*ImportExcel::Bof3(): Biff3 als Workbook?!" ); if( nSubType == 0x0100 ) // Book pExcRoot->eDateiTyp = Biff3W; else if( nSubType == 0x0020 ) // Chart pExcRoot->eDateiTyp = Biff3C; else if( nSubType == 0x0040 ) // Macro pExcRoot->eDateiTyp = Biff3M; else // #i51490# Excel interprets invalid indexes as worksheet pExcRoot->eDateiTyp = Biff3; } void ImportExcel::Array34( void ) { sal_uInt16 nFirstRow, nLastRow, nFormLen; sal_uInt8 nFirstCol, nLastCol; aIn >> nFirstRow >> nLastRow >> nFirstCol >> nLastCol; aIn.Ignore( (GetBiff() >= EXC_BIFF5) ? 6 : 2 ); aIn >> nFormLen; if( ValidColRow( nLastCol, nLastRow ) ) { // jetzt steht Lesemarke auf Formel, Laenge in nFormLen const ScTokenArray* pErgebnis; pFormConv->Reset( ScAddress( static_cast(nFirstCol), static_cast(nFirstRow), GetCurrScTab() ) ); pFormConv->Convert( pErgebnis, maStrm, nFormLen, true, FT_CellFormula); DBG_ASSERT( pErgebnis, "+ImportExcel::Array34(): ScTokenArray ist NULL!" ); ScMarkData aMarkData; aMarkData.SelectOneTable( GetCurrScTab() ); pD->InsertMatrixFormula( static_cast(nFirstCol), static_cast(nFirstRow), static_cast(nLastCol), static_cast(nLastRow), aMarkData, EMPTY_STRING, pErgebnis); } } void ImportExcel::Externname34( void ) { } void ImportExcel::Defrowheight345( void ) { sal_uInt16 nFlags, nDefHeight; maStrm >> nFlags >> nDefHeight; pColRowBuff->SetDefHeight( nDefHeight, nFlags ); } void ImportExcel::TableOp( void ) { sal_uInt16 nFirstRow, nLastRow; sal_uInt8 nFirstCol, nLastCol; sal_uInt16 nGrbit; sal_uInt16 nInpRow, nInpCol, nInpRow2, nInpCol2; aIn >> nFirstRow >> nLastRow >> nFirstCol >> nLastCol >> nGrbit >> nInpRow >> nInpCol >> nInpRow2 >> nInpCol2; if( ValidColRow( nLastCol, nLastRow ) ) { if( nFirstCol && nFirstRow ) { ScTabOpParam aTabOpParam; aTabOpParam.nMode = (nGrbit & EXC_TABLEOP_BOTH) ? 2 : ((nGrbit & EXC_TABLEOP_ROW) ? 1 : 0 ); sal_uInt16 nCol = nFirstCol - 1; sal_uInt16 nRow = nFirstRow - 1; SCTAB nTab = GetCurrScTab(); switch( aTabOpParam.nMode ) { case 0: // COL aTabOpParam.aRefFormulaCell.Set( static_cast(nFirstCol), static_cast(nFirstRow - 1), nTab, sal_False, sal_False, sal_False ); aTabOpParam.aRefFormulaEnd.Set( static_cast(nLastCol), static_cast(nFirstRow - 1), nTab, sal_False, sal_False, sal_False ); aTabOpParam.aRefColCell.Set( static_cast(nInpCol), static_cast(nInpRow), nTab, sal_False, sal_False, sal_False ); nRow++; break; case 1: // ROW aTabOpParam.aRefFormulaCell.Set( static_cast(nFirstCol - 1), static_cast(nFirstRow), nTab, sal_False, sal_False, sal_False ); aTabOpParam.aRefFormulaEnd.Set( static_cast(nFirstCol - 1), static_cast(nLastRow), nTab, sal_False, sal_False, sal_False ); aTabOpParam.aRefRowCell.Set( static_cast(nInpCol), static_cast(nInpRow), nTab, sal_False, sal_False, sal_False ); nCol++; break; case 2: // TWO-INPUT aTabOpParam.aRefFormulaCell.Set( static_cast(nFirstCol - 1), static_cast(nFirstRow - 1), nTab, sal_False, sal_False, sal_False ); aTabOpParam.aRefRowCell.Set( static_cast(nInpCol), static_cast(nInpRow), nTab, sal_False, sal_False, sal_False ); aTabOpParam.aRefColCell.Set( static_cast(nInpCol2), static_cast(nInpRow2), nTab, sal_False, sal_False, sal_False ); break; } ScMarkData aMarkData; aMarkData.SelectOneTable( nTab ); pD->InsertTableOp( aTabOpParam, static_cast(nCol), static_cast(nRow), static_cast(nLastCol), static_cast(nLastRow), aMarkData ); } } else { bTabTruncated = sal_True; GetTracer().TraceInvalidRow(GetCurrScTab(), nLastRow, MAXROW); } } void ImportExcel::Bof4( void ) { sal_uInt16 nSubType; maStrm.DisableDecryption(); maStrm.Ignore( 2 ); maStrm >> nSubType; if( nSubType == 0x0100 ) // Book pExcRoot->eDateiTyp = Biff4W; else if( nSubType == 0x0020 ) // Chart pExcRoot->eDateiTyp = Biff4C; else if( nSubType == 0x0040 ) // Macro pExcRoot->eDateiTyp = Biff4M; else // #i51490# Excel interprets invalid indexes as worksheet pExcRoot->eDateiTyp = Biff4; } void ImportExcel::Bof5( void ) { //POST: eDateiTyp = Typ der zu lesenden Datei sal_uInt16 nSubType, nVers; BiffTyp eDatei; maStrm.DisableDecryption(); maStrm >> nVers >> nSubType; switch( nSubType ) { case 0x0005: eDatei = Biff5W; break; // workbook globals case 0x0006: eDatei = Biff5V; break; // VB module case 0x0010: eDatei = Biff5; break; // worksheet case 0x0020: eDatei = Biff5C; break; // chart case 0x0040: eDatei = Biff5M4; break; // macro sheet default: pExcRoot->eDateiTyp = BiffX; return; } if( nVers == 0x0600 && (GetBiff() == EXC_BIFF8) ) eDatei = ( BiffTyp ) ( eDatei - Biff5 + Biff8 ); pExcRoot->eDateiTyp = eDatei; } void ImportExcel::EndSheet( void ) { pExcRoot->pExtSheetBuff->Reset(); if( GetBiff() <= EXC_BIFF5 ) { pExcRoot->pExtNameBuff->Reset(); mnLastRefIdx = 0; } FinalizeTable(); } void ImportExcel::NeueTabelle( void ) { SCTAB nTab = GetCurrScTab(); if( nTab > 0 && !pD->HasTable( nTab ) ) pD->MakeTable( nTab ); pExcRoot->pShrfmlaBuff->Clear(); InitializeTable( nTab ); pOutlineListBuffer->Append( new XclImpOutlineDataBuffer( GetRoot(), nTab ) ); pExcRoot->pColRowBuff = pColRowBuff = pOutlineListBuffer->Last()->GetColRowBuff(); pColOutlineBuff = pOutlineListBuffer->Last()->GetColOutline(); pRowOutlineBuff = pOutlineListBuffer->Last()->GetRowOutline(); } const ScTokenArray* ImportExcel::ErrorToFormula( sal_uInt8 bErrOrVal, sal_uInt8 nError, double& rVal ) { return pFormConv->GetBoolErr( XclTools::ErrorToEnum( rVal, bErrOrVal, nError ) ); } void ImportExcel::AdjustRowHeight() { /* #93255# Speed up chart import: import all sheets without charts, then update row heights (here), last load all charts -> do not any longer update inside of ScDocShell::ConvertFrom() (causes update of existing charts during each and every change of row height). */ /*if( ScModelObj* pDocObj = GetDocModelObj() ) pDocObj->UpdateAllRowHeights();*/ //just update row heights for : 1. visible sheet, 2. sheet containing sdrobject. i120586 SCTAB nCount = GetDoc().GetTableCount(); SCTAB nVisible = GetDocViewSettings().GetDisplScTab(); GetDoc().SetPendingRowHeights(nVisible, false); ScMarkData aUpdateSheets; for (SCTAB nTab=0; nTabUpdateAllRowHeights(&aUpdateSheets); //end i120586 } void ImportExcel::PostDocLoad( void ) { /* Set automatic page numbering in Default page style (default is "page number = 1"). Otherwise hidden tables (i.e. for scenarios) which have Default page style will break automatic page numbering. */ if( SfxStyleSheetBase* pStyleSheet = GetStyleSheetPool().Find( ScGlobal::GetRscString( STR_STYLENAME_STANDARD ), SFX_STYLE_FAMILY_PAGE ) ) pStyleSheet->GetItemSet().Put( SfxUInt16Item( ATTR_PAGE_FIRSTPAGENO, 0 ) ); // outlines for all sheets, sets hidden rows and columns (#i11776# after filtered ranges) for( XclImpOutlineDataBuffer* pBuffer = pOutlineListBuffer->First(); pBuffer; pBuffer = pOutlineListBuffer->Next() ) pBuffer->Convert(); // document view settings (before visible OLE area) GetDocViewSettings().Finalize(); // process all drawing objects (including OLE, charts, controls; after hiding rows/columns; before visible OLE area) GetObjectManager().ConvertObjects(); // visible area (used if this document is an embedded OLE object) if( SfxObjectShell* pDocShell = GetDocShell() ) { // visible area if embedded const ScExtDocSettings& rDocSett = GetExtDocOptions().GetDocSettings(); SCTAB nDisplScTab = rDocSett.mnDisplTab; /* #i44077# If a new OLE object is inserted from file, there is no OLESIZE record in the Excel file. Calculate used area from file contents (used cells and drawing objects). */ if( !maScOleSize.IsValid() ) { // used area of displayed sheet (cell contents) if( const ScExtTabSettings* pTabSett = GetExtDocOptions().GetTabSettings( nDisplScTab ) ) maScOleSize = pTabSett->maUsedArea; // add all valid drawing objects ScRange aScObjArea = GetObjectManager().GetUsedArea( nDisplScTab ); if( aScObjArea.IsValid() ) maScOleSize.ExtendTo( aScObjArea ); } // valid size found - set it at the document if( maScOleSize.IsValid() ) { pDocShell->SetVisArea( GetDoc().GetMMRect( maScOleSize.aStart.Col(), maScOleSize.aStart.Row(), maScOleSize.aEnd.Col(), maScOleSize.aEnd.Row(), nDisplScTab ) ); GetDoc().SetVisibleTab( nDisplScTab ); } } // #111099# open forms in alive mode (has no effect, if no controls in document) if( ScModelObj* pDocObj = GetDocModelObj() ) pDocObj->setPropertyValue( CREATE_OUSTRING( SC_UNO_APPLYFMDES ), uno::Any( false ) ); // enables extended options to be set to the view after import GetExtDocOptions().SetChanged( true ); // root data owns the extended document options -> create a new object GetDoc().SetExtDocOptions( new ScExtDocOptions( GetExtDocOptions() ) ); const SCTAB nLast = pD->GetTableCount(); const ScRange* p; if( pExcRoot->pPrintRanges->HasRanges() ) { for( SCTAB n = 0 ; n < nLast ; n++ ) { p = pExcRoot->pPrintRanges->First( static_cast(n) ); if( p ) { DBG_ASSERT( pExcRoot->pPrintRanges->GetActList(), "-ImportExcel::PostDocLoad(): Imaginaere Tabelle gefunden!" ); pD->ClearPrintRanges( n ); while( p ) { pD->AddPrintRange( n, *p ); p = pExcRoot->pPrintRanges->Next(); } } else { // #i4063# no print ranges -> print entire sheet pD->SetPrintEntireSheet( n ); } } GetTracer().TracePrintRange(); } if( pExcRoot->pPrintTitles->HasRanges() ) { for( SCTAB n = 0 ; n < nLast ; n++ ) { p = pExcRoot->pPrintTitles->First( static_cast(n) ); if( p ) { DBG_ASSERT( pExcRoot->pPrintTitles->GetActList(), "-ImportExcel::PostDocLoad(): Imaginaere Tabelle gefunden!" ); sal_Bool bRowVirgin = sal_True; sal_Bool bColVirgin = sal_True; while( p ) { if( p->aStart.Col() == 0 && p->aEnd.Col() == MAXCOL && bRowVirgin ) { pD->SetRepeatRowRange( n, p ); bRowVirgin = sal_False; } if( p->aStart.Row() == 0 && p->aEnd.Row() == MAXROW && bColVirgin ) { pD->SetRepeatColRange( n, p ); bColVirgin = sal_False; } p = pExcRoot->pPrintTitles->Next(); } } } } } XclImpOutlineDataBuffer::XclImpOutlineDataBuffer( const XclImpRoot& rRoot, SCTAB nScTab ) : XclImpRoot( rRoot ), mxColOutlineBuff( new XclImpOutlineBuffer( rRoot.GetXclMaxPos().Col() + 1 ) ), mxRowOutlineBuff( new XclImpOutlineBuffer( rRoot.GetXclMaxPos().Row() + 1 ) ), mxColRowBuff( new XclImpColRowSettings( rRoot ) ), mnScTab( nScTab ) { } XclImpOutlineDataBuffer::~XclImpOutlineDataBuffer() { } void XclImpOutlineDataBuffer::Convert() { mxColOutlineBuff->SetOutlineArray( GetDoc().GetOutlineTable( mnScTab, sal_True )->GetColArray() ); mxColOutlineBuff->MakeScOutline(); mxRowOutlineBuff->SetOutlineArray( GetDoc().GetOutlineTable( mnScTab, sal_True )->GetRowArray() ); mxRowOutlineBuff->MakeScOutline(); mxColRowBuff->ConvertHiddenFlags( mnScTab ); }