Добавить в корзинуПозвонить
Найти в Дзене
Макрос решает

VBA неправильно находит последнюю строку в Excel — причины и безопасные решения

Макрос в Excel не видит последние строки, вставляет данные не туда или пропускает часть таблицы? Разбираем ошибки lastRow в VBA и показываем рабочие способы определения последней строки. Макрос работает. Ошибок нет. Excel не зависает. Код проходит до конца, появляется сообщение «Готово», а на первый взгляд всё выглядит нормально. Но потом ты открываешь результат и видишь странность: часть строк не обработалась, новые данные вставились не в конец таблицы, старые записи оказались перезаписаны, а в отчёте появилась пустая область там, где её быть не должно. И почти всегда где-то рядом стоит одна маленькая строка VBA, которая кажется безобидной: lastRow = Cells(Rows.Count, 1).End(xlUp).Row Эта строка встречается в тысячах макросов. Её копируют из уроков, форумов, чужих файлов и генераторов кода. Она действительно часто работает. Но проблема в слове «часто». В рабочих Excel-файлах «часто» недостаточно. Если макрос обрабатывает отчёт, выгрузку, базу клиентов, складские остатки или финансовую
Оглавление

Макрос в Excel не видит последние строки, вставляет данные не туда или пропускает часть таблицы? Разбираем ошибки lastRow в VBA и показываем рабочие способы определения последней строки.

Макрос перезаписывает данные в Excel — 8 ошибок VBA и безопасное решение

Макрос копирует данные неправильно в Excel — 9 ошибок VBA и решения

Почему макрос в Excel работает медленно — 7 ошибок, которые тормозят VBA

Кнопка «Изменить» неактивна в Excel — 5 причин и точные решения

Макрос не запускается в Excel — 7 причин и решения

Макрос работает. Ошибок нет. Excel не зависает. Код проходит до конца, появляется сообщение «Готово», а на первый взгляд всё выглядит нормально. Но потом ты открываешь результат и видишь странность: часть строк не обработалась, новые данные вставились не в конец таблицы, старые записи оказались перезаписаны, а в отчёте появилась пустая область там, где её быть не должно.

И почти всегда где-то рядом стоит одна маленькая строка VBA, которая кажется безобидной:

lastRow = Cells(Rows.Count, 1).End(xlUp).Row

Эта строка встречается в тысячах макросов. Её копируют из уроков, форумов, чужих файлов и генераторов кода. Она действительно часто работает. Но проблема в слове «часто». В рабочих Excel-файлах «часто» недостаточно. Если макрос обрабатывает отчёт, выгрузку, базу клиентов, складские остатки или финансовую таблицу, неправильная последняя строка может испортить весь результат.

Ошибка с lastRow опасна тем, что она почти никогда не выглядит как ошибка. Excel не пишет: «Я нашёл не ту последнюю строку». Он просто берёт неправильную границу и выполняет код дальше. Если последняя строка определилась выше реального конца таблицы, часть данных останется необработанной. Если ниже — макрос захватит пустоты, старые хвосты или случайные значения. Если по неправильному листу — результат вообще уедет в сторону.

Сегодня разберём, почему VBA неправильно находит последнюю строку, какие способы определения lastRow бывают, где они ломаются и как выбрать безопасный вариант под конкретную таблицу. Это не теоретическая тема. Это основа почти любого нормального макроса: копирования, очистки, переноса, фильтрации, удаления строк, сборки отчётов и автоматического добавления данных.

Почему последняя строка так важна

Последняя строка — это граница, до которой макрос считает таблицу живой. Если эта граница определена неверно, дальше ошибается всё: цикл, копирование, вставка, удаление, поиск, сортировка и проверка результата. Можно написать хороший код, добавить обработку ошибок, отключить ScreenUpdating, ускорить выполнение, но если lastRow неправильный — макрос всё равно будет работать не с тем диапазоном.

Представь обычный отчёт. В нём 12000 строк. Макрос должен пройти по всем строкам, проверить статус, подсветить ошибки и перенести нужные записи на другой лист. Если lastRow определился как 8700, последние 3300 строк просто выпадут из обработки. Никакого предупреждения не будет. Пользователь увидит «Готово» и будет уверен, что всё обработано.

Есть и обратная ситуация. В таблице реально 500 строк, но Excel считает последней строкой 60000, потому что где-то внизу осталось старое форматирование, случайный пробел или давно удалённый блок данных. Макрос начинает идти по пустотам, работает медленно, копирует мусор и может вставить данные далеко ниже реального отчёта. Потом человек открывает файл и не понимает, почему таблица «разорвалась».

Поэтому lastRow — это не техническая мелочь. Это точка входа в данные. Если она выбрана неправильно, весь макрос становится ненадёжным. Хороший VBA-код всегда начинается не с действия, а с правильного определения области, с которой он будет работать.

Ошибка №1. Использовать Cells без указания листа

Самая частая проблема — не сам метод поиска последней строки, а то, что он написан без привязки к конкретному листу. В коде используется Cells, Rows.Count и Range, но нигде не указано, на каком листе всё это должно выполняться. В результате VBA берёт активный лист. А активный лист — это не всегда тот, который нужен.

Пока ты тестируешь макрос вручную, он может работать правильно. Ты открыл лист «Данные», нажал кнопку, lastRow нашёлся верно. Но потом ты переключился на лист «Отчёт», запустил тот же макрос — и последняя строка определилась уже по отчёту. Код пошёл дальше, но работал с неправильной границей. Иногда это приводит к пустому результату, иногда к перезаписи данных, иногда к полному хаосу.

Плохой вариант выглядит так:

Dim lastRow As Long
lastRow = Cells(Rows.Count, 1).End(xlUp).Row

В этом коде не видно, где именно ищется последняя строка. VBA сам решает по активному листу. Для рабочего макроса это слишком опасно. Правильнее сначала явно назначить лист, а потом обращаться к его ячейкам.

Dim ws As Worksheet
Dim lastRow As Long
Set ws = ThisWorkbook.Worksheets("Данные")
lastRow = ws.Cells(ws.Rows.Count, 1).End(xlUp).Row

Теперь макрос не зависит от того, какой лист открыт на экране. Он всегда ищет последнюю строку на листе «Данные». Это простая дисциплина, но она сразу убирает огромный пласт странных ошибок, где «вчера работало, а сегодня нет».

Если макрос работает с несколькими книгами, одного указания листа может быть недостаточно. Тогда нужно явно указывать и книгу. ThisWorkbook — это книга, где хранится макрос. ActiveWorkbook — книга, которая сейчас активна. Если они разные, ошибка может быть неприятной. Особенно когда открыто несколько файлов Excel одновременно.

Ошибка №2. Искать последнюю строку по ненадёжному столбцу

Классическая строка lastRow обычно ищет последнюю заполненную ячейку в первом столбце. Это удобно, если столбец A всегда заполнен. Но в реальных таблицах первый столбец часто бывает не самым надёжным: там могут быть пустые строки, служебные отметки, категории, объединённые ячейки или данные, которые появляются не во всех записях.

Например, в таблице есть 10000 строк. В столбце A указана группа товара, но она заполняется только в первой строке каждого блока. Остальные строки внутри группы пустые. Если искать lastRow по столбцу A, макрос может решить, что таблица закончилась намного раньше. При этом данные в столбцах B, C, D и дальше ещё продолжаются.

Плохой подход — автоматически использовать первый столбец только потому, что так написано в примере:

lastRow = ws.Cells(ws.Rows.Count, 1).End(xlUp).Row

Лучший подход — выбрать опорный столбец. Это столбец, где значение есть в каждой рабочей строке: ID, дата операции, номер документа, артикул, имя клиента, код товара, номер строки. Именно по нему нужно искать последнюю строку.

lastRow = ws.Cells(ws.Rows.Count, "B").End(xlUp).Row

Если в столбце B всегда есть номер документа, такой вариант будет стабильнее. Но важно не просто заменить «1» на «B». Нужно понимать структуру таблицы. Опорный столбец выбирается не на глаз, а по смыслу данных.

Хорошая привычка: перед написанием макроса открыть файл и спросить себя: «В каком столбце пустот быть не должно?» Если такого столбца нет, значит таблица плохо подготовлена для автоматизации. Макрос можно написать и для такой таблицы, но он будет сложнее, потому что придётся искать последнюю строку не по одному столбцу, а по всему листу или по нескольким признакам.

Ошибка №3. Не учитывать формулы, которые возвращают пустую строку

Одна из самых неприятных ситуаций возникает, когда ячейки визуально пустые, но внутри них есть формулы. Например, формула возвращает пустую строку:

=ЕСЛИ(A2="";"";A2)

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

Это часто встречается в шаблонных отчётах, где формулы заранее протянуты на 10000 или 50000 строк. Таблица визуально заканчивается на строке 300, но формулы стоят до строки 20000. Макрос видит формулы и считает, что данные продолжаются. Потом он копирует пустые строки, долго обрабатывает лишний диапазон и вставляет в отчёт огромную пустую область.

В таких случаях нужно решить, что считать последней строкой: последнюю ячейку с формулой или последнюю ячейку с видимым значением. Это разные задачи. Если тебе нужно обработать формулы — один подход. Если только реальные данные — другой.

Можно искать последнюю строку по столбцу, где есть именно значения, а не протянутые формулы. Если такого столбца нет, можно пройти снизу вверх и проверить видимое значение через Value.

Dim i As Long
For i = ws.Rows.Count To 1 Step -1
If Trim(ws.Cells(i, "A").Value) <> "" Then*
lastRow = i*

Exit For*

End If*
Next i

Этот способ медленнее стандартного End(xlUp), если проходить весь лист, но он даёт больше контроля. В реальных макросах можно ограничить поиск разумным диапазоном, например до строки 100000, если ты знаешь, что таблица никогда не бывает больше.

Важный момент: если формула возвращает пустую строку, Trim(cell.Value) будет пустым. То есть такой подход ориентируется на результат формулы, а не на факт её существования. Для отчётов это часто именно то, что нужно.

Ошибка №4. UsedRange кажется удобным, но иногда врёт

UsedRange выглядит как готовое решение. Excel сам знает, какая область используется, значит можно взять последнюю строку из UsedRange и не думать. Но на практике UsedRange часто становится источником странных ошибок. Он учитывает не только текущие данные, но и следы прошлой жизни листа: старое форматирование, удалённые значения, случайные ячейки, которые когда-то редактировали.

Например, пользователь когда-то вставил данные до строки 80000, потом удалил их и оставил таблицу на 500 строк. Визуально лист чистый. Но UsedRange может ещё долго помнить большую область. Макрос считает, что лист используется до 80000 строки, и начинает работать с огромным диапазоном. Файл тормозит, результат расползается, а причина выглядит загадочно.

Проблемный вариант может выглядеть так:

lastRow = ws.UsedRange.Rows(ws.UsedRange.Rows.Count).Row

Он не всегда неправильный. Иногда UsedRange полезен. Но использовать его как универсальный способ определения последней строки опасно. Особенно если файл старый, часто редактируемый или приходит от разных людей.

t.me

Лучше искать последнюю строку по данным, а не по «памяти» листа. Если есть опорный столбец — используем его. Если нет — ищем последнюю заполненную ячейку через Find.

Dim lastCell As Range
Set lastCell = ws.Cells.Find(What:="", After:=ws.Range("A1"), SearchOrder:=xlByRows, SearchDirection:=xlPrevious)*
If Not lastCell Is Nothing Then
lastRow = lastCell.Row*
Else
lastRow = 1*
End If

Метод Find часто надёжнее UsedRange, потому что ищет фактическое содержимое. Но и его нужно понимать. Если где-то далеко внизу осталась случайная заметка, Find найдёт её. Поэтому в идеале рабочая таблица должна быть чистой: без служебных записей под основным диапазоном, без случайных комментариев внизу и без мусора за пределами таблицы.

Ошибка №5. Таблица начинается не с первой строки

Многие макросы написаны так, будто данные всегда начинаются с первой строки, а заголовки находятся в строке 1. В реальных файлах это не всегда так. Над таблицей может быть название отчёта, дата выгрузки, комментарии, фильтры, служебные параметры или пустые строки. Если макрос этого не учитывает, он может неправильно определить и начало, и конец данных.

Допустим, заголовки находятся на строке 5, а данные начинаются со строки 6. Если макрос очищает или копирует диапазон с A2, он заденет служебную область. Если он считает количество строк как lastRow - 1, результат будет неверным. Если он проверяет, есть ли данные ниже заголовка, но заголовок ищет в первой строке, он может решить, что таблица пустая.

В таких случаях нужно явно задавать строку заголовков и первую строку данных.

Dim headerRow As Long
Dim firstDataRow As Long
headerRow = 5
firstDataRow = headerRow + 1

Дальше lastRow ищется обычным способом, но диапазон строится уже от firstDataRow, а не от второй строки по привычке.

Set dataRange = ws.Range(ws.Cells(firstDataRow, 1), ws.Cells(lastRow, lastCol))

Такой подход делает код понятнее. Через месяц ты откроешь макрос и сразу увидишь: таблица начинается не сверху, а после пятой строки. Это лучше, чем разбрасывать по коду магические числа вроде A6, B6, A100000 без объяснения.

Для рабочих файлов особенно полезно хранить такие параметры в начале процедуры: имя листа, строка заголовков, опорный столбец, первый столбец, последний столбец. Тогда макрос легче адаптировать под другой отчёт.

Ошибка №6. Пустые строки внутри таблицы сбивают логику

Стандартный поиск снизу вверх по опорному столбцу не боится пустых строк внутри таблицы, если ниже есть заполненные значения. Но многие макросы дополнительно используют логику «идти до первой пустой строки». Вот она уже опасна. В реальных таблицах пустая строка внутри данных не всегда означает конец таблицы.

Например, выгрузка может содержать пустые строки между блоками. Или пользователь специально оставляет разделители. Или часть данных выгружается группами. Если макрос идёт сверху вниз и останавливается на первой пустой ячейке, он обработает только первый блок.

Проблемная логика выглядит так:

i = 2
Do While ws.Cells(i, 1).Value <> ""
ws.Cells(i, 2).Value = "Проверено"*
i = i + 1*
Loop

Если в столбце A пустая строка встретится на 150-й строке, макрос остановится, даже если после неё есть ещё 10000 строк данных. Иногда такой подход уместен, если таблица гарантированно сплошная. Но для большинства рабочих файлов лучше сначала определить lastRow, а потом идти до него.

For i = 2 To lastRow
If Trim(ws.Cells(i, 1).Value) <> "" Then*
ws.Cells(i, 2).Value = "Проверено"*

End If*
Next i

Теперь пустая строка внутри таблицы не остановит макрос. Он пройдёт весь диапазон до последней строки и обработает только те записи, где есть данные. Это намного безопаснее.

Если пустые строки действительно должны разделять разные таблицы на одном листе, тогда нужно писать отдельную логику поиска блока. Но это уже другая задача. Главное — не путать «пустая строка внутри данных» и «конец таблицы».

Ошибка №7. Последняя строка ищется до очистки или после очистки не в тот момент

Иногда lastRow определяется в правильном месте кода, но в неправильный момент. Например, макрос сначала нашёл последнюю строку на листе назначения, потом очистил часть данных, а затем использует старое значение lastRow. Или наоборот: очистил лист, а потом пытается определить последнюю строку по уже пустому диапазону.

Такие ошибки особенно часто встречаются в макросах обновления отчётов. Сначала код должен понять, что есть в источнике. Потом очистить назначение. Потом вставить данные. Если перепутать порядок, lastRow может относиться не к той таблице или уже устареть.

Неправильная логика может выглядеть так: макрос нашёл lastTargetRow, потом очистил отчёт, потом пытается вставлять данные после старой последней строки. В итоге свежие данные уезжают далеко вниз, а сверху остаётся пустота. Пользователь открывает лист и думает, что макрос ничего не вставил, хотя данные находятся где-то на строке 12000.

Правильная последовательность для обновления отчёта обычно такая: определить источник, проверить, что данные есть, сделать резервную копию, очистить область назначения, вставить данные с первой строки области данных. Для добавления в конец последовательность другая: определить источник, найти последнюю строку назначения, проверить свободную область, вставить ниже.

Это две разные логики. Их нельзя смешивать. Если отчёт обновляется полностью, не нужно искать nextRow в старом отчёте. Если данные добавляются в архив, нельзя очищать старый диапазон. Многие ошибки lastRow появляются именно потому, что сценарий не определён заранее.

Ошибка №8. Не проверять, что lastRow вообще найден

Если лист пустой, стандартный поиск может вернуть первую строку. Это не всегда значит, что там есть данные. Макрос может решить, что таблица существует, и начать копировать заголовки, пустые строки или случайный мусор. Поэтому после определения lastRow нужно проверять, есть ли реальные данные.

t.me

Допустим, на листе «Данные» есть только заголовки в первой строке. Тогда lastRow будет равен 1. Если макрос ожидает данные со второй строки, нужно остановиться и показать сообщение пользователю. Иначе код может построить неправильный диапазон.

If lastRow < 2 Then
MsgBox "На листе нет данных для обработки."*
Exit Sub*
End If

Если таблица начинается ниже, проверка должна учитывать firstDataRow.

If lastRow < firstDataRow Then
MsgBox "Данные не найдены."*
Exit Sub*
End If

Это простая защита, но она делает макрос намного надёжнее. Пользователь получает понятное сообщение вместо странного результата. Хороший макрос не должен молча делать вид, что всё нормально, если данных нет.

Точно так же нужно проверять lastCol, если макрос определяет последний столбец. Если заголовков нет или строка заголовков пустая, lastCol может оказаться неверным. Тогда диапазон данных будет построен неправильно.

Надёжный шаблон определения последней строки по опорному столбцу

Теперь соберём рабочий вариант для самой частой ситуации: есть нормальная таблица, у неё есть строка заголовков и опорный столбец, где данные заполнены всегда. Такой способ быстрее и проще, чем универсальные поиски по всему листу.

Sub FindLastRowByKeyColumn()
Dim ws As Worksheet*
Dim lastRow As Long*
Dim headerRow As Long*
Dim firstDataRow As Long*
Dim keyColumn As String*
Set ws = ThisWorkbook.Worksheets("Данные")*
headerRow = 1*
firstDataRow = headerRow + 1*
keyColumn = "A"*
lastRow = ws.Cells(ws.Rows.Count, keyColumn).End(xlUp).Row*
If lastRow < firstDataRow Then*
MsgBox "Данные не найдены."*

Exit Sub*

End If*
MsgBox "Последняя строка данных: " & lastRow*
End Sub

Этот шаблон хорош тем, что его легко читать. Сразу видно, где лист, где заголовок, где первая строка данных и по какому столбцу определяется конец таблицы. Если структура файла изменится, не нужно искать по всему коду, где спрятана цифра 2 или столбец A. Всё находится в начале.

Но этот способ подходит только тогда, когда keyColumn действительно надёжный. Если в нём бывают пустоты, нужно либо выбрать другой столбец, либо использовать более универсальный подход.

Универсальный шаблон поиска последней строки по всему листу

Если таблица устроена хаотично и нет одного надёжного столбца, можно искать последнюю заполненную ячейку по всему листу. Это полезно для выгрузок, где данные могут появляться в разных столбцах, а первый столбец не гарантирован.

Sub FindLastRowOnSheet()
Dim ws As Worksheet*
Dim lastCell As Range*
Dim lastRow As Long*
Set ws = ThisWorkbook.Worksheets("Данные")*
Set lastCell = ws.Cells.Find(What:="
", After:=ws.Range("A1"), LookIn:=xlValues, SearchOrder:=xlByRows, SearchDirection:=xlPrevious)
If lastCell Is Nothing Then*
MsgBox "Лист пустой."*

Exit Sub*

End If*
lastRow = lastCell.Row*
MsgBox "Последняя строка на листе: " & lastRow*
End Sub

Здесь важно обратить внимание на LookIn:=xlValues. Такой поиск ориентируется на значения, которые видит пользователь. Если нужно искать формулы как объекты, можно использовать xlFormulas. Выбор зависит от задачи. Для отчётов чаще важны именно видимые значения, потому что формулы, возвращающие пустоту, не должны раздувать диапазон.

Этот вариант не идеален, если на листе есть служебные заметки далеко ниже таблицы. Поэтому лучше не превращать рабочий лист в склад всего подряд. Таблица должна быть таблицей. Служебные примечания лучше хранить на отдельном листе или выше, но не внизу под данными.

Шаблон для безопасной обработки таблицы до последней строки

Теперь пример практического макроса. Он определяет последнюю строку по опорному столбцу, проверяет наличие данных, проходит по таблице и ставит отметку «Проверено» в соседнем столбце. Это базовая логика, которую можно адаптировать под очистку, перенос, подсветку ошибок или расчёты.

Sub ProcessDataSafely()
Dim ws As Worksheet*
Dim lastRow As Long*
Dim i As Long*
Dim headerRow As Long*
Dim firstDataRow As Long*
On Error GoTo ErrHandler*
Application.ScreenUpdating = False*
Application.EnableEvents = False*
Application.Calculation = xlCalculationManual*
Set ws = ThisWorkbook.Worksheets("Данные")*
headerRow = 1*
firstDataRow = headerRow + 1*
lastRow = ws.Cells(ws.Rows.Count, "A").End(xlUp).Row*
If lastRow < firstDataRow Then*
MsgBox "Нет данных для обработки."*

GoTo SafeExit*

End If*
For i = firstDataRow To lastRow*
If Trim(ws.Cells(i, "A").Value) <> "" Then*

ws.Cells(i, "B").Value = "Проверено"*

End If*

Next i*
MsgBox "Обработка завершена. Строк обработано: " & lastRow - firstDataRow + 1*
SafeExit:
Application.ScreenUpdating = True*
Application.EnableEvents = True*
Application.Calculation = xlCalculationAutomatic*
Exit Sub*
ErrHandler:
MsgBox "Ошибка: " & Err.Description*
Resume SafeExit*
End Sub

В этом коде важны не только lastRow, но и вся обвязка. Отключается обновление экрана, события и пересчёт. В конце всё возвращается обратно даже при ошибке. Есть проверка на отсутствие данных. Есть явный лист. Есть первая строка данных. Это уже не случайный макрос, а нормальный рабочий шаблон.

Если ты используешь такие заготовки постоянно, ошибки становятся реже. Не потому что VBA стал «умнее», а потому что структура кода больше не оставляет места для догадок.

Как понять, что lastRow выбран правильно

После запуска макроса не нужно просто верить сообщению «Готово». Нужно проверить несколько признаков. Первый — последняя обработанная строка должна совпадать с реальным концом таблицы. Второй — данные ниже таблицы не должны участвовать в обработке. Третий — пустые строки внутри таблицы не должны останавливать макрос, если они допустимы. Четвёртый — формулы, возвращающие пустоту, не должны раздувать диапазон, если тебе нужны только реальные значения.

Самый простой способ проверки — временно вывести найденную строку в сообщение.

MsgBox "lastRow = " & lastRow

Ещё лучше — подсветить найденную последнюю строку во время теста.

ws.Rows(lastRow).Interior.Color = RGB(255, 255, 0)

После проверки такую подсветку лучше убрать из рабочего макроса, чтобы не портить оформление. Но на этапе отладки это очень полезно: ты сразу видишь, где VBA считает конец таблицы.

Если lastRow постоянно определяется неверно, не нужно лечить симптомы. Нужно пересмотреть структуру данных. Возможно, выбран плохой опорный столбец. Возможно, внизу есть мусор. Возможно, формулы протянуты слишком далеко. Возможно, таблица начинается не там, где код ожидает. В таких случаях проблема не в одной строке VBA, а в несоответствии кода и реальной структуры файла.

Что использовать в реальной работе

Если таблица нормальная и есть обязательный столбец — используй поиск по опорному столбцу через End(xlUp). Это быстро, понятно и достаточно надёжно. Если таблица хаотичная и данные могут быть в разных столбцах — используй Find по всему листу. Если важно игнорировать формулы, возвращающие пустоту, используй LookIn:=xlValues или отдельную проверку видимых значений.

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

В Телеграме я выкладываю готовые файлы и шаблоны VBA, которые можно использовать без ручной сборки:

безопасное определение последней строки, перенос данных без перезаписи, обработка таблиц без пропуска строк, проверка диапазонов и защита от типовых ошибок.

Если хочешь забирать именно рабочие инструменты, а не только читать разборы, подписывайся.

Итог

Неправильная последняя строка — одна из самых частых причин, почему макросы в Excel работают «почти правильно». Они не падают, не ругаются и не всегда выглядят сломанными. Они просто обрабатывают не весь диапазон, вставляют данные не туда или захватывают лишние строки.

Чтобы этого не происходило, lastRow нужно определять осознанно. Всегда указывать лист. Выбирать надёжный опорный столбец. Проверять, есть ли реальные данные. Учитывать формулы, пустые строки и структуру таблицы. Разделять сценарии добавления и обновления отчёта.

Excel выполняет код буквально. Если ты дал ему неправильную границу, он не догадается, где настоящая таблица. Поэтому задача хорошего VBA-кода — не надеяться на удачу, а точно объяснить Excel, где начинаются и где заканчиваются данные.

Готовые VBA-шаблоны по lastRow, сценарии применения, проверки, ошибки и мини-инструкция «вставил → работает»

Скачать

t.me

Макрос перезаписывает данные в Excel — 8 ошибок VBA и безопасное решение

Макрос копирует данные неправильно в Excel — 9 ошибок VBA и решения

Почему макрос в Excel работает медленно — 7 ошибок, которые тормозят VBA

Кнопка «Изменить» неактивна в Excel — 5 причин и точные решения

Макрос не запускается в Excel — 7 причин и решения