【问题标题】:Excel Macro - Comma Separated Cells to RowsExcel 宏 - 逗号分隔的单元格到行
【发布时间】:2015-06-08 15:39:35
【问题描述】:

我在excel中有以下数据:

a, b, c
d
e
f, g
h
i

每一行,代表一行,在一个单元格中。

我想把它转换成:

a
b
c
d
e
f
g
h
i

我正在使用以下宏,但我无法通过自动调整大小来进行插入,而不是覆盖单元格值。任何帮助表示赞赏。

    Sub SplitCells()


    Dim i As Long



    With Application

        .Calculation = xlCalculationManual

        .ScreenUpdating = False




    For i = 1 To Selection.Rows.Count

        Dim splitValues As Variant


        splitValues = split(Selection.Rows(i).Value, ",")

        Selection.Rows(i).Resize(UBound(splitValues) - LBound(splitValues) + 1).Value = Application.Transpose(splitValues)

    Next i



        .Calculation = xlCalculationAutomatic

        .ScreenUpdating = True

    End With

End Sub

【问题讨论】:

    标签: vba excel


    【解决方案1】:

    此宏将从 A 列中获取您的数据并将其“提取”到 B 列。结果如下所示,请随意畏缩我的图形表示技巧 :-)

        <- A ->   <- B ->
    1   a, b, c   a
    2   d         b
    3   e         c
    4   f, g      d
    5   h         e
    6   i         f
    7             g
    8             h
    9             i
    

    出于测试目的,我将其保留为非破坏性,并且由于创建新列相对容易,因此在 VBA 中填充并删除旧列。给读者的练习......

    这是宏:

    Option Explicit
    Sub Macro1()
        Dim fromCol As String
        Dim toCol As String
        Dim fromRow As String
        Dim toRow As String
        Dim inVal As String
        Dim outVal As String
        Dim commaPos As Integer
    
        ' Copy from column A to column B.'
        fromCol = "A"
        toCol = "B"
        fromRow = "1"
        toRow = "1"
    
        ' Go until no more entries in column A.'
        inVal = Range(fromCol + fromRow).Value
        While inVal <> ""
    
            ' Go until all sub-entries used up.'
            While inVal <> ""
                Range(fromCol + fromRow).Select
    
                ' Extract each subentry.'
                commaPos = InStr(1, inVal, ",")
                While commaPos <> 0
    
                    ' and write to output column.'
                    outVal = Left(inVal, commaPos - 1)
                    Range(toCol + toRow).Select
                    Range(toCol + toRow).Value = outVal
                    toRow = Mid(Str(Val(toRow) + 1), 2)
    
                    ' Remove that sub-entry.'
                    inVal = Mid(inVal, commaPos + 1)
                    While Left(inVal, 1) = " "
                        inVal = Mid(inVal, 2)
                    Wend
                    commaPos = InStr(1, inVal, ",")
                Wend
    
                ' Get last sub-entry (or full entry if no commas).'
                Range(toCol + toRow).Select
                Range(toCol + toRow).Value = inVal
                toRow = Mid(Str(Val(toRow) + 1), 2)
                inVal = ""
            Wend
    
            ' Advance to next source row.'
            fromRow = Mid(Str(Val(fromRow) + 1), 2)
            Range(fromCol + fromRow).Select
            inVal = Range(fromCol + fromRow).Value
        Wend
    End Sub
    

    【讨论】:

      【解决方案2】:

      这是未经测试的,但它是我多次使用的算法模式。不过已经有一段时间了,所以不要完全相信语法。

      sub SplitCells()  
          Dim c as Range      ' iterator for cells in Selection  
          dim r as Range      ' to hold the range which is the first cell in Selection  
          Dim r2 as Range     ' variable range for single cell which is the target for inserting the result  
          Dim a() a Variant   ' array of variants to hold each cell's value after it's split  
          Dim b() as Variant  ' array of variants to hold the accumulation of values to spread into the destination  
          Dim v ar Variant    ' variant to iterate through b for insertion  
          Dim i as Integer    ' cumulative offset from top of destination range while inserting  
      
          For each c in Selection.Cells  
              a = Split(Replace(c.Text, ",", "")) ' will split on whitespace  
              for each v in a  
                  b.Add v  
              next v  
          next c  
      
          ' now you have a new array with the full set of values  
      
          ' insert them a row at a time using Range.Offset  
          i = 0  
          Set r = Selection.Cells(0)  
          For Each v in b  
              Set r2 = r.Offset(1, 0)  
              r2.Value = v  
              i = i + 1  
          next v  
      End Sub  
      

      【讨论】:

      • 您知道您在“Dim a() a Variant”上遇到语法错误,不是吗?我不知道它有什么问题,我从未在 VBA 中使用过变体或数组(我的数组通常存储在 Excel 单元格中:-)。
      【解决方案3】:

      我不是很擅长 Excel VBA,但这有效(不知何故!!)

      Sub arrange()
      
      ' get the current range from the sheet
          curr_range = ActiveSheet.Range("A1:A6")
      
      ' for each cell in that range ...
          For Each Row In curr_range
      
      ' ...put the contents into an array
              arr = Split(Row, ",")
      
      ' for each cell in that array ...
              For Each cell In arr
      
      ' ...output it into a string
                  output_str = output_str & "," & cell
              Next cell
      
          Next Row
      
      ' remove spaces
          output_str = Replace(output_str, " ", "")
      ' remove left ,
          output_str = Right(output_str, Len(output_str) - 1)
      
      ' make it into an array
          output_arr = Split(output_str, ",")
      
      ' populate the sheet back
          ActiveSheet.Range("A:A").Value = Application.WorksheetFunction.Transpose(output_arr)
      
      End Sub
      

      【讨论】:

      • 我讨厌 SO 对 VBA cmets 所做的事情 - 我发现您需要在行尾添加一个“'”以确保着色正常工作。
      • 当我运行这个时,我在正确的单元格下得到了很多 #N/A 单元格。
      • 小批评(不值得投票): 1/ 您删除了字段中的任何空格(例如,“bob, jill smith, george”变成了“bob”、“jillsmith”、“george”)。 2/ 你的“左移”不如“output_str = mid(output_str,2)”。除了那个和 NA 之外,它似乎还不错。
      最近更新 更多