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

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

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

Анализ исходной ситуации

Представим, что у нас есть Форма1, в которой размещено ТабличноеПоле, связанное с ТаблицейЗначений. Также имеется Форма2, которая служит карточкой для редактирования полей этой таблицы. Наша цель — сделать так, чтобы при двойном клике по строке открывалась Форма2, а её поля автоматически заполнялись значениями из выбранной строки.

Для начала разберем стандартный механизм обработки выбора в табличном поле. Нам понадобится событие Выбор (или ПриАктивизацииСтроки, если форма должна обновляться динамически, но в нашем случае лучше использовать именно Выбор).

Реализация базового заполнения через ЗаполнитьЗначенияСвойств

Самый быстрый и правильный с точки зрения платформы способ — использование метода ЗаполнитьЗначенияСвойств. Этот метод сопоставляет имена колонок источника (строки таблицы) с именами реквизитов приемника (формы) и копирует значения там, где имена совпадают. Разберем пошагово код в модуле Формы1:


Процедура ТабличноеПолеВыбор(Элемент, ВыбраннаяСтрока, Колонка, СтандартнаяОбработка)
    
    // Отменяем стандартное действие (например, открытие формы элемента справочника)
    СтандартнаяОбработка = Ложь;
    
    // Получаем экземпляр Формы2. 
    // Владельцем указываем ЭтаФорма, чтобы иметь связь между окнами.
    ФормаРедактирования = ПолучитьФорму("Форма2", ЭтаФорма);
    
    // Заполняем реквизиты формы данными из выбранной строки.
    // ВыбраннаяСтрока в обычном приложении — это объект типа СтрокаТаблицыЗначений.
    ЗаполнитьЗначенияСвойств(ФормаРедактирования, ВыбраннаяСтрока);
    
    // Открываем форму
    ФормаРедактирования.Открыть();
    
КонецПроцедуры

Важное примечание по именованию: Чтобы этот код работал корректно, имена реквизитов в Форме2 должны строго совпадать с именами колонок в ТаблицеЗначений. Если колонка называется КоличествоТовара, то и реквизит в форме должен называться так же. Если имена отличаются, ЗаполнитьЗначенияСвойств просто проигнорирует их.

Решение проблемы с автовосстановлением значений

Часто в обычных формах включено свойство «Автовосстановление» (сохранение значений при закрытии и восстановление при открытии). Это удобно для пользователя, но создает проблему при программном заполнении: система может сначала выполнить ваш код, а затем, в момент метода Открыть(), загрузить старые сохраненные значения из хранилища настроек, затирая актуальные данные.

Проанализируем ситуацию: как нам приоритезировать программный ввод над сохраненным? Рассмотрим несколько стратегий.

Стратегия 1: Использование обработчика ПередОткрытием в Форме2

Механизм восстановления значений срабатывает непосредственно перед открытием формы. Если мы хотим гарантировать чистоту данных, мы можем передать данные в форму через экспортную переменную, а в событии ПередОткрытием принудительно их присвоить. Рассмотрим этот метод.

В модуле Формы2 добавим в самом начале:


Перем ДанныеДляЗаполнения Экспорт;

Процедура ПередОткрытием(Отказ, СтандартнаяОбработка)
    Если ДанныеДляЗаполнения <> Неопределено Тогда
        ЗаполнитьЗначенияСвойств(ЭтаФорма, ДанныеДляЗаполнения);
    КонецЕсли;
КонецПроцедуры

Тогда код вызова в Форме1 изменится следующим образом:


ФормаРедактирования = ПолучитьФорму("Форма2");
ФормаРедактирования.ДанныеДляЗаполнения = ВыбраннаяСтрока;
ФормаРедактирования.Открыть();

Этот подход хорош тем, что обработчик ПередОткрытием срабатывает в тот момент, когда параметры формы уже инициализированы, и мы можем «перебить» восстановленные значения нашими актуальными данными.

Программный сброс сохраняемых значений

Если нам нужно, чтобы форма всегда открывалась с «чистого листа» и не пыталась восстанавливать старые данные, когда мы вызываем её программно, мы можем применить метод УдалитьНастройки. Это радикальный способ, который очищает историю заполнения полей для пользователя.

Также проанализируем настройку самой формы. В свойствах Формы2 загляните в список «Сохраняемые значения». Если для определенных реквизитов критически важно всегда получать данные из таблицы, возможно, стоит просто снять с них флажки сохранения. Это исключит конфликт на уровне метаданных.

Обеспечение визуального обновления

Иногда после программного присвоения значений реквизитам элементы управления на форме (поля ввода) не обновляются визуально. В обычных формах это происходит, если фокус еще не был установлен на форму. В таких случаях в конце процедуры заполнения (внутри Формы2) рекомендуется вызвать метод Обновить().

Разберем пример финальной настройки Формы2:


Процедура ПередОткрытием(Отказ, СтандартнаяОбработка)
    
    // Если форма открывается для редактирования конкретной строки
    Если ТипЗнч(ДанныеДляЗаполнения) = Тип("СтрокаТаблицыЗначений") Тогда
        
        // Принудительно заполняем реквизиты, игнорируя то, что восстановила система
        ЗаполнитьЗначенияСвойств(ЭтаФорма, ДанныеДляЗаполнения);
        
        // Обновляем визуальное состояние всех элементов управления
        ЭтаФорма.Обновить();
        
    КонецЕсли;
    
КонецПроцедуры

Работа с несовпадающими именами

Что делать, если структуру колонок таблицы нельзя привести к именам реквизитов формы? В этом случае нам придется отказаться от ЗаполнитьЗначенияСвойств и выполнить сопоставление вручную. Выясним, как это выглядит на практике:


// В Форме1
ФормаРедактирования = ПолучитьФорму("Форма2");
ФормаРедактирования.РеквизитИмя = ВыбраннаяСтрока.КолонкаФИО;
ФормаРедактирования.РеквизитСумма = ВыбраннаяСтрока.КолонкаИтоговаяЦена;
ФормаРедактирования.Открыть();

Важно: При таком подходе реквизиты РеквизитИмя и РеквизитСумма также должны быть объявлены как Экспорт в модуле Формы2, либо они должны быть реквизитами формы, созданными в конструкторе (тогда они доступны напрямую через точку от объекта формы).

Итоги

Мы рассмотрели процесс программного взаимодействия двух обычных форм. Подведем итоги:

  1. Используйте ЗаполнитьЗначенияСвойств для быстрого копирования данных при совпадении имен.
  2. Для передачи данных используйте Экспортные переменные в вызываемой форме.
  3. Чтобы обойти автовосстановление, выполняйте финальное присвоение значений в обработчике ПередОткрытием.
  4. Не забывайте про метод ЭтаФорма.Обновить() для актуализации интерфейса.
  5. Всегда передавайте владельца формы вторым параметром в ПолучитьФорму, если планируете возвращать измененные данные обратно в таблицу.

Следуя этим правилам, вы обеспечите стабильную работу интерфейса и предсказуемое поведение системы при работе с данными в обычных формах 1С.

← На главную