При разработке пакетных обработок проведения и механизмов автоматического создания связанных документов разработчики нередко сталкиваются с ситуацией: интерактивно из формы документ проводится и формирует подчиненные структуры без сбоев, но при массовой обработке процесс завершается аварийно. Рассмотрим детально, почему возникает ошибка «Значение не является значением объектного типа (Пустая)», как работает передача параметров в транзакциях и как правильно организовать алгоритм пакетного проведения.
Разберем исходную ситуацию. В конфигурации реализован механизм: при установке документу статуса ПроверенБухгалтером и последующем проведении автоматически создается или перезаписывается связанный бухгалтерский документ (например, ПеремещениеТоваров или ПоступлениеТоваровУслуг).
При программном запуске обработки пакетного проведения система выдает ошибку в модуле формирования перемещения:
Если (ДокументБух.Пустая) или (ДокументБух.Дата=Дата(1,1,1,0,0,0)) тогда
НовыйДок = Документы.ПеремещениеТоваров.СоздатьДокумент;
Иначе
НовыйДок = ДокументБух.ПолучитьОбъект;
Если НовыйДок.ПометкаУдаления тогда
НовыйДок.УстановитьПометкуУдаления(Ложь);
НовыйДок.Записать;
КонецЕсли;
НовыйДок.Товары.Очистить;
КонецЕсли;
Проанализируем причину падения: метод Пустая() доступен исключительно для данных ссылочного типа (ссылок справочников, документов, планов счетов и т. д.). Если в переменную ДокументБух попадает значение Неопределено, Null, число или строка, обращение к свойству или методу через точку генерирует исключение «Значение не является значением объектного типа».
Выясним, откуда вызывалась процедура. В обработчике события ПередЗаписью документа находился следующий фрагмент:
Если Клиент = Справочники.Контрагенты.НайтиПоКоду("00-000255") и ((СтатусДокумента = Перечисления.ЕКС_СтатусДокумента.ПроверенБухгалтером) и (СокрЛП(Организация.Код) = "1" или СокрЛП(Организация.Код) = "2")) тогда
ТЗ_Товары = Товары.Выгрузить;
ВХК_МодульДляПриходнойНакладной.СоздатьПеремещение1(ДокументБух, Дата, Номер, ТЗ_Товары, Организация, Клиент, ВидТоваров);
КонецЕсли;
В данном контексте переменная ДокументБух не была объявлена или заполнена в текущей процедуре, поэтому платформа присваивала ей значение Неопределено по умолчанию. При интерактивной работе на форме значение могло заполняться в контексте элементов управления, однако при вызове метода Объект.Записать(РежимЗаписиДокумента.Проведение) из внешней обработки контекст формы полностью отсутствует.
Разберем по шагам, как исправить логику и сделать код надежным и устойчивым к ошибкам.
Для проверки любых типов данных (ссылок, строк, дат, объектов) в платформе 1С:Предприятие следует использовать глобальную контекстную функцию ЗначениеЗаполнено(). Она корректно возвращает Ложь для пустых ссылок, пустых дат и значений Неопределено, предотвращая аварийное завершение программы.
Если НЕ ЗначениеЗаполнено(ДокументБух) Тогда
НовыйДок = Документы.ПеремещениеТоваров.СоздатьДокумент();
Иначе
НовыйДок = ДокументБух.ПолучитьОбъект();
Если НовыйДок.ПометкаУдаления Тогда
НовыйДок.УстановитьПометкуУдаления(Ложь);
НовыйДок.Записать();
КонецЕсли;
НовыйДок.Товары.Очистить();
КонецЕсли;
Нельзя полагаться на неявные переменные модулей. Ссылка на создаваемый дочерний документ должна либо храниться в реквизите родительского документа (например, ДокументОснование или отдельный реквизит ДокументПеремещения), либо определяться через запрос к регистру сведений/критерию отбора перед вызовом процедуры.
Посмотрим на код обработки проведения из темы:
Попытка
ОбДок.Записать(РежимЗаписиДокумента.Проведение);
Исключение
Сообщить(строка(док) + " " + строка(ОписаниеОшибки));
возврат;
КонецПопытки;
Использование оператора Возврат внутри цикла приводит к тому, что при ошибке на одном документе обработка полностью прерывает свою работу и не проводит все последующие документы. Заменим Возврат на оператор Продолжить, чтобы обработка зарегистрировала ошибку и перешла к следующему элементу выборки.
Конструкции вида Справочники.Контрагенты.НайтиПоКоду("00-000255") крайне уязвимы: при смене префиксации, удалении или дублировании элементов логика перестает работать. Рекомендуется использовать предопределенные элементы, константы или регистры сведений для хранения настроек соответствия.
В исходном вопросе также упоминается проблема: при открытии некоторых документов сразу устанавливается признак модифицированности (звездочка в заголовке окна), хотя пользователь не вносил изменения вручную. Проанализируем основные причины такого поведения:
ПриСозданииНаСервере, ПриОткрытии или ПриЧтенииНаСервере происходит программная инициализация реквизитов (например, подстановка текущей даты, пользователя, подразделения или склада), из-за чего форма считает объект измененным.Для устранения ложной модифицированности необходимо перенести алгоритмы заполнения по умолчанию в модуль объекта (в обработчик ОбработкаЗаполнения) и исключить безусловную перезапись реквизитов при чтении данных формы.