Как исправить ошибку «Значение не является значением объектного типа (ссылка)» при загрузке документа из текстового файла в 1С?

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

При реализации механизмов интеграции и загрузки данных из внешних текстовых файлов разработчики часто сталкиваются с ошибками разбора строковых данных и поиска ссылочных элементов. Рассмотрим типичную ситуацию, когда при попытке заполнить реквизит документа возникает ошибка «Значение не является значением объектного типа (ссылка)», выясним причины ее возникновения и разберем по шагам правильные способы восстановления документа.

Анализ ошибки при вызове метода поиска по коду

Проанализируем проблемную строку, на которой прерывается выполнение алгоритма:

Элемент = Справочники[ПолноеИмяСпр].НайтиПоКоду(КодЗначения).Ссылка;

Исключение времени выполнения обусловлено сразу несколькими факторами платформы 1С:Предприятие:

  1. Метод уже возвращает ссылку. Менеджер любого справочника при успешном выполнении метода НайтиПоКоду() возвращает готовую ссылку типа СправочникСсылка.<ИмяСправочника>. Обращение через точку к свойству Ссылка является избыточным.
  2. Элемент не найден или у справочника отключен код. Если элемент с указанным кодом не найден в информационной базе либо у справочника длина кода в конфигураторе установлена равной 0, метод НайтиПоКоду() возвращает Неопределено. Попытка обратиться к свойству .Ссылка у значения Неопределено немедленно вызывает ошибку «Значение не является значением объектного типа».
  3. Несоответствие данных файла механизму поиска. Посмотрим на пример выгрузки: в строке Автор=Абдулов Юрий Владимирович#Пользователи значением является ФИО пользователя, то есть наименование, а не числовой или строковый код. Поиск наименования через НайтиПоКоду() заведомо возвращает Неопределено. Для таких реквизитов требуется вызов НайтиПоНаименованию().

Исправление поиска и заполнения ссылочных данных

Разберем, как правильно организовать поиск элементов справочника с проверкой результата. Избавимся от лишнего обращения к .Ссылка и добавим проверку на корректность найденного значения:


МенеджерСправочника = Справочники[ПолноеИмяСпр];
// Ищем элемент по наименованию или по коду в зависимости от формата данных
ЭлементСсылка = МенеджерСправочника.НайтиПоНаименованию(КодЗначения);

Если Не ЗначениеЗаполнено(ЭлементСсылка) Тогда
    // Если по наименованию не найден, пробуем найти по коду
    ЭлементСсылка = МенеджерСправочника.НайтиПоКоду(КодЗначения);
КонецЕсли;

Если ЗначениеЗаполнено(ЭлементСсылка) Тогда
    НовыйДокумент[Шреквизит.Имя] = ЭлементСсылка;
Иначе
    // Обрабатываем ситуацию, когда элемент не найден в базе
    ЗаписьЖурналаРегистрации("ЗагрузкаДокумента", УровеньЖурналаРегистрации.Предупреждение, , , "Не найден элемент: " + КодЗначения);
КонецЕсли;

Скрытые ошибки алгоритма разбора файла

Помимо ошибки поиска ссылок, в исходном коде парсера присутствует ряд критических недочетов, которые приводят к сбоям при разборе документа. Проанализируем их:

  1. Несовпадение символов-разделителей в табличных частях. В строках файла используется вертикальная черта: ТабличныеЧасти;Запасы|ДатаОтгрузки=.... При этом в алгоритме выполняется поиск одинарной кавычки (РазделительТЧ = Найти(Стр, "'")). Функция не находит разделитель, возвращает 0, и вычисление позиций через Сред() падает с ошибкой неверной длины подстроки. Для разделителя ТЧ необходимо искать символ "|".
  2. Конфликт символа перечисления и справочника. В файле символ "#" отделяет имя справочника (#Пользователи, #БанковскиеСчета), а разделитель "&" вовсе отсутствует. В коде же символ "#" жестко привязан к обращению к коллекции Перечисления. Необходимо согласовать формат файла и кода либо проверять принадлежность имени к метаданным: Метаданные.Справочники.Найти(ИмяОбъекта) или Метаданные.Перечисления.Найти(ИмяОбъекта).
  3. Некорректное преобразование даты. Вызов Дата(ДатаДокумента) со строкой вида "20.04.2022 0:00:00" вызывает ошибку. Конструктор Дата() принимает строки только в каноническом представлении вида "ГГГГММДДЧЧММСС". Для даты пользовательского формата требуется предварительный разбор подстрок (день, месяц, год).
  4. Ошибочная логика создания строк табличной части. В коде добавление строки привязано к жесткому условию Если НаименованиеРТЧ = "Номенклатура". Однако в файле первой строкой ТЧ идет реквизит ДатаОтгрузки. В итоге переменная НоваяСтрока не инициализируется, и обращение к ней приводит к ошибке. Новую строку следует добавлять при изменении номера строки или явном маркере начала позиции.
  5. Отсутствие вызова метода записи. Созданный через Документы[Имя].СоздатьДокумент() объект существует только в оперативной памяти. В конце процедуры обязательно должен вызываться метод НовыйДокумент.Записать().

Оптимальные альтернативы ручному парсингу текстовых файлов

Разбор нестандартных текстовых форматов вручную через строковые функции Найти(), Лев() и Сред() крайне ненадежен и чувствителен к любым изменениям структуры данных. Рассмотрим более надежные стандартные механизмы 1С для выгрузки и загрузки документов:

  1. Использование СериализаторXDTO (XML или JSON). Стандартный механизм СериализаторXDTO.ПрочитатьXML() и СериализаторXDTO.ЗаписатьXML() автоматически сохраняет и восстанавливает структуру документа, табличные части и точные типы данных без необходимости ручного приведения типов и разбора строк.
  2. Идентификация ссылок по Уникальному Идентификатору (UUID). Если требуется текстовый формат обмена, вместо наименований или кодов следует передавать строковое представление УникальныйИдентификатор. Восстановление ссылки через Справочники[Имя].ПолучитьСсылку(Новый УникальныйИдентификатор(СтрокаUUID)) гарантирует однозначное сопоставление объектов и исключает дублирование.
← На главную