xref: /aoo42x/main/sc/source/filter/excel/xiname.cxx (revision b77af630)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_scfilt.hxx"
26 #include "xiname.hxx"
27 #include "rangenam.hxx"
28 #include "xistream.hxx"
29 
30 // for formula compiler
31 #include "excform.hxx"
32 // for filter manager
33 #include "excimp8.hxx"
34 
35 // ============================================================================
36 // *** Implementation ***
37 // ============================================================================
38 
XclImpName(XclImpStream & rStrm,sal_uInt16 nXclNameIdx)39 XclImpName::XclImpName( XclImpStream& rStrm, sal_uInt16 nXclNameIdx ) :
40     XclImpRoot( rStrm.GetRoot() ),
41     mpScData( 0 ),
42     mcBuiltIn( EXC_BUILTIN_UNKNOWN ),
43     mnScTab( SCTAB_MAX ),
44     mbFunction( false ),
45     mbVBName( false )
46 {
47     ExcelToSc& rFmlaConv = GetOldFmlaConverter();
48     ScRangeName& rRangeNames = GetNamedRanges();
49 
50     // 1) *** read data from stream *** ---------------------------------------
51 
52     sal_uInt16 nFlags = 0, nFmlaSize = 0, nExtSheet = EXC_NAME_GLOBAL, nXclTab = EXC_NAME_GLOBAL;
53     sal_uInt8 nNameLen = 0, nShortCut;
54 
55     switch( GetBiff() )
56     {
57         case EXC_BIFF2:
58         {
59             sal_uInt8 nFlagsBiff2;
60             rStrm >> nFlagsBiff2;
61             rStrm.Ignore( 1 );
62             rStrm >> nShortCut >> nNameLen;
63             nFmlaSize = rStrm.ReaduInt8();
64             ::set_flag( nFlags, EXC_NAME_FUNC, ::get_flag( nFlagsBiff2, EXC_NAME2_FUNC ) );
65         }
66         break;
67 
68         case EXC_BIFF3:
69         case EXC_BIFF4:
70         {
71             rStrm >> nFlags >> nShortCut >> nNameLen >> nFmlaSize;
72         }
73         break;
74 
75         case EXC_BIFF5:
76         case EXC_BIFF8:
77         {
78             rStrm >> nFlags >> nShortCut >> nNameLen >> nFmlaSize >> nExtSheet >> nXclTab;
79             rStrm.Ignore( 4 );
80         }
81         break;
82 
83         default: DBG_ERROR_BIFF();
84     }
85 
86     if( GetBiff() <= EXC_BIFF5 )
87         maXclName = rStrm.ReadRawByteString( nNameLen );
88     else
89         maXclName = rStrm.ReadUniString( nNameLen );
90 
91     // 2) *** convert sheet index and name *** --------------------------------
92 
93     // functions and VBA
94     mbFunction = ::get_flag( nFlags, EXC_NAME_FUNC );
95     mbVBName = ::get_flag( nFlags, EXC_NAME_VB );
96 
97     // get built-in name, or convert characters invalid in Calc
98     bool bBuiltIn = ::get_flag( nFlags, EXC_NAME_BUILTIN );
99 
100     // special case for BIFF5 filter range - name appears as plain text without built-in flag
101     if( (GetBiff() == EXC_BIFF5) && (maXclName == XclTools::GetXclBuiltInDefName( EXC_BUILTIN_FILTERDATABASE )) )
102     {
103         bBuiltIn = true;
104         maXclName.Assign( EXC_BUILTIN_FILTERDATABASE );
105     }
106 
107     // convert Excel name to Calc name
108     if( mbVBName )
109     {
110         // VB macro name
111         maScName = maXclName;
112     }
113     else if( bBuiltIn )
114     {
115         // built-in name
116         if( maXclName.Len() )
117             mcBuiltIn = maXclName.GetChar( 0 );
118         if( mcBuiltIn == '?' )      // NUL character is imported as '?'
119             mcBuiltIn = '\0';
120         maScName = XclTools::GetBuiltInDefName( mcBuiltIn );
121     }
122     else
123     {
124         // any other name
125         maScName = maXclName;
126         ScfTools::ConvertToScDefinedName( maScName );
127     }
128 
129     // add index for local names
130     if( nXclTab != EXC_NAME_GLOBAL )
131     {
132         sal_uInt16 nUsedTab = (GetBiff() == EXC_BIFF8) ? nXclTab : nExtSheet;
133         // #163146# do not rename sheet-local names by default, this breaks VBA scripts
134 //        maScName.Append( '_' ).Append( String::CreateFromInt32( nUsedTab ) );
135         // TODO: may not work for BIFF5, handle skipped sheets (all BIFF)
136         mnScTab = static_cast< SCTAB >( nUsedTab - 1 );
137     }
138 
139     // find an unused name
140     String aOrigName( maScName );
141     //while( rRangeNames.SearchName( maScName, nDummy ) )
142         //maScName.Assign( aOrigName ).Append( ' ' ).Append( String::CreateFromInt32( ++nCounter ) );
143 
144     // 3) *** convert the name definition formula *** -------------------------
145 
146     rFmlaConv.Reset();
147     const ScTokenArray* pTokArr = 0; // pointer to token array, owned by rFmlaConv
148     RangeType nNameType = RT_NAME;
149 
150     if( ::get_flag( nFlags, EXC_NAME_BIG ) )
151     {
152         // special, unsupported name
153         rFmlaConv.GetDummy( pTokArr );
154     }
155     else if( bBuiltIn )
156     {
157         // --- print ranges or title ranges ---
158         rStrm.PushPosition();
159         switch( mcBuiltIn )
160         {
161             case EXC_BUILTIN_PRINTAREA:
162                 if( rFmlaConv.Convert( GetPrintAreaBuffer(), rStrm, nFmlaSize, FT_RangeName ) == ConvOK )
163                     nNameType |= RT_PRINTAREA;
164             break;
165             case EXC_BUILTIN_PRINTTITLES:
166                 if( rFmlaConv.Convert( GetTitleAreaBuffer(), rStrm, nFmlaSize, FT_RangeName ) == ConvOK )
167                     nNameType |= RT_COLHEADER | RT_ROWHEADER;
168             break;
169         }
170         rStrm.PopPosition();
171 
172         // --- name formula ---
173         // JEG : double check this.  It is clearly false for normal names
174         //  but some of the builtins (sheettitle?) might be able to handle arrays
175         rFmlaConv.Convert( pTokArr, rStrm, nFmlaSize, false, FT_RangeName );
176 
177         // --- auto or advanced filter ---
178         if( (GetBiff() == EXC_BIFF8) && pTokArr && bBuiltIn )
179         {
180             ScRange aRange;
181             if( pTokArr->IsReference( aRange ) )
182             {
183                 switch( mcBuiltIn )
184                 {
185                     case EXC_BUILTIN_FILTERDATABASE:
186                         GetFilterManager().Insert( &GetOldRoot(), aRange, maScName );
187                     break;
188                     case EXC_BUILTIN_CRITERIA:
189                         GetFilterManager().AddAdvancedRange( aRange );
190                         nNameType |= RT_CRITERIA;
191                     break;
192                     case EXC_BUILTIN_EXTRACT:
193                         if( pTokArr->IsValidReference( aRange ) )
194                             GetFilterManager().AddExtractPos( aRange );
195                     break;
196                 }
197             }
198         }
199     }
200     else if( nFmlaSize > 0 )
201     {
202         // regular defined name
203         rFmlaConv.Convert( pTokArr, rStrm, nFmlaSize, true, FT_RangeName );
204     }
205 
206     // 4) *** create a defined name in the Calc document *** ------------------
207 
208     // #163146# do not ignore hidden names (may be regular names created by VBA scripts)
209     if( pTokArr /*&& (bBuiltIn || !::get_flag( nFlags, EXC_NAME_HIDDEN ))*/ && !mbFunction && !mbVBName )
210     {
211         // create the Calc name data
212         ScRangeData* pData = new ScRangeData( GetDocPtr(), maScName, *pTokArr, ScAddress(), nNameType );
213 	 pData->SetRangeScope(nXclTab == EXC_NAME_GLOBAL ?  MAXTABCOUNT : mnScTab);
214         pData->GuessPosition();             // calculate base position for relative refs
215         pData->SetIndex( nXclNameIdx );     // used as unique identifier in formulas
216         rRangeNames.Insert( pData );        // takes ownership of pData
217         mpScData = pData;                   // cache for later use
218     }
219 }
220 
221 // ----------------------------------------------------------------------------
222 
XclImpNameManager(const XclImpRoot & rRoot)223 XclImpNameManager::XclImpNameManager( const XclImpRoot& rRoot ) :
224     XclImpRoot( rRoot )
225 {
226 }
227 
ReadName(XclImpStream & rStrm)228 void XclImpNameManager::ReadName( XclImpStream& rStrm )
229 {
230     sal_uLong nCount = maNameList.Count();
231     if( nCount < 0xFFFF )
232         maNameList.Append( new XclImpName( rStrm, static_cast< sal_uInt16 >( nCount + 1 ) ) );
233 }
234 
FindName(const String & rXclName,SCTAB nScTab) const235 const XclImpName* XclImpNameManager::FindName( const String& rXclName, SCTAB nScTab ) const
236 {
237     const XclImpName* pGlobalName = 0;   // a found global name
238     const XclImpName* pLocalName = 0;    // a found local name
239     for( const XclImpName* pName = maNameList.First(); pName && !pLocalName; pName = maNameList.Next() )
240     {
241         if( pName->GetXclName() == rXclName )
242         {
243             if( pName->GetScTab() == nScTab )
244                 pLocalName = pName;
245             else if( pName->IsGlobal() )
246                 pGlobalName = pName;
247         }
248     }
249     return pLocalName ? pLocalName : pGlobalName;
250 }
251 
GetName(sal_uInt16 nXclNameIdx) const252 const XclImpName* XclImpNameManager::GetName( sal_uInt16 nXclNameIdx ) const
253 {
254     DBG_ASSERT( nXclNameIdx > 0, "XclImpNameManager::GetName - index must be >0" );
255     return maNameList.GetObject( nXclNameIdx - 1 );
256 }
257 
258 // ============================================================================
259 
260