英文:
How can I loop through 2 Range-Objects in the same Loop in VBA for Excel?
问题
我试图在下面的代码中注释我尝试做什么。我知道如何保留更改的旧值的选定单元格。它适用于一个单元格,但不适用于多个单元格。我不明白如何在同一个For循环中循环遍历2个范围对象。我不认为使用For-Each会起作用。
Dim OldValue As Range
Private Sub Workbook_SheetChange(ByVal Sh As Object, ByVal Target As Range)
Dim FirstFreeRow As Long
Dim tCell As Variant
Dim I As Integer
If Sh.Name = "Changes" Then Exit Sub
If Sh.Name = "Tabelle2" Then Exit Sub
If Intersect(Target, Sh.Range("A2:Z550")) Is Nothing Then Exit Sub
Application.EnableEvents = False
For I = 1 To Target.Count '遍历所有更改的单元格
Set tCell = Target.Cells(I, 1)
With Sheets("Changes")
FirstFreeRow = .Cells(.Rows.Count, 1).End(xlUp).Row + 1
With .Rows(FirstFreeRow)
.Cells(1) = tCell.EntireColumn.Cells(1)
.Cells(2) = tCell.EntireRow.Cells(2)
.Cells(3) = tCell.EntireRow.Cells(3)
.Cells(4) = OldValue.Cells(I, 1).Value '将旧值放在这里
.Cells(5) = tCell.Range("A1").Value
.Cells(6) = Environ("username")
End With
End With
Next I
Application.EnableEvents = True
End Sub
Public Sub Workbook_SheetSelectionChange(ByVal Sh As Object, ByVal Target As Range)
Set OldValue = Target '保存所有选定的单元格
End Sub
边问:如果使用剪切和粘贴,那么显然没有旧值,因为您有一个新的选定单元格。是否有办法?如果没有,也无所谓。
谢谢。
英文:
I tried to comment in the Code below what I try to do. I know how to keep the selected Cells for the old value which got changed. It works with only one cell, but not more. I don't get it how I can loop through the 2 Range-Objects in the same For-Loop. I don't think it will work with a For-Each.
Dim OldValue As Range
Private Sub Workbook_SheetChange(ByVal Sh As Object, ByVal Target As Range)
Dim FirstFreeRow As Long
Dim tCell As Variant
Dim I As Integer
If Sh.Name = "Changes" Then Exit Sub
If Sh.Name = "Tabelle2" Then Exit Sub
If Intersect(Target, Sh.Range("A2:Z550")) Is Nothing Then Exit Sub
Application.EnableEvents = False
For I = 0 To Target.Count 'Go through all changed Cells
tCell = Target.Cells(I, 1)
With Sheets("Changes")
FirstFreeRow = .Cells(Rows.Count, 1).End(xlUp).Row + 1
With .Rows(ErsteFreieZeile) '.EntireRow
.Cells(1) = tCell.EntireColumn.Cells(1)
.Cells(2) = tCell.EntireRow.Cells(2)
.Cells(3) = tCell.EntireRow.Cells(3)
.Cells(4) = OldValue(I, 1).Value 'Put the old value in here
.Cells(5) = tCell.Range("A1").Value
.Cells(6) = Environ("username")
End With
End With
Next I
Application.EnableEvents = True
End Sub
Public Sub Workbook_SheetSelectionChange(ByVal Sh As Object, ByVal Target As Range)
Set OldValue = Target 'Save all selected Cells
End Sub
Sidequestion: If you use Cut and Paste then you don't have the old Value obviously, because you have a new selcted cell. Is there a way too? If not, doesn't matter.
Thanks.
Does this make it more clear? I only have "Tabelle 1". "Tabelle 2" is something else, doesn't matter here.
答案1
得分: 2
以下是翻译好的内容:
你有几种方法来循环遍历范围的所有单元格:
A) 使用计数循环
Dim i As Long
For i = 1 To target.Count
Debug.Print "方法 A ", target(i).Address
Next
如你所见,当你使用这种方法时,你只使用一个索引来访问范围内的单元格。
B) 逐行和逐列循环
Dim row As Long, col As Long
For row = 1 To target.Rows.Count
For col = 1 To target.Columns.Count
Debug.Print "方法 B ", target(row, col).Address
Next col
Next row
现在你使用了两个索引来访问范围,分别是行和列。请注意,这些索引代表相对的行数和列数,所以如果你的范围是 "E5:G10",那么 target(1, 1) 是该范围的第一行和第一列,即单元格 E5。
C) 使用 foreach 循环
Dim cell As Range
For Each cell In target
Debug.Print "方法 C ", cell.Address
Next cell
在大多数情况下,这是最简单的方法。
我在你的代码中至少看到了两个问题:
第一个问题是你在循环中使用了第一种方法(使用计数循环),但是却使用了两个索引来读取目标范围中的单元格。如果你的范围有 3 行 4 列(所以计数 = 12),那么你会从第一行读取 12 个单元格,这不是你想要的。
第二个问题是你缺少了 Set
关键字(而且你声明 tCell
为 Variant 而不是 Range
)。现在,如果 tCell = Target.Cells(I, 1)
,tCell 将获取范围的内容。这会在你的代码后面导致运行时错误(如果 tCell 是一个值,那么 tCell.EntireColumn 将无法工作)。在 VBA 中,你需要使用关键字 Set
将对象的引用分配给变量:Set tCell = Target.Cells(I, 1)
。
英文:
You have several possibilities to loop over all cells of a Range:
A) Loop using Count (of cells)
Dim i As Long
For i = 1 To target.Count
Debug.Print "Method A ", target(i).Address
Next
As you can see, you use only a single index into the range when you use this method
B) Loop over rows and columns
Dim row As Long, col As Long
For row = 1 To target.Rows.Count
For col = 1 To target.Columns.Count
Debug.Print "Method B ", target(row, col).Address
Next col
Next row
Now you use 2 indizes into the range, the row and the column. Note that those indizes represent relative numbers, so if your range is "E5:G10", target(1, 1) is the first row and first column of that range, that is cell E5.
C) Using a foreach loop.
Dim cell As Range
For Each cell In target
Debug.Print "Method C ", cell.Address
Next cell
In most cases that is the easiest way.
I see at least 2 issues in your code:
The first is that you use the first method (using count) for the loop but reads the cell from the target range using 2 indizes. If you have 3 rows by 4 colums in your range (so count = 12), you would read 12 cells from the first row which is not what you want.
Second is that you miss the Set
keyword (and you declare tCell
as Variant instead of Range
. Now id tCell = Target.Cells(I, 1)
, tCell will get the content of the Range. This will give you a runtime error later in your code (tCell.EntireColumn
cannot work if tCell is a value).
In VBA, you need to use the keyword Set
to assign a reference to an object to a variable: Set tCell = Target.Cells(I, 1)
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论