2

我创建了一个 VBA 代码来删除列中可用的所有特殊字符。例如,我在列的每个单元格中有一个带有一些特殊字符的字母数字字符:假设在一个单元格中我有一个值:abc@123!-245 执行我的代码后,我得到了输出 abc 123 245 这里我的代码工作正常删除所有特殊字符。我的代码如下:

Sub ReplaceSpecial()
    Dim cel As Range
    Dim strVal As String
    Dim i As Long
    Application.ScreenUpdating = False
    For Each cel In Selection
        strVal = cel.Value
        For i = 1 To Len(strVal)
            Select Case Asc(Mid(strVal, i, 1))
                Case 32, 48 To 57, 65 To 90, 97 To 122
                    ' Leave ordinary characters alone
                Case Else
                    Mid(strVal, i, 1) = " "
            End Select
        Next i
        cel.Value = strVal
    Next cel
    Application.ScreenUpdating = True
End Sub

现在,如果我想删除我的输出空间,使输出看起来像 abc123245,如何在 VBA 中做到这一点?输入:abc@123!-245 电流输出:abc 123 245 所需输出:abc123245

4

4 回答 4

4

您可以仅使用允许的字符构造一个新字符串。

Sub ReplaceSpecial()
    Dim cel As Range
    Dim strVal As String, temp As String
    Dim i As Long
    Application.ScreenUpdating = False
    For Each cel In Selection
        strVal = cel.Value
        temp = vbNullString
        For i = 1 To Len(strVal)
            Select Case Asc(Mid(strVal, i, 1))
                Case 32, 48 To 57, 65 To 90, 97 To 122
                    temp = temp & Mid(strVal, i, 1)                   
            End Select
        Next i
        cel.Value = temp
    Next cel
    Application.ScreenUpdating = True
End Sub
于 2021-08-30T14:55:32.327 回答
4

我写这篇迟到的帖子的唯一目的是

  • 测试►<code>Application.Match() 函数的一些特性(将字符串输入与有效字符进行比较)并
  • 演示一种将字符串“拆分”为单个字符的好方法,作为替代且可能具有指导意义的解决方案(请参阅帮助功能String2Arr())。

但是,我打算在这里展示更好或更快的代码。

Application.Match()不仅允许在一个数组中执行 1 个字符搜索,还可以一次比较两个数组,即一个字符数组(基于原子化字符串输入)与一个有效字符数组(空格、所有数字和字符从 A 到Z)。由于Application.Match不区分大小写,因此采用例如小写字符就足够了。

输入字符的所有结果都会返回它们在有效字符数组中的位置(否则会导致错误 2042)。此外,有必要排除通配符“*”和“?”,否则它们将被视为发现。

Function ValidChars(ByVal s, Optional JoinResult As Boolean = True)
'Purp: return only valid characters if space,digits,"A-Z" or "a-z"
    'compare all string characters against valid characters
    Dim tmp: tmp = foundCharAt(s)   ' get array with found positions in chars
    'overwrite tmp array
    Dim i As Long, ii As Long
    For i = 1 To UBound(tmp)
        If IsNumeric(tmp(i)) Then                   ' found in valid positions
            If Not Mid(s, i, 1) Like "[?*]" Then    ' exclude wild cards
                ii = ii + 1
                tmp(ii) = Mid(s, i, 1)  ' get char from original string
            End If
        End If
    Next
    ReDim Preserve tmp(1 To ii)         ' reduce to new size
    'join tmp elements to resulting string (if argument JoinResult = True)
    ValidChars = IIf(JoinResult, Join(tmp, ""), tmp)
End Function

帮助功能foundCharAt()

返回有效字符数组中找到的字符位置数组:

Function foundCharAt(ByVal s As String) As Variant
'Purp: return array of found character positions in chars string
'Note: (non-findings show Error 2042; can be identified by IsError + Not IsNumeric)
    Dim chars: chars = String2Arr(" 0123456789abcdefghijklmnopqrstuvwxyz")
    foundCharAt = Application.Match(String2Arr(s), chars, 0)
End Function

帮助功能String2Arr()

在原子化字符串输入后分配单个字符数组:

Function String2Arr(ByVal s As String) As Variant
'Purp: return array of all single characters in a string
'Idea: https://stackoverflow.com/questions/13195583/split-string-into-array-of-characters
    s = StrConv(s, vbUnicode)
    String2Arr = Split(s, vbNullChar, Len(s) \ 2)
End Function

于 2021-08-31T19:21:30.940 回答
3

使用正则表达式的对象并使用否定字符类替换所有不需要的字符。出于演示目的:

Sub Test()

Dim str As String: str = "abc@123!-245"

With CreateObject("vbscript.regexp")
    .Global = True
    .Pattern = "[^0-9A-Za-z ]"
    str = .Replace(str, "")
End With

Debug.Print str

End Sub

该模式[^0-9A-Za-z ]是一个否定字符类,并捕获了所有不是字母数字空格字符的内容。您将在此在线演示中找到更深入的解释。

在撰写本文时,我不确定您是否要省略空格字符。如果是这样,只需从模式中删除空间。


以为我会使用Like()操作员换一种选择:

For i = Len(str) To 1 Step -1
    If Mid(str, i, 1) Like "[!0-9A-Za-z ]" Then
        str= Application.Replace(str, i, 1, "")
    End If
Next

或者使用第二个字符串类型变量(根据@BigBen 的回答):

For i = 1 to Len(str)
    If Mid(str, i, 1) Like "[0-9A-Za-z ]" Then
        temp = temp & Mid(str, i, 1)
    End If
Next
于 2021-08-30T15:45:09.940 回答
2

如果您想在当前工作的基础上再接再厉,请替换:

cel.Value = strVal

和:

cel.Value = Replace(strVal, " ", "")

考虑:

Sub ReplaceSpecial()
    Dim cel As Range
    Dim strVal As String
    Dim i As Long
    Application.ScreenUpdating = False
    For Each cel In Selection
        strVal = cel.Value
        For i = 1 To Len(strVal)
            Select Case Asc(Mid(strVal, i, 1))
                Case 32, 48 To 57, 65 To 90, 97 To 122
                    ' Leave ordinary characters alone
                Case Else
                    Mid(strVal, i, 1) = " "
            End Select
        Next i
        cel.Value = Replace(strVal, " ", "")
    Next cel
    Application.ScreenUpdating = True
End Sub
于 2021-08-30T15:24:04.410 回答