VBA Excel 2 comboboxes issue - vba

I am trying to make an application which lets you update sales condition details using two comboboxes.
See this screenshots for a demo:
1) Datasheet
2) this Userform concerns the creation of a new sales condition
3) a second Userform is required to modify the data and update it in the desired sheet
Regarding my source code for creating a new sales condition, you can find it in here:
Private Sub bAnnuler_Click()
Unload Me
End Sub
Private Sub bEnregistrer_Click()
Sheets("ConditionsVente").Activate
Range("A1").Select
Selection.End(xlDown).Select 'On se positionne sur la derniere ligne non vide
Selection.Offset(1, 0).Select 'On se décale d'une ligne vers le bas
'ActiveCell = txtNom.Value
ActiveCell.Offset(0, 3).Value = txtPrix
ActiveCell.Offset(0, 4).Value = txtDélai
End Sub
Private Sub bReinitialiser_Click()
txtPrix = ""
txtDélai = ""
End Sub
Private Sub cboFournisseur_Change()
End Sub
Private Sub UserForm_Initialize()
'initialiser combobox fournisseur
Dim Fournisseurs As Range
Dim Matieres As Range
Set Fournisseurs = Worksheets("Fournisseurs").Range("A2:A" & Worksheets("Fournisseurs").Range("A2").End(xlDown).Row)
Me.cboFournisseur.MaxLength = Fournisseurs.Count
Me.cboFournisseur.List = Fournisseurs.Value
'initialiser combobox matiere
Set Matieres = Worksheets("Matieres").Range("A2:A" & Worksheets("Matieres").Range("A2").End(xlDown).Row)
Me.cboMatiere.MaxLength = Matieres.Count
Me.cboMatiere.List = Matieres.Value
End Sub
I have two issues:
1) when I run this code, I create a new sales condition but what is saved in the sheet are just the price (prix in french) and the delay (délai in french) and in the columns of Suppliers (Fournisseurs in french) and Raw Material (Matiere in french) are still empty.
2) the second point, in order to make a userform which let me modify the sales condition in the desired sheet, what is the simplest way to realize it ?

For part 1 you need this:
Private Sub bEnregistrer_Click()
Dim nextRow as Integer
With Worksheets("ConditionsVente")
nextRow = .Range("A1").end(xlDown).Row + 1
.Range("A" & nextRow) = txtNom.Value
.Range("B" & nextRow) = txtMatiere.Value
.Range("C" & nextRow) = txtPrix
.Range("D" & nextRow) = txtDélai
End With
End Sub
For part 2 try this:
Private Sub btnSave_Click()
Dim Fournisseurs As Range, Fournisseur as range
Set Fournisseurs = Worksheets("Fournisseurs").Range("A2:A" & Worksheets("Fournisseurs").Range("A2").End(xlDown).Row)
For each Fournisseur in Fournisseurs
If Fournisseur = txtNom.Value And Fournisseur.offset(0, 1) = txtMatiere.Value Then
Fournisseur.offset(0, 3) = txtPrix
Fournisseur.offset(0, 3) = txtDélai
End if
Next Fournisseur
End Sub

Related

VBA userform - Dynamic textbox default value

I have two TextBox in my userform. One is for entering the Name, and the other one is for entering the income.
Now I create a modeless userform, so that user can keep insert the data
Suppose I already have list of Name. For example: Marry, Jamie, Michael
Is it posible to set this list as a default value for Name TextBox?
For example:
After click the button, the userform Pop up and Shows as follow:
Name: Marry
Income: ""
After I enter the income, and click "OK" buttom, the userform will Pop up again.
This time it Shows like this:
Name: Jamie
Income: ""
If my question is not clear enough, please tell me and I will explain it more detailed. Thanks in advance.
Update:
I add my code here to make my question clearer. However, the "story" of my code is a Little bit different. The user will insert the Portfolio ID, Budget value and the date into userform. Then the macro will filter the table in sheet "ALL_List".
Based on Portfolio ID and date, there will be only one line data in that table after filtering. The Budget column for this line of data should be empty. The Macro should automatically insert the Budget value, which was recorded in userform, into Budget column.
There are, for example, 5 ID and 5 Budget value:
Date / ID / Budget
29/06/2018 / 12541 / 336521
29/06/2018 / 4521 / 658882
29/06/2018 / 44359 / 4587996
29/06/2018 / 10223 / 148665
29/06/2018 / 74 / 658324
So, when the first time userform Pop up. I hope there will be a Default ID value "12541" in the Portfolio ID TextBox. After I enter the date and Budget value and click the button "Enter", the Budget value will insert to the Budget column in sheet "ALL_List". Then the userform Pop up again. This time the Default value for ID will be 4521.
After the final Default ID (74) Show up and I enter the value and click Enter, I hope the userform will still Pop up and this time the value of Portfolio ID TextBox will be empty (because there could be other ID which the user wants to insert.)
Hope my descripition is clear. If there is any question, please don't hesitate to inform me. Much Thanks!
Sub Budget_Adjustment()
Dim frm As New UserFormBudget
frm.Show vbModeless
End Sub
Private Sub ButtonClose_Click()
Unload Me
End Sub
Private Sub ButtonEnter_Click()
InsertBudget
End Sub
Private Sub InsertBudget()
Dim UpdateDate As String
Dim PortfolioID, Budgetvalue As Long
UpdateDate = TextBoxDate.Value
PortfolioID = TextBoxID.Value
Budgetvalue = TextBoxBedget.Value
UpdateDate = CDate(UpdateDate)
Sheets("ALL_List").Activate
ActiveSheet.AutoFilterMode = False
Range(Cells(1, 1), Cells(Cells(Rows.Count, 7).End(xlUp).row, 7)).AutoFilter Field:=1, Criteria1:=UpdateDate
Range(Cells(1, 1), Cells(Cells(Rows.Count, 7).End(xlUp).row, 7)).AutoFilter Field:=3, Criteria1:=PortfolioID
Cells(Cells(Rows.Count, "A").End(xlUp).row, "F").Value = Budgetvalue
ActiveSheet.AutoFilterMode = False
TextBoxID.Value = ""
TextBoxBedget.Value = ""
TextBoxID.SetFocus
End Sub
Private Sub TextBoxBedget_KeyDown(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)
If KeyCode = 13 Then
ButtonEnter_Click
End If
End Sub
Private Sub UserForm_Activate()
'Empty TextBoxID
TextBoxID.Value = ""
'Empty TextBoxBedget
TextBoxBedget.Value = ""
'Empty TextBoxDate
TextBoxDate.Value = ""
'Set Focus on NameTextBox
TextBoxDate.SetFocus
End Sub
...
EDIT:
Edited your code a little bit based on the new information you provided. Now, you just enter your ID's you want to edit before hand in the sheet named "list".
I added sheet named "List" :
This code goes in area when you right-click UserFormBudget > View Code:
Private Sub ButtonClose_Click()
Dim lastListRow As Long
With ThisWorkbook.Worksheets("List")
lastListRow = .Cells(.Rows.Count, 1).End(xlUp).row
.Range("A4:A" & lastListRow).Interior.ColorIndex = 0
End With
Unload Me
End Sub
Private Sub ButtonEnter_Click()
InsertBudget
End Sub
Private Sub InsertBudget()
Dim UpdateDate As String
Dim PortfolioID As Long
Dim Budgetvalue As Long
Dim lastListRow As Long
Dim row As Long
UpdateDate = TextBoxDate.Value
PortfolioID = TextBoxID.Value
Budgetvalue = TextBoxBedget.Value
If Len(UpdateDate) > 0 Then
UpdateDate = CDate(UpdateDate)
Else
MsgBox "Need to enter a date"
Exit Sub
End If
With Worksheets("ALL_List")
.Activate
.AutoFilterMode = False
.Range(.Cells(1, 1), .Cells(.Cells(.Rows.Count, 7).End(xlUp).row, 7)).AutoFilter Field:=1, Criteria1:=UpdateDate
.Range(.Cells(1, 1), .Cells(.Cells(.Rows.Count, 7).End(xlUp).row, 7)).AutoFilter Field:=3, Criteria1:=PortfolioID
.Cells(.Cells(.Rows.Count, "A").End(xlUp).row, "F").Value = Budgetvalue
.AutoFilterMode = False
End With
With ThisWorkbook.Worksheets("List")
lastListRow = .Cells(.Rows.Count, 1).End(xlUp).row
TextBoxID.Value = ""
For row = 5 To lastListRow
If .Cells(row, "A").Interior.Color <> RGB(255, 255, 0) Then
TextBoxID.Value = .Cells(row, "A").Value
.Cells(row, "A").Interior.Color = RGB(255, 255, 0)
Exit For
End If
If row = lastListRow Then
TextBoxDate.Value = ""
End If
Next
End With
TextBoxBedget.Value = ""
TextBoxID.SetFocus
End Sub
Private Sub TextBoxBedget_KeyDown(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)
If KeyCode = 13 Then
ButtonEnter_Click
End If
End Sub
And add this code in a module, so right-click project and insert new module, then paste:
Sub Budget_Adjustment()
Dim frm As New UserFormBudget
Dim lastListRow As Long
With ThisWorkbook.Worksheets("List")
lastListRow = .Cells(.Rows.Count, 1).End(xlUp).row
If lastListRow = 3 Then
frm.TextBoxDate.Value = ""
frm.TextBoxID.Value = ""
frm.TextBoxBedget.Value = ""
Else
frm.TextBoxID.Value = .Cells(4, "A").Value
frm.TextBoxBedget.Value = .Cells(4, "B").Value
.Cells(4, "A").Interior.Color = RGB(255, 255, 0)
End If
End With
frm.TextBoxID.SetFocus
frm.Show vbModeless
End Sub
Now, just right-click on the button on List sheet and assign it the macro Budget_Adjustment

Compare 4 columns in one excel sheet using vba

I need your help please, I have 4 columns in an excel sheet and I need to compare them 2 by 2 i will explain to you :
In column A i have users(user1,user2,user3 ...)
In column B i have functionalities ( fonc1, fonc2, fonc3.....)
In column C i have users(user1,user2,user3 ...)
In column D i have functionalities ( fonc1, fonc2, fonc3.....)
The columns C and D are a new version of columns A and B in the columns C and D the users may change order or change functionalities .
When i execute my code i put the result in other new columns:
column F where i have the users
column G where i put the Deleted_functionalities
column H where i put the New_functionalities
The first problem is that the code doesn't get the users it get only the new and deleted functionalities. The second problem is that when the column A is more than column C where the users are stocked the code doesn't work. Can you please help me to find a solution? Thank you in advance .
Here is my code and the file I am working on :
Private Sub CommandButton2_Click()
Dim rngCell As Range
For Each rngCell In Range("B2:B2000")
If WorksheetFunction.CountIf(Range("D2:D2000"), rngCell) = 0 Then
Range("G" & Rows.Count).End(xlUp).Offset(1) = rngCell
End If
Next
For Each rngCell In Range("D2:D2000")
If WorksheetFunction.CountIf(Range("B2:B2000"), rngCell) = 0 Then
Range("H" & Rows.Count).End(xlUp).Offset(1) = rngCell
End If
Next
End Sub
and this is the excel file
http://www.cjoint.com/c/FCxnwjp22rv
try this
Private Sub CommandButton2_Click()
Dim ws As Worksheet
Dim cell As Range, funcCell As Range
Dim oldUserRng As Range, newUserRng As Range, reportRng As Range
Dim iReport As Long
Dim oldFunc As String, newFunc As String
Set ws = ThisWorkbook.Worksheets("users") '<== adapt it to your needs
With ws
Set oldUserRng = .Columns(1).Resize(.Rows.Count - 1).Offset(1).SpecialCells(xlCellTypeConstants, xlTextValues)
Set newUserRng = .Columns(3).Resize(.Rows.Count - 1).Offset(1).SpecialCells(xlCellTypeConstants, xlTextValues)
Set reportRng = .Range("F1:I1") '<== added one report column to account for unchanged functions
End With
reportRng.Value = Array("user", "deleted", "new", "same")
iReport = 1
For Each cell In oldUserRng
With cell
oldFunc = .Offset(, 1).Value
Set funcCell = FindAndOffset(newUserRng, .Value, 1)
If funcCell Is Nothing Then
reportRng.Offset(iReport) = Array(.Value, "", "", oldFunc)
Else
newFunc = funcCell.Value
If newFunc = oldFunc Then
reportRng.Offset(iReport) = Array(.Value, "", "", newFunc)
Else
reportRng.Offset(iReport) = Array(.Value, oldFunc, newFunc, "")
End If
End If
iReport = iReport + 1
End With
Next cell
For Each cell In newUserRng
With cell
Set funcCell = FindAndOffset(oldUserRng, .Value, 1)
If funcCell Is Nothing Then
reportRng.Offset(iReport) = Array(.Value, "", .Offset(, 1).Value, "")
iReport = iReport + 1
End If
End With
Next cell
End Sub
Not so sure it does what you need.
you'd better provide screenshots of "before" and "after" scenarios.
BTW, is it safe to assume that both old and new user columns cannot hold duplicates (i.e.: two or more "userX" in column A and/or column C?)
But it does speed up thing considerably since it iterates only through non empty cells.
I hope I get what you want to achieve. Does the following solve your problem?
Private Sub CommandButton2_Click()
Dim rngCell As Range
For Each rngCell In Range("A2:A20000")
If WorksheetFunction.CountIf(Range("C2:C20000"), rngCell) > 0 Then
Range("F" & Rows.Count).End(xlUp).Offset(1) = rngCell
Range("F" & Rows.Count).End(xlUp).Offset(0, 1) = rngCell.Offset(0, 1).Value
Range("F" & Rows.Count).End(xlUp).Offset(0, 2) = Application.WorksheetFunction.VLookup(rngCell.Value, Range("C2:D20000"), 2, 0)
ElseIf (rngCell <> "") Then
Range("F" & Rows.Count).End(xlUp).Offset(1) = rngCell
Range("F" & Rows.Count).End(xlUp).Offset(0, 1) = rngCell.Offset(0, 1).Value
End If
Next
For Each rngCell In Range("C2:C20000")
If (WorksheetFunction.CountIf(Range("A2:A20000"), rngCell) = 0 And rngCell <> "") Then
Range("F" & Rows.Count).End(xlUp).Offset(1) = rngCell
Range("F" & Rows.Count).End(xlUp).Offset(0, 2) = rngCell.Offset(0, 1).Value
End If
Next
End Sub
A user is only included in column F when he appears both in columns A and C.In case you want to include every user that is either in column A or C the code has to be altered.

How to list items in combobox?

I have created a UserForm with an empty ComboBox to be populated with a list of formulated (basic concatenate) text for user to select. I got the below code but failed.
Private Sub specList_change()
Dim i As Integer
Dim ListSpec As String
'Clear whatever in listbox
Me.specList.Clear
Me.lineText = ""
Me.partText = ""
'Get none empty data from P6:Pxx
i = 5
Do
DoEvents
i = i + 1
ListSpec = Sheets("SPEC CHART").Range("P" & i)
'Add data into the listbox till all data in SPEC CHART worksheet is empty
If Len(ListSpec) <> 0 Then specList.AddItem (ListSpec)
Loop Until ListSpec = ""
End Sub
Appreciate your guidance.
Use UserForm_Initialize event instead.
Private Sub UserForm_Initialize()
Dim r As Range, lr As Long
With Sheets("SPEC CHART")
lr = .Range("P" & .Rows.Count).End(xlUp).Row
If lr > 5 Then
Set r = .Range("P6:P" & lr)
Me.speclist.RowSource = r.Address(, , , True)
End If
End With
End Sub
Aslo if the source is a Range, you can use RowSource property.
You can also use the List property like this:
Me.speclist.List = Application.Transpose(r)
That is in place of me.speclist.RowSource = r.Address(, , , True). HTH.

Changing invoice number automatically on workbook close but checking if it has to increase or not

I have this code below for my workbook that saves the workbook for me and also increases the invoice number by 1 based on the value in a certain cell:
Private Sub Workbook_BeforeClose(Cancel As Boolean)
Range("L5").Value = Range("L5").Value + 1
ThisWorkbook.Save
End Sub
So cell L5 starts with 1 and right now everytime the workbook is closed it will add +1 to it and save the book, so the next time it opens it will be 2,3,4,5 and so on.
The problem I have is that if someone closes it and open and closes it will keep adding numbers even though that invoice doesn't exit.
Is there anyway it can check a list of value from a column in sheet 2 to see if the current invoice number exists, if it does then add 1 and save, if not then leave the same number and save?
UPDATED SUBMIT CODE WITH CLEARING, SAVING, AND UPDAING INVOCE NUMBER. All cells are locked and protected except the cells in the refTable, those are editable by user but L5 is locked and needs to be editable by the VBA code only, not users.
Sub Submit()
Dim refTable As Variant, trans As Variant
refTable = Array("B = L5", "C = C5", "D=G5", "E=C10", "F=C9", "G=I9", "H=I10", "I=C13", "J=C14", "K=C15", "L=C16", "M=C17", "N=C18", "O=I13", "P=I14", "Q=I15", "R=I16", "S=I17", "W=H20")
Dim Row As Long
Row = Worksheets("TravelLog").UsedRange.Rows.Count + 1
For Each trans In refTable
Dim Dest As String, Field As String
Dest = Trim(Left(trans, InStr(1, trans, "=") - 1)) & Row
Field = Trim(Right(trans, Len(trans) - InStr(1, trans, "=")))
Worksheets("TravelLog").Range(Dest).Value = Worksheets("TravelRequest").Range(Field).Value
Next
If Worksheets("TravelRequest").CheckBox1.Value Then
Worksheets("TravelLog").Range("T" & Row).Value = "Yes"
Else
Worksheets("TravelLog").Range("T" & Row).Value = "No"
End If
If Worksheets("TravelRequest").CheckBox2.Value Then
Worksheets("TravelLog").Range("U" & Row).Value = "Yes"
Else
Worksheets("TravelLog").Range("U" & Row).Value = "No"
End If
If Worksheets("TravelRequest").CheckBox3.Value Then
Worksheets("TravelLog").Range("V" & Row).Value = "Yes"
Else
Worksheets("TravelLog").Range("V" & Row).Value = "No"
End If
Range("L5").Value = Range("L5").Value + 1
Range("I9:I10, I13:I17, H20, C5, C9:C10, C13:C18").Select
Selection.ClearContents
Dim OleObj As OLEObject
For Each OleObj In ActiveSheet.OLEObjects
If OleObj.progID = "Forms.CheckBox.1" Then
OleObj.Object = False
End If
Next OleObj
ThisWorkbook.Save
End Sub
Use goto in Workbook_BeforeClose with condition u mentioned like that
Private Sub Workbook_BeforeClose(Cancel As Boolean)
If 'your_condition' = TRUE Then goto do_save
Range("L5").Value = Range("L5").Value + 1
do_save:
ThisWorkbook.Save
End Sub

Excel VBA loop through worksheets fails

Edit: I took all you advice and edited my code. Now it works!!!
Thank you.
Here is the new code:
Sub WorksheetLoop()
Dim AllWorksheets As Integer
Dim Worksheet As Integer
AllWorksheets = ActiveWorkbook.Worksheets.Count
For Worksheet = 2 To AllWorksheets
Sheets(1).Select
Cells(10, Worksheet).Value = Sheets(Worksheet).TextBoxes(2).Text
Cells(13, Worksheet).Value = Sheets(Worksheet).TextBoxes(3).Text
Cells(18, Worksheet).Value = Sheets(Worksheet).TextBoxes(1).Text
Cells(24, Worksheet).Value = Sheets(Worksheet).TextBoxes(5).Text
Cells(34, Worksheet).Value = Sheets(Worksheet).TextBoxes(6).Text
Cells(34, Worksheet).Value = Sheets(Worksheet).TextBoxes(4).Text
Next Worksheet
End Sub
Original Problem
So there is an excel document, which contains an amount of worksheets.
On the first sheet an overview should be created by the script.
It should start in the 2nd worksheet and should write the content of the textboxes (please don't ask why there are textboxes...) to Cell B10, B13, anso so on.
Then the script should go to worksheet 3 and the content of the textboxes should go to C10, C13,...
You get the idea...
I know that this is only possible to Z....
But why do I keep getting error messages?
My VBA knowlage is very small, so sorry for obvious errors.
Edit: I took the advice about the spaces around &
But I still get "object doesn't support this property or method"
Sub WorksheetLoop()
Dim AllWorksheets As Integer
Dim Worksheet As Integer
AllWorksheets = ActiveWorkbook.Worksheets.Count
For Worksheet = 2 To AllWorksheets
For CellAscii = 66 To (AllWorksheet + 66)
Cell = Chr(CellAscii)
Sheets(1).Select
Range(Cell & "10").Value = Sheets(Worksheet).TextBox2.Text
Range(Cell & "13").Value = Sheets(Worksheet).TextBox3.Text
Range(Cell & "18").Value = Sheets(Worksheet).TextBox1.Text
Range(Cell & "24").Value = Sheets(Worksheet).TextBox5.Text
Range(Cell & "30").Value = Sheets(Worksheet).TextBox6.Text
Range(Cell & "34").Value = Sheets(Worksheet).TextBox4.Text
Next CellAscii
Next Worksheet
End Sub
Just try the following when trying to access textboxes:
Sheets("SheetName").TextBoxes("TextBox Name").Text
Verify that your "SheetName" and "TextBox Name" are correct.
Hope this was usefull for you.
Range doesn't take a reference of schema Ay, it takes one with RyCx.
Anyway use SheetX.Cell to access a particular cell in a particular row and column.
You loop through cells like this:
Sub MyLoop()
For RowCounter = 1 To 20
For ColumnCounter = 1 To 20
Set curCell = Worksheets("Sheet1").Cells(RowCounter , ColumnCounter)
If Abs(curCell.Value) < 0.01 Then curCell.Value = 0
Next ColumnCounter
Next RowCounter
End Sub
The main error in your code is that there is no space before and after &
Change Range(Cell&"10").Value to Range(Cell & "10").Value. Similarly for the rest and your code will run just fine :)