Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : : *
6 : : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
12 : : * OpenOffice.org is free software: you can redistribute it and/or modify
13 : : * it under the terms of the GNU Lesser General Public License version 3
14 : : * only, as published by the Free Software Foundation.
15 : : *
16 : : * OpenOffice.org is distributed in the hope that it will be useful,
17 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : : * GNU Lesser General Public License version 3 for more details
20 : : * (a copy is included in the LICENSE file that accompanied this code).
21 : : *
22 : : * You should have received a copy of the GNU Lesser General Public License
23 : : * version 3 along with OpenOffice.org. If not, see
24 : : * <http://www.openoffice.org/license.html>
25 : : * for a copy of the LGPLv3 License.
26 : : *
27 : : ************************************************************************/
28 : :
29 : : #include "xename.hxx"
30 : :
31 : : #include <map>
32 : :
33 : : #include "globstr.hrc"
34 : : #include "document.hxx"
35 : : #include "rangenam.hxx"
36 : : #include "dbdata.hxx"
37 : : #include "xehelper.hxx"
38 : : #include "xelink.hxx"
39 : : #include "globalnames.hxx"
40 : :
41 : : // for filter manager
42 : : #include "excrecds.hxx"
43 : :
44 : : #include <formula/grammar.hxx>
45 : :
46 : : using namespace ::oox;
47 : :
48 : : using ::rtl::OString;
49 : :
50 : : // ============================================================================
51 : : // *** Helper classes ***
52 : : // ============================================================================
53 : :
54 : : /** Represents an internal defined name, supports writing it to a NAME record. */
55 [ # # ][ # # ]: 0 : class XclExpName : public XclExpRecord, protected XclExpRoot
[ # # ][ # # ]
[ # # ][ # # ]
56 : : {
57 : : public:
58 : : /** Creates a standard defined name. */
59 : : explicit XclExpName( const XclExpRoot& rRoot, const String& rName );
60 : : /** Creates a built-in defined name. */
61 : : explicit XclExpName( const XclExpRoot& rRoot, sal_Unicode cBuiltIn );
62 : :
63 : : /** Sets a token array containing the definition of this name. */
64 : : void SetTokenArray( XclTokenArrayRef xTokArr );
65 : : /** Changes this defined name to be local on the specified Calc sheet. */
66 : : void SetLocalTab( SCTAB nScTab );
67 : : /** Hides or unhides the defined name. */
68 : : void SetHidden( bool bHidden = true );
69 : : /** Changes this name to be the call to a VB macro function or procedure.
70 : : @param bVBasic true = Visual Basic macro, false = Sheet macro.
71 : : @param bFunc true = Macro function; false = Macro procedure. */
72 : : void SetMacroCall( bool bVBasic, bool bFunc );
73 : :
74 : :
75 : : /** Sets the name's symbol value
76 : : @param sValue the name's symbolic value */
77 : : void SetSymbol( String sValue );
78 : : /** Returns the name's symbol value */
79 : : inline const String& GetSymbol() const { return msSymbol; }
80 : :
81 : : /** Returns the original name (title) of this defined name. */
82 : 0 : inline const String& GetOrigName() const { return maOrigName; }
83 : : /** Returns the Excel built-in name index of this defined name.
84 : : @return The built-in name index or EXC_BUILTIN_UNKNOWN for user-defined names. */
85 : 0 : inline sal_Unicode GetBuiltInName() const { return mcBuiltIn; }
86 : :
87 : : /** Returns the token array for this defined name. */
88 : 0 : inline XclTokenArrayRef GetTokenArray() const { return mxTokArr; }
89 : :
90 : : /** Returns true, if this is a document-global defined name. */
91 : 0 : inline bool IsGlobal() const { return mnXclTab == EXC_NAME_GLOBAL; }
92 : : /** Returns the Calc sheet of a local defined name. */
93 : 0 : inline SCTAB GetScTab() const { return mnScTab; }
94 : :
95 : : /** Returns true, if this defined name is volatile. */
96 : : bool IsVolatile() const;
97 : : /** Returns true, if this defined name describes a macro call.
98 : : @param bFunc true = Macro function; false = Macro procedure. */
99 : : bool IsMacroCall( bool bVBasic, bool bFunc ) const;
100 : :
101 : : /** Writes the entire NAME record to the passed stream. */
102 : : virtual void Save( XclExpStream& rStrm );
103 : :
104 : : virtual void SaveXml( XclExpXmlStream& rStrm );
105 : :
106 : : private:
107 : : /** Writes the body of the NAME record to the passed stream. */
108 : : virtual void WriteBody( XclExpStream& rStrm );
109 : :
110 : : private:
111 : : String maOrigName; /// The original user-defined name.
112 : : String msSymbol; /// The value of the symbol
113 : : XclExpStringRef mxName; /// The name as Excel string object.
114 : : XclTokenArrayRef mxTokArr; /// The definition of the defined name.
115 : : sal_Unicode mcBuiltIn; /// The built-in index for built-in names.
116 : : SCTAB mnScTab; /// The Calc sheet index for local names.
117 : : sal_uInt16 mnFlags; /// Additional flags for this defined name.
118 : : sal_uInt16 mnExtSheet; /// The 1-based index to a global EXTERNSHEET record.
119 : : sal_uInt16 mnXclTab; /// The 1-based Excel sheet index for local names.
120 : : };
121 : :
122 : : // ----------------------------------------------------------------------------
123 : :
124 : : class ScRangeData;
125 : : class ScDBData;
126 : :
127 : : /** Implementation class of the name manager. */
128 [ # # ][ # # ]: 0 : class XclExpNameManagerImpl : protected XclExpRoot
129 : : {
130 : : public:
131 : : explicit XclExpNameManagerImpl( const XclExpRoot& rRoot );
132 : :
133 : : /** Creates NAME records for built-in and user defined names. */
134 : : void Initialize();
135 : :
136 : : /** Inserts the Calc name with the passed index and returns the Excel NAME index. */
137 : : sal_uInt16 InsertName( SCTAB nTab, sal_uInt16 nScNameIdx );
138 : :
139 : : /** Inserts a new built-in defined name. */
140 : : sal_uInt16 InsertBuiltInName( sal_Unicode cBuiltIn, XclTokenArrayRef xTokArr, SCTAB nScTab, const ScRangeList& aRangeList );
141 : : sal_uInt16 InsertBuiltInName( sal_Unicode cBuiltIn, XclTokenArrayRef xTokArr, const ScRange& aRange );
142 : : /** Inserts a new defined name. Sets another unused name, if rName already exists. */
143 : : sal_uInt16 InsertUniqueName( const String& rName, XclTokenArrayRef xTokArr, SCTAB nScTab );
144 : : /** Returns index of an existing name, or creates a name without definition. */
145 : : sal_uInt16 InsertRawName( const String& rName );
146 : : /** Searches or inserts a defined name describing a macro name.
147 : : @param bVBasic true = Visual Basic macro; false = Sheet macro.
148 : : @param bFunc true = Macro function; false = Macro procedure. */
149 : : sal_uInt16 InsertMacroCall( const String& rMacroName, bool bVBasic, bool bFunc, bool bHidden );
150 : :
151 : : /** Returns the NAME record at the specified position or 0 on error. */
152 : : const XclExpName* GetName( sal_uInt16 nNameIdx ) const;
153 : :
154 : : /** Writes the entire list of NAME records.
155 : : @descr In BIFF7 and lower, writes the entire global link table, which
156 : : consists of an EXTERNCOUNT record, several EXTERNSHEET records, and
157 : : the list of NAME records. */
158 : : void Save( XclExpStream& rStrm );
159 : :
160 : : void SaveXml( XclExpXmlStream& rStrm );
161 : :
162 : : private:
163 : : typedef XclExpRecordList< XclExpName > XclExpNameList;
164 : : typedef XclExpNameList::RecordRefType XclExpNameRef;
165 : :
166 : : typedef ::std::map< ::std::pair<SCTAB, sal_uInt16>, sal_uInt16> NamedExpIndexMap;
167 : :
168 : : private:
169 : : /**
170 : : * @param nTab 0-based table index, or SCTAB_GLOBAL for global names.
171 : : * @param nScIdx calc's name index.
172 : : *
173 : : * @return excel's name index.
174 : : */
175 : : sal_uInt16 FindNamedExpIndex( SCTAB nTab, sal_uInt16 nScIdx );
176 : :
177 : : /** Returns the index of an existing built-in NAME record with the passed definition, otherwise 0. */
178 : : sal_uInt16 FindBuiltInNameIdx( const String& rName,
179 : : const XclTokenArray& rTokArr, bool bDBRange ) const;
180 : : /** Returns an unused name for the passed name. */
181 : : String GetUnusedName( const String& rName ) const;
182 : :
183 : : /** Appends a new NAME record to the record list.
184 : : @return The 1-based NAME record index used elsewhere in the Excel file. */
185 : : sal_uInt16 Append( XclExpNameRef xName );
186 : : /** Creates a new NAME record for the passed user-defined name.
187 : : @return The 1-based NAME record index used elsewhere in the Excel file. */
188 : : sal_uInt16 CreateName( SCTAB nTab, const ScRangeData& rRangeData );
189 : : /** Creates a new NAME record for the passed database range.
190 : : @return The 1-based NAME record index used elsewhere in the Excel file. */
191 : : sal_uInt16 CreateName( const ScDBData& rDBData );
192 : :
193 : : /** Creates NAME records for all built-in names in the document. */
194 : : void CreateBuiltInNames();
195 : : /** Creates NAME records for all user-defined names in the document. */
196 : : void CreateUserNames();
197 : :
198 : : private:
199 : : /**
200 : : * Maps Calc's named range to Excel's NAME records. Global names use
201 : : * -1 as their table index, whereas sheet-local names have 0-based table
202 : : * index.
203 : : */
204 : : NamedExpIndexMap maNamedExpMap;
205 : : XclExpNameList maNameList; /// List of NAME records.
206 : : size_t mnFirstUserIdx; /// List index of first user-defined NAME record.
207 : : };
208 : :
209 : : // ============================================================================
210 : : // *** Implementation ***
211 : : // ============================================================================
212 : :
213 : 0 : XclExpName::XclExpName( const XclExpRoot& rRoot, const String& rName ) :
214 : : XclExpRecord( EXC_ID_NAME ),
215 : : XclExpRoot( rRoot ),
216 : : maOrigName( rName ),
217 : : mxName( XclExpStringHelper::CreateString( rRoot, rName, EXC_STR_8BITLENGTH ) ),
218 : : mcBuiltIn( EXC_BUILTIN_UNKNOWN ),
219 : : mnScTab( SCTAB_GLOBAL ),
220 : : mnFlags( EXC_NAME_DEFAULT ),
221 : : mnExtSheet( EXC_NAME_GLOBAL ),
222 [ # # ][ # # ]: 0 : mnXclTab( EXC_NAME_GLOBAL )
[ # # ][ # # ]
[ # # ]
223 : : {
224 : 0 : }
225 : :
226 : 0 : XclExpName::XclExpName( const XclExpRoot& rRoot, sal_Unicode cBuiltIn ) :
227 : : XclExpRecord( EXC_ID_NAME ),
228 : : XclExpRoot( rRoot ),
229 : : mcBuiltIn( cBuiltIn ),
230 : : mnScTab( SCTAB_GLOBAL ),
231 : : mnFlags( EXC_NAME_DEFAULT ),
232 : : mnExtSheet( EXC_NAME_GLOBAL ),
233 [ # # ][ # # ]: 0 : mnXclTab( EXC_NAME_GLOBAL )
[ # # ][ # # ]
[ # # ]
234 : : {
235 : : // filter source range is hidden in Excel
236 [ # # ]: 0 : if( cBuiltIn == EXC_BUILTIN_FILTERDATABASE )
237 [ # # ]: 0 : SetHidden();
238 : :
239 : : // special case for BIFF5/7 filter source range - name appears as plain text without built-in flag
240 [ # # ][ # # ]: 0 : if( (GetBiff() <= EXC_BIFF5) && (cBuiltIn == EXC_BUILTIN_FILTERDATABASE) )
[ # # ]
241 : : {
242 [ # # ][ # # ]: 0 : String aName( XclTools::GetXclBuiltInDefName( EXC_BUILTIN_FILTERDATABASE ) );
243 [ # # ][ # # ]: 0 : mxName = XclExpStringHelper::CreateString( rRoot, aName, EXC_STR_8BITLENGTH );
[ # # ]
244 [ # # ][ # # ]: 0 : maOrigName = XclTools::GetXclBuiltInDefName( cBuiltIn );
[ # # ]
245 : : }
246 : : else
247 : : {
248 [ # # ][ # # ]: 0 : maOrigName = XclTools::GetBuiltInDefNameXml( cBuiltIn ) ;
249 [ # # ][ # # ]: 0 : mxName = XclExpStringHelper::CreateString( rRoot, cBuiltIn, EXC_STR_8BITLENGTH );
[ # # ]
250 : 0 : ::set_flag( mnFlags, EXC_NAME_BUILTIN );
251 : : }
252 : 0 : }
253 : :
254 : 0 : void XclExpName::SetTokenArray( XclTokenArrayRef xTokArr )
255 : : {
256 : 0 : mxTokArr = xTokArr;
257 : 0 : }
258 : :
259 : 0 : void XclExpName::SetLocalTab( SCTAB nScTab )
260 : : {
261 : : OSL_ENSURE( GetTabInfo().IsExportTab( nScTab ), "XclExpName::SetLocalTab - invalid sheet index" );
262 [ # # ]: 0 : if( GetTabInfo().IsExportTab( nScTab ) )
263 : : {
264 : 0 : mnScTab = nScTab;
265 : 0 : GetGlobalLinkManager().FindExtSheet( mnExtSheet, mnXclTab, nScTab );
266 : :
267 : : // special handling for NAME record
268 [ # # # ]: 0 : switch( GetBiff() )
269 : : {
270 : : case EXC_BIFF5: // EXTERNSHEET index is positive in NAME record
271 : 0 : mnExtSheet = ~mnExtSheet + 1;
272 : 0 : break;
273 : : case EXC_BIFF8: // EXTERNSHEET index not used, but must be created in link table
274 : 0 : mnExtSheet = 0;
275 : 0 : break;
276 : : default: DBG_ERROR_BIFF();
277 : : }
278 : :
279 : : // Excel sheet index is 1-based
280 : 0 : ++mnXclTab;
281 : : }
282 : 0 : }
283 : :
284 : 0 : void XclExpName::SetHidden( bool bHidden )
285 : : {
286 : 0 : ::set_flag( mnFlags, EXC_NAME_HIDDEN, bHidden );
287 : 0 : }
288 : :
289 : 0 : void XclExpName::SetMacroCall( bool bVBasic, bool bFunc )
290 : : {
291 : 0 : ::set_flag( mnFlags, EXC_NAME_PROC );
292 : 0 : ::set_flag( mnFlags, EXC_NAME_VB, bVBasic );
293 : 0 : ::set_flag( mnFlags, EXC_NAME_FUNC, bFunc );
294 : 0 : }
295 : :
296 : 0 : void XclExpName::SetSymbol( String sSymbol )
297 : : {
298 : 0 : msSymbol = sSymbol;
299 : 0 : }
300 : :
301 : 0 : bool XclExpName::IsVolatile() const
302 : : {
303 [ # # ][ # # ]: 0 : return mxTokArr && mxTokArr->IsVolatile();
304 : : }
305 : :
306 : 0 : bool XclExpName::IsMacroCall( bool bVBasic, bool bFunc ) const
307 : : {
308 : : return
309 : 0 : (::get_flag( mnFlags, EXC_NAME_VB ) == bVBasic) &&
310 [ # # ][ # # ]: 0 : (::get_flag( mnFlags, EXC_NAME_FUNC ) == bFunc);
311 : : }
312 : :
313 : 0 : void XclExpName::Save( XclExpStream& rStrm )
314 : : {
315 : : OSL_ENSURE( mxName && (mxName->Len() > 0), "XclExpName::Save - missing name" );
316 : : OSL_ENSURE( !(IsGlobal() && ::get_flag( mnFlags, EXC_NAME_BUILTIN )), "XclExpName::Save - global built-in name" );
317 [ # # ]: 0 : SetRecSize( 11 + mxName->GetSize() + (mxTokArr ? mxTokArr->GetSize() : 2) );
318 : 0 : XclExpRecord::Save( rStrm );
319 : 0 : }
320 : :
321 : 0 : void XclExpName::SaveXml( XclExpXmlStream& rStrm )
322 : : {
323 : 0 : sax_fastparser::FSHelperPtr& rWorkbook = rStrm.GetCurrentStream();
324 : : rWorkbook->startElement( XML_definedName,
325 : : // OOXTODO: XML_comment, "",
326 : : // OOXTODO: XML_customMenu, "",
327 : : // OOXTODO: XML_description, "",
328 : 0 : XML_function, XclXmlUtils::ToPsz( ::get_flag( mnFlags, EXC_NAME_VB ) ),
329 : : // OOXTODO: XML_functionGroupId, "",
330 : : // OOXTODO: XML_help, "",
331 : 0 : XML_hidden, XclXmlUtils::ToPsz( ::get_flag( mnFlags, EXC_NAME_HIDDEN ) ),
332 [ # # ][ # # ]: 0 : XML_localSheetId, mnScTab == SCTAB_GLOBAL ? NULL : OString::valueOf( (sal_Int32)mnScTab ).getStr(),
333 : : XML_name, XclXmlUtils::ToOString( maOrigName ).getStr(),
334 : : // OOXTODO: XML_publishToServer, "",
335 : : // OOXTODO: XML_shortcutKey, "",
336 : : // OOXTODO: XML_statusBar, "",
337 : 0 : XML_vbProcedure, XclXmlUtils::ToPsz( ::get_flag( mnFlags, EXC_NAME_VB ) ),
338 : : // OOXTODO: XML_workbookParameter, "",
339 : : // OOXTODO: XML_xlm, "",
340 [ # # # # ]: 0 : FSEND );
[ # # ][ # # ]
341 [ # # ]: 0 : rWorkbook->writeEscaped( XclXmlUtils::ToOUString( msSymbol ) );
342 : 0 : rWorkbook->endElement( XML_definedName );
343 : 0 : }
344 : :
345 : 0 : void XclExpName::WriteBody( XclExpStream& rStrm )
346 : : {
347 [ # # ]: 0 : sal_uInt16 nFmlaSize = mxTokArr ? mxTokArr->GetSize() : 0;
348 : :
349 : 0 : rStrm << mnFlags // flags
350 : 0 : << sal_uInt8( 0 ); // keyboard shortcut
351 : 0 : mxName->WriteLenField( rStrm ); // length of name
352 : 0 : rStrm << nFmlaSize // size of token array
353 : 0 : << mnExtSheet // BIFF5/7: EXTSHEET index, BIFF8: not used
354 : 0 : << mnXclTab // 1-based sheet index for local names
355 : 0 : << sal_uInt32( 0 ); // length of menu/descr/help/status text
356 : 0 : mxName->WriteFlagField( rStrm ); // BIFF8 flag field (no-op in <=BIFF7)
357 : 0 : mxName->WriteBuffer( rStrm ); // character array of the name
358 [ # # ]: 0 : if( mxTokArr )
359 : 0 : mxTokArr->WriteArray( rStrm ); // token array without size
360 : 0 : }
361 : :
362 : : // ----------------------------------------------------------------------------
363 : :
364 : 0 : XclExpNameManagerImpl::XclExpNameManagerImpl( const XclExpRoot& rRoot ) :
365 : : XclExpRoot( rRoot ),
366 [ # # ][ # # ]: 0 : mnFirstUserIdx( 0 )
367 : : {
368 : 0 : }
369 : :
370 : 0 : void XclExpNameManagerImpl::Initialize()
371 : : {
372 : 0 : CreateBuiltInNames();
373 : 0 : mnFirstUserIdx = maNameList.GetSize();
374 : 0 : CreateUserNames();
375 : 0 : }
376 : :
377 : 0 : sal_uInt16 XclExpNameManagerImpl::InsertName( SCTAB nTab, sal_uInt16 nScNameIdx )
378 : : {
379 : 0 : sal_uInt16 nNameIdx = FindNamedExpIndex( nTab, nScNameIdx );
380 [ # # ]: 0 : if (nNameIdx)
381 : 0 : return nNameIdx;
382 : :
383 : 0 : const ScRangeData* pData = NULL;
384 [ # # ]: 0 : ScRangeName* pRN = (nTab == SCTAB_GLOBAL) ? GetDoc().GetRangeName() : GetDoc().GetRangeName(nTab);
385 [ # # ]: 0 : if (pRN)
386 : 0 : pData = pRN->findByIndex(nScNameIdx);
387 : :
388 [ # # ]: 0 : if (pData)
389 : 0 : nNameIdx = CreateName(nTab, *pData);
390 : :
391 : 0 : return nNameIdx;
392 : : }
393 : :
394 : 0 : sal_uInt16 XclExpNameManagerImpl::InsertBuiltInName( sal_Unicode cBuiltIn, XclTokenArrayRef xTokArr, const ScRange& aRange )
395 : : {
396 [ # # ][ # # ]: 0 : XclExpNameRef xName( new XclExpName( GetRoot(), cBuiltIn ) );
[ # # ]
397 [ # # ][ # # ]: 0 : xName->SetTokenArray( xTokArr );
[ # # ]
398 [ # # ]: 0 : xName->SetLocalTab( aRange.aStart.Tab() );
399 [ # # ]: 0 : String sSymbol;
400 [ # # ]: 0 : aRange.Format( sSymbol, SCR_ABS_3D, GetDocPtr(), ScAddress::Details( ::formula::FormulaGrammar::CONV_XL_A1 ) );
401 [ # # ][ # # ]: 0 : xName->SetSymbol( sSymbol );
[ # # ]
402 [ # # ][ # # ]: 0 : return Append( xName );
[ # # ][ # # ]
[ # # ]
403 : : }
404 : :
405 : 0 : sal_uInt16 XclExpNameManagerImpl::InsertBuiltInName( sal_Unicode cBuiltIn, XclTokenArrayRef xTokArr, SCTAB nScTab, const ScRangeList& rRangeList )
406 : : {
407 [ # # ][ # # ]: 0 : XclExpNameRef xName( new XclExpName( GetRoot(), cBuiltIn ) );
[ # # ]
408 [ # # ][ # # ]: 0 : xName->SetTokenArray( xTokArr );
[ # # ]
409 [ # # ]: 0 : xName->SetLocalTab( nScTab );
410 [ # # ]: 0 : String sSymbol;
411 [ # # ]: 0 : rRangeList.Format( sSymbol, SCR_ABS_3D, GetDocPtr(), ::formula::FormulaGrammar::CONV_XL_A1 );
412 [ # # ][ # # ]: 0 : xName->SetSymbol( sSymbol );
[ # # ]
413 [ # # ][ # # ]: 0 : return Append( xName );
[ # # ][ # # ]
[ # # ]
414 : : }
415 : :
416 : 0 : sal_uInt16 XclExpNameManagerImpl::InsertUniqueName(
417 : : const String& rName, XclTokenArrayRef xTokArr, SCTAB nScTab )
418 : : {
419 : : OSL_ENSURE( rName.Len(), "XclExpNameManagerImpl::InsertUniqueName - empty name" );
420 [ # # ][ # # ]: 0 : XclExpNameRef xName( new XclExpName( GetRoot(), GetUnusedName( rName ) ) );
[ # # ][ # # ]
[ # # ]
421 [ # # ][ # # ]: 0 : xName->SetTokenArray( xTokArr );
[ # # ]
422 [ # # ]: 0 : xName->SetLocalTab( nScTab );
423 [ # # ][ # # ]: 0 : return Append( xName );
[ # # ][ # # ]
424 : : }
425 : :
426 : 0 : sal_uInt16 XclExpNameManagerImpl::InsertRawName( const String& rName )
427 : : {
428 : : // empty name? may occur in broken external Calc tokens
429 [ # # ]: 0 : if( !rName.Len() )
430 : 0 : return 0;
431 : :
432 : : // try to find an existing NAME record, regardless of its type
433 [ # # ]: 0 : for( size_t nListIdx = mnFirstUserIdx, nListSize = maNameList.GetSize(); nListIdx < nListSize; ++nListIdx )
434 : : {
435 [ # # ]: 0 : XclExpNameRef xName = maNameList.GetRecord( nListIdx );
436 [ # # ][ # # ]: 0 : if( xName->IsGlobal() && (xName->GetOrigName() == rName) )
[ # # ][ # # ]
437 : 0 : return static_cast< sal_uInt16 >( nListIdx + 1 );
438 [ # # ][ # # ]: 0 : }
439 : :
440 : : // create a new NAME record
441 [ # # ][ # # ]: 0 : XclExpNameRef xName( new XclExpName( GetRoot(), rName ) );
[ # # ]
442 [ # # ][ # # ]: 0 : return Append( xName );
[ # # ][ # # ]
443 : : }
444 : :
445 : 0 : sal_uInt16 XclExpNameManagerImpl::InsertMacroCall( const String& rMacroName, bool bVBasic, bool bFunc, bool bHidden )
446 : : {
447 : : // empty name? may occur in broken external Calc tokens
448 [ # # ]: 0 : if( !rMacroName.Len() )
449 : 0 : return 0;
450 : :
451 : : // try to find an existing NAME record
452 [ # # ]: 0 : for( size_t nListIdx = mnFirstUserIdx, nListSize = maNameList.GetSize(); nListIdx < nListSize; ++nListIdx )
453 : : {
454 [ # # ]: 0 : XclExpNameRef xName = maNameList.GetRecord( nListIdx );
455 [ # # ][ # # ]: 0 : if( xName->IsMacroCall( bVBasic, bFunc ) && (xName->GetOrigName() == rMacroName) )
[ # # ][ # # ]
[ # # ]
456 : 0 : return static_cast< sal_uInt16 >( nListIdx + 1 );
457 [ # # ][ # # ]: 0 : }
458 : :
459 : : // create a new NAME record
460 [ # # ][ # # ]: 0 : XclExpNameRef xName( new XclExpName( GetRoot(), rMacroName ) );
[ # # ]
461 [ # # ]: 0 : xName->SetMacroCall( bVBasic, bFunc );
462 [ # # ]: 0 : xName->SetHidden( bHidden );
463 : :
464 : : // for sheet macros, add a #NAME! error
465 [ # # ]: 0 : if( !bVBasic )
466 [ # # ][ # # ]: 0 : xName->SetTokenArray( GetFormulaCompiler().CreateErrorFormula( EXC_ERR_NAME ) );
[ # # ][ # # ]
467 : :
468 [ # # ][ # # ]: 0 : return Append( xName );
[ # # ][ # # ]
469 : : }
470 : :
471 : 0 : const XclExpName* XclExpNameManagerImpl::GetName( sal_uInt16 nNameIdx ) const
472 : : {
473 : : OSL_ENSURE( maNameList.HasRecord( nNameIdx - 1 ), "XclExpNameManagerImpl::GetName - wrong record index" );
474 : 0 : return maNameList.GetRecord( nNameIdx - 1 ).get();
475 : : }
476 : :
477 : 0 : void XclExpNameManagerImpl::Save( XclExpStream& rStrm )
478 : : {
479 : 0 : maNameList.Save( rStrm );
480 : 0 : }
481 : :
482 : 0 : void XclExpNameManagerImpl::SaveXml( XclExpXmlStream& rStrm )
483 : : {
484 [ # # ]: 0 : if( maNameList.IsEmpty() )
485 : 0 : return;
486 : 0 : sax_fastparser::FSHelperPtr& rWorkbook = rStrm.GetCurrentStream();
487 : 0 : rWorkbook->startElement( XML_definedNames, FSEND );
488 : 0 : maNameList.SaveXml( rStrm );
489 : 0 : rWorkbook->endElement( XML_definedNames );
490 : : }
491 : :
492 : : // private --------------------------------------------------------------------
493 : :
494 : 0 : sal_uInt16 XclExpNameManagerImpl::FindNamedExpIndex( SCTAB nTab, sal_uInt16 nScIdx )
495 : : {
496 [ # # ]: 0 : NamedExpIndexMap::key_type key = NamedExpIndexMap::key_type(nTab, nScIdx);
497 [ # # ][ # # ]: 0 : NamedExpIndexMap::const_iterator itr = maNamedExpMap.find(key);
498 [ # # ][ # # ]: 0 : return (itr == maNamedExpMap.end()) ? 0 : itr->second;
[ # # ][ # # ]
499 : : }
500 : :
501 : 0 : sal_uInt16 XclExpNameManagerImpl::FindBuiltInNameIdx(
502 : : const String& rName, const XclTokenArray& rTokArr, bool bDBRange ) const
503 : : {
504 : : /* Get built-in index from the name. Special case: the database range
505 : : 'unnamed' will be mapped to Excel's built-in '_FilterDatabase' name. */
506 [ # # ][ # # ]: 0 : sal_Unicode cBuiltIn = (bDBRange && (rName == String(RTL_CONSTASCII_USTRINGPARAM(STR_DB_LOCAL_NONAME)))) ?
[ # # ][ # # ]
507 [ # # ][ # # ]: 0 : EXC_BUILTIN_FILTERDATABASE : XclTools::GetBuiltInDefNameIndex( rName );
[ # # ][ # # ]
[ # # ][ # # ]
508 : :
509 [ # # ]: 0 : if( cBuiltIn < EXC_BUILTIN_UNKNOWN )
510 : : {
511 : : // try to find the record in existing built-in NAME record list
512 [ # # ]: 0 : for( size_t nPos = 0; nPos < mnFirstUserIdx; ++nPos )
513 : : {
514 [ # # ]: 0 : XclExpNameRef xName = maNameList.GetRecord( nPos );
515 [ # # ]: 0 : if( xName->GetBuiltInName() == cBuiltIn )
516 : : {
517 [ # # ]: 0 : XclTokenArrayRef xTokArr = xName->GetTokenArray();
518 [ # # ][ # # ]: 0 : if( xTokArr && (*xTokArr == rTokArr) )
[ # # ][ # # ]
519 [ # # ][ # # ]: 0 : return static_cast< sal_uInt16 >( nPos + 1 );
520 : : }
521 [ # # ][ # # ]: 0 : }
522 : : }
523 : 0 : return 0;
524 : : }
525 : :
526 : 0 : String XclExpNameManagerImpl::GetUnusedName( const String& rName ) const
527 : : {
528 : 0 : String aNewName( rName );
529 : 0 : sal_Int32 nAppIdx = 0;
530 : 0 : bool bExist = true;
531 [ # # ]: 0 : while( bExist )
532 : : {
533 : : // search the list of user-defined names
534 : 0 : bExist = false;
535 [ # # ][ # # ]: 0 : for( size_t nPos = mnFirstUserIdx, nSize = maNameList.GetSize(); !bExist && (nPos < nSize); ++nPos )
[ # # ]
536 : : {
537 [ # # ]: 0 : XclExpNameRef xName = maNameList.GetRecord( nPos );
538 [ # # ]: 0 : bExist = xName->GetOrigName() == aNewName;
539 : : // name exists -> create a new name "<originalname>_<counter>"
540 [ # # ]: 0 : if( bExist )
541 [ # # ][ # # ]: 0 : aNewName.Assign( rName ).Append( '_' ).Append( String::CreateFromInt32( ++nAppIdx ) );
[ # # ][ # # ]
[ # # ]
542 [ # # ]: 0 : }
543 : : }
544 : 0 : return aNewName;
545 : : }
546 : :
547 : 0 : sal_uInt16 XclExpNameManagerImpl::Append( XclExpNameRef xName )
548 : : {
549 [ # # ]: 0 : if( maNameList.GetSize() == 0xFFFF )
550 : 0 : return 0;
551 [ # # ]: 0 : maNameList.AppendRecord( xName );
552 : 0 : return static_cast< sal_uInt16 >( maNameList.GetSize() ); // 1-based
553 : : }
554 : :
555 : 0 : sal_uInt16 XclExpNameManagerImpl::CreateName( SCTAB nTab, const ScRangeData& rRangeData )
556 : : {
557 [ # # ]: 0 : const String& rName = rRangeData.GetName();
558 : :
559 : : /* #i38821# recursive names: first insert the (empty) name object,
560 : : otherwise a recursive call of this function from the formula compiler
561 : : with the same defined name will not find it and will create it again. */
562 : 0 : size_t nOldListSize = maNameList.GetSize();
563 [ # # ][ # # ]: 0 : XclExpNameRef xName( new XclExpName( GetRoot(), rName ) );
[ # # ]
564 [ # # ]: 0 : if (nTab != SCTAB_GLOBAL)
565 [ # # ]: 0 : xName->SetLocalTab(nTab);
566 [ # # ][ # # ]: 0 : sal_uInt16 nNameIdx = Append( xName );
[ # # ]
567 : : // store the index of the NAME record in the lookup map
568 [ # # ]: 0 : NamedExpIndexMap::key_type key = NamedExpIndexMap::key_type(nTab, rRangeData.GetIndex());
569 [ # # ]: 0 : maNamedExpMap[key] = nNameIdx;
570 : :
571 : : /* Create the definition formula.
572 : : This may cause recursive creation of other defined names. */
573 [ # # ]: 0 : if( const ScTokenArray* pScTokArr = const_cast< ScRangeData& >( rRangeData ).GetCode() )
574 : : {
575 [ # # ][ # # ]: 0 : XclTokenArrayRef xTokArr = GetFormulaCompiler().CreateFormula( EXC_FMLATYPE_NAME, *pScTokArr );
576 [ # # ][ # # ]: 0 : xName->SetTokenArray( xTokArr );
[ # # ]
577 : :
578 [ # # ]: 0 : String sSymbol;
579 [ # # ]: 0 : rRangeData.GetSymbol( sSymbol, formula::FormulaGrammar::GRAM_ENGLISH_XL_A1 );
580 [ # # ][ # # ]: 0 : xName->SetSymbol( sSymbol );
[ # # ]
581 : :
582 : : /* Try to replace by existing built-in name - complete token array is
583 : : needed for comparison, and due to the recursion problem above this
584 : : cannot be done earlier. If a built-in name is found, the created NAME
585 : : record for this name and all following records in the list must be
586 : : deleted, otherwise they may contain wrong name list indexes. */
587 [ # # ]: 0 : sal_uInt16 nBuiltInIdx = FindBuiltInNameIdx( rName, *xTokArr, false );
588 [ # # ]: 0 : if( nBuiltInIdx != 0 )
589 : : {
590 : : // delete the new NAME records
591 [ # # ]: 0 : while( maNameList.GetSize() > nOldListSize )
592 [ # # ]: 0 : maNameList.RemoveRecord( maNameList.GetSize() - 1 );
593 : : // use index of the found built-in NAME record
594 [ # # ]: 0 : key = NamedExpIndexMap::key_type(nTab, rRangeData.GetIndex());
595 [ # # ]: 0 : maNamedExpMap[key] = nNameIdx = nBuiltInIdx;
596 [ # # ][ # # ]: 0 : }
597 : : }
598 : :
599 [ # # ][ # # ]: 0 : return nNameIdx;
600 : : }
601 : :
602 : 0 : void XclExpNameManagerImpl::CreateBuiltInNames()
603 : : {
604 : 0 : ScDocument& rDoc = GetDoc();
605 : 0 : XclExpTabInfo& rTabInfo = GetTabInfo();
606 : :
607 : : /* #i2394# built-in defined names must be sorted by the name of the
608 : : containing sheet. Example: SheetA!Print_Range must be stored *before*
609 : : SheetB!Print_Range, regardless of the position of SheetA in the document! */
610 [ # # ]: 0 : for( SCTAB nScTabIdx = 0, nScTabCount = rTabInfo.GetScTabCount(); nScTabIdx < nScTabCount; ++nScTabIdx )
611 : : {
612 : : // find real sheet index from the nScTabIdx counter
613 : 0 : SCTAB nScTab = rTabInfo.GetRealScTab( nScTabIdx );
614 : : // create NAME records for all built-in names of this sheet
615 [ # # ]: 0 : if( rTabInfo.IsExportTab( nScTab ) )
616 : : {
617 : : // *** 1) print ranges *** ----------------------------------------
618 : :
619 [ # # ][ # # ]: 0 : if( rDoc.HasPrintRange() )
620 : : {
621 [ # # ]: 0 : ScRangeList aRangeList;
622 [ # # ][ # # ]: 0 : for( sal_uInt16 nIdx = 0, nCount = rDoc.GetPrintRangeCount( nScTab ); nIdx < nCount; ++nIdx )
623 : : {
624 [ # # ]: 0 : ScRange aRange( *rDoc.GetPrintRange( nScTab, nIdx ) );
625 : : // Calc document does not care about sheet index in print ranges
626 : 0 : aRange.aStart.SetTab( nScTab );
627 : 0 : aRange.aEnd.SetTab( nScTab );
628 [ # # ]: 0 : aRange.Justify();
629 [ # # ]: 0 : aRangeList.Append( aRange );
630 : : }
631 : : // create the NAME record (do not warn if ranges are shrunken)
632 [ # # ][ # # ]: 0 : GetAddressConverter().ValidateRangeList( aRangeList, false );
633 [ # # ][ # # ]: 0 : if( !aRangeList.empty() )
634 [ # # ][ # # ]: 0 : GetNameManager().InsertBuiltInName( EXC_BUILTIN_PRINTAREA, aRangeList );
[ # # ]
635 : : }
636 : :
637 : : // *** 2) print titles *** ----------------------------------------
638 : :
639 [ # # ]: 0 : ScRangeList aTitleList;
640 : : // repeated columns
641 [ # # ][ # # ]: 0 : if( const ScRange* pColRange = rDoc.GetRepeatColRange( nScTab ) )
642 : : aTitleList.Append( ScRange(
643 : 0 : pColRange->aStart.Col(), 0, nScTab,
644 [ # # ]: 0 : pColRange->aEnd.Col(), GetXclMaxPos().Row(), nScTab ) );
645 : : // repeated rows
646 [ # # ][ # # ]: 0 : if( const ScRange* pRowRange = rDoc.GetRepeatRowRange( nScTab ) )
647 : : aTitleList.Append( ScRange(
648 : : 0, pRowRange->aStart.Row(), nScTab,
649 [ # # ]: 0 : GetXclMaxPos().Col(), pRowRange->aEnd.Row(), nScTab ) );
650 : : // create the NAME record
651 [ # # ][ # # ]: 0 : GetAddressConverter().ValidateRangeList( aTitleList, false );
652 [ # # ][ # # ]: 0 : if( !aTitleList.empty() )
653 [ # # ][ # # ]: 0 : GetNameManager().InsertBuiltInName( EXC_BUILTIN_PRINTTITLES, aTitleList );
654 : :
655 : : // *** 3) filter ranges *** ---------------------------------------
656 : :
657 [ # # ]: 0 : if( GetBiff() == EXC_BIFF8 )
658 [ # # ][ # # ]: 0 : GetFilterManager().InitTabFilter( nScTab );
[ # # ]
659 : : }
660 : : }
661 : 0 : }
662 : :
663 : 0 : void XclExpNameManagerImpl::CreateUserNames()
664 : : {
665 [ # # ]: 0 : const ScRangeName& rNamedRanges = GetNamedRanges();
666 [ # # ][ # # ]: 0 : ScRangeName::const_iterator itr = rNamedRanges.begin(), itrEnd = rNamedRanges.end();
667 [ # # ][ # # ]: 0 : for (; itr != itrEnd; ++itr)
[ # # ]
668 : : {
669 : : // skip definitions of shared formulas
670 [ # # ][ # # ]: 0 : if (!itr->second->HasType(RT_SHARED) && !FindNamedExpIndex(SCTAB_GLOBAL, itr->second->GetIndex()))
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # #
# # # # ]
671 [ # # ][ # # ]: 0 : CreateName(SCTAB_GLOBAL, *itr->second);
672 : : }
673 : : //look at every sheet for local range names
674 [ # # ]: 0 : ScRangeName::TabNameCopyMap rLocalNames;
675 [ # # ]: 0 : GetDoc().GetAllTabRangeNames(rLocalNames);
676 : 0 : ScRangeName::TabNameCopyMap::iterator tabIt = rLocalNames.begin(), tabItEnd = rLocalNames.end();
677 [ # # ]: 0 : for (; tabIt != tabItEnd; ++tabIt)
678 : : {
679 [ # # ][ # # ]: 0 : itr = tabIt->second->begin(), itrEnd = tabIt->second->end();
680 [ # # ][ # # ]: 0 : for (; itr != itrEnd; ++itr)
[ # # ]
681 : : {
682 : : // skip definitions of shared formulas
683 [ # # ][ # # ]: 0 : if (!itr->second->HasType(RT_SHARED) && !FindNamedExpIndex(tabIt->first, itr->second->GetIndex()))
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # #
# # # # ]
684 [ # # ][ # # ]: 0 : CreateName(tabIt->first, *itr->second);
685 : : }
686 : 0 : }
687 : 0 : }
688 : :
689 : : // ----------------------------------------------------------------------------
690 : :
691 : 0 : XclExpNameManager::XclExpNameManager( const XclExpRoot& rRoot ) :
692 : : XclExpRoot( rRoot ),
693 [ # # ][ # # ]: 0 : mxImpl( new XclExpNameManagerImpl( rRoot ) )
[ # # ][ # # ]
694 : : {
695 : 0 : }
696 : :
697 [ # # ][ # # ]: 0 : XclExpNameManager::~XclExpNameManager()
698 : : {
699 [ # # ]: 0 : }
700 : :
701 : 0 : void XclExpNameManager::Initialize()
702 : : {
703 : 0 : mxImpl->Initialize();
704 : 0 : }
705 : :
706 : 0 : sal_uInt16 XclExpNameManager::InsertName( SCTAB nTab, sal_uInt16 nScNameIdx )
707 : : {
708 : 0 : return mxImpl->InsertName( nTab, nScNameIdx );
709 : : }
710 : :
711 : 0 : sal_uInt16 XclExpNameManager::InsertBuiltInName( sal_Unicode cBuiltIn, const ScRange& rRange )
712 : : {
713 [ # # ][ # # ]: 0 : XclTokenArrayRef xTokArr = GetFormulaCompiler().CreateFormula( EXC_FMLATYPE_NAME, rRange );
714 [ # # ][ # # ]: 0 : return mxImpl->InsertBuiltInName( cBuiltIn, xTokArr, rRange );
[ # # ][ # # ]
715 : : }
716 : :
717 : 0 : sal_uInt16 XclExpNameManager::InsertBuiltInName( sal_Unicode cBuiltIn, const ScRangeList& rRangeList )
718 : : {
719 : 0 : sal_uInt16 nNameIdx = 0;
720 [ # # ]: 0 : if( !rRangeList.empty() )
721 : : {
722 [ # # ][ # # ]: 0 : XclTokenArrayRef xTokArr = GetFormulaCompiler().CreateFormula( EXC_FMLATYPE_NAME, rRangeList );
723 [ # # ][ # # ]: 0 : nNameIdx = mxImpl->InsertBuiltInName( cBuiltIn, xTokArr, rRangeList.front()->aStart.Tab(), rRangeList );
[ # # ][ # # ]
[ # # ]
724 : : }
725 : 0 : return nNameIdx;
726 : : }
727 : :
728 : 0 : sal_uInt16 XclExpNameManager::InsertUniqueName(
729 : : const String& rName, XclTokenArrayRef xTokArr, SCTAB nScTab )
730 : : {
731 [ # # ]: 0 : return mxImpl->InsertUniqueName( rName, xTokArr, nScTab );
732 : : }
733 : :
734 : 0 : sal_uInt16 XclExpNameManager::InsertRawName( const String& rName )
735 : : {
736 : 0 : return mxImpl->InsertRawName( rName );
737 : : }
738 : :
739 : 0 : sal_uInt16 XclExpNameManager::InsertMacroCall( const String& rMacroName, bool bVBasic, bool bFunc, bool bHidden )
740 : : {
741 : 0 : return mxImpl->InsertMacroCall( rMacroName, bVBasic, bFunc, bHidden );
742 : : }
743 : :
744 : 0 : const String& XclExpNameManager::GetOrigName( sal_uInt16 nNameIdx ) const
745 : : {
746 : 0 : const XclExpName* pName = mxImpl->GetName( nNameIdx );
747 [ # # ]: 0 : return pName ? pName->GetOrigName() : EMPTY_STRING;
748 : : }
749 : :
750 : 0 : SCTAB XclExpNameManager::GetScTab( sal_uInt16 nNameIdx ) const
751 : : {
752 : 0 : const XclExpName* pName = mxImpl->GetName( nNameIdx );
753 [ # # ]: 0 : return pName ? pName->GetScTab() : SCTAB_GLOBAL;
754 : : }
755 : :
756 : 0 : bool XclExpNameManager::IsVolatile( sal_uInt16 nNameIdx ) const
757 : : {
758 : 0 : const XclExpName* pName = mxImpl->GetName( nNameIdx );
759 [ # # ][ # # ]: 0 : return pName && pName->IsVolatile();
760 : : }
761 : :
762 : 0 : void XclExpNameManager::Save( XclExpStream& rStrm )
763 : : {
764 : 0 : mxImpl->Save( rStrm );
765 : 0 : }
766 : :
767 : 0 : void XclExpNameManager::SaveXml( XclExpXmlStream& rStrm )
768 : : {
769 : 0 : mxImpl->SaveXml( rStrm );
770 [ + - ][ + - ]: 24 : }
771 : :
772 : : // ============================================================================
773 : :
774 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|