Vba 根据行数自动创建文本框

Vba 根据行数自动创建文本框,vba,excel,textbox,userform,Vba,Excel,Textbox,Userform,VBA Excel Userform中是否有方法根据特定工作表上的行数自动在Userform上创建文本框 我的数据在表1中,从A1开始,为: A1:发票日期 B1:发票号 C1:发票金额 D1:已收到付款 现在有许多行数据(发票),人们无法知道有多少行与特定客户相关。当用户表单加载时,收到的付款文本框将为空,而发票日期、发票号和发票金额将取自第1页 然后,填写“收到的付款”文本框将非常容易。付款可应用于特定发票。假设一个名为“frmMain”的表单,然后添加4个文本框,以下子程序应执行此操作

VBA Excel Userform中是否有方法根据特定工作表上的行数自动在Userform上创建文本框

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

  • A1:发票日期
  • B1:发票号
  • C1:发票金额
  • D1:已收到付款
现在有许多行数据(发票),人们无法知道有多少行与特定客户相关。当用户表单加载时,收到的付款文本框将为空,而发票日期、发票号和发票金额将取自第1页

然后,填写“收到的付款”文本框将非常容易。付款可应用于特定发票。

假设一个名为“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子addTextBox()
将文本框设置为MSForms.TextBox
Dim intCol,intCol为整数
将strCName设置为字符串
'确定列数
intCols=1
Do While工作表(“Sheet1”)。单元格(1,intCols)。值“”
intCols=intCols+1
环
'添加文本框
对于intCol=1到intCols-1
strCName=“txtC”&intCol
Set ctlTextBox=frmMain.Controls.Add(“Forms.Textbox.1”,strCName)
使用ctlTextBox
.Top=10
.宽度=50
.高度=20
.左=(整数)*60
.Value=intCol
以
下一个
'假设有第1列(即“发票数据”),控件名称将为“txtC1”
'此框可通过以下方式设置:
frmMain.控件(“txtC1”)。值=999
端接头

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

滚动条=2-FmScrollBars垂直 滚动高度=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

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

可以将单击处理程序添加到“显示表单”按钮:

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
该表单将如下所示:

可以在“已付款”列中输入值,单击“保存”按钮时,这些值将复制到电子表格中


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

您的问题的答案是肯定的-有一种方法。您没有问如何,但一个简单的答案是找到相关行的数量,然后让VBA在加载userform时添加该数量的行。如何?当然,我从“如何做”的角度提出了这个问题。谢谢你试过什么@StarShires?斯科特,我不是一个成熟的软件开发人员或程序员。我是一名会计,为了学习,我在这里发布了一个通用问题。我想知道为什么这里的每个人都不遵循你解决问题的智慧。顺便说一句,你的好意很好。谢谢你花时间,但它给了我一个空白的用户表单。在表单上创建一个命令按钮,并在私有子命令按钮1中添加新行addTextBox。当您在打开的表单中单击按钮时,它应该调用子AddTextBoxesDear Reg,我已经添加了代码。现在,当我运行userform并单击命令按钮时,会出现3个文本框,显示999、2、3等值,这可能是我无法正确解释的。加载时的userform应该从表1中获取数据,并将其显示在文本框中,如我在原始帖子中所解释的。现在,如果有30行数据和3列,用户表单将创建90个带有滚动条的文本框,这些文本框将包含从表1、A2到C31I的数据。我应该补充一点,我误读了你的原始帖子(直到我发布后才意识到),因为我是根据列数回答的!很抱歉也就是说,关键代码是“Set ctlTextBox=…”行。这使您能够将控件添加到表单中。With/End With块中的代码只是格式化文本框。这不应该是新答案,而是对现有答案的更新。感谢您的努力。非常感谢:)嗨,德鲁…谢谢你的代码。它工作正常,除了两件事:(1)A1、B1和C1包含标题。(2) 由于我们无法确切知道任何客户的发票数量,userform仅根据其自身高度显示文本框。换句话说,如果是30张发票,则是30个文本框(例如日期),如果是58张发票,则是58个文本框(发票编号)。发票的数量是可变的。感谢代码将生成与发票行一样多的文本框行-阅读您的问题,这似乎就是您要寻找的,是吗?至于标题,只需添加一个偏移量,这可以通过将
Initialize
方法的
for
循环的内容包装成一个复选框来完成:
如果row.row>1,那么
我不知道如何在这里添加图像,但我担心文本框的行与发票行不同。您可以通过添加更多的数据(可能是更多的行,如15、35等)自己尝试一下,看看它是否有效,或者可能由于userform的原因,它们在userform上不可见height@StarShines我想你必须在你的问题中添加更多细节,包括一些代码,可能的截图,和一个简单的例子。祝你好运!我刚才说userform并没有显示所有的文本框,它必须有一个滚动条,以防我们有很多发票。谢谢你的帮助:)