【问题标题】:Automatically creating textboxes based on number of rows根据行数自动创建文本框
【发布时间】:2015-09-22 17:40:44
【问题描述】:

VBA Excel 用户表单中有没有一种方法可以根据特定工作表上的行数在用户表单上自动创建文本框?

我的数据在表格 1 中,从 A1 开始,即:

  • A1:发票日期
  • B1:发票号
  • C1:发票金额
  • D1:已收到付款

现在有很多行数据(发票),我们无法知道有多少行与特定客户相关。当用户表单加载时,收到的付款文本框将为空,而发票日期、发票编号和发票金额将从工作表 1 中获取。

然后很容易填写收到的付款文本框,付款可以应用于特定发票。

【问题讨论】:

  • 您的问题的答案是肯定的——有办法。您没有问如何,但一个简单的答案是找到相关行的数量,然后让 VBA 在加载用户表单时添加该数量的行。
  • 怎么样?当然,我从“如何做”的角度发布了这个问题。谢谢
  • 你有什么尝试@StarShines? mattgemmell.com/what-have-you-tried
  • Scott,我不是一个成熟的软件开发人员或程序员。我是一名会计师,并在此处发布一个通用问题以供学习。我想知道为什么这里的每个人都没有遵循您解决问题的智慧。顺便说一句,您的友好评论得到了很好的注意。干杯

标签: vba excel textbox userform


【解决方案1】:

如果您有这样的电子表格:

您可以向“显示表单”按钮添加点击处理程序:

Sub FormButton_Click()
    TestForm.Show
End Sub

在 TestForm 代码中:

Option Explicit

Const dateCol = 1
Const invoiceNumCol = 2
Const amountCol = 3
Const paymentCol = 4

Private Sub SaveButton_Click()
    Dim row As Range
    Dim box As Control

    For Each row In ActiveSheet.Rows
        On Error GoTo ExitHandler
        row.Cells(1, paymentCol).value = Me.Controls(row.row & paymentCol).value
    Next row

ExitHandler:
    Exit Sub
End Sub

Private Sub UserForm_Initialize()
    Dim row As Range

    For Each row In ActiveSheet.Rows
        If row.Cells(1, dateCol).value = "" Then
            Exit For
        End If

        Call AddBox(row, dateCol)
        Call AddBox(row, invoiceNumCol)
        Call AddBox(row, amountCol)
        Call AddBox(row, paymentCol)
    Next row
End Sub

Private Sub AddBox(row, colIndex)
    Dim box As Control

    Const width = 50
    Const padWidth = width + 4
    Const height = 15
    Const padHeight = height + 4
    Const topMargin = 25
    Const leftMargin = 5

    Set box = Me.Controls.Add("Forms.TextBox.1", row.row & colIndex)
    box.Left = (colIndex - 1) * padWidth + leftMargin
    box.height = height
    box.width = width
    box.Top = (row.row - 1) * padHeight + topMargin
    box.value = row.Cells(1, colIndex).value
End Sub

表单将如下所示:

值可以输入到付费列,当点击保存按钮时,它们将被复制到电子表格中。

为了解释逻辑,它遍历每个填充的行,创建适当的控件并填充值。在 Save 例程中,再次循环遍历行,并将付款值复制回电子表格。

【讨论】:

  • 嗨 Drew ...感谢您提供此代码。它工作正常,除了两件事:(1)A1、B1 和 C1 包含标题。 (2) 由于我们无法确切知道任何客户会有多少张发票,因此用户表单仅根据其自身的高度显示文本框。换句话说,如果 30 个发票,则 30 个文本框例如日期,如果 58 个发票,则 58 个发票编号文本框。发票的数量是可变的。谢谢
  • 代码将生成与发票行一样多的文本框行 - 阅读您的问题,这似乎就是您要寻找的内容,是吗?至于标头,只需添加一个偏移量,可以通过将Initialize 方法的For 循环的内容与检查包装:If row.row > 1 Then
  • 我不知道如何在此处添加图像,但恐怕文本框的行与发票行不一样。您可以通过添加更多数据(可能是更多行,如 15,35,...等)自己尝试,看看它是否有效,或者可能是,由于用户窗体高度,它们在用户窗体上不可见
  • @StarShines 我认为您必须为您的问题添加更多细节,包括一些代码、可能的屏幕截图和Minimal, Complete, Verifiable Example。祝你好运!
  • 我刚才说用户窗体没有显示所有的文本框,它必须有一个滚动条才能向下,以防我们有很多发票。不过感谢您的帮助:)
【解决方案2】:

假设一个名为“frmMain”的表单,然后添加4个文本框,下面的子程序应该这样做:

Private Sub AddTextBoxes()

Dim ctlTextBox As MSForms.TextBox
Dim intCol, intCols As Integer
Dim strCName As String

' Determine number of columns
intCols = 1
Do While Worksheets("Sheet1").Cells(1, intCols).Value <> ""
    intCols = intCols + 1
Loop

' Add text boxes
For intCol = 1 To intCols - 1
    strCName = "txtC" & intCol
    Set ctlTextBox = frmMain.Controls.Add("Forms.Textbox.1", strCName)

    With ctlTextBox
        .Top = 10
        .Width = 50
        .Height = 20
        .Left = (intCol) * 60
        .Value = intCol
    End With

Next

' Assuming there is a column 1 (i.e. "Invoice Data") the control name will be "txtC1"
' This box can be set by:

frmMain.Controls("txtC1").Value = 999



End Sub

【讨论】:

  • 感谢您抽出宝贵时间,但它给了我一个空白的用户表单。
  • 在窗体上创建一个命令按钮,并在 Private sub CommandButton1 中添加新行 AddTextBoxes。当您单击打开表单中的按钮时,它应该调用子 AddTextBoxes
  • 尊敬的 Reg,我已添加代码。现在,当我运行用户窗体并单击命令按钮时,会出现 3 个文本框并显示诸如 999、2、3 之类的值
  • 可能是我无法正确解释。加载时的用户表单应从工作表 1 中获取数据并将其呈现到文本框中,如我原来的帖子中所述。现在如果有 30 行 3 列的数据,用户表单将创建 90 个带有滚动条的文本框,这些文本框将包含从 Sheet 1、A2 到 C31 的数据
  • 我应该补充说我误读了您的原始帖子(直到我发布后才意识到),因为我的答案基于列数!对不起。也就是说,关键代码是“Set ctlTextBox=...”行。这使您能够向表单添加控件。 With/End With 块中的代码只是格式化文本框。
【解决方案3】:

除上述之外,向 frmMain 添加一个名为“fmeMain”的框架,并为 fmeMain 设置以下属性:

ScrollBars = 2 - fmScrollBarsVertical 滚动高度 = 800

向 frmMain 添加一个名为“cmdTest”的命令按钮。在 frmMain 的代码模块中添加以下子程序:

Private Sub AddTextBoxes()

Dim ctlTextBox As MSForms.TextBox
Dim intCol, intRow, intTop As Integer
Dim strCName As String

intTop = 10

For intRow = 2 To 31        ' Assumes that row 1 contains header

    For intCol = 1 To 3

        strCName = "txtC" & intCol & "R" & intRow
        Set ctlTextBox = frmMain.Controls("fmeMain").Add("Forms.Textbox.1", strCName)

        With ctlTextBox
            .Top = intTop
            .Width = 50
            .Height = 20
            .Left = 52 * intCol
            .Value = Worksheets("Sheet1").Cells(intRow, intCol).Value
        End With


    Next

    intTop = intTop + 25

Next


End Sub



Private Sub cmdTest_Click()

AddTextBoxes

End Sub

【讨论】:

  • 这不应该是一个新答案,而是对您现有答案的更新。
  • 感谢您的努力注册。非常感谢:)
猜你喜欢
  • 1970-01-01
  • 2019-06-25
  • 2012-08-20
  • 2022-01-20
  • 2016-01-20
  • 1970-01-01
  • 1970-01-01
  • 2012-05-21
  • 2017-11-28
相关资源
最近更新 更多