Разработка и Конфигурация · 10 мин
Как получить последнюю строку табличной части в 1С
Способы получить последнюю строку табличной части в 1С: Количество()-1, индексы, циклы, запросы. Примеры кода, проверка пустой таблицы, типичные ошибки.
Задача получить последнюю строку табличной части возникает постоянно: при подборе последнего номера строки, при проверке введённых данных, при программном добавлении товаров в документ и при расчёте итогов. Встроенный язык 1С не содержит отдельного метода «ПоследняяСтрока», поэтому разработчики используют обращение по индексу через метод Количество().
Ключевой момент, который нужно помнить: коллекция строк табличной части индексируется с нуля. Это значит, что последняя строка имеет индекс Количество() - 1, а не Количество(). Попытка обратиться по индексу, равному количеству строк, приведёт к ошибке «Индекс находится за границами массива».
Вторая частая ловушка — пустая табличная часть. Если строк нет вообще, обращение по индексу -1 также вызовет ошибку времени выполнения. Поэтому корректный код всегда начинается с проверки, что табличная часть не пуста. Ниже разобраны все рабочие способы: прямой доступ по индексу, получение через цикл, работа с выборкой запроса и особенности управляемых форм.
Базовый способ: обращение по индексу
Самый быстрый и распространённый вариант — взять количество строк и вычесть единицу. Метод Количество() возвращает число строк в табличной части, а оператор квадратных скобок позволяет обратиться к строке по индексу.
Товары = Объект.Товары;
Если Товары.Количество() > 0 Тогда
ПоследняяСтрока = Товары[Товары.Количество() - 1];
Сообщить("Последняя номенклатура: " + ПоследняяСтрока.Номенклатура);
Иначе
Сообщить("Табличная часть пуста");
КонецЕсли;
Такой код работает и на сервере, и на клиенте, и в модуле объекта, и в модуле формы. Возвращаемое значение — объект типа, соответствующего строке табличной части (например, ДокументТабличнаяЧастьСтрока), через точку доступны все реквизиты строки.
Обратите внимание: переменная ПоследняяСтрока содержит ссылку на реальную строку коллекции, а не её копию. Если вы измените реквизиты этой строки, изменения отразятся в документе. Это удобно, когда последнюю строку нужно не только прочитать, но и скорректировать.
ПоследняяСтрока = Объект.Товары[Объект.Товары.Количество() - 1];Проверка на пустую табличную часть
Единственная ситуация, когда обращение к последней строке ломается, — отсутствие строк. Проверка Количество() > 0 обязательна в любом коде, который может выполняться для нового или незаполненного документа.
Есть альтернативный стиль — проверка через Если Товары.Количество() = 0 Тогда Возврат; в начале процедуры. Такой приём «раннего выхода» делает основной код чище, особенно когда после проверки идёт длинная логика обработки.
Не используйте конструкцию Попытка ... Исключение как замену проверки. Обработка исключений медленнее, скрывает реальные проблемы и считается плохим тоном в типовых механизмах 1С. Явная проверка количества строк читается легче и работает предсказуемо.
Получение последней строки через цикл
Если по какой-то причине прямой индекс недоступен или нужно одновременно проанализировать все строки, последнюю строку можно получить в цикле. После завершения обхода переменная цикла будет указывать на последний элемент коллекции.
ПоследняяСтрока = Неопределено;
Для Каждого СтрокаТовары Из Объект.Товары Цикл
// обработка каждой строки
ПоследняяСтрока = СтрокаТовары;
КонецЦикла;
Если ПоследняяСтрока <> Неопределено Тогда
// работаем с последней строкой
КонецЕсли;
Этот способ медленнее прямого обращения по индексу, потому что перебирает всю коллекцию. Он оправдан только когда цикл нужен по другой логике — например, вы ищете последнюю строку, удовлетворяющую условию, а не просто последнюю по порядку.
Последняя строка, подходящая под условие
Частая практическая задача — найти не просто последнюю строку, а последнюю строку с определённым товаром, складом или признаком. Здесь прямой индекс не поможет, нужен цикл с запоминанием найденной строки:
НайденнаяСтрока = Неопределено;
Для Каждого СтрокаТовары Из Объект.Товары Цикл
Если СтрокаТовары.Номенклатура = ИскомаяНоменклатура Тогда
НайденнаяСтрока = СтрокаТовары;
КонецЕсли;
КонецЦикла;
Поскольку при каждом совпадении переменная перезаписывается, после цикла в ней останется именно последняя подходящая строка. Если совпадений не было — останется Неопределено, что тоже нужно обработать.
Последняя строка в управляемой форме
В управляемых формах табличная часть документа обычно доступна через Объект.ИмяТабличнойЧасти, и синтаксис получения последней строки не меняется. Однако есть нюанс: если требуется не прочитать данные, а установить текущую строку в таблице формы, используется элемент формы и его свойство ТекущаяСтрока.
&НаКлиенте
Процедура ПерейтиКПоследнейСтроке(Команда)
Товары = Объект.Товары;
Если Товары.Количество() > 0 Тогда
Элементы.Товары.ТекущаяСтрока = Товары[Товары.Количество() - 1].ПолучитьИдентификатор();
КонецЕсли;
КонецПроцедуры
Разница принципиальна: индекс строки и идентификатор строки данных формы — разные вещи. Индекс начинается с нуля и отражает порядок в коллекции, а идентификатор — внутреннее число, по которому управляемая форма адресует строки. Для установки курсора используйте метод ПолучитьИдентификатор(), а не индекс.
Если табличная часть формы представлена динамическим списком или таблицей значений (реквизит формы), обращение по индексу работает так же, но помните, что на тонком клиенте недоступны некоторые серверные методы — при необходимости выносите логику в серверную процедуру с директивой &НаСервере.
- 1Определите, где выполняется код: модуль объекта, форма, клиент или сервер
- 2Получите коллекцию строк: Товары = Объект.Товары
- 3Проверьте Товары.Количество() > 0
- 4Обратитесь к строке: Товары[Товары.Количество() - 1]
- 5Проверьте результат в отладчике, посмотрев реквизиты строки
Последняя строка через запрос
Когда данные нужны из базы, а объект открывать нежелательно, последнюю строку табличной части можно получить запросом. У табличных частей в запросах есть поле НомерСтроки, и по нему строится сортировка.
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ ПЕРВЫЕ 1
| Товары.Номенклатура,
| Товары.Количество
|ИЗ
| Документ.РеализацияТоваровУслуг.Товары КАК Товары
|ГДЕ
| Товары.Ссылка = &Ссылка
|УПОРЯДОЧИТЬ ПО
| Товары.НомерСтроки УБЫВ";
Запрос.УстановитьПараметр("Ссылка", ДокументСсылка);
Выборка = Запрос.Выполнить().Выбрать();
Если Выборка.Следующий() Тогда
// данные последней строки
КонецЕсли;
Сортировка УБЫВ по номеру строки вместе с ПЕРВЫЕ 1 возвращает именно последнюю строку. Этот способ эффективен при пакетной обработке многих документов, потому что не требует получения объекта и не блокирует его в транзакции чтения.
Сравнение способов
Самый быстрый вариант в коде модуля или формы. Требует, чтобы объект был открыт.
Подходит для поиска последней строки по условию. Медленнее, перебирает всю коллекцию.
Оптимален при пакетной обработке без открытия объектов. Не даёт доступа к методам строки.
Типичные ошибки и как их избежать
Самая частая ошибка — забыть вычесть единицу из количества. Вторая по частоте — отсутствие проверки на пустую табличную часть. Обе приводят к одной и той же ошибке времени выполнения, и обе легко предотвращаются двумя строками кода.
Третья группа проблем связана с управляемыми формами: разработчики путают индекс строки и идентификатор строки формы, а также пытаются обратиться к данным табличной части на клиенте после серверного вызова, когда контекст объекта уже недоступен.
Проверка результата
После написания кода убедитесь, что получена именно та строка, которая ожидалась. Быстрый способ — вывести номер строки и ключевой реквизит:
Сообщить("Номер: " + ПоследняяСтрока.НомерСтроки
+ ", товар: " + ПоследняяСтрока.Номенклатура);
Номер строки последней строки всегда равен количеству строк табличной части (нумерация для пользователя начинается с единицы, в отличие от индексов). Если выведенный номер не совпадает с количеством — где-то ошибка в логике.
Как проверить результат
Равен значению ТЧ.Количество()
Меньше количества или строка не найдена
Код отрабатывает ветку Иначе без ошибок
Ошибка «Индекс находится за границами массива»
Совпадают с данными последней видимой строки документа
Возвращаются данные другой строки
FAQ
Чем отличается индекс строки от номера строки?
Индекс используется в коде и начинается с нуля: первая строка имеет индекс 0. НомерСтроки — реквизит, видимый пользователю, и начинается с единицы. Последняя строка имеет индекс Количество()-1 и номер, равный Количество().
Как получить предпоследнюю строку табличной части?
Обратитесь по индексу ТЧ[ТЧ.Количество() - 2], предварительно проверив, что Количество() >= 2. Тот же принцип работает для любой строки с конца.
Работает ли обращение по индексу для таблицы значений?
Да, таблица значений индексируется так же: ТЗ[ТЗ.Количество() - 1]. Это относится и к таблицам значений, созданным программно, и к реквизитам формы типа «ТаблицаЗначений».
Можно ли получить последнюю строку без загрузки всего документа?
Да, используйте запрос к табличной части с сортировкой по НомерСтроки УБЫВ и конструкцией ПЕРВЫЕ 1. Объект документа при этом в память не загружается, что важно при массовой обработке.
Почему код падает только на некоторых документах?
Скорее всего, на документах с пустой табличной частью. Добавьте проверку Количество() > 0 перед обращением по индексу — это устранит ошибку независимо от заполненности данных.
Как добавить строку после последней?
Метод Добавить() всегда вставляет строку в конец коллекции: НоваяСтрока = Объект.Товары.Добавить(). Отдельно искать последнюю строку для этого не требуется.
Что важно запомнить
Последняя строка табличной части — это ТЧ[ТЧ.Количество() - 1]. Всегда проверяйте, что табличная часть не пуста, не путайте индекс с номером строки и идентификатором формы, а для пакетной обработки используйте запрос с сортировкой по НомерСтроки УБЫВ.