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