merge the formfield patch from ooo-build
[ooovba.git] / sc / source / filter / excel / xename.cxx
blobace7a66dc1f93fcbe0869109bc9c0ddeb3c87763
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: xename.cxx,v $
10 * $Revision: 1.11 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sc.hxx"
33 #include "xename.hxx"
35 #include <map>
37 #include "globstr.hrc"
38 #include "document.hxx"
39 #include "rangenam.hxx"
40 #include "dbcolect.hxx"
41 #include "xehelper.hxx"
42 #include "xelink.hxx"
44 // for filter manager
45 #include "excrecds.hxx"
47 #include <oox/core/tokens.hxx>
48 #include <formula/grammar.hxx>
50 using ::rtl::OString;
52 // ============================================================================
53 // *** Helper classes ***
54 // ============================================================================
56 /** Represents an internal defined name, supports writing it to a NAME record. */
57 class XclExpName : public XclExpRecord, protected XclExpRoot
59 public:
60 /** Creates a standard defined name. */
61 explicit XclExpName( const XclExpRoot& rRoot, const String& rName );
62 /** Creates a built-in defined name. */
63 explicit XclExpName( const XclExpRoot& rRoot, sal_Unicode cBuiltIn );
65 /** Sets a token array containing the definition of this name. */
66 void SetTokenArray( XclTokenArrayRef xTokArr );
67 /** Changes this defined name to be local on the specified Calc sheet. */
68 void SetLocalTab( SCTAB nScTab );
69 /** Hides or unhides the defined name. */
70 void SetHidden( bool bHidden = true );
71 /** Changes this name to be the call to a VB macro function or procedure.
72 @param bVBasic true = Visual Basic macro, false = Sheet macro.
73 @param bFunc true = Macro function; false = Macro procedure. */
74 void SetMacroCall( bool bVBasic, bool bFunc );
77 /** Sets the name's symbol value
78 @param sValue the name's symbolic value */
79 void SetSymbol( String sValue );
80 /** Returns the name's symbol value */
81 inline const String& GetSymbol() const { return msSymbol; }
83 /** Returns the original name (title) of this defined name. */
84 inline const String& GetOrigName() const { return maOrigName; }
85 /** Returns the Excel built-in name index of this defined name.
86 @return The built-in name index or EXC_BUILTIN_UNKNOWN for user-defined names. */
87 inline sal_Unicode GetBuiltInName() const { return mcBuiltIn; }
89 /** Returns the token array for this defined name. */
90 inline XclTokenArrayRef GetTokenArray() const { return mxTokArr; }
92 /** Returns true, if this is a document-global defined name. */
93 inline bool IsGlobal() const { return mnXclTab == EXC_NAME_GLOBAL; }
94 /** Returns the Calc sheet of a local defined name. */
95 inline SCTAB GetScTab() const { return mnScTab; }
97 /** Returns true, if this defined name is volatile. */
98 bool IsVolatile() const;
99 /** Returns true, if this defined name is hidden. */
100 bool IsHidden() const;
101 /** Returns true, if this defined name describes a macro call.
102 @param bFunc true = Macro function; false = Macro procedure. */
103 bool IsMacroCall( bool bVBasic, bool bFunc ) const;
105 /** Writes the entire NAME record to the passed stream. */
106 virtual void Save( XclExpStream& rStrm );
108 virtual void SaveXml( XclExpXmlStream& rStrm );
110 private:
111 /** Writes the body of the NAME record to the passed stream. */
112 virtual void WriteBody( XclExpStream& rStrm );
114 private:
115 String maOrigName; /// The original user-defined name.
116 String msSymbol; /// The value of the symbol
117 XclExpStringRef mxName; /// The name as Excel string object.
118 XclTokenArrayRef mxTokArr; /// The definition of the defined name.
119 sal_Unicode mcBuiltIn; /// The built-in index for built-in names.
120 SCTAB mnScTab; /// The Calc sheet index for local names.
121 sal_uInt16 mnFlags; /// Additional flags for this defined name.
122 sal_uInt16 mnExtSheet; /// The 1-based index to a global EXTERNSHEET record.
123 sal_uInt16 mnXclTab; /// The 1-based Excel sheet index for local names.
126 // ----------------------------------------------------------------------------
128 class ScRangeData;
129 class ScDBData;
131 /** Implementation class of the name manager. */
132 class XclExpNameManagerImpl : protected XclExpRoot
134 public:
135 explicit XclExpNameManagerImpl( const XclExpRoot& rRoot );
137 /** Creates NAME records for built-in and user defined names. */
138 void Initialize();
140 /** Inserts the Calc name with the passed index and returns the Excel NAME index. */
141 sal_uInt16 InsertName( USHORT nScNameIdx );
142 /** Inserts the Calc database range with the passed index and returns the Excel NAME index. */
143 sal_uInt16 InsertDBRange( USHORT nScDBRangeIdx );
145 /** Inserts a new built-in defined name. */
146 sal_uInt16 InsertBuiltInName( sal_Unicode cBuiltIn, XclTokenArrayRef xTokArr, SCTAB nScTab );
147 /** Inserts a new defined name. Sets another unused name, if rName already exists. */
148 sal_uInt16 InsertUniqueName( const String& rName, XclTokenArrayRef xTokArr, SCTAB nScTab );
149 /** Returns index of an existing name, or creates a name without definition. */
150 sal_uInt16 InsertRawName( const String& rName );
151 /** Searches or inserts a defined name describing a macro name.
152 @param bVBasic true = Visual Basic macro; false = Sheet macro.
153 @param bFunc true = Macro function; false = Macro procedure. */
154 sal_uInt16 InsertMacroCall( const String& rMacroName, bool bVBasic, bool bFunc, bool bHidden );
156 /** Returns the NAME record at the specified position or 0 on error. */
157 const XclExpName* GetName( sal_uInt16 nNameIdx ) const;
159 /** Writes the entire list of NAME records.
160 @descr In BIFF7 and lower, writes the entire global link table, which
161 consists of an EXTERNCOUNT record, several EXTERNSHEET records, and
162 the list of NAME records. */
163 void Save( XclExpStream& rStrm );
165 void SaveXml( XclExpXmlStream& rStrm );
167 private:
168 typedef XclExpRecordList< XclExpName > XclExpNameList;
169 typedef XclExpNameList::RecordRefType XclExpNameRef;
170 typedef ::std::map< USHORT, sal_uInt16 > XclExpIndexMap;
172 private:
173 /** Finds the index of a NAME record from the passed Calc index in the specified map. */
174 sal_uInt16 FindNameIdx( const XclExpIndexMap& rMap, USHORT nScIdx ) const;
175 /** Returns the index of an existing built-in NAME record with the passed definition, otherwise 0. */
176 sal_uInt16 FindBuiltInNameIdx( const String& rName,
177 const XclTokenArray& rTokArr, bool bDBRange ) const;
178 /** Returns an unused name for the passed name. */
179 String GetUnusedName( const String& rName ) const;
181 /** Appends a new NAME record to the record list.
182 @return The 1-based NAME record index used elsewhere in the Excel file. */
183 sal_uInt16 Append( XclExpNameRef xName );
184 /** Creates a new NAME record for the passed user-defined name.
185 @return The 1-based NAME record index used elsewhere in the Excel file. */
186 sal_uInt16 CreateName( const ScRangeData& rRangeData );
187 /** Creates a new NAME record for the passed database range.
188 @return The 1-based NAME record index used elsewhere in the Excel file. */
189 sal_uInt16 CreateName( const ScDBData& rDBData );
191 /** Creates NAME records for all built-in names in the document. */
192 void CreateBuiltInNames();
193 /** Creates NAME records for all user-defined names in the document. */
194 void CreateUserNames();
195 /** Creates NAME records for all database ranges in the document. */
196 void CreateDatabaseNames();
198 private:
199 XclExpNameList maNameList; /// List of NAME records.
200 XclExpIndexMap maNameMap; /// Maps Calc defined names to Excel NAME records.
201 XclExpIndexMap maDBRangeMap; /// Maps Calc database ranges to Excel NAME records.
202 String maUnnamedDBName; /// Name of the hidden unnamed database range.
203 size_t mnFirstUserIdx; /// List index of first user-defined NAME record.
206 // ============================================================================
207 // *** Implementation ***
208 // ============================================================================
210 XclExpName::XclExpName( const XclExpRoot& rRoot, const String& rName ) :
211 XclExpRecord( EXC_ID_NAME ),
212 XclExpRoot( rRoot ),
213 maOrigName( rName ),
214 mxName( XclExpStringHelper::CreateString( rRoot, rName, EXC_STR_8BITLENGTH ) ),
215 mcBuiltIn( EXC_BUILTIN_UNKNOWN ),
216 mnScTab( SCTAB_GLOBAL ),
217 mnFlags( EXC_NAME_DEFAULT ),
218 mnExtSheet( EXC_NAME_GLOBAL ),
219 mnXclTab( EXC_NAME_GLOBAL )
223 XclExpName::XclExpName( const XclExpRoot& rRoot, sal_Unicode cBuiltIn ) :
224 XclExpRecord( EXC_ID_NAME ),
225 XclExpRoot( rRoot ),
226 mcBuiltIn( cBuiltIn ),
227 mnScTab( SCTAB_GLOBAL ),
228 mnFlags( EXC_NAME_DEFAULT ),
229 mnExtSheet( EXC_NAME_GLOBAL ),
230 mnXclTab( EXC_NAME_GLOBAL )
232 // filter source range is hidden in Excel
233 if( cBuiltIn == EXC_BUILTIN_FILTERDATABASE )
234 SetHidden();
236 // special case for BIFF5/7 filter source range - name appears as plain text without built-in flag
237 if( (GetBiff() <= EXC_BIFF5) && (cBuiltIn == EXC_BUILTIN_FILTERDATABASE) )
239 String aName( XclTools::GetXclBuiltInDefName( EXC_BUILTIN_FILTERDATABASE ) );
240 mxName = XclExpStringHelper::CreateString( rRoot, aName, EXC_STR_8BITLENGTH );
242 else
244 mxName = XclExpStringHelper::CreateString( rRoot, cBuiltIn, EXC_STR_8BITLENGTH );
245 ::set_flag( mnFlags, EXC_NAME_BUILTIN );
249 void XclExpName::SetTokenArray( XclTokenArrayRef xTokArr )
251 mxTokArr = xTokArr;
254 void XclExpName::SetLocalTab( SCTAB nScTab )
256 DBG_ASSERT( GetTabInfo().IsExportTab( nScTab ), "XclExpName::SetLocalTab - invalid sheet index" );
257 if( GetTabInfo().IsExportTab( nScTab ) )
259 mnScTab = nScTab;
260 GetGlobalLinkManager().FindExtSheet( mnExtSheet, mnXclTab, nScTab );
262 // special handling for NAME record
263 switch( GetBiff() )
265 case EXC_BIFF5: // EXTERNSHEET index is positive in NAME record
266 mnExtSheet = ~mnExtSheet + 1;
267 break;
268 case EXC_BIFF8: // EXTERNSHEET index not used, but must be created in link table
269 mnExtSheet = 0;
270 break;
271 default: DBG_ERROR_BIFF();
274 // Excel sheet index is 1-based
275 ++mnXclTab;
279 void XclExpName::SetHidden( bool bHidden )
281 ::set_flag( mnFlags, EXC_NAME_HIDDEN, bHidden );
284 void XclExpName::SetMacroCall( bool bVBasic, bool bFunc )
286 ::set_flag( mnFlags, EXC_NAME_PROC );
287 ::set_flag( mnFlags, EXC_NAME_VB, bVBasic );
288 ::set_flag( mnFlags, EXC_NAME_FUNC, bFunc );
291 void XclExpName::SetSymbol( String sSymbol )
293 msSymbol = sSymbol;
296 bool XclExpName::IsVolatile() const
298 return mxTokArr.is() && mxTokArr->IsVolatile();
301 bool XclExpName::IsHidden() const
303 return ::get_flag( mnFlags, EXC_NAME_HIDDEN );
306 bool XclExpName::IsMacroCall( bool bVBasic, bool bFunc ) const
308 return
309 (::get_flag( mnFlags, EXC_NAME_VB ) == bVBasic) &&
310 (::get_flag( mnFlags, EXC_NAME_FUNC ) == bFunc);
313 void XclExpName::Save( XclExpStream& rStrm )
315 DBG_ASSERT( mxName.is() && (mxName->Len() > 0), "XclExpName::Save - missing name" );
316 DBG_ASSERT( !(IsGlobal() && ::get_flag( mnFlags, EXC_NAME_BUILTIN )), "XclExpName::Save - global built-in name" );
317 SetRecSize( 11 + mxName->GetSize() + (mxTokArr.is() ? mxTokArr->GetSize() : 2) );
318 XclExpRecord::Save( rStrm );
321 void XclExpName::SaveXml( XclExpXmlStream& rStrm )
323 // For some reason, AutoFilter creates exportable names where maOrigName==""
324 if( maOrigName.Len() == 0 )
325 return;
327 sax_fastparser::FSHelperPtr& rWorkbook = rStrm.GetCurrentStream();
328 rWorkbook->startElement( XML_definedName,
329 // OOXTODO: XML_comment, "",
330 // OOXTODO: XML_customMenu, "",
331 // OOXTODO: XML_description, "",
332 XML_function, XclXmlUtils::ToPsz( ::get_flag( mnFlags, EXC_NAME_VB ) ),
333 // OOXTODO: XML_functionGroupId, "",
334 // OOXTODO: XML_help, "",
335 XML_hidden, XclXmlUtils::ToPsz( ::get_flag( mnFlags, EXC_NAME_HIDDEN ) ),
336 XML_localSheetId, mnScTab == SCTAB_GLOBAL ? NULL : OString::valueOf( (sal_Int32)mnScTab ).getStr(),
337 XML_name, XclXmlUtils::ToOString( maOrigName ).getStr(),
338 // OOXTODO: XML_publishToServer, "",
339 // OOXTODO: XML_shortcutKey, "",
340 // OOXTODO: XML_statusBar, "",
341 XML_vbProcedure, XclXmlUtils::ToPsz( ::get_flag( mnFlags, EXC_NAME_VB ) ),
342 // OOXTODO: XML_workbookParameter, "",
343 // OOXTODO: XML_xlm, "",
344 FSEND );
345 rWorkbook->writeEscaped( XclXmlUtils::ToOUString( msSymbol ) );
346 rWorkbook->endElement( XML_definedName );
349 void XclExpName::WriteBody( XclExpStream& rStrm )
351 sal_uInt16 nFmlaSize = mxTokArr.is() ? mxTokArr->GetSize() : 0;
353 rStrm << mnFlags // flags
354 << sal_uInt8( 0 ); // keyboard shortcut
355 mxName->WriteLenField( rStrm ); // length of name
356 rStrm << nFmlaSize // size of token array
357 << mnExtSheet // BIFF5/7: EXTSHEET index, BIFF8: not used
358 << mnXclTab // 1-based sheet index for local names
359 << sal_uInt32( 0 ); // length of menu/descr/help/status text
360 mxName->WriteFlagField( rStrm ); // BIFF8 flag field (no-op in <=BIFF7)
361 mxName->WriteBuffer( rStrm ); // character array of the name
362 if( mxTokArr.is() )
363 mxTokArr->WriteArray( rStrm ); // token array without size
366 // ----------------------------------------------------------------------------
368 XclExpNameManagerImpl::XclExpNameManagerImpl( const XclExpRoot& rRoot ) :
369 XclExpRoot( rRoot ),
370 maUnnamedDBName( ScGlobal::GetRscString( STR_DB_NONAME ) ),
371 mnFirstUserIdx( 0 )
375 void XclExpNameManagerImpl::Initialize()
377 CreateBuiltInNames();
378 mnFirstUserIdx = maNameList.GetSize();
379 CreateUserNames();
380 CreateDatabaseNames();
383 sal_uInt16 XclExpNameManagerImpl::InsertName( USHORT nScNameIdx )
385 sal_uInt16 nNameIdx = FindNameIdx( maNameMap, nScNameIdx );
386 if( nNameIdx == 0 )
387 if( const ScRangeData* pRangeData = GetNamedRanges().FindIndex( nScNameIdx ) )
388 nNameIdx = CreateName( *pRangeData );
389 return nNameIdx;
392 sal_uInt16 XclExpNameManagerImpl::InsertDBRange( USHORT nScDBRangeIdx )
394 sal_uInt16 nNameIdx = FindNameIdx( maDBRangeMap, nScDBRangeIdx );
395 if( nNameIdx == 0 )
396 if( const ScDBData* pDBData = GetDatabaseRanges().FindIndex( nScDBRangeIdx ) )
397 nNameIdx = CreateName( *pDBData );
398 return nNameIdx;
401 sal_uInt16 XclExpNameManagerImpl::InsertBuiltInName( sal_Unicode cBuiltIn, XclTokenArrayRef xTokArr, SCTAB nScTab )
403 XclExpNameRef xName( new XclExpName( GetRoot(), cBuiltIn ) );
404 xName->SetTokenArray( xTokArr );
405 xName->SetLocalTab( nScTab );
406 return Append( xName );
409 sal_uInt16 XclExpNameManagerImpl::InsertUniqueName(
410 const String& rName, XclTokenArrayRef xTokArr, SCTAB nScTab )
412 DBG_ASSERT( rName.Len(), "XclExpNameManagerImpl::InsertUniqueName - empty name" );
413 XclExpNameRef xName( new XclExpName( GetRoot(), GetUnusedName( rName ) ) );
414 xName->SetTokenArray( xTokArr );
415 xName->SetLocalTab( nScTab );
416 return Append( xName );
419 sal_uInt16 XclExpNameManagerImpl::InsertRawName( const String& rName )
421 // empty name? may occur in broken external Calc tokens
422 if( !rName.Len() )
423 return 0;
425 // try to find an existing NAME record, regardless of its type
426 for( size_t nListIdx = mnFirstUserIdx, nListSize = maNameList.GetSize(); nListIdx < nListSize; ++nListIdx )
428 XclExpNameRef xName = maNameList.GetRecord( nListIdx );
429 if( xName->IsGlobal() && (xName->GetOrigName() == rName) )
430 return static_cast< sal_uInt16 >( nListIdx + 1 );
433 // create a new NAME record
434 XclExpNameRef xName( new XclExpName( GetRoot(), rName ) );
435 return Append( xName );
438 sal_uInt16 XclExpNameManagerImpl::InsertMacroCall( const String& rMacroName, bool bVBasic, bool bFunc, bool bHidden )
440 // empty name? may occur in broken external Calc tokens
441 if( !rMacroName.Len() )
442 return 0;
444 // try to find an existing NAME record
445 for( size_t nListIdx = mnFirstUserIdx, nListSize = maNameList.GetSize(); nListIdx < nListSize; ++nListIdx )
447 XclExpNameRef xName = maNameList.GetRecord( nListIdx );
448 if( xName->IsMacroCall( bVBasic, bFunc ) && (xName->GetOrigName() == rMacroName) )
449 return static_cast< sal_uInt16 >( nListIdx + 1 );
452 // create a new NAME record
453 XclExpNameRef xName( new XclExpName( GetRoot(), rMacroName ) );
454 xName->SetMacroCall( bVBasic, bFunc );
455 xName->SetHidden( bHidden );
457 // for sheet macros, add a #NAME! error
458 if( !bVBasic )
459 xName->SetTokenArray( GetFormulaCompiler().CreateErrorFormula( EXC_ERR_NAME ) );
461 return Append( xName );
464 const XclExpName* XclExpNameManagerImpl::GetName( sal_uInt16 nNameIdx ) const
466 DBG_ASSERT( maNameList.HasRecord( nNameIdx - 1 ), "XclExpNameManagerImpl::GetName - wrong record index" );
467 return maNameList.GetRecord( nNameIdx - 1 ).get();
470 void XclExpNameManagerImpl::Save( XclExpStream& rStrm )
472 maNameList.Save( rStrm );
475 void XclExpNameManagerImpl::SaveXml( XclExpXmlStream& rStrm )
477 if( maNameList.IsEmpty() )
478 return;
479 sax_fastparser::FSHelperPtr& rWorkbook = rStrm.GetCurrentStream();
480 rWorkbook->startElement( XML_definedNames, FSEND );
481 maNameList.SaveXml( rStrm );
482 rWorkbook->endElement( XML_definedNames );
485 // private --------------------------------------------------------------------
487 sal_uInt16 XclExpNameManagerImpl::FindNameIdx( const XclExpIndexMap& rMap, USHORT nScIdx ) const
489 XclExpIndexMap::const_iterator aIt = rMap.find( nScIdx );
490 return (aIt == rMap.end()) ? 0 : aIt->second;
493 sal_uInt16 XclExpNameManagerImpl::FindBuiltInNameIdx(
494 const String& rName, const XclTokenArray& rTokArr, bool bDBRange ) const
496 /* Get built-in index from the name. Special case: the database range
497 'unnamed' will be mapped to Excel's built-in '_FilterDatabase' name. */
498 sal_Unicode cBuiltIn = (bDBRange && (rName == maUnnamedDBName)) ?
499 EXC_BUILTIN_FILTERDATABASE : XclTools::GetBuiltInDefNameIndex( rName );
501 if( cBuiltIn < EXC_BUILTIN_UNKNOWN )
503 // try to find the record in existing built-in NAME record list
504 for( size_t nPos = 0; nPos < mnFirstUserIdx; ++nPos )
506 XclExpNameRef xName = maNameList.GetRecord( nPos );
507 if( xName->GetBuiltInName() == cBuiltIn )
509 XclTokenArrayRef xTokArr = xName->GetTokenArray();
510 if( xTokArr.is() && (*xTokArr == rTokArr) )
511 return static_cast< sal_uInt16 >( nPos + 1 );
515 return 0;
518 String XclExpNameManagerImpl::GetUnusedName( const String& rName ) const
520 String aNewName( rName );
521 sal_Int32 nAppIdx = 0;
522 bool bExist = true;
523 while( bExist )
525 // search the list of user-defined names
526 bExist = false;
527 for( size_t nPos = mnFirstUserIdx, nSize = maNameList.GetSize(); !bExist && (nPos < nSize); ++nPos )
529 XclExpNameRef xName = maNameList.GetRecord( nPos );
530 bExist = xName->GetOrigName() == aNewName;
531 // name exists -> create a new name "<originalname>_<counter>"
532 if( bExist )
533 aNewName.Assign( rName ).Append( '_' ).Append( String::CreateFromInt32( ++nAppIdx ) );
536 return aNewName;
539 sal_uInt16 XclExpNameManagerImpl::Append( XclExpNameRef xName )
541 if( maNameList.GetSize() == 0xFFFF )
542 return 0;
543 maNameList.AppendRecord( xName );
544 return static_cast< sal_uInt16 >( maNameList.GetSize() ); // 1-based
547 sal_uInt16 XclExpNameManagerImpl::CreateName( const ScRangeData& rRangeData )
549 const String& rName = rRangeData.GetName();
551 /* #i38821# recursive names: first insert the (empty) name object,
552 otherwise a recursive call of this function from the formula compiler
553 with the same defined name will not find it and will create it again. */
554 size_t nOldListSize = maNameList.GetSize();
555 XclExpNameRef xName( new XclExpName( GetRoot(), rName ) );
556 sal_uInt16 nNameIdx = Append( xName );
557 // store the index of the NAME record in the lookup map
558 maNameMap[ rRangeData.GetIndex() ] = nNameIdx;
560 /* Create the definition formula.
561 This may cause recursive creation of other defined names. */
562 if( const ScTokenArray* pScTokArr = const_cast< ScRangeData& >( rRangeData ).GetCode() )
564 XclTokenArrayRef xTokArr = GetFormulaCompiler().CreateFormula( EXC_FMLATYPE_NAME, *pScTokArr );
565 xName->SetTokenArray( xTokArr );
567 String sSymbol;
568 rRangeData.GetSymbol( sSymbol, formula::FormulaGrammar::GRAM_NATIVE_XL_A1 );
569 xName->SetSymbol( sSymbol );
571 /* Try to replace by existing built-in name - complete token array is
572 needed for comparison, and due to the recursion problem above this
573 cannot be done earlier. If a built-in name is found, the created NAME
574 record for this name and all following records in the list must be
575 deleted, otherwise they may contain wrong name list indexes. */
576 sal_uInt16 nBuiltInIdx = FindBuiltInNameIdx( rName, *xTokArr, false );
577 if( nBuiltInIdx != 0 )
579 // delete the new NAME records
580 while( maNameList.GetSize() > nOldListSize )
581 maNameList.RemoveRecord( maNameList.GetSize() - 1 );
582 // use index of the found built-in NAME record
583 maNameMap[ rRangeData.GetIndex() ] = nNameIdx = nBuiltInIdx;
587 return nNameIdx;
590 sal_uInt16 XclExpNameManagerImpl::CreateName( const ScDBData& rDBData )
592 // get name and source range, and create the definition formula
593 const String& rName = rDBData.GetName();
594 ScRange aRange;
595 rDBData.GetArea( aRange );
596 XclTokenArrayRef xTokArr = GetFormulaCompiler().CreateFormula( EXC_FMLATYPE_NAME, aRange );
598 // try to use an existing built-in name
599 sal_uInt16 nNameIdx = FindBuiltInNameIdx( rName, *xTokArr, true );
600 if( nNameIdx == 0 )
602 // insert a new name into the list
603 XclExpNameRef xName( new XclExpName( GetRoot(), GetUnusedName( rName ) ) );
604 xName->SetTokenArray( xTokArr );
605 nNameIdx = Append( xName );
608 // store the index of the NAME record in the lookup map
609 maDBRangeMap[ rDBData.GetIndex() ] = nNameIdx;
610 return nNameIdx;
613 void XclExpNameManagerImpl::CreateBuiltInNames()
615 ScDocument& rDoc = GetDoc();
616 XclExpTabInfo& rTabInfo = GetTabInfo();
618 /* #i2394# #100489# built-in defined names must be sorted by the name of the
619 containing sheet. Example: SheetA!Print_Range must be stored *before*
620 SheetB!Print_Range, regardless of the position of SheetA in the document! */
621 for( SCTAB nScTabIdx = 0, nScTabCount = rTabInfo.GetScTabCount(); nScTabIdx < nScTabCount; ++nScTabIdx )
623 // find real sheet index from the nScTabIdx counter
624 SCTAB nScTab = rTabInfo.GetRealScTab( nScTabIdx );
625 // create NAME records for all built-in names of this sheet
626 if( rTabInfo.IsExportTab( nScTab ) )
628 // *** 1) print ranges *** ----------------------------------------
630 if( rDoc.HasPrintRange() )
632 ScRangeList aRangeList;
633 for( USHORT nIdx = 0, nCount = rDoc.GetPrintRangeCount( nScTab ); nIdx < nCount; ++nIdx )
635 ScRange aRange( *rDoc.GetPrintRange( nScTab, nIdx ) );
636 // Calc document does not care about sheet index in print ranges
637 aRange.aStart.SetTab( nScTab );
638 aRange.aEnd.SetTab( nScTab );
639 aRangeList.Append( aRange );
641 GetAddressConverter().ValidateRangeList( aRangeList, true );
642 GetNameManager().InsertBuiltInName( EXC_BUILTIN_PRINTAREA, aRangeList );
645 // *** 2) print titles *** ----------------------------------------
647 ScRangeList aTitleList;
648 // repeated columns
649 if( const ScRange* pColRange = rDoc.GetRepeatColRange( nScTab ) )
650 aTitleList.Append( ScRange(
651 pColRange->aStart.Col(), 0, nScTab,
652 pColRange->aEnd.Col(), GetXclMaxPos().Row(), nScTab ) );
653 // repeated rows
654 if( const ScRange* pRowRange = rDoc.GetRepeatRowRange( nScTab ) )
655 aTitleList.Append( ScRange(
656 0, pRowRange->aStart.Row(), nScTab,
657 GetXclMaxPos().Col(), pRowRange->aEnd.Row(), nScTab ) );
658 // create the NAME record
659 GetAddressConverter().ValidateRangeList( aTitleList, true );
660 GetNameManager().InsertBuiltInName( EXC_BUILTIN_PRINTTITLES, aTitleList );
662 // *** 3) filter ranges *** ---------------------------------------
664 if( GetBiff() == EXC_BIFF8 )
665 GetFilterManager().InitTabFilter( nScTab );
670 void XclExpNameManagerImpl::CreateUserNames()
672 const ScRangeName& rNamedRanges = GetNamedRanges();
673 for( USHORT nNameIdx = 0, nNameCount = rNamedRanges.GetCount(); nNameIdx < nNameCount; ++nNameIdx )
675 const ScRangeData* pRangeData = rNamedRanges[ nNameIdx ];
676 DBG_ASSERT( rNamedRanges[ nNameIdx ], "XclExpNameManagerImpl::CreateUserNames - missing defined name" );
677 // skip definitions of shared formulas
678 if( pRangeData && !pRangeData->HasType( RT_SHARED ) && !FindNameIdx( maNameMap, pRangeData->GetIndex() ) )
679 CreateName( *pRangeData );
683 void XclExpNameManagerImpl::CreateDatabaseNames()
685 const ScDBCollection& rDBRanges = GetDatabaseRanges();
686 for( USHORT nDBIdx = 0, nDBCount = rDBRanges.GetCount(); nDBIdx < nDBCount; ++nDBIdx )
688 const ScDBData* pDBData = rDBRanges[ nDBIdx ];
689 DBG_ASSERT( pDBData, "XclExpNameManagerImpl::CreateDatabaseNames - missing database range" );
690 // skip hidden "unnamed" range
691 if( pDBData && (pDBData->GetName() != maUnnamedDBName) && !FindNameIdx( maDBRangeMap, pDBData->GetIndex() ) )
692 CreateName( *pDBData );
696 // ----------------------------------------------------------------------------
698 XclExpNameManager::XclExpNameManager( const XclExpRoot& rRoot ) :
699 XclExpRoot( rRoot ),
700 mxImpl( new XclExpNameManagerImpl( rRoot ) )
704 XclExpNameManager::~XclExpNameManager()
708 void XclExpNameManager::Initialize()
710 mxImpl->Initialize();
713 sal_uInt16 XclExpNameManager::InsertName( USHORT nScNameIdx )
715 return mxImpl->InsertName( nScNameIdx );
718 sal_uInt16 XclExpNameManager::InsertDBRange( USHORT nScDBRangeIdx )
720 return mxImpl->InsertDBRange( nScDBRangeIdx );
723 //UNUSED2009-05 sal_uInt16 XclExpNameManager::InsertBuiltInName( sal_Unicode cBuiltIn, XclTokenArrayRef xTokArr, SCTAB nScTab )
724 //UNUSED2009-05 {
725 //UNUSED2009-05 return mxImpl->InsertBuiltInName( cBuiltIn, xTokArr, nScTab );
726 //UNUSED2009-05 }
728 sal_uInt16 XclExpNameManager::InsertBuiltInName( sal_Unicode cBuiltIn, const ScRange& rRange )
730 XclTokenArrayRef xTokArr = GetFormulaCompiler().CreateFormula( EXC_FMLATYPE_NAME, rRange );
731 return mxImpl->InsertBuiltInName( cBuiltIn, xTokArr, rRange.aStart.Tab() );
734 sal_uInt16 XclExpNameManager::InsertBuiltInName( sal_Unicode cBuiltIn, const ScRangeList& rRangeList )
736 sal_uInt16 nNameIdx = 0;
737 if( rRangeList.Count() )
739 XclTokenArrayRef xTokArr = GetFormulaCompiler().CreateFormula( EXC_FMLATYPE_NAME, rRangeList );
740 nNameIdx = mxImpl->InsertBuiltInName( cBuiltIn, xTokArr, rRangeList.GetObject( 0 )->aStart.Tab() );
742 return nNameIdx;
745 sal_uInt16 XclExpNameManager::InsertUniqueName(
746 const String& rName, XclTokenArrayRef xTokArr, SCTAB nScTab )
748 return mxImpl->InsertUniqueName( rName, xTokArr, nScTab );
751 sal_uInt16 XclExpNameManager::InsertRawName( const String& rName )
753 return mxImpl->InsertRawName( rName );
756 sal_uInt16 XclExpNameManager::InsertMacroCall( const String& rMacroName, bool bVBasic, bool bFunc, bool bHidden )
758 return mxImpl->InsertMacroCall( rMacroName, bVBasic, bFunc, bHidden );
761 const String& XclExpNameManager::GetOrigName( sal_uInt16 nNameIdx ) const
763 const XclExpName* pName = mxImpl->GetName( nNameIdx );
764 return pName ? pName->GetOrigName() : EMPTY_STRING;
767 SCTAB XclExpNameManager::GetScTab( sal_uInt16 nNameIdx ) const
769 const XclExpName* pName = mxImpl->GetName( nNameIdx );
770 return pName ? pName->GetScTab() : SCTAB_GLOBAL;
773 bool XclExpNameManager::IsVolatile( sal_uInt16 nNameIdx ) const
775 const XclExpName* pName = mxImpl->GetName( nNameIdx );
776 return pName && pName->IsVolatile();
779 void XclExpNameManager::Save( XclExpStream& rStrm )
781 mxImpl->Save( rStrm );
784 void XclExpNameManager::SaveXml( XclExpXmlStream& rStrm )
786 mxImpl->SaveXml( rStrm );
789 // ============================================================================