2000-09-18 23:16:46 +00:00
|
|
|
/*************************************************************************
|
|
|
|
*
|
|
|
|
* $RCSfile: rangenam.cxx,v $
|
|
|
|
*
|
2001-06-26 10:34:05 +00:00
|
|
|
* $Revision: 1.8 $
|
2000-09-18 23:16:46 +00:00
|
|
|
*
|
2001-06-26 10:34:05 +00:00
|
|
|
* last change: $Author: sab $ $Date: 2001-06-26 11:34:05 $
|
2000-09-18 23:16:46 +00:00
|
|
|
*
|
|
|
|
* The Contents of this file are made available subject to the terms of
|
|
|
|
* either of the following licenses
|
|
|
|
*
|
|
|
|
* - GNU Lesser General Public License Version 2.1
|
|
|
|
* - Sun Industry Standards Source License Version 1.1
|
|
|
|
*
|
|
|
|
* Sun Microsystems Inc., October, 2000
|
|
|
|
*
|
|
|
|
* GNU Lesser General Public License Version 2.1
|
|
|
|
* =============================================
|
|
|
|
* Copyright 2000 by Sun Microsystems, Inc.
|
|
|
|
* 901 San Antonio Road, Palo Alto, CA 94303, USA
|
|
|
|
*
|
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
* License version 2.1, as published by the Free Software Foundation.
|
|
|
|
*
|
|
|
|
* This library is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* Lesser General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
|
|
* License along with this library; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
|
|
|
* MA 02111-1307 USA
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* Sun Industry Standards Source License Version 1.1
|
|
|
|
* =================================================
|
|
|
|
* The contents of this file are subject to the Sun Industry Standards
|
|
|
|
* Source License Version 1.1 (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.openoffice.org/license.html.
|
|
|
|
*
|
|
|
|
* Software provided under this License is provided on an "AS IS" basis,
|
|
|
|
* WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
|
|
|
|
* WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
|
|
|
|
* MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
|
|
|
|
* See the License for the specific provisions governing your rights and
|
|
|
|
* obligations concerning the Software.
|
|
|
|
*
|
|
|
|
* The Initial Developer of the Original Code is: Sun Microsystems, Inc.
|
|
|
|
*
|
|
|
|
* Copyright: 2000 by Sun Microsystems, Inc.
|
|
|
|
*
|
|
|
|
* All Rights Reserved.
|
|
|
|
*
|
|
|
|
* Contributor(s): _______________________________________
|
|
|
|
*
|
|
|
|
*
|
|
|
|
************************************************************************/
|
|
|
|
|
|
|
|
#ifdef PCH
|
|
|
|
#include "core_pch.hxx"
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#pragma hdrstop
|
|
|
|
|
|
|
|
//------------------------------------------------------------------------
|
|
|
|
|
|
|
|
#include <tools/debug.hxx>
|
|
|
|
#include <string.h>
|
2001-03-14 15:02:54 +00:00
|
|
|
#include <unotools/collatorwrapper.hxx>
|
2000-09-18 23:16:46 +00:00
|
|
|
|
|
|
|
#include "rangenam.hxx"
|
|
|
|
#include "global.hxx"
|
|
|
|
#include "compiler.hxx"
|
|
|
|
#include "rangeutl.hxx"
|
|
|
|
#include "rechead.hxx"
|
|
|
|
#include "refupdat.hxx"
|
|
|
|
#include "document.hxx"
|
|
|
|
#include "indexmap.hxx"
|
|
|
|
|
|
|
|
|
|
|
|
//========================================================================
|
|
|
|
// ScRangeData
|
|
|
|
//========================================================================
|
|
|
|
|
|
|
|
// Interner ctor fuer das Suchen nach einem Index
|
|
|
|
|
|
|
|
ScRangeData::ScRangeData( USHORT n )
|
|
|
|
: nIndex( n ), pCode( NULL ), bModified( FALSE )
|
|
|
|
{}
|
|
|
|
|
|
|
|
ScRangeData::ScRangeData( ScDocument* pDok,
|
|
|
|
const String& rName,
|
|
|
|
const String& rSymbol,
|
|
|
|
USHORT nCol,
|
|
|
|
USHORT nRow,
|
|
|
|
USHORT nTab,
|
|
|
|
RangeType nType,
|
|
|
|
BOOL bEnglish ) :
|
|
|
|
aName ( rName ),
|
|
|
|
aPos ( nCol, nRow, nTab ),
|
|
|
|
eType ( nType ),
|
|
|
|
pDoc ( pDok ),
|
|
|
|
nIndex ( 0 ),
|
|
|
|
nExportIndex( 0 ),
|
|
|
|
pCode ( NULL ),
|
|
|
|
bModified ( FALSE )
|
|
|
|
{
|
|
|
|
if (rSymbol.Len() > 0)
|
|
|
|
{
|
|
|
|
ScCompiler aComp( pDoc, aPos );
|
|
|
|
aComp.SetCompileEnglish(bEnglish);
|
|
|
|
pCode = aComp.CompileString( rSymbol );
|
|
|
|
if( !pCode->GetError() )
|
|
|
|
{
|
|
|
|
pCode->Reset();
|
|
|
|
ScToken* p = pCode->GetNextReference();
|
|
|
|
if( p )// genau eine Referenz als erstes
|
|
|
|
{
|
|
|
|
if( p->GetType() == svSingleRef )
|
|
|
|
eType = eType | RT_ABSPOS;
|
|
|
|
else
|
|
|
|
eType = eType | RT_ABSAREA;
|
|
|
|
}
|
|
|
|
// ggf. den Fehlercode wg. unvollstaendiger Formel setzen!
|
|
|
|
// Dies ist fuer die manuelle Eingabe
|
|
|
|
aComp.CompileTokenArray();
|
|
|
|
pCode->DelRPN();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ScRangeData::ScRangeData( ScDocument* pDok,
|
|
|
|
const String& rName,
|
|
|
|
const ScTokenArray& rArr,
|
|
|
|
USHORT nCol,
|
|
|
|
USHORT nRow,
|
|
|
|
USHORT nTab,
|
|
|
|
RangeType nType ) :
|
|
|
|
aName ( rName ),
|
|
|
|
aPos ( nCol, nRow, nTab ),
|
|
|
|
eType ( nType ),
|
|
|
|
pDoc ( pDok ),
|
|
|
|
nIndex ( 0 ),
|
|
|
|
nExportIndex( 0 ),
|
|
|
|
pCode ( new ScTokenArray( rArr ) ),
|
|
|
|
bModified ( FALSE )
|
|
|
|
{
|
|
|
|
if( !pCode->GetError() )
|
|
|
|
{
|
|
|
|
pCode->Reset();
|
|
|
|
ScToken* p = pCode->GetNextReference();
|
|
|
|
if( p )// genau eine Referenz als erstes
|
|
|
|
{
|
|
|
|
if( p->GetType() == svSingleRef )
|
|
|
|
eType = eType | RT_ABSPOS;
|
|
|
|
else
|
|
|
|
eType = eType | RT_ABSAREA;
|
|
|
|
}
|
|
|
|
// Die Importfilter haben diesen Test nicht,
|
|
|
|
// da die benannten Bereiche z.T. noch unvollstaendig sind.
|
|
|
|
// if( !pCode->GetCodeLen() )
|
|
|
|
// {
|
|
|
|
// // ggf. den Fehlercode wg. unvollstaendiger Formel setzen!
|
|
|
|
// ScCompiler aComp( pDok, aPos, *pCode );
|
|
|
|
// aComp.CompileTokenArray();
|
|
|
|
// pCode->DelRPN();
|
|
|
|
// }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ScRangeData::ScRangeData( ScDocument* pDok,
|
|
|
|
const String& rName,
|
|
|
|
const ScAddress& rTarget ) :
|
|
|
|
aName ( rName ),
|
|
|
|
aPos ( rTarget ),
|
|
|
|
eType ( RT_NAME ),
|
|
|
|
pDoc ( pDok ),
|
|
|
|
nIndex ( 0 ),
|
|
|
|
nExportIndex( 0 ),
|
|
|
|
pCode ( new ScTokenArray ),
|
|
|
|
bModified ( FALSE )
|
|
|
|
{
|
|
|
|
SingleRefData aRefData;
|
|
|
|
aRefData.InitAddress( rTarget );
|
|
|
|
aRefData.SetFlag3D( TRUE );
|
|
|
|
pCode->AddSingleReference( aRefData );
|
|
|
|
ScCompiler aComp( pDoc, aPos, *pCode );
|
|
|
|
aComp.CompileTokenArray();
|
|
|
|
if ( !pCode->GetError() )
|
|
|
|
eType |= RT_ABSPOS;
|
|
|
|
}
|
|
|
|
|
|
|
|
ScRangeData::ScRangeData(const ScRangeData& rScRangeData) :
|
|
|
|
aName (rScRangeData.aName),
|
|
|
|
aPos (rScRangeData.aPos),
|
|
|
|
eType (rScRangeData.eType),
|
|
|
|
pDoc (rScRangeData.pDoc),
|
|
|
|
nIndex (rScRangeData.nIndex),
|
2001-06-26 10:34:05 +00:00
|
|
|
pCode (rScRangeData.pCode ? rScRangeData.pCode->Clone() : new ScTokenArray), // echte Kopie erzeugen (nicht copy-ctor)
|
2000-09-18 23:16:46 +00:00
|
|
|
bModified (rScRangeData.bModified)
|
|
|
|
{}
|
|
|
|
|
|
|
|
ScRangeData::~ScRangeData()
|
|
|
|
{
|
|
|
|
delete pCode;
|
|
|
|
}
|
|
|
|
|
|
|
|
DataObject* ScRangeData::Clone() const
|
|
|
|
{
|
|
|
|
return new ScRangeData(*this);
|
|
|
|
}
|
|
|
|
|
|
|
|
ScRangeData::ScRangeData
|
|
|
|
( SvStream& rStream, ScMultipleReadHeader& rHdr, USHORT nVer )
|
|
|
|
: pCode ( new ScTokenArray ),
|
|
|
|
bModified (FALSE)
|
|
|
|
|
|
|
|
{
|
|
|
|
rHdr.StartEntry();
|
|
|
|
|
|
|
|
if( nVer >= SC_NEW_TOKEN_ARRAYS )
|
|
|
|
{
|
|
|
|
UINT32 nPos;
|
|
|
|
BYTE nData;
|
|
|
|
rStream.ReadByteString( aName, rStream.GetStreamCharSet() );
|
|
|
|
rStream >> nPos >> eType >> nIndex >> nData;
|
|
|
|
if( nData & 0x0F )
|
|
|
|
rStream.SeekRel( nData & 0x0F );
|
|
|
|
aPos = ScAddress( nPos );
|
|
|
|
pCode->Load( rStream, nVer, aPos );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
UINT16 nTokLen, r, c, t;
|
|
|
|
rStream.ReadByteString( aName, rStream.GetStreamCharSet() );
|
|
|
|
rStream >> c >> r >> t >> eType >> nIndex >> nTokLen;
|
|
|
|
aPos.Set( c, r, t );
|
|
|
|
if( nTokLen )
|
|
|
|
pCode->Load30( rStream, aPos );
|
|
|
|
}
|
|
|
|
|
|
|
|
rHdr.EndEntry();
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOL ScRangeData::Store
|
|
|
|
( SvStream& rStream, ScMultipleWriteHeader& rHdr ) const
|
|
|
|
{
|
|
|
|
rHdr.StartEntry();
|
|
|
|
|
|
|
|
rStream.WriteByteString( aName, rStream.GetStreamCharSet() );
|
|
|
|
rStream << (UINT32) aPos << eType << nIndex << (BYTE) 0x00;
|
|
|
|
pCode->Store( rStream, aPos );
|
|
|
|
|
|
|
|
rHdr.EndEntry();
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOL ScRangeData::IsBeyond( USHORT nMaxRow ) const
|
|
|
|
{
|
|
|
|
if ( aPos.Row() > nMaxRow )
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
ScToken* t;
|
|
|
|
pCode->Reset();
|
|
|
|
while ( t = pCode->GetNextReference() )
|
2001-02-21 17:39:37 +00:00
|
|
|
if ( t->GetSingleRef().nRow > nMaxRow ||
|
|
|
|
(t->GetType() == svDoubleRef &&
|
|
|
|
t->GetDoubleRef().Ref2.nRow > nMaxRow) )
|
2000-09-18 23:16:46 +00:00
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ScRangeData::GuessPosition()
|
|
|
|
{
|
|
|
|
// setzt eine Position, mit der alle relative Referenzen bei CalcAbsIfRel
|
|
|
|
// ohne Fehler verabsolutiert werden koennen
|
|
|
|
|
|
|
|
DBG_ASSERT(aPos == ScAddress(), "die Position geht jetzt verloren");
|
|
|
|
|
|
|
|
INT16 nMinCol = 0;
|
|
|
|
INT16 nMinRow = 0;
|
|
|
|
INT16 nMinTab = 0;
|
|
|
|
|
|
|
|
ScToken* t;
|
|
|
|
pCode->Reset();
|
|
|
|
while ( t = pCode->GetNextReference() )
|
|
|
|
{
|
2001-02-21 17:39:37 +00:00
|
|
|
SingleRefData& rRef1 = t->GetSingleRef();
|
|
|
|
if ( rRef1.IsColRel() && rRef1.nRelCol < nMinCol )
|
|
|
|
nMinCol = rRef1.nRelCol;
|
|
|
|
if ( rRef1.IsRowRel() && rRef1.nRelRow < nMinRow )
|
|
|
|
nMinRow = rRef1.nRelRow;
|
|
|
|
if ( rRef1.IsTabRel() && rRef1.nRelTab < nMinTab )
|
|
|
|
nMinTab = rRef1.nRelTab;
|
2000-09-18 23:16:46 +00:00
|
|
|
|
|
|
|
if ( t->GetType() == svDoubleRef )
|
|
|
|
{
|
2001-02-21 17:39:37 +00:00
|
|
|
SingleRefData& rRef2 = t->GetDoubleRef().Ref2;
|
|
|
|
if ( rRef2.IsColRel() && rRef2.nRelCol < nMinCol )
|
|
|
|
nMinCol = rRef2.nRelCol;
|
|
|
|
if ( rRef2.IsRowRel() && rRef2.nRelRow < nMinRow )
|
|
|
|
nMinRow = rRef2.nRelRow;
|
|
|
|
if ( rRef2.IsTabRel() && rRef2.nRelTab < nMinTab )
|
|
|
|
nMinTab = rRef2.nRelTab;
|
2000-09-18 23:16:46 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
aPos = ScAddress( (USHORT)(-nMinCol), (USHORT)(-nMinRow), (USHORT)(-nMinTab) );
|
|
|
|
|
|
|
|
//! Test
|
|
|
|
// DBG_ERROR(String("Pos ")+String((USHORT)(-nMinCol))+String("/")+
|
|
|
|
// String((USHORT)(-nMinRow))+String("/")+String((USHORT)(-nMinTab)));
|
|
|
|
}
|
|
|
|
|
|
|
|
void ScRangeData::GetSymbol (String& rSymbol) const
|
|
|
|
{
|
|
|
|
ScCompiler aScComp(pDoc, aPos, *pCode);
|
|
|
|
aScComp.CreateStringFromTokenArray( rSymbol );
|
|
|
|
}
|
|
|
|
|
|
|
|
void ScRangeData::GetEnglishSymbol (String& rSymbol, BOOL bCompileXML) const
|
|
|
|
{
|
|
|
|
ScCompiler aScComp(pDoc, aPos, *pCode);
|
|
|
|
aScComp.SetCompileEnglish( TRUE );
|
|
|
|
aScComp.SetCompileXML( bCompileXML );
|
|
|
|
aScComp.CreateStringFromTokenArray( rSymbol );
|
|
|
|
}
|
|
|
|
|
2000-10-06 12:46:12 +00:00
|
|
|
void ScRangeData::UpdateSymbol( String& rSymbol, const ScAddress& rPos,
|
|
|
|
BOOL bEnglish, BOOL bCompileXML )
|
2000-09-18 23:16:46 +00:00
|
|
|
{
|
|
|
|
ScTokenArray* pTemp = pCode->Clone();
|
|
|
|
ScCompiler aComp( pDoc, rPos, *pTemp );
|
2000-10-06 12:46:12 +00:00
|
|
|
aComp.SetCompileEnglish( bEnglish );
|
|
|
|
aComp.SetCompileXML( bCompileXML );
|
2000-09-18 23:16:46 +00:00
|
|
|
aComp.MoveRelWrap();
|
|
|
|
aComp.CreateStringFromTokenArray( rSymbol );
|
|
|
|
delete pTemp;
|
|
|
|
}
|
|
|
|
|
2001-06-20 13:19:26 +00:00
|
|
|
void ScRangeData::UpdateSymbol( rtl::OUStringBuffer& rBuffer, const ScAddress& rPos,
|
|
|
|
BOOL bEnglish, BOOL bCompileXML )
|
|
|
|
{
|
|
|
|
ScTokenArray* pTemp = pCode->Clone();
|
|
|
|
ScCompiler aComp( pDoc, rPos, *pTemp );
|
|
|
|
aComp.SetCompileEnglish( bEnglish );
|
|
|
|
aComp.SetCompileXML( bCompileXML );
|
|
|
|
aComp.MoveRelWrap();
|
|
|
|
aComp.CreateStringFromTokenArray( rBuffer );
|
|
|
|
delete pTemp;
|
|
|
|
}
|
|
|
|
|
2000-09-18 23:16:46 +00:00
|
|
|
void ScRangeData::UpdateReference( UpdateRefMode eUpdateRefMode,
|
|
|
|
const ScRange& r,
|
|
|
|
short nDx, short nDy, short nDz )
|
|
|
|
{
|
|
|
|
BOOL bChanged = FALSE;
|
|
|
|
|
|
|
|
pCode->Reset();
|
|
|
|
if( pCode->GetNextReference() )
|
|
|
|
{
|
|
|
|
ScCompiler aComp( pDoc, aPos, *pCode );
|
|
|
|
BOOL bRelRef = aComp.UpdateNameReference( eUpdateRefMode, r,
|
|
|
|
nDx, nDy, nDz,
|
|
|
|
bChanged);
|
|
|
|
if (eType&RT_SHARED)
|
|
|
|
{
|
|
|
|
if (bRelRef)
|
|
|
|
eType = eType | RT_SHAREDMOD;
|
|
|
|
else
|
|
|
|
eType = eType & ~RT_SHAREDMOD;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bModified = bChanged;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void ScRangeData::UpdateTranspose( const ScRange& rSource, const ScAddress& rDest )
|
|
|
|
{
|
|
|
|
BOOL bChanged = FALSE;
|
|
|
|
|
|
|
|
ScToken* t;
|
|
|
|
pCode->Reset();
|
|
|
|
|
|
|
|
for( t = pCode->GetNextReference(); t; t = pCode->GetNextReference() )
|
|
|
|
{
|
|
|
|
if( t->GetType() != svIndex )
|
|
|
|
{
|
2001-02-21 17:39:37 +00:00
|
|
|
SingleDoubleRefModifier& rMod = (t->GetType() == svSingleRef ?
|
|
|
|
SingleDoubleRefModifier( t->GetSingleRef() ) :
|
|
|
|
SingleDoubleRefModifier( t->GetDoubleRef() ));
|
|
|
|
ComplRefData& rRef = rMod.Ref();
|
2000-09-18 23:16:46 +00:00
|
|
|
if (!rRef.Ref1.IsColRel() && !rRef.Ref1.IsRowRel() &&
|
|
|
|
(!rRef.Ref1.IsFlag3D() || !rRef.Ref1.IsTabRel()) &&
|
|
|
|
( t->GetType() == svSingleRef ||
|
|
|
|
(!rRef.Ref2.IsColRel() && !rRef.Ref2.IsRowRel() &&
|
|
|
|
(!rRef.Ref2.IsFlag3D() || !rRef.Ref2.IsTabRel()))))
|
|
|
|
{
|
2001-02-21 17:39:37 +00:00
|
|
|
if ( ScRefUpdate::UpdateTranspose( pDoc, rSource, rDest, rRef ) != UR_NOTHING )
|
2000-09-18 23:16:46 +00:00
|
|
|
bChanged = TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bModified = bChanged;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ScRangeData::UpdateGrow( const ScRange& rArea, USHORT nGrowX, USHORT nGrowY )
|
|
|
|
{
|
|
|
|
BOOL bChanged = FALSE;
|
|
|
|
|
|
|
|
ScToken* t;
|
|
|
|
pCode->Reset();
|
|
|
|
|
|
|
|
for( t = pCode->GetNextReference(); t; t = pCode->GetNextReference() )
|
|
|
|
{
|
|
|
|
if( t->GetType() != svIndex )
|
|
|
|
{
|
2001-02-21 17:39:37 +00:00
|
|
|
SingleDoubleRefModifier& rMod = (t->GetType() == svSingleRef ?
|
|
|
|
SingleDoubleRefModifier( t->GetSingleRef() ) :
|
|
|
|
SingleDoubleRefModifier( t->GetDoubleRef() ));
|
|
|
|
ComplRefData& rRef = rMod.Ref();
|
2000-09-18 23:16:46 +00:00
|
|
|
if (!rRef.Ref1.IsColRel() && !rRef.Ref1.IsRowRel() &&
|
|
|
|
(!rRef.Ref1.IsFlag3D() || !rRef.Ref1.IsTabRel()) &&
|
|
|
|
( t->GetType() == svSingleRef ||
|
|
|
|
(!rRef.Ref2.IsColRel() && !rRef.Ref2.IsRowRel() &&
|
|
|
|
(!rRef.Ref2.IsFlag3D() || !rRef.Ref2.IsTabRel()))))
|
|
|
|
{
|
2001-02-21 17:39:37 +00:00
|
|
|
if ( ScRefUpdate::UpdateGrow( rArea,nGrowX,nGrowY, rRef ) != UR_NOTHING )
|
2000-09-18 23:16:46 +00:00
|
|
|
bChanged = TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bModified = bChanged; // muss direkt hinterher ausgewertet werden
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOL ScRangeData::operator== (const ScRangeData& rData) const // fuer Undo
|
|
|
|
{
|
|
|
|
if ( nIndex != rData.nIndex ||
|
|
|
|
aName != rData.aName ||
|
|
|
|
aPos != rData.aPos ||
|
|
|
|
eType != rData.eType ) return FALSE;
|
|
|
|
|
|
|
|
USHORT nLen = pCode->GetLen();
|
|
|
|
if ( nLen != rData.pCode->GetLen() ) return FALSE;
|
|
|
|
|
|
|
|
ScToken** ppThis = pCode->GetArray();
|
|
|
|
ScToken** ppOther = rData.pCode->GetArray();
|
|
|
|
|
|
|
|
for ( USHORT i=0; i<nLen; i++ )
|
|
|
|
if ( ppThis[i] != ppOther[i] && !(*ppThis[i] == *ppOther[i]) )
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOL ScRangeData::IsRangeAtCursor( const ScAddress& rPos, BOOL bStartOnly ) const
|
|
|
|
{
|
|
|
|
BOOL bRet = FALSE;
|
|
|
|
ScRange aRange;
|
|
|
|
if ( IsReference(aRange) )
|
|
|
|
{
|
|
|
|
if ( bStartOnly )
|
|
|
|
bRet = ( rPos == aRange.aStart );
|
|
|
|
else
|
|
|
|
bRet = ( aRange.In( rPos ) );
|
|
|
|
}
|
|
|
|
return bRet;
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOL ScRangeData::IsRangeAtBlock( const ScRange& rBlock ) const
|
|
|
|
{
|
|
|
|
BOOL bRet = FALSE;
|
|
|
|
ScRange aRange;
|
|
|
|
if ( IsReference(aRange) )
|
|
|
|
bRet = ( rBlock == aRange );
|
|
|
|
return bRet;
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOL ScRangeData::IsReference( ScRange& rRange ) const
|
|
|
|
{
|
|
|
|
BOOL bIs = FALSE;
|
|
|
|
if ( eType & ( RT_ABSAREA | RT_REFAREA | RT_ABSPOS ) )
|
|
|
|
if ( pCode )
|
|
|
|
return pCode->IsReference( rRange );
|
|
|
|
|
|
|
|
return bIs;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ScRangeData::UpdateTabRef(USHORT nOldTable, USHORT nFlag, USHORT nNewTable)
|
|
|
|
{
|
|
|
|
pCode->Reset();
|
|
|
|
if( pCode->GetNextReference() )
|
|
|
|
{
|
|
|
|
ScRangeData* pRangeData; // darf nicht dereferenziert werden!!
|
|
|
|
BOOL bChanged;
|
|
|
|
ScCompiler aComp( pDoc, aPos, *pCode );
|
|
|
|
switch (nFlag)
|
|
|
|
{
|
|
|
|
case 1: // einfache InsertTab (doc.cxx)
|
|
|
|
pRangeData = aComp.UpdateInsertTab(nOldTable, TRUE ); // und CopyTab (doc2.cxx)
|
|
|
|
break;
|
|
|
|
case 2: // einfaches delete (doc.cxx)
|
|
|
|
pRangeData = aComp.UpdateDeleteTab(nOldTable, FALSE, TRUE, bChanged);
|
|
|
|
break;
|
|
|
|
case 3: // move (doc2.cxx)
|
|
|
|
{
|
|
|
|
pRangeData = aComp.UpdateMoveTab(nOldTable, nNewTable, TRUE );
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
{
|
|
|
|
DBG_ERROR("ScRangeName::UpdateTabRef: Unknown Flag");
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (eType&RT_SHARED)
|
|
|
|
{
|
|
|
|
if (pRangeData)
|
|
|
|
eType = eType | RT_SHAREDMOD;
|
|
|
|
else
|
|
|
|
eType = eType & ~RT_SHAREDMOD;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// wie beim Uebernehmen von Namen in Excel
|
|
|
|
|
|
|
|
void ScRangeData::MakeValidName( String& rName ) // static
|
|
|
|
{
|
|
|
|
if (!ScCompiler::HasCharTable())
|
|
|
|
ScCompiler::Init();
|
|
|
|
|
|
|
|
// ungueltige Zeichen vorne weglassen
|
|
|
|
xub_StrLen nPos = 0;
|
|
|
|
xub_StrLen nLen = rName.Len();
|
|
|
|
while ( nPos < nLen && !ScCompiler::IsWordChar( rName.GetChar(nPos) ) )
|
|
|
|
++nPos;
|
|
|
|
if ( nPos>0 )
|
|
|
|
rName.Erase(0,nPos);
|
|
|
|
|
|
|
|
// wenn vorne ein ungueltiges Anfangszeichen steht, '_' davor
|
|
|
|
if ( rName.Len() && !ScCompiler::IsCharWordChar( rName.GetChar(0) ) )
|
|
|
|
rName.Insert('_',0);
|
|
|
|
|
|
|
|
// ungueltige durch '_' ersetzen
|
|
|
|
nLen = rName.Len();
|
|
|
|
for (nPos=0; nPos<nLen; nPos++)
|
|
|
|
{
|
|
|
|
if ( !ScCompiler::IsWordChar( rName.GetChar(nPos) ) )
|
|
|
|
rName.SetChar( nPos, '_' );
|
|
|
|
}
|
|
|
|
|
|
|
|
// Name darf keine Referenz beinhalten, wie in IsNameValid
|
|
|
|
BOOL bOk;
|
|
|
|
do
|
|
|
|
{
|
|
|
|
bOk = TRUE;
|
|
|
|
ScRange aRange;
|
|
|
|
if( aRange.Parse( rName, NULL ) )
|
|
|
|
bOk = FALSE;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ScAddress aAddr;
|
|
|
|
if ( aAddr.Parse( rName, NULL ) )
|
|
|
|
bOk = FALSE;
|
|
|
|
}
|
|
|
|
if ( !bOk )
|
|
|
|
{ //! Range Parse auch bei Bereich mit ungueltigem Tabellennamen gueltig
|
|
|
|
//! Address Parse dito, Name erzeugt deswegen bei Compile ein #REF!
|
|
|
|
if ( rName.SearchAndReplace( ':', '_' ) == STRING_NOTFOUND
|
|
|
|
&& rName.SearchAndReplace( '.', '_' ) == STRING_NOTFOUND )
|
|
|
|
rName.Insert('_',0);
|
|
|
|
}
|
|
|
|
} while ( !bOk );
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOL ScRangeData::IsNameValid( const String& rName, ScDocument* pDoc )
|
|
|
|
{
|
|
|
|
xub_StrLen nPos = 0;
|
|
|
|
xub_StrLen nLen = rName.Len();
|
|
|
|
if ( !nLen || !ScCompiler::IsCharWordChar( rName.GetChar(nPos++) ) )
|
|
|
|
return FALSE;
|
|
|
|
while ( nPos < nLen )
|
|
|
|
{
|
|
|
|
if ( !ScCompiler::IsWordChar( rName.GetChar(nPos++) ) )
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
// Parse nicht auf VALID pruefen, es reicht, wenn irgendein Bestandteil
|
|
|
|
// erkannt wurde
|
|
|
|
ScRange aRange;
|
|
|
|
if( aRange.Parse( rName, pDoc ) )
|
|
|
|
return FALSE;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ScAddress aAddr;
|
|
|
|
if ( aAddr.Parse( rName, pDoc ) )
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
USHORT ScRangeData::GetErrCode()
|
|
|
|
{
|
|
|
|
return pCode ? pCode->GetError() : 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOL ScRangeData::HasReferences() const
|
|
|
|
{
|
|
|
|
pCode->Reset();
|
|
|
|
return BOOL( pCode->GetNextReference() != NULL );
|
|
|
|
}
|
|
|
|
|
|
|
|
// bei TransferTab von einem in ein anderes Dokument anpassen,
|
|
|
|
// um Referenzen auf die eigene Tabelle mitzubekommen
|
|
|
|
|
|
|
|
void ScRangeData::TransferTabRef( USHORT nOldTab, USHORT nNewTab )
|
|
|
|
{
|
|
|
|
short nTabDiff = nNewTab - nOldTab;
|
|
|
|
short nPosDiff = nNewTab - aPos.Tab();
|
|
|
|
aPos.SetTab( nNewTab );
|
|
|
|
ScToken* t;
|
|
|
|
pCode->Reset();
|
|
|
|
while ( t = pCode->GetNextReference() )
|
|
|
|
{
|
2001-02-21 17:39:37 +00:00
|
|
|
SingleRefData& rRef1 = t->GetSingleRef();
|
|
|
|
if ( rRef1.IsTabRel() )
|
|
|
|
rRef1.nTab += nPosDiff;
|
2000-09-18 23:16:46 +00:00
|
|
|
else
|
2001-02-21 17:39:37 +00:00
|
|
|
rRef1.nTab += nTabDiff;
|
|
|
|
if ( t->GetType() == svDoubleRef )
|
|
|
|
{
|
|
|
|
SingleRefData& rRef2 = t->GetDoubleRef().Ref2;
|
|
|
|
if ( rRef2.IsTabRel() )
|
|
|
|
rRef2.nTab += nPosDiff;
|
|
|
|
else
|
|
|
|
rRef2.nTab += nTabDiff;
|
|
|
|
}
|
2000-09-18 23:16:46 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void ScRangeData::ReplaceRangeNamesInUse( const ScIndexMap& rMap )
|
|
|
|
{
|
|
|
|
BOOL bCompile = FALSE;
|
|
|
|
for ( ScToken* p = pCode->First(); p; p = pCode->Next() )
|
|
|
|
{
|
|
|
|
if ( p->GetOpCode() == ocName )
|
|
|
|
{
|
2001-02-21 17:39:37 +00:00
|
|
|
USHORT nIndex = p->GetIndex();
|
|
|
|
USHORT nNewIndex = rMap.Find( nIndex );
|
|
|
|
if ( nIndex != nNewIndex )
|
2000-09-18 23:16:46 +00:00
|
|
|
{
|
2001-02-21 17:39:37 +00:00
|
|
|
p->SetIndex( nNewIndex );
|
2000-09-18 23:16:46 +00:00
|
|
|
bCompile = TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if ( bCompile )
|
|
|
|
{
|
|
|
|
ScCompiler aComp( pDoc, aPos, *pCode );
|
|
|
|
aComp.CompileTokenArray();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2001-06-15 12:39:13 +00:00
|
|
|
void ScRangeData::ValidateTabRefs()
|
|
|
|
{
|
|
|
|
// try to make sure all relative references and the reference position
|
|
|
|
// are within existing tables, so they can be represented as text
|
|
|
|
// (if the range of used tables is more than the existing tables,
|
|
|
|
// the result may still contain invalid tables, because the relative
|
|
|
|
// references aren't changed so formulas stay the same)
|
|
|
|
|
|
|
|
// find range of used tables
|
|
|
|
|
|
|
|
USHORT nMinTab = aPos.Tab();
|
|
|
|
USHORT nMaxTab = nMinTab;
|
|
|
|
ScToken* t;
|
|
|
|
pCode->Reset();
|
|
|
|
while ( t = pCode->GetNextReference() )
|
|
|
|
{
|
|
|
|
SingleRefData& rRef1 = t->GetSingleRef();
|
|
|
|
if ( rRef1.IsTabRel() && !rRef1.IsTabDeleted() )
|
|
|
|
{
|
|
|
|
if ( rRef1.nTab < nMinTab )
|
|
|
|
nMinTab = rRef1.nTab;
|
|
|
|
if ( rRef1.nTab > nMaxTab )
|
|
|
|
nMaxTab = rRef1.nTab;
|
|
|
|
}
|
|
|
|
if ( t->GetType() == svDoubleRef )
|
|
|
|
{
|
|
|
|
SingleRefData& rRef2 = t->GetDoubleRef().Ref2;
|
|
|
|
if ( rRef2.IsTabRel() && !rRef2.IsTabDeleted() )
|
|
|
|
{
|
|
|
|
if ( rRef2.nTab < nMinTab )
|
|
|
|
nMinTab = rRef2.nTab;
|
|
|
|
if ( rRef2.nTab > nMaxTab )
|
|
|
|
nMaxTab = rRef2.nTab;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
USHORT nTabCount = pDoc->GetTableCount();
|
|
|
|
if ( nMaxTab >= nTabCount && nMinTab > 0 )
|
|
|
|
{
|
|
|
|
// move position and relative tab refs
|
|
|
|
// The formulas that use the name are not changed by this
|
|
|
|
|
|
|
|
USHORT nMove = nMinTab;
|
|
|
|
aPos.SetTab( aPos.Tab() - nMove );
|
|
|
|
|
|
|
|
pCode->Reset();
|
|
|
|
while ( t = pCode->GetNextReference() )
|
|
|
|
{
|
|
|
|
SingleRefData& rRef1 = t->GetSingleRef();
|
|
|
|
if ( rRef1.IsTabRel() && !rRef1.IsTabDeleted() )
|
|
|
|
rRef1.nTab -= nMove;
|
|
|
|
if ( t->GetType() == svDoubleRef )
|
|
|
|
{
|
|
|
|
SingleRefData& rRef2 = t->GetDoubleRef().Ref2;
|
|
|
|
if ( rRef2.IsTabRel() && !rRef2.IsTabDeleted() )
|
|
|
|
rRef2.nTab -= nMove;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2000-09-18 23:16:46 +00:00
|
|
|
int
|
|
|
|
#ifdef WNT
|
|
|
|
__cdecl
|
|
|
|
#endif
|
|
|
|
ScRangeData::QsortNameCompare( const void* p1, const void* p2 )
|
|
|
|
{
|
2001-03-14 15:02:54 +00:00
|
|
|
return (int) ScGlobal::pCollator->compareString(
|
2000-09-18 23:16:46 +00:00
|
|
|
(*(const ScRangeData**)p1)->aName,
|
2001-03-14 15:02:54 +00:00
|
|
|
(*(const ScRangeData**)p2)->aName );
|
2000-09-18 23:16:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//========================================================================
|
|
|
|
// ScRangeName
|
|
|
|
//========================================================================
|
|
|
|
|
|
|
|
ScRangeName::ScRangeName(const ScRangeName& rScRangeName, ScDocument* pDocument) :
|
|
|
|
SortedCollection ( rScRangeName ),
|
|
|
|
pDoc ( pDocument ),
|
|
|
|
nSharedMaxIndex (rScRangeName.nSharedMaxIndex)
|
|
|
|
{
|
|
|
|
for (USHORT i = 0; i < nCount; i++)
|
|
|
|
{
|
|
|
|
((ScRangeData*)At(i))->SetDocument(pDocument);
|
|
|
|
((ScRangeData*)At(i))->SetIndex(((ScRangeData*)rScRangeName.At(i))->GetIndex());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
short ScRangeName::Compare(DataObject* pKey1, DataObject* pKey2) const
|
|
|
|
{
|
|
|
|
USHORT i1 = ((ScRangeData*)pKey1)->GetIndex();
|
|
|
|
USHORT i2 = ((ScRangeData*)pKey2)->GetIndex();
|
|
|
|
return (short) i1 - (short) i2;
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOL ScRangeName::SearchName( const String& rName, USHORT& rIndex ) const
|
|
|
|
{
|
|
|
|
USHORT i = 0;
|
|
|
|
while (i < nCount)
|
|
|
|
{
|
|
|
|
String aName;
|
|
|
|
((*this)[i])->GetName( aName );
|
2001-03-14 15:02:54 +00:00
|
|
|
if ( ScGlobal::pCollator->compareString(
|
|
|
|
aName, rName ) == COMPARE_EQUAL )
|
2000-09-18 23:16:46 +00:00
|
|
|
{
|
|
|
|
rIndex = i;
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOL ScRangeName::Load( SvStream& rStream, USHORT nVer )
|
|
|
|
{
|
|
|
|
BOOL bSuccess = TRUE;
|
|
|
|
USHORT nNewCount;
|
|
|
|
|
|
|
|
while( nCount > 0 )
|
|
|
|
AtFree(0); // alles loeschen
|
|
|
|
|
|
|
|
ScMultipleReadHeader aHdr( rStream );
|
|
|
|
|
|
|
|
USHORT nDummy;
|
|
|
|
if( nVer >= SC_NEW_TOKEN_ARRAYS )
|
|
|
|
rStream >> nSharedMaxIndex >> nNewCount;
|
|
|
|
else
|
|
|
|
rStream >> nSharedMaxIndex >> nDummy >> nNewCount;
|
|
|
|
for (USHORT i=0; i<nNewCount && bSuccess; i++)
|
|
|
|
{
|
|
|
|
ScRangeData* pData = new ScRangeData( rStream, aHdr, nVer );
|
|
|
|
pData->SetDocument(pDoc);
|
|
|
|
Insert( pData );
|
|
|
|
if( rStream.GetError() != SVSTREAM_OK )
|
|
|
|
bSuccess = FALSE;
|
|
|
|
}
|
|
|
|
return bSuccess;
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOL ScRangeName::Store( SvStream& rStream ) const
|
|
|
|
{
|
|
|
|
ScMultipleWriteHeader aHdr( rStream );
|
|
|
|
|
|
|
|
USHORT i;
|
|
|
|
USHORT nSaveCount = nCount;
|
|
|
|
USHORT nSaveMaxRow = pDoc->GetSrcMaxRow();
|
|
|
|
if ( nSaveMaxRow < MAXROW )
|
|
|
|
{
|
|
|
|
nSaveCount = 0;
|
|
|
|
for (i=0; i<nCount; i++)
|
|
|
|
if ( !((const ScRangeData*)At(i))->IsBeyond(nSaveMaxRow) )
|
|
|
|
++nSaveCount;
|
|
|
|
|
|
|
|
if ( nSaveCount < nCount )
|
|
|
|
pDoc->SetLostData(); // Warnung ausgeben
|
|
|
|
}
|
|
|
|
|
|
|
|
rStream << nSharedMaxIndex << nSaveCount;
|
|
|
|
BOOL bSuccess = TRUE;
|
|
|
|
|
|
|
|
for (i=0; i<nCount && bSuccess; i++)
|
|
|
|
{
|
|
|
|
const ScRangeData* pRangeData = (const ScRangeData*)At(i);
|
|
|
|
if ( nSaveMaxRow == MAXROW || !pRangeData->IsBeyond(nSaveMaxRow) )
|
|
|
|
bSuccess = pRangeData->Store( rStream, aHdr );
|
|
|
|
}
|
|
|
|
|
|
|
|
return bSuccess;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ScRangeName::UpdateReference( UpdateRefMode eUpdateRefMode,
|
|
|
|
const ScRange& rRange,
|
|
|
|
short nDx, short nDy, short nDz )
|
|
|
|
{
|
|
|
|
for (USHORT i=0; i<nCount; i++)
|
|
|
|
((ScRangeData*)pItems[i])->UpdateReference(eUpdateRefMode, rRange,
|
|
|
|
nDx, nDy, nDz);
|
|
|
|
}
|
|
|
|
|
|
|
|
void ScRangeName::UpdateTranspose( const ScRange& rSource, const ScAddress& rDest )
|
|
|
|
{
|
|
|
|
for (USHORT i=0; i<nCount; i++)
|
|
|
|
((ScRangeData*)pItems[i])->UpdateTranspose( rSource, rDest );
|
|
|
|
}
|
|
|
|
|
|
|
|
void ScRangeName::UpdateGrow( const ScRange& rArea, USHORT nGrowX, USHORT nGrowY )
|
|
|
|
{
|
|
|
|
for (USHORT i=0; i<nCount; i++)
|
|
|
|
((ScRangeData*)pItems[i])->UpdateGrow( rArea, nGrowX, nGrowY );
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOL ScRangeName::IsEqual(DataObject* pKey1, DataObject* pKey2) const
|
|
|
|
{
|
|
|
|
return *(ScRangeData*)pKey1 == *(ScRangeData*)pKey2;
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOL ScRangeName::Insert(DataObject* pDataObject)
|
|
|
|
{
|
|
|
|
if (!((ScRangeData*)pDataObject)->GetIndex()) // schon gesetzt?
|
|
|
|
{
|
|
|
|
((ScRangeData*)pDataObject)->SetIndex( GetEntryIndex() );
|
|
|
|
}
|
|
|
|
|
|
|
|
return SortedCollection::Insert(pDataObject);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Suche nach einem freien Index
|
|
|
|
|
|
|
|
USHORT ScRangeName::GetEntryIndex()
|
|
|
|
{
|
|
|
|
USHORT nLast = 0;
|
|
|
|
for ( USHORT i = 0; i < nCount; i++ )
|
|
|
|
{
|
|
|
|
USHORT nIdx = ((ScRangeData*)pItems[i])->GetIndex();
|
|
|
|
if( nIdx > nLast )
|
|
|
|
{
|
|
|
|
nLast = nIdx;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nLast + 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
ScRangeData* ScRangeName::FindIndex( USHORT nIndex )
|
|
|
|
{
|
|
|
|
ScRangeData aDataObj( nIndex );
|
|
|
|
USHORT n;
|
|
|
|
if( Search( &aDataObj, n ) )
|
|
|
|
return (*this)[ n ];
|
|
|
|
else
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
ScRangeData* ScRangeName::GetRangeAtCursor( const ScAddress& rPos, BOOL bStartOnly ) const
|
|
|
|
{
|
|
|
|
if ( pItems )
|
|
|
|
{
|
|
|
|
for ( USHORT i = 0; i < nCount; i++ )
|
|
|
|
if ( ((ScRangeData*)pItems[i])->IsRangeAtCursor( rPos, bStartOnly ) )
|
|
|
|
return (ScRangeData*)pItems[i];
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
ScRangeData* ScRangeName::GetRangeAtBlock( const ScRange& rBlock ) const
|
|
|
|
{
|
|
|
|
if ( pItems )
|
|
|
|
{
|
|
|
|
for ( USHORT i = 0; i < nCount; i++ )
|
|
|
|
if ( ((ScRangeData*)pItems[i])->IsRangeAtBlock( rBlock ) )
|
|
|
|
return (ScRangeData*)pItems[i];
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ScRangeName::UpdateTabRef(USHORT nOldTable, USHORT nFlag, USHORT nNewTable)
|
|
|
|
{
|
|
|
|
for (USHORT i=0; i<nCount; i++)
|
|
|
|
((ScRangeData*)pItems[i])->UpdateTabRef(nOldTable, nFlag, nNewTable);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|