При разработке дополнительных отчетов и обработок в системе 1С:Предприятие 8.3 на управляемых формах часто возникает задача: заполнить или изменить табличную часть документа «на лету», то есть непосредственно на экране у пользователя, без предварительной записи документа в базу данных. Типичный сценарий — заполнение табличной части «Товары» из внешнего файла или буфера обмена в документе «Реализация товаров и услуг».
Однако начинающие разработчики часто сталкиваются с тем, что их код меняет данные объекта в базе данных, а не на открытой форме экрана, либо пытаются использовать устаревшие и некорректные методы. В этой статье мы подробно разберем, как правильно взаимодействовать с активной формой документа-владельца из внешней обработки, избегая критических ошибок, и рассмотрим современные стандарты разработки в рамках Библиотеки Стандартных Подсистем (БСП).
Проанализируем типичные ошибки, разберем правильную архитектуру клиент-серверного взаимодействия и рассмотрим профессиональные методы отладки внешних обработок.
Рассмотрим ситуацию, с которой часто начинают разработчики (она представлена в Сообщении 11 форума). Для изменения данных на форме они пытаются получить её программно следующим образом:
ПараметрыФормы = Новый Структура("Ключ", ОбъектНазначения);
ФормаДокумента = ПолучитьФорму("Документ.РеализацияТоваровУслуг.ФормаОбъекта", ПараметрыФормы);
Выясним причину, почему так делать категорически нельзя:
Метод ПолучитьФорму при передаче ключа существующего объекта создает в оперативной памяти компьютера абсолютно новый, независимый экземпляр формы. Этот экземпляр никак не связан с той формой документа, которую пользователь видит в данный момент у себя на мониторе. В результате:
Для корректного изменения данных нам нужно обращаться строго к той форме, из которой была вызвана внешняя обработка. В терминологии 1С эта форма называется владельцем нашей внешней обработки.
Этот вариант применяется тогда, когда вашей внешней обработке требуется показать пользователю собственное диалоговое окно (например, для настройки параметров заполнения, сопоставления колонок из Excel или работы с буфером обмена), а затем перенести полученные данные в документ-источник.
При регистрации внешней обработки в модуле объекта мы указываем тип команды ОткрытиеФормы:
Функция СведенияОВнешнейОбработке() Экспорт
ПараметрыРегистрации = ДополнительныеОтчетыИОбработки.СведенияОВнешнейОбработке();
ПараметрыРегистрации.Вид = ДополнительныеОтчетыИОбработкиКлиентСервер.ВидОбработкиЗаполнениеОбъекта();
ПараметрыРегистрации.Наименование = "Заполнение ТЧ из буфера (пример)";
ПараметрыРегистрации.Версия = "1.0";
ПараметрыРегистрации.Назначение.Добавить("Документ.РеализацияТоваровУслуг");
Команда = ПараметрыРегистрации.Команды.Добавить();
Команда.Идентификатор = "ЗаполнитьИзБуфера";
Команда.Представление = "Заполнить из буфера...";
Команда.Использование = ДополнительныеОтчетыИОбработкиКлиентСервер.ТипКомандыОткрытиеФормы();
Возврат ПараметрыРегистрации;
КонецФункции
Когда пользователь нажимает кнопку заполнения в документе, БСП открывает форму нашей внешней обработки. При этом БСП автоматически устанавливает свойство управляемой формы внешней обработки ВладелецФормы. В этом свойстве как раз и содержится прямая ссылка на активную форму документа «Реализация товаров и услуг».
Разберем по шагам правильный код модуля формы внешней обработки:
&НаКлиенте
Процедура ВыполнитьЗаполнение(Команда)
// Эмулируем получение данных (например, массив ссылок Номенклатуры из буфера)
МассивНоменклатуры = ПолучитьМассивНоменклатурыИзБуфера();
Если МассивНоменклатуры.Количество() = 0 Тогда
ПоказатьПредупреждение(, "Нет данных для добавления!");
Возврат;
КонецЕсли;
// ВладелецФормы — это и есть открытая форма нашего документа "Реализация товаров и услуг"
ФормаДокумента = ВладелецФормы;
// Изменяем данные формы документа.
// Поскольку нам нужно добавить строки на сервере, передаем данные формы документа на серверный обработчик нашей обработки.
ЗаполнитьДокументНаСервере(ФормаДокумента.Объект, МассивНоменклатуры);
// Уведомляем форму документа о том, что данные были изменены (появится звездочка модифицированности)
ФормаДокумента.Модифицированность = Истина;
// Закрываем форму обработки, так как задача выполнена
Закрыть();
КонецПроцедуры
&НаСервереБезКонтекста
Процедура ЗаполнитьДокументНаСервере(ДанныеФормыДокумента, МассивНоменклатуры)
// 1. Преобразуем данные формы (ДанныеФормыСтруктура) в прикладной объект (ДокументОбъект)
// Это необходимо для того, чтобы задействовать все стандартные механизмы работы с ТЧ на сервере
ДокументОбъект = ДанныеФормыВЗначение(ДанныеФормыДокумента, Тип("ДокументОбъект.РеализацияТоваровУслуг"));
// 2. Выполняем заполнение табличной части на сервере
Для Каждого НоменклатураСсылка Из МассивНоменклатуры Цикл
НоваяСтрока = ДокументОбъект.Товары.Добавить();
НоваяСтрока.Номенклатура = НоменклатураСсылка;
// Здесь также можно вызвать типовые процедуры пересчета цен и сумм, например:
// ОбработкаТабличныхЧастей.ЗаполнитьЦеныИЦеныДокумента(...)
КонецЦикла;
// 3. Копируем измененные данные прикладного объекта обратно в структуру данных управляемой формы
ЗначениеВДанныеФормы(ДокументОбъект, ДанныеФормыДокумента);
КонецПроцедуры
Использование связки функций ДанныеФормыВЗначение и ЗначениеВДанныеФормы гарантирует, что структура данных на форме обновится корректно, сохраняя все типы данных и связи.
Если вашей внешней обработке не требуется выводить на экран свое диалоговое окно для пользователя, а нужно просто мгновенно изменить форму (например, заполнить ТЧ по определенному алгоритму одной кнопкой), то открывать форму обработки вообще не нужно.
Для этого в БСП существует современный тип команды: ТипКомандыЗаполнениеФормы. При этом сценарии БСП выполняет команду полностью в фоновом режиме, не открывая никаких промежуточных окон обработки, и сразу передает контекст формы документа в модуль объекта внешней обработки.
Проанализируем регистрацию такой команды в модуле объекта обработки:
Функция СведенияОВнешнейОбработке() Экспорт
ПараметрыРегистрации = ДополнительныеОтчетыИОбработки.СведенияОВнешнейОбработке();
ПараметрыРегистрации.Вид = ДополнительныеОтчетыИОбработкиКлиентСервер.ВидОбработкиЗаполнениеОбъекта();
ПараметрыРегистрации.Наименование = "Автозаполнение ТЧ (без открытия окон)";
ПараметрыРегистрации.Версия = "1.0";
ПараметрыРегистрации.Назначение.Добавить("Документ.РеализацияТоваровУслуг");
Команда = ПараметрыРегистрации.Команды.Добавить();
Команда.Идентификатор = "ЗаполнитьАвтоматически";
Команда.Представление = "Заполнить ТЧ автоматически";
// Указываем тип команды - ЗаполнениеФормы
Команда.Использование = ДополнительныеОтчетыИОбработкиКлиентСервер.ТипКомандыЗаполнениеФормы();
Возврат ПараметрыРегистрации;
КонецФункции
При выборе этого пункта меню БСП автоматически обратится к экспортной процедуре ВыполнитьКоманду в модуле объекта нашей обработки. В параметрах выполнения будет передан контекст открытой формы. Нам остается лишь обработать его:
Процедура ВыполнитьКоманду(ИдентификаторКоманды, ОбъектыНазначения, ПараметрыВыполнения) Экспорт
// ПараметрыВыполнения.ЭтаФорма содержит прямую ссылку на открытую форму документа!
ФормаДокумента = ПараметрыВыполнения.ЭтаФорма;
// Нам не нужно думать о получении формы, мы сразу работаем с реквизитом Объект
// Добавим строку прямо на клиенте через контекст формы (или передадим форму на сервер)
НоваяСтрока = ФормаДокумента.Объект.Товары.Добавить();
// Для примера найдем какую-нибудь номенклатуру
НоваяСтрока.Номенклатура = Справочники.Номенклатура.НайтиПоРеквизиту("Артикул", "12345");
НоваяСтрока.Количество = 10;
// Обязательно взводим флаг модифицированности
ФормаДокумента.Модифицированность = Истина;
КонецПроцедуры
Данный способ является наиболее предпочтительным с точки зрения стандартов БСП, так как он минимизирует количество клиент-серверных вызовов и избавляет от написания лишнего кода для управления формами.
В сообщениях темы автор интересуется, какими параметрами можно оперировать при открытии формы внешней обработки. При использовании типа команды ОткрытиеФормы БСП передает в открываемую форму структуру параметров. Чтобы работать с ними, рекомендуется объявить эти параметры в свойствах самой управляемой формы обработки на вкладке «Параметры»:
ДополнительнаяОбработкаСсылка (тип СправочникСсылка.ДополнительныеОтчетыИОбработки) — ссылка на элемент справочника нашей обработки. Полезно для чтения сохраненных настроек.ИдентификаторКоманды (тип Строка) — имя команды, которая запустила обработку (если одна форма обслуживает несколько команд).ОбъектыНазначения (тип Массив) — массив ссылок на объекты, для которых была запущена обработка (в нашем случае — ссылка на текущий документ, если он уже был записан).Для обращения к ним в коде формы используйте конструкцию Параметры.ИмяПараметра.
В Сообщениях 20–21 пользователи столкнулись со сложностью отладки внешних обработок. Попытки вызвать искусственную ошибку («деление на ноль») часто не приводят к остановке, так как БСП выполняет вызовы внешних обработок в безопасном режиме или внутри попыток. Создавать «фиктивные» формы для эмуляции работы — это долгий и неэффективный путь.
Рассмотрим два лучших современных способа быстрой отладки кода внешней обработки:
Платформа 1С:Предприятие умеет сопоставлять временные файлы, которые БСП создает при запуске внешней обработки, с исходным файлом .epf на вашем диске.
.epf) на диске.ВладелецФормы и Параметры.Важное условие: На сервере 1С должна быть разрешена отладка (ключ запуска службы сервера -debug), а в настройках подключения отладчика Конфигуратора должны быть активны галочки автоматического подключения для локальных и серверных вызовов.
Если точки останова все равно не срабатывают, убедитесь, что при регистрации обработки в справочнике БСП отключен безопасный режим (или в коде сведения об обработке указано ПараметрыРегистрации.БезопасныйРежим = Ложь;). В безопасном режиме отладка серверного кода внешних обработок может блокироваться правами доступа операционной системы или настройками кластера.
Для того чтобы изменить текущую открытую форму документа из дополнительной обработки заполнения ТЧ:
ПолучитьФорму для поиска активного документа.ВладелецФормы для изменения реквизитов вызывающего документа.ЗаполнениеФормы и в модуле объекта считывайте контекст формы через параметр ПараметрыВыполнения.ЭтаФорма.ДанныеФормыВЗначение и ЗначениеВДанныеФормы для корректной обработки табличных частей на стороне сервера без записи в СУБД.