Excel VBA - Value & MsgBox - excel

I posted a question about this piece of code that is already changed by "Alex Bell", He helped me with the code making a MsgBox appear every time the value "496" appears in that specific range. But due to my poor knowledge in this language, there's a lot of things I cannot do.
the next step I was trying to achieve was doing the same thing that is already done, the MsgBox alert if the value is "496", but now with "800" too.
So what is the problem? The Problem is that I cannot figure a way to put the two conditions to work together, for example it tells me where is the "496" and then the "800" and fills both of the cells that contain that specific values.
It's probably a easy question to solve, but again I'm a newbie to vba and when I studied vb in school we didn't learn that much. So be expecting more questions from me on topics related to vba and I'm trying to learn it at the moment.
Private Sub Worksheet_Change(ByVal Target As Range)
Dim cell As Range
If Not Intersect(Target, Range("G3:G500")) Is Nothing Then
For Each cell In Target
'need clarification
'Me.Cells(cell.Row, "496").Interior.ColorIndex = xlColorIndexNone
'If cell.Value <> "" And cell.Value <> prevValue Then
'Me.Cells(cell.Row, "496").Interior.ColorIndex = 3
'End If
If cell.Value = "496" Then
cell.Interior.ColorIndex = 43
MsgBox ("The row where the status is 496 is located in: " & cell.Row)
Else
cell.Interior.ColorIndex = xlColorIndexNone
End If
Next cell
End If
'If Not Intersect(Target, Range("G3:G500")) Is Nothing Then
' For Each cell In Target
'
' If cell.Value = "800" Then
' cell.Interior.ColorIndex = 4
' MsgBox ("The row where the status is 800 is located in: " & cell.Row)
' Else
' cell.Interior.ColorIndex = xlColorIndexNone
' End If
' Next cell
'End If
End Sub

If cell.Value = "496" Or cell.Value = "800" Then
cell.Interior.ColorIndex = 43
MsgBox ("The row where the status is 496 or 800 is located in: " & cell.Row)
Else
cell.Interior.ColorIndex = xlColorIndexNone
End If
Or like this:
If cell.Value = "496" Then
cell.Interior.ColorIndex = 43
MsgBox ("The row where the status is 496 is located in: " & cell.Row)
ElseIf cell.Value = "800" Then
cell.Interior.ColorIndex = 45
MsgBox ("The row where the status is 800 is located in: " & cell.Row)
Else
cell.Interior.ColorIndex = xlColorIndexNone
End If
If you would like to have more checks, you can consider to store the row numbers to print into a variable and at the very end you can call the MsgBox:
Dim rowNumbers As String
rowNumbers = ""
If Not Intersect(Target, Range("G3:G500")) Is Nothing Then
For Each cell In Target
If cell.Value = "496" Then
cell.Interior.ColorIndex = 43
rowNumbers = rowNumbers & cell.Row & " "
ElseIf cell.Value = "800" Then
cell.Interior.ColorIndex = 45
rowNumbers = rowNumbers & cell.Row & " "
Else
cell.Interior.ColorIndex = xlColorIndexNone
End If
Next cell
MsgBox ("The rows where the status is 496 or 800 is located in: " & rowNumbers)
End If

Related

Can't figure out problem with Excel VBA code

I am fairly new to writing code in excel VBA. Most of this code is some I have tried to replicated based on what other people have wrote. The problem I am having is I have a quantity counter and when a barcode is scanned into the cell (A4) it will add the barcode to a new cell (Starts at C8 and goes down) and if this barcode is already scanned once and is scanned again it will add one to the quantity. Now I am trying to add a date and time next to it as a barcode is scanned. This works but has an issue I can't figure out. The barcode must be scanned twice for the date to appear in the proper cell. This is an issue because it raises the quantity up one more than it should. Please help.
Private Sub Worksheet_Change(ByVal Target As Range)
Select Case Target.Address
Case "$A$4"
If Target.Value <> "" Then
On Error Resume Next
Set xitem = Range("C8", Range("C" & Rows.Count) _
.End(xlUp)).Find(Range("A4").Value)
With xitem.Offset(0, -1)
.Value = .Value + 1
.Offset(0, 1).Select
End With
With xitem.Offset(0, 1)
.Value = Date & " " & Time
.NumberFormat = "m/d/yyyy h:mm AM/PM"
End With
On Error GoTo 0
If xitem Is Nothing Then
With Range("C" & Rows.Count).End(xlUp).Offset(1, 0)
.Value = Target.Value
.Offset(0, -1) = 1
End With
End If
Range("A4") = ""
Range("A4").Select
End If
Adds quantity
Case "$C$4"
If Target.Value <> "" Then
On Error Resume Next
Set xitem = Range("C8", Range("C" & Rows.Count).End(xlUp)) _
.Find(Range("C4").Value)
With xitem.Offset(0, -1)
.Value = .Value - 1
End With
If xitem Is Nothing Then MsgBox Target & " cannot be found " _
& "and cannot be removed."
Range("C4") = ""
Range("C4").Select
On Error GoTo 0
End If
Removes quantity (I am going to add an out time to this just trying to get the initial scan time in first)
Case "$E$4" 'find
If Target.Value <> "" Then
On Error Resume Next
Set xitem = Range("C8", Range("C" & Rows.Count).End(xlUp)) _
.Find(Range("E4").Value)
If xitem Is Nothing Then
MsgBox Target & " was not found."
Range("E4").Select
End If
Range("E4") = ""
xitem.Select
On Error GoTo 0
End If
End Select
End Sub
This is what I am using to take me directly to a barcode that has already been scanned.
Sorry if this post is badly formatted never posted before. Any and all help with this issue is appreciated. A photo of the spread sheet is also attached.
You are repeating some things within your code which you only need to do once, like the Find() for example.
Here's one alternative approach:
Private Sub Worksheet_Change(ByVal Target As Range)
Dim Adding As Boolean, Finding As Boolean, Subtracting As Boolean
Dim f As Range, v
Select Case Target.Address(True, True)
Case "$A$4": Adding = True
Case "$C$4": Subtracting = True
Case "$E$4": Finding = True
Case Else: Exit Sub
End Select
v = Trim(Target.Value)
If Len(v) = 0 Then Exit Sub
Set f = Me.Range("C8").Resize(1000, 1).Find(v, lookat:=xlWhole)
If Adding Then
If f Is Nothing Then
'not found: add as new row
Set f = Me.Cells(Rows.Count, 3).End(xlUp).Offset(1, 0)
f.Value = v
End If
f.Offset(0, 1).Value = f.Offset(0, 1).Value + 1
doDate f.Offset(0, -1)
Target.Value = ""
ElseIf Subtracting Then
If f Is Nothing Then
MsgBox v & " not found for subtraction!"
Else
f.Offset(0, 1).Value = f.Offset(0, 1).Value - 1
doDate f.Offset(0, -1)
Target.Value = ""
End If
Else 'finding
If Not f Is Nothing Then
f.EntireRow.Select
Target.Value = ""
Else
MsgBox v & " not found."
End If
End If
If Adding Or Subtracting Then Target.Select
End Sub
Sub doDate(c As Range)
With c
.NumberFormat = "m/d/yyyy h:mm AM/PM"
.Value = Now
End With
End Sub

VBA Trigger Worksheet Change with Copy/Paste

I am trying to use VBA to populate spreadsheet column G with an image file based on the value of column B on the same row of the sheet. If I manually enter the value into column B everything works great, however I have a long list and was hoping to copy/paste multiple values into column B. When I paste it seems like the worksheet change is not triggered and column H is not populated with images. The code I am using is below, any help would be greatly appreciated. Thanks!
Private Sub Worksheet_Change(ByVal Target As Range)
Dim shp As Shape
If Intersect(Target, [B:B]) Is Nothing Then Exit Sub
If Target.Row Mod 20 = 0 Then Exit Sub
On Error GoTo son
For Each shp In ActiveSheet.Shapes
If shp.Type = msoPicture And shp.TopLeftCell.Address = Target.Offset(0, 4).Address Then shp.Delete
Next
If Target.Value <> "" And Dir(ThisWorkbook.Path & "\" & Target.Value & ".jpg") = "" Then
'picture not there!
MsgBox Target.Value & " Doesn't exist!"
End If
ActiveSheet.Pictures.Insert(ThisWorkbook.Path & "\" & Target.Value & ".jpg").Select
Selection.Top = Target.Offset(0, 5).Top
Selection.Left = Target.Offset(0, 5).Left
With Selection.ShapeRange
.LockAspectRatio = msoFalse
.Height = Target.Offset(0, 5).Height
.Width = Target.Offset(0, 5).Width
End With
Target.Offset(1, 0).Select
son:
End Sub
When you paste multiple value the Target parameter becomes array of range you paste.
And it is also a array of 1 member if you paste only 1 row.
So, use For..Next loop to complete all row you were paste. And change all Target to Target(i) and change some code as below.
For i = 1 To Target.Rows.Count
If Target(i).Value <> "" And Dir(ThisWorkbook.Path & "\" & Target(i).Value & ".jpg") = "" Then
'picture not there!
MsgBox Target(i).Value & " Doesn't exist!"
Else
ActiveSheet.Pictures.Insert(ThisWorkbook.Path & "\" & Target(i).Value & ".jpg").Select
Selection.Top = Target(i).Offset(0, 5).Top
Selection.Left = Target(i).Offset(0, 5).Left
With Selection.ShapeRange
.LockAspectRatio = msoFalse
.Height = Target(i).Offset(0, 5).Height
.Width = Target(i).Offset(0, 5).Width
End With
End If
Next

excel "insert line" causing error with target.offset

I have this simple bit of code that automates some dates and stuff when adding line items to a sheet. It works well, but when I insert a line in to the spreadsheet [right-click the line name > insert] an error occurs.
Private Sub Worksheet_Change(ByVal Target As Range)
Dim cell As Range
Dim plusWeek
plusWeek = Now() + 7
For Each cell In Target
'========adds closed date, deleted date if status degenerates=========
If cell.Column = 13 And cell = "Closed" Then
Target.Offset(0, -2) = Format(Now(), "yyyy-mm-dd")
End If
If cell.Column = 13 And cell = "In-Progress" Then
Target.Offset(0, -2) = ""
End If
If cell.Column = 13 And cell = "Open" Then
Target.Offset(0, -2) = ""
End If
'========adds date added if date is embty and description is not empty========
If cell.Column = 8 And IsEmpty(Target.Offset(0, 1)) And Not IsEmpty(Target.Offset(0, 0)) Then
Target.Offset(0, 1) = Format(Now(), "yyyy-mm-dd")
Target.Offset(0, 2) = Format(plusWeek, "yyyy-mm-dd")
Target.Offset(0, 5) = "Open"
End If
'========deletes date added if description is empty========
'If cell.Column = 8 And IsEmpty(Target.Offset(0, 0)) Then
' Target.Offset(0, 1) = ""
'End If
Next cell
End Sub
if I paste a line, add a line or delete a line, error 1004 occurs. The debugger highlights this line, but I can't understand where the error comes from.
If cell.Column = 8 And IsEmpty(Target.Offset(0, 1)) And Not
IsEmpty(Target.Offset(0, 0)) Then
Something like this should work:
Private Sub Worksheet_Change(ByVal Target As Range)
Dim cell As Range, rng As Range
Dim plusWeek
plusWeek = Now() + 7
Set rng = Application.Intersect(Target, Me.Range("H:H,M:M"))
If rng Is Nothing Then Exit Sub
On Error GoTo haveError '<< make sure events don't get left turned off
Application.EnableEvents = False '<< turn events off
For Each cell In rng.Cells
'========adds closed date, deleted date if status degenerates=========
If cell.Column = 13 Then
Select Case cell.Value
Case "Closed": cell.Offset(0, -2) = Format(Now(), "yyyy-mm-dd")
Case "In-Progress", "Open": cell.Offset(0, -2) = ""
End Select
End If
'========adds date added if date is embty and description is not empty========
If cell.Column = 8 And IsEmpty(cell.Offset(0, 1)) And Not IsEmpty(cell) Then
cell.Offset(0, 1) = Format(Now(), "yyyy-mm-dd")
cell.Offset(0, 2) = Format(plusWeek, "yyyy-mm-dd")
cell.Offset(0, 5) = "Open"
End If
'========deletes date added if description is empty========
'If cell.Column = 8 And IsEmpty(Target.Offset(0, 0)) Then
' Target.Offset(0, 1) = ""
'End If
Next cell
haveError:
Application.EnableEvents = True
End Sub

How to change values of selected cells?

I need to know how to, after selecting an amount of cells, use a button to apply its lines of code only on those selected cells.
i've tried selecting and just clicking on the button but didn't work.
if there's another option to allow me to do the same it's also a welcome idea
This is the code that i want to apply, but only on cells selected with my mouse, and not really pre-selected cells like the ones shown in the code.
If Range("h3").Value >= 0 Then
Range("bk3").Value = True
Else
Range("bk3").Value = False
End If
If Range("h3").Value >= 0 Then
Range("j3").Value = Range("j3").Value & " | " & VarNUMCB
Else
End If
If Range("h3").Value >= 0 Then
Range("l3").Value = Now
Else
End If
This will loop selected cells and alter them:
Set selectedRange = Application.Selection
For Each cell In selectedRange.Cells
'do something with the cell, like:
cell.value = cell.value + 1
Next cell
With Selection
If Range("h3").Value >= 0 Then
Range("bk3").Value = True
Range("j3").Value = Range("j3").Value & " | " & VarNUMCB
Range("l3").Value = Now
Else
Range("bk3").Value = False
End If
End With
If you are selecting a cell in column h, then this code uses offset from the selected cell.
With Selection
If .Value >= 0 Then
.Offset(, 55).Value = True
.Offset(, 2).Value = Range("j3").Value & " | " & "Yes"
.Offset(, 3).Value = Now
Else
.Offset(, 55).Value = Falsee
End If
End With
If you are selecting a range of cells in column h then you would have to put the above code within a For Each Cell in Selection loop
For Each cel in Selection
If cel.Value >= 0 Then
cel.Offset(, 55).Value = True
cel.Offset(, 2).Value = Range("j3").Value & " | " & "Yes"
cel.Offset(, 3).Value = Now
Else
cel.Offset(, 55).Value = False
End If
Next cel

How to delete duplicate values?

I dynamically update the cells in columns A and B, and join both values on each row (using &) and place the values in column C.
My purpose is fulfilled by detecting duplicate names when firstName (Column A values) and LastName (column B values) are entered twice. An empty value (observed when the msgbox is displayed) pops up when I delete the duplicate name followed by the first occurrence.
This is an issue at times, especially because sometimes the msgbox does not go away. ie the code crashes.
How can I prevent the empty value, or msgBox from being displayed? I suspect something is wrong with my if statement.
VBA code I placed in the worksheet
Private Sub Worksheet_Change(ByVal Target As Range)
If WorksheetFunction.CountIf(Range("c1:c12"), Target.Offset(0, 1).Value) > 1 And _
Target.Offset(0, 1).Value <> " " Then
MsgBox Target.Offset(0, 1).Value & " is a Duplicate Entry" & vbNewLine & _
" ENTER A NEW NAME", vbInformation, "Duplicate Detected"
Target.Offset(0, 0).Value = " "
Target.Offset(0, 0).Select
ElseIf WorksheetFunction.CountIf(Range("c1:c12"), Target.Offset(0, 2).Value) > 1 And _
Target.Offset(0, 1).Value <> " " Then
MsgBox Target.Offset(0, 2).Value & " is a Duplicate Entry" & vbNewLine & _
" ENTER A NEW NAME", vbInformation, "Duplicate Detected"
Target.Offset(0, 0).Value = " "
Target.Offset(0, 0).Select
Else: Exit Sub
End If
End Sub
If i wanted to create a sheet with
-2 -1 0
ColA ColB ColC
First1 Last1 First1Last1
First2 Last2 First2Last2
First3 Last3 First3Last3
First4 Last4
I would personally start with conditional formatting for ColC to flag what is a duplicate, in case there is an issue, which circumvents a messagebox.
If i did need a messagebox, i would set up similar to what you have:
Private Sub Worksheet_Change(ByVal Target As Range)
If Intersect(Target, Columns(3)) Is Nothing Then Exit Sub
If Target.Count > 1 Then Exit Sub
If Application.CountIfs(Range("C1:C12"),Target.Value) > 1 Then 'checks for first/last name
MsgBox("The name " & Target.Offset(0,-2).Value & " " & Target.Offset(0,-1).Value & " already exists." & vbNewLine & "Please enter a new name.")
End If
End Sub
Edit1:
Given the data entry for colA and colB, would this be more appropriate? I utilized the row of the target, so the negative offset shouldn't be of concern, since you know that colA is first name and colB is last name.
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Count > 1 Then Exit Sub
Dim r as long
r = target.row
If isempty(cells(r,1)) or isempty(cells(r,2)) then exitsub
If Application.CountIfs(Range("B1:B12"),cells(r,2).Value,Range("A1:A12"),cells(r,1).Value) > 1 Then 'checks for first/last name
MsgBox("The name " & cells(r,1).Value & " " & cells(r,2).Value & " already exists." & vbNewLine & "Please enter a new name.")
End If
End Sub
Edit2:
In verifying the use of no values and some values, this macro has been working for my testing (i added the clear contents and .select so you are back on the line you should be adding data); i also added a range specification related to the intersect in case you are adding values like first/last to a random place outside of a1:b12:
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Count > 1 Then Exit Sub
If Intersect(Target, Range(Cells(1, 1), Cells(12, 2))) Is Nothing Then Exit Sub
Dim r As Long
r = Target.Row
If IsEmpty(Cells(r, 1)) Or IsEmpty(Cells(r, 2)) Then Exit Sub
If Application.CountIfs(Range("B1:B12"), Cells(r, 2).Value, Range("A1:A12"), Cells(r, 1).Value) > 1 Then 'checks for first/last name
MsgBox ("The name " & Cells(r, 1).Value & " " & Cells(r, 2).Value & " already exists." & vbNewLine & "Please enter a new name.")
Cells(r, 1).ClearContents
Cells(r, 2).ClearContents
Cells(r, 1).Select
End If
End Sub

Resources