Divide the cell content into separate rows in Exce

2019-06-04 04:40发布

I am trying to split the cell content with length greater than 72 into separate rows with their length not increasing more than 72 chars. I am not able to thing through this logic and need help. Special challenge here is that the content of each cell is is a complete sentence and has no delimiter, so I need to divide the statement only when a word ends and also having length 72 chars preserved for each cell and not more than that.

Any suggestions?

Thanks

2条回答
我想做一个坏孩纸
2楼-- · 2019-06-04 05:07

You can do this using regular expressions. Try adapting this macro, which I wrote some time ago, to your specific requirements: If a word should happen to be longer than w characters, it will overflow -- probably not a problem with 72 character line length; but you can change that behavior by changing the regex.

As written, the macro will write the split text into cells below the original.


Sub WordWrap()
'requires reference to Microsoft VBScript Regular Expressions 5.5
'Wraps at W characters, but will allow overflow if a word is longer than W
Dim RE As RegExp, MC As MatchCollection, m As Match
Dim str As String
Dim w As Long
Dim rSrc As Range, C As Range
Dim mBox As Long
Dim I As Long
'with offset as 1, split data will be below original data
'with offset = 0, split data will replace original data
Const lDestOffset As Long = 1

Set rSrc = Selection
    If rSrc.Rows.Count <> 1 Then
        MsgBox ("You may only select" & vbLf & " Data in One (1) Row")
        Exit Sub
    End If
Set RE = New RegExp
    RE.Global = True
w = InputBox("Maximum characters in a Line: ", , 72)
    If w < 1 Then w = 79
For Each C In rSrc
str = C.Value
'remove all line feeds and nbsp
    RE.Pattern = "[\xA0\r\n\s]+"
    str = RE.Replace(str, " ")
    RE.Pattern = "\S.{0," & w - 1 & "}(?=\s|$)|\S{" & w & ",}"
If RE.Test(str) = True Then
    Set MC = RE.Execute(str)
'see if there is enough room
I = lDestOffset + 1
Do Until I > MC.Count + lDestOffset
    If Len(C(I, 1)) <> 0 Then
        mBox = MsgBox("Data in " & C(I, 1).Address & " will be erased if you contine", vbOKCancel)
        If mBox = vbCancel Then Exit Sub
    End If
I = I + 1
Loop

    I = lDestOffset
    For Each m In MC
        C.Offset(I, 0).Value = m
        I = I + 1
    Next m
End If
Next C
Set RE = Nothing
End Sub

Example using your original post as the data in one cell:

enter image description here

Here is an explanation and links to explanations regarding the line-splitting regular expression, as it would be rendered with a line length of 72 characters.

\S.{0,71}(?=\s|$)|\S{72,}

\S.{0,71}(?=\s|$)|\S{72,}

Options: Case sensitive; ^$ match at line breaks (irrelevant in this instance)

Created with RegexBuddy

EDIT At the request of the original poster, a routine was added which would cycle through the cells in column A, placing the results of the splitting into column B. Some of the original code, allowing selection of line length and source selection, was hard-coded.


Option Explicit
Sub WordWrap2()
'requires reference to Microsoft VBScript Regular Expressions 5.5
'Wraps at W characters, but will allow overflow if a word is longer than W
Dim RE As RegExp, MC As MatchCollection, M As Match
Dim str As String
Const W As Long = 72
Dim rSrc As Range, C As Range
Dim vRes() As Variant
Dim I As Long

'Set source to column A
Set rSrc = Range("A1", Cells(Rows.Count, "A").End(xlUp))

Set RE = New RegExp
    RE.Global = True
    I = 0
    For Each C In rSrc
    str = C.Value

    'remove all line feeds and nbsp
    RE.Pattern = "[\xA0\r\n\s]+"
    str = RE.Replace(str, " ")
    RE.Pattern = "\S.{0," & W - 1 & "}(?=\s|$)|\S{" & W & ",}"

    If RE.Test(str) = True Then
        Set MC = RE.Execute(str)
        ReDim Preserve vRes(1 To MC.Count + I)
        For Each M In MC
            I = I + 1
            vRes(I) = M
        Next M
        Else  'Allow preservation of blank lines in source data
         I = I + 1
    End If
Next C

'if ubound(vres) > 16384 then will need to transpose in a loop
vRes = WorksheetFunction.Transpose(vRes)

With Range("B1").Resize(UBound(vRes, 1))
    .EntireColumn.Clear
    .Value = vRes
    .EntireColumn.AutoFit
End With

Set RE = Nothing
End Sub

查看更多
We Are One
3楼-- · 2019-06-04 05:13

How about this:

Sub Demo()
    Dim str As String
    Dim i As Long, rowIdx As Long
    Dim myString As Variant
    str = " "
    myString = Split(Range("A1").Value)
    rowIdx = 5    '-->row number from where data will be displayed
    For i = LBound(myString) To UBound(myString)
        If (Len(str) + Len(myString(i)) + 1) > 72 Then '-->check for length > 72
            Range("A" & rowIdx).Value = Trim(str)      '-->if > 72 display in cell
            rowIdx = rowIdx + 1                        '-->increment row index
            str = ""                 'set str="" to countinue for new line
        End If
        str = str & myString(i) & " "
    Next
    If Len(str) > 0 Then Range("A" & rowIdx).Value = Trim(str) 'display remiaing words
End Sub

enter image description here

查看更多
登录 后发表回答