Using:
Microsoft Office Excel Macro-Enabled Worksheet 2007
Microsoft Visual Basic
I've been searching on ways to resolve my issue and couldn't really find the key to resolve this.
Case
In a worksheet I need to automatically insert a value (static timestamp) into column right after specified range of columns based on condition that they are all not null (have been filled).
Example goal
Given the order of inserting values into rows one after another, when values in range of columns A:C are filled, I'd want the column D (the next one after specified range) to update.
ColumnA ColumnB ColumnC AutoInsert
filled filled filled 2016-01-11 20:57
filled filled
filled
filled filled filled 2016-01-11 20:58
What have I got?
Right now when I insert value into column A current timestamp appears in column B.
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Cells.Count > 1 Then Exit Sub
If Not Intersect(Target, Range("A:A")) Is Nothing Then
With Target(1, 2)
.Value = Now
End With
End If
End Sub
Current results:
ColumnA AutoInsert
value 2016-01-11 21:06
value 2016-01-11 21:06
value 2016-01-11 21:07
What do I need?
I need some way to check for specified range of columns within row, not only the first column like shown above (in what have I got? section).
I'm not sure whether I need some other method than Intersect, or some kind of a loop. I've tried experimenting with Target(x, y) and Range("A:C"), but the behavior is different than expected and seems to be applied to each active cell.
Try this:
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Cells.Count > 1 Then Exit Sub
If Not Intersect(Target, Range("A:C")) Is Nothing And WorksheetFunction.CountBlank(Range("A" & Target.Row & ":C" & Target.Row)) = 0 Then
With Me.Cells(Target.Row, 4)
Application.EnableEvents = False
.value = Now
End With
End If
Application.EnableEvents = True
End Sub
The Me refers to the sheet. It works because this is a worksheet event. If this was in a module it would need to be ActiveSheet. The .Cells is a Range. It used in this format Cells(Row,Column). The whole thing could have been rewritten as Me.Range("D" & Target.row).
Target is a range and doing Target(row,column) is shorthand for Target.Cells(row,column) You could have put Target(1,4). Target(1,1) would have referred to itself, or the upper left cell in a range of cells. It is not constrained by the range but uses the upper left cell as a starting point.
Related
I have a range 'Bills' (A10:B50) containing dates of my bills, some are paid on the same date so there are duplicates and blanks at the end. I have a range 'Consolidated' (D10:E30) which consolidates the dates and bill amounts into single entries. When I click on the date in 'Consolidated' it highlights the individual entries in the Bills range using conditional formatting.
I use the following to get the date I am clicking on:
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
ActiveSheet.Range("C40").Formula = "=" & Target.Address
End Sub
However, I use C40 elsewhere, it is formatted as a date, the vba causes havoc when the active cell is not a date. How do I get my vba to work ONLY if the active cell is within the Consolidate range?
Thanks
Not the cleanest solution, but try something like this:
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
If Target.Row < Range("$D$10").Row Then Exit Sub
If Target.Column < Range("$D$10").Column Then Exit Sub
If Target.Row > Range("$D$30").Row Then Exit Sub
If Target.Column > Range("$D$30").Column Then Exit Sub
ActiveSheet.Range("C40").Formula = "=" & Target.Address
End Sub
To explain, this checks the target row and columns and makes sure they are not below or above the range of your choice. If you click anywhere outside of range D10 through D30, then nothing will happen with cell C40.
I have tested this and it works. When clicking within D10 through D30, it changes the contents of C40. Hopefully it works for you.
I have a workbook with a two sheets, Rep and Aux.
I want to dynamically set Aux!A2 to the value of the ActiveCell, which is on sheet Rep, but only if the ActiveCell is on column D of that sheet (in the range Rep!D2:D5000).
To top it all of I need this mechanism to run as long as the workbook is active, not just a one-shot.
For example: While being on sheet Rep I place the cursor, i.e. ActiveCell on cell D2. I expect Aux!A2 to be set to the value of Rep!D2. I move the cursor to, say, Rep!F5 and expect nothing to happen to Aux!A2, lastly, I activate cell Rep!D7 and again, expect Aux!A2 to get the ActiveCell's value. Continue till I close the workbook.
My VBA skills are non-existent and Googling, the only thing remotely close to what I described was:
Sub Macro1()
If Not Intersect(ActiveCell, Sheets("Rep").Range("D2:D5000")) Is Nothing Then Sheets("Aux").Range("A2").Value = ActiveCell.Value
End Sub
Which fails completely.
Put this in the code of the "Rep" worksheet. Triggers anytime a cell is selected on that sheet, if the cell is in column 4 (D) then it sets the value of the cell on Aux to match.
Private Sub Worksheet_SelectionChange(ByVal Target As Excel.Range)
If Target.Column = 4 Then
ThisWorkbook.Worksheets("Aux").Cells(2, 1).value = Target.Value
End If
End Sub
EDIT: In response to comments.
Private Sub Worksheet_SelectionChange(ByVal Target As Excel.Range)
End Sub
This subroutine is an event that exists on every worksheet. Any time a selection changes it will run any code you put in it. The "ByVal Target as Excel.Range" part is saying it's giving you a copy of the target range being selected, because you could select more then one cell.
If Target.Column = 4 Then
end if
This is an If Block. If the condition is true, any code between the "Then" and the "End If" will execute. The condition is if the target's column is 4 in this case.
ThisWorkbook.Worksheets("Aux").Cells(2, 1).value = Target.Value
This sets the cell at row 2 column 1 value to match the value of the target that was selected.
Now that I think about it I wonder what this code will do if you select a range of cells.....
I have the excel formula below to pull data from another sheet.
=IF(ISNUMBER(SEARCH("Yes",Sheet7!C4)),Sheet7!A4,"")
These cells used, C4 and A4, will always remain the same. Different item numbers are being scanned in one after another so the values in the cells will change.
When the word Yes is shown in C4 i would like it to record the item # in A4 into the new sheet. This formula works great for that.
However, after the item # is recorded in the new sheet, i would like it to go down to the next row and copy the formula so it can record the next item # scanned.
Is this VBA possible? thank you!
I think you are trying to get something like
If Worksheets("Sheet7").Range("C4").Value Like "*Yes*" Then
ActiveCell.Value = Worksheets("Sheet7").Range("A4").Value
Else
ActiveCell.Value = ""
End If
but don't use ActiveCell - use a proper reference to the cell in which you want to put the value. (Your question doesn't contain enough information to determine what the location is, which is why I was forced to just refer to it as ActiveCell.)
Based on comments, it sounds like you want the following Worksheet_Change event in Worksheets("Sheet7"):
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Cells.Count <> 1 Then
Exit Sub
End If
If Intersect(Range("A4"), Target) Is Nothing Then
Exit Sub
End If
If Range("C4").Value Like "*Yes*" Then
With Worksheets("Sheet1")
.Cells(.Rows.Count, "A").End(xlUp).Offset(1, 0).Value = Target.Value
End With
End If
End Sub
I am trying to find if a user deletes values in certain cells in column B then cells in same rows in column X are also deleted using worksheet_change function.
When I delete only one cell in column B then IsEmpty(Target) returns true and I am able to clear the same row cell in column X.
However, when select multiple cells in column B and press delete button, the IsEmpty(Target) returns False. Now here Target is range of multiple cells. I just can't find a way to find if a user has deleted range of values in column B at the same time. Any help would be much appreciated.
Below code works when one cell is deleted but not when a range of cells are deleted.
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Column <> 2 Then Exit Sub
If Target.Columns.Count > 1 Then Exit Sub
If IsEmpty(Target) Then
Application.EnableEvents = False
ActiveSheet.Range("X" & Target.Row & ":X" & Target.Row + Target.Rows.Count - 1).ClearContents
Application.EnableEvents = True
End If
End Sub
Thanks
Uttam
You misunderstand the purpose of the function IsEmpty.
I guess what you are really looking for are cells which do not contain a value (blank cells). The following line will give you the count of cells which contain a value. If that is equal to zero then they are all blank.
Target.SpecialCells(xlCellTypeConstants).Count
Yet, the above line of code will result in an error if all cells are empty. Hence, you will have to adjust your code as follows:
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Column <> 2 Then Exit Sub
If Target.Columns.Count > 1 Then Exit Sub
Dim bolIsEmpty As Boolean
On Error GoTo AllAreEmpty
bolIsEmpty = Target.SpecialCells(xlCellTypeConstants).Count = 0
On Error GoTo 0
If bolIsEmpty Then
' ... your code here ...
End If
Exit Sub
AllAreEmpty:
bolIsEmpty = True
Resume Next
End Sub
Copy the column in question into a hidden worksheet (workSheet.Visible = xlVeryHidden), then use WorksheetFunction.CountA to compare the number of non-empty cells in the column of the visible worksheet and in the 'shadow' column of the hidden worksheet. This will quickly inform you if the number of cells with contents has decreased (i.e., contents have been deleted).
If so, get the .UsedRange of the observed column, find the first empty cell in it and check if the corresponding cell in the shadow column is empty as well. If yes, continue to the next empty cell; if not, you know the cell content has been deleted, and you can delete the corresponding cell content in your 'column X'.
After each Worksheet_Change event you need to make another 'shadow' copy.
this is my first question so please bear with me if i'm doing anything wrong.
Quick back storey... on sheet "Purchase" in column C i want the item name of what has been purchased, in column D i want the quantity and in column G i want the location of where the item is going. For example i want 10 boxes of tiles delivered to the office. C2=Tiles, D2=10, G2=Office
When the location of an item is entered into column G(cell change) i want the macro to offset to the same row in column C and then search for the value in column A on sheet "Office", i currently have this for searching if a cell changes;
Private Sub worksheet_change(ByVal target As Range)
Dim keycells As String
keycells = "g2:g9999"
If Application.Intersect(ActiveCell, Range(keycells)) = "Office" Then MsgBox "hello"
End Sub
This does work, but it also checks if all other cells change, which i dont want it to do this. In place of "msgbox "hello" " i want to put the script for it to offset to the same row in column C look at the value and then search for this value in column A on sheet "Office".
If it is found i need the macro to add the newly purchased quantity to the current quantity on sheet "Office" (this will be column B), if it is not found i need it add the information from columns C & D on sheet "Purchase" to columns A & B
Also i will need to add more locations to the script and will give these locations a sheet in the workbook over time
If this is possible i will be extremely gratefull for all help provided
The Worksheet_Change event fires on all cell changes.
To prevent your code running unless the cell is in column G, you could restrict it like this:
Private Sub worksheet_change(ByVal target As Range)
Dim keycells As String
Dim iSect
If target.Column = 7 Then
keycells = "g2:g9999"
Set iSect = Application.Intersect(target, Range(keycells))
If Not iSect Is Nothing Then
If lcase(target) = "office" Then
MsgBox "hello"
' add code here to copy the data
End If
End If
End If
End Sub
However, a better solution might be to use formulas (such as an array formula or using INDEX and MATCH) in the target worksheets to extract the data - this will avoid using a macro entirely.