Excel VBA: цикл по столбцу, чтобы определить строку для ввода данных - PullRequest
0 голосов
/ 01 октября 2019

Я пытаюсь создать таблицу, которая сортирует данные по диапазону дат (недели). У меня есть пользовательская форма, которая имеет поле со списком, в котором перечислены диапазоны дат, которые существуют в таблице. Оттуда есть несколько текстовых полей, в которые я бы вводил числа. Моя цель - создать макрос, который циклически перебирает строки в таблице и останавливается, когда достигает строки с соответствующим диапазоном дат, а затем добавляет значения в текстовых полях в соответствующие ячейки в этой строке. Я думаю, что у меня есть настроенный цикл:

** Обновленный код:

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 ячейкам в строке ... Любые идеио том, как это исправить?

Ответы [ 2 ]

0 голосов
/ 02 октября 2019

Код ниже выполнит то, что вы пытаетесь сделать.

Макрос 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() найдет диапазон дат, выбранный в ComboBox1 в столбце D,и запишите каждое 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
0 голосов
/ 01 октября 2019

Это не совсем то, как работает Stackoverflow, но я дам вам толчок в правильном направлении с помощью некоторого кода. В следующий раз сделайте попытку, опубликуйте код, который у вас есть, и вы, вероятно, получите гораздо лучшие ответы / ответы.

Во-первых, есть разные способы решения этой проблемы. Исходя из того, что вы говорите, вы хотите, чтобы он проходил через цикл, находил соответствующую дату и переносил значения в этой строке в форму пользователя. Я покажу вам, как это будет выглядеть, как вы говорите. Возможно, есть более эффективные способы добиться этого, но я придерживаюсь того, что вы описываете. Я предполагаю, что вы знаете, как заполнить поле со списком этими датами.

Теперь мы хотим, чтобы это событие вызывалось только при изменении этого поля со списком, поэтому для начала наша подпрограмма будет выглядеть так:

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

Давайте разберем это. Сначала мы опишем лист, на который мы хотим посмотреть - в данном случае это «Лист1». Ячейки следуют формату (строка №, столбец №). Так что 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

Я добавил комментарии к приведенному выше коду, чтобы помочь объяснить, что я сделал. Но в итоге он проходит по каждому значению в столбце дат, если он соответствует тому, что имеет поле со списком, то он будет проходить по этой строке, собирать данные и назначать их вашим текстовым полям.

Так что всевместе наш код будет выглядеть примерно так:

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, и в помощь вам. Удачи!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...