1

我有一个从管理不善的旧数据库导入的非标准化字符串的大列表(一个包含一个字段的表)。我需要提取在每个字符串中恰好出现一次的一位数(由空格包围)(尽管字符串有时也有其他多位数)。例如,从以下字符串:

"Quality Assurance File System And Records Retention Johnson, R.M. 004 4 2999 ss/ds/free ReviewMo = Aug Effective 1/31/2012 FileOpen-?"

我想拉数字4(或字符串中 4 的位置,即 71)

我可以用

WHERE rsLegacyList.F1 LIKE "* # *" 

select语句中查找每个字符串是否有一个单独的数字,从而过滤我的列表。但它并没有告诉我数字在哪里,所以我可以提取数字本身(使用mid()函数)并开始对列表进行排序。目标是使用该数字本身创建第二个字段,作为对第一个字段中较大字符串进行排序的方法。

有没有办法Instr()与正则表达式一起使用来查找正则表达式在较大字符串中出现的位置?就像是

intMarkerLocation = instr(rsLegacyList.F1, Like "* # *")

但这真的有效吗?

我感谢任何完全避免该问题的建议或解决方法。


@Lee Mac,我做了一个RegExFindStringIndex如下所示的函数:

Public Function RegExFindStringIndex(strToSearch As String, strPatternToMatch As String) As Integer

    Dim regex                       As RegExp
    Dim Matching                    As Match

    Set regex = New RegExp

    With regex
        .MultiLine = False
        .Global = True
        .IgnoreCase = False
        .Pattern = strPatternToMatch
        Matching = .Execute(strToSearch)
        RegExFindStringIndex = Matching.FirstIndex
    End With

    Set regex = Nothing
    Set Matching = Nothing
End Function

但它给了我一个错误Invalid use of property at lineMatching = .Execute(strToSearch)

4

2 回答 2

1

使用正则表达式

如果要使用正则表达式,则需要定义一个 VBA 函数来实例化 RegExp 对象,将pattern属性设置为类似\s\d\s(whitespace-digit-whitespace) 的内容,然后调用该Execute方法来获取一个(或多个)匹配项,每个其中将提供字符串中模式的索引。如果你想走这条路,这里有一些 Excel 的现有示例,但 RegExp 操作在 MS Access 中是相同的。

这是一个示例函数,演示如何使用该Execute方法返回的第一个结果:

Public Function RegexInStr(strStr As String, strPat As String) As Integer
    With New RegExp
        .Multiline = False
        .Global = True
        .IgnoreCase = False
        .Pattern = strPat
        With .Execute(strStr)
            If .Count > 0 Then RegexInStr = .Item(0).FirstIndex + 1
        End With
    End With
End Function

请注意,上面使用了早期绑定,因此您需要在项目中添加对Microsoft VBScript 正则表达式 5.5库的引用。

立即窗口评估示例:

?InStr("abc 1 123", " 1 ")
 4 
?RegexInStr("abc 1 123", "\s\w\s")
 4 

使用 InStr

在查询中使用内置instr函数的替代方法可能是以下不优雅(可能非常慢)的查询:

select
    switch
    (
        instr(rsLegacyList.F1," 0 ")>0,instr(rsLegacyList.F1," 0 ")+1,
        instr(rsLegacyList.F1," 1 ")>0,instr(rsLegacyList.F1," 1 ")+1,
        instr(rsLegacyList.F1," 2 ")>0,instr(rsLegacyList.F1," 2 ")+1,
        instr(rsLegacyList.F1," 3 ")>0,instr(rsLegacyList.F1," 3 ")+1,
        instr(rsLegacyList.F1," 4 ")>0,instr(rsLegacyList.F1," 4 ")+1,
        instr(rsLegacyList.F1," 5 ")>0,instr(rsLegacyList.F1," 5 ")+1,
        instr(rsLegacyList.F1," 6 ")>0,instr(rsLegacyList.F1," 6 ")+1,
        instr(rsLegacyList.F1," 7 ")>0,instr(rsLegacyList.F1," 7 ")+1,
        instr(rsLegacyList.F1," 8 ")>0,instr(rsLegacyList.F1," 8 ")+1,
        instr(rsLegacyList.F1," 9 ")>0,instr(rsLegacyList.F1," 9 ")+1,
        true, null
    ) as intMarkerLocation
from
    rsLegacyList
where 
    rsLegacyList.F1 like "* # *" 
于 2020-01-15T23:38:09.553 回答
0

怎么样:

select
    instr(rsLegacyList.F1, " # ") + 1 as position
from rsLegacyList.F1
where rsLegacyList.F1 LIKE "* # *"
于 2020-01-15T23:33:39.900 回答