Почему при программном заполнении документа не отображаются характеристики и как это исправить?

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

При автоматизированном создании и заполнении документов в типовых конфигурациях 1С на управляемых формах (например, в «1С:Управление торговлей», «1С:Комплексная автоматизация» или «1С:ERP») разработчики часто сталкиваются с неожиданным поведением интерфейса. Документ успешно формируется, строки табличной части заполняются необходимой номенклатурой и характеристиками, однако в интерфейсе пользователя колонка с характеристикой оказывается заблокированной, а вместо значения отображается надпись: «<характеристики не используются>».

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

Выясняем причину: механизм условного оформления и служебные реквизиты формы

Текст-заглушка «<характеристики не используются>» появляется не по ошибке платформы, а в результате работы механизма Условного оформления управляемой формы. В типовых решениях видимость и доступность поля характеристики регулируются дополнительным служебным реквизитом строки, чаще всего имеющим имя ХарактеристикиИспользуются с типом Булево.

Проанализируем две ключевые причины, приводящие к блокировке поля:

  1. Отсутствие интерактивного события. При ручном вводе номенклатуры в строку табличной части срабатывает обработчик события ПриИзменении. В этот момент конфигурация обращается к свойствам номенклатуры (или ее вида) и устанавливает флаг ХарактеристикиИспользуются = Истина. При программной вставке строк платформенные события элементов формы не вызываются.
  2. Потеря служебных данных при сериализации. Реквизит ХарактеристикиИспользуются принадлежит коллекции элементов формы (ДанныеФормыКоллекция) и физически отсутствует в реквизитах табличной части объекта метаданных. Когда в коде используется следующая схема трансформации:
    
    &НаСервере
    Процедура ЗаполнитьНаСервере(ДанныеФормы)
        Док = ДанныеФормыВЗначение(ДанныеФормы, Тип("ДокументОбъект.ЗаказКлиента"));
        // Заполнение Док.Товары...
        ЗначениеВДанныеФормы(Док, ДанныеФормы);
    КонецПроцедуры
    
    метод ДанныеФормыВЗначение преобразует данные формы в ДокументОбъект, полностью отбрасывая экранные реквизиты. При обратном вызове ЗначениеВДанныеФормы платформа заново генерирует строки формы, где значение колонки ХарактеристикиИспользуются сбрасывается в значение по умолчанию — Ложь. Срабатывает условное оформление, блокируя поле.

Способ 1. Обход строк на клиенте через типовые процедуры обработки

Рассмотрим вариант решения, к которому пришел автор темы. Если форма документа уже открывается из клиентского контекста, мы можем обойти коллекцию строк объекта формы непосредственно на клиенте и задействовать типовой общий модуль конфигурации ОбработкаТабличнойЧастиКлиент.

Коллекция строк ДанныеФормыКоллекция доступна для чтения и изменения на стороне тонкого клиента. Посмотрим на пример реализации:


&НаКлиенте
Процедура СоздатьИОткрытьДокумент(Команда)

    Форма = ПолучитьФорму("Документ.ЗаказКлиента.Форма.ФормаДокумента");
    ДанныеФормы = Форма.Объект;
    
    // Выполняем базовое наполнение данных на сервере
    ЗаполнитьДокументНаСервере(ДанныеФормы);
    
    // Копируем заполненные данные обратно в объект формы
    КопироватьДанныеФормы(ДанныеФормы, Форма.Объект);
    
    // Обходим строки табличной части на клиенте для инициализации служебных реквизитов
    Для Каждого ТекСтрока Из Форма.Объект.Товары Цикл
        СтруктураДействий = Новый Структура;
        СтруктураДействий.Вставить("ПроверитьХарактеристикуПоВладельцу", ТекСтрока.Характеристика);
        
        ОбработкаТабличнойЧастиКлиент.ОбработатьСтрокуТЧ(ТекСтрока, СтруктураДействий, Неопределено);
    КонецЦикла;
    
    Форма.Открыть();

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

Метод ОбработкаТабличнойЧастиКлиент.ОбработатьСтрокуТЧ анализирует владельца характеристики, проверяет правила ведения учета по виду номенклатуры и взводит необходимые флаги в строке формы, включая признак ХарактеристикиИспользуются.

Важное ограничение: Данный способ прост в реализации, однако содержит скрытую проблему производительности. Функция ОбработатьСтрокуТЧ на клиенте может выполнять неявные контекстные вызовы сервера для проверки реквизитов номенклатуры. При обработке документов с десятками или сотнями позиций возникнет эффект множественных сетевых запросов («N+1»), что приведет к задержке при открытии формы.

Способ 2. Заполнение служебных реквизитов формы на сервере без сериализации объекта

Проанализируем более производительный и корректный подход. Чтобы не терять служебные колонки формы, откажемся от вызова ДанныеФормыВЗначение и ЗначениеВДанныеФормы. Будем наполнять коллекцию ДанныеФормы напрямую на стороне сервера формы, где все визуальные реквизиты строк доступны для изменения:


&НаСервере
Процедура ЗаполнитьДанныеФормыНаСервере(ДанныеФормы, ТаблицаИсходныхДанных)

    Для Каждого СтрДанных Из ТаблицаИсходныхДанных Цикл
        НоваяСтрока = ДанныеФормы.Товары.Добавить();
        ЗаполнитьЗначенияСвойств(НоваяСтрока, СтрДанных);
        
        // Напрямую выставляем признак использования характеристик
        // В зависимости от логики: Истина, либо на основании свойства вида номенклатуры
        НоваяСтрока.ХарактеристикиИспользуются = Истина;
    КонецЦикла;

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

Если требуется строго следовать типовым алгоритмам проверки, воспользуемся серверным аналогом обработки строк. В конфигурациях присутствует общий модуль ОбработкаТабличнойЧастиСервер, позволяющий выполнить проверку и установку статусов без лишних вызовов между клиентом и сервером.

Способ 3. Передача данных через стандартный параметр «ЗначенияЗаполнения»

Наиболее правильный с точки зрения стандартов разработки «1С:Совместимо» способ — открытие формы нового документа с передачей подготовленных данных в штатный параметр ЗначенияЗаполнения. В таком случае платформа самостоятельно вызывает событие ОбработкаЗаполнения в модуле объекта, а форма при создании выполняет полный цикл серверной инициализации элементов оформления.

Разберем по шагам реализацию этого механизма:


&НаКлиенте
Процедура ОткрытьНовыйДокументСЗаполнением()

    ТаблицаТоваров = СформироватьДанныеЗаполненияНаСервере();
    
    СтруктураЗаполнения = Новый Структура;
    СтруктураЗаполнения.Вставить("Товары", ТаблицаТоваров);
    
    ПараметрыОткрытия = Новый Структура;
    ПараметрыОткрытия.Вставить("ЗначенияЗаполнения", СтруктураЗаполнения);
    
    ОткрытьФорму("Документ.ЗаказКлиента.ФормаОбъекта", ПараметрыОткрытия);

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

При открытии формы управление передается в серверную процедуру ПриСозданииНаСервере. Типовой механизм формы самостоятельно определит признаки учета номенклатуры одним пакетным запросом ко всей таблице товаров и заполнит реквизит ХарактеристикиИспользуются без единого лишнего клиент-серверного вызова.

Способ 4. Создание, запись объекта на сервере и открытие по ссылке

Если создаваемый документ не требует обязательного подтверждения создания от пользователя перед первой записью, наиболее надежным способом будет создание объекта в серверном контексте базы данных:

  1. Создаем документ через Документы.ЗаказКлиента.СоздатьДокумент();
  2. Заполняем шапку и табличную часть стандартным образом;
  3. Записываем документ методом ДокОбъект.Записать();
  4. На клиенте открываем форму документа, передав ссылку в параметре Ключ.

&НаКлиенте
Процедура СоздатьИОткрытьЗаписанныйДокумент()

    СсылкаНаНовыйДокумент = СоздатьДокументНаСервере();
    
    ПараметрыОткрытия = Новый Структура("Ключ", СсылкаНаНовыйДокумент);
    ОткрытьФорму("Документ.ЗаказКлиента.ФормаОбъекта", ПараметрыОткрытия);

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

При таком подходе срабатывают стандартные обработчики ПриЧтенииНаСервере формы документа. Типовой код конфигурации считывает сохраненные данные, вычисляет статусы номенклатуры и гарантированно корректно настраивает условное оформление каждой строки.

Особенности прикладной логики

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

← На главную