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