【问题标题】:Function to trim leading and trailing whitespace in vba在 vba 中修剪前导和尾随空格的功能
【发布时间】:2014-07-25 18:00:48
【问题描述】:

我已经检查了很多关于在 vba 中修剪前导和尾随空格的建议(顺便提一下,excel)。

我找到了这个解决方案,但它也修剪了 å ä ö(也是大写字母),而且我的正则表达式太弱了,看不出原因:

Function MultilineTrim (Byval TextData)
    Dim textRegExp
    Set textRegExp = new regexp
    textRegExp.Pattern = "\s{0,}(\S{1}[\s,\S]*\S{1})\s{0,}"
    textRegExp.Global = False
    textRegExp.IgnoreCase = True
    textRegExp.Multiline = True

    If textRegExp.Test (TextData) Then
      MultilineTrim = textRegExp.Replace (TextData, "$1")
    Else
      MultilineTrim = ""
    End If
End Function

(这是来自 SO 的答案,其中用户帐户似乎处于非活动状态:

https://stackoverflow.com/a/1606433/3701019 )

因此,如果有人可以提供 (a) 问题的替代解决方案或 (b) 不会删除(单个)åäö 字符的正则表达式/代码版本,我会很高兴。

感谢您的帮助!

详情: 问题

  • vba 中的修剪函数不考虑所有空白字符(例如制表符)。需要一些自定义修剪
  • 上面是我找到的最佳解决方案,但它也删除了单个 å ä ö 字符。

我的上下文是 vba 中的 xmlparser,它获取要解析的 xml 块。有时它只是从流中获取一个字符,可能是 å ä ö,然后此函数将其完全剥离。

当然,我很乐意澄清或编辑这个问题。

仅供参考:我已经根据答案准确地分享了我所做的事情,见下文。

【问题讨论】:

  • Regex 可能不是解决这个问题的正确方法:它们可以工作,但速度很慢,每次调用 Trim() 函数时,您最终都会创建一个新的 Regex 对象,这如果在从 text/xml 文件中解析令牌时使用该函数,可能会很多并且会增加很多开销。我会在这方面走老路,并简单地使用老式的字符串操作函数。
  • 感谢您的回复。你是对的,没有实例!但我认为没有必要每次都实例化正则表达式。在将这个小 sn-p 添加到我的代码中时,我将它放在一个类中并重用正则表达式,因此只创建一个实例。一般来说,(数据检索)代码的性能瓶颈在别处。
  • 如果您只是将其用作普通的辅助函数,则不一定需要创建一个类。您可以只使用 Static 声明而不是 Dim 作为函数本身内部的正则表达式,并在第一次使用时对其进行初始化。
  • 关于我为什么回滚你的第二个版本的解释,请阅读Is it OK for users to edit the accepted answer into their question?
  • 好的,@Air,谢谢。我读了你提到的帖子,但我不明白它想让我做什么。所以我asked specifically 并得到了一些其他的观点,所以现在我理解并添加了我在下面所做的事情。自然,接受的答案仍然保持不变,尽管它没有准确地捕捉到我所做的,我试图澄清这一点。

标签: regex excel vba trim


【解决方案1】:

重构和改进的 Richard Vivians 版本

Function cleanMyString(sInput)
    ' Remove leading and trailing spaces
    sInput = Trim(sInput)
    'Remove other characters that you dont want
    sInput = Replace(sInput, Chr(10), "")
    sInput = Replace(sInput, Chr(13), "")
    sInput = Replace(sInput, Chr(9), "")
    cleanMyString = sInput
End Function

【讨论】:

    【解决方案2】:

    consulting with stackexchange people on how to do this 之后,我将添加问题的编辑作为我自己的答案。这里是:

    答案/使用的代码

    感谢答案,这就是我将要使用的:

    Function MultilineTrim(ByVal TextData)
        MultilineTrim = textRegExp.Replace(TextData, "")
    
    '    If textRegExp.Test(TextData) Then
    '        MultilineTrim = textRegExp.Replace(TextData, "$1")
    '    Else
    '        MultilineTrim = "" ' ??
    '    End If
    End Function
    
    Private Sub InitRegExp()
        Set textRegExp = New RegExp
        'textRegExp.Pattern = "\s{0,}(\S{1}[\s,\S]*\S{1})\s{0,}" 'this removes å ä ö - bug!
        'textRegExp.Global = False
    
        'textRegExp.Pattern = "(^[ \t]+|[ \t]+$)" ' leaves a line break at start
        textRegExp.Pattern = "^[\s\xA0]+|[\s\xA0]+$" ' works! Ron Rosenfelds submit
    
        textRegExp.Global = True
    
        textRegExp.IgnoreCase = True
        textRegExp.MultiLine = True
    End Sub
    

    再次感谢大家! (向罗恩·罗森菲尔德点头)

    【讨论】:

      【解决方案3】:

      我会在替换所有其他字符后调用 Trim。这样,如果其他字符后面有空格,它们也会被删除。

      【讨论】:

        【解决方案4】:

        您可以创建一个自定义函数来去除您不想要的字符。

        Private Function CleanMyString(sInput As String) As String
           Dim sResult As String
        
           ' Remove leading ans trailing spaces
           sResult = Trim(sInput)
           'Remove other characters that you dont want
           sResult = Replace(sResult, chr(10), "")
           sResult = Replace(sResult, chr(13), "")
           sResult = Replace(sResult, chr(9), "")
        
        End Function
        

        虽然这不使用正则表达式。不确定这是否符合您的要求?

        【讨论】:

        • 这不起作用,因为Replace() 还会删除字符串内部的空白字符,而不仅仅是字符串边缘。此外,没有char() 函数,而是Chr()(或者,效率更高一点,Chr$())。
        • 另一个小问题,但您可以使用 vbTabvbCrvbLf 常量而不是 9、10、13。使用 vbNullString 而不是空值也稍微高效一些"" 字符串,因为该常量已经定义,并且 VBA 引擎不必为遇到的每个 "" 重新分配一个新的空字符串,它将重新使用由常量定义的字符串。 (在这些优化中,VBA 引擎不如 VB.Net 智能)。
        • 道歉。在答案中将 char 固定为 chr。感谢您对常数的更正。很高兴知道。
        【解决方案5】:

        对于我会使用的正则表达式:

        ^[\s\xA0]+|[\s\xA0]+$
        

        这将匹配 HTML 文档中常见的“常用”空白字符以及 NBSP。

        VBA 代码如下所示,其中 S 是要修剪的行:

        Dim RE as Object, ResultString as String
        Set RE = CreateObject("vbscript.regexp")
        RE.MultiLine = True
        RE.Global = True
        RE.Pattern = "^[\s\xA0]+|[\s\xA0]+$"
        ResultString = RE.Replace(S, "")
        

        以及正则表达式的解释:

        Trim whitespace at the start and the end of each line
        -----------------------------------------------------
        
        ^[\s\xA0]+|[\s\xA0]+$
        
        Options:  ^$ match at line breaks
        
        Match this alternative (attempting the next alternative only if this one fails) «^[\s\xA0]+»
           Assert position at the beginning of a line (at beginning of the string or after a line break character) «^»
           Match a single character present in the list below «[\s\xA0]+»
              Between one and unlimited times, as many times as possible, giving back as needed (greedy) «+»
              A “whitespace character” (ASCII space, tab, line feed, carriage return, vertical tab, form feed) «\s»
              The character with position 0xA0 (160 decimal) in the character set «\xA0»
        Or match this alternative (the entire match attempt fails if this one fails to match) «[\s\xA0]+$»
           Match a single character present in the list below «[\s\xA0]+»
              Between one and unlimited times, as many times as possible, giving back as needed (greedy) «+»
              A “whitespace character” (ASCII space, tab, line feed, carriage return, vertical tab, form feed) «\s»
              The character with position 0xA0 (160 decimal) in the character set «\xA0»
           Assert position at the end of a line (at the end of the string or before a line break character) «$»
        
        Created with RegexBuddy
        

        【讨论】:

        • 试过了,这似乎可以解决问题。打算用这个,谢谢!
        【解决方案6】:

        试试这个:

        Function MultilineTrim (Byval TextData)
            Dim textRegExp
            Set textRegExp = new regexp
            textRegExp.Pattern = "(^[ \t]+|[ \t]+$)"
            textRegExp.Global = True
            textRegExp.IgnoreCase = True
            textRegExp.Multiline = True
        
            MultilineTrim = textRegExp.Replace (TextData, "")
        End Function
        

        【讨论】:

        • 谢谢 - 试过这个,它似乎工作,除了它在开始时留下一个 crlf (或至少 cr 或 lf,无论如何,一个新行)。
        猜你喜欢
        • 2013-03-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-01-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多