Как изменить данные или снять пометку удаления у объекта с закрытым модулем в 1С

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

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

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

Почему не работает подписка на событие

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

Однако в платформе 1С соблюдается строгий порядок выполнения цепочки событий:

  1. Сначала вызывается обработчик в модуле самого объекта.
  2. Только затем вызываются обработчики внешних подписок на событие.

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

Кроме того, механизм расширений конфигурации с аннотациями &Вместо или &ИзменениеИКонтроль также неприменим к методам модулей, поставляемых без исходного текста.

Способ 1. Пересоздание объекта с сохранением ссылки (UUID)

Если логика закрытого модуля проверяет именно факт изменения существующего объекта (например, сравнивает Ссылка.ПометкаУдаления = Истина и ЭтотОбъект.ПометкаУдаления = Ложь), то запись нового объекта обычно не блокируется.

Рассмотрим, как можно программно пересоздать объект с сохранением его исходного уникального идентификатора:

  1. Считываем все реквизиты и табличные части исходного помеченного объекта.
  2. Непосредственно удаляем исходный объект методом Удалить().
  3. Создаем новый экземпляр объекта и назначаем ему прежний идентификатор с помощью метода УстановитьСсылкуНового().
  4. Записываем объект уже без пометки удаления.

Посмотрим на пример программного кода:


// Получаем исходный объект и его идентификатор
ОбъектСсылка = ВыбранныйЭлементСсылка;
Идентификатор = ОбъектСсылка.УникальныйИдентификатор();
ИсходныйОбъект = ОбъектСсылка.ПолучитьОбъект();

// Сохраняем значения реквизитов (например, для справочника)
СтруктураРеквизитов = Новый Структура;
СтруктураРеквизитов.Вставить("Наименование", ИсходныйОбъект.Наименование);
СтруктураРеквизитов.Вставить("Код", ИсходныйОбъект.Код);

// Удаляем старый объект без проверок
ИсходныйОбъект.Удалить();

// Создаем новый объект с тем же UUID
НовыйОбъект = Справочники.Номенклатура.СоздатьЭлемент();
НовыйОбъект.УстановитьСсылкуНового(Справочники.Номенклатура.ПолучитьСсылку(Идентификатор));
ЗаполнитьЗначенияСвойств(НовыйОбъект, СтруктураРеквизитов);
НовыйОбъект.ПометкаУдаления = Ложь;
НовыйОбъект.Записать();

Способ 2. Очистка или замена закрытого модуля через выгрузку в файлы

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

Разберем по шагам алгоритм действий:

  1. В конфигураторе выполним выгрузку конфигурации в файлы (через меню Конфигурация — Выгрузить конфигурацию в файлы).
  2. В полученном каталоге найдем XML-описание и бинарный блок соответствующего объекта метаданных.
  3. Удалим или заменим зашифрованный блок модуля на стандартный пустой модуль.
  4. Выполним загрузку конфигурации из файлов обратно в информационную базу.
  5. Обновим конфигурацию базы данных (F7).

После этого модуль станет открытым для редактирования либо полностью очистится от блокирующего кода.

Способ 3. Прямая правка в базе данных СУБД (SQL) и сопутствующие риски

Если конфигурацию изменять нельзя, остается вариант изменения данных на уровне СУБД. В таблицах СУБД за признак пометки удаления отвечает колонка _Marked (где 0x00 — пометка снята, 0x01 — пометка установлена).

Однако при выполнении прямого SQL-запроса UPDATE необходимо учитывать критические риски:

  1. Кэширование данных: Сервер 1С кэширует считываемые объекты. После изменения поля в СУБД сеансы пользователей продолжат видеть пометку удаления до полной очистки серверного кэша или перезапуска службы ragent.
  2. Механизмы планов обмена: Прямой апдейт в SQL не создает записей в таблицах регистрации изменений (таблицы с префиксом _ChangeRec*). Объект не будет выгружен в другие узлы при следующей синхронизации.
  3. Нарушение ссылочной целостности: Если при снятии пометки удаления должны восстанавливаться связанные движения или подчиненные объекты, на уровне SQL эти зависимости останутся в несогласованном состоянии.

Способ 4. Обращение к поставщику решения или дешифрация

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


Если ОбменДанными.Загрузка Тогда
    Возврат;
КонецЕсли;

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

← На главную