1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 .
24 #include "globstr.hrc"
25 #include "document.hxx"
26 #include "rangenam.hxx"
28 #include "xehelper.hxx"
30 #include "globalnames.hxx"
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
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
);
97 /** Writes the body of the NAME record to the passed stream. */
98 virtual void WriteBody( XclExpStream
& rStrm
);
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 // ----------------------------------------------------------------------------
117 /** Implementation class of the name manager. */
118 class XclExpNameManagerImpl
: protected XclExpRoot
121 explicit XclExpNameManagerImpl( const XclExpRoot
& rRoot
);
123 /** Creates NAME records for built-in and user defined names. */
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
);
153 typedef XclExpRecordList
< XclExpName
> XclExpNameList
;
154 typedef XclExpNameList::RecordRefType XclExpNameRef
;
156 typedef ::std::map
< ::std::pair
<SCTAB
, sal_uInt16
>, sal_uInt16
> NamedExpIndexMap
;
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();
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
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
),
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
),
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
)
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
);
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
)
249 void XclExpName::SetLocalTab( SCTAB nScTab
)
251 OSL_ENSURE( GetTabInfo().IsExportTab( nScTab
), "XclExpName::SetLocalTab - invalid sheet index" );
252 if( GetTabInfo().IsExportTab( nScTab
) )
255 GetGlobalLinkManager().FindExtSheet( mnExtSheet
, mnXclTab
, nScTab
);
257 // special handling for NAME record
260 case EXC_BIFF5
: // EXTERNSHEET index is positive in NAME record
261 mnExtSheet
= ~mnExtSheet
+ 1;
263 case EXC_BIFF8
: // EXTERNSHEET index not used, but must be created in link table
266 default: DBG_ERROR_BIFF();
269 // Excel sheet index is 1-based
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
)
291 bool XclExpName::IsVolatile() const
293 return mxTokArr
&& mxTokArr
->IsVolatile();
296 bool XclExpName::IsMacroCall( bool bVBasic
, bool bFunc
) const
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, "",
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
349 mxTokArr
->WriteArray( rStrm
); // token array without size
352 // ----------------------------------------------------------------------------
354 XclExpNameManagerImpl::XclExpNameManagerImpl( const XclExpRoot
& rRoot
) :
360 void XclExpNameManagerImpl::Initialize()
362 CreateBuiltInNames();
363 mnFirstUserIdx
= maNameList
.GetSize();
367 sal_uInt16
XclExpNameManagerImpl::InsertName( SCTAB nTab
, sal_uInt16 nScNameIdx
)
369 sal_uInt16 nNameIdx
= FindNamedExpIndex( nTab
, nScNameIdx
);
373 const ScRangeData
* pData
= NULL
;
374 ScRangeName
* pRN
= (nTab
== SCTAB_GLOBAL
) ? GetDoc().GetRangeName() : GetDoc().GetRangeName(nTab
);
376 pData
= pRN
->findByIndex(nScNameIdx
);
379 nNameIdx
= CreateName(nTab
, *pData
);
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() );
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
);
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
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() )
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
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() )
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 );
516 String
XclExpNameManagerImpl::GetUnusedName( const String
& rName
) const
518 String
aNewName( rName
);
519 sal_Int32 nAppIdx
= 0;
523 // search the list of user-defined names
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>"
531 aNewName
.Assign( rName
).Append( '_' ).Append( OUString::number( ++nAppIdx
) );
537 sal_uInt16
XclExpNameManagerImpl::Append( XclExpNameRef xName
)
539 if( maNameList
.GetSize() == 0xFFFF )
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
);
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
;
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
);
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
;
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
) );
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
) :
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
);
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: */