I am new to coding and have got this far by googling. I am hoping it is a fairly simple change in the code. I have a form which shows what I want it to. My close button works however my 'add data' button doesn't work. As in it isn't populating the information I enter into the completed form to the worksheet in excel. I get the first column populating always with 0.1, no matter what I enter in. Here is my code if anyone would like to assist. I would be very grateful.
Private Sub cmdbutton_add_Click()
Dim iRow As Long
Dim ws As Worksheet
Set ws = Worksheets("Inputs")
'find first empty row in database
iRow = ws.Cells.Find(What:="*", SearchOrder:=xlRows, SearchDirection:=xlPrevious, LookIn:=xlValues).Row + 1
'Check for a Name number
If Trim(Me.textbox_lineno.Value) = " " Then
Me.textbox_lineno.SetFocus
MsgBox "Please Complete the form"
Exit Sub
End If
'copy the data to the database
ws.Cells(iRow, 1).Value = Me.textbox_lineno.Value
ws.Cells(iRow, 1).Value = Me.listbox_pipetype.Value
ws.Cells(iRow, 1).Value = Me.textbox_frompit.Value
ws.Cells(iRow, 1).Value = Me.textbox_topitormh.Value
ws.Cells(iRow, 1).Value = Me.textbox_linealm.Value
ws.Cells(iRow, 1).Value = Me.textbox_depthstart.Value
ws.Cells(iRow, 1).Value = Me.textbox_depthend.Value
ws.Cells(iRow, 1).Value = Me.textbox_pipedia.Value
ws.Cells(iRow, 1).Value = Me.textbox_beddingbelow.Value
ws.Cells(iRow, 1).Value = Me.textbox_beddingabove.Value
ws.Cells(iRow, 1).Value = Me.textbox_roadallowance.Value
MsgBox "Data Added", vbOKOnly + vbInformation, "Data Added"
'Clear the data
Me.textbox_lineno.Value = ""
Me.listbox_pipetype.Value = ""
Me.textbox_frompit.Value = ""
Me.textbox_topitormh.Value = ""
Me.textbox_linealm.Value = ""
Me.textbox_depthstart.Value = ""
Me.textbox_depthend.Value = ""
Me.textbox_pipedia.Value = ""
Me.textbox_beddingbelow.Value = ""
Me.textbox_beddingabove.Value = ""
Me.textbox_roadallowance.Value = ""
Me.textbox_lineno.SetFocus
End Sub
Private Sub cmdbutton_close_Click()
Unload Me
End Sub
This line should never validate:
If Trim(Me.textbox_lineno.Value) = " " Then
You never increment your column assignments. If I know that an Object exists then I will usually opt for a With Object statement over using another variable.
I extracted the code for clearing the textboxes into their own sub routine.
Because all the data is on one row and With .Range("A1", .Range("A" & .Rows.Count).End(xlUp)).Offset(1) refers the first cell of that row I use Columns(x) which is analogous to using .Cells(1,x). I fell like it looks cleaner.
I feel like these alterations to consolidate the code; make it easier to read. You don't have to scroll up and down the page to see just what the sub is doing.
Private Sub cmdbutton_add_Click()
'Check for a Name number
If Trim(Me.textbox_lineno.Value) = "" Then
Me.textbox_lineno.SetFocus
MsgBox "Please Complete the form", vbInformation, "Action Cancelled"
Exit Sub
End If
With Worksheets("Inputs")
With .Range("A1", .Range("A" & .Rows.Count).End(xlUp)).Offset(1)
'copy the data to the database
.Columns(1).Value = Me.textbox_lineno.Value
.Columns(2).Value = Me.listbox_pipetype.Value
.Columns(3).Value = Me.textbox_frompit.Value
.Columns(4).Value = Me.textbox_topitormh.Value
.Columns(5).Value = Me.textbox_linealm.Value
.Columns(6).Value = Me.textbox_depthstart.Value
.Columns(7).Value = Me.textbox_depthend.Value
.Columns(8).Value = Me.textbox_pipedia.Value
.Columns(9).Value = Me.textbox_beddingbelow.Value
.Columns(10).Value = Me.textbox_beddingabove.Value
.Columns(11).Value = Me.textbox_roadallowance.Value
End With
End With
MsgBox "Data Added", vbOKOnly + vbInformation, "Data Added"
ClearForm
Me.textbox_lineno.SetFocus
End Sub
Function ClearForm()
'Clear the data
Me.textbox_lineno.Value = ""
Me.listbox_pipetype.Value = ""
Me.textbox_frompit.Value = ""
Me.textbox_topitormh.Value = ""
Me.textbox_linealm.Value = ""
Me.textbox_depthstart.Value = ""
Me.textbox_depthend.Value = ""
Me.textbox_pipedia.Value = ""
Me.textbox_beddingbelow.Value = ""
Me.textbox_beddingabove.Value = ""
Me.textbox_roadallowance.Value = ""
End Function
Related
So I've got a userform for entering and looking up customer information, Everythign seems to currently work, except for the "Update" Button. When utilizing the update button, its changing my city and state values to my zipcode value, aswell as adjusting whatever else was changed. City and state should not be changing to my zipcode value. city and state values are populated utilizing a vlookup within a zipcodedata tab.
Below is the code for my update button:
Private Sub UpdateButton_Click()
If Me.CustID.Value = "" Then
MsgBox "Select customer record to update!"
Exit Sub
End If
Dim sh As Worksheet
Set sh = ThisWorkbook.Sheets("Customer Database")
Dim Selected_Row As Long
Selected_Row = Application.WorksheetFunction.Match(CLng(Me.CustID.Value), ThisWorkbook.Worksheets("Customer Database").Range("A:A"), 0)
'Validations-----------------------------------------------------
If Me.CustomerName.Value = "" Then
MsgBox "Plese enter the customers name!", vbCritical
Exit Sub
End If
'-------
If Me.CustomerBusiness.Value = "" Then
MsgBox "Plese enter the customers business!", vbCritical
Exit Sub
End If
'-------
If Me.CustomerAddress.Value = "" Then
MsgBox "Plese enter the customers address!", vbCritical
Exit Sub
End If
'-------
If Me.CustomerPhone.Value = "" Then
MsgBox "Plese enter the customers phone number!", vbCritical
Exit Sub
End If
'----------------------------------------------------------------
sh.Range("B" & Selected_Row).Value = Me.CustomerName.Value
sh.Range("C" & Selected_Row).Value = Me.CustomerBusiness.Value
sh.Range("D" & Selected_Row).Value = Me.CustomerAddress.Value
sh.Range("E" & Selected_Row).Value = Me.City.Value
sh.Range("F" & Selected_Row).Value = Me.State.Value
sh.Range("G" & Selected_Row).Value = Me.Zipcode.Value
sh.Range("H" & Selected_Row).Value = Me.CustomerPhone.Value
sh.Range("I" & Selected_Row).Value = Me.CustomerEmail.Value
sh.Range("J" & Selected_Row).Value = Me.MachineSerial1.Value
sh.Range("K" & Selected_Row).Value = Me.MachineSerial2.Value
sh.Range("L" & Selected_Row).Value = Me.MachineSerial3.Value
'----------------------------------------------------------------
Me.CustomerName.Value = ""
Me.LCaseName.Value = ""
Me.CustomerBusiness.Value = ""
Me.CustomerAddress.Value = ""
Me.Zipcode.Value = ""
Me.City.Value = ""
Me.State.Value = ""
Me.CustomerPhone.Value = ""
Me.CustomerEmail.Value = ""
Me.MachineSerial1.Value = ""
Me.MachineSerial2.Value = ""
Me.MachineSerial3.Value = ""
Me.CustID.Value = ""
'----------------------------------------------------------------
Call Refresh
End Sub
Here is the code for populating the City and State text boxes:
Private Sub Zipcode_Change()
Dim rng As Range
Dim a As Integer
On Error Resume Next
a = 0
Set rng = Worksheets("ZipCodeData").Range("ZipCodes")
Lastrow = Worksheets("ZipCodeData").Cells(Rows.Count, 1).End(xlUp).Row
For i = 2 To Lastrow
If Me.Zipcode = Worksheets("ZipCodeData").Cells(i, 1).Value Then
a = a + 1
End If
Next
If a >= 1 Then
Me.City.Value = Application.WorksheetFunction.VLookup(Zipcode.Value, rng, 2, 0)
Me.State.Value = Application.WorksheetFunction.VLookup(Zipcode.Value, rng, 3, 0)
End If
If a = 0 Then
Me.City.Value = ""
Me.State.Value = ""
End If
End Sub
I've tried commenting out my "Zipcode_Change" sub, as I thought perhaps it was having issues interpreting the vlookup values when utilizing the update feature. I have a "add" button (which is identical to the update button, except the Selected_Row is a Last_Row. The "Add" button functions and works as intended, so I recopied my "Add" button code and readjusted it for the update button, and the issue persists.
I am a beginner on vba, sarching and reading different things about vba I have created a piece of code but doesn't work how I want to. If I search for a specific value the code find it and show on specific textboxes a specific value, but if there are more than one same values (in searching column) I want to make the code go to next one until find every same value, what my actual code doesn't do. Any help on improving this code or any other code that does it I appreciate.
Here is my code,
Private Sub Search_Click()
Dim a As String
Dim b As Double
Dim k As Range
On Error GoTo dontexist:
If Me.TextBox20.Value = "" Or Me.TextBox20.Value = "Number of invoice" Then
Me.Label29.Caption = "Number of invoice"
b = Me.TextBox24.Value
Set k = Sheets("Sheet2").Range("E:E")
r = Application.WorksheetFunction.Match(b, k, 0)
Me.TextBox21.Value = Sheets("Sheet2").Cells(r, 2).Value
Me.TextBox22.Value = Sheets("Sheet2").Cells(r, 8).Value
Me.TextBox23.Value = Sheets("Sheet2").Cells(r, 4).Value
Exit Sub
Else
Me.Label29.Caption = "Sum of invoice"
a = Me.TextBox20.Value
Set k = Sheets("Sheet2").Range("H:H")
r = Application.WorksheetFunction.Match(a, k, 0)
Me.TextBox21.Value = Sheets("Sheet2").Cells(r, 2).Value
Me.TextBox22.Value = Sheets("Sheet2").Cells(r, 5).Value
Me.TextBox23.Value = Sheets("Sheet2").Cells(r, 4).Value
Exit Sub
End If
dontexist:
MsgBox "This record dosn't exist!", vbInformation, "Info!"
End Sub
Add a label to your form to hold the last found row and start the search from there. I have used label30.
Option Explicit
Private Sub Search_Click()
Dim rngSearch As Range, rngFound As Range, sColumn As String
Dim sValue As String, iCount As Long
Dim ws As Worksheet
Set ws = Sheets("Sheet2")
' label to hold row to start search at
If Label30 = "" Then Label30 = "1"
If Len(TextBox24) > 0 Then
' search on number
sValue = TextBox24
sColumn = "E"
Label29 = "Number of invoice"
ElseIf Len(TextBox20) > 0 Then
' search on total
sValue = TextBox20
sColumn = "H"
Label29 = "Sum of invoice"
Else
MsgBox "No search values entered", vbExclamation
Exit Sub
End If
' count number of matches
Set rngSearch = ws.Cells(1, sColumn).EntireColumn
iCount = Application.WorksheetFunction.CountIf(rngSearch, sValue)
If iCount > 0 Then
' continue search from last position
Set rngFound = rngSearch.Find(sValue, _
After:= ws.Range(sColumn & Label30), _
LookIn:=xlValues, _
LookAt:=xlWhole)
If rngFound Is Nothing Then
' not found
Label30 = ""
MsgBox "No more records found"
Else
' is row new
If rngFound.Row > Label30 Then
'MsgBox rngFound.Row
' copy into text boxes
With rngFound.EntireRow
If sColumn = "E" Then
TextBox21 = .Cells(1, 2)
TextBox22 = .Cells(1, 8)
TextBox23 = .Cells(1, 4)
Else
TextBox21 = .Cells(1, 2)
TextBox22 = .Cells(1, 5)
TextBox23 = .Cells(1, 4)
End If
End With
Label30 = rngFound.Row
Else
MsgBox "No more records found", vbExclamation
Label30 = ""
Exit Sub
End If
End If
Else
MsgBox "No records found", vbExclamation
Label30 = ""
End If
End Sub
As the title says, I have created a UserForm that adds data to a table but for some reason it does not add the data to the first empty row. In other words there will alway be an empty row at the top of my table and I can't for the life of me figure out what I'm doing wrong. I'm pretty new to this so there is obviously something I'm doing wrong, but what?
Would love some input on this!
Here is a link to the Excel file if you want to have a look (I made a separate tab in the file that explains the relationship between the Table and the different objects): https://files.fm/u/jguvasvq
If not, here's the code:
Private Sub button_leggtil_Click()
'Validation
If Me.data_foretak.Value = "" Then
MsgBox "Mangler Foretaksnavn."
End If
If Me.data_kontaktperson.Value = "" Then
MsgBox "Mangler Kontaktperson."
End If
If Me.data_telefonnummer.Value = "" Then
MsgBox "Mangler Telefonnummer."
End If
If VBA.IsNumeric(Me.data_telefonnummer.Value) = False Then
MsgBox "Ikke et gyldig telefonnummer."
Exit Sub
End If
If Me.data_epost.Value = "" Then
MsgBox "Mangler Epost."
End If
If Me.data_pris.Value = "" Then
MsgBox "Mangler Pris."
End If
If VBA.IsNumeric(Me.data_pris.Value) = False Then
MsgBox "Ikke gyldig pris format."
Exit Sub
End If
If Me.data_datotilb.Value = "" Then
MsgBox "Mangler dato - Tilbud."
End If
If VBA.IsDate(Me.data_datotilb.Value) = False Then
MsgBox "Feil dato format - Tilbud (Format: dd/mm/aa)."
Exit Sub
End If
If Me.data_datooppf.Value = "" Then
MsgBox "Mangler dato - Oppfølging."
End If
If VBA.IsDate(Me.data_datooppf.Value) = False Then
MsgBox "Feil dato format - Oppfølging (Format: dd/mm/aa)."
Exit Sub
End If
If Me.combo_sannsynlighet.Value = "" Then
MsgBox "Mangler Sannsynlighet."
End If
'Check for duplicate and insert data to table
Dim oNewRow As ListRow
Dim rng As Range
Set rng = ThisWorkbook.Worksheets("Tilbud").Range("TilbudTable")
rng.Select
Set oNewRow = Selection.ListObject.ListRows.Add(AlwaysInsert:=True)
If Application.WorksheetFunction.CountIf(rng, Me.data_foretak) > 0 Then
MsgBox "Denne bedriften finnes alerede i listen."
Exit Sub
End If
With ws
oNewRow.Range.Cells(1, 1).Value = Me.data_foretak
oNewRow.Range.Cells(1, 2).Value = Me.data_kontaktperson
oNewRow.Range.Cells(1, 3).Value = Me.data_telefonnummer
oNewRow.Range.Cells(1, 4).Value = Me.data_epost
oNewRow.Range.Cells(1, 5).Value = Me.data_pris
oNewRow.Range.Cells(1, 6).Value = Me.data_datotilb
oNewRow.Range.Cells(1, 7).Value = Me.data_datooppf
oNewRow.Range.Cells(1, 8).Value = Me.combo_sannsynlighet
End With
' Clear Input
Me.data_foretak.Value = ""
Me.data_kontaktperson.Value = ""
Me.data_telefonnummer.Value = ""
Me.data_epost.Value = ""
Me.data_pris.Value = ""
Me.data_datotilb.Value = ""
Me.data_datooppf.Value = ""
Me.combo_sannsynlighet.Value = ""
End Sub
-------------------------------------------------------------------------------------
Private Sub button_lukk_Click()
'Close form
Unload Me
End Sub
-------------------------------------------------------------------------------------
Private Sub button_tomskjema_Click()
'Clear Form
Me.data_foretak.Value = ""
Me.data_kontaktperson.Value = ""
Me.data_telefonnummer.Value = ""
Me.data_epost.Value = ""
Me.data_pris.Value = ""
Me.data_datotilb.Value = ""
Me.data_datooppf.Value = ""
Me.combo_sannsynlighet.Value = ""
End Sub
-------------------------------------------------------------------------------------
Private Sub UserForm_Activate()
With Me.combo_sannsynlighet
.Clear
.AddItem ""
.AddItem "10%"
.AddItem "20%"
.AddItem "30%"
.AddItem "40%"
.AddItem "50%"
.AddItem "60%"
.AddItem "70%"
.AddItem "80%"
.AddItem "90%"
.AddItem "100%"
End With
End Sub
I appreciate any input!
I find this code adds to a table called MyTable on Sheet1. If the table is empty, it adds as a first row.
Sub Test()
Dim tbl As ListObject
Set tbl = ThisWorkbook.Worksheets("Sheet1").ListObjects("MyTable")
With tbl.ListRows.Add
.Range(tbl.ListColumns("Heading 1").Index) = "Add data in column headed 'Heading 1'"
.Range(tbl.ListColumns("Heading 2").Index) = "Another named column."
.Range(3) = "Third column"
End With
End Sub
Edit - sorry, couldn't test on your code as it's not a Minimal, Reproducible Example - i.e. I couldn't easily copy it straight into my VBE to test.
I recently started learning how to use VBA since I suddenly got put into a position where I need to know it. I've been doing research on coding and such but I feel like I'm messing up every step of the way. I was asked to create a userform where people could enter their time, date, production, task, and a comment box. I was also asked to have both the input sheet and the data sheet locked, on top of that my boss wanted the sheet itself to save when closed so when workers entered their information they wouldn't save.
Private Sub cmdAdd_Click()
Dim lRow As Long
Dim lPart As Long
Dim ws As Worksheet
Set ws = Worksheets("Data")
'find first empty row in database
lRow = ws.Cells.Find(What:="*", SearchOrder:=xlRows, _
SearchDirection:=xlPrevious, LookIn:=xlValues).Row + 1
'check for a part number
If Trim(Me.txtComment.Value) = "" Then
Me.txtComment.SetFocus
MsgBox "Comment is required"
End If
'check for a part number
If Trim(Me.ComboBox1.Value) = "" Then
Me.ComboBox1.SetFocus
MsgBox "Date is required!"
End If
'check for a part number
If Trim(Me.txtTime.Value) = "" Then
Me.txtTime.SetFocus
MsgBox "Time is required"
End If
'check for a part number
If Trim(Me.cboProject.Value) = "" Then
Me.cboProject.SetFocus
MsgBox "Project is required"
End If
'check for a part number
If Trim(Me.cboTask.Value) = "" Then
Me.cboTask.SetFocus
MsgBox "Task is required"
Exit Sub
End If
'copy the data to the database
'use protect and unprotect lines,
' with your password
' if worksheet is protected
With ws
' .Unprotect Password:="password"
.Cells(lRow, 1).Value = Me.ComboBox1.Value
.Cells(lRow, 2).Value = Me.txtTime.Value
.Cells(lRow, 3).Value = Me.txtCount.Value
.Cells(lRow, 4).Value = Me.cboUser.Value
.Cells(lRow, 5).Value = Me.cboProject.Value
.Cells(lRow, 6).Value = Me.cboTask.Value
.Cells(lRow, 7).Value = Me.txtComment.Value
' .Protect Password:="password"
'clear the data
Me.cboUser.Value = ""
Me.ComboBox1.Value = ""
Me.txtTime.Value = ""
Me.txtCount.Value = ""
Me.cboProject.Value = ""
Me.cboTask.Value = ""
Me.txtComment.Value = ""
Me.ComboBox1.Value = Format(Date, "Short Date")
MsgBox ("Work Submitted, proceed to close the form and save the workbook.")
End With
End Sub
Apologies in advance for how awful the code probably is, but it seemed to work just enough for what I was going, the only problem was that when I was recently testing it even if I had a message saying comment required or task required it would still paste information into the datasheet which I don't want to happen.
im using vbs in excel 2010 and i have a form that adds data to this spreadsheet...that's all fine but i need to be able to check if im not duplicating data.
there is one column in spreadsheet where all numbers should be unique.
I'd like to check the text box value in the form against the column entries before i add the value .
this is all i need and this mini project of mine is done
this is the current coding i have that adds the data to sheet
Private Sub cmdbtnSave_Click()
Dim vNewRow As Long
Dim ws As Worksheet
Set ws = DataTable
' Find the next empty row
vNewRow = ws.Cells(Rows.Count, 1).End(xlUp).Offset(1, 0).Row
' Check for data in Field 1
If Trim(Me.invoicemonth.Value) = "" Then
Me.invoicemonth.SetFocus
MsgBox "Please enter invoice month!"
Exit Sub
End If
' Check for data in Field 2
If Trim(Me.dfrdate.Value) = "" Then
Me.dfrdate.SetFocus
MsgBox "Please enter DFR date!"
Exit Sub
End If
' Check for data in Field 3
If Trim(Me.actype.Value) = "" Then
Me.actype.SetFocus
MsgBox "Please enter Airfraft Type!"
Exit Sub
End If
' check a/c rego
If Trim(Me.acrego.Value) = "" Then
Me.acrego.SetFocus
MsgBox "Please enter Aircraft Rego!"
Exit Sub
End If
' check client
If Trim(Me.client.Value) = "" Then
Me.client.SetFocus
MsgBox "Please enter Client"
Exit Sub
End If
' check destination
If Trim(Me.dest.Value) = "" Then
Me.dest.SetFocus
MsgBox "Please enter in destination"
Exit Sub
End If
' check dfr hours
If Trim(Me.dfrhrs.Value) = "" Then
Me.dfrhrs.SetFocus
MsgBox "Please enter DFR Hours"
Exit Sub
End If
' check if pilots name is entered
If Trim(Me.Pilots.Value) = "" Then
Me.Pilots.SetFocus
MsgBox "Please input pilot name ya! wwsshhh!"
Exit Sub
End If
'check if tech log hrs is entered
If Trim(Me.txt_tloghrs.Value) = "" Then
Me.txt_tloghrs.SetFocus
MsgBox "wwsshh!! putim tech log hrs ya!"
Exit Sub
End If
'check if tech log number is in
If Trim(Me.txt_tlogno.Value) = "" Then
Me.txt_tlogno.SetFocus
MsgBox "wwsshh!! mi needim numbba blo displa tech log ya!"
Exit Sub
End If
'check if engineer's name is entered
If Trim(Me.cmb_eng.Value) = "" Then
Me.cmb_eng.SetFocus
MsgBox "WWSSHH! NA NEM BLO ENGINEER EM HUSAIT?"
Exit Sub
End If
'check if fuel supplier is put in
If Trim(Me.cmb_fsupply.Value) = "" Then
Me.cmb_fsupply.SetFocus
MsgBox "if no input select/type NULL"
Exit Sub
End If
'check if branch
If Trim(Me.cmb_branch.Value) = "" Then
Me.cmb_branch.SetFocus
MsgBox "if no input select/type NULL"
Exit Sub
End If
'check if tech log number is in
If Trim(Me.txt_finvoice.Value) = "" Then
Me.txt_finvoice.SetFocus
MsgBox "if no input select/type NULL"
Exit Sub
End If
'check fuel liters
If Trim(Me.txt_ltrs.Value) = "" Then
Me.txt_ltrs.SetFocus
MsgBox "if no input select/type NULL"
Exit Sub
End If
' Input the data in the Data Table
ws.Cells(vNewRow, 1).Value = Me.invoicemonth.Value
ws.Cells(vNewRow, 2).Value = Me.dfrdate.Value
ws.Cells(vNewRow, 3).Value = Me.dfrnumber.Value
ws.Cells(vNewRow, 4).Value = Me.actype.Value
ws.Cells(vNewRow, 5).Value = Me.acrego.Value
ws.Cells(vNewRow, 6).Value = Me.client.Value
ws.Cells(vNewRow, 7).Value = Me.dest.Value
ws.Cells(vNewRow, 8).Value = Me.dfrhrs.Value
ws.Cells(vNewRow, 9).Value = Me.Pilots.Value
ws.Cells(vNewRow, 10).Value = Me.txt_tloghrs.Value
ws.Cells(vNewRow, 11).Value = Me.txt_tlogno.Value
ws.Cells(vNewRow, 12).Value = Me.cmb_eng.Value
ws.Cells(vNewRow, 13).Value = Me.cmb_fsupply.Value
ws.Cells(vNewRow, 14).Value = Me.cmb_branch.Value
ws.Cells(vNewRow, 15).Value = Me.txt_finvoice.Value
ws.Cells(vNewRow, 16).Value = Me.cmb_whosupply.Value
ws.Cells(vNewRow, 17).Value = Me.txt_ltrs.Value
ws.Cells(vNewRow, 1).Activate
' Clear all fields and reset the form
Me.invoicemonth.Value = ""
Me.dfrdate.Value = ""
Me.dfrnumber.Value = ""
Me.actype.Value = ""
Me.acrego.Value = ""
Me.client.Value = ""
Me.dest.Value = ""
Me.dfrhrs.Value = ""
Me.Pilots.Value = ""
Me.txt_tloghrs.Value = ""
Me.txt_tlogno.Value = ""
Me.cmb_eng.Value = ""
Me.cmb_fsupply.Value = ""
Me.cmb_branch.Value = ""
Me.txt_finvoice.Value = ""
Me.cmb_whosupply.Value = ""
Me.txt_ltrs.Value = ""
Me.invoicemonth.SetFocus`
Using subroutines, you can perform this more easily than in one big chunk. You would need to set your values for certain variables like "ws" upon UserForm activation.
Your Save Button click event would be just a few lines then, executing each subroutine. First checking for Duplicates, then Checking for Empties, then Copying the Data, Saving the Workbook, and Clearing the Form for another entry. You will still have to use whatever you are doing to navigate the records or take into account which row on which to put the data. I believe in the example you used "VNewRow".
Private Sub cmdbtnSave_Click()
If IsDuplicate() = False Then
Call CheckEmpty
Call SaveData
ActiveWorkbook.Save
Call ClearData
Else
MsgBox("Duplicate records exist for " & txtBoxToCheck.Value & "!")
'Anything else you want to accomplish, such as reset the form
'You can Call ClearData here.
End If
End Sub
Then you would need a subroutine to check for Duplicates on the column that needs to be all unique. In this example, "txtBoxToCheck" is the name of the textbox and it is located on Sheet1 Column "A". When this runs it will return False if there are no duplicates, and True if there are. Then the save event will either save or not based on that.
Function IsDuplicate() As Boolean
Dim lastRow As Long
Dim resultCheck As Boolean
lastRow = Sheets("Sheet1").Range("A" & Rows.Count).End(xlUp).Row 'gets last row of Sheet1
For row = 2 to lastRow 'Assuming you have a Header Row and Data begins on row 2.
If txtBoxToCheck.Value = Sheets("Sheet1").Cells(row , 1).Value Then
resultCheck = True
End For
Else
resultCheck = False
End If
Next row 'loop until last row of sheet1
IsDuplicate = resultCheck
End Sub
This would lose your custom message boxes but would save you time. In this example, if you set the Tag property on each control that can't be empty. In the example, they are tagged with "NoEmpty". You could remove your list of If/Then Statements with each having the same code and only one value changes and call this instead.
Private Sub CheckEmpty()
Dim ctl As MSForms.Control
For Each ctl In YourForm.Controls 'Set to your form name
If ctl.Tag = "NoEmpty" Then
If (ctl.Value = "")) Then
MsgBox ("Set value for " & ctl.Name)
ctl.SetFocus
End If
End If
Next ctl
End Sub
That would relieve you of an if statement for each cell checking for blank.
You would have a separate subroutine for SaveData. Taking from your original code, without the "Me."
Private Sub SaveData()
'Input the data in the Data Table
ws.Cells(vNewRow, 1).Value = invoicemonth.Value
ws.Cells(vNewRow, 2).Value = dfrdate.Value
ws.Cells(vNewRow, 3).Value = dfrnumber.Value
ws.Cells(vNewRow, 4).Value = actype.Value
ws.Cells(vNewRow, 5).Value = acrego.Value
ws.Cells(vNewRow, 6).Value = client.Value
ws.Cells(vNewRow, 7).Value = dest.Value
ws.Cells(vNewRow, 8).Value = dfrhrs.Value
ws.Cells(vNewRow, 9).Value = Pilots.Value
ws.Cells(vNewRow, 10).Value = txt_tloghrs.Value
ws.Cells(vNewRow, 11).Value = txt_tlogno.Value
ws.Cells(vNewRow, 12).Value = cmb_eng.Value
ws.Cells(vNewRow, 13).Value = cmb_fsupply.Value
ws.Cells(vNewRow, 14).Value = cmb_branch.Value
ws.Cells(vNewRow, 15).Value = txt_finvoice.Value
ws.Cells(vNewRow, 16).Value = cmb_whosupply.Value
ws.Cells(vNewRow, 17).Value = txt_ltrs.Value
End Sub
And another for ClearData, again using your code from above without the "Me."
Private Sub ClearData()
'Clear all fields and reset the form
invoicemonth.Value = ""
dfrdate.Value = ""
dfrnumber.Value = ""
actype.Value = ""
acrego.Value = ""
client.Value = ""
dest.Value = ""
dfrhrs.Value = ""
Pilots.Value = ""
txt_tloghrs.Value = ""
txt_tlogno.Value = ""
cmb_eng.Value = ""
cmb_fsupply.Value = ""
cmb_branch.Value = ""
txt_finvoice.Value = ""
cmb_whosupply.Value = ""
txt_ltrs.Value = ""
invoicemonth.SetFocus
End Sub
In Summary, by doing it this way, you can more easily adapt your code for future projects that are similar, while making it easier for debugging later by you or other people who might have to work on your code. Keep the navigation and other validation methods in place and just modify where the data comes from and goes, and the specific names of the UserForm Controls, worksheets, etc.
edit: added clarification and more comments to code.