При переносе данных между конфигурациями «1С:Предприятие 8» с помощью технологии Конвертация данных 2.0 разработчики часто сталкиваются с необходимостью предоставить пользователю отчет о результатах загрузки. Это могут быть списки созданных документов, найденных дублей или ошибок сопоставления. Однако в управляемом приложении (например, в конфигурации «Бухгалтерия предприятия 3.0») стандартные подходы из обычных форм вызывают критические ошибки.
В этой статье мы подробно разберем, почему возникают ошибки при попытке интерактивного вывода отчетов из правил обмена, проанализируем внутренние механизмы платформы и Библиотеки стандартных подсистем (БСП), а также рассмотрим пять практических способов решения этой проблемы.
Прежде чем перейти к написанию кода, выясним точные причины падения системы. Обычно разработчики пытаются сформировать ТабличныйДокумент прямо в обработчике правил обмена ПослеЗагрузкиДанных и сразу вывести его на экран или записать в файл. При этом система выдает две типичные ошибки.
1. Ошибка метода Показать() на сервере. В управляемом приложении «1С» процесс импорта данных через обработку УниверсальныйОбменДаннымиXML выполняется строго на стороне сервера. Обработчик ПослеЗагрузкиДанных также полностью отрабатывает в серверном контексте. На сервере интерфейсные методы, такие как Показать(), физически отсутствуют. Попытка их вызова приводит к аварийному завершению работы с системным сообщением «Метод объекта не обнаружен».
2. Ошибка «Установлен безопасный режим» при сохранении файла. Пытаясь обойти ограничение серверного контекста, разработчики пробуют записать табличный документ во временный файл на сервере (например, в формате MXL или PDF), чтобы затем передать его на клиент. Но при вызове метода Записать() возникает ошибка безопасности. Дело в том, что конфигурации на базе БСП при выполнении обмена программно включают безопасный режим (БезопасныйРежим = Истина). Это изолирует выполнение произвольного XML-кода правил обмена. В безопасном режиме платформой блокируется любой доступ к файловой системе сервера, и даже отключение флажка «Защита от опасных действий» в настройках пользователя не решает эту проблему.
Разберем по шагам наиболее эффективные способы решения этих архитектурных ограничений.
Это наиболее правильный и красивый с точки зрения архитектуры «1С» подход. Мы разделяем логику формирования данных и их визуализацию: формируем отчет на сервере, помещаем его в специальный буфер, а после завершения загрузки извлекаем его на клиенте и показываем пользователю.
Рассмотрим, как реализовать этот алгоритм:
Шаг 1. На сервере (в обработчике правил ПослеЗагрузкиДанных)
Вместо непосредственного вывода отчета мы сериализуем наш табличный документ во временное хранилище платформы. Адрес этого хранилища мы передаем через глобальную коллекцию параметров обмена.
// Предположим, что ТабличныйДокумент уже сформирован и заполнен данными
АдресХранилища = ПоместитьВоВременноеХранилище(ТабличныйДокумент);
// Записываем адрес в параметры конвертации, чтобы клиентский код мог его прочитать
Параметры.Вставить("АдресОтчетаЗагрузки", АдресХранилища);
Шаг 2. На клиенте (в модуле управляемой формы, запускающей обмен)
Если для интеграции вы используете собственную обработку или дорабатываете типовую форму загрузки данных, то в клиентском коде после вызова серверного метода выполнения обмена (например, ВыполнитьЗагрузку()) добавьте следующий фрагмент:
// Получаем адрес временного хранилища из параметров объекта обработки
АдресОтчета = ОбъектОбработкиОбмена.Параметры.Получить("АдресОтчетаЗагрузки");
Если ЗначениеЗаполнено(АдресОтчета) Тогда
// Получаем сам документ из хранилища на клиенте
ТабДок = ПолучитьИзВременногоХранилища(АдресОтчета);
// Теперь мы на клиенте, и метод Показать() отработает без ошибок
ТабДок.Показать("Отчет о загруженных объектах");
КонецЕсли;
Этот способ гарантирует стабильную работу без нарушения безопасности системы.
Если обмен данными выполняется в интерактивном режиме администратором через стандартную обработку УниверсальныйОбменДаннымиXML, и вам крайне необходимо сохранить файл отчета на диск сервера, вы можете отключить безопасный режим.
Проанализируем, как это сделать:
После снятия этого ограничения в обработчике ПослеЗагрузкиДанных станет доступна работа с файловой системой. Мы сможем записать отчет во временный каталог сервера:
ИмяФайлаОтчета = ПолучитьИмяВременногоФайла("mxl");
ТабличныйДокумент.Записать(ИмяФайлаОтчета, ТипФайлаТабличногоДокумента.MXL);
// Помещаем информацию о файле в параметры, чтобы открыть его на клиенте
Параметры.Вставить("ПутьКФайлуОтчета", ИмяФайлаОтчета);
На клиенте останется только прочитать этот файл и открыть его стандартными средствами операционной системы или платформы.
Когда обмен данными выполняется по расписанию в фоновом режиме, интерактивный вывод окон пользователю в принципе невозможен, так как сессия работает без клиентского интерфейса. В таком случае отчет необходимо сохранять непосредственно в базу данных для последующего анализа.
Безопасный режим не накладывает ограничений на запись ссылочных данных или регистров сведений в СУБД. Выясним, как реализовать этот сценарий:
Шаг 1. Архивирование отчета на сервере
В обработчике ПослеЗагрузкиДанных упакуем наш табличный документ в специальный объект ХранилищеЗначения для сжатия и бинарного сохранения:
ХранилищеОтчета = Новый ХранилищеЗначения(ТабличныйДокумент, Новый СжатиеДанных(9));
Шаг 2. Запись в базу данных
Создадим запись в специально подготовленном регистре сведений (например, «ЛогиЗагрузкиДанных») или прикрепим к справочнику присоединенных файлов:
НоваяЗапись = РегистрыСведений.РезультатыОбменаДанными.СоздатьМенеджерЗаписи();
НоваяЗапись.Период = ТекущаяДата();
НоваяЗапись.УзелИнформационнойБазы = Параметры.УзелОбмена; // Если используется план обмена
НоваяЗапись.БинарныеДанныеОтчета = ХранилищеОтчета;
НоваяЗапись.Записать();
Пользователь сможет в любое удобное время открыть специализированный интерфейс в программе, извлечь табличный документ из регистра и просмотреть результаты загрузки.
Если структура вашего отчета достаточно проста и не требует сложного форматирования ячеек (цвета, шрифты, объединения), отличной альтернативой табличному документу будет использование механизма сообщений.
Платформа «1С:Предприятие 8» спроектирована так, что все текстовые сообщения, сгенерированные методом Сообщить() на сервере во время выполнения транзакции или загрузки, кэшируются. После завершения серверного вызова они автоматически передаются на клиент и отображаются в специальном окне сообщений пользователя.
Посмотрим на пример реализации в обработчике ПослеЗагрузкиДанных:
Сообщить("--- Отчет о результатах загрузки объектов ---");
Сообщить("Успешно обработано документов: " + КоличествоДокументов);
Сообщить("Создано новых контрагентов: " + КоличествоКонтрагентов);
Если ОшибкиВозникли Тогда
Сообщить("ВНИМАНИЕ! Обнаружены ошибки сопоставления номенклатуры.");
КонецЕсли;
Сообщить("--------------------------------------------");
Преимущества данного способа:
Разберем еще один продвинутый метод, который упоминали участники обсуждения. Если стандартная выгрузка/загрузка вас не устраивает, вы можете обернуть правила обмена во внешнюю обработку.
В этом случае вы создаете управляемую форму обработки, добавляете на нее реквизит с типом ТабличныйДокумент и выводите поле табличного документа непосредственно на экран. При запуске обмена из этой формы серверный код загрузки заполняет реквизит формы на сервере, а платформа автоматически синхронизирует (выполняет сериализацию данных) и отображает готовый отчет на клиенте без дополнительных манипуляций с временными хранилищами.
Мы проанализировали специфику работы клиент-серверной архитектуры при обмене данными. Подведем итог, какой метод выбрать в вашей ситуации: