【问题标题】:Excel VBA: Loop through column to identify row for data entryExcel VBA:遍历列以识别数据输入行
【发布时间】:2019-10-03 00:30:36
【问题描述】:

我正在尝试创建一个按日期范围(周)对数据进行排序的表格。我有一个用户表单,它有一个组合框,列出了表中存在的日期范围。从那里,有几个文本框可以输入数字。我的目标是有一个宏循环遍历表中的行并在到达具有相应日期范围的行时停止,然后将文本框中的值添加到该行中的相应单元格。我想我已经设置了循环:

** 更新代码:

Private Sub Submitb_Click()


intLastCol = Sheets("Sheet1").Cells(1, Columns.Count).End(xlToLeft).Column
intLastRow = Sheets("Sheet1").Cells(Rows.Count, 1).End(xlUp).Row
For i = 2 To intLastRow
    If Sheets("Sheet1").Cells(i, 4).Value = ComboBox1.Value Then
        For j = 5 To intLastCol
            Sheets("Sheet1").Cells(i, j).Value = Sheets("Sheet1").Cells(i, j).Value + Controls("Textbox" & 1).Value
        Next j
    End If
Next i

UserForm1.Hide
Call Form_Initialize

End Sub

目前将第一个文本框的值添加到该行中的所有 4 个单元格...关于如何解决这个问题的任何想法?

【问题讨论】:

  • 到目前为止你尝试过什么?到目前为止,你的循环什么也没做......
  • 这篇文章解释了获取列表框值与单元格值,以进行比较。 stackoverflow.com/questions/22836577/… 这篇文章展示了如何将文本框值写入单元格。 stackoverflow.com/questions/19519716/…
  • @MilesFett,到目前为止还不是很多,因为我真的不太了解 VBA(边走边学)。我知道我想转向代码的逻辑,而不是代码。理想情况下,循环将识别哪一行的日期范围与用户表单上选择的日期范围相匹配(组合框从 D2:D6 中提取值)。之后,标记为条目 1-4 的 4 个框将添加到该行中的现有数字中(参见屏幕截图)。我很确定我可以使用大量嵌套的 if 语句来实现这一点,但我正在尝试优化代码/使其干净,因此希望使用循环
  • 好吧,开始尝试,告诉我们您遇到的问题
  • 我在循环中添加了If cell.Value = ComboBox1.Value Then cell.activate。我正在查看使用偏移量来移动一列并一次添加一个值,但我想知道是否有一种方法可以循环它,以便它遍历行中的每一列并向其中添加下一个用户表单条目而不是一大堆行(使用上面的文档作为一个简单的例子,实际的文档在用户表单中有 72 个条目),一次做一个会很痛苦

标签: excel vba


【解决方案1】:

这并不是 Stackoverflow 的真正工作方式,但我会通过一些代码向您推动正确的方向。下一次,试一试,发布你目前的代码,你可能会得到更好的答案/响应。

首先,有不同的方法可以解决这个问题。根据您所说的,您希望它循环,找到匹配的日期,并将该行中的值带入用户表单。我将向您展示您所说的外观。可能有更有效的方法来实现这一点,但我坚持你所描述的。我假设您知道如何使用这些日期填充组合框。

现在,我们只希望在组合框发生更改时触发此事件,因此开始时,我们的 sub 将如下所示:

Private Sub ComboBox1_Change()
'our code will go here
End Sub

现在我们需要添加一些代码来循环遍历您的日期,找到匹配项,然后向下行并获取值。为此,我们将在循环中使用循环。但在我们这样做之前,我们需要定义一些变量以使其动态化,并确保它只在完成工作所需的范围内工作 - 毕竟,我们只想检查该行中包含日期的单元格,而不是该行中的每个单元格。因此,让我们找到其中包含文本的最后一行和最后一列。

intLastCol = Sheets("Sheet1").Cells(2, Columns.Count).End(xlToLeft).Column
intLastRow = Sheets("Sheet1").Cells(Rows.Count, 1).End(xlUp).Row

让我们分解一下。首先,我们描述我们想要查看的工作表——在本例中,它是“Sheet1”。单元格遵循格式(行#、列#)。所以Cells(1, 2) 表示第一行第二列单元格。在这种情况下,我们想找出其中包含文本的最后一列,所以我们说Cells(2, Columns.Count).End(xlToLeft).Column。请注意,我只看第二行,为什么呢?因为您的标题在第一行,我们不在乎那些! intLastRow 遵循相同的格式,但计算包含文本的最后一行。现在我们知道了限制在哪里,是时候创建我们的循环了!

For i = 2 To intLastRow 'start at 2nd row, because we don't want to check the headers row, and only go to the last row of text
    If Sheets("Sheet1").Cells(i, 2).Value = ComboBox1.Value Then 'we are looping down the column, if the text of the value we loop thru matches, then its time for another loop, else continue down the column
        For j = 3 To intLastCol 'starting on the 3rd column, because thats where the data we want is
            Controls("Me.TextBox" & j - 2).Value = Sheets("Sheet1").Cells(i, j).Value 'we go down the row and take the values we see on the sheet and put them in the textbox. Cells(i,j) means i row (where we found the value), and j column (where our values are)
            'Note I do Me.Textbox & j-2, this is because your textboxes are probably named "TextBox1", "TextBox2" etc... but j will only go from 3 to 6... so we take off 2 each time to get to the textbox name
        Next j
    End If
Next i

我在上面的代码中添加了 cmets 来帮助解释我做了什么。但总而言之,它会循环遍历您的日期列中的每个值,如果它与组合框的内容匹配,那么它将循环遍历该行并在那里捕获数据并将其分配给您的文本框。

因此,我们的代码将如下所示:

Private Sub ComboBox1_Change()
    intLastCol = Sheets("Sheet1").Cells(1, Columns.Count).End(xlToLeft).Column
    intLastRow = Sheets("Sheet1").Cells(Rows.Count, 1).End(xlUp).Row

    For i = 2 To intLastRow 
        If Sheets("Sheet1").Cells(i, 2).Value = ComboBox1.Value Then 
            For j = 3 To intLastCol 
                Controls("Me.TextBox" & j - 2).Value = Sheets("Sheet1").Cells(i, j).Value 
            Next j
        End If
    Next i        
End Sub

这将使您大部分时间到达那里。但是,您应该添加错误处理,并命名一些范围。您应该避免在循环中使用硬编码值,例如Cells(i, 2)。如果您曾经添加行或列或更改工作表,Cells(i,2) 不再引用它以前的内容。有大量的在线资源可用于 VBA 并帮助您解决此问题。祝你好运!

【讨论】:

  • 欣赏这个答案的彻底性,但我实际上希望做相反的事情。将文本框中的数据拉到表格中。假设这与您在上面所做的非常相似?
  • 哦,我明白了。那时实际上要容易得多。找到intLastRow,然后循环执行Cells(intLastRow, i + 2).value = Controls("Me.TextBox" & i).value
  • 将使用更新后的代码添加另一个答案,但目前,它将第一个文本框的值插入到行的每个单元格中......关于如何解决这个问题的任何想法?
【解决方案2】:

下面的代码将完成您正在尝试做的事情。

UserForm_Initialize() 宏将在每个日期范围内加载 ComboBox1

Private Sub UserForm_Initialize()
    'uses dynamic range to accommodate for new weeks added to the worksheet
    Me.ComboBox1.RowSource = Sheet1.Range("D2:D" & Sheet1.Range("D" & Sheet1.Rows.Count).End(xlUp).Row).Address

End Sub

CommandButton1_Click() 宏会在 D 列中找到ComboBox1 中选择的日期范围,并将每个TextBox 值写入单元格的右侧,每个TextBox 都有偏移。

Private Sub CommandButton1_Click()
'Define your variables
Dim ws As Worksheet, txbxStr As String, j As Long, i As Long

'Assign your variables
Set ws = ThisWorkbook.Sheets("Sheet1")

    'Loop through the cells in col D
    For j = 2 To Sheet1.Range("D" & Sheet1.Rows.Count).End(xlUp).Row

        'Check if cell value matches ComboBox1's value, if matchs then write the textbox value to the row
        If ws.Cells(j, 4).Value = Me.ComboBox1.Text Then

            'Note; your textboxes must be numbered in sequence, e.g. 1 to 15
            For i = 1 To 15 'Change the second number to the number of textboxes you want to loop through e.g. 72
                txbxStr = Me.Controls("TextBox" & i)
                'Insert each TextBox value in the same row, offsetting 1 cell for each textbox value
                'Note; if your textboxes are numbered 5 to 20, you would have to subtract 4 from i in the line below, e.g. .Offset(, i - 4)
                ws.Cells(j, 4).Offset(, i).Value = txbxStr
            Next i
        End If
    Next j

    'Unload Me 'use if you want to unload the userform
End Sub

【讨论】:

    猜你喜欢
    • 2014-11-27
    • 1970-01-01
    • 2016-07-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多