VBScript数据验证-数值1导致无限循环

VBScript数据验证-数值1导致无限循环,vbscript,infinite-loop,validation,Vbscript,Infinite Loop,Validation,免责声明:我仍然是一个有编程概念的uber-n00b,知道的VBS足以伤害我自己,所以我很可能会对我试图编写的这个程序所包含的一些术语/概念/想法嗤之以鼻。你,一个非常优秀的程序员,有权解雇我,已经被警告了 我一直在尝试编写一个VBScript来验证数据,特别是日期。由于我的用户对键盘的使用有点差,我想我可以通过将日期的每个部分(仅限月和日,我静态设置了年份)的条目分开来简化操作 以前,我只使用1“Do…Loop”验证数字时遇到问题,因为我试图验证它是否为数字输入,同时检查它是否在指定范围内(1

免责声明:我仍然是一个有编程概念的uber-n00b,知道的VBS足以伤害我自己,所以我很可能会对我试图编写的这个程序所包含的一些术语/概念/想法嗤之以鼻。你,一个非常优秀的程序员,有权解雇我,已经被警告了

我一直在尝试编写一个VBScript来验证数据,特别是日期。由于我的用户对键盘的使用有点差,我想我可以通过将日期的每个部分(仅限月和日,我静态设置了年份)的条目分开来简化操作

以前,我只使用1“Do…Loop”验证数字时遇到问题,因为我试图验证它是否为数字输入,同时检查它是否在指定范围内(1-12,一年中的12个月)

前面的代码大致如下所示:

Do
    ' If...Then Statements Here
Loop Until (dtFirstMonth > 0) _
    And (dtFirstMonth < 13) _
    And IsNumeric(dtFirstMonth) _
    And (dtFirstMonth <> "") _
    And (dtFirstMonth <> vbNull)
我也尝试过,但没有成功:

Do
    ' If...Then Statements Here
Loop Until (dtFirstMonth >= CInt(1))
实际上,确实不需要这个段,因为我已经将用户的输入转换成了整数

由于这开始让人困惑,我决定在脚本将用户的输入传递给“CInt”函数之前添加“Round”语句,希望它能确保它不会以某种方式被捕获为0值或十进制值;是的,这对我来说是不合理的想法,但我仍然想探索所有的途径(还有一个事实,我有一些用户患有“胖手指综合症”,还有一些用户有“滥用程序”的心态,所以我想我应该确保脚本中有小数项)。我在嵌套的“Do…Loop”前后添加了“Round”字符串,但仍然存在无限循环问题

这是我所能做到的,现在我被卡住了


我意识到在VBScript中可能有更好的方法来进行日期/时间验证,我当然愿意接受任何新的建议,但我想解决这个问题纯粹是为了启发。

对于简单的数字输入来说,代码太多了。尽量保持简短。例如:

Do
    dtm = InputBox("Please Enter a Numeric Month for the Starting Range", _
                "Starting Range Month")
    Select Case True
        Case isNull(dtm), (not isNumeric(dtm)), dtm = "", dtm = empty, (dtm < 1 OR dtm > 12)
            ' too exhaustive, but just for the sake of the example.
             MsgBox "Please enter an amount between 1 and 12"
        Case else
            ' Hey, this seems to be a valid amount!
            Exit do
    End Select
Loop While True

'  Do something with dtm
Do
dtm=InputBox(“请为起始范围输入数字月份”_
“起始范围月”)
选择Case True
大小写为空(dtm),(非数字(dtm)),dtm=“”,dtm=空,(dtm<1或dtm>12)
“太详尽了,只是为了举例。
MsgBox“请输入介于1和12之间的金额”
其他情况
“嘿,这似乎是一个合理的数额!
退出do
结束选择
在为真时循环
“用dtm做点什么

刚才向您展示了一些创造性的Select大小写,它支持延迟退出,因此,如果值为Null,它会在求值之前逃逸,求值可能会引发错误。

对于简单的数字输入来说,代码太多了。尽量保持简短。例如:

Do
    dtm = InputBox("Please Enter a Numeric Month for the Starting Range", _
                "Starting Range Month")
    Select Case True
        Case isNull(dtm), (not isNumeric(dtm)), dtm = "", dtm = empty, (dtm < 1 OR dtm > 12)
            ' too exhaustive, but just for the sake of the example.
             MsgBox "Please enter an amount between 1 and 12"
        Case else
            ' Hey, this seems to be a valid amount!
            Exit do
    End Select
Loop While True

'  Do something with dtm
Do
dtm=InputBox(“请为起始范围输入数字月份”_
“起始范围月”)
选择Case True
大小写为空(dtm),(非数字(dtm)),dtm=“”,dtm=空,(dtm<1或dtm>12)
“太详尽了,只是为了举例。
MsgBox“请输入介于1和12之间的金额”
其他情况
“嘿,这似乎是一个合理的数额!
退出do
结束选择
在为真时循环
“用dtm做点什么

刚才向您展示了一些创造性的Select大小写,它支持延迟退出,因此,如果值为Null,则它会在进行计算之前退出,因为计算可能会引发错误。

问题在于您试图检查Null值:

(dtFirstMonth = vbNull)
如AutomatedChaos的答案所示,检查空值的正确方法是使用函数
vbNull
实际上是一个与函数一起使用的常量。
vbNull
的值为1,这就是为什么该特定值的行为与其他条目不同的原因。这是根本问题,如果将每个
dtFirstMonth=vbNull
替换为
IsNull(dtFirstMonth)
,则在输入1时不会得到无限循环

现在,代码无限循环的实际位置很有趣。我希望第一个条件
If(dtFirstMonth=vbNull)
对输入“1”的值求值为true,并且您将得到消息框“请输入有效的数字月份”。但是,会触发
Else
条件。这很奇怪,因为通常情况下,当您将字符串与数字进行比较时,VBScript会尝试将数字转换为字符串,反之亦然,因此如果
dtFirstMonth
为“1”,则应等于
vbNull
(即1)。但是,当您将字符串变量与整数变量进行比较时,似乎存在一种特殊情况。请参见此示例:

' vbNull = 1, built-in constant
dtFirstMonth = "1"
MsgBox (dtFirstMonth = vbNull) ' False
MsgBox ("1" = vbNull) ' True
MsgBox (dtFirstMonth = 1) ' True
MsgBox (CInt(dtFirstMonth) = vbNull) ' True
我不知道这是一个bug还是仅仅是关于VBScript隐式转换的一个模糊细节,但它确实说明了在VBScript中隐式转换是不可预测的

至于其他方法,您可能会对函数感兴趣,如果给定的表达式可以转换为日期,该函数将返回
True
。它可能不适合您的用户及其键盘技能,但它会将您的代码减少到:

Do
    str = InputBox("Enter a date (MM/DD)")
    If IsDate(str) Then
        Exit Do
    Else
        WScript.Echo "Please enter a valid date"
    End If
Loop
dt = CDate(str)
' Put your static year here; CDate will default to the current year
dtActual = DateSerial(2007, Month(dt), Day(dt))
WScript.Echo (dtActual) & " - Thanks!"

请注意,
IsDate
对于典型的边缘情况(
Null
Empty
,等等),应该返回
False
,因此不需要单独检查。

问题在于您尝试检查空值:

(dtFirstMonth = vbNull)
如AutomatedChaos的答案所示,检查空值的正确方法是使用函数
vbNull
实际上是一个与函数一起使用的常量。
vbNull
的值为1,这就是为什么该特定值的行为与其他条目不同的原因。这是根本问题,如果您在第一个月更换一次
dt=