Vba Cell Selection Based on Value - excel

I couldn't find anything asking quite what I am looking for...
I am using two conditions to set my selection (Finding the value "Reducer", then in the cell directly below it, finding "" {an empty cell}).
I am having trouble finding a way to select the cells that match these criteria and then listing the cell address (I want to display the cell address in a message box, alerting them of the location of the 'error')
Eventually there will be many more cells to look for, which is why I want to search through multiple cells.
So in a nutshell, I want my code to find the two criteria, select the cell matching the criteria, and show a pop-up message stating which cell the error is in.
Private Sub Worksheet_Change(ByVal Target As Range)
If ActiveSheet.Range("J11").Value < 0 Then
MsgBox "You have exceeded the maximum allowable pipe length for this section. Please review your selection before continuing. ", vbOKOnly, "Inoperable Pipe Length"
End If
Do While ActiveSheet.Range("J17,J7").Value = "Reducer"
If ActiveSheet.Range("J18,J8").Value = "" Then
G = Sheets("Pipe Calcs").Range("J18,J8").Address
MsgBox "Please Select a reducer size in cell " & G & ActiveCell.Address(False, False), vbCritical, "No Reducer Size Selected"
Exit Sub
Else
End
End If
Loop
End Sub

Private Sub Worksheet_Change(ByVal Target As Range)
If ActiveSheet.Range("A1").Value < 0 Then
MsgBox "You have exceeded the maximum allowable pipe length for this section. Please review your selection before continuing. ", vbOKOnly, "Inoperable Pipe Length"
End If
For Each cell In Range("J1:J1000")
If cell.Value = "Reducer" Then
If Range(cell.Address).Offset(1, 0) = "" Then
G = Sheets("Pipe Calcs").Range(cell.Address).Offset(1, 0).Address
MsgBox "Please Select a reducer size in cell " & G
Range(Cell.Address).Offset(1, 0).Select
Exit Sub
End If
End If
Next
End Sub
The above code will check column J for "Reducer", if found, it will see if the cell below contains a value, if it doesn't it will prompt the user for the cell and exit the sub. When the user updates the cell, they trigger the Worksheet_Change statement and cause the macro to run again.

Related

Limit the number of times each option in a dropdown can be selected

I have a table with 16 rows.
Each cell in column A has a dropdown list with 10 items.
I want to set a limit for each of these items so that, for example, the first one couldn’t be selected more than 3 times, the second one no more than 2 times and so on.
Is it feasible with or without VBA?
You could use something like this in the sheet module:
Option Explicit
Private OldValue As Variant
Public Sub Worksheet_SelectionChange(ByVal Target As Range)
'Storing the old value of the newly selected cell
OldValue = Target.Value2
End Sub
Private Sub Worksheet_Change(ByVal Target As Range)
On Error GoTo ErrHandler
Application.EnableEvents = False
'Check if the cell that was changed is in column A
If Not Intersect(Target, Me.Range("A:A")) Is Nothing Then
If Application.WorksheetFunction.CountIf(Me.Range("A1:A1000"), Target.Value2) > 2 Then
MsgBox "You can't select more than 2 times the value: " & Target.Value2
'Reset to the old value
Target.Value2 = OldValue
End If
End If
Application.EnableEvents = True
Exit Sub
ErrHandler:
Application.EnableEvents = True
End Sub
Private Sub Worksheet_Activate()
'If the worksheet just got activated, make sure we have the value of the active cell stored.
If IsEmpty(OldValue) Then
OldValue = ActiveCell.Value2
End If
End Sub
Basically, you have to use the Worksheet_SelectionChange event to store the previous value of the cell when it is selected. Then after the user tries to make a change to the cell, the Worksheet_Change event will look through the first 1000 cells of column A (you can always customize this amount) with the COUNTIF function.
Then, if the number of occurrences of the newly selected value is too high (>2 in this case), an error message is displayed and the value is set back to the previous value.
For safety measures, I've added the Worksheet_Activate event code to make sure that we have the value of the cell even if the user arrives from another sheet and doesn't change the selected cell.
If you want to have different limits for the number of repetitions allowed, you could add a Select Case that would handle that :
...
If Not Intersect(Target, Me.Range("A:A")) Is Nothing Then
Dim UpperLimit As Long
Select Case Target.Value2
Case Is = "First value": UpperLimit = 3
Case Is = "Second value": UpperLimit = 2
Case Is = "Third value": UpperLimit = 1
Case Else: UpperLimit = 2 'Default limit
End Select
If Application.WorksheetFunction.CountIf(Me.Range("A1:A1000"), Target.Value2) > UpperLimit Then
MsgBox "You can't select more than "UpperLimit & " times the value " & Target.Value2
Target.Value2 = OldValue
End If
...
Additionally, you might want to prevent people to copy paste in that region. If that's the case, this could be useful to you:
https://jkp-ads.com/Articles/CatchPaste.asp

How can I lock most of a row when a specific cell has data?

I have a spreadsheet that provides part numbers for the weird and wonderful. It's basically complete when I realised that someone could accidentally change previous entries and break the whole thing! Database is in my sights, but for now Excel must do.
I want to lock Row X from columns A-K when something is in column L, the date. I'm currently using Application.Intersect Target to ensure no-one tries to leave blank rows or incomplete descriptions, but can't seem to get the addition of locking.
Current Sub looks like this:
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Count <> 1 Then Exit Sub
Dim isect As Range
On Error Resume Next
Set isect = Application.Intersect(Target, Range("E3:E9999"))
If Not (isect Is Nothing) Then
If Target.Column = 1 Then
If Len(Target.Value) > 0 And Len(Target.Offset(-1, 2).Value) = 0 Then
' Check if a row is skipped on Initials
MsgBox "You cannot skip a row", vbInformation
Target.ClearContents
End If
Else
If (Len(Target.Value) > 0 And Len(Target.Offset(-1, 0).Value) = 0) Or (Len(Target.Value) > 0 And Len(Target.Offset(-1, 2).Value) = 0) Then
' Check if previous part description is blank
MsgBox "You cannot skip a row, or leave an incomplete part", vbInformation
Target.ClearContents
End If
End If
End If
End Sub
I'm an idiot. I solved this with a simple data validation If(Next Cell = "",Named-List,FALSE) to disable drop-down adjustment once a part has been created.

If statement that only performs action when selection is within a specific column

I am trying to finish this macro that will open another workbook, copy, and paste the selected cells into the other workbook. I want to do this only when the selection is in column A and only when the selection contains data.
The if the selection contains data part is easy, however how can I make a statement that says if selection is not within column A, then MsgBox("Please select data")?
Here is the if statement so far, it still needs the part mentioned directly above.
'Warns if no QN#s are selected
If Selection = "" Then
MsgBox ("Please Select Your QN#s Before Running This Macro")
Exit Sub
End If
This seems to work for recognizing if the cells are within a certain column.
If Not Intersect(Selection, Range("A:A")) Is Nothing Then
'Proceed
Else
MsgBox ("Please Select Your QN#s Before Running This Macro")
Exit Sub
End If
Why not use a Worksheet_SelectionChange?
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
If Target.Column <> 1 Then
MsgBox "Please Select Your QN#s Before Running This Macro", vbOKOnly, "Data Selection"
Else
RunMacro
End If
End Sub
Use this pattern of codes. This is just dealing with the selection and not detecting changes.
Dim a As Integer
Dim b As Integer
Dim c As String
a = Selection.Row
b = Selection.Rows.Count - 1
c = "A" & a & ":" & "A" & a + b
If ((Selection.Column = 1) And (WorksheetFunction.CountA(Range(c)) > 0)) Then
MsgBox "ready to go"
End If
In the above code the hidden rows with data will be considered.
Merged cells are considered as one cell with value and others are blanks( example: When you have merged A2:A5, then you have 3 blank cells)

Value in cell to match in a List I have and do it to every cell under that too(Title Not Good)

I would like the macro/code to take the Product that was entered in that cell (relative reference I guess) and scan a list of Products I have. If it doesn't match I would like the message box to tell me which product entered doesn't match with one in my product list and to return its row number where it was entered.
So to give you another example. Lets say we'll enter a number "1" in a cell. I need the macro to search my list of numbers 1-100, if 1 isn't in there I would like it to tell me. Let's say the next number entered (in the following cell under) was a 101. A message box would tell me 101 is not in my number list and its located in row 2.
It probably needs loops. As I will have a range of about 500 cells going down in that column that I would like it to search that product with a list.
Right click on Sheet Tab --> View Code --> and paste the code given below into the opened code window --> Close the VB Editor --> Save your workbook as Macro-Enabled Workbook.
The following code assumes that you have a named range called "List" on Sheet2 (code name not the tab name).
If you input a value in column A starting from row2, the code will automatically check if the value you entered is found in the named range List and if it doesn't find that value, a msgbox will be popped up to give you some information.
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.CountLarge > 1 Then Exit Sub
If Target.Column = 1 And Target.Row > 1 Then
If Target <> "" Then
If Application.CountIf(Sheet2.Range("List"), Target.Value) = 0 Then
MsgBox "The value " & Target.Value & " you entered in cell " & Target.Address(0, 0) & " was not found in the List", vbExclamation, "Item Not Found!"
End If
End If
End If
End Sub
Edit:
Replace the above proposed code with the following code.
The following code will be useful if you change multiple cells at once and will provide you a list of all the values which were not found in the List named range.
Private Sub Worksheet_Change(ByVal Target As Range)
Dim cell As Range
Dim str As String
Dim Found As Boolean
str = "The following values were not found in the List." & vbNewLine & vbNewLine
If Target.Column = 1 And Target.Row > 1 Then
For Each cell In Target
If cell <> "" Then
If Application.CountIf(Sheet2.Range("List"), cell.Value) = 0 Then
Found = True
str = str & cell.Address(0, 0) & " : " & cell.Value & vbNewLine
End If
End If
Next cell
End If
If Found Then MsgBox str, vbExclamation, "Values Not Found!"
End Sub
You could use a formula get what you want.
=IFERROR(MATCH(PRODUCT,LISTofPRODUCTS,0),"Not Found In List")
Same formula using actual cell references:
=IFERROR(MATCH(A1,$B$1:$B$500,0),"Not Found In List")
Where the value you want to look for is in cell A1, and the list you want to look in is B1:B500
To know what row the un-matched value is in, you could use this formula
=IF(ISERROR(MATCH(A1,$B$1:$B$500,0)),"Found","Value in row " & ROW(A1) & " not found")

Verify contents - do not allow user to enter - give invalid data report

I am trying to write a program to do following steps:
When at cell M2, check the contents of all the cells before column
M in same row
In case any of the cells before column M in same row is empty, do
not allow user to enter any value in cell M2. RAther given a message
to user about empty data.
Creates a report in cell N2 of the missing data's (The first row of
excel is having headings of data contained in columns)
Problems encountered till now:
Indefinite loop - i think when clearing contents loop is triggered again that is causing this problem
I am not sure if the concatenate code is good or not.
Program below:
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Address = "$M$2" Then
MsgBox "1"
Call MyMacro
End If
End Sub
Sub MyMacro()
'If [OR(ISBLANK(A2:L2))] Then
If ISBLANK(A2) Then
MsgBox "2"
Range("N2").Select
ActiveCell.Value = N2.Value + A1.Value
'Range("M2").ClearContents
'MsgBox "3"
'this the message that pops up if any cell in the range is blank
End If
End Sub
Thank you for your response in advance...
Another option,which doesn't use macros, is to use data validation in column M, with the custom formula
=counta(A2:L2)=12
and the custom Error message "Blank cells in columns A through L".
This of course doesn't give you the missing cells, but you could get the first one with this array formula (enter with ctrl+Shift+enter)
=IFERROR(ADDRESS(ROW(),MATCH(TRUE,A2:L2="",0)),"")
Something like this will
test for blanks (true blanks) in A2:L2 when M2 is changed
Turn Events off, to avoiding reloading the code if N2 is used
dump these offending cell range in N12 is there blanks
code
Private Sub Worksheet_Change(ByVal Target As Range)
Dim rng1 As Range
If Intersect(Target, Range("M2")) Is Nothing Then Exit Sub
With Application
.EnableEvents = False
On Error Resume Next
Set rng1 = Range("A2:L2").Cells.SpecialCells(xlBlanks)
On Error GoTo 0
If Not rng1 Is Nothing Then
MsgBox "blank cells in " & rng1.Address(0, 0), vbCritical, "User entry in M2 removed"
[n2] = rng1.Address
[m2].Clear
End If
.EnableEvents = True
End With
End Sub

Resources