summaryrefslogtreecommitdiffstats
path: root/sc/source/filter/excel/impop.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'sc/source/filter/excel/impop.cxx')
-rw-r--r--sc/source/filter/excel/impop.cxx1414
1 files changed, 1414 insertions, 0 deletions
diff --git a/sc/source/filter/excel/impop.cxx b/sc/source/filter/excel/impop.cxx
new file mode 100644
index 000000000..9ddc6e6e7
--- /dev/null
+++ b/sc/source/filter/excel/impop.cxx
@@ -0,0 +1,1414 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * 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 .
+ */
+
+#include <memory>
+#include <imp_op.hxx>
+
+#include <filter/msfilter/countryid.hxx>
+
+#include <scitems.hxx>
+
+#include <o3tl/safeint.hxx>
+#include <sfx2/docfile.hxx>
+#include <svx/svxids.hrc>
+#include <svl/numformat.hxx>
+#include <unotools/configmgr.hxx>
+#include <sal/log.hxx>
+
+#include <sfx2/objsh.hxx>
+#include <tools/urlobj.hxx>
+#include <docuno.hxx>
+
+#include <formulacell.hxx>
+#include <document.hxx>
+#include <globstr.hrc>
+#include <scresid.hxx>
+#include <global.hxx>
+#include <olinetab.hxx>
+#include <stlpool.hxx>
+#include <viewopti.hxx>
+#include <docoptio.hxx>
+#include <scextopt.hxx>
+#include <unonames.hxx>
+#include <paramisc.hxx>
+#include <colrowst.hxx>
+#include <otlnbuff.hxx>
+#include <xistyle.hxx>
+
+#include <namebuff.hxx>
+#include <xltools.hxx>
+#include <xltable.hxx>
+#include <xltracer.hxx>
+#include <xihelper.hxx>
+#include <xipage.hxx>
+#include <xiview.hxx>
+#include <xiescher.hxx>
+#include <xicontent.hxx>
+
+#include <excform.hxx>
+#include <documentimport.hxx>
+
+#if defined(_WIN32)
+#include <math.h>
+#endif
+
+using namespace ::com::sun::star;
+
+ImportTyp::ImportTyp(ScDocument& rDoc, rtl_TextEncoding eQ)
+ : eQuellChar(eQ)
+ , rD(rDoc)
+
+{
+}
+
+ImportTyp::~ImportTyp()
+{
+}
+
+ImportExcel::ImportExcel( XclImpRootData& rImpData, SvStream& rStrm ):
+ ImportTyp( rImpData.mrDoc, rImpData.meTextEnc ),
+ XclImpRoot( rImpData ),
+ maStrm( rStrm, GetRoot() ),
+ aIn( maStrm ),
+ maScOleSize( ScAddress::INITIALIZE_INVALID ),
+ pColOutlineBuff(nullptr),
+ pRowOutlineBuff(nullptr),
+ pColRowBuff(nullptr),
+ mpLastFormula(nullptr),
+ mnLastRefIdx( 0 ),
+ mnIxfeIndex( 0 ),
+ mnLastRecId(0),
+ mbBiff2HasXfs(false),
+ mbBiff2HasXfsValid(false)
+{
+ nBdshtTab = 0;
+
+ // fill in root data - after new's without root as parameter
+ pExcRoot = &GetOldRoot();
+ pExcRoot->pIR = this; // ExcRoot -> XclImpRoot
+ pExcRoot->eDateiTyp = BiffX;
+ pExcRoot->pExtSheetBuff.reset( new ExtSheetBuffer( pExcRoot ) ); //&aExtSheetBuff;
+ pExcRoot->pShrfmlaBuff.reset( new SharedFormulaBuffer( pExcRoot ) ); //&aShrfrmlaBuff;
+ pExcRoot->pExtNameBuff.reset( new ExtNameBuff ( *this ) );
+
+ pOutlineListBuffer.reset(new XclImpOutlineListBuffer);
+
+ // from Biff8 on
+ pFormConv.reset(new ExcelToSc( GetRoot() ));
+ pExcRoot->pFmlaConverter = pFormConv.get();
+
+ bTabTruncated = false;
+
+ // Excel document per Default on 31.12.1899, accords to Excel settings with 1.1.1900
+ ScDocOptions aOpt = rD.GetDocOptions();
+ aOpt.SetDate( 30, 12, 1899 );
+ rD.SetDocOptions( aOpt );
+ rD.GetFormatTable()->ChangeNullDate( 30, 12, 1899 );
+
+ ScDocOptions aDocOpt( rD.GetDocOptions() );
+ aDocOpt.SetIgnoreCase( true ); // always in Excel
+ aDocOpt.SetFormulaRegexEnabled( false ); // regular expressions? what's that?
+ aDocOpt.SetFormulaWildcardsEnabled( true ); // Excel uses wildcard expressions
+ aDocOpt.SetLookUpColRowNames( false ); // default: no natural language refs
+ rD.SetDocOptions( aDocOpt );
+}
+
+ImportExcel::~ImportExcel()
+{
+ GetDoc().SetSrcCharSet( GetTextEncoding() );
+
+ pOutlineListBuffer.reset();
+
+ pFormConv.reset();
+}
+
+void ImportExcel::SetLastFormula( SCCOL nCol, SCROW nRow, double fVal, sal_uInt16 nXF, ScFormulaCell* pCell )
+{
+ LastFormulaMapType::iterator it = maLastFormulaCells.find(nCol);
+ if (it == maLastFormulaCells.end())
+ {
+ std::pair<LastFormulaMapType::iterator, bool> r =
+ maLastFormulaCells.emplace(nCol, LastFormula());
+ it = r.first;
+ }
+
+ it->second.mnCol = nCol;
+ it->second.mnRow = nRow;
+ it->second.mpCell = pCell;
+ it->second.mfValue = fVal;
+ it->second.mnXF = nXF;
+
+ mpLastFormula = &it->second;
+}
+
+void ImportExcel::ReadFileSharing()
+{
+ sal_uInt16 nRecommendReadOnly, nPasswordHash;
+ nRecommendReadOnly = maStrm.ReaduInt16();
+ nPasswordHash = maStrm.ReaduInt16();
+
+ if((nRecommendReadOnly == 0) && (nPasswordHash == 0))
+ return;
+
+ if( SfxItemSet* pItemSet = GetMedium().GetItemSet() )
+ pItemSet->Put( SfxBoolItem( SID_DOC_READONLY, true ) );
+
+ if( SfxObjectShell* pShell = GetDocShell() )
+ {
+ if( nRecommendReadOnly != 0 )
+ pShell->SetLoadReadonly( 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 ) != nullptr;
+ }
+ // read formatting information (includes the XF identifier)
+ sal_uInt8 nFlags1, nFlags2, nFlags3;
+ nFlags1 = maStrm.ReaduInt8();
+ nFlags2 = maStrm.ReaduInt8();
+ nFlags3 = maStrm.ReaduInt8();
+ /* 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
+ nXFIdx = aIn.ReaduInt16();
+ return nXFIdx;
+}
+
+void ImportExcel::ReadDimensions()
+{
+ XclRange aXclUsedArea;
+ 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 = 0, nXclRow2 = 0;
+ nXclRow1 = maStrm.ReaduInt32();
+ nXclRow2 = maStrm.ReaduInt32();
+ aXclUsedArea.maFirst.mnCol = maStrm.ReaduInt16();
+ aXclUsedArea.maLast.mnCol = maStrm.ReaduInt16();
+ if( (nXclRow1 < nXclRow2) && (aXclUsedArea.GetColCount() > 1) &&
+ (nXclRow1 <= o3tl::make_unsigned( 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;
+ nValue = maStrm.ReaduInt16();
+
+ GetXFRangeBuffer().SetXF( aScPos, nXFIdx );
+ GetDocImport().setNumericCell(aScPos, 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;
+ fValue = maStrm.ReadDouble();
+
+ GetXFRangeBuffer().SetXF( aScPos, nXFIdx );
+ GetDocImport().setNumericCell(aScPos, fValue);
+ }
+}
+
+void ImportExcel::ReadLabel()
+{
+ XclAddress aXclPos;
+ maStrm >> aXclPos;
+
+ ScAddress aScPos( ScAddress::UNINITIALIZED );
+ if( !GetAddressConverter().ConvertAddress( aScPos, aXclPos, GetCurrScTab(), true ) )
+ return;
+
+ /* 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)) ? XclStrFlags::EightBitLength : XclStrFlags::NONE;
+ 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 );
+ XclImpStringHelper::SetToDocument(GetDocImport(), aScPos, GetRoot(), aString, nXFIdx);
+}
+
+void ImportExcel::ReadBoolErr()
+{
+ XclAddress aXclPos;
+ maStrm >> aXclPos;
+
+ ScAddress aScPos( ScAddress::UNINITIALIZED );
+ if( !GetAddressConverter().ConvertAddress( aScPos, aXclPos, GetCurrScTab(), true ) )
+ return;
+
+ sal_uInt16 nXFIdx = ReadXFIndex( aScPos, maStrm.GetRecId() == EXC_ID2_BOOLERR );
+ sal_uInt8 nValue, nType;
+ nValue = maStrm.ReaduInt8();
+ nType = maStrm.ReaduInt8();
+
+ if( nType == EXC_BOOLERR_BOOL )
+ GetXFRangeBuffer().SetBoolXF( aScPos, nXFIdx );
+ else
+ GetXFRangeBuffer().SetXF( aScPos, nXFIdx );
+
+ double fValue;
+ std::unique_ptr<ScTokenArray> pScTokArr = ErrorToFormula( nType != EXC_BOOLERR_BOOL, nValue, fValue );
+ ScFormulaCell* pCell = pScTokArr
+ ? new ScFormulaCell(rD, aScPos, std::move(pScTokArr))
+ : new ScFormulaCell(rD, aScPos);
+ pCell->SetHybridDouble( fValue );
+ GetDocImport().setFormulaCell(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;
+ nRk = maStrm.ReadInt32();
+
+ GetXFRangeBuffer().SetXF( aScPos, nXFIdx );
+ GetDocImport().setNumericCell(aScPos, XclTools::GetDoubleFromRK(nRk));
+ }
+}
+
+void ImportExcel::Window1()
+{
+ GetDocViewSettings().ReadWindow1( maStrm );
+}
+
+void ImportExcel::Row25()
+{
+ sal_uInt16 nRow, nRowHeight;
+
+ nRow = aIn.ReaduInt16();
+ aIn.Ignore( 4 );
+
+ if( !GetRoot().GetDoc().ValidRow( nRow ) )
+ return;
+
+ nRowHeight = aIn.ReaduInt16(); // specify direct in Twips
+ aIn.Ignore( 2 );
+
+ if( GetBiff() == EXC_BIFF2 )
+ {// -------------------- BIFF2
+ pColRowBuff->SetHeight( nRow, nRowHeight );
+ }
+ else
+ {// -------------------- BIFF5
+ sal_uInt16 nGrbit;
+
+ aIn.Ignore( 2 ); // reserved
+ nGrbit = aIn.ReaduInt16();
+
+ sal_uInt8 nLevel = ::extract_value< sal_uInt8 >( nGrbit, 0, 3 );
+ pRowOutlineBuff->SetLevel( nRow, nLevel, ::get_flag( nGrbit, EXC_ROW_COLLAPSED ) );
+ pColRowBuff->SetRowSettings( nRow, nRowHeight, nGrbit );
+ }
+}
+
+void ImportExcel::Bof2()
+{
+ sal_uInt16 nSubType;
+ maStrm.DisableDecryption();
+ maStrm.Ignore( 2 );
+ nSubType = maStrm.ReaduInt16();
+
+ 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()
+{
+ // POST: cannot be called after an invalid table!
+ EndSheet();
+ IncCurrScTab();
+}
+
+void ImportExcel::SheetPassword()
+{
+ if (GetRoot().GetBiff() != EXC_BIFF8)
+ return;
+
+ GetRoot().GetSheetProtectBuffer().ReadPasswordHash( aIn, GetCurrScTab() );
+}
+
+void ImportExcel::Externsheet()
+{
+ OUString aUrl, aTabName;
+ bool bSameWorkBook;
+ OUString aEncodedUrl( aIn.ReadByteString( false ) );
+ XclImpUrlHelper::DecodeUrl( aUrl, aTabName, bSameWorkBook, *pExcRoot->pIR, aEncodedUrl );
+ mnLastRefIdx = pExcRoot->pExtSheetBuff->Add( aUrl, aTabName, bSameWorkBook );
+}
+
+void ImportExcel:: WinProtection()
+{
+ if (GetRoot().GetBiff() != EXC_BIFF8)
+ return;
+
+ GetRoot().GetDocProtectBuffer().ReadWinProtect( aIn );
+}
+
+void ImportExcel::Columndefault()
+{// Default Cell Attributes
+ sal_uInt16 nColMic, nColMac;
+ sal_uInt8 nOpt0;
+
+ nColMic = aIn.ReaduInt16();
+ nColMac = aIn.ReaduInt16();
+
+ OSL_ENSURE( aIn.GetRecLeft() == static_cast<std::size_t>(nColMac - nColMic) * 3 + 2,
+ "ImportExcel::Columndefault - wrong record size" );
+
+ nColMac--;
+
+ if( nColMac > rD.MaxCol() )
+ nColMac = static_cast<sal_uInt16>(rD.MaxCol());
+
+ for( sal_uInt16 nCol = nColMic ; nCol <= nColMac ; nCol++ )
+ {
+ nOpt0 = aIn.ReaduInt8();
+ aIn.Ignore( 2 ); // only 0. Attribute-Byte used
+
+ if( nOpt0 & 0x80 ) // Col hidden?
+ pColRowBuff->HideCol( nCol );
+ }
+}
+
+void ImportExcel::Array25()
+{
+ sal_uInt16 nFormLen;
+ sal_uInt16 nFirstRow = aIn.ReaduInt16();
+ sal_uInt16 nLastRow = aIn.ReaduInt16();
+ sal_uInt8 nFirstCol = aIn.ReaduInt8();
+ sal_uInt8 nLastCol = aIn.ReaduInt8();
+
+ if( GetBiff() == EXC_BIFF2 )
+ {// BIFF2
+ aIn.Ignore( 1 );
+ nFormLen = aIn.ReaduInt8();
+ }
+ else
+ {// BIFF5
+ aIn.Ignore( 6 );
+ nFormLen = aIn.ReaduInt16();
+ }
+
+ std::unique_ptr<ScTokenArray> pResult;
+
+ if (GetRoot().GetDoc().ValidColRow(nLastCol, nLastRow))
+ {
+ // the read mark is now on the formula, length in nFormLen
+
+ pFormConv->Reset( ScAddress( static_cast<SCCOL>(nFirstCol),
+ static_cast<SCROW>(nFirstRow), GetCurrScTab() ) );
+ pFormConv->Convert(pResult, maStrm, nFormLen, true);
+
+ SAL_WARN_IF(!pResult, "sc", "*ImportExcel::Array25(): ScTokenArray is NULL!");
+ }
+
+ if (pResult)
+ {
+ ScDocumentImport& rDoc = GetDocImport();
+ ScRange aArrayRange(nFirstCol, nFirstRow, GetCurrScTab(), nLastCol, nLastRow, GetCurrScTab());
+ rDoc.setMatrixCells(aArrayRange, *pResult, formula::FormulaGrammar::GRAM_ENGLISH_XL_A1);
+ }
+}
+
+void ImportExcel::Rec1904()
+{
+ sal_uInt16 n1904;
+
+ n1904 = aIn.ReaduInt16();
+
+ if( n1904 )
+ {// 1904 date system
+ ScDocOptions aOpt = rD.GetDocOptions();
+ aOpt.SetDate( 1, 1, 1904 );
+ rD.SetDocOptions( aOpt );
+ rD.GetFormatTable()->ChangeNullDate( 1, 1, 1904 );
+ }
+}
+
+void ImportExcel::Externname25()
+{
+ sal_uInt32 nRes;
+ sal_uInt16 nOpt;
+
+ nOpt = aIn.ReaduInt16();
+ nRes = aIn.ReaduInt32();
+
+ aIn.ReadByteString( false ); // name
+
+ if( ( nOpt & 0x0001 ) || ( ( nOpt & 0xFFFE ) == 0x0000 ) )
+ {// external name
+ pExcRoot->pExtNameBuff->AddName( mnLastRefIdx );
+ }
+ else if( nOpt & 0x0010 )
+ {// ole link
+ pExcRoot->pExtNameBuff->AddOLE( mnLastRefIdx, nRes ); // nRes is storage ID
+ }
+ else
+ {// dde link
+ pExcRoot->pExtNameBuff->AddDDE( mnLastRefIdx );
+ }
+}
+
+void ImportExcel::Colwidth()
+{// Column Width
+ sal_uInt8 nColFirst, nColLast;
+ sal_uInt16 nColWidth;
+
+ nColFirst = aIn.ReaduInt8();
+ nColLast = aIn.ReaduInt8();
+ nColWidth = aIn.ReaduInt16();
+
+//TODO: add a check for the unlikely case of changed MAXCOL (-> XclImpAddressConverter)
+// if( nColLast > rD.MaxCol() )
+// nColLast = static_cast<sal_uInt16>(rD.MaxCol());
+
+ sal_uInt16 nScWidth = XclTools::GetScColumnWidth( nColWidth, GetCharWidth() );
+ pColRowBuff->SetWidthRange( nColFirst, nColLast, nScWidth );
+}
+
+void ImportExcel::Defrowheight2()
+{
+ sal_uInt16 nDefHeight;
+ nDefHeight = maStrm.ReaduInt16();
+ nDefHeight &= 0x7FFF;
+ pColRowBuff->SetDefHeight( nDefHeight, EXC_DEFROW_UNSYNCED );
+}
+
+void ImportExcel::SheetProtect()
+{
+ if (GetRoot().GetBiff() != EXC_BIFF8)
+ return;
+
+ GetRoot().GetSheetProtectBuffer().ReadProtect( aIn, GetCurrScTab() );
+}
+
+void ImportExcel::DocProtect()
+{
+ if (GetRoot().GetBiff() != EXC_BIFF8)
+ return;
+
+ GetRoot().GetDocProtectBuffer().ReadDocProtect( aIn );
+}
+
+void ImportExcel::DocPassword()
+{
+ if (GetRoot().GetBiff() != EXC_BIFF8)
+ return;
+
+ GetRoot().GetDocProtectBuffer().ReadPasswordHash( aIn );
+}
+
+void ImportExcel::Codepage()
+{
+ SetCodePage( maStrm.ReaduInt16() );
+}
+
+void ImportExcel::Ixfe()
+{
+ mnIxfeIndex = maStrm.ReaduInt16();
+}
+
+void ImportExcel::DefColWidth()
+{
+ // stored as entire characters -> convert to 1/256 of characters (as in COLINFO)
+ double fDefWidth = 256.0 * maStrm.ReaduInt16();
+
+ if (!pColRowBuff)
+ {
+ SAL_WARN("sc", "*ImportExcel::DefColWidth(): pColRowBuff is NULL!");
+ return;
+ }
+
+ // #i3006# additional space for default width - Excel adds space depending on font size
+ tools::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::Colinfo()
+{// Column Formatting Information
+ sal_uInt16 nColFirst, nColLast, nColWidth, nXF;
+ sal_uInt16 nOpt;
+
+ nColFirst = aIn.ReaduInt16();
+ nColLast = aIn.ReaduInt16();
+ nColWidth = aIn.ReaduInt16();
+ nXF = aIn.ReaduInt16();
+ nOpt = aIn.ReaduInt16();
+
+ if( nColFirst > rD.MaxCol() )
+ return;
+
+ if( nColLast > rD.MaxCol() )
+ nColLast = static_cast<sal_uInt16>(rD.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 );
+
+ 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()
+{
+ sal_uInt16 nFlags;
+ nFlags = aIn.ReaduInt16();
+
+ 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()
+{
+ sal_uInt16 nGrbit = 0;
+
+ if( GetBiff() == EXC_BIFF5 )
+ {
+ aIn.DisableDecryption();
+ maSheetOffsets.push_back( aIn.ReaduInt32() );
+ aIn.EnableDecryption();
+ nGrbit = aIn.ReaduInt16();
+ }
+
+ OUString aName( aIn.ReadByteString( false ) );
+
+ SCTAB nScTab = nBdshtTab;
+ if( nScTab > 0 )
+ {
+ OSL_ENSURE( !rD.HasTable( nScTab ), "ImportExcel::Boundsheet - sheet exists already" );
+ rD.MakeTable( nScTab );
+ }
+
+ if( ( nGrbit & 0x0001 ) || ( nGrbit & 0x0002 ) )
+ rD.SetVisible( nScTab, false );
+
+ if( !rD.RenameTab( nScTab, aName ) )
+ {
+ rD.CreateValidTabName( aName );
+ rD.RenameTab( nScTab, aName );
+ }
+
+ nBdshtTab++;
+}
+
+void ImportExcel::Country()
+{
+ sal_uInt16 nUICountry, nDocCountry;
+ nUICountry = maStrm.ReaduInt16();
+ nDocCountry = maStrm.ReaduInt16();
+
+ // 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( true );
+ GetDoc().SetDocOptions( aDocOpt );
+ }
+}
+
+void ImportExcel::Hideobj()
+{
+ sal_uInt16 nHide;
+ ScVObjMode eOle, eChart, eDraw;
+
+ nHide = aIn.ReaduInt16();
+
+ ScViewOptions aOpts( rD.GetViewOptions() );
+
+ switch( nHide )
+ {
+ case 1: // Placeholders
+ eOle = VOBJ_MODE_SHOW; // in Excel 97 only charts as place holder are displayed
+ 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 );
+
+ rD.SetViewOptions( aOpts );
+}
+
+void ImportExcel::Standardwidth()
+{
+ sal_uInt16 nScWidth = XclTools::GetScColumnWidth( maStrm.ReaduInt16(), GetCharWidth() );
+ if (!pColRowBuff)
+ {
+ SAL_WARN("sc", "*ImportExcel::Standardwidth(): pColRowBuff is NULL!");
+ return;
+ }
+ pColRowBuff->SetDefWidth( nScWidth, true );
+}
+
+void ImportExcel::Shrfmla()
+{
+ switch (mnLastRecId)
+ {
+ case EXC_ID2_FORMULA:
+ case EXC_ID3_FORMULA:
+ case EXC_ID4_FORMULA:
+ // This record MUST immediately follow a FORMULA record.
+ break;
+ default:
+ return;
+ }
+
+ if (!mpLastFormula)
+ // The last FORMULA record should have left this data.
+ return;
+
+ aIn.Ignore( 8 );
+ sal_uInt16 nLenExpr = aIn.ReaduInt16();
+
+ // read mark is now on the formula
+
+ std::unique_ptr<ScTokenArray> pResult;
+
+ // The shared range in this record is erroneous more than half the time.
+ // Don't ever rely on it. Use the one from the formula cell above.
+ SCCOL nCol1 = mpLastFormula->mnCol;
+ SCROW nRow1 = mpLastFormula->mnRow;
+
+ ScAddress aPos(nCol1, nRow1, GetCurrScTab());
+ pFormConv->Reset(aPos);
+ pFormConv->Convert( pResult, maStrm, nLenExpr, true, FT_SharedFormula );
+
+ if (!pResult)
+ {
+ SAL_WARN("sc", "+ImportExcel::Shrfmla(): ScTokenArray is NULL!");
+ return;
+ }
+
+ pExcRoot->pShrfmlaBuff->Store(aPos, *pResult);
+
+ // Create formula cell for the last formula record.
+
+ ScDocumentImport& rDoc = GetDocImport();
+
+ ScFormulaCell* pCell = new ScFormulaCell(rD, aPos, std::move(pResult));
+ pCell->GetCode()->WrapReference(aPos, EXC_MAXCOL8, EXC_MAXROW8);
+ rDoc.getDoc().CheckLinkFormulaNeedingCheck( *pCell->GetCode());
+ rDoc.getDoc().EnsureTable(aPos.Tab());
+ rDoc.setFormulaCell(aPos, pCell);
+ pCell->SetNeedNumberFormat(false);
+ if (std::isfinite(mpLastFormula->mfValue))
+ pCell->SetResultDouble(mpLastFormula->mfValue);
+
+ GetXFRangeBuffer().SetXF(aPos, mpLastFormula->mnXF);
+ mpLastFormula->mpCell = pCell;
+}
+
+void ImportExcel::Mulrk()
+{
+ /* rw (2 bytes): An Rw structure that specifies the row containing the
+ cells with numeric data.
+
+ colFirst (2 bytes): A Col structure that specifies the first column in
+ the series of numeric cells within the sheet. The value of colFirst.col
+ MUST be less than or equal to 254.
+
+ rgrkrec (variable): An array of RkRec structures. Each element in the
+ array specifies an RkRec in the row. The number of entries in the array
+ MUST be equal to the value given by the following formula:
+
+ Number of entries in rgrkrec = (colLast.col – colFirst.col +1)
+
+ colLast (2 bytes): A Col structure that specifies the last column in
+ the set of numeric cells within the sheet. This colLast.col value MUST
+ be greater than the colFirst.col value. */
+
+ XclAddress aXclPos;
+ aIn >> aXclPos;
+
+ XclAddress aCurrXclPos(aXclPos);
+ while (true)
+ {
+ if (aXclPos.mnCol > aCurrXclPos.mnCol)
+ break;
+ if (aIn.GetRecLeft() <= 2)
+ break;
+
+ sal_uInt16 nXF = aIn.ReaduInt16();
+ sal_Int32 nRkNum = aIn.ReadInt32();
+
+ ScAddress aScPos( ScAddress::UNINITIALIZED );
+ if( GetAddressConverter().ConvertAddress( aScPos, aCurrXclPos, GetCurrScTab(), true ) )
+ {
+ GetXFRangeBuffer().SetXF( aScPos, nXF );
+ GetDocImport().setNumericCell(aScPos, XclTools::GetDoubleFromRK(nRkNum));
+ }
+ ++aCurrXclPos.mnCol;
+ }
+}
+
+void ImportExcel::Mulblank()
+{
+ /* rw (2 bytes): An Rw structure that specifies a row containing the blank
+ cells.
+
+ colFirst (2 bytes): A Col structure that specifies the first column in
+ the series of blank cells within the sheet. The value of colFirst.col
+ MUST be less than or equal to 254.
+
+ rgixfe (variable): An array of IXFCell structures. Each element of this
+ array contains an IXFCell structure corresponding to a blank cell in the
+ series. The number of entries in the array MUST be equal to the value
+ given by the following formula:
+
+ Number of entries in rgixfe = (colLast.col – colFirst.col +1)
+
+ colLast (2 bytes): A Col structure that specifies the last column in
+ the series of blank cells within the sheet. This colLast.col value MUST
+ be greater than colFirst.col value. */
+
+ XclAddress aXclPos;
+ aIn >> aXclPos;
+
+ XclAddress aCurrXclPos(aXclPos);
+ while (true)
+ {
+ if (aXclPos.mnCol > aCurrXclPos.mnCol)
+ break;
+ if (aIn.GetRecLeft() <= 2)
+ break;
+
+ sal_uInt16 nXF = aIn.ReaduInt16();
+
+ ScAddress aScPos( ScAddress::UNINITIALIZED );
+ if( GetAddressConverter().ConvertAddress( aScPos, aCurrXclPos, GetCurrScTab(), true ) )
+ GetXFRangeBuffer().SetBlankXF( aScPos, nXF );
+ ++aCurrXclPos.mnCol;
+ }
+}
+
+void ImportExcel::Rstring()
+{
+ XclAddress aXclPos;
+ sal_uInt16 nXFIdx;
+ aIn >> aXclPos;
+ nXFIdx = aIn.ReaduInt16();
+
+ ScAddress aScPos( ScAddress::UNINITIALIZED );
+ if( !GetAddressConverter().ConvertAddress( aScPos, aXclPos, GetCurrScTab(), true ) )
+ return;
+
+ // unformatted Unicode string with separate formatting information
+ XclImpString aString;
+ aString.Read( maStrm );
+
+ // character formatting runs
+ if( !aString.IsRich() )
+ aString.ReadFormats( maStrm );
+
+ GetXFRangeBuffer().SetXF( aScPos, nXFIdx );
+ XclImpStringHelper::SetToDocument(GetDocImport(), aScPos, *this, aString, nXFIdx);
+}
+
+void ImportExcel::Cellmerging()
+{
+ XclImpAddressConverter& rAddrConv = GetAddressConverter();
+ SCTAB nScTab = GetCurrScTab();
+
+ sal_uInt16 nCount = maStrm.ReaduInt16();
+ sal_uInt16 nIdx = 0;
+ while (true)
+ {
+ if (maStrm.GetRecLeft() < 8)
+ break;
+ if (nIdx >= nCount)
+ break;
+ 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() );
+ ++nIdx;
+ }
+}
+
+void ImportExcel::Olesize()
+{
+ XclRange aXclOleSize( ScAddress::UNINITIALIZED );
+ maStrm.Ignore( 2 );
+ aXclOleSize.Read( maStrm, false );
+
+ SCTAB nScTab = GetCurrScTab();
+ GetAddressConverter().ConvertRange( maScOleSize, aXclOleSize, nScTab, nScTab, false );
+}
+
+void ImportExcel::Row34()
+{
+ sal_uInt16 nRow, nRowHeight, nGrbit, nXF;
+
+ nRow = aIn.ReaduInt16();
+ aIn.Ignore( 4 );
+
+ SCROW nScRow = static_cast< SCROW >( nRow );
+
+ if( !GetRoot().GetDoc().ValidRow( nScRow ) )
+ return;
+
+ nRowHeight = aIn.ReaduInt16(); // specify direct in Twips
+ aIn.Ignore( 4 );
+
+ nRowHeight = nRowHeight & 0x7FFF; // Bit 15: Row Height not changed manually
+ if( !nRowHeight )
+ nRowHeight = (GetBiff() == EXC_BIFF2) ? 0x25 : 0x225;
+
+ nGrbit = aIn.ReaduInt16();
+ nXF = aIn.ReaduInt16();
+
+ sal_uInt8 nLevel = ::extract_value< sal_uInt8 >( nGrbit, 0, 3 );
+ pRowOutlineBuff->SetLevel( nScRow, nLevel, ::get_flag( nGrbit, EXC_ROW_COLLAPSED ) );
+ pColRowBuff->SetRowSettings( nScRow, nRowHeight, nGrbit );
+
+ if( nGrbit & EXC_ROW_USEDEFXF )
+ GetXFRangeBuffer().SetRowDefXF( nScRow, nXF & EXC_ROW_XFMASK );
+}
+
+void ImportExcel::Bof3()
+{
+ sal_uInt16 nSubType;
+ maStrm.DisableDecryption();
+ maStrm.Ignore( 2 );
+ nSubType = maStrm.ReaduInt16();
+
+ OSL_ENSURE( nSubType != 0x0100, "*ImportExcel::Bof3(): Biff3 as 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()
+{
+ sal_uInt16 nFirstRow, nLastRow, nFormLen;
+ sal_uInt8 nFirstCol, nLastCol;
+
+ nFirstRow = aIn.ReaduInt16();
+ nLastRow = aIn.ReaduInt16();
+ nFirstCol = aIn.ReaduInt8();
+ nLastCol = aIn.ReaduInt8();
+ aIn.Ignore( (GetBiff() >= EXC_BIFF5) ? 6 : 2 );
+ nFormLen = aIn.ReaduInt16();
+
+ std::unique_ptr<ScTokenArray> pResult;
+
+ if( GetRoot().GetDoc().ValidColRow( nLastCol, nLastRow ) )
+ {
+ // the read mark is now on the formula, length in nFormLen
+
+ pFormConv->Reset( ScAddress( static_cast<SCCOL>(nFirstCol),
+ static_cast<SCROW>(nFirstRow), GetCurrScTab() ) );
+ pFormConv->Convert( pResult, maStrm, nFormLen, true );
+
+ SAL_WARN_IF(!pResult, "sc", "+ImportExcel::Array34(): ScTokenArray is NULL!");
+ }
+
+ if (pResult)
+ {
+ ScDocumentImport& rDoc = GetDocImport();
+ ScRange aArrayRange(nFirstCol, nFirstRow, GetCurrScTab(), nLastCol, nLastRow, GetCurrScTab());
+ rDoc.setMatrixCells(aArrayRange, *pResult, formula::FormulaGrammar::GRAM_ENGLISH_XL_A1);
+ }
+}
+
+void ImportExcel::Defrowheight345()
+{
+ sal_uInt16 nFlags, nDefHeight;
+ nFlags = maStrm.ReaduInt16();
+ nDefHeight = maStrm.ReaduInt16();
+
+ if (!pColRowBuff)
+ {
+ SAL_WARN("sc", "*ImportExcel::Defrowheight345(): pColRowBuff is NULL!");
+ return;
+ }
+
+ pColRowBuff->SetDefHeight( nDefHeight, nFlags );
+}
+
+void ImportExcel::TableOp()
+{
+ sal_uInt16 nFirstRow = aIn.ReaduInt16();
+ sal_uInt16 nLastRow = aIn.ReaduInt16();
+ sal_uInt8 nFirstCol = aIn.ReaduInt8();
+ sal_uInt8 nLastCol = aIn.ReaduInt8();
+ sal_uInt16 nGrbit = aIn.ReaduInt16();
+ sal_uInt16 nInpRow = aIn.ReaduInt16();
+ sal_uInt16 nInpCol = aIn.ReaduInt16();
+ sal_uInt16 nInpRow2 = aIn.ReaduInt16();
+ sal_uInt16 nInpCol2 = aIn.ReaduInt16();
+
+ if (utl::ConfigManager::IsFuzzing())
+ {
+ //shrink to smallish arbitrary value to not timeout
+ nLastRow = std::min<sal_uInt16>(nLastRow, MAXROW_30 / 2);
+ }
+
+ if( GetRoot().GetDoc().ValidColRow( nLastCol, nLastRow ) )
+ {
+ if( nFirstCol && nFirstRow )
+ {
+ ScTabOpParam aTabOpParam;
+ aTabOpParam.meMode = (nGrbit & EXC_TABLEOP_BOTH) ? ScTabOpParam::Both : ((nGrbit & EXC_TABLEOP_ROW) ? ScTabOpParam::Row : ScTabOpParam::Column);
+ sal_uInt16 nCol = nFirstCol - 1;
+ sal_uInt16 nRow = nFirstRow - 1;
+ SCTAB nTab = GetCurrScTab();
+ switch (aTabOpParam.meMode)
+ {
+ case ScTabOpParam::Column:
+ aTabOpParam.aRefFormulaCell.Set(
+ static_cast<SCCOL>(nFirstCol),
+ static_cast<SCROW>(nFirstRow - 1), nTab, false,
+ false, false );
+ aTabOpParam.aRefFormulaEnd.Set(
+ static_cast<SCCOL>(nLastCol),
+ static_cast<SCROW>(nFirstRow - 1), nTab, false,
+ false, false );
+ aTabOpParam.aRefColCell.Set( static_cast<SCCOL>(nInpCol),
+ static_cast<SCROW>(nInpRow), nTab, false, false,
+ false );
+ nRow++;
+ break;
+ case ScTabOpParam::Row:
+ aTabOpParam.aRefFormulaCell.Set(
+ static_cast<SCCOL>(nFirstCol - 1),
+ static_cast<SCROW>(nFirstRow), nTab, false, false,
+ false );
+ aTabOpParam.aRefFormulaEnd.Set(
+ static_cast<SCCOL>(nFirstCol - 1),
+ static_cast<SCROW>(nLastRow), nTab, false, false,
+ false );
+ aTabOpParam.aRefRowCell.Set( static_cast<SCCOL>(nInpCol),
+ static_cast<SCROW>(nInpRow), nTab, false, false,
+ false );
+ nCol++;
+ break;
+ case ScTabOpParam::Both: // TWO-INPUT
+ aTabOpParam.aRefFormulaCell.Set(
+ static_cast<SCCOL>(nFirstCol - 1),
+ static_cast<SCROW>(nFirstRow - 1), nTab, false,
+ false, false );
+ aTabOpParam.aRefRowCell.Set( static_cast<SCCOL>(nInpCol),
+ static_cast<SCROW>(nInpRow), nTab, false, false,
+ false );
+ aTabOpParam.aRefColCell.Set( static_cast<SCCOL>(nInpCol2),
+ static_cast<SCROW>(nInpRow2), nTab, false, false,
+ false );
+ break;
+ }
+
+ ScDocumentImport& rDoc = GetDocImport();
+ ScRange aTabOpRange(nCol, nRow, nTab, nLastCol, nLastRow, nTab);
+ rDoc.setTableOpCells(aTabOpRange, aTabOpParam);
+ }
+ }
+ else
+ {
+ bTabTruncated = true;
+ GetTracer().TraceInvalidRow(nLastRow, rD.MaxRow());
+ }
+}
+
+void ImportExcel::Bof4()
+{
+ sal_uInt16 nSubType;
+ maStrm.DisableDecryption();
+ maStrm.Ignore( 2 );
+ nSubType = maStrm.ReaduInt16();
+
+ 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()
+{
+ //POST: eDateiTyp = Type of the file to be read
+ sal_uInt16 nSubType, nVers;
+ BiffTyp eDatei;
+
+ maStrm.DisableDecryption();
+ nVers = maStrm.ReaduInt16();
+ nSubType = maStrm.ReaduInt16( );
+
+ switch( nSubType )
+ {
+ case 0x0005: eDatei = Biff5W; break; // workbook globals
+ case 0x0006: eDatei = Biff5V; break; // VB module
+ case 0x0020: eDatei = Biff5C; break; // chart
+ case 0x0040: eDatei = Biff5M4; break; // macro sheet
+ case 0x0010: // worksheet
+ default: eDatei = Biff5; break; // tdf#144732 Excel interprets invalid indexes as worksheet
+ }
+
+ if( nVers == 0x0600 && (GetBiff() == EXC_BIFF8) )
+ eDatei = static_cast<BiffTyp>( eDatei - Biff5 + Biff8 );
+
+ pExcRoot->eDateiTyp = eDatei;
+}
+
+void ImportExcel::EndSheet()
+{
+ pExcRoot->pExtSheetBuff->Reset();
+
+ if( GetBiff() <= EXC_BIFF5 )
+ {
+ pExcRoot->pExtNameBuff->Reset();
+ mnLastRefIdx = 0;
+ }
+
+ FinalizeTable();
+}
+
+void ImportExcel::NewTable()
+{
+ SCTAB nTab = GetCurrScTab();
+ if( nTab > 0 && !rD.HasTable( nTab ) )
+ rD.MakeTable( nTab );
+
+ if (nTab == 0 && GetBiff() == EXC_BIFF2)
+ {
+ // For Excel 2.1 Worksheet file, we need to set the file name as the
+ // sheet name.
+ INetURLObject aURL(GetDocUrl());
+ rD.RenameTab(0, aURL.getBase());
+ }
+
+ pExcRoot->pShrfmlaBuff->Clear();
+ maLastFormulaCells.clear();
+ mpLastFormula = nullptr;
+
+ InitializeTable( nTab );
+
+ XclImpOutlineDataBuffer* pNewItem = new XclImpOutlineDataBuffer( GetRoot(), nTab );
+ pOutlineListBuffer->push_back( std::unique_ptr<XclImpOutlineDataBuffer>(pNewItem) );
+ pExcRoot->pColRowBuff = pColRowBuff = pNewItem->GetColRowBuff();
+ pColOutlineBuff = pNewItem->GetColOutline();
+ pRowOutlineBuff = pNewItem->GetRowOutline();
+}
+
+std::unique_ptr<ScTokenArray> ImportExcel::ErrorToFormula( bool bErrOrVal, sal_uInt8 nError, double& rVal )
+{
+ return pFormConv->GetBoolErr( XclTools::ErrorToEnum( rVal, bErrOrVal, nError ) );
+}
+
+void ImportExcel::AdjustRowHeight()
+{
+ /* 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();
+}
+
+void ImportExcel::PostDocLoad()
+{
+ /* 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( ScResId( STR_STYLENAME_STANDARD ), SfxStyleFamily::Page ) )
+ pStyleSheet->GetItemSet().Put( SfxUInt16Item( ATTR_PAGE_FIRSTPAGENO, 0 ) );
+
+ // outlines for all sheets, sets hidden rows and columns (#i11776# after filtered ranges)
+ for (auto& rxBuffer : *pOutlineListBuffer)
+ rxBuffer->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 );
+ }
+ }
+
+ // open forms in alive mode (has no effect, if no controls in document)
+ if( ScModelObj* pDocObj = GetDocModelObj() )
+ pDocObj->setPropertyValue( 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( std::make_unique<ScExtDocOptions>( GetExtDocOptions() ) );
+
+ const SCTAB nLast = rD.GetTableCount();
+ const ScRange* p;
+
+ if( GetRoot().GetPrintAreaBuffer().HasRanges() )
+ {
+ for( SCTAB n = 0 ; n < nLast ; n++ )
+ {
+ p = GetRoot().GetPrintAreaBuffer().First(n);
+ if( p )
+ {
+ rD.ClearPrintRanges( n );
+ while( p )
+ {
+ rD.AddPrintRange( n, *p );
+ p = GetRoot().GetPrintAreaBuffer().Next();
+ }
+ }
+ else
+ {
+ // #i4063# no print ranges -> print entire sheet
+ rD.SetPrintEntireSheet( n );
+ }
+ }
+ GetTracer().TracePrintRange();
+ }
+
+ if( !GetRoot().GetTitleAreaBuffer().HasRanges() )
+ return;
+
+ for( SCTAB n = 0 ; n < nLast ; n++ )
+ {
+ p = GetRoot().GetTitleAreaBuffer().First(n);
+ if( p )
+ {
+ bool bRowVirgin = true;
+ bool bColVirgin = true;
+
+ while( p )
+ {
+ if( p->aStart.Col() == 0 && p->aEnd.Col() == rD.MaxCol() && bRowVirgin )
+ {
+ rD.SetRepeatRowRange( n, *p );
+ bRowVirgin = false;
+ }
+
+ if( p->aStart.Row() == 0 && p->aEnd.Row() == rD.MaxRow() && bColVirgin )
+ {
+ rD.SetRepeatColRange( n, *p );
+ bColVirgin = false;
+ }
+
+ p = GetRoot().GetTitleAreaBuffer().Next();
+ }
+ }
+ }
+}
+
+XclImpOutlineDataBuffer::XclImpOutlineDataBuffer( const XclImpRoot& rRoot, SCTAB nScTab ) :
+ XclImpRoot( rRoot ),
+ mxColOutlineBuff( std::make_shared<XclImpOutlineBuffer>( rRoot.GetXclMaxPos().Col() + 1 ) ),
+ mxRowOutlineBuff( std::make_shared<XclImpOutlineBuffer>( rRoot.GetXclMaxPos().Row() + 1 ) ),
+ mxColRowBuff( std::make_shared<XclImpColRowSettings>( rRoot ) ),
+ mnScTab( nScTab )
+{
+}
+
+XclImpOutlineDataBuffer::~XclImpOutlineDataBuffer()
+{
+}
+
+void XclImpOutlineDataBuffer::Convert()
+{
+ mxColOutlineBuff->SetOutlineArray( &GetDoc().GetOutlineTable( mnScTab, true )->GetColArray() );
+ mxColOutlineBuff->MakeScOutline();
+
+ mxRowOutlineBuff->SetOutlineArray( &GetDoc().GetOutlineTable( mnScTab, true )->GetRowArray() );
+ mxRowOutlineBuff->MakeScOutline();
+
+ mxColRowBuff->ConvertHiddenFlags( mnScTab );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */