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