Итак, у меня есть эта форма счета-фактуры, которая выглядит так на листе Invoice_Form книги Excel InvoiceForm.xlsm:
и база данных счетов-фактур в Листе Invoice Database книги Excel InvoiceDatabase.xlsm:

Я создал коды VBA, которые могут связывать записи из формы с базой данных счетов, но то, что код успевает сделать прямо сейчас, - это запись только первой строки формы счета:

Код выглядит так:
Sub Submit_Invoice()
Dim LastRow As Long, ws As Worksheet
Set ws = Sheets("InvoiceDatabase")
LastRow = ws.Range("I" & Rows.Count).End(xlUp).Row + 1
ws.Range("K" & LastRow).Value = Worksheets("Invoice Form").Range("C9:C16").Value
ws.Range("L" & LastRow).Value = Worksheets("Invoice Form").Range("D9:D16").Value
....
End Sub
Итак, возникает вопрос: как мне изменить свой код, чтобы он мог создавать несколько записей в разных строках на основе этой формы, если в форму счета-фактуры добавлены дополнительные продукты?
Спасибо!
Да, я использую Excel 2016, но в этом случае я не могу использовать форму ввода данных. В любом случае я уже изменил код, так как D5 и D6 здесь не проблема, спасибо, что указали на это!





Создайте массив из формы и выгрузите массив в InvoiceDatabase.
Sub Submit_Invoice()
Dim lr As Long, ws As Worksheet
dim arr as variant, i as long
with Worksheets("Invoice Form")
lr = .cells(16, "C").end(xlup).row - 8
redim arr(1 to lr, 1 to 6)
for i=lbound(arr,1) to ubound(arr, 1)
arr(i, 1) = .cells(5, "D").value
arr(i, 2) = .cells(6, "D").value
arr(i, 3) = .cells(i+8, "C").value
arr(i, 4) = .cells(i+8, "D").value
arr(i, 5) = .cells(i+8, "E").value
arr(i, 6) = .cells(i+8, "F").value
next i
end with
WITH WORKSheets("InvoiceDatabase")
lr = .Range("I" & .Rows.Count).End(xlUp).Row + 1
.cells(lr, "I").resize(ubound(arr, 1), ubound(arr, 2)) = arr
end with
End Sub
Привет, Jeeped, спасибо за ответ. К сожалению, код не работает, здесь отображается сообщение об ошибке «Подстрочный индекс диапазона». Вы хоть представляете, почему это происходит? Еще раз спасибо.
Да ладно, вина здесь на моей стороне. Это чудо! но как мне заставить его работать, если листы находятся в разных книгах? Спасибо еще раз за помощь!
Для рабочих листов потребуются родительские ссылки книги.
Моя книга для формы счета-фактуры будет Invoice_Form.xlsm, а база данных счетов - Invoice_Database.xlsm. Как включить эти ссылки в приведенный выше код? Спасибо!
Нравится with Workbooks("Invoice_Form.xlsm").Worksheets("Invoice Form")
Намного разумнее.
Привет, @Jeeped, я пытаюсь понять ваш код, но не могу понять, как вы получаете числа 16 и -8 здесь, в этой строке кода выше: lr = .cells (16, "C"). End (xlup ) .row - 8. Не могли бы вы подробнее рассказать об этом коде? Спасибо.
C16 содержит примечания: поэтому вы начинаете с него вместо Rows.Count и смотрите вверх, чтобы увидеть заполненную строку счета-фактуры. Это похоже на выбор Notes: и нажатие ctrl + стрелка вверх. -8 означает, что строка 9 должна считаться 1.
Я понял, большое спасибо Jeeped! Ты палочка-выручалочка! Хорошего дня :))
Для этого вам действительно следует использовать базу данных формы / доступа или форму данных Excel (2016).
Тем не менее, ваш код перезаписывает каждую строку при записи на другой лист, поскольку она не увеличивается. Кроме того, вам не хватает того, как добавлять даты и номера счетов.
Далее используются более значимые имена и добавляются отсутствующие данные, а также некоторые основные проверки ошибок (например, есть данные для передачи) и служебные операции с точки зрения очистки формы после передачи.
Option Explicit
Public Sub Submit_Invoice()
Dim nextRowDest As Long, lastRowSource As Long, wsDest As Worksheet, wsSource As Worksheet, transferData As Range
Dim invoiceInfo As Range
Application.ScreenUpdating = False
Set wsDest = ThisWorkbook.Worksheets("InvoiceDatabase")
Set wsSource = Workbooks("Invoice_Form.xlsm").Worksheets("Invoice Form")
With wsSource
lastRowSource = wsSource.Range("C" & .Rows.Count).End(xlUp).Row
If lastRowSource < 9 Then Exit Sub '<==No data
Set transferData = .Range("C9:G" & lastRowSource)
Set invoiceInfo = .Range("D5:D6")
End With
With wsDest
nextRowDest = wsDest.Range("I" & Rows.Count).End(xlUp).Row + 1
If nextRowDest < 4 Then Exit Sub '<==Assume headers are in row 3
transferData.Copy .Range("K" & nextRowDest)
invoiceInfo.Copy
.Range("I" & nextRowDest).Resize(transferData.Rows.Count, invoiceInfo.Rows.Count).PasteSpecial Transpose:=True
End With
transferData.ClearContents
invoiceInfo.ClearContents
Application.ScreenUpdating = True
End Sub
Привет, Карр, очень признателен за вашу помощь. Я новичок в VBA и понятия не имел, что решение может быть таким сложным. Примем к сведению ваши предложения и дальнейшие ссылки. Однако мне понадобится время, чтобы изучить ваш код :)) Спасибо и удачного дня!
Не проблема. Если вам нужны какие-либо объяснения, просто спросите, я буду рад помочь.
Вы используете Excel 2016? Вы можете просто использовать встроенные формы ввода данных. Кроме того, как передаются D5 и D6?