При программной работе с табличными частями объектов и коллекциями управляемых форм разработчики нередко сталкиваются с ситуацией, когда метод возвращает не ту строку или обращение по числовому коду приводит к ошибке. Разберем по шагам, как устроена адресация строк в платформе 1С, почему возникает путаница между номерами и индексами, и как правильно обращаться к данным строк в различных сценариях.
Проанализируем базовый механизм работы коллекций в платформе 1С. В табличной части элемента или объекта строки упорядочены, однако доступ к ним по порядковому номеру зависит от контекста:
0, вторая — индекс 1, третья — индекс 2. При вызове метода Получить(2) платформа возвращает элемент с индексом 2, то есть третью по порядку строку.НомерСтроки начинается с 1. Это визуальный и учетный номер строки, который видит пользователь в таблице.Объект.ТабличнаяЧасть имеет тип ДанныеФормыКоллекция. Метод НайтиПоИдентификатору() принимает уникальный внутренний ключ строки формы, который генерируется динамически и не равен ее порядковому номеру или индексу.Если нам требуется получить конкретную строку по ее известной позиции в таблице (например, вторую по порядку), мы должны вычесть единицу из привычного номера строки. Посмотрим на пример безопасного обращения по индексу:
НужныйНомерСтроки = 2;
Индекс = НужныйНомерСтроки - 1;
// Проверяем, существует ли строка с таким индексом
Если Объект.ТабличнаяЧасть.Количество() > Индекс Тогда
Строка = Объект.ТабличнаяЧасть.Получить(Индекс);
// Альтернативный вариант через квадратные скобки:
// Строка = Объект.ТабличнаяЧасть[Индекс];
ЗначениеРеквизита = Строка.Номенклатура;
КонецЕсли;
Важно: прямое обращение через Получить(Индекс) или [Индекс] без предварительной проверки общего количества строк в коллекции при выходе за границы диапазона вызовет исключение «Индекс находится за границами массива».
Рассмотрим вариант, когда необходимо найти строку именно по значению реквизита НомерСтроки. Для этого используем метод НайтиСтроки() с передачей структуры отбора:
ПараметрыОтбора = Новый Структура("НомерСтроки", 2);
НайденныеСтроки = Объект.ТабличнаяЧасть.НайтиСтроки(ПараметрыОтбора);
Если НайденныеСтроки.Количество() > 0 Тогда
Строка = НайденныеСтроки[0];
ЗначениеРеквизита = Строка.Сумма;
КонецЕсли;
Учитываем, что системный реквизит НомерСтроки у вновь добавленных или перемещенных строк в памяти может пересчитываться только в момент записи объекта или специального обновления таблицы.
Разберем ситуацию, когда требуется программно активировать нужную строку в интерфейсе или найти элемент формы по его уникальному идентификатору:
// Получаем строку по индексу
Если Объект.ТабличнаяЧасть.Количество() >= 2 Тогда
Строка = Объект.ТабличнаяЧасть[1]; // Вторая строка
// Получаем динамический идентификатор строки формы
Идентификатор = Строка.ПолучитьИдентификатор();
// Поиск по идентификатору вернет ДанныеФормыЭлементКоллекции
СтрокаПоИД = Объект.ТабличнаяЧасть.НайтиПоИдентификатору(Идентификатор);
// Устанавливаем визуальный фокус на найденную строку в таблице формы
Элементы.ТабличнаяЧасть.ТекущаяСтрока = Идентификатор;
КонецЕсли;
В обычном приложении для позиционирования курсора в табличном поле используется прямое присвоение строки свойству ТекущаяСтрока элемента управления (ЭлементыФормы.ТабличнаяЧасть.ТекущаяСтрока = Строка;).
Если в коде уже доступна определенная строка (например, текущая строка формы), и нам необходимо получить предыдущую относительно нее запись, выясним ее индекс с помощью метода Индекс():
ТекущиеДанные = Элементы.ТабличнаяЧасть.ТекущиеДанные;
Если ТекущиеДанные <> Неопределено Тогда
ИндексТекущей = Объект.ТабличнаяЧасть.Индекс(ТекущиеДанные);
// Проверяем, есть ли предыдущая строка
Если ИндексТекущей > 0 Тогда
ПредыдущаяСтрока = Объект.ТабличнаяЧасть[ИндексТекущей - 1];
ЗначениеПредыдущей = ПредыдущаяСтрока.Количество;
КонецЕсли;
КонецЕсли;
Таким образом, для безошибочной работы со строками табличных частей всегда учитываем: доступ по позиции в коллекции выполняется по индексу (от 0 до Количество() - 1), поиск по реквизитам выполняется через НайтиСтроки(), а работа с методами идентификаторов применяется для интерфейсных элементов управляемой формы.