【问题标题】:VBA Looping through single row selections and executing concat codeVBA循环单行选择并执行concat代码
【发布时间】:2018-11-25 09:53:42
【问题描述】:

所以,我一直在摸索几个小时,试图弄清楚这一点。无论我在哪里看和做什么,我似乎都无法让它发挥作用。

我有一个大约 20 列和完全可变的行数的 excel 文档。我想将定义宽度(列 A:V)内的每个相邻单元格连接到第一个单元格(第一行为 A1),然后移动到下一行并执行相同操作,直到我到达底部。以下片段:

Example before and after I'm trying to make

我有执行连接的代码。为了使其工作,我必须选择要连接的单元格(A1:V1),然后执行代码。即使某些单元格是空白的,我也需要代码以这种方式处理它们并将分号留在那里。代码完全按照我的需要工作,所以我一直在尝试将它包装在某种范围选择、偏移、循环中:

    Dim c As Range
    Dim txt As String

    For Each c In Selection
        txt = txt & c.Value & ";"

    Next c

    Selection.ClearContents
    txt = Left(txt, Len(txt) - 2)
    Selection(1).Value = txt

我正在努力选择 A1:V1,运行代码,然后将其循环到 A2:V1、A3:V3 等。我认为这可以通过循环和偏移量来完成,但是我无法为我的生活弄清楚如何。

任何帮助将不胜感激:)

【问题讨论】:

  • 使其成为您提供范围的用户定义函数。
  • 另外,如果您有 Office 365 Excel,请使用 TEXTJOIN 函数
  • 我将它作为许多其他 VBA 代码的一部分运行,所以我真的不想使用涉及手动输入文档的函数。除非我完全误解了你们每个人的建议。

标签: vba excel loops


【解决方案1】:

这使用变体数组并且会非常快

Dim rng As Range
With Worksheets("Sheet4") 'change to your sheet
    'set the range to the extents of the data
    Set rng = .Range(.Cells(1, 1), .Cells(.Rows.Count, 22).End(xlUp))

    'Load data into an array
    Dim rngArr As Variant
    rngArr = rng.Value

    'create Out Bound array
    Dim OArr() As Variant
    ReDim OArr(1 To UBound(rngArr, 1), 1 To 1)

    'Loop array
    Dim i As Long
    For i = LBound(rngArr, 1) To UBound(rngArr, 1)
        'Combine Each Line in the array and load result into out bound array
        OArr(i, 1) = Join(Application.Index(rngArr, i, 0), ";")
    Next i

    'clear and load results
    rng.Clear
    rng.Cells(1, 1).Resize(UBound(OArr, 1)).Value = OArr

End With

【讨论】:

  • 我被它的运行速度和方法的真棒所震撼,谢谢!唯一要问的另一件事是;我将如何通过工作簿中的多个工作表进行此循环(为了提供一些上下文,我已根据某个列的内容将工作簿拆分为单独的工作表。我需要在工作簿中的所有工作表上重复此过程,其中没有一个会当我将来使用它时具有一致的名称)。
  • 有很多关于如何循环工作表的示例,但您可以添加另一个 For 循环:For each ws in ThisWorkbook 围绕上面的整个代码,而不是 With Worksheets("Sheet4"),您将使用 With ws 请考虑标记通过单击答案旁边的复选标记,这是正确的。
【解决方案2】:

这是我为此编写的一个快速小脚本 - 需要注意的主要是我不使用选择,而是使用定义的范围。

Sub test()

    Dim i As Long

    Dim target As Range
    Dim c As Range

    Dim txt As String

    For i = 3 To 8
        Set target = Range("A" & i & ":C" & i)
        For Each c In target
            txt = txt & c.Value & ";"
        Next c
        Cells(i + 8, "A").Value2 = Left$(txt, Len(txt) - 1)
        txt = ""
    Next i

End Sub

【讨论】:

    【解决方案3】:

    只需将以下范围更改为您的要求:

    Sub concat_build()
        Dim buildline As String
        Dim rw As Range, c As Range
        With ActiveSheet
        For Each rw In .Range("A2:V" & .Cells(.Rows.Count, "B").End(xlUp).Row + 1).Rows
            buildline = ""
            For Each c In rw.Cells
                If buildline <> "" Then buildline = buildline & ";"
                buildline = buildline & c.Value2
            Next
            rw.EntireRow.ClearContents
            rw.EntireRow.Cells(1, 1) = buildline
        Next
        End With
    End Sub
    

    【讨论】:

    • 首先,这很棒!它几乎完成了我第一次想要它做的所有事情,这太棒了!我试图实现的唯一一件事是动态更改范围,因为在使用时行数会发生很大变化。
    • 我已经更改了答案以动态检测 B 列中的行数,并且只执行这些操作。 (我还在.ClearContents 中添加了在写入输出之前擦除每一行。)
    猜你喜欢
    • 2023-02-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-28
    • 1970-01-01
    • 2015-05-04
    • 2021-01-16
    相关资源
    最近更新 更多