При обновлении технологической платформы «1С:Предприятие 8.3» до версий 8.3.14, 8.3.15, 8.3.16 и выше пользователи и разработчики систем, использующих интеграцию с решением БИТ.ФИНАНС (на базе ERP, УТ или БП), часто сталкиваются с критическим сбоем. Ошибка возникает при попытке создания, копирования или проведения документов управленческого учета, таких как бит_кзн_ПлатежнаяПозиция или бит_кзн_ЗаявкаНаРасходованиеСредств.
В процессе работы система внезапно завершает операцию аварийно, выдавая следующее сообщение об ошибке:
Поле объекта не обнаружено (ЭлементыФормы)
{ОбщийМодуль.бит_ОбщегоНазначения.Модуль(5189)}: ЭлементыФормы = ?(ФормаУправляемая, Форма.Элементы, Форма.ЭлементыФормы);
В этой статье мы подробно проанализируем технические причины изменения поведения платформы, детально разберем механизм возникновения ошибки и рассмотрим несколько практических вариантов решения этой проблемы — от быстрого временного исправления до правильного, отказоустойчивого кода, соответствующего стандартам разработки фирмы «1С».
Для того чтобы понять, почему проверенный годами код БИТ.ФИНАНС внезапно перестал работать на новых релизах платформы, обратимся к внутреннему устройству управляемого интерфейса 1С.
Начиная с версии платформы 8.3.14, фирма «1С» провела масштабную унификацию и переименование типов управляемого интерфейса. В частности, привычное понятие «Управляемая форма» во внутренних структурах платформы было переименовано в «Форма клиентского приложения». Соответственно, изменился и тип значения, возвращаемый для таких объектов.
В более ранних версиях платформы вызов функции Строка(Форма) (где параметр является управляемой формой) возвращал строковое представление "УправляемаяФорма". Разработчики БИТ.ФИНАНС опирались на это свойство в общем модуле бит_ОбщегоНазначения для определения типа формы (обычная или управляемая) перед обращением к ее элементам:
ФормаУправляемая = (Строка(Форма) = "УправляемаяФорма");
После обновления платформы до версии 8.3.14 и выше при отключенном режиме совместимости (или при его повышении) функция Строка(Форма) начала возвращать строковое представление "ФормаКлиентскогоПриложения". Рассмотрим цепочку последствий, к которой это приводит:
ФормаУправляемая получает значение Ложь, так как строковое представление формы больше не совпадает с жестко прописанным значением "УправляемаяФорма".ЭлементыФормы = ?(ФормаУправляемая, Форма.Элементы, Форма.ЭлементыФормы);
ФормаУправляемая равна Ложь, система выполняет правую ветку выражения и пытается обратиться к свойству Форма.ЭлементыФормы.ЭлементыФормы (оно присутствует только у обычных форм старого типа). Платформа генерирует исключение «Поле объекта не обнаружено (ЭлементыФормы)», и выполнение кода прекращается.Рассмотрим несколько способов устранения данной проблемы в зависимости от ваших возможностей по редактированию конфигурации.
Самый простой и быстрый способ вернуть систему к жизни — расширить проверку строкового представления формы в общем модуле. Нам нужно учесть оба возможных варианта возвращаемого значения строки (как для старых версий платформ, так и для новых).
Выполним следующие шаги по исправлению кода:
бит_ОбщегоНазначения (обратите внимание, что модуль должен быть доступен для редактирования; если конфигурация находится на поддержке, вам потребуется включить возможность изменения с сохранением поддержки).ФормаУправляемая.
ФормаУправляемая = ?(Строка(Форма) = "УправляемаяФорма" Или Строка(Форма) = "ФормаКлиентскогоПриложения", Истина, Ложь);
Этот способ мгновенно решает проблему, восстанавливая работоспособность всех механизмов настройки доступности элементов БИТ.ФИНАНС. Тем не менее, использование строкового приведения типов не считается «лучшей практикой» (best practice) при программировании в среде 1С, так как строковое представление теоретически может измениться в будущих версиях или зависеть от языковых настроек платформы.
Для создания надежного кода, который гарантированно не сломается при последующих обновлениях платформы, проанализируем типы данных напрямую, без преобразования их в строки. Нам необходимо выполнить сравнение типа объекта Форма с типами управляемой формы.
Однако здесь кроется важный нюанс обратной совместимости: если мы напрямую напишем Тип("ФормаКлиентскогоПриложения") в базе, которая запускается на старой платформе (или работает в режиме совместимости со старыми версиями), система выдаст ошибку Тип не определен. Чтобы избежать этого, применим безопасное динамическое определение типа:
ТипУправляемойФормы = Тип("ФормаКлиентскогоПриложения");
Если ТипУправляемойФормы = Неопределено Тогда
ТипУправляемойФормы = Тип("УправляемаяФорма");
КонецЕсли;
ФормаУправляемая = (ТипЗнч(Форма) = ТипУправляемойФормы);
Проанализируем этот код подробнее. Сначала мы пытаемся получить тип новой платформы "ФормаКлиентскогоПриложения". Если платформа старая, функция вернет Неопределено. В этом случае мы переопределяем переменную старым типом "УправляемаяФорма". После этого мы выполняем абсолютно безопасное и быстрое сравнение типов через функцию ТипЗнч(). Такой подход работает быстрее, чем преобразование объекта формы в длинную строку, и полностью защищен от ошибок совместимости.
Разберем еще один изящный способ решения задачи. Если конечная цель функции — получить доступ к коллекции элементов формы независимо от того, является ли она управляемой или обычной, мы можем уйти от явного анализа типов и использовать конструкцию попытки-исключения для определения доступных свойств объекта.
Заменим логику определения коллекции элементов формы следующим блоком:
Попытка
ЭлементыФормы = Форма.Элементы;
ФормаУправляемая = Истина;
Исключение
Попытка
ЭлементыФормы = Форма.ЭлементыФормы;
ФормаУправляемая = Ложь;
Исключение
ВызватьИсключение "Не удалось определить коллекцию элементов переданного объекта формы!";
КонецПопытки;
КонецПопытки;
Этот подход делает код максимально автономным. Даже если в далеком будущем фирма «1С» решит переименовать типы форм еще раз, логика работы программы не нарушится: система просто попытается прочитать свойство Элементы, а в случае неудачи обратится к свойству обычных форм ЭлементыФормы.
Если ваша информационная база находится на регулярной поддержке и вы не хотите вносить изменения в программный код вручную (чтобы не усложнять процедуру последующих обновлений), правильным решением будет обновление БИТ.ФИНАНС до актуального релиза.
Разработчики компании «Первый Бит» оперативно выпустили исправление данной ошибки в плановых обновлениях БИТ.ФИНАНС. Релизы конфигурации, выпущенные начиная с конца 2019 года, уже полностью адаптированы под новые стандарты работы платформы «1С:Предприятие 8.3» и не содержат данной уязвимости в общем модуле бит_ОбщегоНазначения.
Перед установкой обновлений обязательно сделайте резервную копию (архив выгрузки .dt или копию файла 1Cv8.1CD для файловых баз данных) информационной базы.