LibreOffice Module sc (master)  1
rangenam.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 <string.h>
21 #include <memory>
23 #include <unotools/charclass.hxx>
24 #include <com/sun/star/sheet/NamedRangeFlag.hpp>
25 #include <osl/diagnose.h>
26 
27 #include <token.hxx>
28 #include <tokenarray.hxx>
29 #include <rangenam.hxx>
30 #include <global.hxx>
31 #include <compiler.hxx>
32 #include <refupdat.hxx>
33 #include <document.hxx>
34 #include <refupdatecontext.hxx>
35 #include <tokenstringcontext.hxx>
36 
37 #include <formula/errorcodes.hxx>
38 
39 using namespace formula;
40 using ::std::pair;
41 
42 // ScRangeData
43 
45  const OUString& rName,
46  const OUString& rSymbol,
47  const ScAddress& rAddress,
48  Type nType,
49  const FormulaGrammar::Grammar eGrammar ) :
50  aName ( rName ),
51  aUpperName ( ScGlobal::getCharClass().uppercase( rName ) ),
52  aPos ( rAddress ),
53  eType ( nType ),
54  rDoc ( rDok ),
55  eTempGrammar( eGrammar ),
56  nIndex ( 0 ),
57  bModified ( false )
58 {
59  if (!rSymbol.isEmpty())
60  {
61  // Let the compiler set an error on unknown names for a subsequent
62  // CompileUnresolvedXML().
63  const bool bImporting = rDoc.IsImportingXML();
64  CompileRangeData( rSymbol, bImporting);
65  if (bImporting)
67  }
68  else
69  {
70  // #i63513#/#i65690# don't leave pCode as NULL.
71  // Copy ctor default-constructs pCode if it was NULL, so it's initialized here, too,
72  // to ensure same behavior if unnecessary copying is left out.
73 
74  pCode.reset( new ScTokenArray(rDoc) );
75  pCode->SetFromRangeName(true);
76  }
77 }
78 
80  const OUString& rName,
81  const ScTokenArray& rArr,
82  const ScAddress& rAddress,
83  Type nType ) :
84  aName ( rName ),
85  aUpperName ( ScGlobal::getCharClass().uppercase( rName ) ),
86  pCode ( new ScTokenArray( rArr ) ),
87  aPos ( rAddress ),
88  eType ( nType ),
89  rDoc ( rDok ),
90  eTempGrammar( FormulaGrammar::GRAM_UNSPECIFIED ),
91  nIndex ( 0 ),
92  bModified ( false )
93 {
94  pCode->SetFromRangeName(true);
95  InitCode();
96 }
97 
99  const OUString& rName,
100  const ScAddress& rTarget ) :
101  aName ( rName ),
102  aUpperName ( ScGlobal::getCharClass().uppercase( rName ) ),
103  pCode ( new ScTokenArray(rDok) ),
104  aPos ( rTarget ),
105  eType ( Type::Name ),
106  rDoc ( rDok ),
107  eTempGrammar( FormulaGrammar::GRAM_UNSPECIFIED ),
108  nIndex ( 0 ),
109  bModified ( false )
110 {
111  ScSingleRefData aRefData;
112  aRefData.InitAddress( rTarget );
113  aRefData.SetFlag3D( true );
114  pCode->AddSingleReference( aRefData );
115  pCode->SetFromRangeName(true);
116  ScCompiler aComp( rDoc, aPos, *pCode, rDoc.GetGrammar() );
117  aComp.CompileTokenArray();
118  if ( pCode->GetCodeError() == FormulaError::NONE )
119  eType |= Type::AbsPos;
120 }
121 
122 ScRangeData::ScRangeData(const ScRangeData& rScRangeData, ScDocument* pDocument, const ScAddress* pPos) :
123  aName (rScRangeData.aName),
124  aUpperName (rScRangeData.aUpperName),
125  pCode (rScRangeData.pCode ? rScRangeData.pCode->Clone().release() : new ScTokenArray(*pDocument)), // make real copy (not copy-ctor)
126  aPos (pPos ? *pPos : rScRangeData.aPos),
127  eType (rScRangeData.eType),
128  rDoc (pDocument ? *pDocument : rScRangeData.rDoc),
129  eTempGrammar(rScRangeData.eTempGrammar),
130  nIndex (rScRangeData.nIndex),
131  bModified (rScRangeData.bModified)
132 {
133  pCode->SetFromRangeName(true);
134 }
135 
137 {
138 }
139 
140 void ScRangeData::CompileRangeData( const OUString& rSymbol, bool bSetError )
141 {
142  if (eTempGrammar == FormulaGrammar::GRAM_UNSPECIFIED)
143  {
144  OSL_FAIL( "ScRangeData::CompileRangeData: unspecified grammar");
145  // Anything is almost as bad as this, but we might have the best choice
146  // if not loading documents.
147  eTempGrammar = FormulaGrammar::GRAM_NATIVE;
148  }
149 
150  ScCompiler aComp( rDoc, aPos, eTempGrammar );
151  if (bSetError)
153  pCode = aComp.CompileString( rSymbol );
154  pCode->SetFromRangeName(true);
155  if( pCode->GetCodeError() != FormulaError::NONE )
156  return;
157 
159  FormulaToken* p = aIter.GetNextReference();
160  if( p )
161  {
162  // first token is a reference
163  /* FIXME: wouldn't that need a check if it's exactly one reference? */
164  if( p->GetType() == svSingleRef )
166  else
168  }
169  // For manual input set an error for an incomplete formula.
170  if (!rDoc.IsImportingXML())
171  {
172  aComp.CompileTokenArray();
173  pCode->DelRPN();
174  }
175 }
176 
178 {
179  if (pCode->GetCodeError() == FormulaError::NoName)
180  {
181  // Reconstruct the symbol/formula and then recompile.
182  OUString aSymbol;
183  rCxt.setGrammar(eTempGrammar);
184  ScCompiler aComp(rCxt, aPos, *pCode);
185  aComp.CreateStringFromTokenArray( aSymbol);
186  // Don't let the compiler set an error for unknown names on final
187  // compile, errors are handled by the interpreter thereafter.
188  CompileRangeData( aSymbol, false);
190  }
191 }
192 
193 #if DEBUG_FORMULA_COMPILER
194 void ScRangeData::Dump() const
195 {
196  cout << "-- ScRangeData" << endl;
197  cout << " name: " << aName << endl;
198  cout << " ref position: (col=" << aPos.Col() << ", row=" << aPos.Row() << ", sheet=" << aPos.Tab() << ")" << endl;
199 
200  if (pCode)
201  pCode->Dump();
202 }
203 #endif
204 
206 {
207  // set a position that allows "absoluting" of all relative references
208  // in CalcAbsIfRel without errors
209 
210  OSL_ENSURE(aPos == ScAddress(), "position will go lost now");
211 
212  SCCOL nMinCol = 0;
213  SCROW nMinRow = 0;
214  SCTAB nMinTab = 0;
215 
218  while ( ( t = aIter.GetNextReference() ) != nullptr )
219  {
220  ScSingleRefData& rRef1 = *t->GetSingleRef();
221  if ( rRef1.IsColRel() && rRef1.Col() < nMinCol )
222  nMinCol = rRef1.Col();
223  if ( rRef1.IsRowRel() && rRef1.Row() < nMinRow )
224  nMinRow = rRef1.Row();
225  if ( rRef1.IsTabRel() && rRef1.Tab() < nMinTab )
226  nMinTab = rRef1.Tab();
227 
228  if ( t->GetType() == svDoubleRef )
229  {
230  ScSingleRefData& rRef2 = t->GetDoubleRef()->Ref2;
231  if ( rRef2.IsColRel() && rRef2.Col() < nMinCol )
232  nMinCol = rRef2.Col();
233  if ( rRef2.IsRowRel() && rRef2.Row() < nMinRow )
234  nMinRow = rRef2.Row();
235  if ( rRef2.IsTabRel() && rRef2.Tab() < nMinTab )
236  nMinTab = rRef2.Tab();
237  }
238  }
239 
240  aPos = ScAddress( static_cast<SCCOL>(-nMinCol), static_cast<SCROW>(-nMinRow), static_cast<SCTAB>(-nMinTab) );
241 }
242 
243 OUString ScRangeData::GetSymbol( const FormulaGrammar::Grammar eGrammar ) const
244 {
245  ScCompiler aComp(rDoc, aPos, *pCode, eGrammar);
246  OUString symbol;
247  aComp.CreateStringFromTokenArray( symbol );
248  return symbol;
249 }
250 
251 OUString ScRangeData::GetSymbol( const ScAddress& rPos, const FormulaGrammar::Grammar eGrammar ) const
252 {
253  OUString aStr;
254  ScCompiler aComp(rDoc, rPos, *pCode, eGrammar);
255  aComp.CreateStringFromTokenArray( aStr );
256  return aStr;
257 }
258 
259 void ScRangeData::UpdateSymbol( OUStringBuffer& rBuffer, const ScAddress& rPos )
260 {
261  std::unique_ptr<ScTokenArray> pTemp( pCode->Clone() );
263  aComp.MoveRelWrap();
264  aComp.CreateStringFromTokenArray( rBuffer );
265 }
266 
268 {
269  sc::RefUpdateResult aRes = pCode->AdjustReferenceInName(rCxt, aPos);
271  if (aRes.mbReferenceModified)
272  rCxt.maUpdatedNames.setUpdatedName(nLocalTab, nIndex);
273 }
274 
275 void ScRangeData::UpdateTranspose( const ScRange& rSource, const ScAddress& rDest )
276 {
277  bool bChanged = false;
278 
281 
282  while ( ( t = aIter.GetNextReference() ) != nullptr )
283  {
284  if( t->GetType() != svIndex )
285  {
286  SingleDoubleRefModifier aMod( *t );
287  ScComplexRefData& rRef = aMod.Ref();
288  // Update only absolute references
289  if (!rRef.Ref1.IsColRel() && !rRef.Ref1.IsRowRel() &&
290  (!rRef.Ref1.IsFlag3D() || !rRef.Ref1.IsTabRel()) &&
291  ( t->GetType() == svSingleRef ||
292  (!rRef.Ref2.IsColRel() && !rRef.Ref2.IsRowRel() &&
293  (!rRef.Ref2.IsFlag3D() || !rRef.Ref2.IsTabRel()))))
294  {
295  ScRange aAbs = rRef.toAbs(rDoc, aPos);
296  // Check if the absolute reference of this range is pointing to the transposed source
297  if (ScRefUpdate::UpdateTranspose(rDoc, rSource, rDest, aAbs) != UR_NOTHING)
298  {
299  rRef.SetRange(rDoc.GetSheetLimits(), aAbs, aPos);
300  bChanged = true;
301  }
302  }
303  }
304  }
305 
306  bModified = bChanged;
307 }
308 
309 void ScRangeData::UpdateGrow( const ScRange& rArea, SCCOL nGrowX, SCROW nGrowY )
310 {
311  bool bChanged = false;
312 
315 
316  while ( ( t = aIter.GetNextReference() ) != nullptr )
317  {
318  if( t->GetType() != svIndex )
319  {
320  SingleDoubleRefModifier aMod( *t );
321  ScComplexRefData& rRef = aMod.Ref();
322  if (!rRef.Ref1.IsColRel() && !rRef.Ref1.IsRowRel() &&
323  (!rRef.Ref1.IsFlag3D() || !rRef.Ref1.IsTabRel()) &&
324  ( t->GetType() == svSingleRef ||
325  (!rRef.Ref2.IsColRel() && !rRef.Ref2.IsRowRel() &&
326  (!rRef.Ref2.IsFlag3D() || !rRef.Ref2.IsTabRel()))))
327  {
328  ScRange aAbs = rRef.toAbs(rDoc, aPos);
329  if (ScRefUpdate::UpdateGrow(rArea, nGrowX, nGrowY, aAbs) != UR_NOTHING)
330  {
331  rRef.SetRange(rDoc.GetSheetLimits(), aAbs, aPos);
332  bChanged = true;
333  }
334  }
335  }
336  }
337 
338  bModified = bChanged; // has to be evaluated immediately afterwards
339 }
340 
341 bool ScRangeData::operator== (const ScRangeData& rData) const // for Undo
342 {
343  if ( nIndex != rData.nIndex ||
344  aName != rData.aName ||
345  aPos != rData.aPos ||
346  eType != rData.eType ) return false;
347 
348  sal_uInt16 nLen = pCode->GetLen();
349  if ( nLen != rData.pCode->GetLen() ) return false;
350 
351  FormulaToken** ppThis = pCode->GetArray();
352  FormulaToken** ppOther = rData.pCode->GetArray();
353 
354  for ( sal_uInt16 i=0; i<nLen; i++ )
355  if ( ppThis[i] != ppOther[i] && !(*ppThis[i] == *ppOther[i]) )
356  return false;
357 
358  return true;
359 }
360 
361 bool ScRangeData::IsRangeAtBlock( const ScRange& rBlock ) const
362 {
363  bool bRet = false;
364  ScRange aRange;
365  if ( IsReference(aRange) )
366  bRet = ( rBlock == aRange );
367  return bRet;
368 }
369 
370 bool ScRangeData::IsReference( ScRange& rRange ) const
371 {
372  if ( (eType & ( Type::AbsArea | Type::RefArea | Type::AbsPos )) && pCode )
373  return pCode->IsReference(rRange, aPos);
374 
375  return false;
376 }
377 
378 bool ScRangeData::IsReference( ScRange& rRange, const ScAddress& rPos ) const
379 {
380  if ( (eType & ( Type::AbsArea | Type::RefArea | Type::AbsPos ) ) && pCode )
381  return pCode->IsReference(rRange, rPos);
382 
383  return false;
384 }
385 
387 {
388  if ( (eType & ( Type::AbsArea | Type::RefArea | Type::AbsPos ) ) && pCode )
389  return pCode->IsValidReference(rRange, aPos);
390 
391  return false;
392 }
393 
395 {
396  sc::RefUpdateResult aRes = pCode->AdjustReferenceOnInsertedTab(rCxt, aPos);
397  if (aRes.mbReferenceModified)
398  rCxt.maUpdatedNames.setUpdatedName(nLocalTab, nIndex);
399 
400  if (rCxt.mnInsertPos <= aPos.Tab())
401  aPos.IncTab(rCxt.mnSheets);
402 }
403 
405 {
406  sc::RefUpdateResult aRes = pCode->AdjustReferenceOnDeletedTab(rCxt, aPos);
407  if (aRes.mbReferenceModified)
408  rCxt.maUpdatedNames.setUpdatedName(nLocalTab, nIndex);
409 
410  if (rCxt.mnDeletePos <= aPos.Tab())
411  aPos.IncTab(-rCxt.mnSheets);
412 }
413 
415 {
416  sc::RefUpdateResult aRes = pCode->AdjustReferenceOnMovedTab(rCxt, aPos);
417  if (aRes.mbReferenceModified)
418  rCxt.maUpdatedNames.setUpdatedName(nLocalTab, nIndex);
419 
420  aPos.SetTab(rCxt.getNewTab(aPos.Tab()));
421 }
422 
423 void ScRangeData::MakeValidName( const ScDocument& rDoc, OUString& rName )
424 {
425 
426  // strip leading invalid characters
427  sal_Int32 nPos = 0;
428  sal_Int32 nLen = rName.getLength();
429  while ( nPos < nLen && !ScCompiler::IsCharFlagAllConventions( rName, nPos, ScCharFlags::Name) )
430  ++nPos;
431  if ( nPos>0 )
432  rName = rName.copy(nPos);
433 
434  // if the first character is an invalid start character, precede with '_'
435  if ( !rName.isEmpty() && !ScCompiler::IsCharFlagAllConventions( rName, 0, ScCharFlags::CharName ) )
436  rName = "_" + rName;
437 
438  // replace invalid with '_'
439  nLen = rName.getLength();
440  for (nPos=0; nPos<nLen; nPos++)
441  {
443  rName = rName.replaceAt( nPos, 1, u"_" );
444  }
445 
446  // Ensure that the proposed name is not a reference under any convention,
447  // same as in IsNameValid()
448  ScAddress aAddr;
449  ScRange aRange;
450  for (int nConv = FormulaGrammar::CONV_UNSPECIFIED; ++nConv < FormulaGrammar::CONV_LAST; )
451  {
452  ScAddress::Details details( static_cast<FormulaGrammar::AddressConvention>( nConv ) );
453  // Don't check Parse on VALID, any partial only VALID may result in
454  // #REF! during compile later!
455  while (aRange.Parse(rName, rDoc, details) != ScRefFlags::ZERO ||
456  aAddr.Parse(rName, rDoc, details) != ScRefFlags::ZERO)
457  {
458  // Range Parse is partially valid also with invalid sheet name,
459  // Address Parse ditto, during compile name would generate a #REF!
460  if ( rName.indexOf( '.' ) != -1 )
461  rName = rName.replaceFirst( ".", "_" );
462  else
463  rName = "_" + rName;
464  }
465  }
466 }
467 
469 {
470  /* XXX If changed, sc/source/filter/ftools/ftools.cxx
471  * ScfTools::ConvertToScDefinedName needs to be changed too. */
472  char const a('.');
473  if (rName.indexOf(a) != -1)
475  sal_Int32 nPos = 0;
476  sal_Int32 nLen = rName.getLength();
477  if ( !nLen || !ScCompiler::IsCharFlagAllConventions( rName, nPos++, ScCharFlags::CharName ) )
479  while ( nPos < nLen )
480  {
483  }
484  ScAddress aAddr;
485  ScRange aRange;
486  for (int nConv = FormulaGrammar::CONV_UNSPECIFIED; ++nConv < FormulaGrammar::CONV_LAST; )
487  {
488  ScAddress::Details details( static_cast<FormulaGrammar::AddressConvention>( nConv ) );
489  // Don't check Parse on VALID, any partial only VALID may result in
490  // #REF! during compile later!
491  if (aRange.Parse(rName, rDoc, details) != ScRefFlags::ZERO ||
492  aAddr.Parse(rName, rDoc, details) != ScRefFlags::ZERO )
493  {
495  }
496  }
498 }
499 
501 {
502  // Similar to part of IsNameValid(), but only check if the name is a valid address.
503  ScAddress aAddr;
504  for (int nConv = FormulaGrammar::CONV_UNSPECIFIED; ++nConv < FormulaGrammar::CONV_LAST; )
505  {
506  ScAddress::Details details( static_cast<FormulaGrammar::AddressConvention>( nConv ) );
507  // Don't check Parse on VALID, any partial only VALID may result in
508  // #REF! during compile later!
509  if(aAddr.Parse(aUpperName, rDoc, details) != ScRefFlags::ZERO)
510  return true;
511  }
512  return false;
513 }
514 
516 {
517  return pCode ? pCode->GetCodeError() : FormulaError::NONE;
518 }
519 
521 {
522  return pCode->HasReferences();
523 }
524 
525 sal_uInt32 ScRangeData::GetUnoType() const
526 {
527  sal_uInt32 nUnoType = 0;
528  if ( HasType(Type::Criteria) ) nUnoType |= css::sheet::NamedRangeFlag::FILTER_CRITERIA;
529  if ( HasType(Type::PrintArea) ) nUnoType |= css::sheet::NamedRangeFlag::PRINT_AREA;
532  return nUnoType;
533 }
534 
536 {
537  // try to make sure all relative references and the reference position
538  // are within existing tables, so they can be represented as text
539  // (if the range of used tables is more than the existing tables,
540  // the result may still contain invalid tables, because the relative
541  // references aren't changed so formulas stay the same)
542 
543  // find range of used tables
544 
545  SCTAB nMinTab = aPos.Tab();
546  SCTAB nMaxTab = nMinTab;
549  while ( ( t = aIter.GetNextReference() ) != nullptr )
550  {
551  ScSingleRefData& rRef1 = *t->GetSingleRef();
552  ScAddress aAbs = rRef1.toAbs(rDoc, aPos);
553  if ( rRef1.IsTabRel() && !rRef1.IsTabDeleted() )
554  {
555  if (aAbs.Tab() < nMinTab)
556  nMinTab = aAbs.Tab();
557  if (aAbs.Tab() > nMaxTab)
558  nMaxTab = aAbs.Tab();
559  }
560  if ( t->GetType() == svDoubleRef )
561  {
562  ScSingleRefData& rRef2 = t->GetDoubleRef()->Ref2;
563  aAbs = rRef2.toAbs(rDoc, aPos);
564  if ( rRef2.IsTabRel() && !rRef2.IsTabDeleted() )
565  {
566  if (aAbs.Tab() < nMinTab)
567  nMinTab = aAbs.Tab();
568  if (aAbs.Tab() > nMaxTab)
569  nMaxTab = aAbs.Tab();
570  }
571  }
572  }
573 
574  SCTAB nTabCount = rDoc.GetTableCount();
575  if ( nMaxTab < nTabCount || nMinTab <= 0 )
576  return;
577 
578  // move position and relative tab refs
579  // The formulas that use the name are not changed by this
580 
581  SCTAB nMove = nMinTab;
582  ScAddress aOldPos = aPos;
583  aPos.SetTab( aPos.Tab() - nMove );
584 
585  aIter.Reset();
586  while ( ( t = aIter.GetNextReference() ) != nullptr )
587  {
588  switch (t->GetType())
589  {
590  case svSingleRef:
591  {
592  ScSingleRefData& rRef = *t->GetSingleRef();
593  if (!rRef.IsTabDeleted())
594  {
595  ScAddress aAbs = rRef.toAbs(rDoc, aOldPos);
596  rRef.SetAddress(rDoc.GetSheetLimits(), aAbs, aPos);
597  }
598  }
599  break;
600  case svDoubleRef:
601  {
602  ScComplexRefData& rRef = *t->GetDoubleRef();
603  if (!rRef.Ref1.IsTabDeleted())
604  {
605  ScAddress aAbs = rRef.Ref1.toAbs(rDoc, aOldPos);
606  rRef.Ref1.SetAddress(rDoc.GetSheetLimits(), aAbs, aPos);
607  }
608  if (!rRef.Ref2.IsTabDeleted())
609  {
610  ScAddress aAbs = rRef.Ref2.toAbs(rDoc, aOldPos);
611  rRef.Ref2.SetAddress(rDoc.GetSheetLimits(), aAbs, aPos);
612  }
613  }
614  break;
615  default:
616  ;
617  }
618  }
619 }
620 
622 {
623  pCode.reset(new ScTokenArray( rArr ));
624  pCode->SetFromRangeName(true);
625  InitCode();
626 }
627 
629 {
630  if( pCode->GetCodeError() == FormulaError::NONE )
631  {
633  if( p ) // exact one reference at first
634  {
635  if( p->GetType() == svSingleRef )
637  else
639  }
640  }
641 }
642 
643 extern "C"
644 int ScRangeData_QsortNameCompare( const void* p1, const void* p2 )
645 {
646  return static_cast<int>(ScGlobal::GetCollator().compareString(
647  (*static_cast<const ScRangeData* const *>(p1))->GetName(),
648  (*static_cast<const ScRangeData* const *>(p2))->GetName() ));
649 }
650 
651 namespace {
652 
656 class MatchByRange
657 {
658  const ScRange& mrRange;
659 public:
660  explicit MatchByRange(const ScRange& rRange) : mrRange(rRange) {}
661  bool operator() (std::pair<OUString const, std::unique_ptr<ScRangeData>> const& r) const
662  {
663  return r.second->IsRangeAtBlock(mrRange);
664  }
665 };
666 
667 }
668 
670  : mHasPossibleAddressConflict(false)
671  , mHasPossibleAddressConflictDirty(false)
672 {
673 }
674 
676  : mHasPossibleAddressConflict( r.mHasPossibleAddressConflict )
677  , mHasPossibleAddressConflictDirty( r.mHasPossibleAddressConflictDirty )
678 {
679  for (auto const& it : r.m_Data)
680  {
681  m_Data.insert(std::make_pair(it.first, std::make_unique<ScRangeData>(*it.second)));
682  }
683  // std::map was cloned, so each collection needs its own index to data.
684  maIndexToData.resize( r.maIndexToData.size(), nullptr);
685  for (auto const& itr : m_Data)
686  {
687  size_t nPos = itr.second->GetIndex() - 1;
688  if (nPos >= maIndexToData.size())
689  {
690  OSL_FAIL( "ScRangeName copy-ctor: maIndexToData size doesn't fit");
691  maIndexToData.resize(nPos+1, nullptr);
692  }
693  maIndexToData[nPos] = itr.second.get();
694  }
695 }
696 
697 const ScRangeData* ScRangeName::findByRange(const ScRange& rRange) const
698 {
699  DataType::const_iterator itr = std::find_if(
700  m_Data.begin(), m_Data.end(), MatchByRange(rRange));
701  return itr == m_Data.end() ? nullptr : itr->second.get();
702 }
703 
705 {
706  DataType::iterator itr = m_Data.find(rName);
707  return itr == m_Data.end() ? nullptr : itr->second.get();
708 }
709 
710 const ScRangeData* ScRangeName::findByUpperName(const OUString& rName) const
711 {
712  DataType::const_iterator itr = m_Data.find(rName);
713  return itr == m_Data.end() ? nullptr : itr->second.get();
714 }
715 
717 {
718  if (!i)
719  // index should never be zero.
720  return nullptr;
721 
722  size_t nPos = i - 1;
723  return nPos < maIndexToData.size() ? maIndexToData[nPos] : nullptr;
724 }
725 
727 {
728  if (rCxt.meMode == URM_COPY)
729  // Copying cells does not modify named expressions.
730  return;
731 
732  for (auto const& itr : m_Data)
733  {
734  itr.second->UpdateReference(rCxt, nLocalTab);
735  }
736 }
737 
739 {
740  for (auto const& itr : m_Data)
741  {
742  itr.second->UpdateInsertTab(rCxt, nLocalTab);
743  }
744 }
745 
747 {
748  for (auto const& itr : m_Data)
749  {
750  itr.second->UpdateDeleteTab(rCxt, nLocalTab);
751  }
752 }
753 
755 {
756  for (auto const& itr : m_Data)
757  {
758  itr.second->UpdateMoveTab(rCxt, nLocalTab);
759  }
760 }
761 
762 void ScRangeName::UpdateTranspose(const ScRange& rSource, const ScAddress& rDest)
763 {
764  for (auto const& itr : m_Data)
765  {
766  itr.second->UpdateTranspose(rSource, rDest);
767  }
768 }
769 
770 void ScRangeName::UpdateGrow(const ScRange& rArea, SCCOL nGrowX, SCROW nGrowY)
771 {
772  for (auto const& itr : m_Data)
773  {
774  itr.second->UpdateGrow(rArea, nGrowX, nGrowY);
775  }
776 }
777 
779 {
780  for (auto const& itr : m_Data)
781  {
782  itr.second->CompileUnresolvedXML(rCxt);
783  }
784 }
785 
786 void ScRangeName::CopyUsedNames( const SCTAB nLocalTab, const SCTAB nOldTab, const SCTAB nNewTab,
787  const ScDocument& rOldDoc, ScDocument& rNewDoc, const bool bGlobalNamesToLocal ) const
788 {
789  for (auto const& itr : m_Data)
790  {
791  SCTAB nSheet = (nLocalTab < 0) ? nLocalTab : nOldTab;
792  sal_uInt16 nIndex = itr.second->GetIndex();
793  ScAddress aOldPos( itr.second->GetPos());
794  aOldPos.SetTab( nOldTab);
795  ScAddress aNewPos( aOldPos);
796  aNewPos.SetTab( nNewTab);
797  ScRangeData* pRangeData = nullptr;
798  rOldDoc.CopyAdjustRangeName( nSheet, nIndex, pRangeData, rNewDoc, aNewPos, aOldPos, bGlobalNamesToLocal, false);
799  }
800 }
801 
802 bool ScRangeName::insert( ScRangeData* p, bool bReuseFreeIndex )
803 {
804  if (!p)
805  return false;
806 
807  if (!p->GetIndex())
808  {
809  // Assign a new index. An index must be unique and is never 0.
810  if (bReuseFreeIndex)
811  {
812  IndexDataType::iterator itr = std::find(
813  maIndexToData.begin(), maIndexToData.end(), static_cast<ScRangeData*>(nullptr));
814  if (itr != maIndexToData.end())
815  {
816  // Empty slot exists. Re-use it.
817  size_t nPos = std::distance(maIndexToData.begin(), itr);
818  p->SetIndex(nPos + 1);
819  }
820  else
821  // No empty slot. Append it to the end.
822  p->SetIndex(maIndexToData.size() + 1);
823  }
824  else
825  {
826  p->SetIndex(maIndexToData.size() + 1);
827  }
828  }
829 
830  OUString aName(p->GetUpperName());
831  erase(aName); // ptr_map won't insert it if a duplicate name exists.
832  pair<DataType::iterator, bool> r =
833  m_Data.insert(std::make_pair(aName, std::unique_ptr<ScRangeData>(p)));
834  if (r.second)
835  {
836  // Data inserted. Store its index for mapping.
837  size_t nPos = p->GetIndex() - 1;
838  if (nPos >= maIndexToData.size())
839  maIndexToData.resize(nPos+1, nullptr);
840  maIndexToData[nPos] = p;
842  }
843  return r.second;
844 }
845 
847 {
848  erase(r.GetUpperName());
849 }
850 
851 void ScRangeName::erase(const OUString& rName)
852 {
853  DataType::const_iterator itr = m_Data.find(rName);
854  if (itr != m_Data.end())
855  erase(itr);
856 }
857 
859 {
860  sal_uInt16 nIndex = itr->second->GetIndex();
861  m_Data.erase(itr);
862  OSL_ENSURE( 0 < nIndex && nIndex <= maIndexToData.size(), "ScRangeName::erase: bad index");
863  if (0 < nIndex && nIndex <= maIndexToData.size())
864  maIndexToData[nIndex-1] = nullptr;
867 }
868 
870 {
871  m_Data.clear();
872  maIndexToData.clear();
875 }
876 
878 {
881  for (auto const& itr : m_Data)
882  {
883  if( itr.second->HasPossibleAddressConflict())
884  {
886  return;
887  }
888  }
889 }
890 
892 {
893  return std::equal(m_Data.begin(), m_Data.end(), r.m_Data.begin(), r.m_Data.end(),
894  [](const DataType::value_type& lhs, const DataType::value_type& rhs) {
895  return (lhs.first == rhs.first) && (*lhs.second == *rhs.second);
896  });
897 }
898 
899 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
bool IsTabRel() const
Definition: refdata.hxx:69
SCCOL Col() const
Definition: refdata.cxx:247
sal_uInt32 GetUnoType() const
Definition: rangenam.cxx:525
void UpdateDeleteTab(sc::RefUpdateDeleteTabContext &rCxt, SCTAB nLocalTab=-1)
Definition: rangenam.cxx:746
sal_Int32 nIndex
bool IsTabDeleted() const
Definition: refdata.hxx:86
void CompileUnresolvedXML(sc::CompileFormulaContext &rCxt)
Compile those names that couldn't be resolved during loading and inserting because they may have refe...
Definition: rangenam.cxx:778
sal_Int32 compareString(const OUString &s1, const OUString &s2) const
void IncTab(SCTAB nDelta=1)
Definition: address.hxx:320
SCROW Row() const
Definition: address.hxx:274
SC_DLLPUBLIC ScRange toAbs(const ScSheetLimits &rLimits, const ScAddress &rPos) const
Definition: refdata.cxx:493
SC_DLLPUBLIC void SetCode(const ScTokenArray &)
Definition: rangenam.cxx:621
Single reference (one address) into the sheet.
Definition: refdata.hxx:29
SC_DLLPUBLIC OUString GetSymbol(const formula::FormulaGrammar::Grammar eGrammar=formula::FormulaGrammar::GRAM_DEFAULT) const
Definition: rangenam.cxx:243
const OUString & GetUpperName() const
Definition: rangenam.hxx:112
ScAddress toAbs(const ScSheetLimits &rLimits, const ScAddress &rPos) const
Definition: refdata.cxx:193
sal_uInt16 GetIndex() const
Definition: rangenam.hxx:116
Context for reference update during shifting, moving or copying of cell ranges.
static ScRefUpdateRes UpdateGrow(const ScRange &rArea, SCCOL nGrowX, SCROW nGrowY, ScRange &rRef)
Definition: refupdat.cxx:562
void UpdateTranspose(const ScRange &rSource, const ScAddress &rDest)
Definition: rangenam.cxx:275
std::unique_ptr< ScTokenArray > CompileString(const OUString &rFormula)
Tokenize formula expression string into an array of tokens.
Definition: compiler.cxx:4661
SCTAB getNewTab(SCTAB nOldTab) const
const ContentProperties & rData
bool operator==(const ScRangeName &r) const
Definition: rangenam.cxx:891
static void MakeValidName(const ScDocument &rDoc, OUString &rName)
Definition: rangenam.cxx:423
bool HasPossibleAddressConflict() const
Definition: rangenam.cxx:500
void clear()
Definition: rangenam.cxx:869
void CompileUnresolvedXML(sc::CompileFormulaContext &rCxt)
Definition: rangenam.cxx:177
OUString Name
SC_DLLPUBLIC formula::FormulaGrammar::Grammar GetGrammar() const
Definition: document.hxx:1007
void CreateStringFromTokenArray(OUString &rFormula)
IndexDataType maIndexToData
Definition: rangenam.hxx:191
void setUpdatedName(SCTAB nTab, sal_uInt16 nIndex)
SC_DLLPUBLIC void CheckLinkFormulaNeedingCheck(const ScTokenArray &rCode)
Check token array and set link check if ocDde/ocWebservice is contained.
Definition: documen8.cxx:1154
DataType::const_iterator const_iterator
Definition: rangenam.hxx:203
formula::FormulaGrammar::Grammar eTempGrammar
Definition: rangenam.hxx:77
SC_DLLPUBLIC SCTAB GetTableCount() const
Definition: document.cxx:315
DataType m_Data
Definition: rangenam.hxx:190
virtual const ScSingleRefData * GetSingleRef() const
void UpdateGrow(const ScRange &rArea, SCCOL nGrowX, SCROW nGrowY)
Definition: rangenam.cxx:309
void CopyUsedNames(const SCTAB nLocalTab, const SCTAB nOldTab, const SCTAB nNewTab, const ScDocument &rOldDoc, ScDocument &rNewDoc, const bool bGlobalNamesToLocal) const
Copy names while copying a sheet if they reference the sheet to be copied.
Definition: rangenam.cxx:786
void UpdateGrow(const ScRange &rArea, SCCOL nGrowX, SCROW nGrowY)
Definition: rangenam.cxx:770
SCTAB Tab() const
Definition: address.hxx:283
SC_DLLPUBLIC void GuessPosition()
Definition: rangenam.cxx:205
bool IsColRel() const
Definition: refdata.hxx:65
virtual OUString GetName() const override
OUString aName
Definition: rangenam.hxx:69
void UpdateInsertTab(sc::RefUpdateInsertTabContext &rCxt, SCTAB nLocalTab)
Definition: rangenam.cxx:394
void UpdateReference(sc::RefUpdateContext &rCxt, SCTAB nLocalTab=-1)
Definition: rangenam.cxx:726
bool HasReferences() const
Definition: rangenam.cxx:520
std::unique_ptr< ScTokenArray > pCode
Definition: rangenam.hxx:73
void UpdateInsertTab(sc::RefUpdateInsertTabContext &rCxt, SCTAB nLocalTab=-1)
Definition: rangenam.cxx:738
DocumentType eType
bool IsRangeAtBlock(const ScRange &) const
Definition: rangenam.cxx:361
void SetTab(SCTAB nTabP)
Definition: address.hxx:295
SC_DLLPUBLIC ScRangeData * findByUpperName(const OUString &rName)
Definition: rangenam.cxx:704
SC_DLLPUBLIC const ScRangeData * findByRange(const ScRange &rRange) const
Definition: rangenam.cxx:697
bool IsImportingXML() const
Definition: document.hxx:2220
virtual const ScComplexRefData * GetDoubleRef() const
int i
Reference< XAnimationNode > Clone(const Reference< XAnimationNode > &xSourceNode, const SdPage *pSource, const SdPage *pTarget)
uno_Any a
UpdateRefMode meMode
update mode - insert/delete, copy, or move.
void UpdateTranspose(const ScRange &rSource, const ScAddress &rDest)
Definition: rangenam.cxx:762
void SetFlag3D(bool bVal)
Definition: refdata.hxx:89
int ScRangeData_QsortNameCompare(const void *p1, const void *p2)
Definition: rangenam.cxx:644
void InitAddress(const ScAddress &rAdr)
InitAddress: InitFlags and set address.
Definition: refdata.cxx:27
sal_Int16 SCCOL
Definition: types.hxx:21
ScSheetLimits & GetSheetLimits() const
Definition: document.hxx:896
ScSingleRefData Ref1
Definition: refdata.hxx:124
svIndex
static SC_DLLPUBLIC IsNameValidType IsNameValid(const OUString &rName, const ScDocument &rDoc)
Definition: rangenam.cxx:468
static bool IsCharFlagAllConventions(OUString const &rStr, sal_Int32 nPos, ScCharFlags nFlags)
If the character is allowed as tested by nFlags (SC_COMPILER_C_...
Definition: compiler.cxx:5184
ScSingleRefData Ref2
Definition: refdata.hxx:125
float u
OUString aUpperName
Definition: rangenam.hxx:70
bool IsRowRel() const
Definition: refdata.hxx:67
void UpdateMoveTab(sc::RefUpdateMoveTabContext &rCxt, SCTAB nLocalTab)
Definition: rangenam.cxx:414
ScAddress aPos
Definition: rangenam.hxx:74
SC_DLLPUBLIC ScRangeData * findByIndex(sal_uInt16 i) const
Definition: rangenam.cxx:716
void erase(const ScRangeData &r)
Definition: rangenam.cxx:846
void checkHasPossibleAddressConflict() const
Definition: rangenam.cxx:877
bool operator==(const ScRangeData &rData) const
Definition: rangenam.cxx:341
bool HasType(Type nType) const
Definition: rangenam.hxx:178
void CompileRangeData(const OUString &rSymbol, bool bSetError)
Definition: rangenam.cxx:140
SCTAB Tab() const
Definition: refdata.cxx:254
void setGrammar(formula::FormulaGrammar::Grammar eGram)
ScComplexRefData & Ref()
Definition: token.hxx:437
Reference not affected, no change at all.
Definition: refupdat.hxx:31
svSingleRef
bool IsFlag3D() const
Definition: refdata.hxx:90
FormulaError
void UpdateMoveTab(sc::RefUpdateMoveTabContext &rCxt, SCTAB nLocalTab=-1)
Definition: rangenam.cxx:754
SCCOL Col() const
Definition: address.hxx:279
XPropertyListType t
ScDocument & rDoc
Definition: rangenam.hxx:76
svDoubleRef
sal_Int32 SCROW
Definition: types.hxx:17
void SetIndex(sal_uInt16 nInd)
Definition: rangenam.hxx:115
static ScRefUpdateRes UpdateTranspose(const ScDocument &rDoc, const ScRange &rSource, const ScAddress &rDest, ScRange &rRef)
Definition: refupdat.cxx:538
PyRef getCharClass(const Runtime &)
void UpdateDeleteTab(sc::RefUpdateDeleteTabContext &rCxt, SCTAB nLocalTab)
Definition: rangenam.cxx:404
static SC_DLLPUBLIC CollatorWrapper & GetCollator()
case-insensitive collator
Definition: global.cxx:1055
sal_uInt16 nIndex
Definition: rangenam.hxx:78
bool mHasPossibleAddressConflictDirty
Definition: rangenam.hxx:195
SvStream & endl(SvStream &rStr)
OUString aName
bool mHasPossibleAddressConflict
Definition: rangenam.hxx:194
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
void SetRange(const ScSheetLimits &rLimits, const ScRange &rRange, const ScAddress &rPos)
Set a new range, assuming that the ordering of the range matches the ordering of the reference data f...
Definition: refdata.cxx:498
SCROW Row() const
Definition: refdata.cxx:240
void * p
QPRO_FUNC_TYPE nType
Definition: qproform.cxx:398
void SetExtendedErrorDetection(ExtendedErrorDetection eVal)
Definition: compiler.hxx:472
void SetAddress(const ScSheetLimits &rLimits, const ScAddress &rAddr, const ScAddress &rPos)
Definition: refdata.cxx:213
SC_DLLPUBLIC FormulaError GetErrCode() const
Definition: rangenam.cxx:515
bool mbReferenceModified
This flag indicates whether any reference in the token array has been modified.
SC_DLLPUBLIC bool IsValidReference(ScRange &rRef) const
Definition: rangenam.cxx:386
SC_DLLPUBLIC bool IsReference(ScRange &rRef) const
Definition: rangenam.cxx:370
Complex reference (a range) into the sheet.
Definition: refdata.hxx:122
Type eType
Definition: rangenam.hxx:75
void InitCode()
Definition: rangenam.cxx:628
bool bModified
Definition: rangenam.hxx:79
void UpdateSymbol(OUStringBuffer &rBuffer, const ScAddress &)
Definition: rangenam.cxx:259
SC_DLLPUBLIC ScRefFlags Parse(const OUString &, const ScDocument &, const Details &rDetails=detailsOOOa1, ExternalInfo *pExtInfo=nullptr, const css::uno::Sequence< css::sheet::ExternalLinkInfo > *pExternalLinks=nullptr, sal_Int32 *pSheetEndPos=nullptr, const OUString *pErrRef=nullptr)
Definition: address.cxx:1537
bool CopyAdjustRangeName(SCTAB &rSheet, sal_uInt16 &rIndex, ScRangeData *&rpRangeData, ScDocument &rNewDoc, const ScAddress &rNewPos, const ScAddress &rOldPos, const bool bGlobalNamesToLocal, const bool bUsedByFormula) const
If necessary (name references sheet rOldPos.Tab()) copy and adjust named expression/range from sheet-...
Definition: document10.cxx:801
UpdatedRangeNames maUpdatedNames
StackVar GetType() const
aStr
void ValidateTabRefs()
Definition: rangenam.cxx:535
SC_DLLPUBLIC ScRangeData(ScDocument &rDoc, const OUString &rName, const OUString &rSymbol, const ScAddress &rAdr=ScAddress(), Type nType=Type::Name, const formula::FormulaGrammar::Grammar eGrammar=formula::FormulaGrammar::GRAM_DEFAULT)
Definition: rangenam.cxx:44
SC_DLLPUBLIC bool insert(ScRangeData *p, bool bReuseFreeIndex=true)
Insert object into set.
Definition: rangenam.cxx:802
SC_DLLPUBLIC ~ScRangeData()
Definition: rangenam.cxx:136
sal_uInt16 nPos
sal_Int16 SCTAB
Definition: types.hxx:22
void UpdateReference(sc::RefUpdateContext &rCxt, SCTAB nLocalTab)
Definition: rangenam.cxx:267
bool m_bDetectedRangeSegmentation false