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