/* -*- 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 <excform.hxx>
#include <formulacell.hxx>
#include <document.hxx>
#include <scmatrix.hxx>
#include <formula/errorcodes.hxx>
#include <svl/sharedstringpool.hxx>
#include <sal/log.hxx>
#include <imp_op.hxx>
#include <namebuff.hxx>
#include <root.hxx>
#include <xltracer.hxx>
#include <xihelper.hxx>
#include <xiname.hxx>
#include <xistyle.hxx>
#include <documentimport.hxx>
using ::std::vector;
const sal_uInt16 ExcelToSc::nRowMask = 0x3FFF;
void ImportExcel::Formula25()
{
XclAddress aXclPos;
sal_uInt16 nXF = 0, nFormLen;
double fCurVal;
bool bShrFmla;
aIn >> aXclPos;
if( GetBiff() == EXC_BIFF2 )
{// BIFF2
aIn.Ignore( 3 );
fCurVal = aIn.ReadDouble();
aIn.Ignore( 1 );
nFormLen = aIn.ReaduInt8();
bShrFmla = false;
}
else
{// BIFF5
sal_uInt8 nFlag0;
nXF = aIn.ReaduInt16();
fCurVal = aIn.ReadDouble();
nFlag0 = aIn.ReaduInt8();
aIn.Ignore( 5 );
nFormLen = aIn.ReaduInt16();
bShrFmla = nFlag0 & 0x08; // shared or not shared
}
Formula( aXclPos, nXF, nFormLen, fCurVal, bShrFmla );
}
void ImportExcel::Formula3()
{
Formula4();
}
void ImportExcel::Formula4()
{
XclAddress aXclPos;
aIn >> aXclPos;
sal_uInt16 nXF = aIn.ReaduInt16();
double fCurVal = aIn.ReadDouble();
aIn.Ignore( 2 );
sal_uInt16 nFormLen = aIn.ReaduInt16();
Formula( aXclPos, nXF, nFormLen, fCurVal, false );
}
void ImportExcel::Formula(
const XclAddress& rXclPos, sal_uInt16 nXF, sal_uInt16 nFormLen, double fCurVal, bool bShrFmla)
{
if (!nFormLen)
return;
ScAddress aScPos( ScAddress::UNINITIALIZED );
if (!GetAddressConverter().ConvertAddress(aScPos, rXclPos, GetCurrScTab(), true))
// Conversion failed.
return;
// Formula will be read next, length in nFormLen
std::unique_ptr<ScTokenArray> pResult;
pFormConv->Reset( aScPos );
ScDocumentImport& rDoc = GetDocImport();
if (bShrFmla)
{
// This is a shared formula. Get the token array from the shared formula pool.
SCCOL nSharedCol;
SCROW nSharedRow;
if (ExcelToSc::ReadSharedFormulaPosition(maStrm, nSharedCol, nSharedRow))
{
ScAddress aRefPos(nSharedCol, nSharedRow, GetCurrScTab());
const ScTokenArray* pSharedCode = pFormConv->GetSharedFormula(aRefPos);
if (pSharedCode)
{
ScFormulaCell* pCell;
pCell = new ScFormulaCell(rD, aScPos, pSharedCode->Clone());
pCell->GetCode()->WrapReference(aScPos, EXC_MAXCOL8, EXC_MAXROW8);
rDoc.getDoc().EnsureTable(aScPos.Tab());
rDoc.setFormulaCell(aScPos, pCell);
pCell->SetNeedNumberFormat(false);
if (std::isfinite(fCurVal))
pCell->SetResultDouble(fCurVal);
GetXFRangeBuffer().SetXF(aScPos, nXF);
SetLastFormula(aScPos.Col(), aScPos.Row(), fCurVal, nXF, pCell);
}
else
{
// Shared formula not found even though it's clearly a shared formula.
// The cell will be created in the following shared formula
// record.
SetLastFormula(aScPos.Col(), aScPos.Row(), fCurVal, nXF, nullptr);
}
return;
}
}
ConvErr eErr = pFormConv->Convert( pResult, maStrm, nFormLen, true );
ScFormulaCell* pCell = nullptr;
if (pResult)
{
pCell = new ScFormulaCell(rDoc.getDoc(), aScPos, std::move(pResult));
pCell->GetCode()->WrapReference(aScPos, EXC_MAXCOL8, EXC_MAXROW8);
rDoc.getDoc().CheckLinkFormulaNeedingCheck( *pCell->GetCode());
rDoc.getDoc().EnsureTable(aScPos.Tab());
rDoc.setFormulaCell(aScPos, pCell);
SetLastFormula(aScPos.Col(), aScPos.Row(), fCurVal, nXF, pCell);
}
else
{
pCell = rDoc.getDoc().GetFormulaCell(aScPos);
if (pCell)
pCell->AddRecalcMode( ScRecalcMode::ONLOAD_ONCE );
}
if (pCell)
{
pCell->SetNeedNumberFormat(false);
if( eErr != ConvErr::OK )
ExcelToSc::SetError( *pCell, eErr );
if (std::isfinite(fCurVal))
pCell->SetResultDouble(fCurVal);
}
GetXFRangeBuffer().SetXF(aScPos, nXF);
}
ExcelToSc::ExcelToSc( XclImpRoot& rRoot ) :
ExcelConverterBase(rRoot.GetDocImport().getDoc().GetSharedStringPool()),
XclImpRoot( rRoot ),
maFuncProv( rRoot ),
meBiff( rRoot.GetBiff() )
{
}
ExcelToSc::~ExcelToSc()
{
}
std::unique_ptr<ScTokenArray> ExcelToSc::GetDummy()
{
aPool.Store( u"Dummy()"_ustr );
aPool >> aStack;
return aPool.GetTokenArray( GetDocImport().getDoc(), aStack.Get());
}
// if bAllowArrays is false stream seeks to first byte after <nFormulaLen>
// otherwise it will seek to the first byte after the additional content (eg
// inline arrays) following <nFormulaLen>
ConvErr ExcelToSc::Convert( std::unique_ptr<ScTokenArray>& pResult, XclImpStream& aIn, std::size_t nFormulaLen, bool bAllowArrays, const FORMULA_TYPE eFT )
{
RootData& rR = GetOldRoot();
sal_uInt8 nOp, nLen;
bool bError = false;
bool bArrayFormula = false;
TokenId nBuf0;
const bool bRangeName = eFT == FT_RangeName;
const bool bSharedFormula = eFT == FT_SharedFormula;
const bool bConditional = eFT == FT_CondFormat;
const bool bRNorSF = bRangeName || bSharedFormula || bConditional;
ScSingleRefData aSRD;
ScComplexRefData aCRD;
ExtensionTypeVec aExtensions;
if( nFormulaLen == 0 )
{
aPool.Store( u"-/-"_ustr );
aPool >> aStack;
pResult = aPool.GetTokenArray( GetDocImport().getDoc(), aStack.Get());
return ConvErr::OK;
}
std::size_t nEndPos = aIn.GetRecPos() + nFormulaLen;
while( (aIn.GetRecPos() < nEndPos) && !bError )
{
nOp = aIn.ReaduInt8();
// always reset flags
aSRD.InitFlags();
aCRD.InitFlags();
switch( nOp ) // book page:
{ // SDK4 SDK5
case 0x01: // Array Formula [325 ]
// Array Formula or Shared Formula [ 277]
case 0x02: // Data Table [325 277]
{
sal_uInt16 nUINT16 = 3;
if( meBiff != EXC_BIFF2 )
nUINT16++;
aIn.Ignore( nUINT16 );
bArrayFormula = true;
break;
}
case 0x03: // Addition [312 264]
aStack >> nBuf0;
aPool << aStack << ocAdd << nBuf0;
aPool >> aStack;
break;
case 0x04: // Subtraction [313 264]
// SECOND-TOP minus TOP
aStack >> nBuf0;
aPool << aStack << ocSub << nBuf0;
aPool >> aStack;
break;
case 0x05: // Multiplication [313 264]
aStack >> nBuf0;
aPool << aStack << ocMul << nBuf0;
aPool >> aStack;
break;
case 0x06: // Division [313 264]
// divide TOP by SECOND-TOP
aStack >> nBuf0;
aPool << aStack << ocDiv << nBuf0;
aPool >> aStack;
break;
case 0x07: // Exponentiation [313 265]
// raise SECOND-TOP to power of TOP
aStack >> nBuf0;
aPool << aStack << ocPow << nBuf0;
aPool >> aStack;
break;
case 0x08: // Concatenation [313 265]
// append TOP to SECOND-TOP
aStack >> nBuf0;
aPool << aStack << ocAmpersand << nBuf0;
aPool >> aStack;
break;
case 0x09: // Less Than [313 265]
// SECOND-TOP < TOP
aStack >> nBuf0;
aPool << aStack << ocLess << nBuf0;
aPool >> aStack;
break;
case 0x0A: // Less Than or Equal [313 265]
// SECOND-TOP <= TOP
aStack >> nBuf0;
aPool << aStack << ocLessEqual << nBuf0;
aPool >> aStack;
break;
case 0x0B: // Equal [313 265]
// SECOND-TOP == TOP
aStack >> nBuf0;
aPool << aStack << ocEqual << nBuf0;
aPool >> aStack;
break;
case 0x0C: // Greater Than or Equal [313 265]
// SECOND-TOP >= TOP
aStack >> nBuf0;
aPool << aStack << ocGreaterEqual << nBuf0;
aPool >> aStack;
break;
case 0x0D: // Greater Than [313 265]
// SECOND-TOP > TOP
aStack >> nBuf0;
aPool << aStack << ocGreater << nBuf0;
aPool >> aStack;
break;
case 0x0E: // Not Equal [313 265]
// SECOND-TOP != TOP
aStack >> nBuf0;
aPool << aStack << ocNotEqual << nBuf0;
aPool >> aStack;
break;
case 0x0F: // Intersection [314 265]
aStack >> nBuf0;
aPool << aStack << ocIntersect << nBuf0;
aPool >> aStack;
break;
case 0x10: // Union [314 265]
// ocSep instead of 'ocUnion'
aStack >> nBuf0;
aPool << aStack << ocSep << nBuf0;
// doesn't fit exactly, but is more Excel-like
aPool >> aStack;
break;
case 0x11: // Range [314 265]
aStack >> nBuf0;
aPool << aStack << ocRange << nBuf0;
aPool >> aStack;
break;
case 0x12: // Unary Plus [312 264]
aPool << ocAdd << aStack;
aPool >> aStack;
break;
case 0x13: // Unary Minus [312 264]
aPool << ocNegSub << aStack;
aPool >> aStack;
break;
case 0x14: // Percent Sign [312 264]
aPool << aStack << ocPercentSign;
aPool >> aStack;
break;
case 0x15: // Parenthesis [326 278]
aPool << ocOpen << aStack << ocClose;
aPool >> aStack;
break;
case 0x16: // Missing Argument [314 266]
aPool << ocMissing;
aPool >> aStack;
GetTracer().TraceFormulaMissingArg();
break;
case 0x17: // String Constant [314 266]
{
nLen = aIn.ReaduInt8();
OUString aString = aIn.ReadRawByteString( nLen );
aStack << aPool.Store( aString );
break;
}
case 0x19: // Special Attribute [327 279]
{
sal_uInt16 nData(0), nFactor(0);
sal_uInt8 nOpt = aIn.ReaduInt8();
if( meBiff == EXC_BIFF2 )
{
nData = aIn.ReaduInt8();
nFactor = 1;
}
else
{
nData = aIn.ReaduInt16();
nFactor = 2;
}
if( nOpt & 0x04 )
{
// nFactor -> skip bytes or words AttrChoose
++nData;
aIn.Ignore(static_cast<std::size_t>(nData) * nFactor);
}
else if( nOpt & 0x10 ) // AttrSum
DoMulArgs( ocSum, 1 );
}
break;
case 0x1A: // External Reference [330 ]
switch( meBiff )
{
case EXC_BIFF2: aIn.Ignore( 7 ); break;
case EXC_BIFF3:
case EXC_BIFF4: aIn.Ignore( 10 ); break;
case EXC_BIFF5:
SAL_INFO( "sc", "-ExcelToSc::Convert(): 0x1A does not exist in Biff5!" );
[[fallthrough]];
default:
SAL_INFO( "sc", "-ExcelToSc::Convert(): A little oblivious?" );
}
break;
case 0x1B: // End External Reference [330 ]
switch( meBiff )
{
case EXC_BIFF2: aIn.Ignore( 3 ); break;
case EXC_BIFF3:
case EXC_BIFF4: aIn.Ignore( 4 ); break;
case EXC_BIFF5:
SAL_INFO( "sc", "-ExcelToSc::Convert(): 0x1B does not exist in Biff5!" );
[[fallthrough]];
default:
SAL_INFO( "sc", "-ExcelToSc::Convert(): A little oblivious?" );
}
break;
case 0x1C: // Error Value [314 266]
{
sal_uInt8 nByte = aIn.ReaduInt8();
DefTokenId eOc;
switch( nByte )
{
case EXC_ERR_NULL:
case EXC_ERR_DIV0:
case EXC_ERR_VALUE:
case EXC_ERR_REF:
case EXC_ERR_NAME:
case EXC_ERR_NUM: eOc = ocStop; break;
case EXC_ERR_NA: eOc = ocNotAvail; break;
default: eOc = ocNoName;
}
aPool << eOc;
if( eOc != ocStop )
aPool << ocOpen << ocClose;
aPool >> aStack;
break;
}
case 0x1D: // Boolean [315 266]
{
sal_uInt8 nByte = aIn.ReaduInt8();
if( nByte == 0 )
aPool << ocFalse << ocOpen << ocClose;
else
aPool << ocTrue << ocOpen << ocClose;
aPool >> aStack;
break;
}
case 0x1E: // Integer [315 266]
{
sal_uInt16 nUINT16 = aIn.ReaduInt16();
aStack << aPool.Store( static_cast<double>(nUINT16) );
break;
}
case 0x1F: // Number [315 266]
{
double fDouble = aIn.ReadDouble();
aStack << aPool.Store( fDouble );
break;
}
case 0x40:
case 0x60:
case 0x20: // Array Constant [317 268]
{
aIn.Ignore( (meBiff == EXC_BIFF2) ? 6 : 7 );
if( bAllowArrays )
{
aStack << aPool.StoreMatrix();
aExtensions.push_back( EXTENSION_ARRAY );
}
else
{
aPool << ocBad;
aPool >> aStack;
}
break;
}
case 0x41:
case 0x61:
case 0x21: // Function, Fixed Number of Arguments [333 282]
{
sal_uInt16 nXclFunc;
if( meBiff <= EXC_BIFF3 )
nXclFunc = aIn.ReaduInt8();
else
nXclFunc = aIn.ReaduInt16();
if( const XclFunctionInfo* pFuncInfo = maFuncProv.GetFuncInfoFromXclFunc( nXclFunc ) )
DoMulArgs( pFuncInfo->meOpCode, pFuncInfo->mnMaxParamCount );
else
DoMulArgs( ocNoName, 0 );
}
break;
case 0x42:
case 0x62:
case 0x22: // Function, Variable Number of Arg. [333 283]
{
sal_uInt16 nXclFunc;
sal_uInt8 nParamCount;
nParamCount = aIn.ReaduInt8();
nParamCount &= 0x7F;
if( meBiff <= EXC_BIFF3 )
nXclFunc = aIn.ReaduInt8();
else
nXclFunc = aIn.ReaduInt16();
if( const XclFunctionInfo* pFuncInfo = maFuncProv.GetFuncInfoFromXclFunc( nXclFunc ) )
DoMulArgs( pFuncInfo->meOpCode, nParamCount );
else
DoMulArgs( ocNoName, 0 );
}
break;
case 0x43:
case 0x63:
case 0x23: // Name [318 269]
{
sal_uInt16 nUINT16 = aIn.ReaduInt16();
switch( meBiff )
{
case EXC_BIFF2: aIn.Ignore( 5 ); break;
case EXC_BIFF3:
case EXC_BIFF4: aIn.Ignore( 8 ); break;
case EXC_BIFF5: aIn.Ignore( 12 ); break;
default:
OSL_FAIL(
"-ExcelToSc::Convert(): A little oblivious?" );
}
const XclImpName* pName = GetNameManager().GetName( nUINT16 );
if(pName && !pName->GetScRangeData())
aStack << aPool.Store( ocMacro, pName->GetXclName() );
else
aStack << aPool.StoreName(nUINT16, -1);
}
break;
case 0x44:
case 0x64:
case 0x24: // Cell Reference [319 270]
case 0x4A:
case 0x6A:
case 0x2A: // Deleted Cell Reference [323 273]
{
sal_uInt16 nUINT16 = aIn.ReaduInt16();
sal_uInt8 nByte = aIn.ReaduInt8();
aSRD.SetAbsCol(static_cast<SCCOL>(nByte));
aSRD.SetAbsRow(nUINT16 & 0x3FFF);
aSRD.SetRelTab(0);
aSRD.SetFlag3D( bRangeName );
ExcRelToScRel( nUINT16, nByte, aSRD, bRangeName );
switch ( nOp )
{
case 0x4A:
case 0x6A:
case 0x2A: // Deleted Cell Reference [323 273]
// no information which part is deleted, set both
aSRD.SetColDeleted( true );
aSRD.SetRowDeleted( true );
}
aStack << aPool.Store( aSRD );
break;
}
case 0x45:
case 0x65:
case 0x25: // Area Reference [320 270]
case 0x4B:
case 0x6B:
case 0x2B: // Deleted Area Reference [323 273]
{
sal_uInt16 nRowFirst, nRowLast;
sal_uInt8 nColFirst, nColLast;
ScSingleRefData& rSRef1 = aCRD.Ref1;
ScSingleRefData& rSRef2 = aCRD.Ref2;
nRowFirst = aIn.ReaduInt16();
nRowLast = aIn.ReaduInt16();
nColFirst = aIn.ReaduInt8();
nColLast = aIn.ReaduInt8();
rSRef1.SetRelTab(0);
rSRef2.SetRelTab(0);
rSRef1.SetFlag3D( bRangeName );
rSRef2.SetFlag3D( bRangeName );
ExcRelToScRel( nRowFirst, nColFirst, aCRD.Ref1, bRangeName );
ExcRelToScRel( nRowLast, nColLast, aCRD.Ref2, bRangeName );
if( IsComplColRange( nColFirst, nColLast ) )
SetComplCol( aCRD );
else if( IsComplRowRange( nRowFirst, nRowLast ) )
SetComplRow( aCRD );
switch ( nOp )
{
case 0x4B:
case 0x6B:
case 0x2B: // Deleted Area Reference [323 273]
// no information which part is deleted, set all
rSRef1.SetColDeleted( true );
rSRef1.SetRowDeleted( true );
rSRef2.SetColDeleted( true );
rSRef2.SetRowDeleted( true );
}
aStack << aPool.Store( aCRD );
}
break;
case 0x46:
case 0x66:
case 0x26: // Constant Reference Subexpression [321 271]
aExtensions.push_back( EXTENSION_MEMAREA );
[[fallthrough]];
case 0x47:
case 0x67:
case 0x27: // Erroneous Constant Reference Subexpr. [322 272]
case 0x48:
case 0x68:
case 0x28: // Incomplete Constant Reference Subexpr.[331 281]
aIn.Ignore( (meBiff == EXC_BIFF2) ? 4 : 6 );
break;
case 0x4C:
case 0x6C:
case 0x2C: // Cell Reference Within a Name [323 ]
// Cell Reference Within a Shared Formula[ 273]
{
sal_uInt16 nUINT16 = aIn.ReaduInt16();
sal_uInt8 nByte = aIn.ReaduInt8(); // >> Attribute, Row >> Col
aSRD.SetRelTab(0);
aSRD.SetFlag3D( bRangeName );
ExcRelToScRel( nUINT16, nByte, aSRD, bRNorSF );
aStack << aPool.Store( aSRD );
break;
}
case 0x4D:
case 0x6D:
case 0x2D: // Area Reference Within a Name [324 ]
{ // Area Reference Within a Shared Formula[ 274]
sal_uInt16 nRowFirst, nRowLast;
sal_uInt8 nColFirst, nColLast;
aCRD.Ref1.SetRelTab(0);
aCRD.Ref2.SetRelTab(0);
aCRD.Ref1.SetFlag3D( bRangeName );
aCRD.Ref2.SetFlag3D( bRangeName );
nRowFirst = aIn.ReaduInt16();
nRowLast = aIn.ReaduInt16();
nColFirst = aIn.ReaduInt8();
nColLast = aIn.ReaduInt8( );
ExcRelToScRel( nRowFirst, nColFirst, aCRD.Ref1, bRNorSF );
ExcRelToScRel( nRowLast, nColLast, aCRD.Ref2, bRNorSF );
if( IsComplColRange( nColFirst, nColLast ) )
SetComplCol( aCRD );
else if( IsComplRowRange( nRowFirst, nRowLast ) )
SetComplRow( aCRD );
aStack << aPool.Store( aCRD );
}
break;
case 0x49:
case 0x69:
case 0x29: // Variable Reference Subexpression [331 281]
case 0x4E:
case 0x6E:
case 0x2E: // Reference Subexpression Within a Name [332 282]
case 0x4F:
case 0x6F:
case 0x2F: // Incomplete Reference Subexpression... [332 282]
aIn.Ignore( (meBiff == EXC_BIFF2) ? 1 : 2 );
break;
case 0x58:
case 0x78:
case 0x38: // Command-Equivalent Function [333 ]
{
OUString aString = u"COMM_EQU_FUNC"_ustr;
sal_uInt8 nByte = aIn.ReaduInt8();
aString += OUString::number( nByte );
nByte = aIn.ReaduInt8();
aStack << aPool.Store( aString );
DoMulArgs( ocPush, nByte + 1 );
break;
}
case 0x59:
case 0x79:
case 0x39: // Name or External Name [ 275]
{
sal_Int16 nINT16 = aIn.ReadInt16();
aIn.Ignore( 8 );
sal_uInt16 nUINT16 = aIn.ReaduInt16();
if( nINT16 >= 0 )
{
aPool << ocBad;
aPool >> aStack;
}
else
aStack << aPool.StoreName( nUINT16, -1 );
aIn.Ignore( 12 );
break;
}
case 0x5A:
case 0x7A:
case 0x3A: // 3-D Cell Reference [ 275]
case 0x5C:
case 0x7C:
case 0x3C: // Deleted 3-D Cell Reference [ 277]
{
sal_uInt16 nTabFirst, nTabLast, nRow;
sal_Int16 nExtSheet;
sal_uInt8 nCol;
nExtSheet = aIn.ReadInt16();
aIn.Ignore( 8 );
nTabFirst = aIn.ReaduInt16();
nTabLast = aIn.ReaduInt16();
nRow = aIn.ReaduInt16();
nCol = aIn.ReaduInt8();
if( nExtSheet >= 0 )
{ // from external
if( rR.pExtSheetBuff->GetScTabIndex( nExtSheet, nTabLast ) )
{
nTabFirst = nTabLast;
nExtSheet = 0; // found
}
else
{
aPool << ocBad;
aPool >> aStack;
nExtSheet = 1; // don't create a SingleRef
}
}
if( nExtSheet <= 0 )
{ // in current Workbook
aSRD.SetAbsTab(nTabFirst);
aSRD.SetFlag3D(true);
ExcRelToScRel( nRow, nCol, aSRD, bRangeName );
switch ( nOp )
{
case 0x5C:
case 0x7C:
case 0x3C: // Deleted 3-D Cell Reference [ 277]
// no information which part is deleted, set both
aSRD.SetColDeleted( true );
aSRD.SetRowDeleted( true );
}
if ( !ValidTab(static_cast<SCTAB>(nTabFirst)) )
aSRD.SetTabDeleted( true );
if( nTabLast != nTabFirst )
{
aCRD.Ref1 = aCRD.Ref2 = aSRD;
aCRD.Ref2.SetAbsTab(nTabLast);
aCRD.Ref2.SetTabDeleted( !ValidTab(static_cast<SCTAB>(nTabLast)) );
aStack << aPool.Store( aCRD );
}
else
aStack << aPool.Store( aSRD );
}
}
break;
case 0x5B:
case 0x7B:
case 0x3B: // 3-D Area Reference [ 276]
case 0x5D:
case 0x7D:
case 0x3D: // Deleted 3-D Area Reference [ 277]
{
sal_uInt16 nTabFirst, nTabLast, nRowFirst, nRowLast;
sal_Int16 nExtSheet;
sal_uInt8 nColFirst, nColLast;
nExtSheet = aIn.ReadInt16();
aIn.Ignore( 8 );
nTabFirst = aIn.ReaduInt16();
nTabLast = aIn.ReaduInt16();
nRowFirst = aIn.ReaduInt16();
nRowLast = aIn.ReaduInt16();
nColFirst = aIn.ReaduInt8();
nColLast = aIn.ReaduInt8();
if( nExtSheet >= 0 )
// from external
{
if( rR.pExtSheetBuff->GetScTabIndex( nExtSheet, nTabLast ) )
{
nTabFirst = nTabLast;
nExtSheet = 0; // found
}
else
{
aPool << ocBad;
aPool >> aStack;
nExtSheet = 1; // don't create a CompleteRef
}
}
if( nExtSheet <= 0 )
{// in current Workbook
// first part of range
ScSingleRefData& rR1 = aCRD.Ref1;
ScSingleRefData& rR2 = aCRD.Ref2;
rR1.SetAbsTab(nTabFirst);
rR2.SetAbsTab(nTabLast);
rR1.SetFlag3D(true);
rR2.SetFlag3D( nTabFirst != nTabLast );
ExcRelToScRel( nRowFirst, nColFirst, aCRD.Ref1, bRangeName );
ExcRelToScRel( nRowLast, nColLast, aCRD.Ref2, bRangeName );
if( IsComplColRange( nColFirst, nColLast ) )
SetComplCol( aCRD );
else if( IsComplRowRange( nRowFirst, nRowLast ) )
SetComplRow( aCRD );
switch ( nOp )
{
case 0x5D:
case 0x7D:
case 0x3D: // Deleted 3-D Area Reference [ 277]
// no information which part is deleted, set all
rR1.SetColDeleted( true );
rR1.SetRowDeleted( true );
rR2.SetColDeleted( true );
rR2.SetRowDeleted( true );
}
if ( !ValidTab(static_cast<SCTAB>(nTabFirst)) )
rR1.SetTabDeleted( true );
if ( !ValidTab(static_cast<SCTAB>(nTabLast)) )
rR2.SetTabDeleted( true );
aStack << aPool.Store( aCRD );
}//END in current Workbook
}
break;
default: bError = true;
}
bError |= !aIn.IsValid();
}
ConvErr eRet;
if( bError )
{
aPool << ocBad;
aPool >> aStack;
pResult = aPool.GetTokenArray( GetDocImport().getDoc(), aStack.Get());
eRet = ConvErr::Ni;
}
else if( aIn.GetRecPos() != nEndPos )
{
aPool << ocBad;
aPool >> aStack;
pResult = aPool.GetTokenArray( GetDocImport().getDoc(), aStack.Get());
eRet = ConvErr::Count;
}
else if( bArrayFormula )
{
pResult = nullptr;
eRet = ConvErr::OK;
}
else
{
pResult = aPool.GetTokenArray( GetDocImport().getDoc(), aStack.Get());
eRet = ConvErr::OK;
}
aIn.Seek( nEndPos );
if( eRet == ConvErr::OK )
ReadExtensions( aExtensions, aIn );
return eRet;
}
// stream seeks to first byte after <nFormulaLen>
ConvErr ExcelToSc::Convert( ScRangeListTabs& rRangeList, XclImpStream& aIn, std::size_t nFormulaLen,
SCTAB nTab, const FORMULA_TYPE eFT )
{
RootData& rR = GetOldRoot();
sal_uInt8 nOp, nLen;
bool bError = false;
const bool bRangeName = eFT == FT_RangeName;
const bool bSharedFormula = eFT == FT_SharedFormula;
const bool bRNorSF = bRangeName || bSharedFormula;
ScSingleRefData aSRD;
ScComplexRefData aCRD;
aCRD.Ref1.SetAbsTab(aEingPos.Tab());
aCRD.Ref2.SetAbsTab(aEingPos.Tab());
if( nFormulaLen == 0 )
return ConvErr::OK;
std::size_t nEndPos = aIn.GetRecPos() + nFormulaLen;
while( (aIn.GetRecPos() < nEndPos) && !bError )
{
nOp = aIn.ReaduInt8();
std::size_t nIgnore = 0;
// always reset flags
aSRD.InitFlags();
aCRD.InitFlags();
switch( nOp ) // book page:
{ // SDK4 SDK5
case 0x01: // Array Formula [325 ]
// Array Formula or Shared Formula [ 277]
case 0x02: // Data Table [325 277]
nIgnore = (meBiff == EXC_BIFF2) ? 3 : 4;
break;
case 0x03: // Addition [312 264]
case 0x04: // Subtraction [313 264]
case 0x05: // Multiplication [313 264]
case 0x06: // Division [313 264]
case 0x07: // Exponentiation [313 265]
case 0x08: // Concatenation [313 265]
case 0x09: // Less Than [313 265]
case 0x0A: // Less Than or Equal [313 265]
case 0x0B: // Equal [313 265]
case 0x0C: // Greater Than or Equal [313 265]
case 0x0D: // Greater Than [313 265]
case 0x0E: // Not Equal [313 265]
case 0x0F: // Intersection [314 265]
case 0x10: // Union [314 265]
case 0x11: // Range [314 265]
case 0x12: // Unary Plus [312 264]
case 0x13: // Unary Minus [312 264]
case 0x14: // Percent Sign [312 264]
case 0x15: // Parenthesis [326 278]
case 0x16: // Missing Argument [314 266]
break;
case 0x17: // String Constant [314 266]
nLen = aIn.ReaduInt8();
nIgnore = nLen;
break;
case 0x19: // Special Attribute [327 279]
{
sal_uInt16 nData(0), nFactor(0);
sal_uInt8 nOpt = aIn.ReaduInt8();
if( meBiff == EXC_BIFF2 )
{
nData = aIn.ReaduInt8();
nFactor = 1;
}
else
{
nData = aIn.ReaduInt16();
nFactor = 2;
}
if( nOpt & 0x04 )
{
// nFactor -> skip bytes or words AttrChoose
++nData;
aIn.Ignore(static_cast<std::size_t>(nData) * nFactor);
}
}
break;
case 0x1A: // External Reference [330 ]
switch( meBiff )
{
case EXC_BIFF2: nIgnore = 7; break;
case EXC_BIFF3:
case EXC_BIFF4: nIgnore = 10; break;
case EXC_BIFF5: SAL_INFO( "sc", "-ExcelToSc::Convert(): 0x1A does not exist in Biff5!" );
[[fallthrough]];
default: SAL_INFO( "sc", "-ExcelToSc::Convert(): A little oblivious?" );
}
break;
case 0x1B: // End External Reference [330 ]
switch( meBiff )
{
case EXC_BIFF2: nIgnore = 3; break;
case EXC_BIFF3:
case EXC_BIFF4: nIgnore = 4; break;
case EXC_BIFF5: SAL_INFO( "sc", "-ExcelToSc::Convert(): 0x1B does not exist in Biff5!" );
[[fallthrough]];
default: SAL_INFO( "sc", "-ExcelToSc::Convert(): A little oblivious?" );
}
break;
case 0x1C: // Error Value [314 266]
case 0x1D: // Boolean [315 266]
nIgnore = 1;
break;
case 0x1E: // Integer [315 266]
case 0x58:
case 0x78:
case 0x38: // Command-Equivalent Function [333 ]
nIgnore = 2;
break;
case 0x1F: // Number [315 266]
nIgnore = 8;
break;
case 0x40:
case 0x60:
case 0x20: // Array Constant [317 268]
nIgnore = (meBiff == EXC_BIFF2) ? 6 : 7;
break;
case 0x41:
case 0x61:
case 0x21: // Function, Fixed Number of Arguments [333 282]
nIgnore = (meBiff <= EXC_BIFF3) ? 1 : 2;
break;
case 0x42:
case 0x62:
case 0x22: // Function, Variable Number of Arg. [333 283]
nIgnore = (meBiff <= EXC_BIFF3) ? 2 : 3;
break;
case 0x43:
case 0x63:
case 0x23: // Name [318 269]
switch( meBiff )
{
case EXC_BIFF2: nIgnore = 7; break;
case EXC_BIFF3:
case EXC_BIFF4: nIgnore = 10; break;
case EXC_BIFF5: nIgnore = 14; break;
default: OSL_FAIL( "-ExcelToSc::Convert(): A little oblivious?" );
}
break;
case 0x44:
case 0x64:
case 0x24: // Cell Reference [319 270]
{
sal_uInt16 nUINT16 = aIn.ReaduInt16();
sal_uInt8 nByte = aIn.ReaduInt8();
aSRD.SetAbsCol(static_cast<SCCOL>(nByte));
aSRD.SetAbsRow(nUINT16 & 0x3FFF);
aSRD.SetRelTab(0);
aSRD.SetFlag3D( bRangeName );
ExcRelToScRel( nUINT16, nByte, aSRD, bRangeName );
rRangeList.Append(aSRD.toAbs(GetDocImport().getDoc(), aEingPos), nTab);
break;
}
case 0x45:
case 0x65:
case 0x25: // Area Reference [320 270]
{
sal_uInt16 nRowFirst, nRowLast;
sal_uInt8 nColFirst, nColLast;
ScSingleRefData &rSRef1 = aCRD.Ref1;
ScSingleRefData &rSRef2 = aCRD.Ref2;
nRowFirst = aIn.ReaduInt16();
nRowLast = aIn.ReaduInt16();
nColFirst = aIn.ReaduInt8();
nColLast = aIn.ReaduInt8();
rSRef1.SetRelTab(0);
rSRef2.SetRelTab(0);
rSRef1.SetFlag3D( bRangeName );
rSRef2.SetFlag3D( bRangeName );
ExcRelToScRel( nRowFirst, nColFirst, aCRD.Ref1, bRangeName );
ExcRelToScRel( nRowLast, nColLast, aCRD.Ref2, bRangeName );
if( IsComplColRange( nColFirst, nColLast ) )
SetComplCol( aCRD );
else if( IsComplRowRange( nRowFirst, nRowLast ) )
SetComplRow( aCRD );
rRangeList.Append(aCRD.toAbs(GetDocImport().getDoc(), aEingPos), nTab);
}
break;
case 0x46:
case 0x66:
case 0x26: // Constant Reference Subexpression [321 271]
case 0x47:
case 0x67:
case 0x27: // Erroneous Constant Reference Subexpr. [322 272]
case 0x48:
case 0x68:
case 0x28: // Incomplete Constant Reference Subexpr.[331 281]
nIgnore = (meBiff == EXC_BIFF2) ? 4 : 6;
break;
case 0x4A:
case 0x6A:
case 0x2A: // Deleted Cell Reference [323 273]
nIgnore = 3;
break;
case 0x4B:
case 0x6B:
case 0x2B: // Deleted Area Reference [323 273]
nIgnore = 6;
break;
case 0x4C:
case 0x6C:
case 0x2C: // Cell Reference Within a Name [323 ]
// Cell Reference Within a Shared Formula[ 273]
{
sal_uInt16 nUINT16 = aIn.ReaduInt16();
sal_uInt8 nByte = aIn.ReaduInt8(); // >> Attribute, Row >> Col
aSRD.SetRelTab(0);
aSRD.SetFlag3D( bRangeName );
ExcRelToScRel( nUINT16, nByte, aSRD, bRNorSF );
rRangeList.Append(aSRD.toAbs(GetDocImport().getDoc(), aEingPos), nTab);
break;
}
case 0x4D:
case 0x6D:
case 0x2D: // Area Reference Within a Name [324 ]
{ // Area Reference Within a Shared Formula[ 274]
sal_uInt16 nRowFirst, nRowLast;
sal_uInt8 nColFirst, nColLast;
aCRD.Ref1.SetRelTab(0);
aCRD.Ref2.SetRelTab(0);
aCRD.Ref1.SetFlag3D( bRangeName );
aCRD.Ref2.SetFlag3D( bRangeName );
nRowFirst = aIn.ReaduInt16();
nRowLast = aIn.ReaduInt16();
nColFirst = aIn.ReaduInt8();
nColLast = aIn.ReaduInt8();
ExcRelToScRel( nRowFirst, nColFirst, aCRD.Ref1, bRNorSF );
ExcRelToScRel( nRowLast, nColLast, aCRD.Ref2, bRNorSF );
if( IsComplColRange( nColFirst, nColLast ) )
SetComplCol( aCRD );
else if( IsComplRowRange( nRowFirst, nRowLast ) )
SetComplRow( aCRD );
rRangeList.Append(aCRD.toAbs(GetDocImport().getDoc(), aEingPos), nTab);
}
break;
case 0x49:
case 0x69:
case 0x29: // Variable Reference Subexpression [331 281]
case 0x4E:
case 0x6E:
case 0x2E: // Reference Subexpression Within a Name [332 282]
case 0x4F:
case 0x6F:
case 0x2F: // Incomplete Reference Subexpression... [332 282]
nIgnore = (meBiff == EXC_BIFF2) ? 1 : 2;
break;
case 0x59:
case 0x79:
case 0x39: // Name or External Name [ 275]
nIgnore = 24;
break;
case 0x5A:
case 0x7A:
case 0x3A: // 3-D Cell Reference [ 275]
{
sal_uInt16 nTabFirst, nTabLast, nRow;
sal_Int16 nExtSheet;
sal_uInt8 nCol;
nExtSheet = aIn.ReadInt16();
aIn.Ignore( 8 );
nTabFirst = aIn.ReaduInt16();
nTabLast = aIn.ReaduInt16();
nRow = aIn.ReaduInt16();
nCol = aIn.ReaduInt8();
if( nExtSheet >= 0 )
// from external
{
if( rR.pExtSheetBuff->GetScTabIndex( nExtSheet, nTabLast ) )
{
nTabFirst = nTabLast;
nExtSheet = 0; // found
}
else
{
aPool << ocBad;
aPool >> aStack;
nExtSheet = 1; // don't create a SingleRef
}
}
if( nExtSheet <= 0 )
{// in current Workbook
bool b3D = ( static_cast<SCTAB>(nTabFirst) != aEingPos.Tab() ) || bRangeName;
aSRD.SetAbsTab(nTabFirst);
aSRD.SetFlag3D( b3D );
ExcRelToScRel( nRow, nCol, aSRD, bRangeName );
if( nTabLast != nTabFirst )
{
aCRD.Ref1 = aSRD;
aCRD.Ref2 = aSRD;
aCRD.Ref2.SetAbsTab(static_cast<SCTAB>(nTabLast));
b3D = ( static_cast<SCTAB>(nTabLast) != aEingPos.Tab() );
aCRD.Ref2.SetFlag3D( b3D );
rRangeList.Append(aCRD.toAbs(GetDocImport().getDoc(), aEingPos), nTab);
}
else
rRangeList.Append(aSRD.toAbs(GetDocImport().getDoc(), aEingPos), nTab);
}
}
break;
case 0x5B:
case 0x7B:
case 0x3B: // 3-D Area Reference [ 276]
{
sal_uInt16 nTabFirst, nTabLast, nRowFirst, nRowLast;
sal_Int16 nExtSheet;
sal_uInt8 nColFirst, nColLast;
nExtSheet = aIn.ReadInt16();
aIn.Ignore( 8 );
nTabFirst = aIn.ReaduInt16();
nTabLast = aIn.ReaduInt16();
nRowFirst = aIn.ReaduInt16();
nRowLast = aIn.ReaduInt16();
nColFirst = aIn.ReaduInt8();
nColLast = aIn.ReaduInt8();
if( nExtSheet >= 0 )
// from external
{
if( rR.pExtSheetBuff->GetScTabIndex( nExtSheet, nTabLast ) )
{
nTabFirst = nTabLast;
nExtSheet = 0; // found
}
else
{
aPool << ocBad;
aPool >> aStack;
nExtSheet = 1; // don't create a CompleteRef
}
}
if( nExtSheet <= 0 )
{// in current Workbook
// first part of range
ScSingleRefData &rR1 = aCRD.Ref1;
ScSingleRefData &rR2 = aCRD.Ref2;
rR1.SetAbsTab(nTabFirst);
rR2.SetAbsTab(nTabLast);
rR1.SetFlag3D( ( static_cast<SCTAB>(nTabFirst) != aEingPos.Tab() ) || bRangeName );
rR2.SetFlag3D( ( static_cast<SCTAB>(nTabLast) != aEingPos.Tab() ) || bRangeName );
ExcRelToScRel( nRowFirst, nColFirst, aCRD.Ref1, bRangeName );
ExcRelToScRel( nRowLast, nColLast, aCRD.Ref2, bRangeName );
if( IsComplColRange( nColFirst, nColLast ) )
SetComplCol( aCRD );
else if( IsComplRowRange( nRowFirst, nRowLast ) )
SetComplRow( aCRD );
rRangeList.Append(aCRD.toAbs(GetDocImport().getDoc(), aEingPos), nTab);
}//END in current Workbook
}
break;
case 0x5C:
case 0x7C:
case 0x3C: // Deleted 3-D Cell Reference [ 277]
nIgnore = 17;
break;
case 0x5D:
case 0x7D:
case 0x3D: // Deleted 3-D Area Reference [ 277]
nIgnore = 20;
break;
default: bError = true;
}
bError |= !aIn.IsValid();
aIn.Ignore( nIgnore );
}
ConvErr eRet;
if( bError )
eRet = ConvErr::Ni;
else if( aIn.GetRecPos() != nEndPos )
eRet = ConvErr::Count;
else
eRet = ConvErr::OK;
aIn.Seek( nEndPos );
return eRet;
}
void ExcelToSc::ConvertExternName( std::unique_ptr<ScTokenArray>& /*rpArray*/, XclImpStream& /*rStrm*/, std::size_t /*nFormulaLen*/,
const OUString& /*rUrl*/, const vector<OUString>& /*rTabNames*/ )
{
}
void ExcelToSc::GetAbsRefs( ScRangeList& rRangeList, XclImpStream& rStrm, std::size_t nLen )
{
OSL_ENSURE_BIFF( GetBiff() == EXC_BIFF5 );
if( GetBiff() != EXC_BIFF5 )
return;
sal_uInt8 nOp;
sal_uInt16 nRow1, nRow2;
sal_uInt8 nCol1, nCol2;
SCTAB nTab1, nTab2;
sal_uInt16 nTabFirst, nTabLast;
sal_Int16 nRefIdx;
std::size_t nSeek;
std::size_t nEndPos = rStrm.GetRecPos() + nLen;
while( rStrm.IsValid() && (rStrm.GetRecPos() < nEndPos) )
{
nOp = rStrm.ReaduInt8();
nSeek = 0;
switch( nOp )
{
case 0x44:
case 0x64:
case 0x24: // Cell Reference [319 270]
case 0x4C:
case 0x6C:
case 0x2C: // Cell Reference Within a Name [323 ]
// Cell Reference Within a Shared Formula[ 273]
nRow1 = rStrm.ReaduInt16();
nCol1 = rStrm.ReaduInt8();
nRow2 = nRow1;
nCol2 = nCol1;
nTab1 = nTab2 = GetCurrScTab();
goto _common;
case 0x45:
case 0x65:
case 0x25: // Area Reference [320 270]
case 0x4D:
case 0x6D:
case 0x2D: // Area Reference Within a Name [324 ]
// Area Reference Within a Shared Formula[ 274]
nRow1 = rStrm.ReaduInt16();
nRow2 = rStrm.ReaduInt16();
nCol1 = rStrm.ReaduInt8();
nCol2 = rStrm.ReaduInt8();
nTab1 = nTab2 = GetCurrScTab();
goto _common;
case 0x5A:
case 0x7A:
case 0x3A: // 3-D Cell Reference [ 275]
nRefIdx = rStrm.ReadInt16();
rStrm.Ignore( 8 );
nTabFirst = rStrm.ReaduInt16();
nTabLast = rStrm.ReaduInt16();
nRow1 = rStrm.ReaduInt16();
nCol1 = rStrm.ReaduInt8();
nRow2 = nRow1;
nCol2 = nCol1;
goto _3d_common;
case 0x5B:
case 0x7B:
case 0x3B: // 3-D Area Reference [ 276]
nRefIdx = rStrm.ReadInt16();
rStrm.Ignore( 8 );
nTabFirst = rStrm.ReaduInt16();
nTabLast = rStrm.ReaduInt16();
nRow1 = rStrm.ReaduInt16();
nRow2 = rStrm.ReaduInt16();
nCol1 = rStrm.ReaduInt8();
nCol2 = rStrm.ReaduInt8();
_3d_common:
nTab1 = static_cast< SCTAB >( nTabFirst );
nTab2 = static_cast< SCTAB >( nTabLast );
// skip references to deleted sheets
if( (nRefIdx >= 0) || !ValidTab( nTab1 ) || (nTab1 != nTab2) )
break;
goto _common;
_common:
// do not check abs/rel flags, linked controls have set them!
{
ScRange aScRange;
nRow1 &= 0x3FFF;
nRow2 &= 0x3FFF;
if( GetAddressConverter().ConvertRange( aScRange, XclRange( nCol1, nRow1, nCol2, nRow2 ), nTab1, nTab2, true ) )
rRangeList.push_back( aScRange );
}
break;
case 0x03: // Addition [312 264]
case 0x04: // Subtraction [313 264]
case 0x05: // Multiplication [313 264]
case 0x06: // Division [313 264]
case 0x07: // Exponentiation [313 265]
case 0x08: // Concatenation [313 265]
case 0x09: // Less Than [313 265]
case 0x0A: // Less Than or Equal [313 265]
case 0x0B: // Equal [313 265]
case 0x0C: // Greater Than or Equal [313 265]
case 0x0D: // Greater Than [313 265]
case 0x0E: // Not Equal [313 265]
case 0x0F: // Intersection [314 265]
case 0x10: // Union [314 265]
case 0x11: // Range [314 265]
case 0x12: // Unary Plus [312 264]
case 0x13: // Unary Minus [312 264]
case 0x14: // Percent Sign [312 264]
case 0x15: // Parenthesis [326 278]
case 0x16: // Missing Argument [314 266]
break;
case 0x1C: // Error Value [314 266]
case 0x1D: // Boolean [315 266]
nSeek = 1;
break;
case 0x1E: // Integer [315 266]
case 0x41:
case 0x61:
case 0x21: // Function, Fixed Number of Arguments [333 282]
case 0x49:
case 0x69:
case 0x29: // Variable Reference Subexpression [331 281]
case 0x4E:
case 0x6E:
case 0x2E: // Reference Subexpression Within a Name [332 282]
case 0x4F:
case 0x6F:
case 0x2F: // Incomplete Reference Subexpression... [332 282]
case 0x58:
case 0x78:
case 0x38: // Command-Equivalent Function [333 ]
nSeek = 2;
break;
case 0x42:
case 0x62:
case 0x22: // Function, Variable Number of Arg. [333 283]
case 0x4A:
case 0x6A:
case 0x2A: // Deleted Cell Reference [323 273]
nSeek = 3;
break;
case 0x01: // Array Formula [325 ]
// Array Formula or Shared Formula [ 277]
case 0x02: // Data Table [325 277]
nSeek = 4;
break;
case 0x46:
case 0x66:
case 0x26: // Constant Reference Subexpression [321 271]
case 0x47:
case 0x67:
case 0x27: // Erroneous Constant Reference Subexpr. [322 272]
case 0x48:
case 0x68:
case 0x28: // Incomplete Constant Reference Subexpr.[331 281]
case 0x4B:
case 0x6B:
case 0x2B: // Deleted Area Reference [323 273]
nSeek = 6;
break;
case 0x40:
case 0x60:
case 0x20: // Array Constant [317 268]
nSeek = 7;
break;
case 0x1F: // Number [315 266]
nSeek = 8;
break;
case 0x43:
case 0x63:
case 0x23: // Name [318 269]
nSeek = 14;
break;
case 0x5C:
case 0x7C:
case 0x3C: // Deleted 3-D Cell Reference [ 277]
nSeek = 17;
break;
case 0x5D:
case 0x7D:
case 0x3D: // Deleted 3-D Area Reference [ 277]
nSeek = 20;
break;
case 0x59:
case 0x79:
case 0x39: // Name or External Name [ 275]
nSeek = 24;
break;
case 0x17: // String Constant [314 266]
nSeek = rStrm.ReaduInt8();
break;
case 0x19: // Special Attribute [327 279]
{
sal_uInt8 nOpt;
sal_uInt16 nData;
nOpt = rStrm.ReaduInt8();
nData = rStrm.ReaduInt16();
if( nOpt & 0x04 )
nSeek = nData * 2 + 2;
}
break;
}
rStrm.Ignore( nSeek );
}
rStrm.Seek( nEndPos );
}
void ExcelToSc::DoMulArgs( DefTokenId eId, sal_uInt8 nCnt )
{
TokenId eParam[ 256 ];
sal_Int32 nPass;
if( eId == ocCeil || eId == ocFloor )
{
aStack << aPool.Store( 1.0 ); // default, because not present in Excel
nCnt++;
}
for( nPass = 0; aStack.HasMoreTokens() && (nPass < nCnt); nPass++ )
aStack >> eParam[ nPass ];
// #i70925# reduce parameter count, if no more tokens available on token stack
if( nPass < nCnt )
nCnt = static_cast< sal_uInt8 >( nPass );
if( nCnt > 0 && eId == ocExternal )
{
TokenId n = eParam[ nCnt - 1 ];
//##### ADJUST STUPIDITY FOR BASIC-FUNCS!
if( const OUString* pExt = aPool.GetExternal( n ) )
{
if( const XclFunctionInfo* pFuncInfo = maFuncProv.GetFuncInfoFromXclMacroName( *pExt ) )
aPool << pFuncInfo->meOpCode;
else
aPool << n;
nCnt--;
}
else
aPool << eId;
}
else
aPool << eId;
aPool << ocOpen;
if( nCnt > 0 )
{
// attention: 0 = last parameter, nCnt-1 = first parameter
sal_Int16 nSkipEnd = -1; // skip all parameters <= nSkipEnd
sal_Int16 nLast = nCnt - 1;
// functions for which parameters have to be skipped
if( eId == ocPercentrank && nCnt == 3 )
nSkipEnd = 0; // skip last parameter if necessary
// Joost special cases
else if( eId == ocIf )
{
sal_uInt16 nNullParam = 0;
for( nPass = 0 ; nPass < nCnt ; nPass++ )
{
if( aPool.IsSingleOp( eParam[ nPass ], ocMissing ) )
{
if( !nNullParam )
nNullParam = static_cast<sal_uInt16>(aPool.Store( 0.0 ));
eParam[ nPass ] = nNullParam;
}
}
}
// [Parameter{;Parameter}]
if( nLast > nSkipEnd )
{
// nSkipEnd is either 0 or -1 => nLast >= 0
aPool << eParam[ nLast ];
for( nPass = nLast - 1 ; nPass > nSkipEnd ; nPass-- )
{
// nPass > nSkipEnd => nPass >= 0
aPool << ocSep << eParam[nPass];
}
}
}
aPool << ocClose;
aPool >> aStack;
}
void ExcelToSc::ExcRelToScRel( sal_uInt16 nRow, sal_uInt8 nCol, ScSingleRefData &rSRD, const bool bName )
{
if( bName )
{
// C O L
if( nRow & 0x4000 )
rSRD.SetRelCol(nCol);
else
rSRD.SetAbsCol(nCol);
// R O W
if( nRow & 0x8000 )
{// rel Row
if( nRow & 0x2000 ) // Bit 13 set?
// Row negative
rSRD.SetRelRow(nRow | 0xC000);
else
// Row positive
rSRD.SetRelRow(nRow & nRowMask);
}
else
{// abs Row
rSRD.SetAbsRow(nRow & nRowMask);
}
// T A B
// abs needed if rel in shared formula for ScCompiler UpdateNameReference
if ( rSRD.IsTabRel() && !rSRD.IsFlag3D() )
rSRD.SetAbsTab(GetCurrScTab());
}
else
{
bool bColRel = (nRow & 0x4000) > 0;
bool bRowRel = (nRow & 0x8000) > 0;
if (bColRel)
rSRD.SetRelCol(nCol - aEingPos.Col());
else
rSRD.SetAbsCol(nCol);
rSRD.SetAbsRow(nRow & nRowMask);
if (bRowRel)
rSRD.SetRelRow(rSRD.Row() - aEingPos.Row());
// T A B
// #i10184# abs needed if rel in shared formula for ScCompiler UpdateNameReference
if ( rSRD.IsTabRel() && !rSRD.IsFlag3D() )
rSRD.SetAbsTab(GetCurrScTab() + rSRD.Tab());
}
}
std::unique_ptr<ScTokenArray> ExcelToSc::GetBoolErr( XclBoolError eType )
{
FormulaError nError;
aPool.Reset();
aStack.Reset();
DefTokenId eOc;
switch( eType )
{
case xlErrNull: eOc = ocStop; nError = FormulaError::NoCode; break;
case xlErrDiv0: eOc = ocStop; nError = FormulaError::DivisionByZero; break;
case xlErrValue: eOc = ocStop; nError = FormulaError::NoValue; break;
case xlErrRef: eOc = ocStop; nError = FormulaError::NoRef; break;
case xlErrName: eOc = ocStop; nError = FormulaError::NoName; break;
case xlErrNum: eOc = ocStop; nError = FormulaError::IllegalFPOperation; break;
case xlErrNA: eOc = ocNotAvail; nError = FormulaError::NotAvailable; break;
case xlErrTrue: eOc = ocTrue; nError = FormulaError::NONE; break;
case xlErrFalse: eOc = ocFalse; nError = FormulaError::NONE; break;
case xlErrUnknown: eOc = ocStop; nError = FormulaError::UnknownState; break;
default:
OSL_FAIL( "ExcelToSc::GetBoolErr - wrong enum!" );
eOc = ocNoName;
nError = FormulaError::UnknownState;
}
aPool << eOc;
if( eOc != ocStop )
aPool << ocOpen << ocClose;
aPool >> aStack;
std::unique_ptr<ScTokenArray> pResult = aPool.GetTokenArray( GetDocImport().getDoc(), aStack.Get());
if( nError != FormulaError::NONE )
pResult->SetCodeError( nError );
pResult->SetExclusiveRecalcModeNormal();
return pResult;
}
bool ExcelToSc::ReadSharedFormulaPosition( XclImpStream& rStrm, SCCOL& rCol, SCROW& rRow )
{
rStrm.PushPosition();
sal_uInt8 nOp;
nOp = rStrm.ReaduInt8();
if (nOp != 0x01) // must be PtgExp token.
{
rStrm.PopPosition();
return false;
}
sal_uInt16 nRow, nCol;
nRow = rStrm.ReaduInt16();
nCol = rStrm.ReaduInt16();
rStrm.PopPosition();
rCol = nCol;
rRow = nRow;
return true;
}
const ScTokenArray* ExcelToSc::GetSharedFormula( const ScAddress& rRefPos ) const
{
return GetOldRoot().pShrfmlaBuff->Find(rRefPos);
}
void ExcelToSc::SetError( ScFormulaCell &rCell, const ConvErr eErr )
{
FormulaError nInd;
switch( eErr )
{
case ConvErr::Ni: nInd = FormulaError::UnknownToken; break;
case ConvErr::Count: nInd = FormulaError::CodeOverflow; break;
default: nInd = FormulaError::NoCode; // I had no better idea
}
rCell.SetErrCode( nInd );
}
void ExcelToSc::SetComplCol( ScComplexRefData &rCRD )
{
ScSingleRefData &rSRD = rCRD.Ref2;
ScDocument& rDoc = GetDocImport().getDoc();
if( rSRD.IsColRel() )
rSRD.SetRelCol(rDoc.MaxCol() - aEingPos.Col());
else
rSRD.SetAbsCol(rDoc.MaxCol());
}
void ExcelToSc::SetComplRow( ScComplexRefData &rCRD )
{
ScSingleRefData &rSRD = rCRD.Ref2;
ScDocument& rDoc = GetDocImport().getDoc();
if( rSRD.IsRowRel() )
rSRD.SetRelRow(rDoc.MaxRow() - aEingPos.Row());
else
rSRD.SetAbsRow(rDoc.MaxRow());
}
void ExcelToSc::ReadExtensionArray( unsigned int n, XclImpStream& aIn )
{
sal_uInt8 nByte = aIn.ReaduInt8();
sal_uInt16 nUINT16 = aIn.ReaduInt16();
SCSIZE nC, nCols;
SCSIZE nR, nRows;
if( GetBiff() == EXC_BIFF8 )
{
nCols = nByte + 1;
nRows = nUINT16 + 1;
}
else
{
nCols = nByte ? nByte : 256;
nRows = nUINT16;
}
ScMatrix* pMatrix = aPool.GetMatrix( n );
if( nullptr != pMatrix )
{
pMatrix->Resize(nCols, nRows);
pMatrix->GetDimensions( nC, nR);
if( nC != nCols || nR != nRows )
{
OSL_FAIL( "ExcelToSc::ReadExtensionArray - matrix size mismatch" );
pMatrix = nullptr;
}
}
else
{
OSL_FAIL( "ExcelToSc::ReadExtensionArray - missing matrix" );
}
//assuming worst case scenario of unknown types
const size_t nMinRecordSize = 1;
const size_t nMaxRows = aIn.GetRecLeft() / (nMinRecordSize * nCols);
if (nRows > nMaxRows)
{
SAL_WARN("sc", "Parsing error: " << nMaxRows <<
" max possible rows, but " << nRows << " claimed, truncating");
nRows = nMaxRows;
}
svl::SharedStringPool& rPool = GetDoc().GetSharedStringPool();
for( nR = 0 ; nR < nRows; nR++ )
{
for( nC = 0 ; nC < nCols; nC++ )
{
nByte = aIn.ReaduInt8();
switch( nByte )
{
case EXC_CACHEDVAL_EMPTY:
aIn.Ignore( 8 );
if( nullptr != pMatrix )
{
pMatrix->PutEmpty( nC, nR );
}
break;
case EXC_CACHEDVAL_DOUBLE:
{
double fDouble = aIn.ReadDouble();
if( nullptr != pMatrix )
{
pMatrix->PutDouble( fDouble, nC, nR );
}
break;
}
case EXC_CACHEDVAL_STRING:
{
OUString aString;
if( GetBiff() == EXC_BIFF8 )
{
nUINT16 = aIn.ReaduInt16();
aString = aIn.ReadUniString( nUINT16 );
}
else
{
nByte = aIn.ReaduInt8();
aString = aIn.ReadRawByteString( nByte );
}
if( nullptr != pMatrix )
{
pMatrix->PutString(rPool.intern(aString), nC, nR);
}
break;
}
case EXC_CACHEDVAL_BOOL:
nByte = aIn.ReaduInt8();
aIn.Ignore( 7 );
if( nullptr != pMatrix )
{
pMatrix->PutBoolean( nByte != 0, nC, nR );
}
break;
case EXC_CACHEDVAL_ERROR:
nByte = aIn.ReaduInt8();
aIn.Ignore( 7 );
if( nullptr != pMatrix )
{
pMatrix->PutError( XclTools::GetScErrorCode( nByte ), nC, nR );
}
break;
}
}
}
}
void ExcelToSc::ReadExtensionNlr( XclImpStream& aIn )
{
sal_uInt32 nFlags;
nFlags = aIn.ReaduInt32();
sal_uInt32 nCount = nFlags & EXC_TOK_NLR_ADDMASK;
aIn.Ignore( nCount * 4 ); // Drop the cell positions
}
void ExcelToSc::ReadExtensionMemArea( XclImpStream& aIn )
{
sal_uInt16 nCount = aIn.ReaduInt16();
aIn.Ignore( static_cast<std::size_t>(nCount) * ((GetBiff() == EXC_BIFF8) ? 8 : 6) ); // drop the ranges
}
void ExcelToSc::ReadExtensions( const ExtensionTypeVec& rExtensions,
XclImpStream& aIn )
{
unsigned int nArray = 0;
for(int eType : rExtensions)
{
switch( eType )
{
case EXTENSION_ARRAY:
ReadExtensionArray( nArray++, aIn );
break;
case EXTENSION_NLR:
ReadExtensionNlr( aIn );
break;
case EXTENSION_MEMAREA:
ReadExtensionMemArea( aIn );
break;
}
}
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
↑ V1051 Consider checking for misprints. It's possible that the 'nUINT16' should be checked here.