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