LibreOffice Module sc (master)  1
xiname.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 <xiname.hxx>
21 #include <xlname.hxx>
22 #include <rangenam.hxx>
23 #include <xistream.hxx>
24 #include <excform.hxx>
25 #include <excimp8.hxx>
26 #include <scextopt.hxx>
27 #include <document.hxx>
28 
29 // *** Implementation ***
30 
32  mrStrm(rStrm), mnStrmPos(0), mnStrmSize(0) {}
33 
34 XclImpName::XclImpName( XclImpStream& rStrm, sal_uInt16 nXclNameIdx ) :
35  XclImpRoot( rStrm.GetRoot() ),
36  mpScData( nullptr ),
37  mnScTab( SCTAB_MAX ),
40  mnNameIndex( nXclNameIdx ),
41  mbVBName( false ),
42  mbMacro( false )
43 {
44  ExcelToSc& rFmlaConv = GetOldFmlaConverter();
45 
46  // 1) *** read data from stream *** ---------------------------------------
47 
48  sal_uInt16 nFlags = 0, nFmlaSize = 0, nExtSheet = EXC_NAME_GLOBAL;
49  sal_uInt8 nNameLen = 0;
51 
52  switch( GetBiff() )
53  {
54  case EXC_BIFF2:
55  {
56  sal_uInt8 nFlagsBiff2;
57  nFlagsBiff2 = rStrm.ReaduInt8();
58  rStrm.Ignore( 1 );
59  rStrm.Ignore( 1 ); //nShortCut
60  nNameLen = rStrm.ReaduInt8();
61  nFmlaSize = rStrm.ReaduInt8();
62  ::set_flag( nFlags, EXC_NAME_FUNC, ::get_flag( nFlagsBiff2, EXC_NAME2_FUNC ) );
63  }
64  break;
65 
66  case EXC_BIFF3:
67  case EXC_BIFF4:
68  {
69  nFlags = rStrm.ReaduInt16();
70  rStrm.Ignore( 1 ); //nShortCut
71  nNameLen = rStrm.ReaduInt8();
72  nFmlaSize = rStrm.ReaduInt16();
73  }
74  break;
75 
76  case EXC_BIFF5:
77  case EXC_BIFF8:
78  {
79  nFlags = rStrm.ReaduInt16();
80  rStrm.Ignore( 1 ); //nShortCut
81  nNameLen = rStrm.ReaduInt8();
82  nFmlaSize = rStrm.ReaduInt16();
83  nExtSheet = rStrm.ReaduInt16();
84  mnXclTab = rStrm.ReaduInt16();
85  rStrm.Ignore( 4 );
86  }
87  break;
88 
89  default: DBG_ERROR_BIFF();
90  }
91 
92  if( GetBiff() <= EXC_BIFF5 )
93  maXclName = rStrm.ReadRawByteString( nNameLen );
94  else
95  maXclName = rStrm.ReadUniString( nNameLen );
96 
97  // 2) *** convert sheet index and name *** --------------------------------
98 
99  // functions and VBA
100  bool bFunction = ::get_flag( nFlags, EXC_NAME_FUNC );
101  mbVBName = ::get_flag( nFlags, EXC_NAME_VB );
102  mbMacro = ::get_flag( nFlags, EXC_NAME_PROC );
103 
104  // get built-in name, or convert characters invalid in Calc
105  bool bBuiltIn = ::get_flag( nFlags, EXC_NAME_BUILTIN );
106 
107  // special case for BIFF5 filter range - name appears as plain text without built-in flag
109  {
110  bBuiltIn = true;
111  maXclName = OUStringChar(EXC_BUILTIN_FILTERDATABASE);
112  }
113 
114  // convert Excel name to Calc name
115  if( mbVBName )
116  {
117  // VB macro name
119  }
120  else if( bBuiltIn )
121  {
122  // built-in name
123  if( !maXclName.isEmpty() )
124  cBuiltIn = maXclName[0];
125  if( cBuiltIn == '?' ) // NUL character is imported as '?'
126  cBuiltIn = '\0';
128  }
129  else
130  {
131  // any other name
133  }
134 
135  // add index for local names
136  if( mnXclTab != EXC_NAME_GLOBAL )
137  {
138  sal_uInt16 nUsedTab = (GetBiff() == EXC_BIFF8) ? mnXclTab : nExtSheet;
139  // TODO: may not work for BIFF5, handle skipped sheets (all BIFF)
140  mnScTab = static_cast< SCTAB >( nUsedTab - 1 );
141  }
142 
143  // 3) *** convert the name definition formula *** -------------------------
144 
145  rFmlaConv.Reset();
146  std::unique_ptr<ScTokenArray> pTokArr;
147 
148  if( ::get_flag( nFlags, EXC_NAME_BIG ) )
149  {
150  // special, unsupported name
151  pTokArr = rFmlaConv.GetDummy();
152  }
153  else if( bBuiltIn )
154  {
155  SCTAB const nLocalTab = (mnXclTab == EXC_NAME_GLOBAL) ? SCTAB_MAX : (mnXclTab - 1);
156 
157  // --- print ranges or title ranges ---
158  rStrm.PushPosition();
159  switch( cBuiltIn )
160  {
162  if( rFmlaConv.Convert( GetPrintAreaBuffer(), rStrm, nFmlaSize, nLocalTab, FT_RangeName ) == ConvErr::OK )
164  break;
166  if( rFmlaConv.Convert( GetTitleAreaBuffer(), rStrm, nFmlaSize, nLocalTab, FT_RangeName ) == ConvErr::OK )
168  break;
169  }
170  rStrm.PopPosition();
171 
172  // --- name formula ---
173  // JEG : double check this. It is clearly false for normal names
174  // but some of the builtins (sheettitle?) might be able to handle arrays
175  rFmlaConv.Convert( pTokArr, rStrm, nFmlaSize, false, FT_RangeName );
176 
177  // --- auto or advanced filter ---
178  if ((GetBiff() == EXC_BIFF8) && pTokArr)
179  {
180  ScRange aRange;
181  if (pTokArr->IsReference(aRange, ScAddress()))
182  {
183  switch( cBuiltIn )
184  {
186  GetFilterManager().Insert( &GetOldRoot(), aRange);
187  break;
191  break;
192  case EXC_BUILTIN_EXTRACT:
193  if (pTokArr->IsValidReference(aRange, ScAddress()))
194  GetFilterManager().AddExtractPos( aRange );
195  break;
196  }
197  }
198  }
199  }
200  else if( nFmlaSize > 0 )
201  {
202  // Regular defined name. We need to convert the tokens after all the
203  // names have been registered (for cross-referenced names).
204  mpTokensData.reset(new TokenStrmData(rStrm));
205  mpTokensData->mnStrmPos = rStrm.GetSvStreamPos();
206  rStrm.StorePosition(mpTokensData->maStrmPos);
207  mpTokensData->mnStrmSize = nFmlaSize;
208  }
209 
210  if (pTokArr && !bFunction && !mbVBName)
211  InsertName(pTokArr.get());
212 }
213 
215 {
216  if (!mpTokensData)
217  return;
218 
219  ExcelToSc& rFmlaConv = GetOldFmlaConverter();
220  rFmlaConv.Reset();
221  std::unique_ptr<ScTokenArray> pArray;
222 
223  XclImpStreamPos aOldPos;
224  XclImpStream& rStrm = mpTokensData->mrStrm;
225  rStrm.StorePosition(aOldPos);
226  rStrm.RestorePosition(mpTokensData->maStrmPos);
227  rFmlaConv.Convert(pArray, rStrm, mpTokensData->mnStrmSize, true, FT_RangeName);
228  rStrm.RestorePosition(aOldPos);
229 
230  if (pArray)
231  InsertName(pArray.get());
232 
233  mpTokensData.reset();
234 }
235 
237 {
238  // create the Calc name data
240  pData->GuessPosition(); // calculate base position for relative refs
241  pData->SetIndex( mnNameIndex ); // used as unique identifier in formulas
242  if (mnXclTab == EXC_NAME_GLOBAL)
243  {
244  if (!GetDoc().GetRangeName()->insert(pData))
245  pData = nullptr;
246  }
247  else
248  {
249  ScRangeName* pLocalNames = GetDoc().GetRangeName(mnScTab);
250  if (pLocalNames)
251  {
252  if (!pLocalNames->insert(pData))
253  pData = nullptr;
254  }
255  else
256  {
257  delete pData;
258  pData = nullptr;
259  }
260 
261  if (GetBiff() == EXC_BIFF8 && pData)
262  {
263  ScRange aRange;
264  // discard deleted ranges ( for the moment at least )
265  if ( pData->IsValidReference( aRange ) )
266  {
268  }
269  }
270  }
271  if (pData)
272  {
274  mpScData = pData; // cache for later use
275  }
276 }
277 
279  XclImpRoot( rRoot )
280 {
281 }
282 
284 {
285  sal_uLong nCount = maNameList.size();
286  if( nCount < 0xFFFF )
287  maNameList.push_back( std::make_unique<XclImpName>( rStrm, static_cast< sal_uInt16 >( nCount + 1 ) ) );
288 }
289 
290 const XclImpName* XclImpNameManager::FindName( const OUString& rXclName, SCTAB nScTab ) const
291 {
292  const XclImpName* pGlobalName = nullptr; // a found global name
293  const XclImpName* pLocalName = nullptr; // a found local name
294  for( const auto& rxName : maNameList )
295  {
296  if( rxName->GetXclName() == rXclName )
297  {
298  if( rxName->GetScTab() == nScTab )
299  pLocalName = rxName.get();
300  else if( rxName->IsGlobal() )
301  pGlobalName = rxName.get();
302  }
303 
304  if (pLocalName)
305  break;
306  }
307  return pLocalName ? pLocalName : pGlobalName;
308 }
309 
310 const XclImpName* XclImpNameManager::GetName( sal_uInt16 nXclNameIdx ) const
311 {
312  OSL_ENSURE( nXclNameIdx > 0, "XclImpNameManager::GetName - index must be >0" );
313  return ( nXclNameIdx <= 0 || nXclNameIdx > maNameList.size() ) ? nullptr : maNameList.at( nXclNameIdx - 1 ).get();
314 }
315 
317 {
318  for (auto& rxName : maNameList)
319  rxName->ConvertTokens();
320 }
321 
322 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
OUString ReadRawByteString(sal_uInt16 nChars)
Reads nChar byte characters and returns the string.
Definition: xistream.cxx:944
const sal_uInt16 EXC_NAME_VB
Definition: xlname.hxx:36
Type
#define DBG_ERROR_BIFF()
Definition: xltools.hxx:31
const sal_Unicode EXC_BUILTIN_CRITERIA
Definition: xlname.hxx:53
sal_uInt16 mnNameIndex
Definition: xiname.hxx:70
XclImpNameManager(const XclImpRoot &rRoot)
Definition: xiname.cxx:278
void InsertName(const ScTokenArray *pArray)
Definition: xiname.cxx:236
const sal_Unicode EXC_BUILTIN_EXTRACT
Definition: xlname.hxx:51
void ConvertAllTokens()
Definition: xiname.cxx:316
void ReadName(XclImpStream &rStrm)
Reads a NAME record and creates an entry in this buffer.
Definition: xiname.cxx:283
std::unique_ptr< ContentProperties > pData
const ScRangeData * mpScData
Name inserted into the Calc document.
Definition: xiname.hxx:66
sal_uIntPtr sal_uLong
SC_DLLPUBLIC ScRangeName * GetRangeName(SCTAB nTab) const
Definition: documen3.cxx:168
static OUString ConvertToScDefinedName(const OUString &rName)
Converts a string to a valid Calc defined name or database range name.
Definition: ftools.cxx:145
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:93
OUString Name
TokenStrmData(XclImpStream &rStrm)
Definition: xiname.cxx:31
void AddExtractPos(const ScRange &rRange)
Definition: excimp8.cxx:794
ScDocument & GetDoc() const
Returns reference to the destination document (import) or source document (export).
Definition: xlroot.cxx:278
RootData & GetOldRoot() const
Returns old RootData struct.
Definition: xlroot.hxx:137
const XclImpName * GetName(sal_uInt16 nXclNameIdx) const
Returns the defined name specified by its Excel index.
Definition: xiname.cxx:310
const XclImpRoot & GetRoot() const
Returns this root instance - for code readability in derived classes.
Definition: xiroot.hxx:132
void Insert(RootData *pRoot, const ScRange &rRange)
Definition: excimp8.cxx:781
const sal_uInt16 EXC_NAME_BIG
Definition: xlname.hxx:41
const sal_uInt16 EXC_NAME_BUILTIN
Definition: xlname.hxx:39
sal_uInt16 sal_Unicode
bool mbVBName
Definition: xiname.hxx:71
SC_DLLPUBLIC void CheckLinkFormulaNeedingCheck(const ScTokenArray &rCode)
Check token array and set link check if ocDde/ocWebservice is contained.
Definition: documen8.cxx:1152
MS Excel 4.0.
Definition: xlconst.hxx:35
int nCount
void StorePosition(XclImpStreamPos &rPos)
Stores current stream position into rPos.
Definition: xistream.cxx:961
ExcelToSc & GetOldFmlaConverter() const
Returns the old formula converter.
Definition: xiroot.cxx:129
static OUString GetBuiltInDefName(sal_Unicode cBuiltIn)
Returns the Calc UI representation of a built-in defined name used in NAME records.
Definition: xltools.cxx:491
SC_DLLPUBLIC void GuessPosition()
Definition: rangenam.cxx:208
OUString maScName
Original name read from the file.
Definition: xiname.hxx:65
void PopPosition()
Seeks to last position from user position stack.
Definition: xistream.cxx:532
const sal_Unicode EXC_BUILTIN_UNKNOWN
Definition: xlname.hxx:62
ScRangeData::Type meNameType
Calc sheet index of local names.
Definition: xiname.hxx:68
ScExtTabSettings & GetOrCreateTabSettings(SCTAB nTab)
Definition: scextopt.cxx:190
MS Excel 5.0, MS Excel 7.0 (95)
Definition: xlconst.hxx:36
ScExtDocOptions & GetExtDocOptions() const
Returns the extended document options.
Definition: xlroot.cxx:421
XclImpAutoFilterBuffer & GetFilterManager() const
Returns the filter manager.
Definition: xiroot.cxx:217
std::unique_ptr< ScTokenArray > GetDummy()
Definition: excform.cxx:196
const sal_Unicode EXC_BUILTIN_PRINTTITLES
Definition: xlname.hxx:55
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:73
MS Excel 3.0.
Definition: xlconst.hxx:34
ScRangeListTabs & GetTitleAreaBuffer() const
Returns the buffer that contains all print titles in the document.
Definition: xiroot.cxx:172
const sal_Unicode EXC_BUILTIN_PRINTAREA
Definition: xlname.hxx:54
OUString maXclName
Definition: xiname.hxx:64
std::unique_ptr< TokenStrmData > mpTokensData
Whether it's a user-defined macro.
Definition: xiname.hxx:74
sal_uInt16 ReaduInt16()
Definition: xistream.cxx:648
virtual ConvErr Convert(std::unique_ptr< ScTokenArray > &, XclImpStream &rStrm, std::size_t nFormulaLen, bool bAllowArrays, const FORMULA_TYPE eFT=FT_CellFormula) override
Definition: excform.cxx:206
OUString ReadUniString(sal_uInt16 nChars, sal_uInt8 nFlags)
Reads ext.
Definition: xistream.cxx:886
const XclImpName * FindName(const OUString &rXclName, SCTAB nScTab) const
Tries to find the name used in Calc, based on the original Excel defined name.
Definition: xiname.cxx:290
void SetIndex(sal_uInt16 nInd)
Definition: rangenam.hxx:116
void Ignore(std::size_t nBytes)
Seeks forward inside the current record.
Definition: xistream.cxx:795
unsigned char sal_uInt8
sal_uInt8 ReaduInt8()
Definition: xistream.cxx:616
SCTAB mnScTab
Pointer to Calc defined name (no ownership).
Definition: xiname.hxx:67
This class represents an Excel stream position.
Definition: xistream.hxx:202
bool mbMacro
true = Visual Basic procedure or function.
Definition: xiname.hxx:72
XclBiff GetBiff() const
Returns the current BIFF version of the importer/exporter.
Definition: xlroot.hxx:140
void PushPosition()
Pushes current position on user position stack.
Definition: xistream.cxx:526
const sal_uInt16 EXC_NAME_GLOBAL
BIFF2 function/command flag.
Definition: xlname.hxx:45
SC_DLLPUBLIC bool IsValidReference(ScRange &rRef) const
Definition: rangenam.cxx:385
void ConvertTokens()
Definition: xiname.cxx:214
void AddAdvancedRange(const ScRange &rRange)
Definition: excimp8.cxx:787
MS Excel 2.1.
Definition: xlconst.hxx:33
This class is used to import record oriented streams.
Definition: xistream.hxx:278
std::size_t GetSvStreamPos() const
Returns the absolute stream position.
Definition: xistream.hxx:460
XclImpName(const XclImpName &)=delete
void SvStream & rStrm
const SCTAB SCTAB_MAX
Definition: address.hxx:58
Access to global data from other classes.
Definition: xiroot.hxx:126
const sal_uInt16 EXC_NAME_PROC
Definition: xlname.hxx:37
sal_uInt16 mnXclTab
Definition: xiname.hxx:69
ScTokenArray * GetCode()
Definition: rangenam.hxx:120
const sal_uInt8 EXC_NAME2_FUNC
Definition: xlname.hxx:43
Represents a defined name.
Definition: xiname.hxx:34
const sal_uInt16 EXC_NAME_FUNC
Definition: xlname.hxx:35
SC_DLLPUBLIC bool insert(ScRangeData *p, bool bReuseFreeIndex=true)
Insert object into set.
Definition: rangenam.cxx:810
void RestorePosition(const XclImpStreamPos &rPos)
Restores stream position contained in rPos.
Definition: xistream.cxx:966
XclImpNameList maNameList
Definition: xiname.hxx:105
const sal_Unicode EXC_BUILTIN_FILTERDATABASE
Definition: xlname.hxx:61
sal_Int16 SCTAB
Definition: types.hxx:23
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:480
ScRangeListTabs & GetPrintAreaBuffer() const
Returns the buffer that contains all print areas in the document.
Definition: xiroot.cxx:166