【问题标题】:Is it possible to write this VBA code any better?是否可以更好地编写此 VBA 代码?
【发布时间】:2011-12-06 07:02:55
【问题描述】:

我在这里重新发明轮子吗?有一个更好的方法吗?此 VBA 函数在 Access 中的表单的注释字段中查找字符串的第一个实例,该字符串包含 20 个或更少字符,没有空格,用 (~) 波浪线括起来,然后返回它。

Public Function ParseComment(strComment As String) As String

'  This function parses the comment field of the job entry dialog for (~) tilde 
'  surrounded text, then returns that text.

Dim intCounter As Integer
Dim intFirstChar As Integer
Dim intLastChar As Integer
Dim strResult As String

intFirstChar = 0
intLastChar = 0
intCounter = 0

Do While (intLastChar = 0) And (intCounter < Len(strComment))
    intCounter = intCounter + 1

    strCharacter = Mid(strComment, intCounter, 1)

    If (strCharacter = "~") Then
        If intFirstChar Then
            intLastChar = intCounter
        Else
            intFirstChar = intCounter + 1
        End If
    End If

Loop

strResult = Mid(strComment, intFirstChar, intLastChar - intFirstChar)

If (intLastChar - intFirstChar <= 20) And (intFirstChar <> 0 Or intLastChar <> 0) And Not InStr(strResult, " ") Then
    ParseComment = strResult
End If

End Function

非常感谢。

【问题讨论】:

  • 总是可以更好地编写代码,但如果这对你有用,为什么还要麻烦?
  • 只是一个旁注,你可以做Dim intFirstChar as Integer=0 它可以用你所有的初始化来清理代码,当你声明它们时初始化它们。
  • @JonH "Dim intFirstChar As Integer = 0" 将导致 VBA 中的编译错误。 VBA 已经将局部整数变量初始化为零,因此即使有可能也毫无意义。但是它可以在 VB.NET 中运行。
  • 啊好吧不知道,只是注意到它是 vba,以为他只是在做 vb.net。谢谢
  • 这个问题很危险地接近投票结束“不具建设性”或“不是一个真正的问题”,因为“喋喋不休的开放式问题会降低我们网站的实用性并将其他问题排除在外首页。” (常见问题解答)我认为您应该明确表达担忧并缩小问题范围。只是说。

标签: ms-access vba


【解决方案1】:

我会使用InStr 来查找~ 字符的第一次和第二次出现,类似这样,而不是手动循环:

Public Function ParseComment(strComment As String) As String

'  This function parses the comment field of the job entry dialog for (~) tilde
'  surrounded text, then returns that text.

Dim firstTilde As Integer
Dim secondTilde As Integer
Dim strResult As String

firstTilde = 0
secondTilde = 0
strResult = ""

firstTilde = InStr(strComment, "~")

If firstTilde > 0 Then

    secondTilde = InStr(firstTilde + 1, strComment, "~")

    If (secondTilde > 0) And (secondTilde < 20) Then

        strResult = Mid(strComment, firstTilde, secondTilde)

        If InStr(strResult, " ") = 0 Then

            ParseComment = strResult
        End If
    End If
End If

End Function

[免责声明,我没有测试过这个!]

【讨论】:

    【解决方案2】:

    使用内置函数可能会快一点,但不要想象它会产生重大影响...

    类似:

    Public Function getTildeDelimStringPart(inputstring As String) As String
    
    Dim commentStart As Long, commentEnd As Long
    
    commentStart = InStr(1, inputstring, "~")
    
    If commentStart = 0 Then ' no tilde
        getTildeDelimStringPart = vbNullString
        Exit Function
    End If
    
    commentEnd = InStr(1 + commentStart, inputstring, "~")
    If commentEnd = 0 Then
        getTildeDelimStringPart = vbNullString
        Exit Function
    End If
    
    getTildeDelimStringPart = Mid(inputstring, commentStart, commentEnd - commentStart + 1)
    
    End Function
    

    【讨论】:

    • 尽可能利用内置函数是一个好习惯。在某些情况下,在某些语言中它可能只是稍微快一点,但大多数时候你会赢。在instr的情况下,也部分是算法的改变。
    【解决方案3】:

    我看到每个人都给了你更多的方法来做到这一点(instr 是一个很好的方法,请参阅 Vicky 的回答!),所以我将列出一些优化代码的技巧:

    • 使用 Long 而不是 Integer。 VBA 每次都会将它们转换为 Long。
    • 在 VBA 中 Int 和 Long 的默认值是 0,所以不需要这样声明。
    • 使用 Mid$ 而不是 Mid
    • 使用 Instr() 将是查找 ~ 位置的一种非常有效的方法

    有趣的提示:如果您确实想评估每个字符,最快的方法是数字比较:

    if Asc(Mid$(strComment, intCounter, 1)) = 126 Then
    

    【讨论】:

      【解决方案4】:

      这对我有用:

      Public Function ParseComment(strComment As String) As String
      
      Dim regex As Object ' VBScript_RegExp_55.RegExp
      Dim regexmatch As Object ' VBScript_RegExp_55.MatchCollection
      Set regex = CreateObject("VBScript_RegExp_55.RegExp")
      
      With regex
        .MultiLine = False
        .Global = False
        .IgnoreCase = True
        .Pattern = "(~[^ ~]{1,20}~)"
      End With
      
      Set regexmatch = regex.Execute(strComment)
      
      If regexmatch.Count > 0 Then
        ParseComment = regexmatch(0)
      End If
      
      End Function
      

      如果要删除波浪号,可以在末尾添加额外的解析。

      我在以下字符串上对其进行了测试:

      ABC~123aA%dwdD~CBA

      函数返回~123aA%dwdD~

      忘记提及此代码需要位于 %windir%\system32\vbscript.dll\3 中的 VBScript 正则表达式 5.5,尽管该代码是后期绑定的,因此您应该可以将其放入您的项目中。

      【讨论】:

      • 您的正则表达式不遵循不允许空格(或其他〜)的模式。应该是 "(~[^ ~]{1,20}~)" 这将允许 1 到 20 个不是空格或 ~ 的字符。
      • 我不知道 VBA 可以做 RegEx。谢谢 JP,我要试试这个。
      • 我一般不会像问题中那样使用正则表达式进行简单的解析,因为正则表达式的开销没有足够的复杂性来处理,因此它通常比较慢。
      • @Issun -- OP 的代码不考虑波浪线中间字符串。我可能不应该在我的示例中包含“%”,因为 OP 声明他的字符串都是波浪线之间的文本。此外,字符数无关紧要。 OP 想要波浪线之间的所有字符。
      • OP 声明“20 个字符或更少”和“无空格”。如果你有~xxx~xx~你可以说2个波浪号之间有6个字符,但更正确的说法是波浪号包围的字符有2组,一组3个字符,一组2个。:)
      猜你喜欢
      • 2021-05-25
      • 1970-01-01
      • 2014-06-04
      • 1970-01-01
      • 2020-01-29
      • 2013-01-14
      • 2017-08-19
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多