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