При разработке механизмов обмена данными или выгрузки отчетности в формате XML начинающие программисты 1С часто сталкиваются с ошибками типизации. Одна из самых распространенных — попытка передать в метод ЗаписатьТекст() объектного типа (число, дата, ссылка) вместо строки. В этой статье мы разберем, почему возникают такие ошибки, как правильно преобразовывать типы данных для XML и как оптимизировать код для повышения производительности.
Рассмотрим ситуацию: при выгрузке результата запроса в XML-файл вы используете метод ЗаписьXML.ЗаписатьТекст(Строка.Получить(2)). В этот момент система выдает ошибку «Несоответствие типов (параметр номер 1)». Проанализируем ситуацию: метод ЗаписатьТекст() объекта ЗаписьXML ожидает на вход исключительно значение типа Строка. Если в третьей колонке вашего запроса (индекс 2) находится число (например, количество товара), дата или ссылка на справочник, 1С не выполняет автоматическое преобразование к строке, что и приводит к падению программы.
Использование функции ЗначениеВСтрокуВнутр() кажется простым выходом, так как она принудительно возвращает текст. Однако это решение в корне неверно. Выясним причину: данная функция формирует специфическую системную строку (похожую на JSON, но во внутреннем формате 1С), которая содержит служебную информацию о типе. Например, вместо числа 3050 вы получите {"N",3050}. Такой формат сделает ваш XML-файл нечитаемым для других программ и невалидным согласно схеме XSD.
Для корректной записи любых данных в XML необходимо использовать специализированную функцию XMLСтрока(Значение). Рассмотрим подробнее, почему она лучше стандартного метода Строка():
Строка() может добавлять неразрывные пробелы для разделения разрядов (например, "1 250,50"), что недопустимо в XML. Функция XMLСтрока() запишет число в каноническом виде: "1250.50" (без пробелов, с точкой в качестве разделителя).Посмотрим на пример правильного использования:
// Вместо: ЗаписьXML.ЗаписатьТекст(ЗначениеВСтрокуВнутр(Строка.Количество));
// Используем:
ЗаписьXML.ЗаписатьТекст(XMLСтрока(Строка.Количество));
Проанализируем ваш метод получения данных через Строка.Получить(Индекс). Это считается плохим тоном в разработке на 1С по нескольким причинам:
Рассмотрим, как сделать код надежнее. Всегда обращайтесь к полям по их именам, заданным в тексте запроса через ключевое слово КАК.
Для Каждого ТекСтрока Из РезультатЗапроса Цикл
ЗаписьXML.ЗаписатьНачалоЭлемента("T3RXXXXG2S");
// Обращаемся по имени поля
ЗаписьXML.ЗаписатьТекст(ТекСтрока.КонтрагентНаименование);
ЗаписьXML.ЗаписатьКонецЭлемента();
КонецЦикла;
В исходном коде часто встречается ошибка: создание нескольких отдельных циклов по одной и той же таблице значений для заполнения разных узлов XML. Это существенно замедляет работу системы. Разберем по шагам, как оптимизировать процесс:
Для Каждого.ЗаписатьНачалоАтрибута + ЗаписатьТекст + ЗаписатьКонецАтрибута, используйте одну команду ЗаписатьАтрибут("Имя", "Значение").Пример оптимизированного заполнения строки отчета:
Счетчик = 0;
Для Каждого СтрокаДанных Из РезультатЗапроса Цикл
Счетчик = Счетчик + 1;
СтрНомер = XMLСтрока(Счетчик);
// Записываем наименование
ЗаписьXML.ЗаписатьНачалоЭлемента("T3RXXXXG2S");
ЗаписьXML.ЗаписатьАтрибут("ROWNUM", СтрНомер);
ЗаписьXML.ЗаписатьТекст(СтрокаДанных.КонтрагентНаименование);
ЗаписьXML.ЗаписатьКонецЭлемента();
// Записываем код ЕДРПОУ
ЗаписьXML.ЗаписатьНачалоЭлемента("T3RXXXXG3S");
ЗаписьXML.ЗаписатьАтрибут("ROWNUM", СтрНомер);
ЗаписьXML.ЗаписатьТекст(СтрокаДанных.КонтрагентКодПоЕДРПОУ);
ЗаписьXML.ЗаписатьКонецЭлемента();
// Записываем количество
ЗаписьXML.ЗаписатьНачалоЭлемента("T3RXXXXG5");
ЗаписьXML.ЗаписатьАтрибут("ROWNUM", СтрНомер);
ЗаписьXML.ЗаписатьТекст(XMLСтрока(СтрокаДанных.Количество));
ЗаписьXML.ЗаписатьКонецЭлемента();
КонецЦикла;
При выгрузке данных в XML критически важно, чтобы запрос возвращал "чистые" данные. Выясним, какие подводные камни могут встретиться:
Проблема NULL: Если вы используете левое соединение в запросе, некоторые поля могут содержать NULL. Функция XMLСтрока() при передаче в нее NULL может вести себя непредсказуемо или возвращать пустую строку, что может нарушить логику принимающей стороны. Всегда используйте функцию ЕСТЬNULL() в тексте запроса.
Проблема производительности (разрыв ссылок): Если в цикле вы обращаетесь к данным через точку от ссылки (например, Строка.Контрагент.Наименование), 1С будет выполнять отдельный запрос к базе данных на каждой итерации цикла. Проанализируем ситуацию: при 1000 строк вы получите 1000 лишних запросов к БД.
Решение: Получайте все необходимые строковые данные (Наименование, Код, ИНН) сразу в основном запросе. Идеально, если результат запроса — это плоская таблица с типами Строка, Число, Дата.
Если вам необходимо формировать сложные файлы (например, налоговую отчетность по строгим государственным схемам), ручная запись через ЗаписьXML становится слишком трудоемкой и рискованной. Рассмотрим альтернативу — механизм XDTO.
XDTO позволяет загрузить .xsd схему прямо в конфигурацию. После этого вы сможете работать с XML как с обычным объектом 1С:
Это исключает человеческий фактор при написании имен тегов вроде T3RXXXXG2S, так как они будут подтягиваться из схемы автоматически.
Подведем итоги нашего анализа. Для корректной работы с XML в 1С следует придерживаться следующих правил:
ЗначениеВСтрокуВнутр для экспорта данных.XMLСтрока() для преобразования чисел, дат и булевых значений.NULL и получать все данные «через точку» еще на этапе выполнения запроса.Соблюдение этих простых правил не только избавит вас от ошибки «Параметр 1», но и сделает ваши механизмы обмена данными быстрыми и надежными.