Почему документ 1С не проводится автоматически и возникает ошибка Значение не является значением объектного типа Пустая

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

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

Анализ проблемы и механизма возникновения ошибки

Разберем исходную ситуацию. В конфигурации реализован механизм: при установке документу статуса ПроверенБухгалтером и последующем проведении автоматически создается или перезаписывается связанный бухгалтерский документ (например, ПеремещениеТоваров или ПоступлениеТоваровУслуг).

При программном запуске обработки пакетного проведения система выдает ошибку в модуле формирования перемещения:


Если (ДокументБух.Пустая) или (ДокументБух.Дата=Дата(1,1,1,0,0,0)) тогда 
    НовыйДок = Документы.ПеремещениеТоваров.СоздатьДокумент; 
Иначе 
    НовыйДок = ДокументБух.ПолучитьОбъект; 
    Если НовыйДок.ПометкаУдаления тогда 
        НовыйДок.УстановитьПометкуУдаления(Ложь); 
        НовыйДок.Записать; 
    КонецЕсли; 
    НовыйДок.Товары.Очистить; 
КонецЕсли;

Проанализируем причину падения: метод Пустая() доступен исключительно для данных ссылочного типа (ссылок справочников, документов, планов счетов и т. д.). Если в переменную ДокументБух попадает значение Неопределено, Null, число или строка, обращение к свойству или методу через точку генерирует исключение «Значение не является значением объектного типа».

Выясним, откуда вызывалась процедура. В обработчике события ПередЗаписью документа находился следующий фрагмент:


Если Клиент = Справочники.Контрагенты.НайтиПоКоду("00-000255") и ((СтатусДокумента = Перечисления.ЕКС_СтатусДокумента.ПроверенБухгалтером) и (СокрЛП(Организация.Код) = "1" или СокрЛП(Организация.Код) = "2")) тогда 
    ТЗ_Товары = Товары.Выгрузить; 
    ВХК_МодульДляПриходнойНакладной.СоздатьПеремещение1(ДокументБух, Дата, Номер, ТЗ_Товары, Организация, Клиент, ВидТоваров); 
КонецЕсли;

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

Пошаговое устранение ошибок в алгоритме

Разберем по шагам, как исправить логику и сделать код надежным и устойчивым к ошибкам.

  1. Замена небезопасной проверки на функцию ЗначениеЗаполнено.

    Для проверки любых типов данных (ссылок, строк, дат, объектов) в платформе 1С:Предприятие следует использовать глобальную контекстную функцию ЗначениеЗаполнено(). Она корректно возвращает Ложь для пустых ссылок, пустых дат и значений Неопределено, предотвращая аварийное завершение программы.

    
    Если НЕ ЗначениеЗаполнено(ДокументБух) Тогда
        НовыйДок = Документы.ПеремещениеТоваров.СоздатьДокумент();
    Иначе
        НовыйДок = ДокументБух.ПолучитьОбъект();
        Если НовыйДок.ПометкаУдаления Тогда
            НовыйДок.УстановитьПометкуУдаления(Ложь);
            НовыйДок.Записать();
        КонецЕсли;
        НовыйДок.Товары.Очистить();
    КонецЕсли;
    
  2. Корректное хранение и получение ссылки на связанный документ.

    Нельзя полагаться на неявные переменные модулей. Ссылка на создаваемый дочерний документ должна либо храниться в реквизите родительского документа (например, ДокументОснование или отдельный реквизит ДокументПеремещения), либо определяться через запрос к регистру сведений/критерию отбора перед вызовом процедуры.

  3. Исправление обработки ошибок в пакетном проведении.

    Посмотрим на код обработки проведения из темы:

    
    Попытка 
        ОбДок.Записать(РежимЗаписиДокумента.Проведение); 
    Исключение 
        Сообщить(строка(док) + " " + строка(ОписаниеОшибки)); 
        возврат; 
    КонецПопытки;
    

    Использование оператора Возврат внутри цикла приводит к тому, что при ошибке на одном документе обработка полностью прерывает свою работу и не проводит все последующие документы. Заменим Возврат на оператор Продолжить, чтобы обработка зарегистрировала ошибку и перешла к следующему элементу выборки.

  4. Отказ от ненадежного поиска по коду в коде конфигурации.

    Конструкции вида Справочники.Контрагенты.НайтиПоКоду("00-000255") крайне уязвимы: при смене префиксации, удалении или дублировании элементов логика перестает работать. Рекомендуется использовать предопределенные элементы, константы или регистры сведений для хранения настроек соответствия.

Причины ложной модифицированности документов при открытии

В исходном вопросе также упоминается проблема: при открытии некоторых документов сразу устанавливается признак модифицированности (звездочка в заголовке окна), хотя пользователь не вносил изменения вручную. Проанализируем основные причины такого поведения:

  1. Неявное присвоение значений в событиях формы: В обработчиках ПриСозданииНаСервере, ПриОткрытии или ПриЧтенииНаСервере происходит программная инициализация реквизитов (например, подстановка текущей даты, пользователя, подразделения или склада), из-за чего форма считает объект измененным.
  2. Автоматическое приведение составных типов: Если реквизит объекта имеет составной тип и не заполнен, форма при открытии может автоматически приводить его к типу по умолчанию, вызывая модификацию.
  3. Программный пересчет табличных частей: Автоматический пересчет итоговых сумм или НДС при открытии формы без предварительной проверки реального изменения данных приводит к перезаписи строк табличной части.

Для устранения ложной модифицированности необходимо перенести алгоритмы заполнения по умолчанию в модуль объекта (в обработчик ОбработкаЗаполнения) и исключить безусловную перезапись реквизитов при чтении данных формы.

← На главную