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