Excel VBA在循环内复制和粘贴循环
Posted
技术标签:
【中文标题】Excel VBA在循环内复制和粘贴循环【英文标题】:Excel VBA Copy and Paste Loop within Loop 【发布时间】:2013-12-27 18:29:26 【问题描述】:我已经研究这个 VBA 代码有一段时间了,因为我是一个完全的菜鸟,所以我觉得我什么都没有。我一直在研究大量内容,但似乎无法结合各种答案来帮助解决我的方案。
基本上我要做的是从一个工作表中逐行获取数据并将其推断到另一个工作表。我相信这将涉及循环,而且我对 VBA 很陌生,我不知道该怎么做。
这是我正在尝试的逻辑: 对于工作表 1 上的每一行,我想对工作表 2 执行 3 个不同的复制和粘贴活动,然后它将循环到工作表 1 上的下一行并执行 3 个活动,依此类推。这将继续向下,直到 sheet1 中的 A 列为空白。 Sheet1 数据从 A3 开始,sheet2 粘贴区域从 A2 开始。
第一个活动是将单元格 F3、D3、A3 和 H3(按此顺序,因此 F3 将是 A2,D3 将是 B2 等)从工作表 1 复制到工作表 2 到 A2、B2、C2 等。无法使用目标函数,因为我只需要值而不需要其他格式——这是我遇到的众多问题之一。
下一个活动是将单元格 F3、D3、A3 和 I3 从工作表 1 复制到工作表 2,并粘贴在先前的复制和粘贴下方 - 同样没有格式,只有值。另外需要注意的是,其中一些可能是空白的(A 列除外),但我仍然需要该行至少包含 A 列数据——所有这些活动都是如此。
第三个活动是复制和粘贴 sheet1 的 F3、D3 和 A3 一定次数,引用 K3 的编号 - 每次复制和粘贴都将在下一个可用的空白单元格中。因此,如果 K3 中的数字看起来像是在 sheet2 中创建了 3 行 - 由于 activity1 和 2 各自创建了自己的行,因此 sheet2 上总共有 5 行。
在工作表 1 的第 3 行完成这三个活动后,它将移动到第 4 行并执行前三个活动并粘贴到工作表 2。同样,它将不粘贴任何格式,并在工作表 2 的下一个空白行中粘贴。同样,一旦 A 列中的单元格为空白,此循环将停止。
以下是我不完整的代码。我什至认为它不会有一点帮助,甚至不看它可能会更好。我刚刚开始感到沮丧,因为我什至不能做一个简单的复制和粘贴,而是在循环中单独循环。我什至还没有开始我的第三项活动。非常感谢!
Sub copyTest3()
Dim proj As Range, release As Range, pm As Range, lead As Range, coord As Range
Dim leadCopy As Range, coordCopy As Range
Dim i As Range
Set proj = Range("A3", Range("A3").End(xlDown))
Set release = Range("D3", Range("D3").End(xlDown))
Set pm = Range("F3", Range("F3").End(xlDown))
Set lead = Range("H3", Range("H3").End(xlDown))
Set coord = Range("I3", Range("I3").End(xlDown))
Set leadCopy = Union(pm, release, proj, lead)
Set coordCopy = Union(pm, release, proj, coord)
For i = 1 To Range(ActiveSheet.Range("A3"), ActiveSheet.Range("A3").End(xlDown))
leadCopy.Copy
Sheets("Sheet2").Activate
Range("A2").Select
ActiveSheet.PasteSpecial xlPasteValues
Application.CutCopyMode = False
Sheets("Sheet1").Activate
coordCopy.Copy
Sheets("Sheet2").Activate
Range("A2").Select
ActiveSheet.PasteSpecial xlPasteValues
Next i
End Sub
【问题讨论】:
您的要求是可行的。但在我尝试之前让我问这个。似乎没有任何逻辑(即仅在 x 条件为真时粘贴)。如果是这种情况,您可以只粘贴整个列(以所需的顺序,而不是逐行粘贴吗?这将比循环快得多。 没错,没有任何逻辑要粘贴...除了我的第三个活动将查看“k”列并计算复制和粘贴多少次,基本上会有多少新行表 2。我不认为做列会起作用,因为目标表在每列中会有很多重复的名称。重要的是要注意活动 2 将粘贴在 sheet2 A-D 上,就像活动 1 一样——这就是为什么每个人都需要在 sheet2 中自己的行。这能回答你的问题吗? 【参考方案1】:有很多方法可以做到这一点,有些方法比其他方法更有效。我的解决方案可能不是最有效的,但希望它对您来说很容易理解,以便您学习。
很难理解您在活动三中尝试做什么,因此我无法为该步骤提供解决方案。使用我的代码作为第三步的模板,如果遇到问题,请随时发表评论。
请注意,我在此代码中没有使用 .Activate
、.Select
或 .Copy
。 .Activate
和 .Select
是巨大的效率杀手,它们使您的代码更容易“破坏”,因此请尽可能避免使用它们。 .Copy
在使用值或公式时不是必需的,也会减慢您的代码速度。
未经测试
Sub testLoopPaste()
Dim i As Long
Dim ii As Long
Dim i3 as Long
Dim LastRow As Long
Dim wb As Workbook
Dim sht1 As Worksheet
Dim sht2 As Worksheet
Set wb = ThisWorkbook
Set sht1 = wb.Sheets("Sheet1")
Set sht2 = wb.Sheets("Sheet2")
'Find the last row (in column A) with data.
LastRow = sht1.Range("A:A").Find("*", searchdirection:=xlPrevious).Row
ii = 2
'This is the beginning of the loop
For i = 3 To LastRow
'First activity
sht2.Range("A" & ii) = sht1.Range("F" & i).Value
sht2.Range("B" & ii) = sht1.Range("D" & i).Value
sht2.Range("C" & ii) = sht1.Range("A" & i).Value
sht2.Range("D" & ii) = sht1.Range("H" & i).Value
ii = ii + 1
'Second activity
sht2.Range("A" & ii) = sht1.Range("F" & i).Value
sht2.Range("B" & ii) = sht1.Range("D" & i).Value
sht2.Range("C" & ii) = sht1.Range("A" & i).Value
sht2.Range("D" & ii) = sht1.Range("I" & i).Value
ii = ii + 1
'Third activity
For i3 = 1 To sht1.Range("K" & I)
sht2.Range("A" & ii) = sht1.Range("F" & i).Value
sht2.Range("B" & ii) = sht1.Range("D" & i).Value
sht2.Range("C" & ii) = sht1.Range("A" & i).Value
ii = ii + 1
Next i3
Next i
End Sub
【讨论】:
是的,这绝对是我想要做的!第三个活动将查看每列 K 并根据 K 列中的数字重复将 F、D 和 A 复制并粘贴到 sheet2 到 A、B 和 C。我不完全确定如何执行此操作:-/ 查看我更新的代码。我添加了活动三。第三个活动本质上是另一个循环,根据 K 列中的数字循环。这是您要找的吗? 就是这样!你不知道我尝试了多少时间!非常感谢! 嗨,ARich,我试图向您发送消息,但我想没有办法做到这一点。我不想再打扰你了,但我很好奇你能否解释一下代码是如何工作的。我了解 Dims 和 Set,但我可以使用更多关于 ii = 2 以及为什么 For i = 3 和 ii = ii + 1 等的解释。我只是没有真正了解循环部分以及如何ii、i 和 i3 专门工作... 不用担心。注意这些变量中的每一个是如何声明的As Long
。在这种特殊情况下,我使用这三个变量作为计数器。例如,您希望循环从第三行开始,所以我在 3 (For i = 3
) 处启动计数器 i
。下一个计数器需要从第二行开始,所以ii = 2
,然后当我们需要转到下一行时,ii = ii + 1
。最后一个循环从 1 开始(`For i3 = 1),需要以 K 中的值结束。Read this 了解有关变量的更多信息。【参考方案2】:
我通常在 Excel 中的工作表之间复制数据的方法是创建源范围和目标范围对象,每个范围仅引用一行。当我想移动到下一行时,我使用Offset
将范围偏移量返回到下一行。
由于范围仅引用一行,因此您可以使用整数对其进行索引以获取该行中的单元格。例如。如果cursor
引用第 3 行中的 A 到 D 列,cursor(3)
将为您提供单元格 C3。
Dim src_cursor As Range
Dim dest_cursor As Range
Set src_cursor = ActiveSheet.Range("A3:I3")
Set dest_cursor = Sheets("Sheet2").Range("A2:D2")
'' Loop until column A is empty in source data
Do Until IsEmpty(src_cursor(1))
dest_cursor(1) = src_cursor(6) '' copy F -> A
dest_cursor(2) = src_cursor(4) '' copy D -> B
'' and so on
'' move cursors to next row
Set src_cursor = src_cursor.Offset(1, 0)
Set dest_cursor = dest_cursor.Offset(1, 0)
Loop
此外,这可能有点跑题了,但最好使用 Enum
来命名列号,而不是像我在此处所做的那样对它们进行硬编码。
【讨论】:
感谢您的意见。看到比我自己更好的代码编写方式还是很高兴的!以上是关于Excel VBA在循环内复制和粘贴循环的主要内容,如果未能解决你的问题,请参考以下文章
excel VBA'循环时'的问题。似乎无法找到结束循环的布尔值
VBA Excel to Word - 对于下一个循环随机跳过数据