提问人:ExcelN00b 提问时间:9/6/2023 更新时间:9/6/2023 访问量:49
如何为此 VBA 宏创建循环?
How do I create a loop for this VBA macro?
问:
我有一个训练矩阵,我希望能够单击每个人的姓名,然后将他们的行复制到单独的工作表上的报告样式格式。
我找到了一些有效的东西,但由于我根本不是程序员,我一直在为 excel 表格中的每一行复制和粘贴相同的代码行......我意识到有一种更好的方法可以做到这一点,但我不知道该怎么做。我想我可以侥幸逃脱,直到我遇到“程序太大”错误。
目前,我将每个人的姓名设置为指向文档 (A1) 中单元格的链接,然后我有以下代码:
Private Sub Worksheet_FollowHyperlink(ByVal Target As Hyperlink)
If Target.Range.Address = "$A$4" Then
Sheets("Report").Activate
Sheets("Data Table").Range("A4:E4").Copy Destination:=Sheets("Report").Range("B2")
Sheets("Data Table").Range("F3:BAA3").Copy
Sheets("Report").Range("A4").PasteSpecial Transpose:=True, Paste:=xlPasteValues
Sheets("Data Table").Range("F1:BAA1").Copy
Sheets("Report").Range("B4").PasteSpecial Transpose:=True, Paste:=xlPasteValues
Sheets("Data Table").Range("F2:BAA2").Copy
Sheets("Report").Range("C4").PasteSpecial Transpose:=True, Paste:=xlPasteValues
Sheets("Data Table").Range("F4:BAA4").Copy
Sheets("Report").Range("D4").PasteSpecial Transpose:=True, Paste:=xlPasteValues
Sheets("Report").Range("D4:D1500").Select
Selection.SpecialCells(xlCellTypeBlanks).EntireRow.Delete
End If
If Target.Range.Address = "$A$5" Then
Sheets("Report").Activate
Sheets("Data Table").Range("A5:E5").Copy Destination:=Sheets("Report").Range("B2")
Sheets("Data Table").Range("F1:BAA1").Copy
Sheets("Report").Range("B4").PasteSpecial Transpose:=True, Paste:=xlPasteValues
Sheets("Data Table").Range("F3:BAA3").Copy
Sheets("Report").Range("A4").PasteSpecial Transpose:=True, Paste:=xlPasteValues
Sheets("Data Table").Range("F2:BAA2").Copy
Sheets("Report").Range("C4").PasteSpecial Transpose:=True, Paste:=xlPasteValues
Sheets("Data Table").Range("F5:BAA5").Copy
Sheets("Report").Range("D4").PasteSpecial Transpose:=True, Paste:=xlPasteValues
Sheets("Report").Range("D4:D1500").Select
Selection.SpecialCells(xlCellTypeBlanks).EntireRow.Delete
End If
End Sub
您会注意到每个块中唯一的变化是“If”范围以及第一个和第四个数据表范围,每次增加一个。我总共有 212 行,将来还会添加更多行。
我想要一些可以更有效地做同样事情的东西(比如 LOOP),并且希望在添加另一个人时不需要修改!我有一种感觉,这是很有可能的,并不像我想象的那么难,但正如我所说,我绝对不是一个程序员。
遵循 DRY 理念的任何帮助将不胜感激!!=)
-大卫
TLDR:我尝试输入其中的 212 个 if 语句,但它在大约 70 个条目时停止工作,程序太大了。我想我会在这里问我如何编写一个循环,然后我自己尝试将其拆分为 3 个类似的过程......
答:
2赞
Tim Williams
9/6/2023
#1
像这样的东西:
Private Sub Worksheet_FollowHyperlink(ByVal Target As Hyperlink)
Dim rw As Range, ws As Worksheet
Set rw = Target.EntireRow 'the row with the clicked link
Set ws = ThisWorkbook.Worksheets("Report")
CopyValues rw.Range("A1:E1"), ws.Range("B2") 'Note: `Range` is *relative* to `rw`
' and not to the sheet
' `Me` is the worksheet for this code module...
CopyValues Me.Range("F1:BAA1"), ws.Range("B4"), True 'True=Transpose
CopyValues Me.Range("F2:BAA2"), ws.Range("C4"), True
CopyValues Me.Range("F3:BAA3"), ws.Range("A4"), True
CopyValues rw.Range("F1:BAA1"), ws.Range("D4"), True
ws.Range("D4:D1500").SpecialCells(xlCellTypeBlanks).EntireRow.Delete
End Sub
'copy values between `rngSrc` and `rngDest`, with optional Transpose (defaults to False)
' Note: Transpose has an upper limit of about 65k cells....
Sub CopyValues(rngSrc As Range, rngDest As Range, Optional Transpose As Boolean = False)
With rngSrc
If Transpose Then
rngDest.Cells(1).Resize(.Columns.Count, .Rows.Count).Value = Application.Transpose(.Value)
Else
rngDest.Cells(1).Resize(.Rows.Count, .Columns.Count).Value = .Value
End If
End With
End Sub
评论
0赞
ExcelN00b
9/6/2023
我现在没有太多时间看这个,但我看到了你关于 65k 单元格转置限制的说明,我有 200 名员工(行)和 1100 个程序(列)。我确实抓住了我们的 SOP 计数 x4(数字、姓名、修订信、匹配的员工培训数据),所以最多 4000 个单元格,然后可能有几百个新的 SOP,所以我认为我尝试转置的最大单元格数是 5000。
0赞
Tim Williams
9/6/2023
限制仅针对每次调用,(例如)F:BAA 为 1374 列,所以我认为那里没有问题......
0赞
Tim Williams
9/6/2023
在上面做了一些编辑:rw.Range(...)
Me.Range(...)
0赞
taller
9/6/2023
#2
如果目标在 A 列中且行号在 4 到 100 之间(根据需要更新),则将执行复制/粘贴。
Private Sub Worksheet_FollowHyperlink(ByVal Target As Hyperlink)
Dim c As Range
Set c = Target.Range
If c.Column = 1 And (c.Row >= 4 And c.Row <= 100) Then
Sheets("Report").Activate
Sheets("Data Table").Range("A" & c.Row).Resize(1, 5).Copy Destination:=Sheets("Report").Range("B2")
Sheets("Data Table").Range("F3:BAA3").Copy
Sheets("Report").Range("A4").PasteSpecial Transpose:=True, Paste:=xlPasteValues
Sheets("Data Table").Range("F1:BAA1").Copy
Sheets("Report").Range("B4").PasteSpecial Transpose:=True, Paste:=xlPasteValues
Sheets("Data Table").Range("F2:BAA2").Copy
Sheets("Report").Range("C4").PasteSpecial Transpose:=True, Paste:=xlPasteValues
Sheets("Data Table").Range("F" & c.Row).Resize(1, 1374).Copy
Sheets("Report").Range("D4").PasteSpecial Transpose:=True, Paste:=xlPasteValues
Sheets("Report").Range("D4:D1500").SpecialCells(xlCellTypeBlanks).EntireRow.Delete
End If
End Sub
0赞
VBasic2008
9/6/2023
#3
工作表 FollowHyperlink:将值复制到另一个工作表
工作表模块,例如Sheet1(数据表)
Private Sub Worksheet_FollowHyperlink(ByVal Target As Hyperlink)
'Debug.Print Target.Range.Address
' Reference the source worksheet.
Dim sws As Worksheet: Set sws = Me ' Data Table
'Set sws = Target.Range.Worksheet
' Reference the target range in the source worksheet.
Dim trg As Range:
Set trg = sws.Range("A4", sws.Cells(sws.Rows.Count, "A").End(xlUp))
' Attempt to reference the target cell.
Dim tCell As Range: Set tCell = Intersect(trg, Target.Range)
If tCell Is Nothing Then Exit Sub ' no intersection (no target cell)
' Reference the destination worksheet.
Dim dws As Worksheet: Set dws = sws.Parent.Sheets("Report")
'Set dws = ThisWorkbook.Sheets("Report")
'Set dws = Target.Range.Worksheet.Parent.Sheets("Report")
' Declare variables.
Dim srg As Range, drg As Range
' Copy 'A:E'
Set srg = tCell.EntireRow.Columns("A:E")
Set drg = dws.Range("B2")
srg.Copy drg
' Copy 'F:BAA'
Set srg = sws.Columns("F:BAA")
Dim cCount As Long: cCount = srg.Columns.Count
Set drg = dws.Range("A4:D4").Resize(cCount)
With Application
drg.Columns(1).Value = .Transpose(srg.Rows(3).Value)
drg.Columns(2).Value = .Transpose(srg.Rows(1).Value)
drg.Columns(3).Value = .Transpose(srg.Rows(2).Value)
drg.Columns(4).Value = .Transpose(srg.Rows(tCell.Row).Value)
End With
' Attempt to reference the empty cells in destination column 'D'.
Set drg = Nothing ' reset
On Error Resume Next ' prevent error if no empty cells
Set drg = dws.Range("D4", dws.Cells(dws.Rows.Count, "D").End(xlUp)) _
.SpecialCells(xlCellTypeBlanks)
On Error GoTo 0
' Delete entire rows of the empty cells.
If Not drg Is Nothing Then ' there are empty cells
drg.EntireRow.Delete
'Else ' no empty cells; do nothing
End If
End Sub
评论