Excel VBA如何将多个控件和变量转换成一个通用函数
Excel VBA How to convert multiple controls and variables into a universal function
我有一个 -userform- 有 100 个不同的控件(文本框和组合框),我正在尝试将一大块代码合并为更小且通用的代码...通过基于活动控件并使用这是我调用另一个 sub 的参考点,其中声明的变量将成为即插即用。
所以这是有效的基本代码...但我需要将其复制 25 次,我觉得有更好的方法,但我似乎无法弄清楚...
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
我试过这条路...这是失败的!!!我不知道如何将它读作控件名称,它读作字符串。
我试过将控件放在前面,但没用...
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)
我希望能够改变这个...
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)
使用变量实现即插即用...如果可能...
在 sheet 上创建 two-column 查找 table,使用单位和转换因子,并使用 vlookup 直接将单位转换为缩放值。
然后将 M1_AfterUpdate
中的几乎所有代码分解为通用方法,您可以将 M1
等传递给这些方法。
大致如下:
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
所以如果有人遇到这样的事情,这里是修复...再次感谢您提醒我有一个简单的方法!
第 1 步:在作品中构建工具sheet...见图。我为自己使用了一系列 index/match...但是您需要什么...
The worksheet tool...
第 2 步:在一个单独的模块中有这个位...这是直接与工具对话的代码。
Option Explicit
Sub Conv_Loop()
Dim CtrlName
CtrlName = RecipeCost.CtrlName
Sheets("Control").Range("C24").Value = RecipeCost.Controls("I" & CtrlName).Value
Sheets("Control").Range("C25").Value = RecipeCost.Controls("Q" & CtrlName).Value
Sheets("Control").Range("C26").Value = RecipeCost.Controls("M" & CtrlName).Value
RecipeCost.Controls("C" & CtrlName).Value = Sheets("Control").Range("C28").Value
End Sub
第 3 步:在需要与转换管理器对话的变量的用户窗体中,首先声明一个 public 变量。然后在你想要激活函数的控件中声明你的变量值,然后调用它。如果您不想看到该工具或不想让其他人使用它,请将 sheet 设置为 xlVeryHidden。
Option Explicit
Public CtrlName
Private Sub M1_AfterUpdate(): CtrlName = 1: Call Conv_Loop: End Sub
这让我费了九牛二虎之力,却让它变得非常简单!!!
感谢 Tim Williams 提醒我..."Create a two-column lookup table on a sheet",仅此而已...
我有一个 -userform- 有 100 个不同的控件(文本框和组合框),我正在尝试将一大块代码合并为更小且通用的代码...通过基于活动控件并使用这是我调用另一个 sub 的参考点,其中声明的变量将成为即插即用。
所以这是有效的基本代码...但我需要将其复制 25 次,我觉得有更好的方法,但我似乎无法弄清楚...
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
我试过这条路...这是失败的!!!我不知道如何将它读作控件名称,它读作字符串。
我试过将控件放在前面,但没用...
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)
我希望能够改变这个...
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)
使用变量实现即插即用...如果可能...
在 sheet 上创建 two-column 查找 table,使用单位和转换因子,并使用 vlookup 直接将单位转换为缩放值。
然后将 M1_AfterUpdate
中的几乎所有代码分解为通用方法,您可以将 M1
等传递给这些方法。
大致如下:
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
所以如果有人遇到这样的事情,这里是修复...再次感谢您提醒我有一个简单的方法!
第 1 步:在作品中构建工具sheet...见图。我为自己使用了一系列 index/match...但是您需要什么...
The worksheet tool...
第 2 步:在一个单独的模块中有这个位...这是直接与工具对话的代码。
Option Explicit
Sub Conv_Loop()
Dim CtrlName
CtrlName = RecipeCost.CtrlName
Sheets("Control").Range("C24").Value = RecipeCost.Controls("I" & CtrlName).Value
Sheets("Control").Range("C25").Value = RecipeCost.Controls("Q" & CtrlName).Value
Sheets("Control").Range("C26").Value = RecipeCost.Controls("M" & CtrlName).Value
RecipeCost.Controls("C" & CtrlName).Value = Sheets("Control").Range("C28").Value
End Sub
第 3 步:在需要与转换管理器对话的变量的用户窗体中,首先声明一个 public 变量。然后在你想要激活函数的控件中声明你的变量值,然后调用它。如果您不想看到该工具或不想让其他人使用它,请将 sheet 设置为 xlVeryHidden。
Option Explicit
Public CtrlName
Private Sub M1_AfterUpdate(): CtrlName = 1: Call Conv_Loop: End Sub
这让我费了九牛二虎之力,却让它变得非常简单!!!
感谢 Tim Williams 提醒我..."Create a two-column lookup table on a sheet",仅此而已...