【问题标题】:Remove special characters from range in VBA从VBA中的范围中删除特殊字符
【发布时间】:2021-10-29 07:42:50
【问题描述】:

我创建了一个 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

【问题讨论】:

  • 我认为将 Mid(strVal, i, 1) = " " 更改为 Mid(strVal, i, 1) = "" 不起作用?
  • 将 Mid(strVal,i,1) = " " 替换为 Mid(strVal,i,1) = vbnullstring
  • 前参考,PQ option YT Video

标签: excel regex vba vba7 vba6


【解决方案1】:

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

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

【讨论】:

    【解决方案2】:

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

    • 测试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
    
    

    【讨论】:

      【解决方案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 ] 模式是一个否定字符类,它捕获了所有字母数字空格字符。您将在此在线demo 中找到更深入的解释。

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


      我想我会使用 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
      

      【讨论】:

        【解决方案4】:

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

        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
        

        【讨论】:

        • 这可能会替换 OP 想要保留的空格(即对应于 Case 32 中的 32...)
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-08-14
        • 2016-10-26
        • 2014-08-17
        • 1970-01-01
        • 2011-04-11
        • 2016-01-23
        相关资源
        最近更新 更多