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