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