/************************************************************************* * * OpenOffice.org - a multi-platform office productivity suite * * $RCSfile: address.hxx,v $ * * $Revision: 1.12 $ * * last change: $Author: vg $ $Date: 2007-02-27 11:52:12 $ * * The Contents of this file are made available subject to * the terms of GNU Lesser General Public License Version 2.1. * * * GNU Lesser General Public License Version 2.1 * ============================================= * Copyright 2005 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 * ************************************************************************/ #ifndef SC_ADDRESS_HXX #define SC_ADDRESS_HXX #ifndef _STREAM_HXX #include #endif #ifndef _STRING_HXX #include #endif #ifndef _SOLAR_H #include #endif #ifndef _TOOLS_DEBUG_HXX #include #endif #ifndef _RTL_USTRBUF_HXX_ #include #endif #ifndef _OSL_ENDIAN_H_ #include #endif #ifndef INCLUDED_LIMITS #include #define INCLUDED_LIMITS #endif #ifndef INCLUDED_SCDLLAPI_H #include "scdllapi.h" #endif class ScDocument; // The typedefs typedef sal_Int32 SCROW; typedef sal_Int16 SCCOL; typedef sal_Int16 SCTAB; typedef sal_Int32 SCCOLROW; // a type capable of holding either SCCOL or SCROW // temporarily signed typedefs typedef sal_Int32 SCsROW; typedef sal_Int16 SCsCOL; typedef sal_Int16 SCsTAB; typedef sal_Int32 SCsCOLROW; // size_t typedef to be able to find places where code was changed from USHORT // to size_t and is used to read/write from/to streams. typedef size_t SCSIZE; // Maximum possible value of data type, NOT maximum row value. // MSC confuses numeric_limit max() with macro max() if vcl/wintypes.hxx is // included, we should not be using those stupid macros anyway. #undef min #undef max const SCROW SCROW_MAX = ::std::numeric_limits::max(); const SCCOL SCCOL_MAX = ::std::numeric_limits::max(); const SCTAB SCTAB_MAX = ::std::numeric_limits::max(); const SCCOLROW SCCOLROW_MAX = ::std::numeric_limits::max(); const SCSIZE SCSIZE_MAX = ::std::numeric_limits::max(); // A define to handle critical sections we hopefully don't need very often. #define SC_ROWLIMIT_MORE_THAN_32K 1 /* set to 1 if we throw the switch */ // The maximum values. Defines are needed for preprocessor checks in // bcaslot.cxx, otherwise type safe constants are preferred. #define MAXROWCOUNT_DEFINE 65536 #define MAXCOLCOUNT_DEFINE 256 // Count values const SCROW MAXROWCOUNT = MAXROWCOUNT_DEFINE; const SCCOL MAXCOLCOUNT = MAXCOLCOUNT_DEFINE; const SCTAB MAXTABCOUNT = 256; const SCCOLROW MAXCOLROWCOUNT = MAXROWCOUNT; // Maximum values const SCROW MAXROW = MAXROWCOUNT - 1; const SCCOL MAXCOL = MAXCOLCOUNT - 1; const SCTAB MAXTAB = MAXTABCOUNT - 1; const SCCOLROW MAXCOLROW = MAXROW; // Special values const SCTAB SC_TAB_APPEND = SCTAB_MAX; const SCTAB TABLEID_DOC = SCTAB_MAX; // entire document, e.g. protect const SCROW SCROWS32K = 32000; const SCCOL SCCOL_REPEAT_NONE = SCCOL_MAX; const SCROW SCROW_REPEAT_NONE = SCROW_MAX; // We hope to get rid of the binary file format. If not, these are the places // we'd have to investigate because variable types changed. Just place code in // #if SC_ROWLIMIT_STREAM_ACCESS for now. #define SC_ROWLIMIT_STREAM_ACCESS 0 // usage: //#if SC_ROWLIMIT_STREAM_ACCESS //#error address types changed! //... code ... //#endif // SC_ROWLIMIT_STREAM_ACCESS // For future reference, place in code where more than 64k rows would need a // special handling: // #if SC_ROWLIMIT_MORE_THAN_64K // #error row limit 64k // #endif #define SC_ROWLIMIT_MORE_THAN_64K 0 /* set to 1 if we throw the switch */ const SCROW SCROWS64K = 65536; // === old stuff defines ===================================================== #ifdef WIN // Under 16bit Windows rows still had to be limited to 8192. // (define manually for testing) #define SC_LIMIT_ROWS #endif #define MAXROW_30 8191 #define MAXROW_40 31999 #ifdef SC_LIMIT_ROWS #undef MAXROWCOUNT_DEFINE #define MAXROWCOUNT_DEFINE 8192 const SCROW W16MAXROWCOUNT = MAXROWCOUNT_DEFINE; const SCROW W16MAXROW = W16MAXROWCOUNT - 1; #define MAXROWCOUNT W16MAXROWCOUNT #define MAXROW W16MAXROW #endif #define VALIDCOL(nCol) (ValidCol(nCol)) #define VALIDROW(nRow) (ValidRow(nRow)) #define VALIDTAB(nTab) (ValidTab(nTab)) #define VALIDCOLROW(nCol,nRow) (ValidColRow(nCol,nRow)) #define VALIDCOLROWTAB(nCol,nRow,nTab) (ValidColRowTab(nCol,nRow,nTab)) // === old stuff defines end ================================================= inline bool ValidCol( SCCOL nCol ) { return static_cast(0) <= nCol && nCol <= MAXCOL; } inline bool ValidRow( SCROW nRow ) { return static_cast(0) <= nRow && nRow <= MAXROW; } inline bool ValidTab( SCTAB nTab ) { return static_cast(0) <= nTab && nTab <= MAXTAB; } inline bool ValidTab( SCTAB nTab, SCTAB nMaxTab ) { return static_cast(0) <= nTab && nTab <= nMaxTab; } inline bool ValidColRow( SCCOL nCol, SCROW nRow ) { return ValidCol( nCol) && ValidRow( nRow); } inline bool ValidColRowTab( SCCOL nCol, SCROW nRow, SCTAB nTab ) { return ValidCol( nCol) && ValidRow( nRow) && ValidTab( nTab); } // === ScAddress ============================================================= // The old cell address is combined in one UINT32: // +---+---+-------+ // |Tab|Col| Row | // +---+---+-------+ // For speed reasons access isn't done by shifting bits but by using platform // dependent casts, which unfortunately also leads to aliasing problems when // not using gcc -fno-strict-aliasing // The result of ConvertRef() is a bit group of the following: #define SCA_COL_ABSOLUTE 0x01 #define SCA_ROW_ABSOLUTE 0x02 #define SCA_TAB_ABSOLUTE 0x04 #define SCA_TAB_3D 0x08 #define SCA_COL2_ABSOLUTE 0x10 #define SCA_ROW2_ABSOLUTE 0x20 #define SCA_TAB2_ABSOLUTE 0x40 #define SCA_TAB2_3D 0x80 #define SCA_VALID_ROW 0x0100 #define SCA_VALID_COL 0x0200 #define SCA_VALID_TAB 0x0400 // somewhat cheesy kludge to force the display of the document name even for // local references. Requires TAB_3D to be valid #define SCA_FORCE_DOC 0x0800 #define SCA_VALID_ROW2 0x1000 #define SCA_VALID_COL2 0x2000 #define SCA_VALID_TAB2 0x4000 #define SCA_VALID 0x8000 #define SCA_ABS SCA_VALID \ | SCA_COL_ABSOLUTE | SCA_ROW_ABSOLUTE | SCA_TAB_ABSOLUTE #define SCR_ABS SCA_ABS \ | SCA_COL2_ABSOLUTE | SCA_ROW2_ABSOLUTE | SCA_TAB2_ABSOLUTE #define SCA_ABS_3D SCA_ABS | SCA_TAB_3D #define SCR_ABS_3D SCR_ABS | SCA_TAB_3D // === ScAddress ============================================================= class SC_DLLPUBLIC ScAddress { private: SCROW nRow; SCCOL nCol; SCTAB nTab; public: enum Uninitialized { UNINITIALIZED }; enum InitializeInvalid { INITIALIZE_INVALID }; enum Convention { CONV_UNSPECIFIED = -1, /* useful when we want method to chose, must be first */ /* elements must be sequential and changes should be reflected in ScCompiler::pCharTables */ CONV_OOO = 0, /* 'doc'#sheet.A1:sheet2.B2 */ CONV_XL_A1, /* [doc]sheet:sheet2!A1:B2 */ CONV_XL_R1C1, /* [doc]sheet:sheet2!R1C1:R2C2 */ CONV_LOTUS_A1, /* external? 3d? A1.B2 */ CONV_LAST /* for loops, must always be last */ }; struct Details { Convention eConv; SCROW nRow; SCCOL nCol; inline Details( Convention eConvP, SCROW nRowP, SCCOL nColP ) : eConv( eConvP ), nRow( nRowP ), nCol( nColP ) {} inline Details( Convention eConvP, ScAddress const & rAddr ) : eConv( eConvP ), nRow( rAddr.Row() ), nCol( rAddr.Col() ) {} inline Details( Convention eConvP) : eConv( eConvP ), nRow( 0 ), nCol( 0 ) {} /* Use the convention associated with rAddr::Tab() */ Details( const ScDocument* pDoc, const ScAddress & rAddr ); void SetPos( const ScDocument* pDoc, const ScAddress & rAddr ); }; static const Details detailsOOOa1; inline ScAddress() : nRow(0), nCol(0), nTab(0) {} inline ScAddress( SCCOL nColP, SCROW nRowP, SCTAB nTabP ) : nRow(nRowP), nCol(nColP), nTab(nTabP) {} /** Yes, it is what it seems to be: Uninitialized. May be used for performance reasons if it is initialized by other means. */ inline ScAddress( Uninitialized ) {} inline ScAddress( InitializeInvalid ) : nRow(-1), nCol(-1), nTab(-1) {} inline ScAddress( const ScAddress& r ) : nRow(r.nRow), nCol(r.nCol), nTab(r.nTab) {} inline ScAddress& operator=( const ScAddress& r ); inline void Set( SCCOL nCol, SCROW nRow, SCTAB nTab ); inline SCROW Row() const { return nRow; } inline SCCOL Col() const { return nCol; } inline SCTAB Tab() const { return nTab; } inline void SetRow( SCROW nRowP ) { nRow = nRowP; } inline void SetCol( SCCOL nColP ) { nCol = nColP; } inline void SetTab( SCTAB nTabP ) { nTab = nTabP; } inline void SetInvalid() { nRow = -1; nCol = -1; nTab = -1; } inline bool IsValid() const { return (nRow >= 0) && (nCol >= 0) && (nTab >= 0); } inline void PutInOrder( ScAddress& r ); inline void IncRow( SCsROW n=1 ) { nRow = sal::static_int_cast(nRow + n); } inline void IncCol( SCsCOL n=1 ) { nCol = sal::static_int_cast(nCol + n); } inline void IncTab( SCsTAB n=1 ) { nTab = sal::static_int_cast(nTab + n); } inline void GetVars( SCCOL& nColP, SCROW& nRowP, SCTAB& nTabP ) const { nColP = nCol; nRowP = nRow; nTabP = nTab; } USHORT Parse( const String&, ScDocument* = NULL, const Details& rDetails = detailsOOOa1); void Format( String&, USHORT = 0, ScDocument* = NULL, const Details& rDetails = detailsOOOa1) const; // The document for the maximum defined sheet number bool Move( SCsCOL dx, SCsROW dy, SCsTAB dz, ScDocument* =NULL ); inline bool operator==( const ScAddress& r ) const; inline bool operator!=( const ScAddress& r ) const; inline bool operator<( const ScAddress& r ) const; inline bool operator<=( const ScAddress& r ) const; inline bool operator>( const ScAddress& r ) const; inline bool operator>=( const ScAddress& r ) const; // moved from ScTripel /// "(1,2,3)" String GetText() const; /// "A1" or "$A$1" or R1C1 or R[1]C[1] String GetColRowString( bool bAbsolute = FALSE, const Details& rDetails = detailsOOOa1) const; }; inline void ScAddress::PutInOrder( ScAddress& r ) { if ( r.Col() < Col() ) { SCCOL nTmp = r.Col(); r.SetCol( Col() ); SetCol( nTmp ); } if ( r.Row() < Row() ) { SCROW nTmp = r.Row(); r.SetRow( Row() ); SetRow( nTmp ); } if ( r.Tab() < Tab() ) { SCTAB nTmp = r.Tab(); r.SetTab( Tab() ); SetTab( nTmp ); } } inline void ScAddress::Set( SCCOL nColP, SCROW nRowP, SCTAB nTabP ) { nCol = nColP; nRow = nRowP; nTab = nTabP; } inline ScAddress& ScAddress::operator=( const ScAddress& r ) { nCol = r.nCol; nRow = r.nRow; nTab = r.nTab; return *this; } inline bool ScAddress::operator==( const ScAddress& r ) const { return nRow == r.nRow && nCol == r.nCol && nTab == r.nTab; } inline bool ScAddress::operator!=( const ScAddress& r ) const { return !operator==( r ); } inline bool ScAddress::operator<( const ScAddress& r ) const { // Same behavior as the old UINT32 nAddress < r.nAddress with encoded // tab|col|row bit fields. if (nTab == r.nTab) { if (nCol == r.nCol) return nRow < r.nRow; else return nCol < r.nCol; } else return nTab < r.nTab; } inline bool ScAddress::operator<=( const ScAddress& r ) const { return operator<( r ) || operator==( r ); } inline bool ScAddress::operator>( const ScAddress& r ) const { return !operator<=( r ); } inline bool ScAddress::operator>=( const ScAddress& r ) const { return !operator<( r ); } // === ScRange =============================================================== class SC_DLLPUBLIC ScRange { public: ScAddress aStart, aEnd; inline ScRange() : aStart(), aEnd() {} inline ScRange( ScAddress::Uninitialized e ) : aStart( e ), aEnd( e ) {} inline ScRange( ScAddress::InitializeInvalid e ) : aStart( e ), aEnd( e ) {} inline ScRange( const ScAddress& s, const ScAddress& e ) : aStart( s ), aEnd( e ) { aStart.PutInOrder( aEnd ); } inline ScRange( const ScRange& r ) : aStart( r.aStart ), aEnd( r.aEnd ) {} inline ScRange( const ScAddress& r ) : aStart( r ), aEnd( r ) {} inline ScRange( SCCOL nCol, SCROW nRow, SCTAB nTab ) : aStart( nCol, nRow, nTab ), aEnd( aStart ) {} inline ScRange( SCCOL nCol1, SCROW nRow1, SCTAB nTab1, SCCOL nCol2, SCROW nRow2, SCTAB nTab2 ) : aStart( nCol1, nRow1, nTab1 ), aEnd( nCol2, nRow2, nTab2 ) {} inline ScRange& operator=( const ScRange& r ) { aStart = r.aStart; aEnd = r.aEnd; return *this; } inline ScRange& operator=( const ScAddress& rPos ) { aStart = aEnd = rPos; return *this; } inline void SetInvalid() { aStart.SetInvalid(); aEnd.SetInvalid(); } inline bool IsValid() const { return aStart.IsValid() && aEnd.IsValid(); } inline bool In( const ScAddress& ) const; // is Address& in Range? inline bool In( const ScRange& ) const; // is Range& in Range? USHORT Parse( const String&, ScDocument* = NULL, const ScAddress::Details& rDetails = ScAddress::detailsOOOa1 ); USHORT ParseAny( const String&, ScDocument* = NULL, const ScAddress::Details& rDetails = ScAddress::detailsOOOa1 ); USHORT ParseCols( const String&, ScDocument* = NULL, const ScAddress::Details& rDetails = ScAddress::detailsOOOa1 ); USHORT ParseRows( const String&, ScDocument* = NULL, const ScAddress::Details& rDetails = ScAddress::detailsOOOa1 ); void Format( String&, USHORT = 0, ScDocument* = NULL, const ScAddress::Details& rDetails = ScAddress::detailsOOOa1 ) const; inline void GetVars( SCCOL& nCol1, SCROW& nRow1, SCTAB& nTab1, SCCOL& nCol2, SCROW& nRow2, SCTAB& nTab2 ) const; // The document for the maximum defined sheet number bool Move( SCsCOL dx, SCsROW dy, SCsTAB dz, ScDocument* =NULL ); void Justify(); void ExtendOne(); void ExtendTo( const ScRange& rRange ); bool Intersects( const ScRange& ) const; // do two ranges intersect? inline bool operator==( const ScRange& r ) const; inline bool operator!=( const ScRange& r ) const; inline bool operator<( const ScRange& r ) const; inline bool operator<=( const ScRange& r ) const; inline bool operator>( const ScRange& r ) const; inline bool operator>=( const ScRange& r ) const; }; inline void ScRange::GetVars( SCCOL& nCol1, SCROW& nRow1, SCTAB& nTab1, SCCOL& nCol2, SCROW& nRow2, SCTAB& nTab2 ) const { aStart.GetVars( nCol1, nRow1, nTab1 ); aEnd.GetVars( nCol2, nRow2, nTab2 ); } inline bool ScRange::operator==( const ScRange& r ) const { return ( (aStart == r.aStart) && (aEnd == r.aEnd) ); } inline bool ScRange::operator!=( const ScRange& r ) const { return !operator==( r ); } // Sort on upper left corner, if equal then use lower right too. inline bool ScRange::operator<( const ScRange& r ) const { return aStart < r.aStart || (aStart == r.aStart && aEnd < r.aEnd) ; } inline bool ScRange::operator<=( const ScRange& r ) const { return operator<( r ) || operator==( r ); } inline bool ScRange::operator>( const ScRange& r ) const { return !operator<=( r ); } inline bool ScRange::operator>=( const ScRange& r ) const { return !operator<( r ); } inline bool ScRange::In( const ScAddress& rAddr ) const { return aStart.Col() <= rAddr.Col() && rAddr.Col() <= aEnd.Col() && aStart.Row() <= rAddr.Row() && rAddr.Row() <= aEnd.Row() && aStart.Tab() <= rAddr.Tab() && rAddr.Tab() <= aEnd.Tab(); } inline bool ScRange::In( const ScRange& r ) const { return aStart.Col() <= r.aStart.Col() && r.aEnd.Col() <= aEnd.Col() && aStart.Row() <= r.aStart.Row() && r.aEnd.Row() <= aEnd.Row() && aStart.Tab() <= r.aStart.Tab() && r.aEnd.Tab() <= aEnd.Tab(); } // === ScRangePair =========================================================== class ScRangePair { private: ScRange aRange[2]; public: ScRangePair() {} ScRangePair( const ScRangePair& r ) { aRange[0] = r.aRange[0]; aRange[1] = r.aRange[1]; } ScRangePair( const ScRange& r1, const ScRange& r2 ) { aRange[0] = r1; aRange[1] = r2; } inline ScRangePair& operator= ( const ScRangePair& r ); const ScRange& GetRange( USHORT n ) const { return aRange[n]; } ScRange& GetRange( USHORT n ) { return aRange[n]; } inline int operator==( const ScRangePair& ) const; inline int operator!=( const ScRangePair& ) const; }; inline ScRangePair& ScRangePair::operator= ( const ScRangePair& r ) { aRange[0] = r.aRange[0]; aRange[1] = r.aRange[1]; return *this; } inline int ScRangePair::operator==( const ScRangePair& r ) const { return ( (aRange[0] == r.aRange[0]) && (aRange[1] == r.aRange[1]) ); } inline int ScRangePair::operator!=( const ScRangePair& r ) const { return !operator==( r ); } // === ScRefAddress ========================================================== class ScRefAddress { ScAddress aAdr; bool bRelCol; bool bRelRow; bool bRelTab; public: inline ScRefAddress() : bRelCol(false), bRelRow(false), bRelTab(false) {} inline ScRefAddress( SCCOL nCol, SCROW nRow, SCTAB nTab, bool bRelColP, bool bRelRowP, bool bRelTabP ) : aAdr(nCol, nRow, nTab), bRelCol(bRelColP), bRelRow(bRelRowP), bRelTab(bRelTabP) {} inline ScRefAddress( const ScAddress& rAdr, bool bRelColP, bool bRelRowP, bool bRelTabP ) : aAdr(rAdr), bRelCol(bRelColP), bRelRow(bRelRowP), bRelTab(bRelTabP) {} inline ScRefAddress( const ScRefAddress& rRef ) : aAdr(rRef.aAdr), bRelCol(rRef.bRelCol), bRelRow(rRef.bRelRow), bRelTab(rRef.bRelTab) {} inline ScRefAddress& operator=( const ScRefAddress& ); inline bool IsRelCol() const { return bRelCol; } inline bool IsRelRow() const { return bRelRow; } inline bool IsRelTab() const { return bRelTab; } inline void SetRelCol(bool bNewRelCol) { bRelCol = bNewRelCol; } inline void SetRelRow(bool bNewRelRow) { bRelRow = bNewRelRow; } inline void SetRelTab(bool bNewRelTab) { bRelTab = bNewRelTab; } inline void Set( const ScAddress& rAdr, bool bNewRelCol, bool bNewRelRow, bool bNewRelTab ); inline void Set( SCCOL nNewCol, SCROW nNewRow, SCTAB nNewTab, bool bNewRelCol, bool bNewRelRow, bool bNewRelTab ); inline const ScAddress& GetAddress() const { return aAdr; } inline SCCOL Col() const { return aAdr.Col(); } inline SCROW Row() const { return aAdr.Row(); } inline SCTAB Tab() const { return aAdr.Tab(); } inline int operator == ( const ScRefAddress& r ) const; inline int operator != ( const ScRefAddress& r ) const { return !(operator==(r)); } String GetRefString( ScDocument* pDoc, SCTAB nActTab, const ScAddress::Details& rDetails = ScAddress::detailsOOOa1) const; }; inline ScRefAddress& ScRefAddress::operator=( const ScRefAddress& rRef ) { aAdr = rRef.aAdr; bRelCol = rRef.bRelCol; bRelRow = rRef.bRelRow; bRelTab = rRef.bRelTab; return *this; } inline void ScRefAddress::Set( const ScAddress& rAdr, bool bNewRelCol, bool bNewRelRow, bool bNewRelTab ) { aAdr = rAdr; bRelCol = bNewRelCol; bRelRow = bNewRelRow; bRelTab = bNewRelTab; } inline void ScRefAddress::Set( SCCOL nNewCol, SCROW nNewRow, SCTAB nNewTab, bool bNewRelCol, bool bNewRelRow, bool bNewRelTab ) { aAdr.Set( nNewCol, nNewRow, nNewTab); bRelCol = bNewRelCol; bRelRow = bNewRelRow; bRelTab = bNewRelTab; } inline int ScRefAddress::operator==( const ScRefAddress& r ) const { return aAdr == r.aAdr && bRelCol == r.bRelCol && bRelRow == r.bRelRow && bRelTab == r.bRelTab; } // =========================================================================== // Global functions // =========================================================================== // Special values for cells always broadcasting or listening (RECALCMODE_ALWAYS // and the like). #define BCA_BRDCST_ALWAYS ScAddress( 0, SCROW_MAX, 0 ) #define BCA_LISTEN_ALWAYS ScRange( BCA_BRDCST_ALWAYS, BCA_BRDCST_ALWAYS ) template< typename T > void PutInOrder( T& nStart, T& nEnd ) { if (nEnd < nStart) { T nTemp; nTemp = nEnd; nEnd = nStart; nStart = nTemp; } } bool ConvertSingleRef( ScDocument* pDoc, const String& rRefString, SCTAB nDefTab, ScRefAddress& rRefAddress, const ScAddress::Details& rDetails = ScAddress::detailsOOOa1); bool ConvertDoubleRef(ScDocument* pDoc, const String& rRefString, SCTAB nDefTab, ScRefAddress& rStartRefAddress, ScRefAddress& rEndRefAddress, const ScAddress::Details& rDetails = ScAddress::detailsOOOa1); /// append alpha representation of column to buffer SC_DLLPUBLIC void ColToAlpha( rtl::OUStringBuffer& rBuffer, SCCOL nCol); inline void ColToAlpha( String& rStr, SCCOL nCol) { rtl::OUStringBuffer aBuf(2); ColToAlpha( aBuf, nCol); rStr.Append( aBuf.getStr(), static_cast(aBuf.getLength())); } inline String ColToAlpha( SCCOL nCol ) { rtl::OUStringBuffer aBuf(2); ColToAlpha( aBuf, nCol); return aBuf.makeStringAndClear(); } /// get column number of A..IV... string bool AlphaToCol( SCCOL& rCol, const String& rStr); #endif // SC_ADDRESS_HXX