При автоматизации загрузки накладных из формата Excel (особенно УПД от поставщиков обуви, одежды или табака) разработчики часто сталкиваются со специфической ошибкой: «Ошибка передачи данных между клиентом и сервером. Значение недопустимого типа... Ошибка преобразования данных XDTO». В тексте ошибки обычно указывается на наличие недопустимого символа в определенной позиции. Давайте разберем природу этой проблемы и рассмотрим эффективные способы её решения.
Проанализируем ситуацию: ошибка возникает не в момент самого чтения файла методом Прочитать(), а в момент передачи объекта ТабличныйДокумент из серверной функции обратно на клиент. В 1С:Предприятии 8 при передаче сложных объектов между клиентом и сервером происходит их сериализация в формат XML.
Основная причина кроется в содержимом ячеек Excel. Если файл содержит коды маркировки (DataMatrix), в них часто присутствует спецсимвол GS (Group Separator), имеющий ASCII-код 29. Согласно стандарту XML 1.0, этот символ является «непечатным» и запрещенным к использованию в XML-структурах. Как только парсер XDTO встречает символ с кодом 29 в составе строки ячейки табличного документа, процесс передачи прерывается с ошибкой.
Рассмотрим подробнее позицию 71, упомянутую в тексте ошибки. В кодах маркировки «Честный Знак» это место часто совпадает с разделителем между различными группами данных (например, после серийного номера перед датой или кодом проверки). Это подтверждает, что проблема именно в специфических символах маркировки.
Самый правильный архитектурный подход в управляемом приложении — не передавать весь ТабличныйДокумент обратно на клиент, если в нем содержатся «проблемные» символы. Вместо этого мы выполним всю логику разбора файла непосредственно на сервере.
Разберем по шагам, как изменить код:
ТабличныйДокумент.Пример реализации серверной функции:
&НаСервере
Функция ПрочитатьДанныеФайлаНаСервере(АдресДокументаВХранилище, Расширение)
ДанныеДокумента = ПолучитьИзВременногоХранилища(АдресДокументаВХранилище);
ИмяФайла = ПолучитьИмяВременногоФайла(Расширение);
ДанныеДокумента.Записать(ИмяФайла);
ТабДок = Новый ТабличныйДокумент;
ТабДок.Прочитать(ИмяФайла);
// Создаем структуру для возврата данных
Результат = Новый Массив;
// Проходим по строкам (например, со 2-й строки, если 1-я — заголовок)
Для НомерСтроки = 2 По ТабДок.ВысотаТаблицы Цикл
СтрокаДанных = Новый Структура;
ТекстКодаМаркировки = ТабДок.Область(НомерСтроки, 5).Текст; // Допустим, код в 5-й колонке
// Очищаем текст от недопустимых символов XML перед добавлением в структуру
СтрокаДанных.Вставить("Номенклатура", ТабДок.Область(НомерСтроки, 1).Текст);
СтрокаДанных.Вставить("КодМаркировки", ОбщегоНазначения.ЗаменитьНедопустимыеСимволыXML(ТекстКодаМаркировки));
СтрокаДанных.Вставить("Количество", ТабДок.Область(НомерСтроки, 3).Значение);
Результат.Добавить(СтрокаДанных);
КонецЦикла;
Попытка
УдалитьФайлы(ИмяФайла);
Исключение
// Логируем ошибку удаления, если необходимо
КонецПопытки;
Возврат Результат; // Массив структур успешно передается через XDTO
КонецФункции
Если вам все же необходимо вывести данные в табличный документ на форме, воспользуйтесь встроенным механизмом БСП (Библиотеки Стандартных Подсистем). Функция ОбщегоНазначения.ЗаменитьНедопустимыеСимволыXML() заменяет символы с кодами 0-31 (кроме разрешенных) на пробелы или удаляет их.
Важный нюанс: Помните, что для системы «Честный Знак» символ GS является критически важным. Если вы удалите его из строки перед тем, как отправить код на проверку в сервис маркировки, код может стать невалидным. Поэтому:
Как упоминалось в обсуждении, альтернативным способом является чтение файла через COM-соединение. Этот метод позволяет обращаться к данным напрямую, минуя механизмы ТабличногоДокумента 1С.
Проанализируем этот подход:
Попытка
Excel = Новый COMОбъект("Excel.Application");
Книга = Excel.Workbooks.Open(ИмяФайла);
Лист = Книга.Sheets(1);
Для Стр = 1 По Лист.UsedRange.Rows.Count Цикл
ЗначениеЯчейки = Лист.Cells(Стр, 1).Value;
// Здесь мы можем сразу очистить строку
ЧистоеЗначение = ОбщегоНазначения.ЗаменитьНедопустимыеСимволыXML(Строка(ЗначениеЯчейки));
// Дальнейшая логика...
КонецЦикла;
Книга.Close(Ложь);
Excel.Quit();
Исключение
// Обработка ошибок при отсутствии Excel на сервере
КонецПопытки;
Однако помните, что этот метод требует установленного Microsoft Excel на сервере (если код выполняется &НаСервере) или на клиенте. Кроме того, работа через COM значительно медленнее, чем прямое чтение файла платформой 1С.
Если вы хотите избежать написания кода с нуля, рекомендуется рассмотреть типовые инструменты 1С:
xlsx, которые работают быстрее и не требуют наличия стороннего ПО.Подводя итог, отметим: столкнувшись с ошибкой недопустимых символов XML, первым делом проверьте, не пытаетесь ли вы вернуть ТабличныйДокумент с «сырыми» кодами маркировки с сервера на клиент. Перенос логики обработки данных на сервер — самый надежный способ исправить эту ошибку и повысить производительность вашей обработки.