Конфликт внутренних идентификаторов у объекта

Конфликт внутренних идентификаторов у объекта

Office 365, AD, Active Directory, Sharepoint, C#, Powershell. Технические статьи и заметки.

1С 8.3. Расширение — ошибка конфликта обработчика событий формы

Дано: платформа 1С 8.3.10 (на примере конфигурации 1С: Университет ПРОФ)
Проблема: перестало работать событие формы в одном из расширений.
Описание:
Два программиста написали два разных расширения конфигурации, в которых сослались на одну и ту же форму и унаследовали одно и то же событие формы — "ПриСозданииНаСервере".
В расширении №1 использовался тип перехватчика события "После".
В расширении №2 использовался тип перехватчика события "Вместо".
Пока не было добавлено расширение 2, первое расширение работало нормально. Однако после загрузки второго расширения, событие из первого перестало работать (событие из второго расширения работало).

Этапы решения проблемы:
Как мы знаем, аннотации (&Вместо, &Перед, &После) для обработчиков событий форм не используются (по крайней мере, пробовала это сделать, но ничего не получилось). Приходится фактически заменять сам обработчик и прописывать его в свойствах самой формы. Т.е. при попытке добавить расширение для обработчика возникнет такое сообщение:
"Метод является обработчиком события. Добавить расширение обработчика?"

Пыталась нажимать "Нет" и делать с аннотациями, но, как уже писала раньше, это не работает.

Вот пример двух расширений, ссылающихся на одну и ту же форму:

Свойства первого расширения, задание обработчика "После":

Свойства второго расширения, задание обработчика "Вместо":

Так это выглядит непосредственно в коде расширения:

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

При запуске конфигурации получаю ошибку:
Ошибка инициализации модуля по причине:
<ГрафикПлатежей Справочник.Объекты.Форма.ФормаЭлемента.Форма(589,11)>:
Процедура или функция с указанным именем уже определена (УП_ПриСозданииНаСервереПосле)
Процедура >УП_ПриСозданииНаСервереПосле(Отказ, СтандартнаяОбработка)

Затем заметила, что действительно назвала обработчики одинаково (т.к. скопировала название из другого). Переименовала префикс во втором расширении:

Однако опять возникла ошибка:
<ДоговорУП Справочник.Объекты.Форма.ФормаЭлемента.Форма(184)>:
Ошибка при вызове метода контекста (Добавить)
Команда = ЭтаФорма.Команды.Добавить("ФильтрацияУП");
по причине: Имя не уникально

Почему-то событие формы начало отрабатывать дважды, а т.к. там добавление пункта меню, оно вызывало эту ошибку.
Тут оказалась сама виновата, т.к. при переименовании процедуры обработчика, нужно было зайти в свойства самой формы и также заменить процедуру обработчика события:

Читайте также:  Как найти системный администратор в компьютере

Вроде бы всё должно работать нормально, но при запуске объекта с данным расширением опять ошибка:
Запрещено изменение параметра, отменяющего действие (параметр номер 1 в процедуре)

Т.е. ругается на попытку сделать отказ в процедуре второго расширения:
Отказ = Истина;

Получается в обработчике типа После нельзя делать "Отказ". Но мы знаем, что в типе "Вместо" работало. Проверяем, как работает в типе "Перед":

Теперь работает нормально, с другим не конфликтует.

PS: в итоге, с целью избавиться от подобных проблем в будущем, всё равно оптимизировала код так, что перехват этих обработчиков больше не потребовался 🙂

Основное назначение расширений в БИТ:МДМ — это реализация сложного интерфейса в формах объектах НСИ, требующего программирования на языке 1С Предприятие ( условия видимости, доступности, автозаполнение, контроль значений реквизитов и т.п.). Изменение состава метаданных у хранимых объектов в расширении не допускается. В связи с этим у заимствованных свойств, связанных с хранением данных (например реквизиты справочников, перечисления и т.п. ) должен быть установлен признак " Контролируемое свойство " ( подробно о терминологии и расширениях в общем см. https://its.1c.ru/db/v8310doc#bookmark:dev:TI000001513). Для форм справочников, для модулей соответственно выставляется признак "Модифицируемое св-во"

Из предыдущего пункта автоматически следует, что любые изменения контролируемых свойств из списка ниже автоматически ведут к неработоспособности расширения:

  1. Изменение идентификатора реквизита ( например ТипПродукции на ТипыПродукции)
  2. Изменение простого типа данных ( Например со строка (100) на строка (150))
  3. Удаление или добавление типа даннных в сложном типе ( Например со "строка(10)" на "Число,Строка(10)"

Не забывайте про стандартные реквизиты ( например изменение длины кода и наименования)

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

При подключении расширения сопоставление заимствованных объектов ведется по паре "Наименование объекта метаданных, внутренний идентификатор объекта"

Для обращения к предопределенному элементу справочника из расширения, его значение должно быть заимствовано из основной конфигурации, и так же как для объектов и свойств, для предопределенных значений действует предыдущее правило — их нужно заимствовать только из копии рабочей базы или из скопированной модели.

Читайте также:  Как подключить клавишу с подсветкой в автомобиле

Предопределенные элементы справочников описываются в справочнике "Предопределенные элементы", а не создаются в конфигураторе

Для проверки корректности расширения используйте либо команду "Проверка возможности применения всех расширений" в конфигураторе, либо в предприятии "Все функцииСтандартныеУправление расширениями конфигурацииПроверить применимость"

Если в расширении необходимо модифицировать модуль объекта, то такое расширение можно подключить только с отключенным безопасным режимом, иначе при попытке обратиться к модулю объекта возникнет ошибка типа "Ошибка расширения модуля ‘Справочник.нси_Объект_УУАЗ_Заказы.МодульОбъекта’: расширение модуля запрещено из-за того, что расширение ‘Заказы’ подключено в безопасном режиме"

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

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

Использовать команду Расширения – Обновить расширение формы редактора формы.

Если требуется посмотреть, как выглядит сохраненная форма – следует использовать команду Расширения – Показать сохраненную форму в редакторе заимствованной управляемой формы.

Модифицировать расширение, так чтобы в «запоминаемую» форму попали только нужные элементы ( например только страницу "ОсновнаяСтраница"). Для этого необходимо воспользоваться инструкцией Удаление из интерфейса неиспользуемых страниц формы

Если пользователь в предприятии изменяет настройки формы ( например порядок вывода реквизитов), то эти изменение имеют более высокий приорите, чем изменения в расширении. Для возврата формы к виду, заданному в расширении необходимо воспользоваться командой "Установит стандартные настройки"

Очень часто платформа падает при удалении из расширения какого то реквизита или объекта, в этом случае необходимо отключить проверку СервисПараметрыОбщие — снять флаг "При удалении выполнять проверку в модулях"

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

Очевидным способом решения задачи является постоянная проверка наличия свойства объекта перед обращением к нему.

Читайте также:  Схема монитора lg w2042s

&НаКлиентеНаСервереБезКонтекста
Функция ЕстьСвойство(ОбъектСвойства, ИмяСвойства)

ПроверочноеЗначение = Новый УникальныйИдентификатор;
СтруктураПроверки = Новый Структура(ИмяСвойства, ПроверочноеЗначение);
ЗаполнитьЗначенияСвойств(СтруктураПроверки, ОбъектСвойства);
ЕстьСвойство = СтруктураПроверки[ИмяСвойства] <> ПроверочноеЗначение;

Если ЕстьСвойство(Объект, "ИНН") .

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

При использовании выгрузки расширения в файли и последующей загрузки его из файлов возникает ошибка, приводящая к невозможности редактирования заголовков реквизитов ( именно из файлов а не из одного файла). Если возникла необходимость загрузки расширений из файлов — необходимо проверить возможность редактирования заголовков.

Для автоматического распространения и подключения расширения требуется добавить его как макеты в метаданных справочника нси_ОбъектыНСИ с типом ДвоичныеДанные. Требуется соблюдать именование:

_ _
Например, интерфейс_нси_Объект_Контрагенты_ЗаполнениеПоЕГРЮЛ

По ссылке можно посмотреть статью с видео, описывающим тонкие моменты при сравнения форм при применении расширения

Функция ПолучитьИД_Вариант1(Объект)
Перем Стр;
Стр=ЗначениеВСтрокуВнутр(Объект);
СЗ=СоздатьОбъект("СписокЗначений");
СЗ.ИзСтрокиСРазделителями(Сред(Стр,2,СтрДлина(Стр)-2));
Возврат СЗ.ПолучитьЗначение(СЗ.РазмерСписка());
КонецФункции
//_____________________________________________________________________________

Функция ПолучитьИД_Вариант2(Объект)
Перем Стр;
СЗ=СоздатьОбъект("СписокЗначений");
СЗ.ДобавитьЗначение("",Объект);
СЗ.ПолучитьЗначение(1,Стр);
Возврат Стр;
КонецФункции
//_____________________________________________________________________________

Процедура Сформировать()
// Пусть "Объект" — это реквизит формы типа "Справочник"
Сообщить("Объект: "+Объект.ТекущийЭлемент());
Сообщить("Вариант 1: "+ПолучитьИД_Вариант1(Объект.ТекущийЭлемент()));
Сообщить("Вариант 2: "+ПолучитьИД_Вариант2(Объект.ТекущийЭлемент()));
КонецПроцедуры

Если нужно получить id в том виде, в котором он хранится в таблицах 1С, воспользуйтесь недокументированной функцией _IdToStr(),
н-р: Сообщить("Вариант 1: "+_IdToStr(ПолучитьИД_Вариант1(Объект.ТекущийЭлемент())));
Подробнее о недокументированных возможностях 1С можно посмотреть здесь.

Необходимо добавить, что если база с использованием УРБД, то система не контролирует уникальность этого идентификационного номера.
Необходимо еще к номеру добавлять место создания, т.е. префикс той базы, где был создан объект.

Формат строки, полученной с помощью ф-ии ЗначениеВСтрокуВнутр():

Список = СоздатьОбъект("СписокЗначений");
Список.ДобавитьЗначение("O"); // тип
Список.ДобавитьЗначение("0"); // длина
Список.ДобавитьЗначение("0"); // точность
Список.ДобавитьЗначение("255"); // ИД вида объекта
Список.ДобавитьЗначение("0"); // флаг неотр. (?)
Список.ДобавитьЗначение("0"); // флаг разделения триад (?)
Список.ДобавитьЗначение("9548"); // ИД объекта
Зн = ЗначениеИзСтрокиВнутр("<"+Список.ВСтрокуСРазделителями()+">")

Седьмой параметр списка — строка 13 символов:
01-10 ИД вида объекта
11-20 ИД объекта
21-23 ИД информационной базы (УРИБ).
В таком виде он будет, если передавать не Объект.ТекущийЭлемент(), а просто Объект.

Ссылка на основную публикацию
Коды для разблокировки телефона нокиа
Секретные коды Nokia для сброса, проверки и настроек. На этой странице собраны все полезные секретные и не секретные коды для...
Киностудия windows live не сохраняет фильм
Запрос в поисковых системах «MovieMaker не сохраняет фильм что делать», говорит о распространенной проблеме записи готового видеоролика в Муви Мейкер...
Кнопка как в предыдущем разделе не активна
Опубликовано Михаил Непомнящий в 18.04.2017 18.04.2017 Текстовый редактор Microsoft Word позволяет добавлять два типа колонтитулов – верхние и нижние, а...
Команда обновить в автокаде
Все действия в программе AutoCAD мы совершаем с помощью команд, которые вызываем на ленте из контекстного меню, либо же вводом...
Adblock detector