Как исправить ошибку «Несоответствие типов (параметр номер '2')» в методе ЗаписатьАтрибут при выполнении регламентного задания в 1С

Программист 1С v8.3 (Обычные формы) 1С:Комплексная автоматизация IT и автоматизация бизнеса
← На главную

Рассмотрим распространенную проблему, с которой сталкиваются разработчики при переносе кода из интерактивных обработок в фоновые или регламентные задания. В интерактивном режиме выгрузка в XML проходит без ошибок, но при запуске на сервере в составе регламентного задания система выдает критический сбой:

{ОбщийМодуль.МойОбщийМодуль.Модуль(600)}: Ошибка при вызове метода контекста (ЗаписатьАтрибут) по причине: Несоответствие типов (параметр номер '2')

В этой статье мы подробно разберем, почему возникает данная ошибка, проанализируем разницу выполнения кода на клиенте и на сервере, а также рассмотрим несколько надежных способов ее решения.

Почему возникает ошибка «Несоответствие типов»?

Метод объекта ЗаписьXML.ЗаписатьАтрибут() принимает строго определенные типы параметров. Синтаксис метода выглядит следующим образом:

ЗаписатьАтрибут(Имя, Значение)

Здесь второй параметр (Значение) должен быть строго типа «Строка». Если в этот параметр передается значение любого другого типа — например, Число, Дата, Булево, Ссылка (СправочникСсылка, ДокументСсылка), Неопределено или NULL — платформа 1С:Предприятие генерирует ошибку несоответствия типов.

Почему код работает в обработке, но падает в регламентном задании?

Проанализируем ключевые причины, из-за которых поведение одного и того же алгоритма меняется при переходе в фоновый режим на сервере:

  1. Разница в источнике данных (Формы vs База данных): При интерактивном запуске обработки данные часто берутся из элементов управления формы. Поля ввода на форме могут автоматически преобразовывать значения в их строковые представления. В регламентном задании форм нет — код работает напрямую с выборками из таблиц базы данных или результатами запросов, где типы данных остаются «чистыми» (ссылки, числа, даты).
  2. Работа с неопределенными значениями и NULL: В запросах, использующих левые соединения, отсутствующие данные возвращают тип NULL. На клиенте при выводе в форму такое значение может визуализироваться как пустая строка, но при попытке прямой записи NULL в XML на сервере метод неизбежно вызовет ошибку.
  3. Ограничения прав доступа (RLS): Регламентные задания выполняются под специальным пользователем (или системным сеансом). Если у этого пользователя ограничены права на чтение определенных объектов или реквизитов (настроен RLS), то при обращении к реквизитам вместо ссылок или строк код получит Неопределено или пустую ссылку.
  4. Неинициализированные параметры сеанса: Если алгоритм выгрузки опирается на параметры сеанса (например, ПараметрыСеанса.ТекущийПользователь), в регламентном задании они могут быть не заполнены, что приведет к возврату пустых значений при поиске данных.

Способ 1. Использование специализированной функции XMLСтрока()

Наиболее правильным и надежным способом решения проблемы является использование встроенной функции платформы 1С — XMLСтрока(). Эта функция предназначена специально для приведения базовых типов данных 1С к каноническому строковому представлению XML.

Функция XMLСтрока() корректно обрабатывает следующие типы данных:

Рассмотрим пример использования этой функции:


// Небезопасный код, который может вызвать ошибку на сервере:
ЗаписьXML.ЗаписатьАтрибут("КодСотрудника", Выборка.Код); 

// Безопасный код с использованием XMLСтрока:
ЗаписьXML.ЗаписатьАтрибут("КодСотрудника", XMLСтрока(Выборка.Код));

Применение XMLСтрока() гарантирует, что на вход метода ЗаписатьАтрибут всегда поступит значение типа «Строка», соответствующее стандартам XML.


Способ 2. Явная проверка типов данных перед записью

Если в процессе выгрузки могут возникать ситуации, когда переменная принимает значение Неопределено или нетипизированные данные, нам необходимо внедрить явную проверку типа.

Разберем пример реализации такой проверки на практике:


ЗначениеАтрибута = Выборка.Наименование;

// Проверяем тип данных перед записью
Если ТипЗнч(ЗначениеАтрибута) = Тип("Строка") Тогда
    ЗаписьXML.ЗаписатьАтрибут("Имя", ЗначениеАтрибута);
ИначеЕсли ЗначениеЗаполнено(ЗначениеАтрибута) Тогда
    // Если тип не строка, но значение заполнено, принудительно приводим к строке
    ЗаписьXML.ЗаписатьАтрибут("Имя", Строка(ЗначениеАтрибута));
Иначе
    // Если значение не заполнено (NULL, Неопределено), пишем пустую строку
    ЗаписьXML.ЗаписатьАтрибут("Имя", "");
КонецЕсли;

Этот подход позволяет гибко реагировать на непредвиденные типы данных в выгрузке и избегать аварийного завершения регламентного задания.


Способ 3. Обработка NULL в запросах

Если данные для формирования XML собираются с помощью запроса, содержащего левые соединения (ЛЕВОЕ СОЕДИНЕНИЕ), обязательно обрабатывайте возможные значения NULL непосредственно в тексте запроса. Это избавит код от необходимости дополнительной фильтрации в цикле выгрузки.

Посмотрим на пример правильного конструирования запроса:


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |	Номенклатура.Ссылка КАК Ссылка,
    |	ЕСТЬNULL(Номенклатура.Артикул, """") КАК Артикул,
    |	ЕСТЬNULL(ЦеныНоменклатурыСрезПоследних.Цена, 0) КАК Цена
    |ИЗ
    |	Справочник.Номенклатура КАК Номенклатура
    |	ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ЦеныНоменклатуры.СрезПоследних КАК ЦеныНоменклатурыСрезПоследних
    |		ПО ЦеныНоменклатурыСрезПоследних.Номенклатура = Номенклатура.Ссылка";

Использование функции ЕСТЬNULL() гарантирует, что в выборку вместо неопределенного типа NULL попадет пустая строка или числовой ноль, которые затем легко преобразовать методом XMLСтрока().


Способ 4. Форматирование дат и чисел вручную

Иногда системное преобразование XMLСтрока() не подходит под специфические требования принимающей стороны (например, если требуется другой формат даты или чисел). В таких случаях мы рекомендуем использовать явное форматирование с помощью функции Формат().

Рассмотрим примеры форматирования числовых значений и дат:


// Форматирование даты в стандартный формат XML (ГГГГ-ММ-ДД)
СтрокаДаты = Формат(Выборка.ДатаДокумента, "ДФ=yyyy-MM-dd");
ЗаписьXML.ЗаписатьАтрибут("Дата", СтрокаДаты);

// Форматирование числа: исключаем разделители групп (пробелы) и устанавливаем точку в качестве разделителя дробной части
СтрокаСуммы = Формат(Выборка.СуммаДокумента, "ЧГ=0; ЧРД=.");
ЗаписьXML.ЗаписатьАтрибут("Сумма", СтрокаСуммы);

Использование функции Формат() гарантирует получение строкового значения независимо от региональных настроек операционной системы, установленных на сервере 1С:Предприятия.

Резюме

Для предотвращения ошибок «Несоответствие типов» в методе ЗаписатьАтрибут придерживайтесь следующих правил:

  1. Всегда оборачивайте передаваемые значения в функцию XMLСтрока(), если вы выгружаете стандартные типы 1С.
  2. Используйте функцию ЕСТЬNULL() в запросах для исключения попадания типа NULL в выборку.
  3. Для дат и чисел применяйте явное форматирование через Формат(), чтобы нивелировать разницу в региональных настройках сервера и клиента.
← На главную