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_sc.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