【问题标题】:What Result Should It Return?它应该返回什么结果?
【发布时间】:2015-05-01 05:04:21
【问题描述】:

我有这个 VB 脚本。我不知道这会产生什么结果?

expressao = "Format(#30/04/2015#,""Short Date"")<=Format(#01/05/2015#,""Short Date"")"
        Debug.Print "Resultado 6: " & Eval(expressao)

我稍微改变了上面的 sn-p 代码,但它仍然带来相同的结果:false (0):

expressao = "Format(#30/04/2015#,""dd/mm/yyyy"")<=Format(#01/05/2015#,""dd/mm/yyyy"")"
Debug.Print "Resultado 8: " & Eval(expressao)

这是使用相应控件的绑定字段的 ValidationRule 测试任何表单控件的值的最终代码。您只需在表单源表中设置一次 ValidationRule 并使用此 ValidationRule 来测试每个控件,然后再保存记录集更改。如果它通过了测试,则没有任何反应,但如果它失败了,您可以向用户显示 ValidationText 并将 SetFocus 显示给相应的控件以进行适当的更改。

Private Function TestarValidationRule(tela As Form, campoTestado As Control) As Variant
    'Author: Alex Borges
    'Location: Rio de Janeiro, Brazil
    'With the help of Adrian and Mat
    On Error GoTo ErroGeral
    Dim registro As DAO.Recordset
    Dim regraValidacao As Variant
    Dim textoValidacao As Variant
    Dim resultado As Variant
    Dim mensagem As String
    Dim expressao As String

    Set registro = tela.Recordset

    regraValidacao = registro.Fields(Right(campoTestado.Name, Len(campoTestado.Name) - 4)).ValidationRule
    textoValidacao = registro.Fields(Right(campoTestado.Name, Len(campoTestado.Name) - 4)).ValidationText

    'Campo sem regra de validação
    If ((regraValidacao & "") = "") Then
        GoTo Erro1

    'Campo com regra de validação
    Else
        Select Case VarType(campoTestado.Value)
            Case vbString
                expressao = """" & CStr(campoTestado.Value) & """" & regraValidacao
                expressao = Replace(expressao, "And ", "And """ & CStr(campoTestado.Value) & """")
                expressao = Replace(expressao, "Or ", "Or """ & CStr(campoTestado.Value) & """")
            Case vbDate
                expressao = "#" & Format(campoTestado.Value, "mm/dd/yyyy") & "#" & regraValidacao
                expressao = Replace(expressao, "And ", "And #" & Format(campoTestado.Value, "mm/dd/yyyy") & "#")
                expressao = Replace(expressao, "Or ", "Or #" & Format(campoTestado.Value, "mm/dd/yyyy") & "#")
                expressao = Replace(expressao, "Now()", "#" & Format(Now(), "mm/dd/yyyy") & "#")
        End Select

        resultado = Null
        resultado = Eval(expressao)

        If (resultado = -1) Then
            TestarValidationRule = vbSim

        'Se campo não passou na regra de validação
        ElseIf (resultado = 0) Then
            'Campo deveria ter texto de validação, mas, não tem
            If ((textoValidacao & "") = "") Then
                    mensagem = MsgBox("Este campo deveria apresentar instruções de preenchimento já que não passou no teste de validação." & Chr(13) + Chr(10) & _
                        "Favor, informar ao desenvolvedor do sistema.", vbExclamation + vbOKOnly, "Validação do Campo")
            Else
                mensagem = MsgBox(textoValidacao, vbInformation + vbOKOnly, "Validação do Campo")
            End If

            campoTestado.SetFocus
            TestarValidationRule = vbNao

        'Se teste gerou um resultado inesperado
        Else
            GoTo ErroGeral
        End If
    End If

Sair:
    Set registro = Nothing
    Exit Function
ErroGeral:
    TestarValidationRule = CVErr(513)
    GoTo Sair
Erro1:
    'Resultado de campo sem regra de validação
    TestarValidationRule = Null
    GoTo Sair
End Function

【问题讨论】:

  • 那一点仍然比较String的值。见my answer
  • 它无论如何都不起作用。 Eval 将 Format 结果转换为日期,因此它不是在比较字符串。
  • ?typename(Format(#30/04/2015#,"dd/mm/yyyy")) 在即时窗格中输出String。我不知道Eval 做了什么,但是Format 函数是在VBA.Strings 模块中定义的,所以是的,它是在比较字符串。
  • MSDN 不是这么说的。

标签: ms-access vba


【解决方案1】:

它返回 False,因为您没有比较日期 - 您正在比较返回 String 值的 Format 调用的结果。

"30*" &lt;= "01*"False

删除 Format 来比较日期文字,然后使用可排序的日期格式:

expressao = "#2015-04-30# <= #2015-05-01#"

【讨论】:

  • 嗨,垫子。我按照你所说的开始了我的测试,只比较了没有格式的日期,但是,我带来了一个错误的结果。 expressao = "#30/04/2015#
  • 但对我来说不是。它仍然返回错误。我想分享我的打印屏幕。
  • expressao = "#2015-04-30# 它返回 "Resultado 5: 0"
  • 好的垫子。 expressao = "#2015/04/30#
【解决方案2】:

正如几位提到的,您的原件:

expressao = "Format(#30/04/2015#,""Short Date"")<=Format(#01/05/2015#,""Short Date"")"

永远不会工作。有两个原因:

  1. 您比较的是字符串而不是日期。

  2. 您的日期值语法错误

语法必须是 mm/dd/yyyy 或 - 首选 - yyyy/mm/dd。

如果您使用 dd/mm/yyyy,Access 足够聪明,可以确定 30/04/2015 应该读作 04/30/2015。

所以跟随马特:

expressao = "#2015-04-30# <= #2015-05-01#"

这永远不会失败。

【讨论】:

  • 很抱歉重述了一遍,但听起来你不明白为什么即使在 Mat 向你展示了如何做之后它也不起作用。
  • 对我来说,如果你想重述一些事情,没有必要说对不起,但是,你为什么删除我的上一篇文章?你觉得里面有什么冒犯的地方吗?
  • 嗯..?我不删除cmets...甚至不能这样做。
  • 好吧,我不知道管理员遵循什么规则(或者即使他们有),但是这里发生了奇怪的事情,比如我的帖子被神秘地删除了。我对你的错误肯定表示抱歉。你看过我上面发布的最终代码吗?使用此代码,我可以在表格设置中将验证规则设置为它们各自的验证文本,然后以编程方式测试表单控件的值。如果您发现任何错误,如果您让我知道,我将不胜感激。从我发帖到现在,我做了一些改变,试图进一步改进。
  • 是的。如下所述,您已恢复为日期表达式的无效 dd/mm/yyyy 语法 - 转换为 yyyy/mm/dd 是多余的。您也可以使用 yyyymmdd 格式,但是,日期应该像日期一样处理,而不是字符串或整数,没有例外。正如多次提到的,Mat 的解决方案很中肯:expressao = "#2015-04-30#
【解决方案3】:

我假设你对它为什么返回 0 感到困惑?这是因为在 vba 中 0=false,-1=true。如果这个假设是正确的,那么在这种情况下得到错误使用以下内容:

Debug.Print "Resultado 6: " & cbool(Eval(expressao)) 

希望对您有所帮助。

编辑:好的,这很有趣,## 似乎将日期格式化为 dd/mm/yyyy 但有趣的是,如果你 debug.print #01/05/2015# 输出是 05/01/2015 这就是它结束的原因起来是假的。删除##...

有关此方面的更多信息,请参阅: http://www.vb123.com/Pages/kb/200309_ds_aa.aspx

它相当长,但似乎比我现在能解释得更好。

【讨论】:

  • 你好阿德里安。我知道-1是真的,0是假的。我不知道为什么这个表达式在假设返回 true (-1) 时返回 false (0)。感谢你的协助。日期 1 早于日期 2。
  • 我的本地日期格式是 dd/mm/yyyy,与美国格式 mm/dd/yyyy 不同。我怀疑这会以某种方式干扰。这就是为什么我添加了格式(日期,“短日期”),但没有成功。日期 1 来自表单控件,日期 2 来自表字段的 ValidationRule。也许日期 1 格式是 dd/mm/yyyy 但日期 2 是 mm/dd/yyyy。
  • #date# 转换为 mm/dd/yy。
  • 如果两个日期都被转换为 mm/dd/yy 为什么它仍然会带来错误的结果?我要比较的是(2015 年 4 月 30 日
  • 嗯,2015 年 4 月 30 日似乎没有被转换。