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