Рассмотрим распространенную проблему, с которой сталкиваются разработчики при переносе кода из интерактивных обработок в фоновые или регламентные задания. В интерактивном режиме выгрузка в XML проходит без ошибок, но при запуске на сервере в составе регламентного задания система выдает критический сбой:
{ОбщийМодуль.МойОбщийМодуль.Модуль(600)}: Ошибка при вызове метода контекста (ЗаписатьАтрибут) по причине: Несоответствие типов (параметр номер '2')
В этой статье мы подробно разберем, почему возникает данная ошибка, проанализируем разницу выполнения кода на клиенте и на сервере, а также рассмотрим несколько надежных способов ее решения.
Метод объекта ЗаписьXML.ЗаписатьАтрибут() принимает строго определенные типы параметров. Синтаксис метода выглядит следующим образом:
ЗаписатьАтрибут(Имя, Значение)
Здесь второй параметр (Значение) должен быть строго типа «Строка». Если в этот параметр передается значение любого другого типа — например, Число, Дата, Булево, Ссылка (СправочникСсылка, ДокументСсылка), Неопределено или NULL — платформа 1С:Предприятие генерирует ошибку несоответствия типов.
Проанализируем ключевые причины, из-за которых поведение одного и того же алгоритма меняется при переходе в фоновый режим на сервере:
NULL. На клиенте при выводе в форму такое значение может визуализироваться как пустая строка, но при попытке прямой записи NULL в XML на сервере метод неизбежно вызовет ошибку.Неопределено или пустую ссылку.ПараметрыСеанса.ТекущийПользователь), в регламентном задании они могут быть не заполнены, что приведет к возврату пустых значений при поиске данных.Наиболее правильным и надежным способом решения проблемы является использование встроенной функции платформы 1С — XMLСтрока(). Эта функция предназначена специально для приведения базовых типов данных 1С к каноническому строковому представлению XML.
Функция XMLСтрока() корректно обрабатывает следующие типы данных:
Рассмотрим пример использования этой функции:
// Небезопасный код, который может вызвать ошибку на сервере:
ЗаписьXML.ЗаписатьАтрибут("КодСотрудника", Выборка.Код);
// Безопасный код с использованием XMLСтрока:
ЗаписьXML.ЗаписатьАтрибут("КодСотрудника", XMLСтрока(Выборка.Код));
Применение XMLСтрока() гарантирует, что на вход метода ЗаписатьАтрибут всегда поступит значение типа «Строка», соответствующее стандартам XML.
Если в процессе выгрузки могут возникать ситуации, когда переменная принимает значение Неопределено или нетипизированные данные, нам необходимо внедрить явную проверку типа.
Разберем пример реализации такой проверки на практике:
ЗначениеАтрибута = Выборка.Наименование;
// Проверяем тип данных перед записью
Если ТипЗнч(ЗначениеАтрибута) = Тип("Строка") Тогда
ЗаписьXML.ЗаписатьАтрибут("Имя", ЗначениеАтрибута);
ИначеЕсли ЗначениеЗаполнено(ЗначениеАтрибута) Тогда
// Если тип не строка, но значение заполнено, принудительно приводим к строке
ЗаписьXML.ЗаписатьАтрибут("Имя", Строка(ЗначениеАтрибута));
Иначе
// Если значение не заполнено (NULL, Неопределено), пишем пустую строку
ЗаписьXML.ЗаписатьАтрибут("Имя", "");
КонецЕсли;
Этот подход позволяет гибко реагировать на непредвиденные типы данных в выгрузке и избегать аварийного завершения регламентного задания.
Если данные для формирования XML собираются с помощью запроса, содержащего левые соединения (ЛЕВОЕ СОЕДИНЕНИЕ), обязательно обрабатывайте возможные значения NULL непосредственно в тексте запроса. Это избавит код от необходимости дополнительной фильтрации в цикле выгрузки.
Посмотрим на пример правильного конструирования запроса:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Номенклатура.Ссылка КАК Ссылка,
| ЕСТЬNULL(Номенклатура.Артикул, """") КАК Артикул,
| ЕСТЬNULL(ЦеныНоменклатурыСрезПоследних.Цена, 0) КАК Цена
|ИЗ
| Справочник.Номенклатура КАК Номенклатура
| ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ЦеныНоменклатуры.СрезПоследних КАК ЦеныНоменклатурыСрезПоследних
| ПО ЦеныНоменклатурыСрезПоследних.Номенклатура = Номенклатура.Ссылка";
Использование функции ЕСТЬNULL() гарантирует, что в выборку вместо неопределенного типа NULL попадет пустая строка или числовой ноль, которые затем легко преобразовать методом XMLСтрока().
Иногда системное преобразование XMLСтрока() не подходит под специфические требования принимающей стороны (например, если требуется другой формат даты или чисел). В таких случаях мы рекомендуем использовать явное форматирование с помощью функции Формат().
Рассмотрим примеры форматирования числовых значений и дат:
// Форматирование даты в стандартный формат XML (ГГГГ-ММ-ДД)
СтрокаДаты = Формат(Выборка.ДатаДокумента, "ДФ=yyyy-MM-dd");
ЗаписьXML.ЗаписатьАтрибут("Дата", СтрокаДаты);
// Форматирование числа: исключаем разделители групп (пробелы) и устанавливаем точку в качестве разделителя дробной части
СтрокаСуммы = Формат(Выборка.СуммаДокумента, "ЧГ=0; ЧРД=.");
ЗаписьXML.ЗаписатьАтрибут("Сумма", СтрокаСуммы);
Использование функции Формат() гарантирует получение строкового значения независимо от региональных настроек операционной системы, установленных на сервере 1С:Предприятия.
Для предотвращения ошибок «Несоответствие типов» в методе ЗаписатьАтрибут придерживайтесь следующих правил:
XMLСтрока(), если вы выгружаете стандартные типы 1С.ЕСТЬNULL() в запросах для исключения попадания типа NULL в выборку.Формат(), чтобы нивелировать разницу в региональных настройках сервера и клиента.