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