blob: 7819cbc9ca20031e48c5ee60d3e4cd565bb0c08e [file] [log] [blame]
/**************************************************************
*
* 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_sc.hxx"
#include "imp_op.hxx"
#include <filter/msfilter/countryid.hxx>
#include "scitems.hxx"
#include <editeng/eeitem.hxx>
#include <editeng/editdata.hxx>
#include <editeng/editeng.hxx>
#include <editeng/editobj.hxx>
#include <editeng/editstat.hxx>
#include <editeng/flditem.hxx>
#include <svx/pageitem.hxx>
#include <editeng/colritem.hxx>
#include <sfx2/printer.hxx>
#include <sfx2/docfile.hxx>
#include <svl/zforlist.hxx>
#include <sfx2/objsh.hxx>
#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 <math.h>
#else
#include <stdlib.h>
#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<sal_uInt16>(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<SCCOL>(nFirstCol),
static_cast<SCROW>(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<SCCOL>(nFirstCol),
static_cast<SCROW>(nFirstRow), static_cast<SCCOL>(nLastCol),
static_cast<SCROW>(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<sal_uInt16>(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<sal_uInt16>(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<SCCOL>(nFirstCol),
static_cast<SCROW>(nFirstRow), GetCurrScTab(),
static_cast<SCCOL>(nLastCol), static_cast<SCROW>(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<SCCOL>(nFirstCol),
static_cast<SCROW>(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<SCCOL>(nFirstCol),
static_cast<SCROW>(nFirstRow), static_cast<SCCOL>(nLastCol),
static_cast<SCROW>(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<SCCOL>(nFirstCol),
static_cast<SCROW>(nFirstRow - 1), nTab, sal_False,
sal_False, sal_False );
aTabOpParam.aRefFormulaEnd.Set(
static_cast<SCCOL>(nLastCol),
static_cast<SCROW>(nFirstRow - 1), nTab, sal_False,
sal_False, sal_False );
aTabOpParam.aRefColCell.Set( static_cast<SCCOL>(nInpCol),
static_cast<SCROW>(nInpRow), nTab, sal_False, sal_False,
sal_False );
nRow++;
break;
case 1: // ROW
aTabOpParam.aRefFormulaCell.Set(
static_cast<SCCOL>(nFirstCol - 1),
static_cast<SCROW>(nFirstRow), nTab, sal_False, sal_False,
sal_False );
aTabOpParam.aRefFormulaEnd.Set(
static_cast<SCCOL>(nFirstCol - 1),
static_cast<SCROW>(nLastRow), nTab, sal_False, sal_False,
sal_False );
aTabOpParam.aRefRowCell.Set( static_cast<SCCOL>(nInpCol),
static_cast<SCROW>(nInpRow), nTab, sal_False, sal_False,
sal_False );
nCol++;
break;
case 2: // TWO-INPUT
aTabOpParam.aRefFormulaCell.Set(
static_cast<SCCOL>(nFirstCol - 1),
static_cast<SCROW>(nFirstRow - 1), nTab, sal_False,
sal_False, sal_False );
aTabOpParam.aRefRowCell.Set( static_cast<SCCOL>(nInpCol),
static_cast<SCROW>(nInpRow), nTab, sal_False, sal_False,
sal_False );
aTabOpParam.aRefColCell.Set( static_cast<SCCOL>(nInpCol2),
static_cast<SCROW>(nInpRow2), nTab, sal_False, sal_False,
sal_False );
break;
}
ScMarkData aMarkData;
aMarkData.SelectOneTable( nTab );
pD->InsertTableOp( aTabOpParam, static_cast<SCCOL>(nCol),
static_cast<SCROW>(nRow), static_cast<SCCOL>(nLastCol),
static_cast<SCROW>(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; nTab<nCount; ++nTab)
{
if ( false == GetDoc().IsPendingRowHeights(nTab))
aUpdateSheets.SelectTable( nTab, true );
}
ScModelObj* pDocObj = GetDocModelObj();
if (pDocObj && (aUpdateSheets.GetSelectCount()))
pDocObj->UpdateAllRowHeights(&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<sal_uInt16>(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<sal_uInt16>(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 );
}