Ms Access - VBA - 以编程方式创建带有大小的标签

Ms Access - VBA - Create Labels Programatically with Size

我正在尝试创建 Labels & Textboxes 并根据变量计数动态地为其分配一些值 NoOfRecords(问题是我事先不知道我有多少控件'将需要。数量将由特定 table 中有多少记录驱动。 我的表单名称是 frmDashboard

我试过的是

Set cNN = Nothing
Set rsfnum = Nothing
Dim strconnfnum As String
Set cNN = CurrentProject.Connection
Set rsfnum = New ADODB.Recordset

strconnfnum = "SELECT nz(employeename,'') as employeename from employees"
rsfnum.Open strconnfnum, cNN, adOpenKeyset, adLockOptimistic

'Number of Records in Employees tables

NoOfRecords = rsfnum.RecordCount


    For x = 1 To NoOfRecords
        Set ctrl = CreateControl("frmDashboard", acLabel, acDetail, , "", 0 + (x * 300), 0, 300, 240)
        ctrl.ControlName = "lblDynamic_control_" & x
       Controls("lblDynamic_control_" & x).Caption = x
        Set ctrl1 = CreateControl("frmDashboard", acTextBox, acDetail, , "", 0 + (x * 300), 0, 300, 240)
        ctrl1.ControlName = "txtDynamic_control_" & x  
       Controls("txtDynamic_control_" & x).Value= x
    Next x

我在这里面临 2 个问题

1) 如何像下面这样依次显示标签和文本框 (下一个标签和文本框应该正好在顶部下方。)

2)以上代码抛出如下错误

好的 - 免责声明我在这里完全是新手 - 但我调查了这个并且显然 VBA 不会让你创建控件(即 'set ctrl' 或 'set ctrl1' 命令) 在运行时。这些必须在设计时创建,并根据运行时的动态输入使其可见。

如果 NoOfRecords 有最大值,我可能建议在设计时对所有可能的 ctrls 进行预编码(使用循环),并根据运行时的动态输入使数字变为 visible/active .

至于组织标签和文本框的布局,这也将作为设计循环的一部分完成。如下面的文档所述,每个 ctrl 的左上角的位置可以在 'left' 和 'top' 命令的 CreateControl 方法中指定(您当前将其设置为 left = 0+( x*300), 顶部 = 0 ).只需在通过 ctrl 创建进行迭代时对 x 和 y 坐标添加必要的调整。

CreateControl 方法文档:https://msdn.microsoft.com/en-us/library/office/aa221167%28v=office.11%29.aspx

希望对您有所帮助!

您看到的错误是正确的,当您最终将数据库作为编译的拆分数据库分发时无法克服。

这里的技巧是提前创建您可能需要的所有控件。然后你需要贴上标签,让它们在表格上按顺序排列。所以像 Text1Text2LabelLabel2。这样你就可以通过它们的索引(这将是你的字段在你的记录集中的索引)遍历每个 textbox/label 组合。

Private Function ReBindControls()

    Dim rs As DAO.Recordset 'if you are using ADO then replace this with ADODB.Recordset 
    If IsNull(Combo99) Then
        Exit Function
    End If
    Set rs = CurrentDb.OpenRecordset(Combo99) ' If you are using ADO use the appropriate ADO method to open the recordset

    Dim fs As DAO.Fields 'if you are using ADO then replace this with ADODB.Fields
    Set fs = rs.Fields

    Dim f As Integer
    Dim aLabel As Label, aTextBox As TextBox

    Set Me.Recordset = rs

    For f = 0 To fs.Count - 1
        Set aLabel = Controls("Label" & f)
        aLabel.Caption = fs(f).Name
        aLabel.Visible = True

        Set aTextBox = Controls("text" & f)
        aTextBox.ControlSource = fs(f).Name
        aTextBox.Visible = True

        aLabel.Move 1 * 1440, f * 1440 / 2
        aTextBox.Move 2.5 * 1440, f * 1440 / 2
    Next f

End Function


Function clearBindings()
    Dim c As Integer
    Dim aLabel As Label, aTextBox As TextBox

    For c = 0 To maxIndexOfControls
        Set aTextBox = Controls("text" & c)
        aTextBox.ControlSource = ""
        Set aLabel = Controls("Label" & c)
        aLabel.Visible = False
        aTextBox.Visible = False
        aLabel.Move 0, 0
        aTextBox.Move 0, 0

    Next c
End Function

如果你同时调用这两个

Private Sub Combo99_Change()
    clearBindings
    ReBindControls
End Sub

你可以得到这些结果