【问题标题】:Excel VBA How to convert multiple controls and variables into a universal functionExcel VBA 如何将多个控件和变量转换为通用函数
【发布时间】:2019-09-27 20:44:07
【问题描述】:

我有一个 -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)

使用变量变成即插即用...如果可能的话...

【问题讨论】:

  • 在工作表上创建一个两列的查找表,带有Unit & Conversion Factor,并使用vlookup直接将单位转换为缩放值。不过,这只是一个起点,因为它似乎只会处理您拥有的部分重复内容。

标签: excel vba variables controls userform


【解决方案1】:

在工作表上创建一个包含单位和转换因子的两列查找表,并使用 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

【讨论】:

  • 感谢您提醒我有一个完整的工作簿可供我使用...大声笑有时我会尝试使事情过于复杂...所以我将其进一步分解并构建了一个转换工具在一个 xlveryhidden 表中,我只是填充了 3 个变量,然后将结果返回到正确的用户窗体控件...谢谢!!!
【解决方案2】:

所以如果有人遇到这样的事情,这里是解决办法...再次感谢你提醒我有一个简单的方法!

第 1 步:在工作表中构建工具...参见图片。我为我使用了一系列索引/匹配...但是您需要什么...

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 步:在包含需要与转换管理器对话的变量的用户表单中,首先声明一个公共变量。然后在控件中你想激活函数,然后声明你的变量值,然后调用它。如果您不想看到该工具或使其可用于其他工具,则将工作表设置为 xlVeryHidden。

Option Explicit

Public CtrlName

Private Sub M1_AfterUpdate(): CtrlName = 1: Call Conv_Loop: End Sub

这花了我试图做的一个愚蠢的世界,让它变得非常容易!!!

感谢 Tim Williams 提醒我...“在工作表上创建一个包含两列的查找表”,仅此而已...

【讨论】:

    猜你喜欢
    • 2011-01-23
    • 2016-10-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-17
    • 1970-01-01
    • 2016-10-08
    • 1970-01-01
    相关资源
    最近更新 更多