Using Excel VBA to automatically move to cell if value changes - vba

I have put values in columns from C to F, with G being the calculation from these cells (C to F).
Is there a way to automatically move to cell C in next row when I put the number in cell F at the end?
I have tried using macro plus VBA but it seems there is a problem.
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Address = "$H$6" Then
Call Macro1
End If
End Sub
MACRO
Sub Macro1()
'
' Macro1 Macro
'
ActiveCell.Offset(1, -3).Range("A1").Select
End Sub
In H6, I used the SUM of the F cell to trigger it but it didn't work.

You are checking only for the cell H6. It will only move if you type something in H6 other cells will have no effect.
So, test for the F column (number 6):
if Target.Column = 6 then
....
endif
Since the acive cell is probably below the one edited (if user pressed enter) or anywhere else (if user just clicked another place), using ActiveCell will be a bad thing, use the changed row instead:
if Target.Column = 6 then
call Macro1(Target.row)
end if
Sub Macro1(row as integer)
Worksheets("TheNameOfTheSheet").Cells(row,3).Select
end sub

This code will only fire if the user changes the value in cell H6. It doesn't fire if that value is changed due to a calculation (ie because the user changes the value in another cell). This is mentioned in the MSDN documentation for the Worksheet Change event at https://msdn.microsoft.com/en-us/library/office/ff839775.aspx.
Also, I would suggest not using ActiveCell.Offset as you don't know which cell will be active when macro1 is run. If the user types a number in F6 and presses enter then F7 becomes the Activecell, but if the user types a number and presses the right arrow key, it will be cell G6.
Instead of using ActiveCell, you can use Target from the Change event, as we know that is the cell that was updated:
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Address = "$F$6" Then
Macro1 LastCell:=Target
End If
End Sub
Sub Macro1(LastCell As Range)
LastCell.Offset(1, -3).Select
End Sub
If you have more than one row of data and want to repeat the macro for a number of cells in F, you may want to test for a specific Colum (F), and a range of Row numbers, instead of one cell address. There's also no real need to call a separate sub unless you're doing something more complex. You might want to try something like the following:
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Column = 6 Then
If Target.Row > 1 And Target.Row < 10 Then
Target.Offset(1, -3).Select
End If
End If
End Sub
(You'd need to adjust the Row numbers according to your needs).

Related

select value of active cell from a range

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.

Dynamically, continously, set a cell's value according to ActiveCell's value (which is on another worksheet)

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.....

VBA go to next row and pull formula from above after data has been entered

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

Excel-VBA - How to identify Target range (more than 1 cell) is deleted in a Worksheet_Change function?

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.

How to wrap Excel cursor to keep it within a specific range

In Excel, I have three columns:
column1, column2, column3
I am entering data into excel using a barcode scanner that is attached to an IPAD. The barcode scanner sends ENTER after every scan. I believe that I can set excel up such that ENTER would cause the next column to be selected (instead of the next row)
However, I do not know how to have it go to the next row after there is an ENTER detected in column3. Right now I have this:
Private Sub Workbook_SheetChange(ByVal Sh As Object, ByVal Target As Range)
If Target.Column = 3 Then
If Target.Value = "{enter}" Then
MsgBox "SDf"
End If
End If
End Sub
But Target.Value detects only the string inside the cell, it does not detect what has been pressed.
How do I get the next row to be selected after ENTER is detected in column 3?
You don't need vba code for this.
The easiest way is to unlock the cells in those three columns and lock the rest of the cells. Once done, protect the entire sheet. However when protecting, ensure you uncheck the option called Select Locked Cells See screenshot. The yellow columns are unprotected.
The next step is to set excel so that after the data is entered and Enter key is pressed, the cursor moves to the next column. You can do that (Say in Excel 2010) from the File TAB | Options | Excel Options | Advanced
When the cursor reaches the last column and data is entered and the enter is pressed, the cursor will automatically move to the next row. See snapshot.
HTH
In addition to Siddharth's excellent suggestion, here's an event-based approach:
Private Sub Worksheet_Change(ByVal Target As Range)
'named (contiguous) range on input sheet
Const DATA_NAME As String = "DATA"
Dim rngData As Range, numCols As Long
If Target.Cells.Count > 1 Then Exit Sub
Set rngData = Me.Range(DATA_NAME)
numCols = rngData.Columns.Count
If Not Intersect(rngData, Target) Is Nothing Then
If Target.Column < rngData.Columns(numCols).Column Then
Target.Offset(0, 1).Select
Else
Target.Offset(1, -(numCols - 1)).Select
End If
End If
End Sub