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.
Related
I've created a button, then assigned a macro to it which is in module1. when I select a cell within a range, then press the button, I want that cell to be given a value. if a cell within the range is not selected then pressing the button should pop up with a message box. I am just starting to write the code and already getting an issue.
If Intersect(Target, Range("D12:AS23")) Is Nothing Then
MsgBox "Please select a date.", , "Error"
Exit Sub
Else
Edit: I've got past this issue now using active cell instead of the target. but now I'm struggling again at the next bit. its saying application/object-defined error and highlighting this line. full code below
Cells(LastRow, 2).Value = Application.SumIf(Sheets("Settings").range("ListEmployeeNames"), Cells(3, 2).Value, Sheets("Settings").range("ListEmployeeID"))
Sub AddNote()
Dim SelectedDate As Date
SelectedDate = Cells(ActiveCell.Row, 2) - 1 + ActiveCell.Value
If intersect(ActiveCell, range("D12:AS23")) Is Nothing Then
MsgBox "Please select a date.", , "Error"
Exit Sub
Else
With Sheets("Notes")
xtt = Application.InputBox("Insert your Comment here", "Comment")
If xtt = vbNullString Or xtt = False Then
End If
Dim LastRow As Integer
LastRow = 2 + .listobjects("TblNotes").range.rows.Count
Cells(LastRow, 2).Value = Application.SumIf(Sheets("Settings").range("ListEmployeeNames"), Cells(3, 2).Value, Sheets("Settings").range("ListEmployeeID"))
Cells(LastRow, 4).Value = SelectedDate
Cells(LastRow, 5).Value = xht
End With
End If
End Sub
Got it working 90% on my own, thanks to #LeeLiFong for tipping me off about "target" being an issue and also #BraX for point int he right direction about including arguements to qualify things. I cant accept my answer for another 48 hours.
Dim SelectedDate As Date
SelectedDate = Cells(ActiveCell.Row, 2) - 1 + ActiveCell.Value
If intersect(ActiveCell, range("D12:AS23")) Is Nothing Then
MsgBox "Please select a date.", , "Error"
Exit Sub
Else
Call SmoothCodeStart
With Sheets("Notes")
xt4 = Application.InputBox("Insert your Comment here", "Comment")
If xt4 = vbNullString Or xt4 = False Then
End If
Dim LastRow As Integer
LastRow = 2 + .listobjects("TblNotes").range.rows.Count
.Cells(LastRow, 2).Value = Application.SumIf(Sheets("Settings").range("ListEmployeeNames"), Cells(3, 2).Value, Sheets("Settings").range("ListEmployeeID"))
.Cells(LastRow, 4).Value = SelectedDate
.Cells(LastRow, 6).Value = xt4
End With
Call SmoothCodeEnd
End If
I have three forms.
Form1(login)
Form 2(informationAdd)
Form 3(Information add to different sheet)
For some reason my macro is not entering my data into excel when I press submit for the third form.
My second form enters information but when entering the third form the information is no where to be found.
Private Sub cmdSubmit_Click()
'Dim iRow As Long
'Dim ws As Worksheet
Set ws = Worksheets("Scrap")
'find first empty row in database
iRow = ws.Cells.Find(What:="*", SearchOrder:=xlRows, _
SearchDirection:=xlPrevious, LookIn:=xlValues).Row + 1
'check for a part number
If Trim(Me.txtPress.Value) = "" Then
Me.txtPress.SetFocus
MsgBox "Please enter press scrap"
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(iRow, 1).Value = Me.txtDelam.Value
.Cells(iRow, 2).Value = Me.txtCuts.Value
.Cells(iRow, 3).Value = Me.txtBurns.Value
.Cells(iRow, 4).Value = Me.txtDents.Value
.Cells(iRow, 5).Value = Me.txtStaple.Value
.Cells(iRow, 6).Value = Me.txtGlue.Value
.Cells(iRow, 7).Value = Me.txtPress.Value
' .Protect Password:="Password"
End With
'clear the data
Me.txtDelam.Value = ""
Me.txtCuts.Value = ""
Me.txtBurns.Value = ""
Me.txtDents.Value = ""
Me.txtStaple.Value = ""
Me.txtGlue.Value = ""
Me.txtPress.Value = ""
Me.txtPress.SetFocus
Unload Me
End Sub
Did you send all Form 2 textbox values to Form 3 ?
I tried this way.
You may be have this kind of code in your Form 2 :
Private Sub CommandButton1_Click()
' I send the value from Form2 to Form3
YourForm3.txtPress.Value = YourForm2.TextBox1.Value
YourForm3.Show
Unload Me
End Sub
In the next step, the Form3 is opened with the Form2 informations, I run your code and it's working.
To my test, I just modified your iRow variables to iRow = ws.Range("A" & Rows.Count).End(xlUp).Row + 1
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
I have 2 sheet on my excel workbook.
1 is Stock In sheet and 1 is Stock Out sheet.
I wish to store the information in Stock Out sheet when the data is found in Stock In.
Stock In sheet:
Stock Out sheet:
For example, the Stock Out sheet only will able to accept the data when the PT# and the Rack is tally with the detail in Stock In sheet.
As below will be the code for my delete button inside my userform:
Private Sub TrackOut_Click()
Sheets("Stock Out").Activate
Dim cDelete As VbMsgBoxResult
With Me
If Len(.TextBox1.Value) * Len(.PT.Value) *
Len(.Rack2.Value) * _
Len(.Operator2.Value) = 0 Then
MsgBox "Please Complete All Fields Before Submit"
Else
cDelete = MsgBox("Are you sure that you want to delete this record", vbYesNo + vbDefaultButton2, "Track Out")
If cDelete = vbYes Then
If Sheets("Stock In").Columns(2).Find(What:=PT.Text) Is Nothing Then
MsgBox "No stock inventory for this PT#"
Exit Sub
End If
eRow = Sheet2.Cells(Rows.Count, 1).End(xlUp).Offset(1, 0).Row
Cells(eRow, 1).Value = TextBox1.Text
Cells(eRow, 2).Value = PT.Text
Cells(eRow, 3).Value = Rack2.Text
Cells(eRow, 4).Value = Operator2.Text
Else
If cDelete = vbNo Then
Unload Me
End If
End If
End If
End With
End Sub
OK - this is what I understand and what the code adjustment below does:
Operator completes a userform and inputs Date, PT#, Rack No and Operator. This gets looked-up in 'Stock In' sheet (all fields must match). If operator confirms then the record gets transferred to 'Stock Out' sheet on next available row and deleted from 'Stock In' sheet and other records moved up.
If you only want say two fields to match (userform and 'Stock In') then see the code for the adjustments to make: commented as '**
Private Sub TrackOut_Click()
Sheets("Stock Out").Activate
Dim cDelete As VbMsgBoxResult
Dim fndItm As Range
Dim orow As Long, irow As Long
Dim reqStock As String, itmStock As String
Dim stockArr(4) As String
With Me
If Len(.TextBox1.Value) * Len(.PT.Value) * Len(.Rack2.Value) * Len(.Operator2.Value) = 0 Then
MsgBox "Please Complete All Fields Before Submit."
Else
'collect requested (userform) data
'** reqStock should include those fields you require to match with Stock In record
'** currently set to check all fields
reqStock = .TextBox1.Value & .PT.Value & .Rack2.Value & .Operator2.Value
Set fndItm = Sheets("Stock In").Columns(2).Find(What:=PT.Text)
If Not fndItm Is Nothing Then
'if PT# found collect stock row data
With Sheets("Stock In")
irow = fndItm.Row
stockArr(0) = Format(.Cells(irow, 1).Value, "dd/mm/yyyy")
stockArr(1) = .Cells(irow, 2).Value
stockArr(2) = .Cells(irow, 3).Value
stockArr(3) = .Cells(irow, 4).Value
'** itmStock should include those fields you require to match with userform fields
'** these should match reqStock
'** currently set to check all fields
itmStock = stockArr(0) & stockArr(1) & stockArr(2) & stockArr(3)
End With
'compare requested (userfrom) data with Stock In data
If reqStock = itmStock Then
cDelete = MsgBox("Are you sure that you want to delete this record from stock?", vbYesNo) ' + vbDefaultButton2, _
"Track Out")
If cDelete = vbYes Then
'xfer record to Stock Out sheet
With Sheets("Stock Out")
orow = .Cells(Rows.Count, 1).End(xlUp).Offset(1, 0).Row
.Range(.Cells(orow, 1), .Cells(orow, 4)) = stockArr
End With
'delete record from Stock In sheet
With Sheets("Stock In")
.Range(.Cells(irow, 1), .Cells(irow, 4)).Delete xlShiftUp
End With
End If
'clear userform fields for next entry
.TextBox1.Value = ""
.PT.Value = ""
.Rack2.Value = ""
.Operator2.Value = ""
Else
MsgBox "PT# found but requested information does not match."
End If
Else
MsgBox "No stock inventory for this PT#."
Exit Sub
End If
End If
End With
End Sub
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.