减少单元格中的行数 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
如果需要,很乐意提供进一步的帮助。
我有一个 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
如果需要,很乐意提供进一步的帮助。