I have a -userform- that has 100 different controls (Textbox and combobox) and i am trying to consolidate one large chunk of code down to something smaller and universal... by basing it on the active control and using that as my reference point for calling another sub where the declared variables will become plug and play.
So here is the base code that works... But i would need to replicate this 25 times and I feel like there is a better way, but i cannot seem to figure it out...
Option Explicit
Public Gal, Kg, L, Qt, Pt, Lbs, C, FlOz, Ea, Prts, Oz, Tbs, Tsp, Dl, G, Ml As Integer
Private Sub M1_AfterUpdate() 'this is where the math happens
'I have 25 variables, M1:M25 - by 16 variables, Gal:Ml for each
Gal = 128: Kg = 35.274: L = 33.814: Qt = 32: Pt = 16: Lbs = 16: C = 8 'multiply
FlOz = 1: Ea = 1: Prts = 1: Oz = 1 'stay
Tbs = 2: Tsp = 6: Dl = 3.381: G = 28.353: Ml = 29.574 'divide
'this is the base code that does ecactly what I need... But i would have to replicate this whole thing 25 times...
If ActiveControl.Text = "Gal" Then C1.Value = Round(((Q1 * Gal) * (Application.WorksheetFunction.Index(Sheets("Inventory").Range("C6:L1006"), _
Application.WorksheetFunction.Match(I1, Sheets("Inventory").Range("C6:C1006"), 0), 10))), 2)
If ActiveControl.Text = "Kg" Then C1.Value = Round(((Q1 * Kg) * (Application.WorksheetFunction.Index(Sheets("Inventory").Range("C6:L1006"), _
Application.WorksheetFunction.Match(I1, Sheets("Inventory").Range("C6:C1006"), 0), 10))), 2)
If ActiveControl.Text = "L" Then C1.Value = Round(((Q1 * L) * (Application.WorksheetFunction.Index(Sheets("Inventory").Range("C6:L1006"), _
Application.WorksheetFunction.Match(I1, Sheets("Inventory").Range("C6:C1006"), 0), 10))), 2)
' it goes on through each of the variables but i post it all, you get the idea ; )
End Sub
I have tried this road...THIS WAS A FAIL!!! I couldn't figure how to read it as a control name, it read as string.
I tried putting contol / controls in the front and that didnt work...
Option Explicit
Public Gal, Kg, L, Qt, Pt, Lbs, C, FlOz, Ea, Prts, Oz, Tbs, Tsp, Dl, G, Ml As Integer
Private Sub M1_AfterUpdate() 'this is where the math happens
Dim ActCtrl As Control: Set ActCtrl = ActiveControl.Name
Dim VarA As Integer
Dim x, y, z As String
If ActCtrl = M1 Then VarA = 1 ' 25 if lines written to represent 25 rows of form controls
'M2 is VarA=2 and so on till 25
'this puts them together, but it returns string.
x = "I" & VarA
y = "Q" & VarA
z = "C" & VarA
'this is where it would end
z.Value = Round(((y * Ml) * (Application.WorksheetFunction.Index(Sheets("Inventory").Range("C6:L1006"), _
Application.WorksheetFunction.Match(x, Sheets("Inventory").Range("C6:C1006"), 0), 10))), 2)
I would like to be able to change this...
If ActiveControl.Text = "Gal" Then C1.Value = Round(((Q1 * Gal) * (Application.WorksheetFunction.Index(Sheets("Inventory").Range("C6:L1006"), _
Application.WorksheetFunction.Match(I1, Sheets("Inventory").Range("C6:C1006"), 0), 10))), 2)
into a plug and play using variables... If possible...
Create a two-column lookup table on a sheet, with Unit & Conversion Factor, and use vlookup to directly convert the units to the scaling value.
Then factor almost all of the code out of your M1_AfterUpdate
into generic methods to which you can just pass M1
etc.
Something along these lines:
Private Sub M1_AfterUpdate()
HandleCombo M1
End Sub
Private Sub M2_AfterUpdate()
HandleCombo M2
End Sub
'etc for other combos
'handle a combo box changing
Sub HandleCombo(cmbo)
Dim f, c as object
f = GetScalingFactor(cmbo.Text)
Set c = me.Controls(Replace(cmbo.Name, "M", "C")) 'corresponding text control
c.Value = 'long formula which uses f
End Sub
'convert unit to scaling factor
Function GetScalingFactor(unit)
Dim m, rv
m = Application.Vlookup(unit, _
thisworkbook.sheets("lookup").Range("A2:B26"), _
2, False)
If not iserror(m) then
rv = m
else
'no match on the unit name - what to do here?
rv = -1 'or raise an error
end if
GetScalingFactor = rv
End function