减少单元格中的行数 Breaks/chr(10)

Reducing number of Line Breaks/chr(10) in a Cell

我有一个 excel sheet 单元格,其中的换行符数量可变,我想减少它,以便每行之间只有一个换行符。

例如

HELLO




WORLD



GOODBYE

将修改为:

HELLO 

WORLD

GOODBYE

我已经为此苦苦思索了几个小时,想出了一些方法,但 none 非常有效或产生了最好的结果。

这变得特别困难,因为我使用的数据集在换行符之前有空格。

因此常规解析也不起作用。

我尝试用 ~ 替换单元格中 chr(10) 的所有实例,以使其更易于使用,但我仍然没有得到确切的数量。我想知道有没有更好的方法。

这是我目前的情况:

 myString = Replace(myString, Chr(10), "~")

    Do While InStr(myString, "~~") > 0
        str1 = Split(myString, "~")
        For k = 0 To UBound(str1)
        myString = Replace(myString, "~~", "~")
        Next k
    Loop

    Do While InStr(myString, "   ~") > 0
        str1 = Split(myString, "~")
        For k = 0 To UBound(str1)
        myString = Replace(myString, "  ~", "")
        Next k
    Loop

myString = Replace(myString, "   ~", " ~")
myString = Replace(myString, " ~", "~")
myString = Replace(myString, "~", Chr(10))

Cells(2, 2).Value = myString

所以我使用了一些 do while 循环来捕获不同类型的换行符(或在本例中为波浪符)的实例,但我认为这不是解决此问题的最佳方法。

我在想办法循环遍历单元格中的字符,如果有多个chr(10)的例子,用""代替。

所以伪代码看起来像:

for i to len(mystring)
    if mystring(i) = chr(10) AND myString(i+1) = chr(10) Then
       myString(i + 1) = ""

但不幸的是,我认为这不可能通过 vba 实现。

如果有人好心帮我调整我目前的代码或协助我完成上述伪代码,将不胜感激!

你可以用一个公式来做:

=SUBSTITUTE(SUBSTITUTE(TRIM(SUBSTITUTE(SUBSTITUTE(SUBSTITUTE(TRIM(A1)," ","|"),"|"&CHAR(10)," "),CHAR(10)," "))," ",CHAR(10)),"|"," ")

这会将所有 space 更改为 |,然后将 Char(10) 更改为 space。 trim 删除了额外的 space。我们反过来,space 到 Char(10)| 到 spaces.


VBA:

Function manytoone(str As String)
    str = Replace(Application.Trim(str), " ", "|")
    str = Replace(str, "|" & Chr(10), " ")
    str = Replace(str, Chr(10), " ")
    str = Application.Trim(str)
    str = Replace(str, " ", Chr(10))
    str = Replace(str, "|", " ")
    manytoone = str

End Function

VBA 方法会将连续的 vbLf 常量替换为单个常量。

循环遍历字符串,只要有多个 vbLf 在一起,删除后,替换字符串。

Sub RemoveExcessLinebreaks()

    Dim s As String, rng As Range
    Set rng = ThisWorkbook.Worksheets(1).Range("B4")
    s = rng.Value

    While InStr(1, s, vbLf & vbLf) > 0
        s = Replace(s, vbLf & vbLf, vbLf)
    Wend

    rng.Value = s

End Sub

显然,您需要根据您的目的修改 rng 对象,或者将其变成子本身的参数。

vbLf 是 "LineFeed" 的常量。换行有多种类型,例如 vbCr(Carriage Return)或 vbCrLf(组合)。在单元格中按 Alt + Enter 似乎使用 vbLf 变体,这就是为什么我在其他常量上使用此常量。

您可以使用正则表达式。

下面的正则表达式模式删除了任何包含零到任意数量的空格的行,以及它的终止 crlf,并且还删除了最后一个单词末尾的 crlf。

Option Explicit
Sub trimXSLF()
    Dim myRng As Range, myCell As Range, WS As Worksheet
    Dim RE As Object
    Const sPat As String = "^\s*[\x0A\x0D]+|[\x0A\x0D](?!\s*\S+\s*)"
    Const sRepl As String = ""

Set WS = Worksheets("sheet4") 'or whatever
With WS
    Set myRng = .Range(.Cells(1, 1), .Cells(.Rows.Count, 1).End(xlUp))
End With

Set RE = CreateObject("vbscript.regexp")
With RE
    .Global = True
    .MultiLine = True
    .Pattern = sPat

    For Each myCell In myRng
        myCell = .Replace(myCell.Value2, sRepl)
    Next myCell

End With
End Sub

如果 myRng 很大(数万行),宏可以 运行 在 VBA 数组上处理以提高速度。

这已经得到很好的回答,但还没有满足其中一个要求(每行之间有 1 行),所以这是我回答这个问题的看法。详情请通过代码查看评论:

Option Explicit

Sub reduceNewLines()

Dim ws As Worksheet: Set ws = ActiveWorkbook.Sheets("Sheet1")
Dim lRow As Long: lRow = ws.Cells(ws.Rows.Count, 1).End(xlUp).Row
Dim lCol As Long: lCol = ws.Cells(1, ws.Columns.Count).End(xlToLeft).Column
Dim arrData As Variant: arrData = ws.Range(ws.Cells(1, 1), ws.Cells(lRow, lCol))
Dim arrVal() As String
Dim R As Long, C As Long, X As Long

For R = LBound(arrData) To UBound(arrData) 'Iterate through each row of data
    For C = LBound(arrData, 2) To UBound(arrData, 2) 'iterate through each column of data (though might be just 1)

        arrVal = Split(arrData(R, C), Chr(10)) 'allocate each row to an array, split at new line

        arrData(R, C) = "" 'reset the data inside this field

        For X = LBound(arrVal) To UBound(arrVal)
            arrVal(X) = Trim(arrVal(X)) 'clear leading/trailing spaces
            If Left(arrVal(X), 1) <> " " And arrVal(X) <> "" Then
                arrData(R, C) = arrData(R, C) & arrVal(X) & Chr(10) & Chr(10) 'allocate new data + 2 lines
            End If
        Next X

        arrData(R, C) = Left(arrData(R, C), Len(arrData(R, C)) - 2) 'remove the last 2 extra new lines
    Next C
Next R

ws.Range(ws.Cells(1, 1), ws.Cells(lRow, lCol)) = arrData 'allocate the data back to the sheet

End Sub

如果需要,很乐意提供进一步的帮助。