В разработке на платформе 1С:Предприятие 7.7 программисты часто сталкиваются с существенным ограничением: в штатном функционале форм справочников и документов отсутствует предопределенная процедура ПослеЗаписи(). Существует только ПриЗаписи(), которая выполняется внутри транзакции. Это создает проблему, если нам нужно передать данные во внешнюю систему или выполнить действия, требующие, чтобы данные уже гарантированно были зафиксированы в базе данных и были доступны для чтения в актуальном виде.
Разберем подробно несколько проверенных временем способов решения этой задачи: от стандартных приемов платформы до использования мощных внешних компонент.
Проанализируем наиболее изящный способ, который позволяет выйти за пределы транзакции записи. Использование внешней компоненты FormEx позволяет сгенерировать событие, которое будет обработано системой сразу после того, как она освободится от текущих задач (включая закрытие транзакции записи).
Рассмотрим алгоритм реализации:
ПриЗаписи() модуля формы вызываем метод генерации внешнего события.Пример кода в модуле формы:
Процедура ПриЗаписи()
// Основная логика записи...
// Генерируем асинхронное событие через сервис FormEx
// Передаем идентификатор, тип события и ссылку на текущий объект
глСервис.ВнешнееСобытие("ОбменДанными", "ПослеЗаписиСправочника", ЗначениеВСтрокуВнутр(ТекущийЭлемент()));
КонецПроцедуры
В глобальном модуле в процедуре ПриОбработкеВнешнегоСобытия() мы ловим этот вызов:
Процедура глОбработкаВнешнегоСобытия(Источник, Событие, Данные) Экспорт
Если Источник = "ОбменДанными" Тогда
Если Событие = "ПослеЗаписиСправочника" Тогда
ОбъектСпр = ЗначениеИзСтрокиВнутр(Данные);
// Теперь объект гарантированно записан, можем выгружать его
ВыгрузитьОбъектВФайл(ОбъектСпр);
КонецЕсли;
КонецЕсли;
КонецПроцедуры
Выясним, как сделать решение еще более профессиональным с помощью компоненты 1С++. Она предоставляет прямой доступ к событию ПослеЗаписи через объект РасширениеФормы. Это избавляет нас от необходимости использовать внешние события и глобальный модуль.
Рассмотрим пример инициализации расширения в модуле формы:
Перем Расширение;
Процедура ПриОткрытии()
Расширение = СоздатьОбъект("РасширениеФормы");
Расширение.УстановитьИмяСобытия("ПослеЗаписи", "ПослеЗаписиФормы");
КонецПроцедуры
Процедура ПослеЗаписиФормы()
// Данное событие вызывается компонентой 1С++ автоматически
// сразу после успешного завершения записи в БД.
Сообщить("Элемент успешно зафиксирован в базе: " + ТекущийЭлемент());
ВыполнитьОбмен(ТекущийЭлемент());
КонецПроцедуры
Посмотрим на ситуацию, когда использование внешних компонент запрещено или нежелательно. Часто программисты пытаются вызвать Записать() внутри ПриЗаписи(), но сталкиваются с тем, что ТекущийЭлемент() все равно возвращает старые данные из кэша формы. Чтобы получить актуальные значения, необходимо создать отдельный объект-справочник и найти в нем текущий элемент.
Разберем этот прием:
Процедура ПриЗаписи()
// Вызываем стандартную запись, чтобы данные ушли в буфер БД
Записать();
// Создаем новый контекст объекта для чтения актуальных данных
Спр = СоздатьОбъект("Справочник.Номенклатура");
Если Спр.НайтиЭлемент(ТекущийЭлемент()) = 1 Тогда
// Здесь Спр.Наименование уже будет содержать новое значение
ВыгрузитьЗначение(Спр.Наименование);
КонецЕсли;
КонецПроцедуры
Важно: При таком подходе стоит учитывать, что транзакция все еще может быть открыта, если запись инициирована из другой транзакции. Однако для большинства задач обмена данными этого достаточно.
Проанализируем самый надежный системный способ. Если в конфигурации включена компонента "Управление распределенными информационными базами" (УРБД), система автоматически ведет учет всех измененных объектов в служебной таблице _1SUPDTS.
Преимущества этого метода:
СоздатьОбъект().Вы можете написать обработку, которая по расписанию (через ОбработкаОжидания) проверяет наличие записей в системных таблицах и выполняет выгрузку.
Если ваша база работает на MS SQL Server, мы можем реализовать логику на уровне СУБД. Это "тяжелая артиллерия", которая полезна при интеграции с высоконагруженными системами.
Разберем по шагам:
AFTER UPDATE, INSERT на таблицу справочника (например, SC123).ROWID или ID) измененного элемента в нашу очередь.Этот метод гарантирует, что вы поймаете изменение, даже если оно было сделано прямым запросом к базе данных (хотя так делать в 1С 7.7 крайне не рекомендуется).
Подведем итоги нашего анализа. Выбор метода зависит от ваших технических условий:
СоздатьОбъект).Помните, что архитектура 1С 7.7 требует особого внимания к транзакциям. Любые длительные операции (например, отправка данных по HTTP или запись в тяжелый файл) лучше выносить за пределы процедуры ПриЗаписи(), чтобы не блокировать работу других пользователей в базе данных.