Conditional cell disablement in Excel - vba

I'm using Excel 2007. I want the following behaviour:
If cell A2 is empty or contains value "Create" then cell B2 is inactive and the user cannot enter a value.
If cell A2 contains the value "Modify" or "Retire" then cell B2 is active and the user can enter a value.
These behaviours need to be limited to their specific rows, so cell B3 needs to be unaffected by the value in cell A2. These behaviours need to be functional in rows 2 to 501.
I guess that this will require some VBA

The simplest solution (yet not fail proof) would be to create a data validation for the cell by going to data, data-validation, and custom. In the formula input, you could put in
=A2<>"Create"
if you dont want B2 to be editable if A2 contains "Create". Then you can highlight A2 and B2 and drag it down to row 501. thats the quickest solution that I've stumbled across. Hope this helps

2 ways you can persue here I think, either you protect the worksheet and lock those specific cells based on the conditions you stated, or you write a routine for the worksheet_change event.
The first is rather devious I think, so I would opt for the latter.
Something like this perhaps?
Option Explicit
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Column = 2 Then
If Target.Value = vbNullString Then Exit Sub 'to prevent endless loops
If Cells(Target.Row, 1) = "Create" Or Cells(Target.Row, 1) = vbNullString Then
Target.Value = vbNullString
End If
End If
End Sub
All this in the worksheet.
Some explanation:
This sub gets called by Excel whenever the worksheet is changed (hence the name). So if you type a value into any cell, the sub gets called when you leave the cell (hit enter or click another cell, etc).
The Target argument in the sub is the range that has just changed.
So if you type 33 in cell B1, Target will be Range("B1"). So Target.Column is the column of the cell that has just changed (in this case, 2), Target.Row is the row (1) and Target.Value hold the value you just entered (33). So Cells(Target.Row, 1) is (in this case) cell A1.
This sub will work for all the rows in the sheet, but I'm sure you can adapt it to check which row it is in.
EDIT: added some explanation

Related

VBA: use one cell (as data entry field) to copy data to another tab

I'm currently working in an Excel file and would like to have one cell (say B3) of which the content is automatically pasted in another tab. After replacing the content from B3 by other info, I would still like to have the old info in the other tab, but now supplemented with the new content underneath it. So that the B3 would be sort of a data entry field, and the other tab serves as a 'database'. I think this would require the use of VBA, but I'm very unfamiliar with this, so any help would be great!
you can use worksheet event like this :
Private Sub Worksheet_Change(ByVal Target As Range)
' Change value on cell A1
If Target.Address = "$A$1" Then
' Insert value on column 2
Me.Cells(1, 2).Insert xlShiftDown
Me.Cells(1, 2).Value = Target.Value
End If
End Sub

VBA - Is it possible to transform a cell into a cutom hyperlink?

I am wondering if it could be possible to use VBA in order to be able to transform a cell which already contains a part of the url into an active hyperlink.
To be more specific here is an example of what i've managed to work with so far:
On column B, in cell B14 i have the following formula
=HYPERLINK("https://google.ro/"&D14,"search") -> this is only for row 14
now on cell D14 i have the last part of the URL, for example "dogs". now when i press on cell D14 it open a new browser page and takes me to that specific address.
So my question is, can i do this on a single cell using VBA, on this example in D14, without using Column B anymore? Basically is there a way to integrate the formula used in column B into VBA?
Thanks.
Add an Event-Routine for your sheet. This one will open the browser immediately when clicking on it (in the example, it is limited to column 'D')
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
' Check if only 1 cell is selected
If Target.Rows.Count > 1 Or Target.Columns.Count > 1 Then Exit Sub
If Target.Column = 4 And Target.Value <> "" Then
ThisWorkbook.FollowHyperlink "https://www.google.de/search?source=hp&q=" & Target.Value
End If
End Sub
If I've understood correctly, you need the ThisWorkbook.FollowHyperlink method
Sub TestHyperlink()
ThisWorkbook.FollowHyperlink "https://google.ro/" & Range("D14")
End Sub
You may need to qualify the Range("D14") with the worksheet name depending where you're calling your code from.

Worksheet_Change determine value not content

I am trying to detect if there are changes in a cell value, not particularly the cell contents. I have found multiple solutions to find out if a cell contents has changed, but it does not work when a cell is equal to another cell.
For example, I have cell A1 set to equal B1 and then B1 has a formula that calls in multiple other cells, so I am not able to go back to the beginning and determine whether the cell has changed from that. It needs to come directly from A1.
This is one of the examples I found on this site, but does not determine if the value of A1 has changed, just whether the contents has changed.
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Column = 1 Then
Cells(Target.Row, 3).Value = Date
End If
End Sub
The function application.volatile TRUE at the top of your sub will make your sub calculate each time any value in Excel changes. So then you need a global variable which stores the last-known value of your specified range, and any time the sub runs, start with an
If new_cell_value <> stored_global_variable then...
and close with
stored_global_variable = new_cell value'
End If
See here for further info [h/t to vzczc for the original answer and method]: Refresh Excel VBA Function Results

Dynamically locking cells in Excel

I have four columns (A,B,C,D). My requirement is that in each row, only one cell should accept data, and the remaining cells should not accept data (i.e. the remaining three cells should be in locked mode).
How do I do this?
Here's one way to do what you ask. (Or at least what I think you're asking.)
First, unlock all the cells in the sheet. By default they are all in locked state (though this does not take effect until you actually protect the sheet) so you need to unlock them to start with, otherwise you won't be able to input any data anywhere as soon as you protect the sheet. You can do this manually (In 2003: Select all cells, Format > Cells > Protection > uncheck "Locked") or using VBA as follows:
Sub UnlockAll()
With Sheet1 ' Or whatever sheet you're working on
.Unprotect
.Cells.Locked = False
.Protect
End With
End Sub
The above only needs to be executed once.
Then you have to use the Worksheet_Change event to lock and unlock cells dynamically. In your sheet's module, write this code:
Private Sub Worksheet_Change(ByVal Target As Range)
Me.Unprotect
If Not IsEmpty(Target) Then
'Data was added in target cell. Lock its neighbours.
Me.Cells(Target.Row, 1).Resize(, 4).Locked = True
Target.Locked = False
Else
'Data was erased from target cell. Release its neighbours.
Me.Cells(Target.Row, 1).Resize(, 4).Locked = False
End If
Me.Protect
End Sub
Say you write data in cell B2; this will lock cells B1, B3, and B4 so that no data can be entered. If you later decide to clear cell B2, then this will unlock B1, B3, and B4.

Excel, 2 sheets, 2 columns, same value?

I have 2 sheets sheet1 and sheet2 in an excel 2007 file.
In sheet2 I have a column that is managed by a form/macro(with a tree view control). When an element has been selected, the cell is filled with an "x", when it has been unselected, the cell is filled with "" (nothing).
In sheet1 I want to create a column equal to the sheet2 column.
So for example: if sheet2!C24 = "x" then sheet1!c24 should also be "x"
I also would like it to work both ways. If the user changes sheet1!c24 to "x", then I want sheet2!c24 to take the same value.
Problems:
- in Sheet1, I tried sheet1!c24 = sheet2!c24, but then when sheet2!c24 = "", sheet1!c24 displays 0 instead of nothing
- in Sheet2, I tried sheet2!c24 = sheet1!c24, but then the cells display the formula (='sheet1!c24') instead of the value...
So basically, what I want is that whatever change you do, in sheet1 or in sheet2, both columns in sheet1 and sheet2 are updated...
How can I achieve this?
What I think you need to do is use the Worksheet_Change events for both sheets and if a change is made in the column you are interested in, then you update the same cell in the other sheet.
Something like this would go in the worksheet code module:
Private Sub worksheet_change(ByVal target As Range)
Dim c As Range
'Test to see if the cell just changed is
'in the column we are interested in
Set c = Application.Intersect(target, Range("A:A"))
If Not c Is Nothing Then
'Copy across to other sheet
If Not beingEdited Then
beingEdited = True
Sheet1.Range(target.Address) = target.Value
beingEdited = False
End If
End If
End Sub
You'd need a beingEdited variable to be declared somewhere else with larger scope so that you could avoid the events triggering themselves and Excel getting stuck in a loop.
In the other sheet you'd basically have the same procedure, except that it would reference the first worksheet, e.g. Sheet1.Range(target.Address) = target.Value.
Obviously, you'd have to tweak this to your ranges/sheets.
You've got the right idea, but you probably need to turn off events before making the change, otherwise you'll end up in a loop
Private Sub worksheet_change(ByVal target As Range)
application.enableevents = false
sheet1.range("c24").value = sheet2.("c24").value
application.enableevents = true
end sub
Just make sure you enable events again at the end.
i did something like this where i had a summary sheet and a tests sheet. When I added a new value in tests sheet and it passed (P) a cell in summary sheet will keep increment. This is to keep a count of how many tests passed. here it is:
COUNTIF(tests!$C$5:$C$1017, "P");
hope this helps.