LibreOffice Module sc (master)  1
validat.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 <config_features.h>
21 
22 #include <validat.hxx>
23 #include <com/sun/star/sheet/TableValidationVisibility.hpp>
24 
25 #include <sfx2/app.hxx>
26 #include <sfx2/objsh.hxx>
27 #include <basic/sbmeth.hxx>
28 #include <basic/sbmod.hxx>
29 #include <basic/sbstar.hxx>
30 #include <basic/sberrors.hxx>
31 
32 #include <basic/sbx.hxx>
33 #include <svl/zforlist.hxx>
34 #include <svl/sharedstringpool.hxx>
35 #include <vcl/svapp.hxx>
36 #include <vcl/weld.hxx>
37 #include <rtl/math.hxx>
38 #include <osl/diagnose.h>
39 
40 #include <document.hxx>
41 #include <formulacell.hxx>
42 #include <patattr.hxx>
43 #include <globstr.hrc>
44 #include <scresid.hxx>
45 #include <rangenam.hxx>
46 #include <dbdata.hxx>
47 #include <typedstrdata.hxx>
48 #include <editutil.hxx>
49 #include <tokenarray.hxx>
50 #include <scmatrix.hxx>
51 #include <cellvalue.hxx>
52 #include <comphelper/lok.hxx>
53 #include <sfx2/lokhelper.hxx>
54 
55 #include <math.h>
56 #include <memory>
57 
58 using namespace formula;
59 
60 // Entries for validation (with only one condition)
61 
63  const OUString& rExpr1, const OUString& rExpr2,
64  ScDocument& rDocument, const ScAddress& rPos,
65  const OUString& rExprNmsp1, const OUString& rExprNmsp2,
66  FormulaGrammar::Grammar eGrammar1,
67  FormulaGrammar::Grammar eGrammar2 )
68  : ScConditionEntry( eOper, rExpr1, rExpr2, rDocument, rPos, rExprNmsp1,
69  rExprNmsp2, eGrammar1, eGrammar2 )
70  , nKey( 0 )
71  , eDataMode( eMode )
72  , bShowInput(false)
73  , bShowError(false)
74  , eErrorStyle( SC_VALERR_STOP )
75  , mnListType( css::sheet::TableValidationVisibility::UNSORTED )
76 {
77 }
78 
80  const ScTokenArray* pArr1, const ScTokenArray* pArr2,
81  ScDocument& rDocument, const ScAddress& rPos )
82  : ScConditionEntry( eOper, pArr1, pArr2, rDocument, rPos )
83  , nKey( 0 )
84  , eDataMode( eMode )
85  , bShowInput(false)
86  , bShowError(false)
87  , eErrorStyle( SC_VALERR_STOP )
88  , mnListType( css::sheet::TableValidationVisibility::UNSORTED )
89 {
90 }
91 
93  : ScConditionEntry( r )
94  , nKey( r.nKey )
95  , eDataMode( r.eDataMode )
96  , bShowInput( r.bShowInput )
97  , bShowError( r.bShowError )
98  , eErrorStyle( r.eErrorStyle )
99  , mnListType( r.mnListType )
100  , aInputTitle( r.aInputTitle )
101  , aInputMessage( r.aInputMessage )
102  , aErrorTitle( r.aErrorTitle )
103  , aErrorMessage( r.aErrorMessage )
104 {
105  // Formulae copied by RefCount
106 }
107 
109  : ScConditionEntry( rDocument, r )
110  , nKey( r.nKey )
111  , eDataMode( r.eDataMode )
112  , bShowInput( r.bShowInput )
113  , bShowError( r.bShowError )
114  , eErrorStyle( r.eErrorStyle )
115  , mnListType( r.mnListType )
116  , aInputTitle( r.aInputTitle )
117  , aInputMessage( r.aInputMessage )
118  , aErrorTitle( r.aErrorTitle )
119  , aErrorMessage( r.aErrorMessage )
120 {
121  // Formulae really copied
122 }
123 
125 {
126 }
127 
129 {
131  return EqualEntries( aDefault );
132 }
133 
135 {
136  // test same parameters (excluding Key)
137 
138  return ScConditionEntry::operator==(r) &&
139  eDataMode == r.eDataMode &&
140  bShowInput == r.bShowInput &&
141  bShowError == r.bShowError &&
142  eErrorStyle == r.eErrorStyle &&
143  mnListType == r.mnListType &&
144  aInputTitle == r.aInputTitle &&
146  aErrorTitle == r.aErrorTitle &&
148 }
149 
151 {
152  bShowInput = false;
153 }
154 
156 {
157  bShowError = false;
158 }
159 
160 void ScValidationData::SetInput( const OUString& rTitle, const OUString& rMsg )
161 {
162  bShowInput = true;
163  aInputTitle = rTitle;
164  aInputMessage = rMsg;
165 }
166 
167 void ScValidationData::SetError( const OUString& rTitle, const OUString& rMsg,
168  ScValidErrorStyle eStyle )
169 {
170  bShowError = true;
171  eErrorStyle = eStyle;
172  aErrorTitle = rTitle;
173  aErrorMessage = rMsg;
174 }
175 
176 bool ScValidationData::GetErrMsg( OUString& rTitle, OUString& rMsg,
177  ScValidErrorStyle& rStyle ) const
178 {
179  rTitle = aErrorTitle;
180  rMsg = aErrorMessage;
181  rStyle = eErrorStyle;
182  return bShowError;
183 }
184 
185 bool ScValidationData::DoScript( const ScAddress& rPos, const OUString& rInput,
186  ScFormulaCell* pCell, weld::Window* pParent ) const
187 {
188  ScDocument* pDocument = GetDocument();
189  SfxObjectShell* pDocSh = pDocument->GetDocumentShell();
190  if ( !pDocSh )
191  return false;
192 
193  bool bScriptReturnedFalse = false; // default: do not abort
194 
195  // Set up parameters
196  css::uno::Sequence< css::uno::Any > aParams(2);
197 
198  // 1) entered or calculated value
199  OUString aValStr = rInput;
200  double nValue;
201  bool bIsValue = false;
202  if ( pCell ) // if cell exists, call interpret
203  {
204  bIsValue = pCell->IsValue();
205  if ( bIsValue )
206  nValue = pCell->GetValue();
207  else
208  aValStr = pCell->GetString().getString();
209  }
210  if ( bIsValue )
211  aParams[0] <<= nValue;
212  else
213  aParams[0] <<= aValStr;
214 
215  // 2) Position of the cell
216  OUString aPosStr(rPos.Format(ScRefFlags::VALID | ScRefFlags::TAB_3D, pDocument, pDocument->GetAddressConvention()));
217  aParams[1] <<= aPosStr;
218 
219  // use link-update flag to prevent closing the document
220  // while the macro is running
221  bool bWasInLinkUpdate = pDocument->IsInLinkUpdate();
222  if ( !bWasInLinkUpdate )
223  pDocument->SetInLinkUpdate( true );
224 
225  if ( pCell )
226  pDocument->LockTable( rPos.Tab() );
227 
228  css::uno::Any aRet;
229  css::uno::Sequence< sal_Int16 > aOutArgsIndex;
230  css::uno::Sequence< css::uno::Any > aOutArgs;
231 
232  ErrCode eRet = pDocSh->CallXScript(
233  aErrorTitle, aParams, aRet, aOutArgsIndex, aOutArgs );
234 
235  if ( pCell )
236  pDocument->UnlockTable( rPos.Tab() );
237 
238  if ( !bWasInLinkUpdate )
239  pDocument->SetInLinkUpdate( false );
240 
241  // Check the return value from the script
242  // The contents of the cell get reset if the script returns false
243  bool bTmp = false;
244  if ( eRet == ERRCODE_NONE &&
245  aRet.getValueType() == cppu::UnoType<bool>::get() &&
246  ( aRet >>= bTmp ) &&
247  !bTmp )
248  {
249  bScriptReturnedFalse = true;
250  }
251 
252  if ( eRet == ERRCODE_BASIC_METHOD_NOT_FOUND && !pCell )
253  // Macro not found (only with input)
254  {
255  //TODO: different error message, if found, but not bAllowed ??
256  std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(pParent,
257  VclMessageType::Warning, VclButtonsType::Ok,
258  ScResId(STR_VALID_MACRONOTFOUND)));
259  xBox->run();
260  }
261 
262  return bScriptReturnedFalse;
263 }
264 
265  // true -> abort
266 
267 bool ScValidationData::DoMacro( const ScAddress& rPos, const OUString& rInput,
268  ScFormulaCell* pCell, weld::Window* pParent ) const
269 {
271  {
272  return DoScript( rPos, rInput, pCell, pParent );
273  }
274 
275  ScDocument* pDocument = GetDocument();
276  SfxObjectShell* pDocSh = pDocument->GetDocumentShell();
277  if ( !pDocSh )
278  return false;
279 
280  bool bDone = false;
281  bool bRet = false; // default: do not abort
282 
283  // If the Doc was loaded during a Basic-Calls,
284  // the Sbx-object may not be created (?)
285 // pDocSh->GetSbxObject();
286 
287 #if HAVE_FEATURE_SCRIPTING
288  // no security check ahead (only CheckMacroWarn), that happens in CallBasic
289 
290  // Function search by their simple name,
291  // then assemble aBasicStr, aMacroStr for SfxObjectShell::CallBasic
292 
293  StarBASIC* pRoot = pDocSh->GetBasic();
294  SbxVariable* pVar = pRoot->Find( aErrorTitle, SbxClassType::Method );
295  if (SbMethod* pMethod = dynamic_cast<SbMethod*>(pVar))
296  {
297  SbModule* pModule = pMethod->GetModule();
298  SbxObject* pObject = pModule->GetParent();
299  OUStringBuffer aMacroStr = pObject->GetName();
300  aMacroStr.append('.').append(pModule->GetName()).append('.').append(pMethod->GetName());
301  OUString aBasicStr;
302 
303  // the distinction between document- and app-basic has to be done
304  // by checking the parent (as in ScInterpreter::ScMacro), not by looping
305  // over all open documents, because this may be called from within loading,
306  // when SfxObjectShell::GetFirst/GetNext won't find the document.
307 
308  if ( pObject->GetParent() )
309  aBasicStr = pObject->GetParent()->GetName(); // Basic of document
310  else
311  aBasicStr = SfxGetpApp()->GetName(); // Basic of application
312 
313  // Parameter for Macro
314  SbxArrayRef refPar = new SbxArray;
315 
316  // 1) entered or calculated value
317  OUString aValStr = rInput;
318  double nValue = 0.0;
319  bool bIsValue = false;
320  if ( pCell ) // if cell set, called from interpret
321  {
322  bIsValue = pCell->IsValue();
323  if ( bIsValue )
324  nValue = pCell->GetValue();
325  else
326  aValStr = pCell->GetString().getString();
327  }
328  if ( bIsValue )
329  refPar->Get32(1)->PutDouble( nValue );
330  else
331  refPar->Get32(1)->PutString( aValStr );
332 
333  // 2) Position of the cell
334  OUString aPosStr(rPos.Format(ScRefFlags::VALID | ScRefFlags::TAB_3D, pDocument, pDocument->GetAddressConvention()));
335  refPar->Get32(2)->PutString( aPosStr );
336 
337  // use link-update flag to prevent closing the document
338  // while the macro is running
339  bool bWasInLinkUpdate = pDocument->IsInLinkUpdate();
340  if ( !bWasInLinkUpdate )
341  pDocument->SetInLinkUpdate( true );
342 
343  if ( pCell )
344  pDocument->LockTable( rPos.Tab() );
345  SbxVariableRef refRes = new SbxVariable;
346  ErrCode eRet = pDocSh->CallBasic( aMacroStr.makeStringAndClear(), aBasicStr, refPar.get(), refRes.get() );
347  if ( pCell )
348  pDocument->UnlockTable( rPos.Tab() );
349 
350  if ( !bWasInLinkUpdate )
351  pDocument->SetInLinkUpdate( false );
352 
353  // Interrupt input if Basic macro returns false
354  if ( eRet == ERRCODE_NONE && refRes->GetType() == SbxBOOL && !refRes->GetBool() )
355  bRet = true;
356  bDone = true;
357  }
358 #endif
359  if ( !bDone && !pCell ) // Macro not found (only with input)
360  {
361  //TODO: different error message, if found, but not bAllowed ??
362  std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(pParent,
363  VclMessageType::Warning, VclButtonsType::Ok,
364  ScResId(STR_VALID_MACRONOTFOUND)));
365  xBox->run();
366  }
367 
368  return bRet;
369 }
370 
372 {
373  if ( eErrorStyle == SC_VALERR_MACRO )
374  DoMacro( pCell->aPos, EMPTY_OUSTRING, pCell, nullptr );
375 }
376 
377  // true -> abort
378 
379 bool ScValidationData::DoError(weld::Window* pParent, const OUString& rInput,
380  const ScAddress& rPos) const
381 {
382  if ( eErrorStyle == SC_VALERR_MACRO )
383  return DoMacro(rPos, rInput, nullptr, pParent);
384 
385  // Output error message
386 
387  OUString aTitle = aErrorTitle;
388  if (aTitle.isEmpty())
389  aTitle = ScResId( STR_MSSG_DOSUBTOTALS_0 ); // application title
390  OUString aMessage = aErrorMessage;
391  if (aMessage.isEmpty())
392  aMessage = ScResId( STR_VALID_DEFERROR );
393 
394  VclButtonsType eStyle = VclButtonsType::Ok;
395  VclMessageType eType = VclMessageType::Error;
396  switch (eErrorStyle)
397  {
398  case SC_VALERR_INFO:
399  eType = VclMessageType::Info;
400  eStyle = VclButtonsType::OkCancel;
401  break;
402  case SC_VALERR_WARNING:
403  eType = VclMessageType::Warning;
404  eStyle = VclButtonsType::OkCancel;
405  break;
406  default:
407  break;
408  }
409 
412 
413  std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(pParent, eType,
414  eStyle, aMessage, bIsMobile));
415  xBox->set_title(aTitle);
416 
417  switch (eErrorStyle)
418  {
419  case SC_VALERR_INFO:
420  xBox->set_default_response(RET_OK);
421  break;
422  case SC_VALERR_WARNING:
423  xBox->set_default_response(RET_CANCEL);
424  break;
425  default:
426  break;
427  }
428 
429  short nRet = xBox->run();
430 
431  return ( eErrorStyle == SC_VALERR_STOP || nRet == RET_CANCEL );
432 }
433 
435  const OUString& rTest,
436  const ScPatternAttr& rPattern,
437  const ScAddress& rPos,
438  const CustomValidationPrivateAccess& ) const
439 {
440  OSL_ENSURE(GetDataMode() == SC_VALID_CUSTOM,
441  "ScValidationData::IsDataValidCustom invoked for a non-custom validation");
442 
443  if (rTest.isEmpty()) // check whether empty cells are allowed
444  return IsIgnoreBlank();
445 
446  if (rTest[0] == '=') // formulas do not pass the validity test
447  return false;
448 
449  SvNumberFormatter* pFormatter = GetDocument()->GetFormatTable();
450 
451  // get the value if any
452  sal_uInt32 nFormat = rPattern.GetNumberFormat( pFormatter );
453  double nVal;
454  bool bIsVal = pFormatter->IsNumberFormat( rTest, nFormat, nVal );
455 
456  ScRefCellValue aTmpCell;
457  svl::SharedString aSS;
458  if (bIsVal)
459  {
460  aTmpCell.meType = CELLTYPE_VALUE;
461  aTmpCell.mfValue = nVal;
462  }
463  else
464  {
465  aTmpCell.meType = CELLTYPE_STRING;
466  aSS = mpDoc->GetSharedStringPool().intern(rTest);
467  aTmpCell.mpString = &aSS;
468  }
469 
470  ScCellValue aOriginalCellValue(ScRefCellValue(*GetDocument(), rPos));
471 
472  aTmpCell.commit(*GetDocument(), rPos);
473  bool bRet = IsCellValid(aTmpCell, rPos);
474  aOriginalCellValue.commit(*GetDocument(), rPos);
475 
476  return bRet;
477 }
478 
485 {
487  double mfVal;
488  sal_uInt32 mnFormat;
489 
490  ScValidationDataIsNumeric( double fVal, SvNumberFormatter* pFormatter = nullptr, sal_uInt32 nFormat = 0 )
491  : mpFormatter(pFormatter), mfVal(fVal), mnFormat(nFormat)
492  {
493  }
494 
495  void init( const ScDocument& rDoc, const ScAddress& rPos )
496  {
497  const ScPatternAttr* pPattern = rDoc.GetPattern( rPos.Col(), rPos.Row(), rPos.Tab());
498  mpFormatter = rDoc.GetFormatTable();
499  mnFormat = pPattern->GetNumberFormat( mpFormatter);
500  }
501 };
502 
503 bool ScValidationData::IsDataValidTextLen( const OUString& rTest, const ScAddress& rPos,
504  ScValidationDataIsNumeric* pDataNumeric ) const
505 {
506  sal_Int32 nLen;
507  if (!pDataNumeric)
508  nLen = rTest.getLength();
509  else
510  {
511  if (!pDataNumeric->mpFormatter)
512  pDataNumeric->init( *GetDocument(), rPos);
513 
514  // For numeric values use the resulting input line string to
515  // determine length, otherwise an once accepted value maybe could
516  // not be edited again, for example abbreviated dates or leading
517  // zeros or trailing zeros after decimal separator change length.
518  OUString aStr;
519  pDataNumeric->mpFormatter->GetInputLineString( pDataNumeric->mfVal, pDataNumeric->mnFormat, aStr);
520  nLen = aStr.getLength();
521  }
522  ScRefCellValue aTmpCell( static_cast<double>(nLen));
523  return IsCellValid( aTmpCell, rPos);
524 }
525 
527  const OUString& rTest, const ScPatternAttr& rPattern, const ScAddress& rPos ) const
528 {
529  if ( eDataMode == SC_VALID_ANY ) // check if any cell content is allowed
530  return true;
531 
532  if (rTest.isEmpty()) // check whether empty cells are allowed
533  return IsIgnoreBlank();
534 
535  if (rTest[0] == '=') // formulas do not pass the validity test
536  return false;
537 
538  SvNumberFormatter* pFormatter = GetDocument()->GetFormatTable();
539 
540  // get the value if any
541  sal_uInt32 nFormat = rPattern.GetNumberFormat( pFormatter );
542  double nVal;
543  bool bIsVal = pFormatter->IsNumberFormat( rTest, nFormat, nVal );
544 
545  bool bRet;
547  {
548  if (!bIsVal)
549  bRet = IsDataValidTextLen( rTest, rPos, nullptr);
550  else
551  {
552  ScValidationDataIsNumeric aDataNumeric( nVal, pFormatter, nFormat);
553  bRet = IsDataValidTextLen( rTest, rPos, &aDataNumeric);
554  }
555  }
556  else
557  {
558  if (bIsVal)
559  {
560  ScRefCellValue aTmpCell(nVal);
561  bRet = IsDataValid(aTmpCell, rPos);
562  }
563  else
564  {
566  ScRefCellValue aTmpCell(&aSS);
567  bRet = IsDataValid(aTmpCell, rPos);
568  }
569  }
570 
571  return bRet;
572 }
573 
574 bool ScValidationData::IsDataValid( ScRefCellValue& rCell, const ScAddress& rPos ) const
575 {
576  if( eDataMode == SC_VALID_LIST )
577  return IsListValid(rCell, rPos);
578 
579  if ( eDataMode == SC_VALID_CUSTOM )
580  return IsCellValid(rCell, rPos);
581 
582  double nVal = 0.0;
583  OUString aString;
584  bool bIsVal = true;
585 
586  switch (rCell.meType)
587  {
588  case CELLTYPE_VALUE:
589  nVal = rCell.mfValue;
590  break;
591  case CELLTYPE_STRING:
592  aString = rCell.mpString->getString();
593  bIsVal = false;
594  break;
595  case CELLTYPE_EDIT:
596  if (rCell.mpEditText)
597  aString = ScEditUtil::GetString(*rCell.mpEditText, GetDocument());
598  bIsVal = false;
599  break;
600  case CELLTYPE_FORMULA:
601  {
602  ScFormulaCell* pFCell = rCell.mpFormula;
603  bIsVal = pFCell->IsValue();
604  if ( bIsVal )
605  nVal = pFCell->GetValue();
606  else
607  aString = pFCell->GetString().getString();
608  }
609  break;
610  default: // Notes, Broadcaster
611  return IsIgnoreBlank(); // as set
612  }
613 
614  bool bOk = true;
615  switch (eDataMode)
616  {
617  // SC_VALID_ANY already above
618 
619  case SC_VALID_WHOLE:
620  case SC_VALID_DECIMAL:
621  case SC_VALID_DATE: // Date/Time is only formatting
622  case SC_VALID_TIME:
623  bOk = bIsVal;
624  if ( bOk && eDataMode == SC_VALID_WHOLE )
625  bOk = ::rtl::math::approxEqual( nVal, floor(nVal+0.5) ); // integers
626  if ( bOk )
627  bOk = IsCellValid(rCell, rPos);
628  break;
629 
630  case SC_VALID_TEXTLEN:
631  if (!bIsVal)
632  bOk = IsDataValidTextLen( aString, rPos, nullptr);
633  else
634  {
635  ScValidationDataIsNumeric aDataNumeric( nVal);
636  bOk = IsDataValidTextLen( aString, rPos, &aDataNumeric);
637  }
638  break;
639 
640  default:
641  OSL_FAIL("not yet done");
642  break;
643  }
644 
645  return bOk;
646 }
647 
648 namespace {
649 
653 class ScStringTokenIterator
654 {
655 public:
656  explicit ScStringTokenIterator( const ScTokenArray& rTokArr ) :
657  maIter( rTokArr ), mbOk( true ) {}
658 
660  rtl_uString* First();
662  rtl_uString* Next();
663 
665  bool Ok() const { return mbOk; }
666 
667 private:
668  svl::SharedString maCurString;
670  bool mbOk;
671 };
672 
673 rtl_uString* ScStringTokenIterator::First()
674 {
675  maIter.Reset();
676  mbOk = true;
677  return Next();
678 }
679 
680 rtl_uString* ScStringTokenIterator::Next()
681 {
682  if( !mbOk )
683  return nullptr;
684 
685  // seek to next non-separator token
686  const FormulaToken* pToken = maIter.NextNoSpaces();
687  while( pToken && (pToken->GetOpCode() == ocSep) )
688  pToken = maIter.NextNoSpaces();
689 
690  mbOk = !pToken || (pToken->GetType() == formula::svString);
691 
692  maCurString = svl::SharedString(); // start with invalid string.
693  if (mbOk && pToken)
694  maCurString = pToken->GetString();
695 
696  // string found but empty -> get next token; otherwise return it
697  return (maCurString.isValid() && maCurString.isEmpty()) ? Next() : maCurString.getData();
698 }
699 
701 sal_uLong lclGetCellFormat( const ScDocument& rDoc, const ScAddress& rPos )
702 {
703  const ScPatternAttr* pPattern = rDoc.GetPattern( rPos.Col(), rPos.Row(), rPos.Tab() );
704  if( !pPattern )
705  pPattern = rDoc.GetDefPattern();
706  return pPattern->GetNumberFormat( rDoc.GetFormatTable() );
707 }
708 
709 } // namespace
710 
712 {
713  return (eDataMode == SC_VALID_LIST) && (mnListType != css::sheet::TableValidationVisibility::INVISIBLE);
714 }
715 
717  std::vector<ScTypedStrData>* pStrings, ScRefCellValue& rCell, const ScAddress& rPos,
718  const ScTokenArray& rTokArr, int& rMatch) const
719 {
720  bool bOk = true;
721 
722  // pDoc is private in condition, use an accessor and a long winded name.
723  ScDocument* pDocument = GetDocument();
724  if( nullptr == pDocument )
725  return false;
726 
727  ScFormulaCell aValidationSrc(
729 
730  // Make sure the formula gets interpreted and a result is delivered,
731  // regardless of the AutoCalc setting.
732  aValidationSrc.Interpret();
733 
734  ScMatrixRef xMatRef;
735  const ScMatrix *pValues = aValidationSrc.GetMatrix();
736  if (!pValues)
737  {
738  // The somewhat nasty case of either an error occurred, or the
739  // dereferenced value of a single cell reference or an immediate result
740  // is stored as a single value.
741 
742  // Use an interim matrix to create the TypedStrData below.
743  xMatRef = new ScMatrix(1, 1, 0.0);
744 
745  FormulaError nErrCode = aValidationSrc.GetErrCode();
746  if (nErrCode != FormulaError::NONE)
747  {
748  /* TODO : to use later in an alert box?
749  * OUString rStrResult = "...";
750  * rStrResult += ScGlobal::GetLongErrorString(nErrCode);
751  */
752 
753  xMatRef->PutError( nErrCode, 0, 0);
754  bOk = false;
755  }
756  else if (aValidationSrc.IsValue())
757  xMatRef->PutDouble( aValidationSrc.GetValue(), 0);
758  else
759  {
760  svl::SharedString aStr = aValidationSrc.GetString();
761  xMatRef->PutString(aStr, 0);
762  }
763 
764  pValues = xMatRef.get();
765  }
766 
767  // which index matched. We will want it eventually to pre-select that item.
768  rMatch = -1;
769 
770  SvNumberFormatter* pFormatter = GetDocument()->GetFormatTable();
771 
772  SCSIZE nCol, nRow, nCols, nRows, n = 0;
773  pValues->GetDimensions( nCols, nRows );
774 
775  bool bRef = false;
776  ScRange aRange;
777 
778  ScTokenArray* pArr = const_cast<ScTokenArray*>(&rTokArr);
779  if (pArr->GetLen() == 1)
780  {
783  if (t)
784  {
785  OpCode eOpCode = t->GetOpCode();
786  if (eOpCode == ocDBArea || eOpCode == ocTableRef)
787  {
788  if (const ScDBData* pDBData = pDocument->GetDBCollection()->getNamedDBs().findByIndex(t->GetIndex()))
789  {
790  pDBData->GetArea(aRange);
791  bRef = true;
792  }
793  }
794  else if (eOpCode == ocName)
795  {
796  const ScRangeData* pName = pDocument->FindRangeNameBySheetAndIndex( t->GetSheet(), t->GetIndex());
797  if (pName && pName->IsReference(aRange))
798  {
799  bRef = true;
800  }
801  }
802  else if (t->GetType() != svIndex)
803  {
804  if (pArr->IsValidReference(aRange, rPos))
805  {
806  bRef = true;
807  }
808  }
809  }
810  }
811 
812  bool bHaveEmpty = false;
813  svl::SharedStringPool& rSPool = pDocument->GetSharedStringPool();
814 
815  /* XL artificially limits things to a single col or row in the UI but does
816  * not list the constraint in MOOXml. If a defined name or INDIRECT
817  * resulting in 1D is entered in the UI and the definition later modified
818  * to 2D, it is evaluated fine and also stored and loaded. Lets get ahead
819  * of the curve and support 2d. In XL, values are listed row-wise, do the
820  * same. */
821  for( nRow = 0; nRow < nRows ; nRow++ )
822  {
823  for( nCol = 0; nCol < nCols ; nCol++ )
824  {
825  ScTokenArray aCondTokArr(*pDocument);
826  std::unique_ptr<ScTypedStrData> pEntry;
827  OUString aValStr;
828  ScMatrixValue nMatVal = pValues->Get( nCol, nRow);
829 
830  // strings and empties
831  if( ScMatrix::IsNonValueType( nMatVal.nType ) )
832  {
833  aValStr = nMatVal.GetString().getString();
834 
835  // Do not add multiple empty strings to the validation list,
836  // especially not if they'd bloat the tail with a million empty
837  // entries for a column range, fdo#61520
838  if (aValStr.isEmpty())
839  {
840  if (bHaveEmpty)
841  continue;
842  bHaveEmpty = true;
843  }
844 
845  if( nullptr != pStrings )
846  pEntry.reset(new ScTypedStrData( aValStr, 0.0, ScTypedStrData::Standard));
847 
848  if (!rCell.isEmpty() && rMatch < 0)
849  aCondTokArr.AddString(rSPool.intern(aValStr));
850  }
851  else
852  {
853  FormulaError nErr = nMatVal.GetError();
854 
855  if( FormulaError::NONE != nErr )
856  {
857  aValStr = ScGlobal::GetErrorString( nErr );
858  }
859  else
860  {
861  // FIXME FIXME FIXME
862  // Feature regression. Date formats are lost passing through the matrix
863  //pFormatter->GetInputLineString( pMatVal->fVal, 0, aValStr );
864  //For external reference and a formula that results in an area or array, date formats are still lost.
865  if ( bRef )
866  {
867  pDocument->GetInputString(static_cast<SCCOL>(nCol+aRange.aStart.Col()),
868  static_cast<SCROW>(nRow+aRange.aStart.Row()), aRange.aStart.Tab() , aValStr);
869  }
870  else
871  {
872  pFormatter->GetInputLineString( nMatVal.fVal, 0, aValStr );
873  }
874  }
875 
876  if (!rCell.isEmpty() && rMatch < 0)
877  {
878  // I am not sure errors will work here, but a user can no
879  // manually enter an error yet so the point is somewhat moot.
880  aCondTokArr.AddDouble( nMatVal.fVal );
881  }
882  if( nullptr != pStrings )
883  pEntry.reset(new ScTypedStrData( aValStr, nMatVal.fVal, ScTypedStrData::Value));
884  }
885 
886  if (rMatch < 0 && !rCell.isEmpty() && IsEqualToTokenArray(rCell, rPos, aCondTokArr))
887  {
888  rMatch = n;
889  // short circuit on the first match if not filling the list
890  if( nullptr == pStrings )
891  return true;
892  }
893 
894  if( pEntry )
895  {
896  assert(pStrings);
897  pStrings->push_back(*pEntry);
898  n++;
899  }
900  }
901  }
902 
903  // In case of no match needed and an error occurred, return that error
904  // entry as valid instead of silently failing.
905  return bOk || rCell.isEmpty();
906 }
907 
908 bool ScValidationData::FillSelectionList(std::vector<ScTypedStrData>& rStrColl, const ScAddress& rPos) const
909 {
910  bool bOk = false;
911 
912  if( HasSelectionList() )
913  {
914  std::unique_ptr<ScTokenArray> pTokArr( CreateFlatCopiedTokenArray(0) );
915 
916  // *** try if formula is a string list ***
917 
918  sal_uInt32 nFormat = lclGetCellFormat( *GetDocument(), rPos );
919  ScStringTokenIterator aIt( *pTokArr );
920  for (rtl_uString* pString = aIt.First(); pString && aIt.Ok(); pString = aIt.Next())
921  {
922  double fValue;
923  OUString aStr(pString);
924  bool bIsValue = GetDocument()->GetFormatTable()->IsNumberFormat(aStr, nFormat, fValue);
925  rStrColl.emplace_back(
926  aStr, fValue, bIsValue ? ScTypedStrData::Value : ScTypedStrData::Standard);
927  }
928  bOk = aIt.Ok();
929 
930  // *** if not a string list, try if formula results in a cell range or
931  // anything else we recognize as valid ***
932 
933  if (!bOk)
934  {
935  int nMatch;
936  ScRefCellValue aEmptyCell;
937  bOk = GetSelectionFromFormula(&rStrColl, aEmptyCell, rPos, *pTokArr, nMatch);
938  }
939  }
940 
941  return bOk;
942 }
943 
944 bool ScValidationData::IsEqualToTokenArray( ScRefCellValue& rCell, const ScAddress& rPos, const ScTokenArray& rTokArr ) const
945 {
946  // create a condition entry that tests on equality and set the passed token array
947  ScConditionEntry aCondEntry( ScConditionMode::Equal, &rTokArr, nullptr, *GetDocument(), rPos );
948  return aCondEntry.IsCellValid(rCell, rPos);
949 }
950 
951 bool ScValidationData::IsListValid( ScRefCellValue& rCell, const ScAddress& rPos ) const
952 {
953  bool bIsValid = false;
954 
955  /* Compare input cell with all supported tokens from the formula.
956  Currently a formula may contain:
957  1) A list of strings (at least one string).
958  2) A single cell or range reference.
959  3) A single defined name (must contain a cell/range reference, another
960  name, or DB range, or a formula resulting in a cell/range reference
961  or matrix/array).
962  4) A single database range.
963  5) A formula resulting in a cell/range reference or matrix/array.
964  */
965 
966  std::unique_ptr< ScTokenArray > pTokArr( CreateFlatCopiedTokenArray( 0 ) );
967 
968  // *** try if formula is a string list ***
969 
971  sal_uInt32 nFormat = lclGetCellFormat( *GetDocument(), rPos );
972  ScStringTokenIterator aIt( *pTokArr );
973  for (rtl_uString* pString = aIt.First(); pString && aIt.Ok(); pString = aIt.Next())
974  {
975  /* Do not break the loop, if a valid string has been found.
976  This is to find invalid tokens following in the formula. */
977  if( !bIsValid )
978  {
979  // create a formula containing a single string or number
980  ScTokenArray aCondTokArr(*GetDocument());
981  double fValue;
982  OUString aStr(pString);
983  if (GetDocument()->GetFormatTable()->IsNumberFormat(aStr, nFormat, fValue))
984  aCondTokArr.AddDouble( fValue );
985  else
986  aCondTokArr.AddString(rSPool.intern(aStr));
987 
988  bIsValid = IsEqualToTokenArray(rCell, rPos, aCondTokArr);
989  }
990  }
991 
992  if( !aIt.Ok() )
993  bIsValid = false;
994 
995  // *** if not a string list, try if formula results in a cell range or
996  // anything else we recognize as valid ***
997 
998  if (!bIsValid)
999  {
1000  int nMatch;
1001  bIsValid = GetSelectionFromFormula(nullptr, rCell, rPos, *pTokArr, nMatch);
1002  bIsValid = bIsValid && nMatch >= 0;
1003  }
1004 
1005  return bIsValid;
1006 }
1007 
1009 {
1010  // for Ref-Undo - real copy with new tokens!
1011 
1012  for (const auto& rxItem : rList)
1013  {
1014  InsertNew( std::unique_ptr<ScValidationData>(rxItem->Clone()) );
1015  }
1016 
1017  //TODO: faster insert for sorted entries from rList ???
1018 }
1019 
1021  const ScValidationDataList& rList)
1022 {
1023  // for new documents - real copy with new tokens!
1024 
1025  for (const auto& rxItem : rList)
1026  {
1027  InsertNew( std::unique_ptr<ScValidationData>(rxItem->Clone(&rNewDoc)) );
1028  }
1029 
1030  //TODO: faster insert for sorted entries from rList ???
1031 }
1032 
1034 {
1035  //TODO: binary search
1036 
1037  for( iterator it = begin(); it != end(); ++it )
1038  if( (*it)->GetKey() == nKey )
1039  return it->get();
1040 
1041  OSL_FAIL("ScValidationDataList: Entry not found");
1042  return nullptr;
1043 }
1044 
1046 {
1047  for( iterator it = begin(); it != end(); ++it )
1048  (*it)->CompileXML();
1049 }
1050 
1052 {
1053  for( iterator it = begin(); it != end(); ++it )
1054  (*it)->UpdateReference(rCxt);
1055 }
1056 
1058 {
1059  for (iterator it = begin(); it != end(); ++it)
1060  (*it)->UpdateInsertTab(rCxt);
1061 }
1062 
1064 {
1065  for (iterator it = begin(); it != end(); ++it)
1066  (*it)->UpdateDeleteTab(rCxt);
1067 }
1068 
1070 {
1071  for (iterator it = begin(); it != end(); ++it)
1072  (*it)->UpdateMoveTab(rCxt);
1073 }
1074 
1076 {
1077  return maData.begin();
1078 }
1079 
1081 {
1082  return maData.begin();
1083 }
1084 
1086 {
1087  return maData.end();
1088 }
1089 
1091 {
1092  return maData.end();
1093 }
1094 
1095 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
static bool IsNonValueType(ScMatValType nType)
String, empty or empty path, but not value nor boolean.
Definition: scmatrix.hxx:173
Matrix data type that can store values of mixed types.
Definition: scmatrix.hxx:113
ErrCode CallBasic(const OUString &rMacro, const OUString &rBasicName, SbxArray *pArgs, SbxValue *pRet=nullptr)
static bool IsXScriptURL(const OUString &rScriptURL)
bool IsDataValid(const OUString &rTest, const ScPatternAttr &rPattern, const ScAddress &rPos) const
Definition: validat.cxx:526
SC_DLLPUBLIC void Format(OStringBuffer &r, ScRefFlags nFlags, const ScDocument *pDocument=nullptr, const Details &rDetails=detailsOOOa1) const
Definition: address.cxx:2107
OUString aInputMessage
Definition: validat.hxx:72
virtual svl::SharedString GetString() const
SC_DLLPUBLIC ScDBCollection * GetDBCollection() const
Definition: document.hxx:816
OUString getString() const
ScAddress aStart
Definition: address.hxx:500
SharedString intern(const OUString &rStr)
bool GetSelectionFromFormula(std::vector< ScTypedStrData > *pStrings, ScRefCellValue &rCell, const ScAddress &rPos, const ScTokenArray &rTokArr, int &rMatch) const
Tries to fill the passed collection with list validation entries.
Definition: validat.cxx:716
ScDBData * findByIndex(sal_uInt16 nIndex)
Definition: dbdata.cxx:1138
SC_DLLPUBLIC svl::SharedStringPool & GetSharedStringPool()
Definition: documen2.cxx:563
SC_DLLPUBLIC void GetInputString(SCCOL nCol, SCROW nRow, SCTAB nTab, OUString &rString)
Definition: document.cxx:3540
bool FillSelectionList(std::vector< ScTypedStrData > &rStrings, const ScAddress &rPos) const
Tries to fill the passed collection with list validation entries.
Definition: validat.cxx:908
#define EMPTY_OUSTRING
Definition: global.hxx:215
bool isLOKMobilePhone() const
const OUString & GetName(SbxNameType=SbxNameType::NONE) const
ocName
SCROW Row() const
Definition: address.hxx:262
OUString aErrorTitle
Definition: validat.hxx:73
VclButtonsType
bool isEmpty() const
Definition: cellvalue.cxx:670
void SetInLinkUpdate(bool bSet)
Definition: documen8.cxx:774
bool IsDataValidCustom(const OUString &rTest, const ScPatternAttr &rPattern, const ScAddress &rPos, const CustomValidationPrivateAccess &) const
Definition: validat.cxx:434
ScValidErrorStyle
Definition: validat.hxx:51
sal_uIntPtr sal_uLong
Context for reference update during shifting, moving or copying of cell ranges.
ScMatrixValue Get(SCSIZE nC, SCSIZE nR) const
: If bString the ScMatrixValue->pS may still be NULL to indicate an empty string! ...
Definition: scmatrix.cxx:3094
sal_Int64 n
ScValidationMode eDataMode
Definition: validat.hxx:66
StarBASIC * GetBasic() const
OpCode GetOpCode() const
This is very similar to ScCellValue, except that it references the original value instead of copying ...
Definition: cellvalue.hxx:104
bool HasSelectionList() const
Returns true, if the validation cell will show a selection list.
Definition: validat.cxx:711
OUString aInputTitle
Definition: validat.hxx:71
bool DoMacro(const ScAddress &rPos, const OUString &rInput, ScFormulaCell *pCell, weld::Window *pParent) const
Definition: validat.cxx:267
EmbeddedObjectRef * pObject
bool IsCellValid(ScRefCellValue &rCell, const ScAddress &rPos) const
Definition: conditio.cxx:1219
RET_CANCEL
SC_DLLPUBLIC formula::FormulaGrammar::AddressConvention GetAddressConvention() const
Definition: documen3.cxx:489
Try NOT to use this struct.
Definition: scmatrix.hxx:53
ScValidationDataListDataType::const_iterator const_iterator
Definition: validat.hxx:217
exports com.sun.star. sheet
virtual sal_Int16 GetSheet() const
SfxApplication * SfxGetpApp()
bool DoScript(const ScAddress &rPos, const OUString &rInput, ScFormulaCell *pCell, weld::Window *pParent) const
Definition: validat.cxx:185
void UnlockTable(SCTAB nTab)
Definition: document.cxx:5317
Store arbitrary cell value of any kind.
Definition: cellvalue.hxx:36
ScValidErrorStyle eErrorStyle
Definition: validat.hxx:69
double fVal
Definition: scmatrix.hxx:55
void UpdateMoveTab(sc::RefUpdateMoveTabContext &rCxt)
Definition: validat.cxx:1069
const EditTextObject * mpEditText
Definition: cellvalue.hxx:110
size_t SCSIZE
size_t typedef to be able to find places where code was changed from USHORT to size_t and is used to ...
Definition: address.hxx:45
const BorderLinePrimitive2D *pCandidateB assert(pCandidateA)
ScValidationDataIsNumeric(double fVal, SvNumberFormatter *pFormatter=nullptr, sal_uInt32 nFormat=0)
Definition: validat.cxx:490
double GetValue()
FormulaError GetErrCode()
OpCode
SbxBOOL
static SfxViewShell * Current()
void SetInput(const OUString &rTitle, const OUString &rMsg)
Definition: validat.cxx:160
::boost::intrusive_ptr< ScMatrix > ScMatrixRef
Definition: types.hxx:26
ScConditionMode
Definition: conditio.hxx:61
ScFormulaCell * mpFormula
Definition: cellvalue.hxx:111
SCTAB Tab() const
Definition: address.hxx:271
VclMessageType
virtual ~ScValidationData() override
Definition: validat.cxx:124
void commit(ScDocument &rDoc, const ScAddress &rPos) const
Set cell value at specified position in specified document.
Definition: cellvalue.cxx:592
const OUString & GetName() const
ScAddress aPos
SC_DLLPUBLIC const ScPatternAttr * GetPattern(SCCOL nCol, SCROW nRow, SCTAB nTab) const
Definition: document.cxx:4735
void init(const ScDocument &rDoc, const ScAddress &rPos)
Definition: validat.cxx:495
ScValidationMode
Definition: validat.hxx:39
ScValidationDataListDataType maData
Definition: validat.hxx:209
sal_uInt16 GetLen() const
ScValidationMode GetDataMode() const
Definition: validat.hxx:115
void DoCalcError(ScFormulaCell *pCell) const
Definition: validat.cxx:371
ocSep
DocumentType eType
bool operator==(const ScFormatEntry &) const
Definition: conditio.cxx:55
FormulaError GetError() const
Only valid if ScMatrix methods indicate that this is no string!
Definition: scmatrix.hxx:63
T * get() const
sal_uInt16 char * pName
Definition: callform.cxx:58
SC_DLLPUBLIC SvNumberFormatter * GetFormatTable() const
Definition: documen2.cxx:438
ScValidationData * GetData(sal_uInt32 nKey)
Definition: validat.cxx:1033
void UpdateReference(sc::RefUpdateContext &rCxt)
Definition: validat.cxx:1051
OUString aErrorMessage
Definition: validat.hxx:74
void GetDimensions(SCSIZE &rC, SCSIZE &rR) const
Definition: scmatrix.cxx:2984
const svl::SharedString * mpString
Definition: cellvalue.hxx:109
bool IsEqualToTokenArray(ScRefCellValue &rCell, const ScAddress &rPos, const ScTokenArray &rTokArr) const
Tests, if pCell is equal to what the passed token array represents.
Definition: validat.cxx:944
svIndex
bool Interpret(SCROW nStartOffset=-1, SCROW nEndOffset=-1)
#define ERRCODE_BASIC_METHOD_NOT_FOUND
ScValidationData(ScValidationMode eMode, ScConditionMode eOper, const OUString &rExpr1, const OUString &rExpr2, ScDocument &rDocument, const ScAddress &rPos, const OUString &rExprNmsp1=EMPTY_OUSTRING, const OUString &rExprNmsp2=EMPTY_OUSTRING, formula::FormulaGrammar::Grammar eGrammar1=formula::FormulaGrammar::GRAM_DEFAULT, formula::FormulaGrammar::Grammar eGrammar2=formula::FormulaGrammar::GRAM_DEFAULT)
Definition: validat.cxx:62
OUString ScResId(const char *pId)
Definition: scdll.cxx:95
bool IsNumberFormat(const OUString &sString, sal_uInt32 &F_Index, double &fOutNumber, SvNumInputOptions eInputOptions=SvNumInputOptions::NONE)
ErrCode CallXScript(const OUString &rScriptURL, const css::uno::Sequence< css::uno::Any > &aParams, css::uno::Any &aRet, css::uno::Sequence< sal_Int16 > &aOutParamIndex, css::uno::Sequence< css::uno::Any > &aOutParam, bool bRaiseError=true, const css::uno::Any *aCaller=nullptr)
bool EqualEntries(const ScValidationData &r) const
Definition: validat.cxx:134
const SbxObject * GetParent() const
To test numeric data text length in IsDataValidTextLen().
Definition: validat.cxx:484
sal_uInt32 GetNumberFormat(SvNumberFormatter *) const
Definition: patattr.cxx:1257
css::uno::Type const & get()
void GetInputLineString(const double &fOutNumber, sal_uInt32 nFIndex, OUString &rOutString)
ScMatValType nType
Definition: scmatrix.hxx:57
virtual sal_uInt16 GetIndex() const
FormulaError
SCCOL Col() const
Definition: address.hxx:267
XPropertyListType t
void LockTable(SCTAB nTab)
Definition: document.cxx:5307
void InsertNew(std::unique_ptr< ScValidationData > pNew)
Definition: validat.hxx:224
bool GetErrMsg(OUString &rTitle, OUString &rMsg, ScValidErrorStyle &rStyle) const
Definition: validat.cxx:176
const svl::SharedString & GetString() const
Only valid if ScMatrix methods indicate so!
Definition: scmatrix.hxx:60
bool GetBool() const
void UpdateDeleteTab(sc::RefUpdateDeleteTabContext &rCxt)
Definition: validat.cxx:1063
CellType meType
Definition: cellvalue.hxx:106
svl::SharedString GetString()
bool IsEmpty() const
Definition: validat.cxx:128
const PropertyValue * pValues
void ResetInput()
Definition: validat.cxx:150
virtual SbxDataType GetType() const override
FormulaToken * AddString(const svl::SharedString &rStr)
#define ERRCODE_NONE
ScValidationDataListDataType::iterator iterator
Definition: validat.hxx:216
bool PutString(const OUString &)
AnnotationVector::iterator maIter
RET_OK
void SetError(const OUString &rTitle, const OUString &rMsg, ScValidErrorStyle eStyle)
Definition: validat.cxx:167
bool PutDouble(double)
const ScMatrix * GetMatrix()
ocTableRef
SC_DLLPUBLIC ScPatternAttr * GetDefPattern() const
Definition: document.cxx:6056
ScDocument * mpDoc
Definition: conditio.hxx:257
NamedDBs & getNamedDBs()
Definition: dbdata.hxx:315
SC_DLLPUBLIC bool IsReference(ScRange &rRef) const
Definition: rangenam.cxx:369
void UpdateInsertTab(sc::RefUpdateInsertTabContext &rCxt)
Definition: validat.cxx:1057
virtual SbxVariable * Find(const OUString &, SbxClassType) override
bool IsValidReference(ScRange &rRange, const ScAddress &rPos) const
Exactly and only one valid range (no #REF!s)
Definition: token.cxx:1860
bool DoError(weld::Window *pParent, const OUString &rInput, const ScAddress &rPos) const
Definition: validat.cxx:379
bool IsInLinkUpdate() const
Definition: documen8.cxx:782
static SC_DLLPUBLIC OUString GetString(const EditTextObject &rEditText, const ScDocument *pDoc)
Retrieves string with paragraphs delimited by new lines (' ').
Definition: editutil.cxx:115
SfxObjectShell * GetDocumentShell() const
Definition: document.hxx:1058
std::unique_ptr< ScTokenArray > CreateFlatCopiedTokenArray(sal_uInt16 nPos) const
Create a flat copy using ScTokenArray copy-ctor with shared tokens.
Definition: conditio.cxx:1281
ScDocument * GetDocument() const
Definition: conditio.hxx:414
bool IsIgnoreBlank() const
Definition: conditio.hxx:372
SbxVariable * Get32(sal_uInt32)
SvNumberFormatter * mpFormatter
Definition: validat.cxx:486
ScRangeData * FindRangeNameBySheetAndIndex(SCTAB nTab, sal_uInt16 nIndex) const
Find a named expression / range name in either global or a local scope.
Definition: documen3.cxx:264
void commit(ScDocument &rDoc, const ScAddress &rPos) const
Set cell value at specified position in specified document.
Definition: cellvalue.cxx:402
StackVar GetType() const
aStr
void ResetError()
Definition: validat.cxx:155
static OUString GetErrorString(FormulaError nErrNumber)
Definition: global.cxx:301
static weld::MessageDialog * CreateMessageDialog(weld::Widget *pParent, VclMessageType eMessageType, VclButtonsType eButtonType, const OUString &rPrimaryMessage, bool bMobile=false)
ocDBArea
bool IsDataValidTextLen(const OUString &rTest, const ScAddress &rPos, ScValidationDataIsNumeric *pDataNumeric) const
Tests, if string or numeric data has valid text length.
Definition: validat.cxx:503
sal_Int16 nValue
sal_Int16 mnListType
Definition: validat.hxx:70
FormulaToken * AddDouble(double fVal)
bool IsListValid(ScRefCellValue &rCell, const ScAddress &rPos) const
Tests, if contents of pCell occur in cell range referenced by own formula, or in a string list...
Definition: validat.cxx:951