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