Как программно связать поле ввода с конкретной строкой таблицы значений на управляемой форме 1С?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При разработке интерфейсов на управляемых формах в «1С:Предприятие 8» часто возникает задача динамического вывода полей ввода. Классический сценарий: у нас есть реквизит формы типа ТаблицаЗначений или табличная часть объекта, и мы хотим отобразить данные этой таблицы не в виде стандартной сетки (элемента формы "Таблица"), а в виде отдельных, независимо расположенных полей ввода. При этом каждое поле должно быть жестко привязано к конкретной ячейке в конкретной строке таблицы.

Например, первое поле ввода должно редактировать значение в первой строке таблицы, второе — во второй, и так далее. В этой статье мы подробно разберем, как правильно реализовать такое поведение программно, разберем типичные ошибки разработчиков и напишем отказоустойчивый код.

В чем заключается основная сложность и типичная ошибка?

Многие разработчики при попытке связать программно созданное поле с текущей или конкретной строкой таблицы пытаются обратиться к коллекции элементов формы. Они пишут код, подобный следующему:


// Ошибка! Этот код вызовет исключение платформы
ПолеТест.ПутьКДанным = "Элементы.ТаблицаСостояний.ТекущиеДанные.Значение";

Проанализируем причину этой ошибки. Платформа 1С строго разделяет понятия Данных (Реквизитов) и их Отображения (Элементов). Свойство ПутьКДанным визуального элемента формы может ссылаться только на реквизиты формы. Оно принципиально не может содержать в своем пути обращение к коллекции Элементы.

Правильный синтаксис адресации строки по индексу

Для того чтобы связать поле ввода с конкретной ячейкой таблицы значений или табличной части по индексу строки, необходимо использовать специальный синтаксис обращения к реквизиту формы напрямую через квадратные скобки. Шаблон выглядит так:

"ИмяРеквизитаФормыТаблицы[ИндексСтроки].ИмяКолонки"

Рассмотрим несколько примеров:

  1. Если у нас есть реквизит формы ТаблицаСостояний (тип ТаблицаЗначений), и мы хотим связать поле с колонкой Значение первой строки (индекс 0):
    ПолеТест.ПутьКДанным = "ТаблицаСостояний[0].Значение";
  2. Если мы работаем с табличной частью документа или справочника, которая находится внутри реквизита Объект (например, табличная часть ЗначенияРеквизитов), и нам нужна вторая строка (индекс 1) колонки Значение:
    ПолеТест.ПутьКДанным = "Объект.ЗначенияРеквизитов[1].Значение";

При таком подходе платформа осуществляет полноценную двустороннюю связь. Если пользователь изменит значение в поле ввода, оно мгновенно и автоматически запишется в соответствующую строку таблицы. И наоборот: если значение будет изменено в таблице программно, поле ввода сразу же обновит свое визуальное представление.

Пошаговый пример реализации программного создания полей

Давайте разберем готовое практическое решение. Предположим, у нас на форме есть табличная часть ЗначенияРеквизитов, подчиненная основному реквизиту Объект. Нам необходимо для каждой строки этой табличной части динамически создать на форме отдельное поле ввода.

Напишем процедуру, которая будет вызываться на сервере при заполнении или инициализации данных формы. При реализации этого алгоритма крайне важно обратить внимание на корректное преобразование индекса строки в строковый вид. Если просто преобразовать число в строку, то при индексах больше 999 платформа по умолчанию применит группировку разрядов и вставит неразрывный пробел (например, получится "1 000"), что приведет к ошибке пути к данным. Чтобы этого избежать, воспользуемся функцией Формат() с обнулением параметров группировки.


&НаСервере
Процедура СоздатьПоляРеквизитовНаСервере()

    // Обходим строки нашей табличной части
    Для Каждого СтрокаТЧ Из Объект.ЗначенияРеквизитов Цикл
        
        // Получаем точный индекс строки в коллекции данных
        ИндексСтроки = Объект.ЗначенияРеквизитов.Индекс(СтрокаТЧ);
        
        // Форматируем индекс в строку без разделителей разрядов (триад)
        СтрокаИндекса = Формат(ИндексСтроки, "ЧДЦ=; ЧН=; ЧГ=");
        
        // Формируем уникальное имя для создаваемого элемента формы
        ИмяПоляФормы = "ДинамическоеПоле_" + СтрокаИндекса;
        
        // Проверяем, не было ли это поле создано ранее (например, при повторном вызове процедуры)
        Если Элементы.Найти(ИмяПоляФормы) <> Неопределено Тогда
            Продолжить;
        КонецЕсли;
        
        // Формируем правильный путь к данным для конкретной строки и колонки "Значение"
        ПутьКДаннымПоля = "Объект.ЗначенияРеквизитов[" + СтрокаИндекса + "].Значение";
        
        // Добавляем элемент формы типа "ПолеФормы" в нужную группу (например, на саму форму)
        НовоеПоле = Элементы.Добавить(ИмяПоляФормы, Тип("ПолеФормы"), ЭтаФорма);
        НовоеПоле.Вид = ВидПоляФормы.ПолеВвода;
        НовоеПоле.Заголовок = СтрокаТЧ.НаименованиеРеквизита; // задаем заголовок из данных строки
        
        // Связываем элемент формы с ячейкой в табличной части
        НовоеПоле.ПутьКДанным = ПутьКДаннымПоля;
        
        // Дополнительно: настраиваем типы данных для поля ввода
        Если ЗначениеЗаполнено(СтрокаТЧ.ДополнительныйРеквизит) Тогда
            // Например, получаем описание типов из метаданных доп. реквизита
            НовоеПоле.ОграничениеТипа = СтрокаТЧ.ДополнительныйРеквизит.ТипЗначения;
        КонецЕсли;
        
        // Делаем поле видимым
        НовоеПоле.Видимость = Истина;
        
    КонецЦикла;

КонецПроцедуры

Важные ограничения и особенности механизма

Для того чтобы этот механизм работал стабильно и без сбоев, необходимо строго соблюдать несколько правил платформы:

  1. Существование строк в таблице. На момент установки свойства ПутьКДанным строка с указанным индексом уже обязательно должна быть создана в коллекции данных на сервере. Если вы попытаетесь связать поле с путем "ТаблицаСостояний[5].Значение", а в таблице на данный момент всего 3 строки (индексы 0, 1, 2), платформа сгенерирует критическую ошибку выполнения. Поэтому порядок действий всегда такой: сначала добавляем строки в таблицу значений, и только затем создаем элементы формы и прописываем пути к данным.
  2. Удаление строк из таблицы. Если в процессе работы пользователя строки будут удалены из таблицы данных, все элементы формы, которые ссылались на индексы удаленных (или сместившихся) строк, потеряют связь с данными и могут вызвать ошибки отображения. При изменении состава строк таблицы необходимо программно пересоздавать элементы формы или динамически обновлять их свойства ПутьКДанным.
  3. Неприменимость к Динамическим Спискам. Обратите внимание, что данный механизм адресации по индексу строки через квадратные скобки категорически не работает для реквизитов типа ДинамическийСписок. Данные динамического списка считываются с сервера порциями и не хранятся в оперативной памяти клиента целиком, поэтому связать поле ввода с конкретным индексом строки динамического списка невозможно.
← На главную