| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| |
| // MARKER(update_precomp.py): autogen include statement, do not remove |
| #include "precompiled_sc.hxx" |
| #include "xiname.hxx" |
| #include "rangenam.hxx" |
| #include "xistream.hxx" |
| |
| // for formula compiler |
| #include "excform.hxx" |
| // for filter manager |
| #include "excimp8.hxx" |
| |
| // ============================================================================ |
| // *** Implementation *** |
| // ============================================================================ |
| |
| XclImpName::XclImpName( XclImpStream& rStrm, sal_uInt16 nXclNameIdx ) : |
| XclImpRoot( rStrm.GetRoot() ), |
| mpScData( 0 ), |
| mcBuiltIn( EXC_BUILTIN_UNKNOWN ), |
| mnScTab( SCTAB_MAX ), |
| mbFunction( false ), |
| mbVBName( false ) |
| { |
| ExcelToSc& rFmlaConv = GetOldFmlaConverter(); |
| ScRangeName& rRangeNames = GetNamedRanges(); |
| |
| // 1) *** read data from stream *** --------------------------------------- |
| |
| sal_uInt16 nFlags = 0, nFmlaSize = 0, nExtSheet = EXC_NAME_GLOBAL, nXclTab = EXC_NAME_GLOBAL; |
| sal_uInt8 nNameLen = 0, nShortCut; |
| |
| switch( GetBiff() ) |
| { |
| case EXC_BIFF2: |
| { |
| sal_uInt8 nFlagsBiff2; |
| rStrm >> nFlagsBiff2; |
| rStrm.Ignore( 1 ); |
| rStrm >> nShortCut >> nNameLen; |
| nFmlaSize = rStrm.ReaduInt8(); |
| ::set_flag( nFlags, EXC_NAME_FUNC, ::get_flag( nFlagsBiff2, EXC_NAME2_FUNC ) ); |
| } |
| break; |
| |
| case EXC_BIFF3: |
| case EXC_BIFF4: |
| { |
| rStrm >> nFlags >> nShortCut >> nNameLen >> nFmlaSize; |
| } |
| break; |
| |
| case EXC_BIFF5: |
| case EXC_BIFF8: |
| { |
| rStrm >> nFlags >> nShortCut >> nNameLen >> nFmlaSize >> nExtSheet >> nXclTab; |
| rStrm.Ignore( 4 ); |
| } |
| break; |
| |
| default: DBG_ERROR_BIFF(); |
| } |
| |
| if( GetBiff() <= EXC_BIFF5 ) |
| maXclName = rStrm.ReadRawByteString( nNameLen ); |
| else |
| maXclName = rStrm.ReadUniString( nNameLen ); |
| |
| // 2) *** convert sheet index and name *** -------------------------------- |
| |
| // functions and VBA |
| mbFunction = ::get_flag( nFlags, EXC_NAME_FUNC ); |
| mbVBName = ::get_flag( nFlags, EXC_NAME_VB ); |
| |
| // get built-in name, or convert characters invalid in Calc |
| bool bBuiltIn = ::get_flag( nFlags, EXC_NAME_BUILTIN ); |
| |
| // special case for BIFF5 filter range - name appears as plain text without built-in flag |
| if( (GetBiff() == EXC_BIFF5) && (maXclName == XclTools::GetXclBuiltInDefName( EXC_BUILTIN_FILTERDATABASE )) ) |
| { |
| bBuiltIn = true; |
| maXclName.Assign( EXC_BUILTIN_FILTERDATABASE ); |
| } |
| |
| // convert Excel name to Calc name |
| if( mbVBName ) |
| { |
| // VB macro name |
| maScName = maXclName; |
| } |
| else if( bBuiltIn ) |
| { |
| // built-in name |
| if( maXclName.Len() ) |
| mcBuiltIn = maXclName.GetChar( 0 ); |
| if( mcBuiltIn == '?' ) // NUL character is imported as '?' |
| mcBuiltIn = '\0'; |
| maScName = XclTools::GetBuiltInDefName( mcBuiltIn ); |
| } |
| else |
| { |
| // any other name |
| maScName = maXclName; |
| ScfTools::ConvertToScDefinedName( maScName ); |
| } |
| |
| // add index for local names |
| if( nXclTab != EXC_NAME_GLOBAL ) |
| { |
| sal_uInt16 nUsedTab = (GetBiff() == EXC_BIFF8) ? nXclTab : nExtSheet; |
| // #163146# do not rename sheet-local names by default, this breaks VBA scripts |
| // maScName.Append( '_' ).Append( String::CreateFromInt32( nUsedTab ) ); |
| // TODO: may not work for BIFF5, handle skipped sheets (all BIFF) |
| mnScTab = static_cast< SCTAB >( nUsedTab - 1 ); |
| } |
| |
| // find an unused name |
| String aOrigName( maScName ); |
| //while( rRangeNames.SearchName( maScName, nDummy ) ) |
| //maScName.Assign( aOrigName ).Append( ' ' ).Append( String::CreateFromInt32( ++nCounter ) ); |
| |
| // 3) *** convert the name definition formula *** ------------------------- |
| |
| rFmlaConv.Reset(); |
| const ScTokenArray* pTokArr = 0; // pointer to token array, owned by rFmlaConv |
| RangeType nNameType = RT_NAME; |
| |
| if( ::get_flag( nFlags, EXC_NAME_BIG ) ) |
| { |
| // special, unsupported name |
| rFmlaConv.GetDummy( pTokArr ); |
| } |
| else if( bBuiltIn ) |
| { |
| // --- print ranges or title ranges --- |
| rStrm.PushPosition(); |
| switch( mcBuiltIn ) |
| { |
| case EXC_BUILTIN_PRINTAREA: |
| if( rFmlaConv.Convert( GetPrintAreaBuffer(), rStrm, nFmlaSize, FT_RangeName ) == ConvOK ) |
| nNameType |= RT_PRINTAREA; |
| break; |
| case EXC_BUILTIN_PRINTTITLES: |
| if( rFmlaConv.Convert( GetTitleAreaBuffer(), rStrm, nFmlaSize, FT_RangeName ) == ConvOK ) |
| nNameType |= RT_COLHEADER | RT_ROWHEADER; |
| break; |
| } |
| rStrm.PopPosition(); |
| |
| // --- name formula --- |
| // JEG : double check this. It is clearly false for normal names |
| // but some of the builtins (sheettitle?) might be able to handle arrays |
| rFmlaConv.Convert( pTokArr, rStrm, nFmlaSize, false, FT_RangeName ); |
| |
| // --- auto or advanced filter --- |
| if( (GetBiff() == EXC_BIFF8) && pTokArr && bBuiltIn ) |
| { |
| ScRange aRange; |
| if( pTokArr->IsReference( aRange ) ) |
| { |
| switch( mcBuiltIn ) |
| { |
| case EXC_BUILTIN_FILTERDATABASE: |
| GetFilterManager().Insert( &GetOldRoot(), aRange, maScName ); |
| break; |
| case EXC_BUILTIN_CRITERIA: |
| GetFilterManager().AddAdvancedRange( aRange ); |
| nNameType |= RT_CRITERIA; |
| break; |
| case EXC_BUILTIN_EXTRACT: |
| if( pTokArr->IsValidReference( aRange ) ) |
| GetFilterManager().AddExtractPos( aRange ); |
| break; |
| } |
| } |
| } |
| } |
| else if( nFmlaSize > 0 ) |
| { |
| // regular defined name |
| rFmlaConv.Convert( pTokArr, rStrm, nFmlaSize, true, FT_RangeName ); |
| } |
| |
| // 4) *** create a defined name in the Calc document *** ------------------ |
| |
| // #163146# do not ignore hidden names (may be regular names created by VBA scripts) |
| if( pTokArr /*&& (bBuiltIn || !::get_flag( nFlags, EXC_NAME_HIDDEN ))*/ && !mbFunction && !mbVBName ) |
| { |
| // create the Calc name data |
| ScRangeData* pData = new ScRangeData( GetDocPtr(), maScName, *pTokArr, ScAddress(), nNameType ); |
| pData->SetRangeScope(nXclTab == EXC_NAME_GLOBAL ? MAXTABCOUNT : mnScTab); |
| pData->GuessPosition(); // calculate base position for relative refs |
| pData->SetIndex( nXclNameIdx ); // used as unique identifier in formulas |
| rRangeNames.Insert( pData ); // takes ownership of pData |
| mpScData = pData; // cache for later use |
| } |
| } |
| |
| // ---------------------------------------------------------------------------- |
| |
| XclImpNameManager::XclImpNameManager( const XclImpRoot& rRoot ) : |
| XclImpRoot( rRoot ) |
| { |
| } |
| |
| void XclImpNameManager::ReadName( XclImpStream& rStrm ) |
| { |
| sal_uLong nCount = maNameList.Count(); |
| if( nCount < 0xFFFF ) |
| maNameList.Append( new XclImpName( rStrm, static_cast< sal_uInt16 >( nCount + 1 ) ) ); |
| } |
| |
| const XclImpName* XclImpNameManager::FindName( const String& rXclName, SCTAB nScTab ) const |
| { |
| const XclImpName* pGlobalName = 0; // a found global name |
| const XclImpName* pLocalName = 0; // a found local name |
| for( const XclImpName* pName = maNameList.First(); pName && !pLocalName; pName = maNameList.Next() ) |
| { |
| if( pName->GetXclName() == rXclName ) |
| { |
| if( pName->GetScTab() == nScTab ) |
| pLocalName = pName; |
| else if( pName->IsGlobal() ) |
| pGlobalName = pName; |
| } |
| } |
| return pLocalName ? pLocalName : pGlobalName; |
| } |
| |
| const XclImpName* XclImpNameManager::GetName( sal_uInt16 nXclNameIdx ) const |
| { |
| DBG_ASSERT( nXclNameIdx > 0, "XclImpNameManager::GetName - index must be >0" ); |
| return maNameList.GetObject( nXclNameIdx - 1 ); |
| } |
| |
| // ============================================================================ |
| |