circular reference with data validation list in excel - excel

I'm trying to see if it is possible to choose an item from a data validation list in either sheet 2 or 3 or 4, cell E2 to change automatically. Meaning i want the cell E2 in each of these sheets linked with each other, so if i change any one of them the other has to show the new value. The list itself is in sheet 1.
I also would like to extend this macro from just cell E2 to a range of cells (E2 to E300).
The problem i have now is if i use the code, it also changes the value of cell E2 in sheet 1. I have the code copied to modules in sheets 2, 3 4 and not in module of sheet 1.
Private Sub Worksheet_Change(ByVal Target As Range)
Dim ws As Worksheet
If Target.Address = "$E$2" Then
For Each ws In ThisWorkbook.Worksheets
If Not ws.Name = Me.Name And Not ws.Name = "Sheet1" Then
If Not ws.Range(Target.Address) = Me.Range(Target.Address) Then
ws.Range(Target.Address) = Me.Range(Target.Address)
End If
End If
Next ws
End If
End Sub

Welcome to SO. You cna handle an unique sub from Worksheet_Change event
I made up this code in that event on each worksheet.
Private Sub Worksheet_Change(ByVal Target As Range)
UPDATE_E_VALUES ActiveSheet, Target
End Sub
And the code in a module of sub UPDATE_E_VALUES is:
Public Sub UPDATE_E_VALUES(ByVal vThisWK As Worksheet, ByVal vThisCell As Range)
Application.EnableEvents = False
Application.ScreenUpdating = False
If vThisCell.Row >= 2 And vThisCell.Row <= 300 And vThisCell.Column = 5 Then 'check if cell is in range E2:E300
Select Case vThisWK.Name
Case "Sheet1"
'we do nothing
Case "Sheet5"
'we do nothing
Case Else
'we update all E cells with same address
With ThisWorkbook
.Worksheets("Sheet2").Range(vThisCell.Address).Value = vThisCell.Value
.Worksheets("Sheet3").Range(vThisCell.Address).Value = vThisCell.Value
.Worksheets("Sheet4").Range(vThisCell.Address).Value = vThisCell.Value
End With
End Select
With ThisWorkbook
.Worksheets("Sheet2").Range(vThisCell.Address).Value = vThisCell.Value
End With
End If
Application.EnableEvents = True
Application.ScreenUpdating = True
End Sub
Hope you can adapt this to your needs. You can add/remove extra lines where you want sheets to be affected or not

Related

How to dynamically lock and unlock a cell in Excel?

What should i do to dynamically lock/unlock my cell in excel? For example, if i create a new document, by default all cells are unlock but i entered a data on that cell it will be lock. I tried this, which i found here Lock empty cells and unlock free cells
Sub test()
Dim rngTemp As Range
For Each rngTemp In Range("A1:XFD1048576").Cells
With rngTemp
If .Value > 0 Or Len(.Value) > 0 Then
.Locked = False
End If
End With
Next
End Sub
but it's not working on my case. I am using 2007 excel version. Do i still need to save the code or Alt + Q is enough?
EDIT: As per #JvdV's answer I tried the following:
Private Sub Worksheet_Change(ByVal Target As Range)
Dim rng As Range
With Sheet1
.Unprotect
.Cells.Locked = True
.Cells.SpecialCells(xlCellTypeBlanks).Locked = False
.Protect
End With
End Sub
But this returns an error Run-time error '1004' No cells were found on .Cells.SpecialCells(xlCellTypeBlanks).Locked = False.
If you really are intested in those cells, you can simply refer to a worksheet's cells. Also, no need to loop through those cells individually, for example:
Sub test()
Dim rng As Range
With Sheet1 'Change according to your sheet's CodeName
.Unprotect
.Cells.Locked = False
.Cells.SpecialCells(xlCellTypeBlanks).Locked = True
.Protect
End With
End Sub
Where .Cells.Locked = False unlocks all cells and .Cells.SpecialCells(xlCellTypeBlanks).Locked = True locks all cells blank cells (Note: a ="" value through formulas is considered a value and will stay unlocked)
Both Unprotect and Protect are needed to have full effect of your changes.
If this is code you want to run each time a value is changed, you'll have to look into the Worksheet_Change event. And if your goal is to have empty cells unlocked and cells that contain a value locked, just swap around the True and False.
EDIT (as per your comments)
If this is something you like to run on every next selection of cells, try the following (error handler included since you not using the whole worksheet nomore)
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Sheet1.Unprotect 'Change according to your sheet's CodeName
With Target
.Cells.Locked = True
On Error Resume Next
.Cells.SpecialCells(xlCellTypeBlanks).Locked = False
On Error GoTo 0
End With
Sheet1.Protect
End Sub
If you looking for an alternative where you loop through your target range, you can implement the suggestion by #M.Schalk
As an addition to the (correct) answer above, here is my suggestion for a Worksheet_Change event, as you requested in the comments. This will have to be placed in the workbook-specific code module:
Private Sub Worksheet_Change(ByVal Target As Range)
Dim cll As Range
On Error Resume Next
For Each cll In Target.Cells
With cll
If .Value2 <> vbNullString Then
.Locked = True
Else
.Locked = False
End If
End With
Next
End Sub
It's important to note, that (at least in my version of Excel) the .Locked property of a cell only has an effect when the sheet is protected. To change the value of the .Locked property however, the sheet must not be protected. To incorporate this you might want to use something like this:
Private Sub Worksheet_Change(ByVal Target As Range)
Dim cll As Range
On Error GoTo Handler
Me.Unprotect
For Each cll In Target.Cells
With cll
If .Value2 <> vbNullString Then
MsgBox cll.Value2
.Locked = True
Else
MsgBox "NullString"
.Locked = False
End If
End With
Next
Handler:
Me.Protect
End Sub
This will lead to every cell becoming un-changeable once a value is entered, while still letting the user enter values in all empty cells. To change existing values you will need to manually unprotect the sheet. You might use something like the code provided in the answer above to restore a desired state after the sheet was unprotected and changed.

disable the range of cells on another sheet ( say Sheet2) based on the value in the current sheet(say Sheet1)

I'm trying to disable the range of cells on another sheet ( say Sheet4) based on the value in the current sheet(say Sheet1)
I have tried to disable the values in the sheet4("M4,M6,M8,M10,M12") based on the values in sheet1("C5") by using worksheet change function.
With Sheet1 I have used the below code and getting the error message
Subscript Out of Range
Private Sub Worksheet_Change(ByVal Target As Range)
Dim myRng As Range
Dim Cancel As Boolean
If Not Intersect(Target, Me.Range("C5")) Is Nothing Then
Set myRng = ThisWorkbook.Worksheets("Sheet4").Range("M4,M6,M8,M10,M12")
Me.Unprotect Password:=SHEET_PASSWORD
If Me.Range("C5").Value = "Yes" Then
myRng.Locked = False
Else
myRng.Locked = True
ThisWorkbook.Worksheets("Sheet4").Range("M4,M6,M8,M10,M12") = ""
End If
Me.Protect Password:=SHEET_PASSWORD
End If
End Sub
If I choose "Yes" in the cell value C5 in Sheet1, the cell values (M4,M6,M8,M10,M12) in sheet4 should be enabled. If i choose "No" in the cell value C5 in Sheet1, the cell values (M4,M6,M8,M10,M12) in sheet4 should be disabled.
I think This is what you are looking For.
Private Sub Worksheet_Change(ByVal Target As Range)
If ChangeEventFlag = 0 Then
Dim myRng As Range
Dim Cancel As Boolean
If Not Intersect(Target, Me.Range("C5")) Is Nothing Then
With ThisWorkbook.Worksheets("Sheet4")
.Unprotect Password:="password"
.Cells.Locked = False
Set myRng = .Range("M4,M6,M8,M10,M12")
If Me.Range("C5").Value = "Yes" Then
myRng.Locked = False
Else
myRng.Locked = True
myRng.Value = ""
End If
.Protect Password:="password"
End With
End If
End If
End Sub
Note:
Not sure about the use of ChangeEventFlag
Change the Password, I used password for testing
Use:
Whichever sheet you will paste this code on will Lock Range("M4,M6,M8,M10,M12") of Sheet4 if it's C5 is No(Anything Other Than Yes Actually) and will unlock it if C5 is Yes

If A1 changes, put something into B1 | If A2 changes, put something into B2

I have rows from 1-100.
I know how to target specific cells and get data from them, but how would I do this when any row from 1 to 100 can be changed?
Say you put anything into Row A3. How would you write "Updated" into row B3 via VBA?
I want this to apply to rows A1-A100.
Thanks
Place the following event macro in the worksheet code area:
Private Sub Worksheet_Change(ByVal Target As Range)
Dim A As Range, Intersection As Range, Cell As Range
Set A = Range("A1:A100")
Set Intersection = Intersect(Target, A)
If Intersection Is Nothing Then Exit Sub
Application.EnableEvents = False
For Each Cell In Intersection
Cell.Offset(0, 1).Value = "Updated"
Next Cell
Application.EnableEvents = True
End Sub
Open VBA Editor
Double click on the sheet you event take action (sheets appears in the left top box)
Select Worksheet on the left box above code box
Select change on the right box above code box
Paste the code
Option Explicit
Private Sub Worksheet_Change(ByVal Target As Range)
With ThisWorkbook.Worksheets("Sheet1")
If Not Intersect(Target, .Range("A1:A100")) Is Nothing Then
Application.EnableEvents = False
.Range("B" & Target.Row).Value = "Updated"
Application.EnableEvents = True
End If
End With
End Sub

Hide Excel sheet based on value of a cell in a range

I'm trying to hide a sheet in an Excel workbook based on the contents of any of the cells in a given range.
Let's say I have two sheets - "Sheet1" and "Sheet2".
On Sheet1, I want to set up a range - cell C10 to F10.
Each of these cells can either be blank, or contain "Yes" or "No" - chosen from a dropdown box.
If ANY of the cells in the range are set to "Yes", I want Sheet2 to be visible, otherwise (if all the cells are either blank or contain "No") I want Sheet2 hidden.
I've tried various pieces of code, including the below.
Private Sub Worksheet_Change(ByVal Target As Range)
Dim rCell As Range
Application.ScreenUpdating = False
For Each rCell In Range("C10:F10")
If rCell.Value = "Yes" Then
Worksheets("Sheet2").Visible = True
Else
Worksheets("Sheet2").Visible = False
End If
Next rCell
Application.ScreenUpdating = True
End Sub
I've got about as far as Sheet 2 being visible if all the cells equal "Yes" or if F10 equals "Yes", but not if only one of the cells contains "Yes".
No loop needed, and create an If to test whether the Cell that change is in the range to test, just to save some comp time:
Private Sub Worksheet_Change(ByVal Target As Range)
If Not Intersect(Range("C10:F10"),Target) Is Nothing Then
Worksheets("Sheet2").Visible = Application.Countif(Range("C10:F10"),"Yes")>0
End If
End Sub
Modify and try:
Option Explicit
Sub test()
Dim ws As Worksheet
Dim rng As Range, cell As Range
Dim Hide As Boolean
For Each ws In ThisWorkbook.Worksheets
Set rng = ws.Range("C10:F10")
For Each cell In rng
Hide = False
If cell.Value = "Yes" Then
Hide = False
Exit For
Else
Hide = True
End If
Next
If Hide = True Then
ws.Visible = False
End If
Next
End Sub

interlink excel cell within a workbook

I have Excel Workbook in which there are 4 sheet which has two cell name start date and end date, whose values should be same across all 4 sheet, I want that If I change the value in anyone of the sheets the other three sheets automatically update that values. And vice versa.
Use the Workbook_SheetChange event to update the same cells on every worksheet if any one of the cells changes.
For example, if each sheet has the named ranges start_date and end_date (where their scope is limited to that sheet only), changes made to any start_date or end_date range on any sheet will update the corresponding range on all the other sheets.
Option Explicit
Private Sub Workbook_SheetChange(ByVal Sh As Object, ByVal Target As Range)
On Error GoTo SafeExit
Application.EnableEvents = False
Dim ws As Worksheet
With Sh
If Not Intersect(Target, .Range("start_date")) Is Nothing Then
For Each ws In Worksheets
ws.Range("start_date").Value = Target.Value
Next ws
End If
If Not Intersect(Target, .Range("end_date")) Is Nothing Then
For Each ws In Worksheets
ws.Range("end_date").Value = Target.Value
Next ws
End If
End With
SafeExit:
Application.EnableEvents = True
End Sub
If you are referring to the cells by their address and not by a defined name, something like this could work:
Private Sub Workbook_SheetChange(ByVal Sh As Object, ByVal Target As Range)
On Error GoTo SafeExit
Application.EnableEvents = False
Dim ws As Worksheet
With Sh
' "A1" is the start date, change as needed
If Not Intersect(Target, .Range("A1")) Is Nothing Then
For Each ws In Worksheets
ws.Range("A1").Value = Target.Value
Next ws
End If
' "B1" is the end date, change as needed
If Not Intersect(Target, .Range("B1")) Is Nothing Then
For Each ws In Worksheets
ws.Range("B1").Value = Target.Value
Next ws
End If
End With
SafeExit:
Application.EnableEvents = True
End Sub
This code goes in the ThisWorkbook module in the VBA editor.
You don't need VBA for this but rather named ranges. Put your cursor in the input cell, say E5, for start_date and then click in the named range box (in the upper left corner of the worksheet grid, directly above column A). Type start_date over E5 and hit Enter. Now, cell E5 is named start_date. If you use =start_date anywhere else in the workbook, it will refer to the current contents of cell E5. If you want to edit the named ranges in any way, go to the ribbon menu FORMULAS -> Name Manager.
If you want to do this with VBA for the sole purpose of learning VBA, I would recommend taking a VBA course instead. Udemy has some good ones that often go on sale for about $10, and I'm sure that there are plenty of free resources elsewhere as well.

Resources