#vba #excel #loops
#vba #excel #циклы
Вопрос:
Я переформатировал диапазон Sheets("Records")
в рабочей книге как a Table (named "RecordsTable")
, чтобы упростить выполнение INDEX(MATCH,MATCH)
функций для создания отчетов…. но теперь я испортил свою процедуру цикла для заполнения этого диапазона с момента ввода Sheets("FORM")
.
Раньше это было:
Set r = Sheets("Records").Range(A amp; Rows.Count).End(x1Up).Offset(1, 0)
i = 0
For Each c In Range("dataRange")
'dataRange is a list of cells to reference from the FORM input sheet
r.Offset(0, i).Value = Worksheets("FORM").Range(c)
i = i 1
Next
Однако этот код теперь выбирает первую строку в КОНЦЕ "RecordsTable"
(строка 501, поскольку я определил 500 строк в моей таблице) и вставляет туда данные.
Я попытался изменить его на это:
Set r = Sheets("Records").ListObjects("RecordsTable").DataBodyRange("A" amp; Rows.Count).End(x1Up).Offset(1, 0)
i = 0
For Each c In Range("dataRange")
r.Offset(0, i).Value = Worksheets("FORM").Range(c)
i = i 1
Next
Но этот код по-прежнему выбирает строку 501 и делает эту строку частью "RecordsTable"
.
Как я могу правильно Set "r" to =
использовать первую пустую строку в "RecordsTable"
?
Для справки, Column "A" in "RecordsTable"
имеет заголовок [INV #]
. Кроме того, когда я перехожу в "Set r = ..."
строку, Rows.Count
возвращается значение более 1 миллиона (т. Е. Общее количество строк на листе) — если я правильно понимаю, я хочу, чтобы оно возвращало значение 500 (т. Е. Общее количество строк в таблице) — это правильно?
Редактировать
"dataRange"
это список ссылок на ячейки с одним столбцом (у меня они помечены в столбце B, как предлагает @chrisneilsen:
A
J6
Y6
J8
J10
Y8
и т.д.
Это ячейки Sheets("FORM")
, из которых мне нужно извлекать данные и заполнять их в моей таблице в порядке, указанном в "dataRange"
.
Комментарии:
1. Очень быстрое предложение: посмотрите, как вы разместили рабочий лист перед использованием
ListObjects
? Делайте это каждый раз, когда вы используетеRange()
,Cells()
, и т.д.Rows.Count
Это подскажет VBA, с какого листа получать эту информацию. В противном случае он используетActiveSheet
, и это может привести к неожиданным результатам.2. @BruceWayne ^^ Спасибо
Ответ №1:
Предполагая, что у вас действительно есть таблица, добавьте данные в таблицу (ListObject), используя ее свойства и методы:
Sub Demo()
Dim lo As ListObject
Dim c As Range
Set lo = Worksheets("Records").ListObjects("RecordsTable")
For Each c In Sheets("V").Range("dataRange")
If Not lo.InsertRowRange Is Nothing Then
lo.InsertRowRange.Cells(1, 1) = Sheets("FORM").Range(c)
Else
lo.ListRows.Add.Range.Cells(1, 1) = Sheets("FORM").Range(c)
End If
Next
End Sub
Примечание: зацикливание диапазона на листе V
и использование его в качестве указателя на данные на листе FORM
, скопированные из вашего ответа — я предполагаю, что вы знаете, что вы здесь делаете
На основе комментария OP, добавление данных в одну новую строку
Sub Demo()
Dim lo As ListObject
Dim c As Range, TableRange As Range
Dim i As Long
Set lo = Worksheetsheets("Records").ListObjects("RecordsTable")
If Not lo.InsertRowRange Is Nothing Then
Set TableRange = lo.InsertRowRange
Else
Set TableRange = lo.ListRows.Add.Range
End If
i = 1
For Each c In Sheets("V").Range("dataRange")
TableRange.Cells(1, i) = Sheets("FORM").Range(c)
i = i 1
Next
End Sub
Обратите внимание, это предполагает, что порядок столбцов таблицы совпадает с порядком dataRange
. Возможно, было бы лучше включить имена полей таблицы dataRange
, чтобы избежать проблем с несоответствием
Как упоминалось в обновленном OP, если метки столбцов находятся в следующем столбце, замените For
цикл этим (и добавьте Dim r as Range, col as long
в объявления)
For Each c In Sheets("V").Range("dataRange")
If Not c = vbNullString Then
Set r = Worksheets("FORM").Range(c.Value)
col = lo.ListColumns(c.Offset(, 1).Value).Index
TableRange.Cells(1, col) = r.Value
End If
Next
Комментарии:
1. Спасибо. Я попытался использовать это, и он правильно добавляет строку в таблицу и начинает ввод данных в первом столбце, но последующие итерации продолжают добавлять данные в первый столбец, следующую доступную строку. У меня определено 40 ячеек
dataRange
, и мне нужно, чтобы каждая из них переходила в следующий столбец после предыдущего.2. Хорошо, это новая информация. Итак, вы хотите добавить только одну новую строку и вставить все данные в эту строку? См . Обновление
3. Спасибо, Крис. Я пытался решить это с тех пор, как вы опубликовали, и это обновление помогает. Тем не менее, он по-прежнему выдает мне «ошибку, определяемую приложением или объектом»
TableRange.Cells(1, i) = Sheets("FORM").Range(c)
.4. Основываясь на вашем коде
= Sheets("FORM").Range(c)
, я предполагаюdataRange
, что это список адресов на листеFROM
. Это правильно? Если значениеc
не является допустимым адресом (напримерC10') that will cause an error. can you post (edit your Q) some sample data for both
, recordsTable` иdataRange
5. Вопрос обновлен, как и было запрошено. Надеюсь, это то, что вы искали.