/************************************************************** * * 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_scfilt.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 ); } // ============================================================================