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