LibreOffice Module sc (master) 1
xename.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
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 .
18 */
19
20#include <xename.hxx>
21
22#include <map>
23
24#include <document.hxx>
25#include <rangenam.hxx>
26#include <tokenarray.hxx>
27#include <xehelper.hxx>
28#include <xelink.hxx>
29#include <excrecds.hxx>
30#include <xlname.hxx>
31#include <xeformula.hxx>
32#include <xestring.hxx>
33#include <xltools.hxx>
34
35#include <formula/grammar.hxx>
36#include <oox/export/utils.hxx>
37#include <oox/token/tokens.hxx>
38
39using namespace ::oox;
40
41// *** Helper classes ***
42
43namespace {
44
46class XclExpName : public XclExpRecord, protected XclExpRoot
47{
48public:
50 explicit XclExpName( const XclExpRoot& rRoot, const OUString& rName );
52 explicit XclExpName( const XclExpRoot& rRoot, sal_Unicode cBuiltIn );
53
55 void SetTokenArray( const XclTokenArrayRef& xTokArr );
57 void SetLocalTab( SCTAB nScTab );
59 void SetHidden( bool bHidden = true );
63 void SetMacroCall( bool bVBasic, bool bFunc );
64
67 void SetSymbol( const OUString& rValue );
68
70 const OUString& GetOrigName() const { return maOrigName; }
73 sal_Unicode GetBuiltInName() const { return mcBuiltIn; }
74
76 const OUString& GetSymbol() const { return msSymbol; }
77
79 bool IsGlobal() const { return mnXclTab == EXC_NAME_GLOBAL; }
81 SCTAB GetScTab() const { return mnScTab; }
82
84 bool IsVolatile() const;
87 bool IsMacroCall( bool bVBasic, bool bFunc ) const;
88
90 virtual void Save( XclExpStream& rStrm ) override;
91
92 virtual void SaveXml( XclExpXmlStream& rStrm ) override;
93
94private:
96 virtual void WriteBody( XclExpStream& rStrm ) override;
98 OUString GetWithDefaultRangeSeparator( const OUString& rSymbol ) const;
99
100private:
101 OUString maOrigName;
102 OUString msSymbol;
103 XclExpStringRef mxName;
104 XclTokenArrayRef mxTokArr;
105 sal_Unicode mcBuiltIn;
106 SCTAB mnScTab;
107 sal_uInt16 mnFlags;
108 sal_uInt16 mnExtSheet;
109 sal_uInt16 mnXclTab;
110};
111
112}
113
116{
117public:
118 explicit XclExpNameManagerImpl( const XclExpRoot& rRoot );
119
121 void Initialize();
122
124 sal_uInt16 InsertName( SCTAB nTab, sal_uInt16 nScNameIdx, SCTAB nCurrTab );
125
127 sal_uInt16 InsertBuiltInName( sal_Unicode cBuiltIn, const XclTokenArrayRef& xTokArr, SCTAB nScTab, const ScRangeList& aRangeList );
128 sal_uInt16 InsertBuiltInName( sal_Unicode cBuiltIn, const XclTokenArrayRef& xTokArr, const ScRange& aRange );
130 sal_uInt16 InsertUniqueName( const OUString& rName, const XclTokenArrayRef& xTokArr, SCTAB nScTab );
132 sal_uInt16 InsertRawName( const OUString& rName );
136 sal_uInt16 InsertMacroCall( const OUString& rMacroName, bool bVBasic, bool bFunc, bool bHidden );
137
139 const XclExpName* GetName( sal_uInt16 nNameIdx ) const;
140
145 void Save( XclExpStream& rStrm );
146
148
149private:
152
153 typedef ::std::map< ::std::pair<SCTAB, OUString>, sal_uInt16> NamedExpMap;
154
155private:
162 sal_uInt16 FindNamedExp( SCTAB nTab, OUString sName );
163
165 sal_uInt16 FindBuiltInNameIdx( const OUString& rName,
166 const OUString& sSymbol ) const;
168 OUString GetUnusedName( const OUString& rName ) const;
169
172 sal_uInt16 Append( XclExpName* pName );
173 sal_uInt16 Append( XclExpNameRef const & rxName ) { return Append(rxName.get()); }
176 sal_uInt16 CreateName( SCTAB nTab, const ScRangeData& rRangeData );
177
179 void CreateBuiltInNames();
181 void CreateUserNames();
182
183private:
192};
193
194// *** Implementation ***
195
196XclExpName::XclExpName( const XclExpRoot& rRoot, const OUString& rName ) :
198 XclExpRoot( rRoot ),
199 maOrigName( rName ),
200 mxName( XclExpStringHelper::CreateString( rRoot, rName, XclStrFlags::EightBitLength ) ),
201 mcBuiltIn( EXC_BUILTIN_UNKNOWN ),
202 mnScTab( SCTAB_GLOBAL ),
204 mnExtSheet( EXC_NAME_GLOBAL ),
205 mnXclTab( EXC_NAME_GLOBAL )
206{
207}
208
209XclExpName::XclExpName( const XclExpRoot& rRoot, sal_Unicode cBuiltIn ) :
211 XclExpRoot( rRoot ),
212 mcBuiltIn( cBuiltIn ),
213 mnScTab( SCTAB_GLOBAL ),
215 mnExtSheet( EXC_NAME_GLOBAL ),
216 mnXclTab( EXC_NAME_GLOBAL )
217{
218 // filter source range is hidden in Excel
219 if( cBuiltIn == EXC_BUILTIN_FILTERDATABASE )
220 SetHidden();
221
222 // special case for BIFF5/7 filter source range - name appears as plain text without built-in flag
223 if( (GetBiff() <= EXC_BIFF5) && (cBuiltIn == EXC_BUILTIN_FILTERDATABASE) )
224 {
227 maOrigName = XclTools::GetXclBuiltInDefName( cBuiltIn );
228 }
229 else
230 {
231 maOrigName = XclTools::GetBuiltInDefNameXml( cBuiltIn ) ;
234 }
235}
236
237void XclExpName::SetTokenArray( const XclTokenArrayRef& xTokArr )
238{
239 mxTokArr = xTokArr;
240}
241
242void XclExpName::SetLocalTab( SCTAB nScTab )
243{
244 OSL_ENSURE( GetTabInfo().IsExportTab( nScTab ), "XclExpName::SetLocalTab - invalid sheet index" );
245 if( !GetTabInfo().IsExportTab( nScTab ) )
246 return;
247
248 mnScTab = nScTab;
249 GetGlobalLinkManager().FindExtSheet( mnExtSheet, mnXclTab, nScTab );
250
251 // special handling for NAME record
252 switch( GetBiff() )
253 {
254 case EXC_BIFF5: // EXTERNSHEET index is positive in NAME record
255 mnExtSheet = ~mnExtSheet + 1;
256 break;
257 case EXC_BIFF8: // EXTERNSHEET index not used, but must be created in link table
258 mnExtSheet = 0;
259 break;
260 default: DBG_ERROR_BIFF();
261 }
262
263 // Excel sheet index is 1-based
264 ++mnXclTab;
265}
266
267void XclExpName::SetHidden( bool bHidden )
268{
270}
271
272void XclExpName::SetMacroCall( bool bVBasic, bool bFunc )
273{
275 ::set_flag( mnFlags, EXC_NAME_VB, bVBasic );
277}
278
279void XclExpName::SetSymbol( const OUString& rSymbol )
280{
281 msSymbol = rSymbol;
282}
283
284bool XclExpName::IsVolatile() const
285{
286 return mxTokArr && mxTokArr->IsVolatile();
287}
288
289bool XclExpName::IsMacroCall( bool bVBasic, bool bFunc ) const
290{
291 return
292 (::get_flag( mnFlags, EXC_NAME_VB ) == bVBasic) &&
293 (::get_flag( mnFlags, EXC_NAME_FUNC ) == bFunc);
294}
295
296void XclExpName::Save( XclExpStream& rStrm )
297{
298 OSL_ENSURE( mxName && (mxName->Len() > 0), "XclExpName::Save - missing name" );
299 OSL_ENSURE( !(IsGlobal() && ::get_flag( mnFlags, EXC_NAME_BUILTIN )), "XclExpName::Save - global built-in name" );
300 SetRecSize( 11 + mxName->GetSize() + (mxTokArr ? mxTokArr->GetSize() : 2) );
301 XclExpRecord::Save( rStrm );
302}
303
304OUString XclExpName::GetWithDefaultRangeSeparator( const OUString& rSymbol ) const
305{
306 sal_Int32 nPos = rSymbol.indexOf(';');
307 if ( nPos > -1 )
308 {
309 // convert with validation
310 ScRange aRange;
312 ScRefFlags nRes = aRange.Parse( rSymbol.copy(0, nPos), GetDoc(), detailsXL );
313 if ( nRes & ScRefFlags::VALID )
314 {
315 nRes = aRange.Parse( rSymbol.copy(nPos+1), GetDoc(), detailsXL );
316 if ( nRes & ScRefFlags::VALID )
317 {
318 return rSymbol.replaceFirst(";", ",");
319 }
320 }
321 }
322 return rSymbol;
323}
324
325void XclExpName::SaveXml( XclExpXmlStream& rStrm )
326{
327 // tdf#100034: Don't save print range if the built-in index is unknown
328 // and sheet index is valid (this is a deleted range)
329 if (mcBuiltIn == EXC_BUILTIN_UNKNOWN && mnScTab != SCTAB_GLOBAL)
330 return;
331
332 sax_fastparser::FSHelperPtr& rWorkbook = rStrm.GetCurrentStream();
333 rWorkbook->startElement( XML_definedName,
334 // OOXTODO: XML_comment, "",
335 // OOXTODO: XML_customMenu, "",
336 // OOXTODO: XML_description, "",
337 XML_function, ToPsz( ::get_flag( mnFlags, EXC_NAME_VB ) ),
338 // OOXTODO: XML_functionGroupId, "",
339 // OOXTODO: XML_help, "",
340 XML_hidden, ToPsz( ::get_flag( mnFlags, EXC_NAME_HIDDEN ) ),
341 XML_localSheetId, sax_fastparser::UseIf(OString::number( mnScTab ), mnScTab != SCTAB_GLOBAL),
342 XML_name, maOrigName.toUtf8(),
343 // OOXTODO: XML_publishToServer, "",
344 // OOXTODO: XML_shortcutKey, "",
345 // OOXTODO: XML_statusBar, "",
346 XML_vbProcedure, ToPsz( ::get_flag( mnFlags, EXC_NAME_VB ) )
347 // OOXTODO: XML_workbookParameter, "",
348 // OOXTODO: XML_xlm, ""
349 );
350 rWorkbook->writeEscaped( GetWithDefaultRangeSeparator( msSymbol ) );
351 rWorkbook->endElement( XML_definedName );
352}
353
354void XclExpName::WriteBody( XclExpStream& rStrm )
355{
356 sal_uInt16 nFmlaSize = mxTokArr ? mxTokArr->GetSize() : 0;
357
358 rStrm << mnFlags // flags
359 << sal_uInt8( 0 ); // keyboard shortcut
360 mxName->WriteLenField( rStrm ); // length of name
361 rStrm << nFmlaSize // size of token array
362 << mnExtSheet // BIFF5/7: EXTSHEET index, BIFF8: not used
363 << mnXclTab // 1-based sheet index for local names
364 << sal_uInt32( 0 ); // length of menu/descr/help/status text
365 mxName->WriteFlagField( rStrm ); // BIFF8 flag field (no-op in <=BIFF7)
366 mxName->WriteBuffer( rStrm ); // character array of the name
367 if( mxTokArr )
368 mxTokArr->WriteArray( rStrm ); // token array without size
369}
370
373static bool lcl_EnsureAbs3DToken( const SCTAB nTab, formula::FormulaToken* pTok, const bool bFix = true )
374{
375 bool bFixRequired = false;
376 if ( !pTok || ( pTok->GetType() != formula::svSingleRef && pTok->GetType() != formula::svDoubleRef ) )
377 return bFixRequired;
378
379 ScSingleRefData* pRef1 = pTok->GetSingleRef();
380 if ( !pRef1 )
381 return bFixRequired;
382
383 ScSingleRefData* pRef2 = nullptr;
384 if ( pTok->GetType() == formula::svDoubleRef )
385 pRef2 = pTok->GetSingleRef2();
386
387 if ( pRef1->IsTabRel() || !pRef1->IsFlag3D() )
388 {
389 bFixRequired = true;
390 if ( bFix )
391 {
392 if ( pRef1->IsTabRel() && nTab != SCTAB_GLOBAL )
393 pRef1->SetAbsTab( nTab + pRef1->Tab() ); //XLS requirement
394 if ( !pRef1->IsTabRel() )
395 {
396 pRef1->SetFlag3D( true ); //XLSX requirement
397 if ( pRef2 && !pRef2->IsTabRel() )
398 pRef2->SetFlag3D( pRef2->Tab() != pRef1->Tab() );
399 }
400 }
401 }
402
403 if ( pRef2 && pRef2->IsTabRel() && !pRef1->IsTabRel() )
404 {
405 bFixRequired = true;
406 if ( bFix && nTab != SCTAB_GLOBAL )
407 {
408 pRef2->SetAbsTab( nTab + pRef2->Tab() );
409 pRef2->SetFlag3D( pRef2->Tab() != pRef1->Tab() );
410 }
411 }
412 return bFixRequired;
413}
414
416 XclExpRoot( rRoot ),
417 mnFirstUserIdx( 0 )
418{
419}
420
422{
426}
427
428sal_uInt16 XclExpNameManagerImpl::InsertName( SCTAB nTab, sal_uInt16 nScNameIdx, SCTAB nCurrTab )
429{
430 sal_uInt16 nNameIdx = 0;
431 const ScRangeData* pData = nullptr;
432 ScRangeName* pRN = (nTab == SCTAB_GLOBAL) ? GetDoc().GetRangeName() : GetDoc().GetRangeName(nTab);
433 if (pRN)
434 pData = pRN->findByIndex(nScNameIdx);
435
436 if (pData)
437 {
438 bool bEmulateGlobalRelativeTable = false;
439 const ScTokenArray* pCode = pData->GetCode();
440 if ( pCode
441 && nTab == SCTAB_GLOBAL
442 && (pData->HasType( ScRangeData::Type::AbsPos ) || pData->HasType( ScRangeData::Type::AbsArea )) )
443 {
444 bEmulateGlobalRelativeTable = lcl_EnsureAbs3DToken( nTab, pCode->FirstToken(), /*bFix=*/false );
445 }
446 nNameIdx = FindNamedExp( bEmulateGlobalRelativeTable ? nCurrTab : nTab, pData->GetName() );
447 if (!nNameIdx)
448 nNameIdx = CreateName(nTab, *pData);
449 }
450
451 return nNameIdx;
452}
453
454sal_uInt16 XclExpNameManagerImpl::InsertBuiltInName( sal_Unicode cBuiltIn, const XclTokenArrayRef& xTokArr, const ScRange& aRange )
455{
456 XclExpNameRef xName = new XclExpName( GetRoot(), cBuiltIn );
457 xName->SetTokenArray( xTokArr );
458 xName->SetLocalTab( aRange.aStart.Tab() );
460 xName->SetSymbol( sSymbol );
461 return Append( xName );
462}
463
464sal_uInt16 XclExpNameManagerImpl::InsertBuiltInName( sal_Unicode cBuiltIn, const XclTokenArrayRef& xTokArr, SCTAB nScTab, const ScRangeList& rRangeList )
465{
466 XclExpNameRef xName = new XclExpName( GetRoot(), cBuiltIn );
467 xName->SetTokenArray( xTokArr );
468 xName->SetLocalTab( nScTab );
469 OUString sSymbol;
471 xName->SetSymbol( sSymbol );
472 return Append( xName );
473}
474
476 const OUString& rName, const XclTokenArrayRef& xTokArr, SCTAB nScTab )
477{
478 OSL_ENSURE( !rName.isEmpty(), "XclExpNameManagerImpl::InsertUniqueName - empty name" );
479 XclExpNameRef xName = new XclExpName( GetRoot(), GetUnusedName( rName ) );
480 xName->SetTokenArray( xTokArr );
481 xName->SetLocalTab( nScTab );
482 return Append( xName );
483}
484
485sal_uInt16 XclExpNameManagerImpl::InsertRawName( const OUString& rName )
486{
487 // empty name? may occur in broken external Calc tokens
488 if( rName.isEmpty() )
489 return 0;
490
491 // try to find an existing NAME record, regardless of its type
492 for( size_t nListIdx = mnFirstUserIdx, nListSize = maNameList.GetSize(); nListIdx < nListSize; ++nListIdx )
493 {
494 XclExpNameRef xName = maNameList.GetRecord( nListIdx );
495 if( xName->IsGlobal() && (xName->GetOrigName() == rName) )
496 return static_cast< sal_uInt16 >( nListIdx + 1 );
497 }
498
499 // create a new NAME record
500 XclExpNameRef xName = new XclExpName( GetRoot(), rName );
501 return Append( xName );
502}
503
504sal_uInt16 XclExpNameManagerImpl::InsertMacroCall( const OUString& rMacroName, bool bVBasic, bool bFunc, bool bHidden )
505{
506 // empty name? may occur in broken external Calc tokens
507 if( rMacroName.isEmpty() )
508 return 0;
509
510 // try to find an existing NAME record
511 for( size_t nListIdx = mnFirstUserIdx, nListSize = maNameList.GetSize(); nListIdx < nListSize; ++nListIdx )
512 {
513 XclExpNameRef xName = maNameList.GetRecord( nListIdx );
514 if( xName->IsMacroCall( bVBasic, bFunc ) && (xName->GetOrigName() == rMacroName) )
515 return static_cast< sal_uInt16 >( nListIdx + 1 );
516 }
517
518 // create a new NAME record
519 XclExpNameRef xName = new XclExpName( GetRoot(), rMacroName );
520 xName->SetMacroCall( bVBasic, bFunc );
521 xName->SetHidden( bHidden );
522
523 // for sheet macros, add a #NAME! error
524 if( !bVBasic )
525 xName->SetTokenArray( GetFormulaCompiler().CreateErrorFormula( EXC_ERR_NAME ) );
526
527 return Append( xName );
528}
529
530const XclExpName* XclExpNameManagerImpl::GetName( sal_uInt16 nNameIdx ) const
531{
532 OSL_ENSURE( maNameList.HasRecord( nNameIdx - 1 ), "XclExpNameManagerImpl::GetName - wrong record index" );
533 return maNameList.GetRecord( nNameIdx - 1 );
534}
535
537{
539}
540
542{
543 if( maNameList.IsEmpty() )
544 return;
545 sax_fastparser::FSHelperPtr& rWorkbook = rStrm.GetCurrentStream();
546 rWorkbook->startElement(XML_definedNames);
548 rWorkbook->endElement( XML_definedNames );
549}
550
551// private --------------------------------------------------------------------
552
553sal_uInt16 XclExpNameManagerImpl::FindNamedExp( SCTAB nTab, OUString sName )
554{
555 NamedExpMap::key_type key(nTab, sName);
556 NamedExpMap::const_iterator itr = maNamedExpMap.find(key);
557 return (itr == maNamedExpMap.end()) ? 0 : itr->second;
558}
559
561 const OUString& rName, const OUString& sSymbol ) const
562{
563 /* Get built-in index from the name. Special case: the database range
564 'unnamed' will be mapped to Excel's built-in '_FilterDatabase' name. */
566
567 if( cBuiltIn < EXC_BUILTIN_UNKNOWN )
568 {
569 // try to find the record in existing built-in NAME record list
570 for( size_t nPos = 0; nPos < mnFirstUserIdx; ++nPos )
571 {
573 if( xName->GetBuiltInName() == cBuiltIn && xName->GetSymbol().replace(';', ',') == sSymbol.replace(';', ',') )
574 {
575 // tdf#112567 restore the original built-in names with non-localized separators
576 // TODO: support more localizations, if needed
577 if ( xName->GetSymbol() != sSymbol )
578 {
579 xName->SetSymbol(xName->GetSymbol().replace(';', ','));
580 }
581 return static_cast< sal_uInt16 >( nPos + 1 );
582 }
583 }
584 }
585 return 0;
586}
587
588OUString XclExpNameManagerImpl::GetUnusedName( const OUString& rName ) const
589{
590 OUString aNewName( rName );
591 sal_Int32 nAppIdx = 0;
592 bool bExist = true;
593 while( bExist )
594 {
595 // search the list of user-defined names
596 bExist = false;
597 for( size_t nPos = mnFirstUserIdx, nSize = maNameList.GetSize(); !bExist && (nPos < nSize); ++nPos )
598 {
600 bExist = xName->GetOrigName() == aNewName;
601 // name exists -> create a new name "<originalname>_<counter>"
602 if( bExist )
603 aNewName = rName + "_" + OUString::number( ++nAppIdx );
604 }
605 }
606 return aNewName;
607}
608
609sal_uInt16 XclExpNameManagerImpl::Append( XclExpName* pName )
610{
611 if( maNameList.GetSize() == 0xFFFF )
612 return 0;
614 return static_cast< sal_uInt16 >( maNameList.GetSize() ); // 1-based
615}
616
617sal_uInt16 XclExpNameManagerImpl::CreateName( SCTAB nTab, const ScRangeData& rRangeData )
618{
619 const OUString& rName = rRangeData.GetName();
620
621 /* #i38821# recursive names: first insert the (empty) name object,
622 otherwise a recursive call of this function from the formula compiler
623 with the same defined name will not find it and will create it again. */
624 size_t nOldListSize = maNameList.GetSize();
625 XclExpNameRef xName = new XclExpName( GetRoot(), rName );
626 if (nTab != SCTAB_GLOBAL)
627 xName->SetLocalTab(nTab);
628 sal_uInt16 nNameIdx = Append( xName );
629 // store the index of the NAME record in the lookup map
630 NamedExpMap::key_type key(nTab, rRangeData.GetName());
631 maNamedExpMap[key] = nNameIdx;
632
633 /* Create the definition formula.
634 This may cause recursive creation of other defined names. */
635 if( const ScTokenArray* pScTokArr = const_cast< ScRangeData& >( rRangeData ).GetCode() )
636 {
637 XclTokenArrayRef xTokArr;
638 OUString sSymbol;
639 // MSO requires named ranges to have absolute sheet references
640 if ( rRangeData.HasType( ScRangeData::Type::AbsPos ) || rRangeData.HasType( ScRangeData::Type::AbsArea ) )
641 {
642 // Don't modify the actual document; use a temporary copy to create the export formulas.
643 ScTokenArray aTokenCopy( pScTokArr->CloneValue() );
644 lcl_EnsureAbs3DToken(nTab, aTokenCopy.FirstToken());
645
646 xTokArr = GetFormulaCompiler().CreateFormula(EXC_FMLATYPE_NAME, aTokenCopy);
647 if ( GetOutput() != EXC_OUTPUT_BINARY )
648 {
649 ScCompiler aComp(GetDoc(), rRangeData.GetPos(), aTokenCopy,
651 aComp.CreateStringFromTokenArray( sSymbol );
652 }
653 }
654 else
655 {
656 bool bOOXML = GetOutput() == EXC_OUTPUT_XML_2007;
657 xTokArr = GetFormulaCompiler().CreateFormula( EXC_FMLATYPE_NAME, *pScTokArr, bOOXML ?
658 &rRangeData.GetPos() : nullptr );
659 sSymbol = rRangeData.GetSymbol( (GetOutput() == EXC_OUTPUT_BINARY) ?
661 }
662 xName->SetTokenArray( xTokArr );
663 xName->SetSymbol( sSymbol );
664
665 /* Try to replace by existing built-in name - complete token array is
666 needed for comparison, and due to the recursion problem above this
667 cannot be done earlier. If a built-in name is found, the created NAME
668 record for this name and all following records in the list must be
669 deleted, otherwise they may contain wrong name list indexes. */
670 sal_uInt16 nBuiltInIdx = FindBuiltInNameIdx( rName, sSymbol );
671 if( nBuiltInIdx != 0 )
672 {
673 // delete the new NAME records
674 while( maNameList.GetSize() > nOldListSize )
676 // use index of the found built-in NAME record
677 key = NamedExpMap::key_type(nTab, rRangeData.GetName());
678 maNamedExpMap[key] = nNameIdx = nBuiltInIdx;
679 }
680 }
681
682 return nNameIdx;
683}
684
686{
687 ScDocument& rDoc = GetDoc();
688 XclExpTabInfo& rTabInfo = GetTabInfo();
689
690 /* #i2394# built-in defined names must be sorted by the name of the
691 containing sheet. Example: SheetA!Print_Range must be stored *before*
692 SheetB!Print_Range, regardless of the position of SheetA in the document! */
693 for( SCTAB nScTabIdx = 0, nScTabCount = rTabInfo.GetScTabCount(); nScTabIdx < nScTabCount; ++nScTabIdx )
694 {
695 // find real sheet index from the nScTabIdx counter
696 SCTAB nScTab = rTabInfo.GetRealScTab( nScTabIdx );
697 // create NAME records for all built-in names of this sheet
698 if( rTabInfo.IsExportTab( nScTab ) )
699 {
700 // *** 1) print ranges *** ----------------------------------------
701
702 if( rDoc.HasPrintRange() )
703 {
704 ScRangeList aRangeList;
705 for( sal_uInt16 nIdx = 0, nCount = rDoc.GetPrintRangeCount( nScTab ); nIdx < nCount; ++nIdx )
706 {
707 const ScRange* pPrintRange = rDoc.GetPrintRange( nScTab, nIdx );
708 if (!pPrintRange)
709 continue;
710 ScRange aRange( *pPrintRange );
711 // Calc document does not care about sheet index in print ranges
712 aRange.aStart.SetTab( nScTab );
713 aRange.aEnd.SetTab( nScTab );
714 aRange.PutInOrder();
715 aRangeList.push_back( aRange );
716 }
717 // create the NAME record (do not warn if ranges are shrunken)
718 GetAddressConverter().ValidateRangeList( aRangeList, false );
719 if( !aRangeList.empty() )
721 }
722
723 // *** 2) print titles *** ----------------------------------------
724
725 ScRangeList aTitleList;
726 // repeated columns
727 if( std::optional<ScRange> oColRange = rDoc.GetRepeatColRange( nScTab ) )
728 aTitleList.push_back( ScRange(
729 oColRange->aStart.Col(), 0, nScTab,
730 oColRange->aEnd.Col(), GetXclMaxPos().Row(), nScTab ) );
731 // repeated rows
732 if( std::optional<ScRange> oRowRange = rDoc.GetRepeatRowRange( nScTab ) )
733 aTitleList.push_back( ScRange(
734 0, oRowRange->aStart.Row(), nScTab,
735 GetXclMaxPos().Col(), oRowRange->aEnd.Row(), nScTab ) );
736 // create the NAME record
737 GetAddressConverter().ValidateRangeList( aTitleList, false );
738 if( !aTitleList.empty() )
740
741 // *** 3) filter ranges *** ---------------------------------------
742
743 if( GetBiff() == EXC_BIFF8 )
745 }
746 }
747}
748
750{
751 std::vector<ScRangeData*> vEmulateAsLocalRange;
752 const ScRangeName& rNamedRanges = GetNamedRanges();
753 for (const auto& rEntry : rNamedRanges)
754 {
755 // skip definitions of shared formulas
756 if (!FindNamedExp(SCTAB_GLOBAL, rEntry.second->GetName()))
757 {
758 const ScTokenArray* pCode = rEntry.second->GetCode();
759 if ( pCode
760 && (rEntry.second->HasType( ScRangeData::Type::AbsPos ) || rEntry.second->HasType( ScRangeData::Type::AbsArea ))
761 && lcl_EnsureAbs3DToken( SCTAB_GLOBAL, pCode->FirstToken(), /*bFix=*/false ) )
762 {
763 vEmulateAsLocalRange.emplace_back(rEntry.second.get());
764 }
765 else
766 CreateName(SCTAB_GLOBAL, *rEntry.second);
767 }
768 }
769 //look at sheets containing local range names
770 ScRangeName::TabNameCopyMap rLocalNames;
771 GetDoc().GetAllTabRangeNames(rLocalNames);
772 for (const auto& [rTab, pRangeName] : rLocalNames)
773 {
774 for (const auto& rEntry : *pRangeName)
775 {
776 // skip definitions of shared formulas
777 if (!FindNamedExp(rTab, rEntry.second->GetName()))
778 CreateName(rTab, *rEntry.second);
779 }
780 }
781
782 // Emulate relative global variables by creating a copy in each local range.
783 // Creating AFTER true local range names so that conflicting global names will be ignored.
784 for ( SCTAB nTab = 0; nTab < GetDoc().GetTableCount(); ++nTab )
785 {
786 for ( auto rangeDataItr : vEmulateAsLocalRange )
787 {
788 if ( !FindNamedExp(nTab, rangeDataItr->GetName()) )
789 CreateName(nTab, *rangeDataItr );
790 }
791 }
792}
793
795 XclExpRoot( rRoot ),
796 mxImpl( std::make_shared<XclExpNameManagerImpl>( rRoot ) )
797{
798}
799
801{
802}
803
805{
806 mxImpl->Initialize();
807}
808
809sal_uInt16 XclExpNameManager::InsertName( SCTAB nTab, sal_uInt16 nScNameIdx, SCTAB nCurrTab )
810{
811 return mxImpl->InsertName( nTab, nScNameIdx, nCurrTab );
812}
813
814sal_uInt16 XclExpNameManager::InsertBuiltInName( sal_Unicode cBuiltIn, const ScRange& rRange )
815{
817 return mxImpl->InsertBuiltInName( cBuiltIn, xTokArr, rRange );
818}
819
820sal_uInt16 XclExpNameManager::InsertBuiltInName( sal_Unicode cBuiltIn, const ScRangeList& rRangeList )
821{
822 sal_uInt16 nNameIdx = 0;
823 if( !rRangeList.empty() )
824 {
826 nNameIdx = mxImpl->InsertBuiltInName( cBuiltIn, xTokArr, rRangeList.front().aStart.Tab(), rRangeList );
827 }
828 return nNameIdx;
829}
830
832 const OUString& rName, const XclTokenArrayRef& xTokArr, SCTAB nScTab )
833{
834 return mxImpl->InsertUniqueName( rName, xTokArr, nScTab );
835}
836
837sal_uInt16 XclExpNameManager::InsertRawName( const OUString& rName )
838{
839 return mxImpl->InsertRawName( rName );
840}
841
842sal_uInt16 XclExpNameManager::InsertMacroCall( const OUString& rMacroName, bool bVBasic, bool bFunc, bool bHidden )
843{
844 return mxImpl->InsertMacroCall( rMacroName, bVBasic, bFunc, bHidden );
845}
846
847OUString XclExpNameManager::GetOrigName( sal_uInt16 nNameIdx ) const
848{
849 const XclExpName* pName = mxImpl->GetName( nNameIdx );
850 return pName ? pName->GetOrigName() : OUString();
851}
852
853SCTAB XclExpNameManager::GetScTab( sal_uInt16 nNameIdx ) const
854{
855 const XclExpName* pName = mxImpl->GetName( nNameIdx );
856 return pName ? pName->GetScTab() : SCTAB_GLOBAL;
857}
858
859bool XclExpNameManager::IsVolatile( sal_uInt16 nNameIdx ) const
860{
861 const XclExpName* pName = mxImpl->GetName( nNameIdx );
862 return pName && pName->IsVolatile();
863}
864
866{
867 mxImpl->Save( rStrm );
868}
869
871{
872 mxImpl->SaveXml( rStrm );
873}
874
875/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
const char * pName
ScRefFlags
Definition: address.hxx:158
SCTAB Tab() const
Definition: address.hxx:283
void SetTab(SCTAB nTabP)
Definition: address.hxx:295
SC_DLLPUBLIC const ScRange * GetPrintRange(SCTAB nTab, sal_uInt16 nPos)
Definition: document.cxx:6268
SC_DLLPUBLIC void GetAllTabRangeNames(ScRangeName::TabNameCopyMap &rRangeNames) const
Get all range names that are local to each table.
Definition: documen3.cxx:107
SC_DLLPUBLIC bool HasPrintRange()
Definition: document.cxx:6239
SC_DLLPUBLIC std::optional< ScRange > GetRepeatColRange(SCTAB nTab)
Definition: document.cxx:6276
SC_DLLPUBLIC std::optional< ScRange > GetRepeatRowRange(SCTAB nTab)
Definition: document.cxx:6284
SC_DLLPUBLIC ScRangeName * GetRangeName(SCTAB nTab) const
Definition: documen3.cxx:171
SC_DLLPUBLIC sal_uInt16 GetPrintRangeCount(SCTAB nTab)
Definition: document.cxx:6261
SC_DLLPUBLIC SCTAB GetTableCount() const
Definition: document.cxx:297
bool HasType(Type nType) const
Definition: rangenam.hxx:178
void GetName(OUString &rName) const
Definition: rangenam.hxx:110
const ScAddress & GetPos() const
Definition: rangenam.hxx:113
SC_DLLPUBLIC OUString GetSymbol(const formula::FormulaGrammar::Grammar eGrammar=formula::FormulaGrammar::GRAM_DEFAULT) const
Definition: rangenam.cxx:244
ScRange & front()
Definition: rangelst.hxx:92
void Format(OUString &, ScRefFlags nFlags, const ScDocument &, formula::FormulaGrammar::AddressConvention eConv=formula::FormulaGrammar::CONV_OOO, sal_Unicode cDelimiter=0, bool bFullAddressNotation=false) const
Definition: rangelst.cxx:132
bool empty() const
Definition: rangelst.hxx:88
void push_back(const ScRange &rRange)
Definition: rangelst.cxx:1137
SC_DLLPUBLIC ScRangeData * findByIndex(sal_uInt16 i) const
Definition: rangenam.cxx:716
::std::map< SCTAB, const ScRangeName * > TabNameCopyMap
Map that stores non-managed pointers to ScRangeName instances.
Definition: rangenam.hxx:201
OUString Format(const ScDocument &rDocument, ScRefFlags nFlags=ScRefFlags::ZERO, const ScAddress::Details &rDetails=ScAddress::detailsOOOa1, bool bFullAddressNotation=false) const
Returns string with formatted cell range from aStart to aEnd, according to provided address conventio...
Definition: address.cxx:2170
void PutInOrder()
Definition: address.hxx:622
ScAddress aEnd
Definition: address.hxx:498
ScRefFlags Parse(const OUString &, const ScDocument &, const ScAddress::Details &rDetails=ScAddress::detailsOOOa1, ScAddress::ExternalInfo *pExtInfo=nullptr, const css::uno::Sequence< css::sheet::ExternalLinkInfo > *pExternalLinks=nullptr, const OUString *pErrRef=nullptr)
Definition: address.cxx:1700
ScAddress aStart
Definition: address.hxx:497
void ValidateRangeList(ScRangeList &rScRanges, bool bWarn)
Checks and eventually crops the cell ranges to valid dimensions.
Definition: xehelper.cxx:261
void InitTabFilter(SCTAB nScTab)
Creates the filter records for the specified sheet.
Definition: excrecds.cxx:1192
XclTokenArrayRef CreateFormula(XclFormulaType eType, const ScTokenArray &rScTokArr, const ScAddress *pScBasePos=nullptr, XclExpRefLog *pRefLog=nullptr)
Creates and returns the token array of a formula.
Definition: xeformula.cxx:2656
Implementation class of the name manager.
Definition: xename.cxx:116
XclExpNameList maNameList
Definition: xename.cxx:190
sal_uInt16 InsertBuiltInName(sal_Unicode cBuiltIn, const XclTokenArrayRef &xTokArr, SCTAB nScTab, const ScRangeList &aRangeList)
Inserts a new built-in defined name.
Definition: xename.cxx:464
XclExpNameManagerImpl(const XclExpRoot &rRoot)
Definition: xename.cxx:415
sal_uInt16 CreateName(SCTAB nTab, const ScRangeData &rRangeData)
Creates a new NAME record for the passed user-defined name.
Definition: xename.cxx:617
NamedExpMap maNamedExpMap
Maps Calc's named range to Excel's NAME records.
Definition: xename.cxx:189
size_t mnFirstUserIdx
List of NAME records.
Definition: xename.cxx:191
void Initialize()
Creates NAME records for built-in and user defined names.
Definition: xename.cxx:421
XclExpNameList::RecordRefType XclExpNameRef
Definition: xename.cxx:151
sal_uInt16 FindBuiltInNameIdx(const OUString &rName, const OUString &sSymbol) const
Returns the index of an existing built-in NAME record with the passed definition, otherwise 0.
Definition: xename.cxx:560
void CreateUserNames()
Creates NAME records for all user-defined names in the document.
Definition: xename.cxx:749
sal_uInt16 FindNamedExp(SCTAB nTab, OUString sName)
Definition: xename.cxx:553
sal_uInt16 Append(XclExpName *pName)
Appends a new NAME record to the record list.
Definition: xename.cxx:609
const XclExpName * GetName(sal_uInt16 nNameIdx) const
Returns the NAME record at the specified position or 0 on error.
Definition: xename.cxx:530
void SaveXml(XclExpXmlStream &rStrm)
Definition: xename.cxx:541
sal_uInt16 InsertUniqueName(const OUString &rName, const XclTokenArrayRef &xTokArr, SCTAB nScTab)
Inserts a new defined name.
Definition: xename.cxx:475
sal_uInt16 InsertRawName(const OUString &rName)
Returns index of an existing name, or creates a name without definition.
Definition: xename.cxx:485
void Save(XclExpStream &rStrm)
Writes the entire list of NAME records.
Definition: xename.cxx:536
void CreateBuiltInNames()
Creates NAME records for all built-in names in the document.
Definition: xename.cxx:685
sal_uInt16 InsertName(SCTAB nTab, sal_uInt16 nScNameIdx, SCTAB nCurrTab)
Inserts the Calc name with the passed index and returns the Excel NAME index.
Definition: xename.cxx:428
XclExpRecordList< XclExpName > XclExpNameList
Definition: xename.cxx:150
sal_uInt16 Append(XclExpNameRef const &rxName)
Definition: xename.cxx:173
::std::map< ::std::pair< SCTAB, OUString >, sal_uInt16 > NamedExpMap
Definition: xename.cxx:153
sal_uInt16 InsertMacroCall(const OUString &rMacroName, bool bVBasic, bool bFunc, bool bHidden)
Searches or inserts a defined name describing a macro name.
Definition: xename.cxx:504
OUString GetUnusedName(const OUString &rName) const
Returns an unused name for the passed name.
Definition: xename.cxx:588
sal_uInt16 InsertRawName(const OUString &rName)
Returns index of an existing name, or creates a name without definition.
Definition: xename.cxx:837
SCTAB GetScTab(sal_uInt16 nNameIdx) const
Returns the Calc sheet of a local defined name, or SCTAB_GLOBAL for global defined names.
Definition: xename.cxx:853
sal_uInt16 InsertUniqueName(const OUString &rName, const XclTokenArrayRef &xTokArr, SCTAB nScTab)
Inserts a new defined name.
Definition: xename.cxx:831
sal_uInt16 InsertName(SCTAB nTab, sal_uInt16 nScNameIdx, SCTAB nCurrTab)
Inserts the Calc name with the passed index and returns the Excel NAME index.
Definition: xename.cxx:809
XclExpNameManager(const XclExpRoot &rRoot)
Definition: xename.cxx:794
bool IsVolatile(sal_uInt16 nNameIdx) const
Returns true, if the specified defined name is volatile.
Definition: xename.cxx:859
void Initialize()
Creates NAME records for built-in and user defined names.
Definition: xename.cxx:804
virtual ~XclExpNameManager() override
Definition: xename.cxx:800
virtual void Save(XclExpStream &rStrm) override
Writes the entire list of NAME records.
Definition: xename.cxx:865
sal_uInt16 InsertBuiltInName(sal_Unicode cBuiltIn, const ScRange &rRange)
Inserts a new built-in defined name, referring to the passed sheet range.
Definition: xename.cxx:814
sal_uInt16 InsertMacroCall(const OUString &rMacroName, bool bVBasic, bool bFunc, bool bHidden=false)
Searches or inserts a defined name describing a macro name.
Definition: xename.cxx:842
OUString GetOrigName(sal_uInt16 nNameIdx) const
Returns the Calc sheet of a local defined name, or SCTAB_GLOBAL for global defined names.
Definition: xename.cxx:847
virtual void SaveXml(XclExpXmlStream &rStrm) override
Definition: xename.cxx:870
XclExpNameMgrImplRef mxImpl
Definition: xename.hxx:70
virtual void SaveXml(XclExpXmlStream &rStrm)
Definition: xerecord.cxx:40
virtual void SaveXml(XclExpXmlStream &rStrm) override
Definition: xerecord.hxx:382
bool HasRecord(size_t nPos) const
Returns true, if the passed index points to an exiting record.
Definition: xerecord.hxx:330
size_t GetSize() const
Definition: xerecord.hxx:327
void RemoveRecord(size_t nPos)
Removes the record at the specified position from the list.
Definition: xerecord.hxx:369
bool IsEmpty() const
Definition: xerecord.hxx:326
virtual void Save(XclExpStream &rStrm) override
Writes the complete record list.
Definition: xerecord.hxx:375
void AppendRecord(RecType *pRec)
Appends a record to the list.
Definition: xerecord.hxx:348
RecType * GetRecord(size_t nPos) const
Returns reference to an existing record or empty reference on error.
Definition: xerecord.hxx:333
Base class for single records with any content.
Definition: xerecord.hxx:143
virtual void Save(XclExpStream &rStrm) override
Writes the record header and calls WriteBody().
Definition: xerecord.cxx:150
virtual void WriteBody(XclExpStream &rStrm)
Writes the body of the record (without record header).
Definition: xerecord.cxx:146
Access to global data from other classes.
Definition: xeroot.hxx:113
XclExpNameManager & GetNameManager() const
Returns the buffer that contains internal defined names.
Definition: xeroot.cxx:142
XclExpFormulaCompiler & GetFormulaCompiler() const
Returns the formula compiler to produce formula token arrays.
Definition: xeroot.cxx:88
XclExpAddressConverter & GetAddressConverter() const
Returns the address converter.
Definition: xeroot.cxx:82
XclExpTabInfo & GetTabInfo() const
Returns the buffer for Calc->Excel sheet index conversion.
Definition: xeroot.cxx:76
const XclExpRoot & GetRoot() const
Returns this root instance - for code readability in derived classes.
Definition: xeroot.hxx:118
XclExpFilterManager & GetFilterManager() const
Returns the filter manager.
Definition: xeroot.cxx:154
This class is used to export Excel record streams.
Definition: xestream.hxx:73
This class provides methods to create an XclExpString.
Definition: xehelper.hxx:215
static XclExpStringRef CreateString(const XclExpRoot &rRoot, const OUString &rString, XclStrFlags nFlags=XclStrFlags::NONE, sal_uInt16 nMaxLen=EXC_STR_MAXLEN)
Creates a new unformatted string from the passed string.
Definition: xehelper.cxx:536
Stores the correct Excel sheet index for each Calc sheet.
Definition: xelink.hxx:62
SCTAB GetScTabCount() const
Returns the number of Calc sheets.
Definition: xelink.hxx:89
SCTAB GetRealScTab(SCTAB nSortedScTab) const
Returns the Calc sheet index of the nSortedTab-th entry in the sorted sheet names list.
Definition: xelink.cxx:819
bool IsExportTab(SCTAB nScTab) const
Returns true, if the specified Calc sheet will be exported.
Definition: xelink.cxx:774
XclOutput GetOutput() const
Returns the current output format of the importer/exporter.
Definition: xlroot.hxx:143
XclBiff GetBiff() const
Returns the current BIFF version of the importer/exporter.
Definition: xlroot.hxx:141
ScRangeName & GetNamedRanges() const
Returns the defined names container of the Calc document.
Definition: xlroot.cxx:311
const ScAddress & GetXclMaxPos() const
Returns the highest possible cell address in an Excel document (using current BIFF version).
Definition: xlroot.hxx:246
ScDocument & GetDoc() const
Returns reference to the destination document (import) or source document (export).
Definition: xlroot.cxx:285
static OUString GetBuiltInDefNameXml(sal_Unicode cBuiltIn)
Returns the Excel built-in name with OOXML prefix @descr Adds the "_xlnm." prefix to the representati...
Definition: xltools.cxx:500
static OUString GetXclBuiltInDefName(sal_Unicode cBuiltIn)
Returns the raw English UI representation of a built-in defined name used in NAME records.
Definition: xltools.cxx:484
static sal_Unicode GetBuiltInDefNameIndex(const OUString &rDefName)
Returns the Excel built-in name index of the passed defined name from Calc.
Definition: xltools.cxx:505
void CreateStringFromTokenArray(OUString &rFormula)
FormulaToken * FirstToken() const
FormulaToken ** GetCode() const
virtual const ScSingleRefData * GetSingleRef() const
virtual const ScSingleRefData * GetSingleRef2() const
StackVar GetType() const
int nCount
OUString sName
FuncFlags mnFlags
Information about all parameters.
bool get_flag(Type nBitField, Type nMask)
Returns true, if at least one of the bits set in nMask is set in nBitField.
Definition: ftools.hxx:75
void set_flag(Type &rnBitField, Type nMask, bool bSet=true)
Sets or clears (according to bSet) all set bits of nMask in rnBitField.
Definition: ftools.hxx:95
OUString aName
sal_uInt16 nPos
std::unique_ptr< sal_Int32[]> pData
void SvStream & rStrm
std::shared_ptr< T > make_shared(Args &&... args)
const char * UseIf(const char *s, bool bUse)
std::shared_ptr< FastSerializerHelper > FSHelperPtr
Single reference (one address) into the sheet.
Definition: refdata.hxx:30
void SetAbsTab(SCTAB nVal)
Definition: refdata.cxx:93
SCTAB Tab() const
Definition: refdata.cxx:254
bool IsTabRel() const
Definition: refdata.hxx:69
void SetFlag3D(bool bVal)
Definition: refdata.hxx:89
bool IsFlag3D() const
Definition: refdata.hxx:90
unsigned char sal_uInt8
sal_uInt16 sal_Unicode
sal_Int16 SCTAB
Definition: types.hxx:22
static bool lcl_EnsureAbs3DToken(const SCTAB nTab, formula::FormulaToken *pTok, const bool bFix=true)
Returns true (needed fixing) if FormulaToken was not absolute and 3D.
Definition: xename.cxx:373
std::shared_ptr< XclExpString > XclExpStringRef
Definition: xeroot.hxx:35
const SCTAB SCTAB_GLOBAL
An invalid Calc sheet index, for common use.
Definition: xlconst.hxx:74
const sal_uInt8 EXC_ERR_NAME
Definition: xlconst.hxx:108
@ EXC_BIFF5
MS Excel 4.0.
Definition: xlconst.hxx:34
@ EXC_BIFF8
MS Excel 5.0, MS Excel 7.0 (95)
Definition: xlconst.hxx:35
@ EXC_OUTPUT_BINARY
Definition: xlconst.hxx:42
@ EXC_OUTPUT_XML_2007
MS Excel binary .xls.
Definition: xlconst.hxx:43
@ EXC_FMLATYPE_NAME
Data validation.
Definition: xlformula.hxx:166
std::shared_ptr< XclTokenArray > XclTokenArrayRef
Definition: xlformula.hxx:416
const sal_Unicode EXC_BUILTIN_UNKNOWN
Definition: xlname.hxx:61
const sal_uInt16 EXC_NAME_DEFAULT
Definition: xlname.hxx:32
const sal_uInt16 EXC_ID_NAME
Definition: xlname.hxx:28
const sal_uInt16 EXC_NAME_VB
Definition: xlname.hxx:35
const sal_Unicode EXC_BUILTIN_FILTERDATABASE
Definition: xlname.hxx:60
const sal_uInt16 EXC_NAME_HIDDEN
Definition: xlname.hxx:33
const sal_uInt16 EXC_NAME_BUILTIN
Definition: xlname.hxx:38
const sal_Unicode EXC_BUILTIN_PRINTTITLES
Definition: xlname.hxx:54
const sal_uInt16 EXC_NAME_GLOBAL
BIFF2 function/command flag.
Definition: xlname.hxx:44
const sal_uInt16 EXC_NAME_PROC
Definition: xlname.hxx:36
const sal_Unicode EXC_BUILTIN_PRINTAREA
Definition: xlname.hxx:53
const sal_uInt16 EXC_NAME_FUNC
Definition: xlname.hxx:34
XclStrFlags
Flags used to specify import/export mode of strings.
Definition: xlstring.hxx:29
@ EightBitLength
Always use UCS-2 characters (default: try to compress). BIFF8 only.
#define DBG_ERROR_BIFF()
Definition: xltools.hxx:33