2017-08-29 14 views
1

我想验证我的Access窗体中的文本框中的条目。文本框背后的字段存储识别每个项目记录的项目编号。我们目前在文本框的before_update事件中有一个非常复杂的Do While循环,它可以成功地验证事件,但我正在收紧代码并希望了解如何进行更优雅的正则表达式验证。这是技术细节。通过VBA和正则表达式验证Access项目编号字段

项目编号有一个标准格式,如PJ17-14-000,分成三个块,用破折号分隔。这是每个块的规则。

第一个区块是项目类型/会计年度区块。前两个字符总是字母字符,并且它们会更改以反映不同的高级项目类型。 PJ,EL,RM,ER是一些例子,但这些可以是任何两个字母字符。然后接下来的两个字符总是数字,并反映项目开始的财政年度。例如,PJ17-14-000开始于2017财年。

第二个块只是一个数字,表示项目建立的顺序。所以PJ17-1-000是第一个在2017财年开始的PJ项目.PJ17-2-000是第二个。等等。这个数字的位数没有理论上的限制,但实际上从来没有超过四位数。 但是,这很重要,前面的数字不能为零。所以我们永远不会使用像PJ17-01-000这样的项目编号,验证应该拒绝这样的编号。相反,分析师应该简单地输入PJ17-1-000。

最后,最后一个块总是只有三个数字字符表示子项目。大多数项目只有一个部分(没有子项目),所以最后一个块只是000.但是有些项目有很多子项目,所以它们可能有PJ17-1-001,PJ17-1-002,PJ17-1-003(等等)记录。对于第三块,数字可以(通常是)具有前导零。

这些是项目号码本身的规则。以下是有趣的部分:我们的数据库允许分析师在项目字段中输入由空格分隔的多个项目编号。 (我知道有更好的设计使用链接表和子表单,但这是我们的遗留系统。)为什么一个项目有两个数字是一个漫长而复杂的故事,但有时(通常)他们这样做,我们必须允许为了那个原因。因此项目编号字段可能需要(因此应该允许)合计项目编号,例如“PJ17-1-000 ER16-143-000 PI16-23-000”。

因此,验证应该遵循上述规则,适用于任何单个项目编号,并且应该允许任意数量的项目编号由一个空格分隔。我会怎么做?

我开始玩vbscript.regexp,但无法弄清楚如何解决这个复杂的问题。欣赏任何关于如何做这项工作的帮助,或者您认为比我们目前的野兽更优雅,更易于阅读/维护的任何其他方法。

回答

2

使用

^[A-Z]{2}\d{2}-[1-9]\d*-\d+(?: [A-Z]{2}\d{2}-[1-9]\d*-\d+)*$ 

regex demo

单个项目码型为[A-Z]{2}\d{2}-[1-9]\d*-\d+

  • [A-Z]{2} - 2个ASCII大写字母(注意:如果objRegEx.IgnoreCase = True那么这也将匹配小写ASCII字母)
  • \d{2} - 2位数字
  • - - 连字符
  • [1-9]\d* - 从19一个数字,然后0+任何数字
  • - - 连字符
  • \d+ - 1或多个数字。

整个图案是^<code>(?: <code>)*$

  • ^ - 串
  • 的开始
  • <code> - 零个或更多个序列 - 上述
  • (?: <code>)*如所描述的项目代码图案:
    • - 空间
    • 串的端 -
    • <code> - 上述
  • $如所描述的项目的代码的模式。

VBA代码:

Function IsProjCodeValid(s As String) As Boolean 
    Dim objRegEx As Object 
    Set objRegEx = CreateObject("VBScript.RegExp") 
    objRegEx.IgnoreCase = True 
    objRegEx.Pattern = "^[A-Z]{2}\d{2}-[1-9]\d*-\d+(?: [A-Z]{2}\d{2}-[1-9]\d*-\d+)*$" 

    IsProjCodeValid = objRegEx.Test(s) 
End Function 
+0

哇,这是快!我认为可能需要调整的一件事是子项目编号的代码。这不仅仅是“一个或多个数字”。它恰好是三位数字。所以我认为调整将简单地将\ d +更改为\ d {3}。似乎工作。这听起来正确吗? –

+0

@EmilyFTW:如果位数总是3,那么使用'\ d {3}'。 –