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