Macro to show most recently used cell - excel

I have a working macro that hides/unhides specific columns based off specific values in Column B. I also want to add another trigger that takes the user to the most recently used row. Below is my attempt.
Private Sub Worksheet_Change(ByVal Target As Range)
If Not Intersect(Target, Range("B:B")) Is Nothing Then
On Error GoTo safe_exit
Application.EnableEvents = False
Dim t As Range
For Each t In Intersect(Target, Range("B:B"))
Select Case (t.Value)
Case "A"
Columns("B:BP").EntireColumn.Hidden = False
Columns("H:BL").EntireColumn.Hidden = True
Case "B"
Columns("B:BP").EntireColumn.Hidden = False
Columns("F:G").EntireColumn.Hidden = True
Columns("P:BP").EntireColumn.Hidden = True
End Select
Next t
End If
safe_exit:
Application.EnableEvents = True
'Go to last cell in column B
With ActiveSheet
Range("B5").Select
Selection.End(xlDown).Select
End With
End Sub

Perhaps I misread your question from the other answer - and if so, I will be more than happy to delete this one.
You can simply add a variable that will track this for you and persist as long as you keep Excel open.
Private lastUsedRng As Range
Private Sub Worksheet_Change(ByVal Target As Range)
Set lastUsedRng = Target
. . .
...that takes the user to the most recently used row
You can accomplish this with
lastUsedRng.Select

Use Select as little as possible, and replace the last section starting with 'Go to last cell in column B with something like this, except moving it inside the If...End If.
With Me
.Cells(.Rows.Count, 2).End(xlUp).Select
End With

Related

Use Excel VBA to update column cell contents

This is a simple answer but one I cannot find.
I have two columns of data.
Column A (1) has yes/no data validation list options in every cell.
Column B also has data validation with say 6 strings of text options in every cell.
But I only want each the corresponding cell (column B) to update in the same row as column A
e.g A20 toggled, then B20 is updated. Like so
A20 is selected “Yes” from the dropdown option and B20 is updated with the string “complete” which is one of the states you can select in the dropdown boxes manually in every cell in column B.
I had some code but I would have to write an argument for every cell and then two macros for every yes / no.
This is code that works for one cell only but this is not ideal for many cells but it works
Private Sub Worksheet_Change(ByVal Target As Range)
If Not Intersect(Target, Range("A20")) Is Nothing Then
Select Case Range("A20")
Case "Yes": Macro_001
Case "No": Macro_002
End Select
End If
End Sub
Sub Macro_001()
Application.Calculation = xlManual
Application.ScreenUpdating = False
Sheets("August 2020").Select
Sheets("August 2020").Range("B20").Select
ActiveCell.FormulaR1C1 = "Complete"
Application.ScreenUpdating = True
Application.Calculation = xlAutomatic
End Sub
Sub Macro_002()
Application.Calculation = xlManual
Application.ScreenUpdating = False
Sheets("August 2020").Select
Sheets("August 2020").Range("B20").Select
ActiveCell.FormulaR1C1 = ""
Application.ScreenUpdating = True
Application.Calculation = xlAutomatic
End Sub
There much be an easier way with .range perhaps
Thanks in advance
In the developer tab click view code, choose the sheet you want the macro to run on, make sure the upper left drop down says worksheet and the upper right says Change (I'll assume your sheet has headers):
Private Sub Worksheet_Change(ByVal Target As Range)
Dim KeyCells As Range
Dim ChangeCell As Range
Dim numrows As Long
numrows = Cells(Rows.Count, 1).End(xlUp).Row
Set TriggerCells = Range("A1")
Set KeyCells = Range("B2:B" & numrows)
If Application.Intersect(TriggerCells, Range("A1")) = "[Column Header Text]" Then
If Not Application.Intersect(KeyCells, Range(Target.Address)) Is Nothing Then
If Target.Value = "Yes" Then
Range("B" & Target.Row).Value = "Completed"
End If
End If
End If
End Sub
Try that, see if it works for you.

disable entry to cell if another cell is not empty

How do I render any cell in range ("A1:A10") uneditable (cannot be changed) if there is any content in 2 cells to the right (same row, column C), and make that cell editable again once the cell in same row column C becomes empty.
I tried the code below but it has no effect, i can still edit the cells in col A even with content in col C. Ideally I would like to have it done without protecting sheet.
Private Sub Worksheet_Change(ByVal Target As Range)
Application.EnableEvents = False
If Not Intersect(Target, Range("C1:C10")) Is Nothing Then
If Target.Value <> "" Then
Target.Offset(0, -2).Cells.Locked = True
ActiveSheet.Protect Contents:=True
End If
Application.EnableEvents = True
End If
End Sub
Thank you,
Jay
Option Explicit
'*** Note: I need to reside in the Sheet Module for the
' sheet I am working on!
'*** Note: Make sure the Locked flags for A1:A10 and
' C1:C10 are cleared before implementing.
Private Sub Worksheet_Change(ByVal Target As Range)
Dim rng As Range
Application.EnableEvents = False 'Turn off Events to prevent loop!
If Not Intersect(Target, Range("C1:C10")) Is Nothing Then
ActiveSheet.Unprotect 'You need to unprotect before proceeding
For Each rng In Target
If rng <> "" Then 'Checking for Target.Address will always have a value!
rng.Offset(0, -2).Locked = True
Else
rng.Offset(0, -2).Locked = False
End If
Next rng
ActiveSheet.Protect Contents:=True 'Turn Protection back on
'*** If you have other protected elements DrawingObjects and/or Scenarios
' you need to include in line above.
End If
Application.EnableEvents = True 'Re-enable Events
End Sub 'Worksheet_Change
HTH
You are checking Target.Address on being an empty string. Why? Shouldn't that be Target.Value?
In top of this, what's going wrong? Did you debug the code, using breakpoints? What did you see? ... In case my answer does not satisfy your needs, please edit your question and add the needed information.

Need help changing cell values when cell in same row changes

I need help automatically changing cells containing a certain value whenever a specific cell on same row changes value.
E.g whenever a cell in B column changes = change TRUE to FALSE on that specific row.
My VBA knowledge is pretty much nonexistent and Im certainly a beginner.
Im fairly sure that Worksheet.Change is what Im looking for and I've been trying out some code I've found here on SO, such as:
Private Sub Worksheet_Change(ByVal Target As Range)
If Intersect(Target, Target.Parent.Range("B:B")) Is Nothing Then Exit Sub
For Each x In Target
Cells(x.Row, 3).Value = "False"
Next
End Sub
I know though that this doesn't replace specific values in whatever column the cells are.
I've been trying out silly things like:
Private Sub Worksheet_Change(ByVal Target As Range)
If Intersect(Target, Target.Parent.Range("B:B")) Is Nothing Then Exit Sub
For Each x In Target
If Cells(x.Row, x.Column).Value = "TRUE" Then Value = "FALSE"
Next
End Sub
But of course it doesnt work.
Think you could point me out a direction of what I should be researching?
Replace the change event sub on the sheet where you have your data with the code below. I think that should do the trick
Private Sub Worksheet_Change(ByVal Target As Range)
Dim oRng As Range
Dim oCell As Range
' Check if change was in column B
If Intersect(Target, Target.Parent.Range("B:B")) Is Nothing Then Exit Sub
' Turn off events so that when we make a change on the sheet, this event is not triggered again
Application.EnableEvents = False
' Set the range to include all column in Target row
Set oRng = Target.Parent.Range("C" & Target.Row & ":" & Target.Parent.Cells(Target.Row, Target.Parent.UsedRange.Columns.Count).Address)
' Loop through all cells to change the value
For Each oCell In oRng
If Trim(LCase(oCell.Value)) = "true" Then
oCell.Value = "FALSE"
End If
Next
' Enable events again
Application.EnableEvents = True
End Sub

How to return a timestamp when a specific value is entered into a specific cell

I'm creating a report-styled sheet in Excel, and trying to get a timestamp to automatically be entered in cell "P4" if cell "I6" has a value of "Completed"
I've tried using =IF formulas, which worked, but I'm unable to toggle iterative calculation on the machines this sheet will be working on.
I'm fairly new to writing my own VBA, and I'm having some trouble getting my current code to work. Below is what I currently have, which isn't giving me any results.
Private Sub Worksheet_Change(ByVal Target As Range)
Dim r As String
Set r = Cells("I6")
If r.Value Is Nothing Then Exit Sub
If r.Value <> "Completed" Then Exit Sub
If r.Offset(-2, 7).Value <> "" Then Exit Sub
Application.EnableEvents = False
r.Offset(-2, 7) = Now()
Application.EnableEvents = True
End If
End Sub
I expect the code to give me a current timestamp in Cell "P4" once the value "Completed" is entered into cell "I6", but nothing is showing up. How would I correct it in order to get the value based timestamps?
As this sub is called at every cell's change (and you may use it later for other cell-checks also), check by Intersect first, if "your" cell is affected.
The changed range is given as Target (which may be a single cell or a complete range, e. g. when you paste on it). If that is intersected with your monitored cell I6, you can go ...
Private Sub Worksheet_Change(ByVal Target As Range)
Dim RelevantArea As Range
Set RelevantArea = Intersect(Target, Me.Range("I6"))
If Not RelevantArea Is Nothing Then
If Target.Value = "Completed" Then
Application.EnableEvents = False
Me.Range("P4").Value = Now()
Application.EnableEvents = True
End If
End If
End Sub

VBA Range find in 1 column to Show/Hide another column

This one has driven me mad so hopefully one of you can tell me what I'm doing wrong.
All I want to do is if any cell in column I contains the value "Y" then column J gets hidden. If you then delete the Y from any cell then column J appears again.
Here's my code:
Private Sub Worksheet_Change(ByVal Target As Range)
Dim rng As Range
Set rng = Range("I:I")
Set cell = rng.Find(What:="Y")
If cell Is Nothing Then
Columns("J").EntireColumn.Hidden = True
Else
Columns("J").EntireColumn.Hidden = False
End If
End Sub
Basically the code does absolutely nothing. Which annoys me more than getting an error, because I have no clue what I've done wrong.
Try the following...
Private Sub Worksheet_Change(ByVal Target As Range)
Dim cell As Range
Columns("I:I").Select
Set cell = Selection.Find(What:="Y", After:=ActiveCell, LookIn:=xlFormulas, _
LookAt:=xlWhole, SearchOrder:=xlByRows, SearchDirection:=xlNext, _
MatchCase:=False, SearchFormat:=False)
If cell Is Nothing Then
Columns("J").EntireColumn.Hidden = False
Else
Columns("J").EntireColumn.Hidden = True
End If
End Sub
This is something that works:
Option Explicit
Private Sub Worksheet_Change(ByVal Target As Range)
Dim c As Range
If Target.Column = 9 Then
With Range("I:I")
Set c = .Find("Y")
If Not c Is Nothing Then
Columns("J").EntireColumn.Hidden = True
Else
Columns("J").EntireColumn.Hidden = False
End If
End With
End If
End Sub
In order to make sure that it works, put your code in the corresponding sheet,not in the module
Make sure that macros are enabled
Firstly, you can keep this VBA really simple if you have a cell in your workbook which tests if there are any Y in column I. I put the following into cell A1
=COUNTIF(I:I,"Y")
I advise putting this on the worksheet because Excel is smart and will perform this calculation quicker than VBA - it also gives you some sight of what's going on.
We can now use the value of A1 to determine whether to hide column J in the macro
Firstly, it's probably a good idea to test if column J is in the correct state when you open the workbook so put the following code into the ThisWorkbook module. This code is optional
Sub Workbook_Open()
With Me.Worksheets("Sheet1")
If .Range("A1").Value > 0 Then
.Range("J:J").EntireColumn.Hidden = True
Else:
.Range("J:J").EntireColumn.Hidden = False
End If
End With
End Sub
Then to monitor any changes to values in column I, place the following code into your worksheet module
Sub Worksheet_Change(ByVal Target As Range)
If Not Intersect(Target, Me.Range("I:I")) Is Nothing Then
If Me.Range("A1") > 0 Then
Me.Range("J:J").EntireColumn.Hidden = True
Else
Me.Range("J:J").EntireColumn.Hidden = False
End If
End If
End Sub
Note: this code is not designed for the user changing multiple cells at once, which shouldn't be a problem if you intend to use it as described. If you wish to paste over multiple cells (for example) at a time, then this will need to be adapted slightly.
Private Sub Worksheet_Change(ByVal Target As Range)
Columns("J").EntireColumn.Hidden = WorksheetFunction.CountIf(Columns("I"),"Y") >0
End Sub
Or
Private Sub Worksheet_Change(ByVal Target As Range)
If Not Intersect(Target, Columns("I")) Is Nothing Then Columns("J").EntireColumn.Hidden = WorksheetFunction.CountIf(Columns("I"),"Y") >0
End Sub

Resources