[英]VBA: How to locate range being edited through “fill down” or “copy/paste” (or any multiple cells) in worksheet module
I have two worksheets with five columns that I want to keep track of any changes made. 我有两个包含五个专栏的工作表,我想跟踪所做的任何更改。 I present the original state of these columns in worksheet A and mark the change in worksheet B.
我在工作表A中显示这些列的原始状态,并在工作表B中标记更改。
Following is the look of worksheet B, let's say that worksheet A has the "ORIG" part but with filters and everthing: 以下是工作表B的外观,假设工作表A具有“ ORIG”部分,但具有过滤器和其他功能:
Note: I already wrote another worksheet subroutine, that will filter to "All the same?" 注意:我已经编写了另一个工作表子例程,该子例程将过滤为“都一样吗?” = False (meaning that this row is changed) whenever this worksheet is activated.
= False(表示此行已更改),只要此工作表被激活。
I already wrote the code that would work for the change of one cell (eg when you edit the cell with F2 and then hit ENTER when you are done) -- a worksheet subroutine that is triggered when the worksheet is changed. 我已经编写了适用于更改一个单元格的代码(例如,当您使用F2编辑该单元格,然后在完成时按ENTER键)-一个工作表子例程,该例程在工作表更改时触发。 The subroutine will check for the changed range, and if the range is a specified area, correponding area is updated in another worksheet.
该子例程将检查更改的范围,如果范围是指定的区域,则在另一个工作表中更新相应的区域。
Private Sub Worksheet_Change(ByVal target As Range)
Dim start_row As Long: start_row = 4
Dim last_row As Long: last_row = findLastRow()
' when values are changed in "REPORT", check if values are ouputable and update these values
If IsInArray(Number2Letter(target.Column), inputColumns) And target.row >= start_row And target.row <= last_row Then
' Update corresponding cell in worksheetB
End If
End Sub
Public Function Number2Letter(ColumnNumber As Long) As String
'convert a given number into it's corresponding Letter Reference
Dim columnLetter As String
columnLetter = Split(Cells(1, ColumnNumber).Address, "$")(1)
Number2Letter = columnLetter
End Function
Public Function IsInArray(valToBeFound As Variant, arr As Variant) As Boolean
'INPUT: Pass the function a value to search for and an array of values of any data type.
'OUTPUT: True if is in array, false otherwise
Dim element As Variant
On Error GoTo IsInArrayError: 'array is empty
For Each element In arr
If element = valToBeFound Then
IsInArray = True
Exit Function
End If
Next element
Exit Function
IsInArrayError:
On Error GoTo 0
IsInArray = False
End Function
Public Function findLastRow() As Long
'Finds the last non-blank cell on a sheet
Dim lRow As Long
lRow = Cells.Find(what:="*", _
After:=Range("A1"), _
lookat:=xlPart, _
LookIn:=xlFormulas, _
SearchOrder:=xlByRows, _
SearchDirection:=xlPrevious, _
MatchCase:=False).row
findLastRow = lRow
End Function
For simplicity, I hid the "do something" part, but that part already works. 为了简单起见,我隐藏了“做某事”部分,但是该部分已经可以使用了。 Same thing with UDF/UDS as I only showed them if someone is interested.
使用UDF / UDS的情况与我仅在有人感兴趣时向他们展示的情况相同。 In addition, the array inputColumns already exists, so don't worry about that part either.
另外,数组inputColumns已经存在,因此也不必担心该部分。
1. Is there such a property like targetRange that would work for fill down or paste, like I mentioned? 1.是否有像targetRange这样的属性可以像我提到的那样用于填充或粘贴?
2. Or is there a different worksheet event that I can use? 2.还是可以使用其他工作表事件 ?
3. If neither exists, I am thinking of mark original state in an array and compare it with what is visible on first worksheet every time we get to worksheet B. The problem with this approach is that it consumes both space and speed. 3.如果两者都不存在,我正在考虑在数组中标记原始状态,并将其与每次进入工作表B时在第一个工作表上可见的状态进行比较。这种方法的问题在于,它既占用空间又消耗速度。 Could you think of a better way?
您能想到更好的方法吗?
Thank you! 谢谢!
I think that the Intersect function will help you out a lot here. 我认为相交功能将在这里为您提供很多帮助。 You can define a range that you want to 'audit' and compare it against all the values that are changed by a single operation in your worksheet.
您可以定义要“审核”的范围,并将其与工作表中单个操作更改的所有值进行比较。 If there's any overlap, write out the value of those cells to some target destination.
如果有任何重叠,请将那些单元格的值写到某个目标位置。
Private Sub Worksheet_Change(ByVal target As Range)
Dim AuditRange As Range
Set AuditRange = Range("B4:F16") 'your "Audit Area"
Set range_auditedAndChanged = Intersect(target, AuditRange)
If Not range_auditedAndChanged Is Nothing Then
For Each c In range_auditedAndChanged
'put in whereever your audit workbook is for Sheets("Sheet2")
Sheets("Sheet2").Range(c.Address).Value = c.Value
Next c
End If
End Sub
Right now, you only get the values audited - no formats of any kind. 目前,您只审核了值-没有任何格式。 You could change the Value assignment to some kind of copy, but that would hijack the user experience for a moment even with screen updating turned off.
您可以将“值”分配更改为某种副本,但是即使关闭了屏幕更新,这也会劫持用户一段时间。
At any rate, I think this is cleaner and quite performant and has a lot fewer UDFs to manage. 无论如何,我认为这是更干净,性能更好的,并且要管理的UDF少得多。 Hope it helps.
希望能帮助到你。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.