#excel #vba #slowdown
#excel #vba #замедление
Вопрос:
Я пытаюсь скопировать данные с отображаемого листа в соответствующий потребитель # в листе счетов, содержащий (176000) строк, следующий код, который я нашел, работает, но он очень медленный, для выполнения одной записи требуется около 5 минут.
Sub SAVERECOVERY()
For i = 5 To 125
If Cells(i, 20) > 0 Then
Sheets("Bills").Cells(Cells(i, 20), 24) = Sheets("Display").Cells(i, 5)
Sheets("Bills").Cells(Cells(i, 20), 25) = Sheets("Display").Cells(i, 7)
Sheets("Bills").Cells(Cells(i, 20), 26) = Sheets("Display").Cells(i, 9)
Sheets("Bills").Cells(Cells(i, 20), 27) = Sheets("Display").Cells(i, 11)
End If
Next
End Sub
Комментарии:
1. Для передачи больших объемов данных используйте массив, создайте массив со всеми необходимыми данными, а затем вставьте сразу (таким образом, вы работаете с Excel только 2 или 3 раза вместо 176k)
2. Но вы не добавляете данные, вы изменяете их, как я вижу в коде, вы проверяете, больше ли ячейки в столбце 20 0, если да, то вы меняете ту же строку из счетов, что и на дисплее? Это ваша цель?
3. да, дорогая, это именно то, что я хочу сделать, у меня около 175000 строк в счетах, где доступны данные счетов потребителей, и теперь мне нужно изменить один сегмент счета потребителя, для которого я разработал таблицу отображения,
4. Но давайте предположим, что у одного потребителя есть 3 отдельные строки данных. На вашем листе отображения у этого потребителя также есть 3 строки данных или только одна? Потому что, если это позже, вы даете ему только последнюю запись из листа счетов.
5. уважаемый, на листе отображения отображается только один потребитель с ежемесячными счетами одного и того же потребителя за 2012 год, содержащими около 125 строк данных, поэтому теперь я редактирую эти счета на листе отображения и хочу, чтобы отредактированные данные были сохранены в листе счетов против уже существующих данных того же потребителя.
Ответ №1:
Попробуйте следующий код, пожалуйста. Это должно быть очень быстро. Необходимо только задать строки, в которые будут копироваться диапазоны ( firstRow
, lastRow
), и позаботиться о том, чтобы в столбце 20 были (последовательные) строки, в которые будет вставлен результат обработки. Фактически, было бы достаточно записать только первую строку:
Sub SAVERECOVERY()
Dim firstRow As Long, lastRow As Long, shB As Worksheet, shD As Worksheet
Dim arr24 As Variant, arr25 As Variant, arr26 As Variant, arr27 As Variant
Dim pasteRow As Long, i As Long, arrRows As Variant
Set shB = Sheets("Bills")
Set shD = Sheets("Display")
firstRow = 5: lastRow = 125: pasteRow = CLng(shD.cells(firstRow, 20))
arr24 = shD.Range(shD.cells(firstRow, 5), shD.cells(lastRow, 5)).value
arr25 = shD.Range(shD.cells(firstRow, 7), shD.cells(lastRow, 7)).value
arr26 = shD.Range(shD.cells(firstRow, 9), shD.cells(lastRow, 9)).value
arr27 = shD.Range(shD.cells(firstRow, 11), shD.cells(lastRow, 11)).value
arrRows = shD.Range(shD.cells(firstRow, 20), shD.cells(lastRow, 20)).value
Application.Calculation = xlCalculationManual
For i = 1 To UBound(arrRows)
If arr24(i, 1) <> "" Then shB.cells(CLng(arrRows(i, 1)), 24).value = arr24(i, 1)
If arr25(i, 1) <> "" Then shB.cells(CLng(arrRows(i, 1)), 25).value = arr25(i, 1)
If arr26(i, 1) <> "" Then shB.cells(CLng(arrRows(i, 1)), 26).value = arr26(i, 1)
If arr27(i, 1) <> "" Then shB.cells(CLng(arrRows(i, 1)), 27).value = arr27(i, 1)
Next i
Application.Calculation = xlCalculationAutomatic
shB.Activate: shB.cells(pasteRow, 24).Select
MsgBox "Ready..."
End Sub
Комментарии:
1. спасибо, дорогой, это работает, но единственная проблема в том, что он должен копировать только данные в заполненные ячейки, например, если ячейки от b4 до b134 на листе отображения имеют пустые ячейки, он не должен копировать данные из этого столбца строк 5,7,9,11. но ваш код копирует значения там, где этого не должно быть. я прикрепил новые изображения, пожалуйста, проверьте и заранее спасибо, короче говоря, как в вашем коде, последняя строка должна быть пустой строкой на листах отображения с b5 по b130.
2. @rohail nisar: Хорошо. Сейчас нет времени смотреть на код. Я сделаю это примерно через два часа… Но перед этим вы должны прояснить некоторые аспекты: Если нам нужно обработать 125 строк, как в вашем вопросе, и только 5 таких строк не являются пустыми, будут ли вставлены только они? Я имею в виду, что промежуточные строки на листе «Счета» уже содержат данные и не должны быть перезаписаны? Тогда возможно ли, чтобы в одном столбце (из 5, 7, 9, 11) строка не была пустой, а в других столбцах была пустой? Я имею в виду, что для обработки всех столбцов будет достаточно одной проверки на пустоту или нет?
3. @rohail nisar: Попробуйте обновленный код, пожалуйста. Он проверит каждый столбец на наличие пустых ячеек и скопирует только непустые. Пожалуйста, также отправьте отзыв. Я не проверял это, но это должно сработать. Я должен на некоторое время покинуть офис. Если это будет работать так, как вам нужно, мы здесь голосуем за код ответа и, что более важно, мы устанавливаем флажок слева от кода, чтобы сделать его принятым ответом . Таким образом, кто-то другой, ищущий что-то подобное, будет знать, что код работает…