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.
Related
I am completely new in this and got stuck on something that sounds like a simple thing.
I created simple user form, where assemblers will enter one of the items as a search criteria. The listbox is then populated with all results from original spreadsheet showing the location of that part. Assembler will then select one item that they need to pick and click the button "pick".
What that will do is enter the date in "PickDate" in spreadsheet. And that is where I am stuck.
My thinking was to select the row in the spreadsheet identical to the selected row in listbox, and then create address of the cell using that row and column. But it doesn't work. Tried several things that I could find on internet and nothing works. At one point I had date being entered in correct column, but not correct row. Unfortunately, cannot remember what that code was.
Any help would be appreciated.
Thanks a lot. userform spreadsheet
Private Sub PickBtn_Click()
Dim i As Integer
For i = 1 To Range("A10000").End(xlUp).Row
If Cells(i, 2) = Results.List(Results.ListIndex) Then
Rows(i).Select
.Range(Selection, 7).Value = Date
End If
Next i
End Sub
Entry form
Private Sub CancelJob_Click()
'Close EntryForm form
Unload EntryForm
'Show InitialForm form
InitialForm.Show
End Sub
Private Sub UserForm_Initialize()
'Empty all fields
JobBox.Value = ""
Customer.Value = ""
Location.Value = ""
Rack.Value = ""
'Fill combo box with product types
With ProductCombo
.AddItem "Channel Letter Faces"
.AddItem "Channel Letter Backers"
.AddItem "Routed Aluminum Panels"
.AddItem "Routed ACM Panels"
End With
'Set focus on Work order TextBox
JobBox.SetFocus
End Sub
Private Sub SubmitJob_Click()
'Make fields mandatory
If JobBox.Value = "" Or ProductCombo.Value = "" Or Rack.Value = "" Then
If MsgBox("Cannot submit. Please fill the mandatory fields.",
vbQuestion + vbOKOnly) <> vbOKOnly Then
Exit Sub
End If
End If
'Start transfering process
Dim emptyRow As Long
'Make Sheet1 active
Sheet1.Activate
'Determine emptyRow
emptyRow = WorksheetFunction.CountA(Range("A:A")) + 1
'Transfer information to the table
Cells(emptyRow, 1).Value = Date 'Auto populate 1st column with submission date
Cells(emptyRow, 2).Value = JobBox.Value
Cells(emptyRow, 3).Value = Customer.Value
Cells(emptyRow, 4).Value = Location.Value
Cells(emptyRow, 5).Value = ProductCombo.Value
Cells(emptyRow, 6).Value = Rack.Value
'Save workbook after transfer of data
ActiveWorkbook.Save
'Close EntryForm
Unload Me
'Quit application so that others can use it
'Application.Quit
End Sub
This is complete code for this search part of the userform that I cannot
figure out (I was playing with the code for "submit" button that I am stuck). Maybe it will help for troubleshooting:
Private Sub ClearForm(Except As String)
' Clears the list box and text boxes EXCEPT the text box
' currently having data entered into it
Select Case Except
Case "Job"
FormEvents = False
Customer.Value = ""
Location.Value = ""
Results.Clear
FormEvents = True
Case "Customer"
FormEvents = False
Job.Value = ""
Location.Value = ""
Results.Clear
FormEvents = True
Case "Location"
FormEvents = False
Job.Value = ""
Customer.Value = ""
Results.Clear
FormEvents = True
Case Else
FormEvents = False
Job.Value = ""
Customer.Value = ""
Location.Value = ""
Results.Clear
FormEvents = True
End Select
End Sub
Private Sub ClearBtn_Click()
ClearForm ("")
End Sub
Private Sub Job_Change()
If FormEvents Then ClearForm ("Job")
End Sub
Private Sub Customer_Change()
If FormEvents Then ClearForm ("Customer")
End Sub
Private Sub Location_Change()
If FormEvents Then ClearForm ("Location")
End Sub
Private Sub PickBtn_Click()
Dim i As Integer
Sheet1.Activate
For i = 1 To Range("A10000").End(xlUp).row
If Cells(i, 2) = Results.List(Results.ListIndex) Then
Rows(i).Select
Me.Range("Selection:G").Value = Date
End If
Next i
End Sub
Private Sub SearchBtn_Click()
Dim SearchTerm As String
Dim SearchColumn As String
Dim RecordRange As Range
Dim FirstAddress As String
Dim FirstCell As Range
Dim RowCount As Integer
' Display an error if no search term is entered
If Job.Value = "" And Customer.Value = "" And Location.Value = "" Then
MsgBox "No search term specified", vbCritical + vbOKOnly
Exit Sub
End If
' Work out what is being searched for
If Job.Value <> "" Then
SearchTerm = Job.Value
SearchColumn = "Job"
End If
If Customer.Value <> "" Then
SearchTerm = Customer.Value
SearchColumn = "Customer"
End If
If Location.Value <> "" Then
SearchTerm = Location.Value
SearchColumn = "Location"
End If
Results.Clear
' Only search in the relevant table column i.e. if somone is
searching Location
' only search in the Location column
With Range("Table1[" & SearchColumn & "]")
' Find the first match
Set RecordRange = .Find(SearchTerm, LookIn:=xlValues)
' If a match has been found
If Not RecordRange Is Nothing Then
FirstAddress = RecordRange.Address
RowCount = 0
Do
' Set the first cell in the row of the matching value
Set FirstCell = Range("B" & RecordRange.row)
' Add matching record to List Box
Results.AddItem
Results.List(RowCount, 0) = FirstCell(1, 1)
Results.List(RowCount, 1) = FirstCell(1, 2)
Results.List(RowCount, 2) = FirstCell(1, 3)
Results.List(RowCount, 3) = FirstCell(1, 4)
Results.List(RowCount, 4) = FirstCell(1, 5)
Results.List(RowCount, 5) = FirstCell(1, 7)
RowCount = RowCount + 1
' Look for next match
Set RecordRange = .FindNext(RecordRange)
' When no further matches are found, exit the sub
If RecordRange Is Nothing Then
Exit Sub
End If
' Keep looking while unique matches are found
Loop While RecordRange.Address <> FirstAddress
Else
' If you get here, no matches were found
Results.AddItem
Results.List(RowCount, 0) = "Nothing Found"
End If
End With
End Sub
Private Sub UserForm_Initialize()
FormEvents = True
End Sub
Add another column in the list box to hold the row number.
Results.List(RowCount, 6) = FirstCell.Row
And then code becomes
Private Sub PickBtn_Click()
Dim r as long
r = Results.List(Results.ListIndex,6)
Range(r, 7).Value = Date
End Sub
I am working on a userform where users can edit entries from a list selection and save them to specific cells.
Private Sub CommandButton3_Click()
Dim lZeile As Long
If ListBox1.ListIndex = -1 Then Exit Sub
If Trim(CStr(TextBox_Name.Text)) = "" Then
MsgBox "Sie müssen mindestens einen Namen eingeben!", vbCritical + vbOKOnly, "FEHLER!"
Exit Sub
End If
lZeile = 2
Do While Trim(CStr(Tabelle4.Cells(lZeile, 1).Value)) <> ""
If ListBox1.Text = Trim(CStr(Tabelle4.Cells(lZeile, 1).Value)) Then
Tabelle4.Cells(lZeile, 1).Value = Trim(CStr(TextBox_Name.Text))
Tabelle4.Cells(lZeile, 11).Value = ListBox_Problem.Text
Tabelle4.Cells(lZeile, 12).Value = TextBox_Problem2.Text
Tabelle4.Cells(lZeile, 4).Value = ComboBox1.Text
Tabelle4.Cells(lZeile, 3).Value = ComboBox2.Text
Tabelle4.Cells(lZeile, 13).Value = TextBox3.Text
Tabelle4.Cells(lZeile, 14).Value = TextBox4.Text
If ListBox1.Text <> Trim(CStr(TextBox_Name.Text)) Then
Call UserForm_Initialize
If ListBox1.ListCount > 0 Then ListBox1.ListIndex = 0
End If
Exit Do
End If
lZeile = lZeile + 1
Loop
End Sub
Now I have a ListBox where multiple entries can be selected. I want to write the selected entries into one single cell with "," as delimiter.
I have found the following code for that:
Dim i As Long
sText = ""
Range("B34").Value = ""
With Me.ListBox1
For i = 0 To .ListCount - 1
If .Selected(i) Then
sText = sText & ", " & .List(i)
End If
Next i
End With
sText = Mid(sText, 3)
If Len(sText) > 0 Then
Range("B34").Value = sText
Else
MsgBox "No selection made.", vbInformation
End If
I tried to incorporate it into mine but just cannot get it to work. I am not that fluent with VBA and was wondering if someone could help me?
The easiest way is to put your code (minor changes made) into a function:
Public Function GetCommaSeparatedListBoxItems(ByVal FromListBox As MSForms.ListBox) As String
Dim sText As String
With FromListBox
Dim i As Long
For i = 0 To .ListCount - 1 'loop through all items in the ListBox
If .Selected(i) Then 'chech each item if it is selected and if so …
sText = sText & ", " & .List(i) '… append this item comma delimited to `sText`
End If
Next i
End With
'since `sText` is empty in the beginning, data will always start with a comma, so removo that
'example data before: ", Item 1, Item 2, Item 3"
sText = Mid$(sText, 3)
'example data afterwards: "Item 1, Item 2, Item 3"
'return the comma separated items in the function
GetCommaSeparatedListBoxItems = sText
'Alternatively instead of the lise above you can …
If Len(sText) > 0 Then 'check if something was selected in the listbox and …
GetCommaSeparatedListBoxItems = sText '… return the value
Else
MsgBox "No selection made.", vbInformation '… or a error message
End If
End Function
That you can easily use like:
Debug.Print GetCommaSeparatedListBoxItems(FromListBox:=Me.ListBox1)
Example to write it into a cell you can use the function (in your first code) like:
Tabelle4.Cells(lZeile, 14).Value = GetCommaSeparatedListBoxItems(FromListBox:=Me.ListBox1)
you just need to adjust the code Me.ListBox1 to your multi select ListBox.
I have two commands button the first to post data and the second to run macro
how could I merge these two commands in one button?
as I need to post data then run macro
Private Sub post_Click()
If Me.today.Value = "" Then
MsgBox " You should enter contract date "
Exit Sub
End If
If Not (Me.percentage.Value = "" Xor Me.txtamount.Value = "") Then
MsgBox "You should select % or amount"
Exit Sub
End if
Dim ws As Worksheet
Set ws = Worksheets("6 Y")
ws.Cells(3, 17).Value = ComboBox2.Text
ws.Cells(4, 17).Value = Price.Text
ws.Cells(6, 19).Value = today.Text
ws.Cells(7, 24).Value = percentage.Text
ws.Cells(7, 25).Value = txtamount.Text
ws.Cells(1, 27).Value = ComboBoxpmtplan.Text
End Sub
Private Sub COMMRUN_Click()
Macro1
End Sub
You can simply call the function by name
Private Sub COMMRUN_Click()
Macro1
post_Click
End Sub
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
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.