bump product version to 4.1.6.2
[LibreOffice.git] / sc / source / filter / excel / xename.cxx
blob276624cd2e6471a04dff440bee05c798f0e30657
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include "xename.hxx"
22 #include <map>
24 #include "globstr.hrc"
25 #include "document.hxx"
26 #include "rangenam.hxx"
27 #include "dbdata.hxx"
28 #include "xehelper.hxx"
29 #include "xelink.hxx"
30 #include "globalnames.hxx"
32 // for filter manager
33 #include "excrecds.hxx"
35 #include <formula/grammar.hxx>
37 using namespace ::oox;
40 // ============================================================================
41 // *** Helper classes ***
42 // ============================================================================
44 /** Represents an internal defined name, supports writing it to a NAME record. */
45 class XclExpName : public XclExpRecord, protected XclExpRoot
47 public:
48 /** Creates a standard defined name. */
49 explicit XclExpName( const XclExpRoot& rRoot, const String& rName );
50 /** Creates a built-in defined name. */
51 explicit XclExpName( const XclExpRoot& rRoot, sal_Unicode cBuiltIn );
53 /** Sets a token array containing the definition of this name. */
54 void SetTokenArray( XclTokenArrayRef xTokArr );
55 /** Changes this defined name to be local on the specified Calc sheet. */
56 void SetLocalTab( SCTAB nScTab );
57 /** Hides or unhides the defined name. */
58 void SetHidden( bool bHidden = true );
59 /** Changes this name to be the call to a VB macro function or procedure.
60 @param bVBasic true = Visual Basic macro, false = Sheet macro.
61 @param bFunc true = Macro function; false = Macro procedure. */
62 void SetMacroCall( bool bVBasic, bool bFunc );
65 /** Sets the name's symbol value
66 @param sValue the name's symbolic value */
67 void SetSymbol( String sValue );
68 /** Returns the name's symbol value */
69 inline const String& GetSymbol() const { return msSymbol; }
71 /** Returns the original name (title) of this defined name. */
72 inline const String& GetOrigName() const { return maOrigName; }
73 /** Returns the Excel built-in name index of this defined name.
74 @return The built-in name index or EXC_BUILTIN_UNKNOWN for user-defined names. */
75 inline sal_Unicode GetBuiltInName() const { return mcBuiltIn; }
77 /** Returns the token array for this defined name. */
78 inline XclTokenArrayRef GetTokenArray() const { return mxTokArr; }
80 /** Returns true, if this is a document-global defined name. */
81 inline bool IsGlobal() const { return mnXclTab == EXC_NAME_GLOBAL; }
82 /** Returns the Calc sheet of a local defined name. */
83 inline SCTAB GetScTab() const { return mnScTab; }
85 /** Returns true, if this defined name is volatile. */
86 bool IsVolatile() const;
87 /** Returns true, if this defined name describes a macro call.
88 @param bFunc true = Macro function; false = Macro procedure. */
89 bool IsMacroCall( bool bVBasic, bool bFunc ) const;
91 /** Writes the entire NAME record to the passed stream. */
92 virtual void Save( XclExpStream& rStrm );
94 virtual void SaveXml( XclExpXmlStream& rStrm );
96 private:
97 /** Writes the body of the NAME record to the passed stream. */
98 virtual void WriteBody( XclExpStream& rStrm );
100 private:
101 String maOrigName; /// The original user-defined name.
102 String msSymbol; /// The value of the symbol
103 XclExpStringRef mxName; /// The name as Excel string object.
104 XclTokenArrayRef mxTokArr; /// The definition of the defined name.
105 sal_Unicode mcBuiltIn; /// The built-in index for built-in names.
106 SCTAB mnScTab; /// The Calc sheet index for local names.
107 sal_uInt16 mnFlags; /// Additional flags for this defined name.
108 sal_uInt16 mnExtSheet; /// The 1-based index to a global EXTERNSHEET record.
109 sal_uInt16 mnXclTab; /// The 1-based Excel sheet index for local names.
112 // ----------------------------------------------------------------------------
114 class ScRangeData;
115 class ScDBData;
117 /** Implementation class of the name manager. */
118 class XclExpNameManagerImpl : protected XclExpRoot
120 public:
121 explicit XclExpNameManagerImpl( const XclExpRoot& rRoot );
123 /** Creates NAME records for built-in and user defined names. */
124 void Initialize();
126 /** Inserts the Calc name with the passed index and returns the Excel NAME index. */
127 sal_uInt16 InsertName( SCTAB nTab, sal_uInt16 nScNameIdx );
129 /** Inserts a new built-in defined name. */
130 sal_uInt16 InsertBuiltInName( sal_Unicode cBuiltIn, XclTokenArrayRef xTokArr, SCTAB nScTab, const ScRangeList& aRangeList );
131 sal_uInt16 InsertBuiltInName( sal_Unicode cBuiltIn, XclTokenArrayRef xTokArr, const ScRange& aRange );
132 /** Inserts a new defined name. Sets another unused name, if rName already exists. */
133 sal_uInt16 InsertUniqueName( const String& rName, XclTokenArrayRef xTokArr, SCTAB nScTab );
134 /** Returns index of an existing name, or creates a name without definition. */
135 sal_uInt16 InsertRawName( const String& rName );
136 /** Searches or inserts a defined name describing a macro name.
137 @param bVBasic true = Visual Basic macro; false = Sheet macro.
138 @param bFunc true = Macro function; false = Macro procedure. */
139 sal_uInt16 InsertMacroCall( const String& rMacroName, bool bVBasic, bool bFunc, bool bHidden );
141 /** Returns the NAME record at the specified position or 0 on error. */
142 const XclExpName* GetName( sal_uInt16 nNameIdx ) const;
144 /** Writes the entire list of NAME records.
145 @descr In BIFF7 and lower, writes the entire global link table, which
146 consists of an EXTERNCOUNT record, several EXTERNSHEET records, and
147 the list of NAME records. */
148 void Save( XclExpStream& rStrm );
150 void SaveXml( XclExpXmlStream& rStrm );
152 private:
153 typedef XclExpRecordList< XclExpName > XclExpNameList;
154 typedef XclExpNameList::RecordRefType XclExpNameRef;
156 typedef ::std::map< ::std::pair<SCTAB, sal_uInt16>, sal_uInt16> NamedExpIndexMap;
158 private:
160 * @param nTab 0-based table index, or SCTAB_GLOBAL for global names.
161 * @param nScIdx calc's name index.
163 * @return excel's name index.
165 sal_uInt16 FindNamedExpIndex( SCTAB nTab, sal_uInt16 nScIdx );
167 /** Returns the index of an existing built-in NAME record with the passed definition, otherwise 0. */
168 sal_uInt16 FindBuiltInNameIdx( const String& rName,
169 const XclTokenArray& rTokArr, bool bDBRange ) const;
170 /** Returns an unused name for the passed name. */
171 String GetUnusedName( const String& rName ) const;
173 /** Appends a new NAME record to the record list.
174 @return The 1-based NAME record index used elsewhere in the Excel file. */
175 sal_uInt16 Append( XclExpNameRef xName );
176 /** Creates a new NAME record for the passed user-defined name.
177 @return The 1-based NAME record index used elsewhere in the Excel file. */
178 sal_uInt16 CreateName( SCTAB nTab, const ScRangeData& rRangeData );
179 /** Creates a new NAME record for the passed database range.
180 @return The 1-based NAME record index used elsewhere in the Excel file. */
181 sal_uInt16 CreateName( const ScDBData& rDBData );
183 /** Creates NAME records for all built-in names in the document. */
184 void CreateBuiltInNames();
185 /** Creates NAME records for all user-defined names in the document. */
186 void CreateUserNames();
188 private:
190 * Maps Calc's named range to Excel's NAME records. Global names use
191 * -1 as their table index, whereas sheet-local names have 0-based table
192 * index.
194 NamedExpIndexMap maNamedExpMap;
195 XclExpNameList maNameList; /// List of NAME records.
196 size_t mnFirstUserIdx; /// List index of first user-defined NAME record.
199 // ============================================================================
200 // *** Implementation ***
201 // ============================================================================
203 XclExpName::XclExpName( const XclExpRoot& rRoot, const String& rName ) :
204 XclExpRecord( EXC_ID_NAME ),
205 XclExpRoot( rRoot ),
206 maOrigName( rName ),
207 mxName( XclExpStringHelper::CreateString( rRoot, rName, EXC_STR_8BITLENGTH ) ),
208 mcBuiltIn( EXC_BUILTIN_UNKNOWN ),
209 mnScTab( SCTAB_GLOBAL ),
210 mnFlags( EXC_NAME_DEFAULT ),
211 mnExtSheet( EXC_NAME_GLOBAL ),
212 mnXclTab( EXC_NAME_GLOBAL )
216 XclExpName::XclExpName( const XclExpRoot& rRoot, sal_Unicode cBuiltIn ) :
217 XclExpRecord( EXC_ID_NAME ),
218 XclExpRoot( rRoot ),
219 mcBuiltIn( cBuiltIn ),
220 mnScTab( SCTAB_GLOBAL ),
221 mnFlags( EXC_NAME_DEFAULT ),
222 mnExtSheet( EXC_NAME_GLOBAL ),
223 mnXclTab( EXC_NAME_GLOBAL )
225 // filter source range is hidden in Excel
226 if( cBuiltIn == EXC_BUILTIN_FILTERDATABASE )
227 SetHidden();
229 // special case for BIFF5/7 filter source range - name appears as plain text without built-in flag
230 if( (GetBiff() <= EXC_BIFF5) && (cBuiltIn == EXC_BUILTIN_FILTERDATABASE) )
232 String aName( XclTools::GetXclBuiltInDefName( EXC_BUILTIN_FILTERDATABASE ) );
233 mxName = XclExpStringHelper::CreateString( rRoot, aName, EXC_STR_8BITLENGTH );
234 maOrigName = XclTools::GetXclBuiltInDefName( cBuiltIn );
236 else
238 maOrigName = XclTools::GetBuiltInDefNameXml( cBuiltIn ) ;
239 mxName = XclExpStringHelper::CreateString( rRoot, cBuiltIn, EXC_STR_8BITLENGTH );
240 ::set_flag( mnFlags, EXC_NAME_BUILTIN );
244 void XclExpName::SetTokenArray( XclTokenArrayRef xTokArr )
246 mxTokArr = xTokArr;
249 void XclExpName::SetLocalTab( SCTAB nScTab )
251 OSL_ENSURE( GetTabInfo().IsExportTab( nScTab ), "XclExpName::SetLocalTab - invalid sheet index" );
252 if( GetTabInfo().IsExportTab( nScTab ) )
254 mnScTab = nScTab;
255 GetGlobalLinkManager().FindExtSheet( mnExtSheet, mnXclTab, nScTab );
257 // special handling for NAME record
258 switch( GetBiff() )
260 case EXC_BIFF5: // EXTERNSHEET index is positive in NAME record
261 mnExtSheet = ~mnExtSheet + 1;
262 break;
263 case EXC_BIFF8: // EXTERNSHEET index not used, but must be created in link table
264 mnExtSheet = 0;
265 break;
266 default: DBG_ERROR_BIFF();
269 // Excel sheet index is 1-based
270 ++mnXclTab;
274 void XclExpName::SetHidden( bool bHidden )
276 ::set_flag( mnFlags, EXC_NAME_HIDDEN, bHidden );
279 void XclExpName::SetMacroCall( bool bVBasic, bool bFunc )
281 ::set_flag( mnFlags, EXC_NAME_PROC );
282 ::set_flag( mnFlags, EXC_NAME_VB, bVBasic );
283 ::set_flag( mnFlags, EXC_NAME_FUNC, bFunc );
286 void XclExpName::SetSymbol( String sSymbol )
288 msSymbol = sSymbol;
291 bool XclExpName::IsVolatile() const
293 return mxTokArr && mxTokArr->IsVolatile();
296 bool XclExpName::IsMacroCall( bool bVBasic, bool bFunc ) const
298 return
299 (::get_flag( mnFlags, EXC_NAME_VB ) == bVBasic) &&
300 (::get_flag( mnFlags, EXC_NAME_FUNC ) == bFunc);
303 void XclExpName::Save( XclExpStream& rStrm )
305 OSL_ENSURE( mxName && (mxName->Len() > 0), "XclExpName::Save - missing name" );
306 OSL_ENSURE( !(IsGlobal() && ::get_flag( mnFlags, EXC_NAME_BUILTIN )), "XclExpName::Save - global built-in name" );
307 SetRecSize( 11 + mxName->GetSize() + (mxTokArr ? mxTokArr->GetSize() : 2) );
308 XclExpRecord::Save( rStrm );
311 void XclExpName::SaveXml( XclExpXmlStream& rStrm )
313 sax_fastparser::FSHelperPtr& rWorkbook = rStrm.GetCurrentStream();
314 rWorkbook->startElement( XML_definedName,
315 // OOXTODO: XML_comment, "",
316 // OOXTODO: XML_customMenu, "",
317 // OOXTODO: XML_description, "",
318 XML_function, XclXmlUtils::ToPsz( ::get_flag( mnFlags, EXC_NAME_VB ) ),
319 // OOXTODO: XML_functionGroupId, "",
320 // OOXTODO: XML_help, "",
321 XML_hidden, XclXmlUtils::ToPsz( ::get_flag( mnFlags, EXC_NAME_HIDDEN ) ),
322 XML_localSheetId, mnScTab == SCTAB_GLOBAL ? NULL : OString::valueOf( (sal_Int32)mnScTab ).getStr(),
323 XML_name, XclXmlUtils::ToOString( maOrigName ).getStr(),
324 // OOXTODO: XML_publishToServer, "",
325 // OOXTODO: XML_shortcutKey, "",
326 // OOXTODO: XML_statusBar, "",
327 XML_vbProcedure, XclXmlUtils::ToPsz( ::get_flag( mnFlags, EXC_NAME_VB ) ),
328 // OOXTODO: XML_workbookParameter, "",
329 // OOXTODO: XML_xlm, "",
330 FSEND );
331 rWorkbook->writeEscaped( XclXmlUtils::ToOUString( msSymbol ) );
332 rWorkbook->endElement( XML_definedName );
335 void XclExpName::WriteBody( XclExpStream& rStrm )
337 sal_uInt16 nFmlaSize = mxTokArr ? mxTokArr->GetSize() : 0;
339 rStrm << mnFlags // flags
340 << sal_uInt8( 0 ); // keyboard shortcut
341 mxName->WriteLenField( rStrm ); // length of name
342 rStrm << nFmlaSize // size of token array
343 << mnExtSheet // BIFF5/7: EXTSHEET index, BIFF8: not used
344 << mnXclTab // 1-based sheet index for local names
345 << sal_uInt32( 0 ); // length of menu/descr/help/status text
346 mxName->WriteFlagField( rStrm ); // BIFF8 flag field (no-op in <=BIFF7)
347 mxName->WriteBuffer( rStrm ); // character array of the name
348 if( mxTokArr )
349 mxTokArr->WriteArray( rStrm ); // token array without size
352 // ----------------------------------------------------------------------------
354 XclExpNameManagerImpl::XclExpNameManagerImpl( const XclExpRoot& rRoot ) :
355 XclExpRoot( rRoot ),
356 mnFirstUserIdx( 0 )
360 void XclExpNameManagerImpl::Initialize()
362 CreateBuiltInNames();
363 mnFirstUserIdx = maNameList.GetSize();
364 CreateUserNames();
367 sal_uInt16 XclExpNameManagerImpl::InsertName( SCTAB nTab, sal_uInt16 nScNameIdx )
369 sal_uInt16 nNameIdx = FindNamedExpIndex( nTab, nScNameIdx );
370 if (nNameIdx)
371 return nNameIdx;
373 const ScRangeData* pData = NULL;
374 ScRangeName* pRN = (nTab == SCTAB_GLOBAL) ? GetDoc().GetRangeName() : GetDoc().GetRangeName(nTab);
375 if (pRN)
376 pData = pRN->findByIndex(nScNameIdx);
378 if (pData)
379 nNameIdx = CreateName(nTab, *pData);
381 return nNameIdx;
384 sal_uInt16 XclExpNameManagerImpl::InsertBuiltInName( sal_Unicode cBuiltIn, XclTokenArrayRef xTokArr, const ScRange& aRange )
386 XclExpNameRef xName( new XclExpName( GetRoot(), cBuiltIn ) );
387 xName->SetTokenArray( xTokArr );
388 xName->SetLocalTab( aRange.aStart.Tab() );
389 String sSymbol;
390 aRange.Format( sSymbol, SCR_ABS_3D, GetDocPtr(), ScAddress::Details( ::formula::FormulaGrammar::CONV_XL_A1 ) );
391 xName->SetSymbol( sSymbol );
392 return Append( xName );
395 sal_uInt16 XclExpNameManagerImpl::InsertBuiltInName( sal_Unicode cBuiltIn, XclTokenArrayRef xTokArr, SCTAB nScTab, const ScRangeList& rRangeList )
397 XclExpNameRef xName( new XclExpName( GetRoot(), cBuiltIn ) );
398 xName->SetTokenArray( xTokArr );
399 xName->SetLocalTab( nScTab );
400 String sSymbol;
401 rRangeList.Format( sSymbol, SCR_ABS_3D, GetDocPtr(), ::formula::FormulaGrammar::CONV_XL_A1 );
402 xName->SetSymbol( sSymbol );
403 return Append( xName );
406 sal_uInt16 XclExpNameManagerImpl::InsertUniqueName(
407 const String& rName, XclTokenArrayRef xTokArr, SCTAB nScTab )
409 OSL_ENSURE( rName.Len(), "XclExpNameManagerImpl::InsertUniqueName - empty name" );
410 XclExpNameRef xName( new XclExpName( GetRoot(), GetUnusedName( rName ) ) );
411 xName->SetTokenArray( xTokArr );
412 xName->SetLocalTab( nScTab );
413 return Append( xName );
416 sal_uInt16 XclExpNameManagerImpl::InsertRawName( const String& rName )
418 // empty name? may occur in broken external Calc tokens
419 if( !rName.Len() )
420 return 0;
422 // try to find an existing NAME record, regardless of its type
423 for( size_t nListIdx = mnFirstUserIdx, nListSize = maNameList.GetSize(); nListIdx < nListSize; ++nListIdx )
425 XclExpNameRef xName = maNameList.GetRecord( nListIdx );
426 if( xName->IsGlobal() && (xName->GetOrigName() == rName) )
427 return static_cast< sal_uInt16 >( nListIdx + 1 );
430 // create a new NAME record
431 XclExpNameRef xName( new XclExpName( GetRoot(), rName ) );
432 return Append( xName );
435 sal_uInt16 XclExpNameManagerImpl::InsertMacroCall( const String& rMacroName, bool bVBasic, bool bFunc, bool bHidden )
437 // empty name? may occur in broken external Calc tokens
438 if( !rMacroName.Len() )
439 return 0;
441 // try to find an existing NAME record
442 for( size_t nListIdx = mnFirstUserIdx, nListSize = maNameList.GetSize(); nListIdx < nListSize; ++nListIdx )
444 XclExpNameRef xName = maNameList.GetRecord( nListIdx );
445 if( xName->IsMacroCall( bVBasic, bFunc ) && (xName->GetOrigName() == rMacroName) )
446 return static_cast< sal_uInt16 >( nListIdx + 1 );
449 // create a new NAME record
450 XclExpNameRef xName( new XclExpName( GetRoot(), rMacroName ) );
451 xName->SetMacroCall( bVBasic, bFunc );
452 xName->SetHidden( bHidden );
454 // for sheet macros, add a #NAME! error
455 if( !bVBasic )
456 xName->SetTokenArray( GetFormulaCompiler().CreateErrorFormula( EXC_ERR_NAME ) );
458 return Append( xName );
461 const XclExpName* XclExpNameManagerImpl::GetName( sal_uInt16 nNameIdx ) const
463 OSL_ENSURE( maNameList.HasRecord( nNameIdx - 1 ), "XclExpNameManagerImpl::GetName - wrong record index" );
464 return maNameList.GetRecord( nNameIdx - 1 ).get();
467 void XclExpNameManagerImpl::Save( XclExpStream& rStrm )
469 maNameList.Save( rStrm );
472 void XclExpNameManagerImpl::SaveXml( XclExpXmlStream& rStrm )
474 if( maNameList.IsEmpty() )
475 return;
476 sax_fastparser::FSHelperPtr& rWorkbook = rStrm.GetCurrentStream();
477 rWorkbook->startElement( XML_definedNames, FSEND );
478 maNameList.SaveXml( rStrm );
479 rWorkbook->endElement( XML_definedNames );
482 // private --------------------------------------------------------------------
484 sal_uInt16 XclExpNameManagerImpl::FindNamedExpIndex( SCTAB nTab, sal_uInt16 nScIdx )
486 NamedExpIndexMap::key_type key = NamedExpIndexMap::key_type(nTab, nScIdx);
487 NamedExpIndexMap::const_iterator itr = maNamedExpMap.find(key);
488 return (itr == maNamedExpMap.end()) ? 0 : itr->second;
491 sal_uInt16 XclExpNameManagerImpl::FindBuiltInNameIdx(
492 const String& rName, const XclTokenArray& rTokArr, bool bDBRange ) const
494 /* Get built-in index from the name. Special case: the database range
495 'unnamed' will be mapped to Excel's built-in '_FilterDatabase' name. */
496 sal_Unicode cBuiltIn = (bDBRange && (rName == String(RTL_CONSTASCII_USTRINGPARAM(STR_DB_LOCAL_NONAME)))) ?
497 EXC_BUILTIN_FILTERDATABASE : XclTools::GetBuiltInDefNameIndex( rName );
499 if( cBuiltIn < EXC_BUILTIN_UNKNOWN )
501 // try to find the record in existing built-in NAME record list
502 for( size_t nPos = 0; nPos < mnFirstUserIdx; ++nPos )
504 XclExpNameRef xName = maNameList.GetRecord( nPos );
505 if( xName->GetBuiltInName() == cBuiltIn )
507 XclTokenArrayRef xTokArr = xName->GetTokenArray();
508 if( xTokArr && (*xTokArr == rTokArr) )
509 return static_cast< sal_uInt16 >( nPos + 1 );
513 return 0;
516 String XclExpNameManagerImpl::GetUnusedName( const String& rName ) const
518 String aNewName( rName );
519 sal_Int32 nAppIdx = 0;
520 bool bExist = true;
521 while( bExist )
523 // search the list of user-defined names
524 bExist = false;
525 for( size_t nPos = mnFirstUserIdx, nSize = maNameList.GetSize(); !bExist && (nPos < nSize); ++nPos )
527 XclExpNameRef xName = maNameList.GetRecord( nPos );
528 bExist = xName->GetOrigName() == aNewName;
529 // name exists -> create a new name "<originalname>_<counter>"
530 if( bExist )
531 aNewName.Assign( rName ).Append( '_' ).Append( OUString::number( ++nAppIdx ) );
534 return aNewName;
537 sal_uInt16 XclExpNameManagerImpl::Append( XclExpNameRef xName )
539 if( maNameList.GetSize() == 0xFFFF )
540 return 0;
541 maNameList.AppendRecord( xName );
542 return static_cast< sal_uInt16 >( maNameList.GetSize() ); // 1-based
545 sal_uInt16 XclExpNameManagerImpl::CreateName( SCTAB nTab, const ScRangeData& rRangeData )
547 const String& rName = rRangeData.GetName();
549 /* #i38821# recursive names: first insert the (empty) name object,
550 otherwise a recursive call of this function from the formula compiler
551 with the same defined name will not find it and will create it again. */
552 size_t nOldListSize = maNameList.GetSize();
553 XclExpNameRef xName( new XclExpName( GetRoot(), rName ) );
554 if (nTab != SCTAB_GLOBAL)
555 xName->SetLocalTab(nTab);
556 sal_uInt16 nNameIdx = Append( xName );
557 // store the index of the NAME record in the lookup map
558 NamedExpIndexMap::key_type key = NamedExpIndexMap::key_type(nTab, rRangeData.GetIndex());
559 maNamedExpMap[key] = nNameIdx;
561 /* Create the definition formula.
562 This may cause recursive creation of other defined names. */
563 if( const ScTokenArray* pScTokArr = const_cast< ScRangeData& >( rRangeData ).GetCode() )
565 XclTokenArrayRef xTokArr = GetFormulaCompiler().CreateFormula( EXC_FMLATYPE_NAME, *pScTokArr );
566 xName->SetTokenArray( xTokArr );
568 String sSymbol;
569 rRangeData.GetSymbol( sSymbol, formula::FormulaGrammar::GRAM_ENGLISH_XL_A1 );
570 xName->SetSymbol( sSymbol );
572 /* Try to replace by existing built-in name - complete token array is
573 needed for comparison, and due to the recursion problem above this
574 cannot be done earlier. If a built-in name is found, the created NAME
575 record for this name and all following records in the list must be
576 deleted, otherwise they may contain wrong name list indexes. */
577 sal_uInt16 nBuiltInIdx = FindBuiltInNameIdx( rName, *xTokArr, false );
578 if( nBuiltInIdx != 0 )
580 // delete the new NAME records
581 while( maNameList.GetSize() > nOldListSize )
582 maNameList.RemoveRecord( maNameList.GetSize() - 1 );
583 // use index of the found built-in NAME record
584 key = NamedExpIndexMap::key_type(nTab, rRangeData.GetIndex());
585 maNamedExpMap[key] = nNameIdx = nBuiltInIdx;
589 return nNameIdx;
592 void XclExpNameManagerImpl::CreateBuiltInNames()
594 ScDocument& rDoc = GetDoc();
595 XclExpTabInfo& rTabInfo = GetTabInfo();
597 /* #i2394# built-in defined names must be sorted by the name of the
598 containing sheet. Example: SheetA!Print_Range must be stored *before*
599 SheetB!Print_Range, regardless of the position of SheetA in the document! */
600 for( SCTAB nScTabIdx = 0, nScTabCount = rTabInfo.GetScTabCount(); nScTabIdx < nScTabCount; ++nScTabIdx )
602 // find real sheet index from the nScTabIdx counter
603 SCTAB nScTab = rTabInfo.GetRealScTab( nScTabIdx );
604 // create NAME records for all built-in names of this sheet
605 if( rTabInfo.IsExportTab( nScTab ) )
607 // *** 1) print ranges *** ----------------------------------------
609 if( rDoc.HasPrintRange() )
611 ScRangeList aRangeList;
612 for( sal_uInt16 nIdx = 0, nCount = rDoc.GetPrintRangeCount( nScTab ); nIdx < nCount; ++nIdx )
614 ScRange aRange( *rDoc.GetPrintRange( nScTab, nIdx ) );
615 // Calc document does not care about sheet index in print ranges
616 aRange.aStart.SetTab( nScTab );
617 aRange.aEnd.SetTab( nScTab );
618 aRange.Justify();
619 aRangeList.Append( aRange );
621 // create the NAME record (do not warn if ranges are shrunken)
622 GetAddressConverter().ValidateRangeList( aRangeList, false );
623 if( !aRangeList.empty() )
624 GetNameManager().InsertBuiltInName( EXC_BUILTIN_PRINTAREA, aRangeList );
627 // *** 2) print titles *** ----------------------------------------
629 ScRangeList aTitleList;
630 // repeated columns
631 if( const ScRange* pColRange = rDoc.GetRepeatColRange( nScTab ) )
632 aTitleList.Append( ScRange(
633 pColRange->aStart.Col(), 0, nScTab,
634 pColRange->aEnd.Col(), GetXclMaxPos().Row(), nScTab ) );
635 // repeated rows
636 if( const ScRange* pRowRange = rDoc.GetRepeatRowRange( nScTab ) )
637 aTitleList.Append( ScRange(
638 0, pRowRange->aStart.Row(), nScTab,
639 GetXclMaxPos().Col(), pRowRange->aEnd.Row(), nScTab ) );
640 // create the NAME record
641 GetAddressConverter().ValidateRangeList( aTitleList, false );
642 if( !aTitleList.empty() )
643 GetNameManager().InsertBuiltInName( EXC_BUILTIN_PRINTTITLES, aTitleList );
645 // *** 3) filter ranges *** ---------------------------------------
647 if( GetBiff() == EXC_BIFF8 )
648 GetFilterManager().InitTabFilter( nScTab );
653 void XclExpNameManagerImpl::CreateUserNames()
655 const ScRangeName& rNamedRanges = GetNamedRanges();
656 ScRangeName::const_iterator itr = rNamedRanges.begin(), itrEnd = rNamedRanges.end();
657 for (; itr != itrEnd; ++itr)
659 // skip definitions of shared formulas
660 if (!itr->second->HasType(RT_SHARED) && !FindNamedExpIndex(SCTAB_GLOBAL, itr->second->GetIndex()))
661 CreateName(SCTAB_GLOBAL, *itr->second);
663 //look at every sheet for local range names
664 ScRangeName::TabNameCopyMap rLocalNames;
665 GetDoc().GetAllTabRangeNames(rLocalNames);
666 ScRangeName::TabNameCopyMap::iterator tabIt = rLocalNames.begin(), tabItEnd = rLocalNames.end();
667 for (; tabIt != tabItEnd; ++tabIt)
669 itr = tabIt->second->begin(), itrEnd = tabIt->second->end();
670 for (; itr != itrEnd; ++itr)
672 // skip definitions of shared formulas
673 if (!itr->second->HasType(RT_SHARED) && !FindNamedExpIndex(tabIt->first, itr->second->GetIndex()))
674 CreateName(tabIt->first, *itr->second);
679 // ----------------------------------------------------------------------------
681 XclExpNameManager::XclExpNameManager( const XclExpRoot& rRoot ) :
682 XclExpRoot( rRoot ),
683 mxImpl( new XclExpNameManagerImpl( rRoot ) )
687 XclExpNameManager::~XclExpNameManager()
691 void XclExpNameManager::Initialize()
693 mxImpl->Initialize();
696 sal_uInt16 XclExpNameManager::InsertName( SCTAB nTab, sal_uInt16 nScNameIdx )
698 return mxImpl->InsertName( nTab, nScNameIdx );
701 sal_uInt16 XclExpNameManager::InsertBuiltInName( sal_Unicode cBuiltIn, const ScRange& rRange )
703 XclTokenArrayRef xTokArr = GetFormulaCompiler().CreateFormula( EXC_FMLATYPE_NAME, rRange );
704 return mxImpl->InsertBuiltInName( cBuiltIn, xTokArr, rRange );
707 sal_uInt16 XclExpNameManager::InsertBuiltInName( sal_Unicode cBuiltIn, const ScRangeList& rRangeList )
709 sal_uInt16 nNameIdx = 0;
710 if( !rRangeList.empty() )
712 XclTokenArrayRef xTokArr = GetFormulaCompiler().CreateFormula( EXC_FMLATYPE_NAME, rRangeList );
713 nNameIdx = mxImpl->InsertBuiltInName( cBuiltIn, xTokArr, rRangeList.front()->aStart.Tab(), rRangeList );
715 return nNameIdx;
718 sal_uInt16 XclExpNameManager::InsertUniqueName(
719 const String& rName, XclTokenArrayRef xTokArr, SCTAB nScTab )
721 return mxImpl->InsertUniqueName( rName, xTokArr, nScTab );
724 sal_uInt16 XclExpNameManager::InsertRawName( const String& rName )
726 return mxImpl->InsertRawName( rName );
729 sal_uInt16 XclExpNameManager::InsertMacroCall( const String& rMacroName, bool bVBasic, bool bFunc, bool bHidden )
731 return mxImpl->InsertMacroCall( rMacroName, bVBasic, bFunc, bHidden );
734 const String& XclExpNameManager::GetOrigName( sal_uInt16 nNameIdx ) const
736 const XclExpName* pName = mxImpl->GetName( nNameIdx );
737 return pName ? pName->GetOrigName() : EMPTY_STRING;
740 SCTAB XclExpNameManager::GetScTab( sal_uInt16 nNameIdx ) const
742 const XclExpName* pName = mxImpl->GetName( nNameIdx );
743 return pName ? pName->GetScTab() : SCTAB_GLOBAL;
746 bool XclExpNameManager::IsVolatile( sal_uInt16 nNameIdx ) const
748 const XclExpName* pName = mxImpl->GetName( nNameIdx );
749 return pName && pName->IsVolatile();
752 void XclExpNameManager::Save( XclExpStream& rStrm )
754 mxImpl->Save( rStrm );
757 void XclExpNameManager::SaveXml( XclExpXmlStream& rStrm )
759 mxImpl->SaveXml( rStrm );
762 // ============================================================================
764 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */