VBA去除前导空格问题

3
我在尝试比较宏中的字符串,但数据输入不一致。差异在于前导空格的数量(例如,“ test”与“test”与“ test”)。
对于我的宏,示例中的三个字符串应该是等效的。但是我不能使用Replace,因为字符串中间的任何空格(如“test one two three”)都应该被保留。我原本以为这就是Trim应该做的事情(以及删除所有尾随空格)。但是当我在字符串上使用Trim时,我没有看到任何区别,并且我绝对会留下字符串前面的空格。
所以A)VBA中Trim真正的作用是什么?B)是否有内置函数可以实现我想要做的事情,还是我需要编写一个函数?
谢谢!

2
“Trim”会删除前导和尾随空格。你确定那是一个空格吗?尝试使用“Print Asc(Txt)”查看ASCII代码是否真的是32。 - stenci
你的数据要么在字符串开头没有空格(字符代码32),要么你的代码实现有误。VBA Trim函数在VBA帮助文件中有详细描述。它与同名的工作表函数略有不同。 - Ron Rosenfeld
6个回答

3

正如Gary's Student所说的,这个字符不是32,而实际上是160。作为一个简单的人来讲,空格就是空格。因此,我创建了以下函数,可以删除所有Unicode字符,这些字符对人眼无法显示(即非特殊字符、非字母数字字符)。该函数如下:

Function TrueTrim(v As String) As String
Dim out As String
Dim bad As String
bad = "||127||129||141||143||144||160||173||" 'Characters that don't output something
       'the human eye can see based on http://www.gtwiki.org/mwiki/?title=VB_Chr_Values

out = v

'Chop off the first character so long as it's white space
If v <> "" Then
    Do While AscW(Left(out, 1)) < 33 Or InStr(1, bad, "||" & AscW(Left(out, 1)) & "||") <> 0 'Left(out, 1) = " " Or Left(out, 1) = Chr(9) Or Left(out, 1) = Chr(160)
        out = Right(out, Len(out) - 1)
    Loop

    'Chop off the last character so long as it's white space
    Do While AscW(Right(out, 1)) < 33 Or InStr(1, bad, "||" & AscW(Right(out, 1)) & "||") <> 0 'Right(out, 1) = " " Or Right(out, 1) = Chr(9) Or Right(out, 1) = Chr(160)
        out = Left(out, Len(out) - 1)
    Loop
End If 'else out = "" and there's no processing to be done

'Capture result for return
TrueTrim = out
End Function

如果你要削减数据,我会选择使用正则表达式解决方案,它更通用和健壮。 - Jeanno
@Jeanno,下面的正则表达式解决方案没有捕获所有字符,而这个解决方案做到了。 - Ryu S.

2

TRIM()函数将删除所有前导空格。

Sub demo()
    Dim s As String
    s = "   test   "
    s2 = Trim(s)
    msg = ""
    For i = 1 To Len(s2)
        msg = msg & i & vbTab & Mid(s2, i, 1) & vbCrLf
    Next i
    MsgBox msg
End Sub

可能存在看不见但不是空格的字符,导致数据出现问题。


结果证明确实如此。我使用了Code(left({cell}m 1))来获取字符(对于那些好奇的人,是160)。鉴于此,我继续创建了一个函数来清除前导空格(任何代码值小于32、160和少数其他值)。 - JMichael

2

0
为什么不尝试使用Instr函数呢?像这样:
Function Comp2Strings(str1 As String, str2 As String) As Boolean
    If InStr(str1, str2) <> 0 Or InStr(str2, str1) <> 0 Then
        Comp2Strings = True
    Else
        Comp2Strings = False
    End If
End Function

基本上,您正在检查string1是否包含string2或string2是否包含string1。这始终有效,并且您无需修剪数据。


Comp2Strings = (InStr(str1, str2) <> 0 Or InStr(str2, str1) <> 0) 比较两个字符串 = (InStr(str1,str2)<> 0 或 InStr(str2,str1)<> 0) - Maciej Los
这将无法通过 str1 = " test"str1 = "test " - stenci
根据原帖,只有一个字符串会有前导或尾随空格。所以这个方法可以正常工作。 - Jeanno
这会告诉我是否有前导空格(或取决于str2的空格字符),但我需要清除后续存储的空格(抱歉在原始帖子中没有引用它,因为我没有考虑到它,我的问题是InStr返回0,而对于我的大脑来说,它应该返回一个> 0的值) - JMichael

0

VBA的Trim函数仅限于处理空格。它将删除字符串开头和结尾的空格。

为了处理换行符和制表符等内容,我一直导入Microsoft VBScript RegEx库并使用它来替换空白字符。

在您的VBA窗口中,转到工具,引用,然后找到Microsoft VBScript Regular Expressions 5.5。选中它并点击确定。

然后,您可以创建一个相当简单的函数来修剪所有空格,而不仅仅是空格。

Private Function TrimEx(stringToClean As String)
    Dim re As New RegExp
    ' Matches any whitespace at start of string
    re.Pattern = "^\s*"
    stringToClean = re.Replace(stringToClean, "")
    ' Matches any whitespace at end of string
    re.Pattern = "\s*$"
    stringToClean = re.Replace(stringToClean, "")
    TrimEx = stringToClean
End Function

据我所知,这应该可以工作。我只是从来不喜欢正则表达式,因为代码太密集了,很容易搞砸。 - JMichael
这对OP的问题无效。\s在vbscript中无法匹配NBSP(字符代码160)。但是,你可以使用类似[\s\xA0]的正则表达式,并设置适当的开头和结尾锚点以及多行集合设置为true。 - Ron Rosenfeld

0

非打印字符分隔网页的不同行。我分别用X、Y和Z替换了它们。

Debug.Print Trim(Mid("X test ", 2)) ' 在VBA中,第一个位置计为2

Debug.Print Trim(Mid("XY test ", 3)) ' 在VBA中,第二个位置计为3

Debug.Print Trim(Mid("X Y Z test ", 2)) ' 需要更多轮次 :)

程序员喜欢使用大文本,因为可以使用内置工具(如inSTR、Mid、Left等)进行整齐地切割。使用来自多个子元素的文本(即使用.textContent与.innerText)可能会导致需要处理多个非打印字符,但DOM和REGEX并不适合初学者。精确地处理内部文本的子元素(逐个子元素!)可能有助于避免非打印字符。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接