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