Make cell mandatory in excel using vba - excel

I have tried this code for creating mandatory fields but the problem is it is showing the error message before going to the cell.
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Dim lastRow As Long
With ActiveSheet
lastRow = .Cells(.Rows.count, "A").End(xlUp).Row
Dim I, J As Integer
For I = 1 To lastRow
If Cells(I, "C").Value = "" Then
MsgBox "Please Enter Business Type Value", vbOKOnly
Exit Sub
End If
'If Cells(I, "D").Value = "" Then
'MsgBox "Please Enter Customer Account Code", vbOKOnly
'Exit Sub
'End If
'If Cells(I, "E").Value = "" Then
'MsgBox "Please Enter Transport Mode Value", vbOKOnly
'Exit Sub
'End If
'If Cells(I, "F").Value = "" Then
'MsgBox "Please Enter Incoterm Value", vbOKOnly
'Exit Sub
'End If
'If Cells(I, "K").Value = "" Then
'MsgBox "Please Enter From date Value", vbOKOnly
'Exit Sub
'End If
'If Cells(I, "L").Value = "" Then
'MsgBox "Please Enter To date Value", vbOKOnly
'Exit Sub
'End If
'If Cells(I, "K").Value > Cells(I, "L").Value Then
'MsgBox "To date value should greater than From value", vbOKOnly
'Exit Sub
'End If
'If Cells(I, "N").Value = "" Then
'MsgBox "Please Enter Origin Country Code Value", vbOKOnly
'Exit Sub
'End If
'If Cells(I, "O").Value = "" Then
'MsgBox "Please Enter Point of Origin Location Code Value", vbOKOnly
'Exit Sub
'End If
'If Cells(I, "R").Value = "" Then
'MsgBox "Please Enter Port of Loading Code Value", vbOKOnly
'Exit Sub
'End If
'If Cells(I, "S").Value = "" Then
'MsgBox "Please Enter Origin Clearance Location Value", vbOKOnly
'Exit Sub
'End If
'If Cells(I, "T").Value = "" Then
'MsgBox "Please Enter Destination Clearance Location Value", vbOKOnly
'Exit Sub
'End If
'If Cells(I, "U").Value = "" Then
'MsgBox "Please Enter Port of Discharge Code Value", vbOKOnly
'Exit Sub
'End If
If Cells(I, "Y").Value = "" Then
MsgBox "Please Enter Consignee Final Destination Location Code Value", vbOKOnly
Exit Sub
End If
If Cells(I, "Z").Value = "" Then
MsgBox "Please Enter Destination Country Code Value", vbOKOnly
Exit Sub
End If
If Cells(I, "AF").Value = "" Then
MsgBox "Please Enter Active status Value", vbOKOnly
Exit Sub
End If
If Cells(I, "AH").Value = "" Then
MsgBox "Please Enter Carrier Allocation Number Value", vbOKOnly
Exit Sub
End If
If Cells(I, "AI").Value = "" Then
MsgBox "Please Enter Carrier Allocation Valid From Date Value", vbOKOnly
Exit Sub
End If
If Cells(I, "AJ").Value = "" Then
MsgBox "Please Enter Carrier Nomination Sequence Number Value", vbOKOnly
Exit Sub
End If
Next I
End With
End Sub

This code
tracks A1:A10 to see if any cells are changed
then looks to see if the corresponding cell in row Y is empty
if empty a message is returned and the cell in A1:A10 that was changed is then blanked out
code
Private Sub Worksheet_Change(ByVal Target As Range)
Dim rng1 As Range
Dim rng2 As Range
Set rng1 = Intersect(Target, [a1:a10])
'exit if no cells in A1:A10 are changed
If rng1 Is Nothing Then Exit Sub
'turn off events to avoid code retriggering itself
Application.EnableEvents = False
For Each rng2 In rng1
If Cells(rng2.Row, "Y") = vbNullString Then
MsgBox "Please Enter Consignee Final Destination Location Code Value, your entry will be deleted", vbOKOnly
rng2.Value = vbNullString
End If
Next
Application.EnableEvents = True
End Sub

Another approach would be:
In your Worksheet_SelectionChange make all cells which do not pass your checks red. All who pass your checks green. You can do this with the following code. Do not produce any error messages in this procedure.
Range("A1").Interior.Color = RGB(255, 0, 0) 'red
Range("A1").Interior.Color = RGB(0, 255, 0) 'green
Do only allow saving the workbook if all your checks are passed. Therefore you can use the proceudre I have provided you in the other answer.

I think the event you are using may cause your problem.
You could implement mandatory fields with the Workbook_BeforeSave event. This will get fired, as soon as the user tries to save the excel file. Now you check all your fields which you define as mandatory and display the respective "error message".
When you set Cancel = True you can abort the saving process wich then really forces the user to add something in the required fields.
In the Workbook_BeforeSave event you can paste in all your checks you have already implemented.
More details on the Workbook_BeforeSave can be found here: https://msdn.microsoft.com/de-de/library/office/ff840057.aspx
Here you can find more info on how to implement the Workbook_BeforeSave event:http://www.positivevision.biz/blog/bid/153139/Excel-Tips-and-Tricks-Mandatory-Cell-Input

Related

Is there a way to sort rows by date with a vba command button

I have a data entry form for inputting lost and found items into a worksheet, I'm able to search the items but I have a list box for recent entries but obviously the first row is the first item on the list box, is there someway that I can sort rows from the page to the most recent entry by clicking the submit button?
Private Sub Submit_Button_Click()
Dim sh As Worksheet
Set sh = ThisWorkbook.Sheets("Found_Property")
Dim last_row As Long
last_row = Application.WorksheetFunction.CountA(sh.Range("A:A"))
'validation-----------------------------------------------------
If Me.Date_Item_Found_Textbox.Value = "" Then
MsgBox "Please enter the date the item was found.", vbCritical
Exit Sub
End If
If Me.Property_Owner_Textbox.Value = "" Then
MsgBox "Please enter the name of the owner of the property, if not available
enter N/A.", vbCritical
Exit Sub
End If
If Me.Location_Found_Combobox.Value = "" Then
MsgBox "Please select a location the item was found.", vbCritical
Exit Sub
End If
If Me.Property_Description_Textbox.Value = "" Then
MsgBox "Please enter a breif description of the item.", vbCritical
Exit Sub
End If
If Me.Reporting_Officer_Combobox.Value = "" Then
MsgBox "Please select your name or the reporting officer's name.", vbCritical
Exit Sub
End If
If Me.Contact_Number_Textbox.Value = "" Then
MsgBox "Please enter a valid contact number for the reporting party.",
vbCritical
Exit Sub
End If
If Me.Location_Stored_Combobox.Value = "" Then
MsgBox "Please select the location of which the item is stored.", vbCritical
Exit Sub
End If
'---------------------------------------------------------------
sh.Range("A" & last_row + 1).Value = "=Row()-2"
sh.Range("B" & last_row + 1).Value = Me.Date_Item_Found_Textbox.Value
sh.Range("D" & last_row + 1).Value = Me.Property_Owner_Textbox.Value
sh.Range("E" & last_row + 1).Value = Me.Contact_Number_Textbox.Value
sh.Range("F" & last_row + 1).Value = Me.Location_Found_Combobox.Value
sh.Range("G" & last_row + 1).Value = Me.Property_Description_Textbox.Value
sh.Range("H" & last_row + 1).Value = Me.Reporting_Officer_Combobox.Value
sh.Range("I" & last_row + 1).Value = Me.Location_Stored_Combobox.Value
sh.Range("J" & last_row + 1).Value = Now
'---------------------------------------------------------------
Me.ID_Textbox = ""
Me.Date_Item_Found_Textbox = ""
Me.Property_Owner_Textbox = ""
Me.Contact_Number_Textbox = ""
Me.Location_Found_Combobox = ""
Me.Property_Description_Textbox = ""
Me.Reporting_Officer_Combobox = ""
Me.Location_Stored_Combobox = ""
'-----
MsgBox "The item has been successfully entered as FOUND PROPERTY"
Call refresh_data
Me.Date_Item_Found_Textbox.SetFocus
Dim mycell As Range
Dim myrange As Range
Set myrange = Worksheets("Found_Property").Range("A3:J100")
For Each mycell In myrange
mycell.Value = UCase(mycell.Value)
Next mycell
End Sub

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

How to make a multi-select listbox selection required in a userform?

I have a userform with a multi-select list box.
The code I wrote expects the user to select two options.
I need that the user gets an error message only if they don't select at least one option.
I started with the code for a single-select list box error message. I tried making it >= -1 <0 <>-1 and none of them allow the user to select just one option.
The line in question is:
If ListBoxNextSteps.ListIndex <> 1 Then
MsgBox "Please select next steps"
Exit Sub
End If
Private Sub CommandButtonSubmit_Click()
'Requires specific fields to be complete before user can submit
If ComboBoxDBN = "" Then
MsgBox "Please select a DBN"
Exit Sub
End If
If TextBoxDate = "" Then
MsgBox "Plese enter a date"
Exit Sub
End If
If CheckBoxCohort = False Then
If TextBoxContactName = "" Then
MsgBox "Please list school officials that you contacted"
Exit Sub
End If
If ListBoxSupportType.ListIndex = -1 Then
MsgBox "Please select a support type"
Exit Sub
End If
If TextBoxDiscussion = "" Then
MsgBox "Please describe your discussion points"
Exit Sub
End If
If TextBoxLearn = "" Then
MsgBox "Please describe what you learned about the school's challenges"
Exit Sub
End If
If (CheckBoxAdminDiff + CheckBoxConflict + CheckBoxShortage + CheckBoxDataSystems + CheckBoxOther) = 0 Then
MsgBox "Please select at least one bucket"
Exit Sub
End If
If (CheckBoxOther = True And TextBoxIfOther = "") Then
MsgBox "Please describe other bucket"
Exit Sub
End If
If ListBoxNextSteps.ListIndex <> 1 Then
MsgBox "Please select next steps"
Exit Sub
End If
If ListBoxResolution.ListIndex = -1 Then
MsgBox "Please select a resolution status"
Exit Sub
End If
End If
'tells form to put responses in a long table
Dim emptyRow As Long
'Make Sheet1 (SchoolSupport) active so it knows where to put the responses
Sheet1.Activate
ActiveSheet.Protect UserInterfaceOnly:=True, AllowFiltering:=True
'Determine emptyRow so it knows where the next entry goes
emptyRow = WorksheetFunction.CountA(Range("A:A")) + 1
'Transfer information from form fields to table cells
Cells(emptyRow, 1).Value = ComboBoxDBN.Value
Cells(emptyRow, 2).Value = TextBoxDate.Value
Cells(emptyRow, 3).Value = TextBoxContactName.Value
Cells(emptyRow, 6).Value = ListBoxSupportType.Value
Cells(emptyRow, 7).Value = TextBoxDiscussion.Value
Cells(emptyRow, 8).Value = TextBoxBestPractice.Value
Cells(emptyRow, 9).Value = TextBoxLearn.Value
Cells(emptyRow, 15).Value = TextBoxIfOther.Value
'Makes sure multiple selections appear in same cell
If CheckBoxCohort = False Then
Dim s As String, i As Integer
With ListBoxNextSteps
For i = 0 To .ListCount - 1
If .Selected(i) = True Then s = s & .List(i) & ", "
Next i
End With
With Cells(emptyRow, 16)
.Value = Left(s, Len(s) - 1)
End With
End If
Cells(emptyRow, 17).Value = ListBoxResolution.Value
Cells(emptyRow, 18).Value = TextBoxEscalateTo.Value
Cells(emptyRow, 19).Value = ListBoxEscalateLocation.Value
Cells(emptyRow, 20).Value = ListBoxEscalateStatus.Value
Cells(emptyRow, 21).Value = TextBoxPertinentNotes.Value
If CheckBoxUnresponsive.Value = True Then Cells(emptyRow, 4).Value = "Y"
If CheckBoxCohort.Value = True Then Cells(emptyRow, 5).Value = "Y"
If CheckBoxAdminDiff.Value = True Then Cells(emptyRow, 10).Value = "Y"
If CheckBoxConflict.Value = True Then Cells(emptyRow, 11).Value = "Y"
If CheckBoxShortage.Value = True Then Cells(emptyRow, 12).Value = "Y"
If CheckBoxDataSystems.Value = True Then Cells(emptyRow, 13).Value = "Y"
If CheckBoxOther.Value = True Then Cells(emptyRow, 14).Value = "Y"
'Saves workbook
Application.ActiveWorkbook.Save
Unload SchoolSupportForm
End Sub
I expect the ListBoxNextSteps error message to appear only if the user hasn't made any selection, but instead, it appears if the user hasn't made at least 2 selections.
You can use the Selected method of the ListBox object to check whether an item is selected. The following code loops through each item in the listbox. If an item is selected, the boolean variable itemSelected is set to True and the For/Next loop is exited. After exiting the loop, if itemSelected is set to False, the message is displayed and then it exits the sub.
Dim itemSelected As Boolean
Dim i As Long
itemSelected = False
With Me.ListBoxNextSteps
For i = 0 To .ListCount - 1
If .Selected(i) Then
itemSelected = True
Exit For
End If
Next i
End With
If Not itemSelected Then
MsgBox "Please select next steps"
Exit Sub
End If

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

Calling a macro from another

I running a macro that pops up a message if the user inputs a value in column E having column D empty. therefore the user has to input value in D and then in E. once the user inputs a value in D, by Vlookup formula the sheet will display a number in column F.
The second macro should then check if value of column F is not equal to value input in column E, if not equal popup a message.
First part is working but not the second. any idea please. thanks
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Address = Cells(Target.Row, 5).Address And Target.Value <> "" And Cells(Target.Row, 4).Value = "" Then
MsgBox "Input value in column D"
Cells(Target.Row, 4).Select
Target.Clear
End If
Call Macro2
End Sub
Sub Macro2()
If Target.Address = Sheets(1).Cells(Target.Row, 5).Address And Target.Value <> "" And Target.Value <> Sheets(1).Cells(Target.Row, 6).Value Then
MsgBox "E and F don't match"
End If
End Sub
If the second one is the problem, then pass the Target to it:
Private Sub Worksheet_Change(ByVal Target As Range)
Application.EnableEvents = False '<--- Consider removing this line
If Target.Address = Cells(Target.Row, 5).Address _
And Target.Value <> "" _
And Cells(Target.Row, 4).Value = "" Then
MsgBox "Input value in column D"
Cells(Target.Row, 4).Select
Target.Clear
End If
Macro2 Target
Application.EnableEvents = True '<--- Consider removing this line
End Sub
Sub Macro2(Target As Range)
If IsError(Target) Then
MsgBox Target.Address & "is an error!"
ElseIf IsError(Sheets(1).Cells(Target.Row, 6)) Then
MsgBox Sheets(1).Cells(Target.Row, 6).Address & " is an error!"
ElseIf Target.Address = Sheets(1).Cells(Target.Row, 5).Address _
And Target.Value <> "" _
And Target.Value <> Sheets(1).Cells(Target.Row, 6).Value Then
MsgBox "E and F don't match"
End If
End Sub
However, it could be that Target.Clear is making a loop within the Worksheet_Change, because it changes the worksheet once again. Depending on whether this is ok or not ok, you may consider writing Application.EnableEvents = False and Application.EnableEvents = True at the start or at the end of the Sub.

Resources