【问题标题】:How to split cell contents from multiple columns into rows by delimeter?如何通过分隔符将单元格内容从多列拆分为行?
【发布时间】:2021-12-21 05:54:25
【问题描述】:

我的代码从列中获取包含分隔符 (;) 的单元格,并创建新行(除列之外的所有内容都是重复的)以分隔这些值。

我有什么

我的数据中的多列需要这个,但我不希望数据重叠(例如:对于 3 列,我希望这 3 列中的每行只有一个值)。如果我可以选择多列而不是像我现在的代码那样只选择一列,那将是理想的。

我想要什么

Sub splitByCol()
    Dim r As Range, i As Long, ar
    Set r = Worksheets("Sheet").Range("J2000").End(xlUp)
    Do While r.Row > 1
        ar = Split(r.Value, "; ")
        If UBound(ar) >= 0 Then r.Value = ar(0)
        For i = UBound(ar) To 1 Step -1
            r.EntireRow.Copy
            r.Offset(1).EntireRow.Insert
            r.Offset(1).Value = ar(i)
        Next
        Set r = r.Offset(-1)
    Loop
End Sub

【问题讨论】:

  • 你确定这不是你想要的图片中的错误吗?我的意思是,在列中,不应该是Red 后跟Blue,而不是Blue - Blue...应该有更多的两个字符串由“;”分隔 在一个单元格中?如果是,你能估计一个最大值吗?
  • @FaneDuru 嗨,抱歉,这是我的错字。一个单元格中可以有超过 2 个字符串,但最大值可能在 5 个左右。
  • 我不确定我是否正确理解了拆分逻辑,只看你的图片......第三和第六行之后的边界线应该是什么意思?他们只是为了混淆视听吗?
  • 请测试我的答案中的代码并发送一些反馈。它假设边界线只是为了混淆...... :)

标签: excel vba


【解决方案1】:

试试这个代码

Sub Test()
    Dim a, x, e, i As Long, ii As Long, iii As Long, k As Long
    a = Range("A1").CurrentRegion.Value
    ReDim b(1 To 1000, 1 To UBound(a, 2))
    For i = LBound(a) To UBound(a)
        For ii = 2 To 3
            x = Split(a(i, ii), "; ")
            For Each e In x
                k = k + 1
                b(k, 1) = k
                b(k, 2) = IIf(ii = 2, e, Empty)
                b(k, 3) = IIf(ii = 3, e, Empty)
                b(k, 4) = a(i, 4)
            Next e
        Next ii
    Next i
    Range("A5").Resize(UBound(b, 1), UBound(b, 2)).Value = b
End Sub

【讨论】:

    【解决方案2】:

    我会走这条路

    Sub SplitByCol()
    
        With Worksheets("Sheet")
        
            With .Range("B2", .Cells(.Rows.Count, "B").End(xlUp))
                
                Dim firstColValues As Variant
                    firstColValues = .Value
    
                Dim secondColValues As Variant
                    secondColValues = .Offset(, 1).Value
    
                Dim thirdColValues As Variant
                    thirdColValues = .Offset(, 2).Value
            
                .Offset(, -1).Resize(, 4).ClearContents
                
            End With
            
            Dim iRow As Long
                For iRow = LBound(firstColValues) To UBound(firstColValues)
                
                    Dim currFirstColValues As Variant
                        currFirstColValues = Split(firstColValues(iRow, 1), "; ")
                    Dim currSecondColValues As Variant
                        currSecondColValues = Split(secondColValues(iRow, 1), "; ")
                        
                            With .Cells(.Rows.Count, "C").End(xlUp).Offset(1, -1)
                                With .Resize(UBound(currFirstColValues) + 1)
                                    .Value = currFirstColValues
                                    .Offset(, 2).Value = thirdColValues(iRow, 1)
                                End With
                            End With
                            
                            With .Cells(.Rows.Count, "B").End(xlUp).Offset(1, 1)
                                With .Resize(UBound(currSecondColValues) + 1)
                                    .Value = currSecondColValues
                                    .Offset(, 1).Value = thirdColValues(iRow, 1)
                                End With
                            End With
                            
                Next
                
        End With
        
    End Sub
    

    当光标位于 VBA IDE 中的任何代码行时,按 F8 逐步跟踪代码,并观察 Excel 用户界面中发生的情况

    编辑

    通过辅助函数添加编辑后的代码以进行更“参数化”的处理

    Sub SplitByCol()
    
        With Worksheets("Sheet")
        
            With .Range("B2", .Cells(.Rows.Count, "B").End(xlUp))
                
                Dim firstColValues As Variant
                    firstColValues = .Value
                Dim secondColValues As Variant
                    secondColValues = .Offset(, 1).Value
                Dim thirdColValues As Variant
                    thirdColValues = .Offset(, 2).Value
            
                .Offset(, -1).Resize(, 4).ClearContents
                
            End With
            
            Dim iRow As Long
                For iRow = LBound(firstColValues) To UBound(firstColValues)
                
                    Dim currFirstColValues As Variant
                        currFirstColValues = Split(firstColValues(iRow, 1), "; ")
                    Dim currSecondColValues As Variant
                        currSecondColValues = Split(secondColValues(iRow, 1), "; ")
                        
                         WriteOne .Cells(.Rows.Count, "C").End(xlUp).Offset(1), _
                                   currFirstColValues, thirdColValues(iRow, 1), _
                                   -1, 2
                            
                         WriteOne .Cells(.Rows.Count, "B").End(xlUp).Offset(1), _
                                  currSecondColValues, thirdColValues(iRow, 1), _
                                  1, 1
                Next
                
        End With
        
    End Sub
    
    
    Sub WriteOne(refCel As Range, _
                 currMainColValues As Variant, thirdColValue As Variant, _
                 mainValuesOffsetFromRefCel As Long, thirdColValuesOffsetFromRefCel As Long)
    
        With refCel.Offset(, mainValuesOffsetFromRefCel)
            With .Resize(UBound(currMainColValues) + 1)
                .Value = currMainColValues
                .Offset(, thirdColValuesOffsetFromRefCel).Value = thirdColValue
            End With
        End With
    
    End Sub
    

    【讨论】:

      【解决方案3】:

      请使用下一个代码。它使用数组,对于大范围的处理应该非常快,主要在内存中工作:

      Sub testSplitInsert()
         Dim sh As Worksheet, lastR As Long, arr, arrSp, arrFin, i As Long, j As Long, k As Long
         
         Set sh = ActiveSheet
         lastR = sh.Range("B" & sh.rows.count).End(xlUp).row
         arr = sh.Range("B1:D" & lastR).Value
         ReDim arrFin(1 To UBound(arr) * 10, 1 To 3) 'maximum to keep max 10 rows per each case
         k = 1 'initialize the variable to load the final array
         For i = 1 To UBound(arr)
              arrSp = Split(Replace(arr(i, 1)," ",""), ";") 'trim for the case when somebody used Red;Blue, instead of Red; Blue
              For j = 0 To UBound(arrSp)
                  arrFin(k, 1) = arrSp(j): arrFin(k, 3) = arr(i, 3): k = k + 1
              Next j
              arrSp = Split(Replace(arr(i, 1)," ",""), ";")
              For j = 0 To UBound(arrSp)
                  arrFin(k, 2) = arrSp(j): arrFin(k, 3) = arr(i, 3): k = k + 1
              Next j
         Next
         
         sh.Range("G1").Resize(k - 1, 3).Value = arrFin
      End Sub
      

      它处理“B:D”列中的范围,并在“G:I”列中返回结果。它可以很容易地适应处理任何列范围并返回甚至覆盖现有范围,但只有在检查它是否返回您需要的内容后才能这样做......

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2018-03-17
        • 2020-10-24
        • 1970-01-01
        • 2019-09-23
        • 1970-01-01
        • 2023-01-13
        • 2011-11-29
        相关资源
        最近更新 更多