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 $
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"
37 #include "globstr.hrc"
38 #include "document.hxx"
39 #include "rangenam.hxx"
40 #include "dbcolect.hxx"
41 #include "xehelper.hxx"
45 #include "excrecds.hxx"
47 #include <oox/core/tokens.hxx>
48 #include <formula/grammar.hxx>
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
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
);
111 /** Writes the body of the NAME record to the passed stream. */
112 virtual void WriteBody( XclExpStream
& rStrm
);
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 // ----------------------------------------------------------------------------
131 /** Implementation class of the name manager. */
132 class XclExpNameManagerImpl
: protected XclExpRoot
135 explicit XclExpNameManagerImpl( const XclExpRoot
& rRoot
);
137 /** Creates NAME records for built-in and user defined names. */
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
);
168 typedef XclExpRecordList
< XclExpName
> XclExpNameList
;
169 typedef XclExpNameList::RecordRefType XclExpNameRef
;
170 typedef ::std::map
< USHORT
, sal_uInt16
> XclExpIndexMap
;
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();
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
),
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
),
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
)
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
);
244 mxName
= XclExpStringHelper::CreateString( rRoot
, cBuiltIn
, EXC_STR_8BITLENGTH
);
245 ::set_flag( mnFlags
, EXC_NAME_BUILTIN
);
249 void XclExpName::SetTokenArray( XclTokenArrayRef xTokArr
)
254 void XclExpName::SetLocalTab( SCTAB nScTab
)
256 DBG_ASSERT( GetTabInfo().IsExportTab( nScTab
), "XclExpName::SetLocalTab - invalid sheet index" );
257 if( GetTabInfo().IsExportTab( nScTab
) )
260 GetGlobalLinkManager().FindExtSheet( mnExtSheet
, mnXclTab
, nScTab
);
262 // special handling for NAME record
265 case EXC_BIFF5
: // EXTERNSHEET index is positive in NAME record
266 mnExtSheet
= ~mnExtSheet
+ 1;
268 case EXC_BIFF8
: // EXTERNSHEET index not used, but must be created in link table
271 default: DBG_ERROR_BIFF();
274 // Excel sheet index is 1-based
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
)
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
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 )
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, "",
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
363 mxTokArr
->WriteArray( rStrm
); // token array without size
366 // ----------------------------------------------------------------------------
368 XclExpNameManagerImpl::XclExpNameManagerImpl( const XclExpRoot
& rRoot
) :
370 maUnnamedDBName( ScGlobal::GetRscString( STR_DB_NONAME
) ),
375 void XclExpNameManagerImpl::Initialize()
377 CreateBuiltInNames();
378 mnFirstUserIdx
= maNameList
.GetSize();
380 CreateDatabaseNames();
383 sal_uInt16
XclExpNameManagerImpl::InsertName( USHORT nScNameIdx
)
385 sal_uInt16 nNameIdx
= FindNameIdx( maNameMap
, nScNameIdx
);
387 if( const ScRangeData
* pRangeData
= GetNamedRanges().FindIndex( nScNameIdx
) )
388 nNameIdx
= CreateName( *pRangeData
);
392 sal_uInt16
XclExpNameManagerImpl::InsertDBRange( USHORT nScDBRangeIdx
)
394 sal_uInt16 nNameIdx
= FindNameIdx( maDBRangeMap
, nScDBRangeIdx
);
396 if( const ScDBData
* pDBData
= GetDatabaseRanges().FindIndex( nScDBRangeIdx
) )
397 nNameIdx
= CreateName( *pDBData
);
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
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() )
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
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() )
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 );
518 String
XclExpNameManagerImpl::GetUnusedName( const String
& rName
) const
520 String
aNewName( rName
);
521 sal_Int32 nAppIdx
= 0;
525 // search the list of user-defined names
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>"
533 aNewName
.Assign( rName
).Append( '_' ).Append( String::CreateFromInt32( ++nAppIdx
) );
539 sal_uInt16
XclExpNameManagerImpl::Append( XclExpNameRef xName
)
541 if( maNameList
.GetSize() == 0xFFFF )
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
);
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
;
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();
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 );
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
;
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
;
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
) );
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
) :
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 )
725 //UNUSED2009-05 return mxImpl->InsertBuiltInName( cBuiltIn, xTokArr, nScTab );
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() );
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 // ============================================================================