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