1С 8.3 Проверка на изменение полей регистра сведений ПередЗаписью, кеширование средствами БСП
Данные > Примеры кода 1С > 1С 8.3 Регистры сведений
Перейти в раздел примеры кода 1С 8.3:
//by telegram t.me/yellow_pad (Жёлтая тетрадь Блог программиста 1C)
Проверить изменение поля регистра сведений ПередЗаписью. В отличие от объектов ссылочного типа, при изменении регистра платформа сперва записывает пустой набор записей, а затем набор записей с данными. Выходит, что в момент записи фиксируемых данных прежних данных в базе уже нет, и сверить новые значения полей не с чем.
Вариант решения - перед записью пустого набора получить запросом текущие данные регистра и закешировать их во временное хранилище, передав во вторую итерацию ссылку на это хранилище (например, через параметр сеанса). БСП: БуферОбмена - кеширование любых данных без передачи адреса хранилища
В БСП реализован универсальный механизм - БуферОбмена, и он никак не связан с буфером обмена ОС. Он принимает любые данные, сохраняет их во временное хранилище, а адрес временного хранилища записывает в параметр сеанса БуферОбмена. Механизмом можно пользоваться для передачи данных в коде без возможности передать напрямую адрес временного хранилища. В типовых конфигурациях используется для передачи строк табличных частей и вложенных файлов.
ОбщегоНазначения.СкопироватьВБуферОбмена(Данные);
БуферОбмена = ОбщегоНазначения.СтрокиИзБуфераОбмена();
Данные = БуферОбмена.Данные;
БуферОбмена = ОбщегоНазначения.СтрокиИзБуфераОбмена();
Данные = БуферОбмена.Данные;
Пример использования механизма - отслеживание изменений полей регистра сведений ПередЗаписью:
Пример кода в 1С 8.3:
Процедура ПередЗаписью(Отказ, Замещение)
Если ОбменДанными.Загрузка Тогда
Возврат;
КонецЕсли;
ИмяИсточника = ОбщегоНазначения.КонтрольнаяСуммаСтрокой(Новый Структура("Пользователь, Отборы", ИмяПользователя(), Отбор.Задача.Значение));
Если ЭтотОбъект.Количество() = 0 Тогда
ОбщегоНазначения.СкопироватьВБуферОбмена(ПолучитьНачальныеДанные(Отбор.Задача.Значение), ИмяИсточника);
Иначе
БуферОбмена = ОбщегоНазначения.СтрокиИзБуфераОбмена();
Если БуферОбмена.Источник = ИмяИсточника Тогда // новая запись
НачальныеДанные = БуферОбмена.Данные;
Иначе
НачальныеДанные = Неопределено;
КонецЕсли;
ТекущаяДата = ТекущаяДата();
Для Каждого Запись Из ЭтотОбъект Цикл
ТекНачальныеДанные = ?(НачальныеДанные = Неопределено, Неопределено, НачальныеДанные.Найти(Запись.Задача, "Задача"));
Если ТекНачальныеДанные = Неопределено Тогда // запись создана
Запись.ДатаСоздания = ТекущаяДата;
Продолжить;
КонецЕсли;
Если ЗначениеЗаполнено(Запись.Ссылка)
И НЕ Запись.Ссылка = ТекНачальныеДанные.Ссылка Тогда // получена новая ссылка
Запись.ДатаПолученияСсылки = ТекущаяДата;
КонецЕсли;
КонецЦикла;
// очистим буфер обмена
ОбщегоНазначения.СкопироватьВБуферОбмена(Неопределено, ИмяИсточника);
КонецЕсли;
КонецПроцедуры
Функция ПолучитьНачальныеДанные(Задачи)
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| *
|ИЗ
| РегистрСведений.ЗадачиДляОбмена КАК ЗадачиДляОбмена
|ГДЕ
| ЗадачиДляОбмена.Задача В (&Задачи)";
Запрос.УстановитьПараметр("Задачи", Отбор.Задача.Значение);
Возврат Запрос.Выполнить().Выгрузить();
КонецФункции
Если ОбменДанными.Загрузка Тогда
Возврат;
КонецЕсли;
ИмяИсточника = ОбщегоНазначения.КонтрольнаяСуммаСтрокой(Новый Структура("Пользователь, Отборы", ИмяПользователя(), Отбор.Задача.Значение));
Если ЭтотОбъект.Количество() = 0 Тогда
ОбщегоНазначения.СкопироватьВБуферОбмена(ПолучитьНачальныеДанные(Отбор.Задача.Значение), ИмяИсточника);
Иначе
БуферОбмена = ОбщегоНазначения.СтрокиИзБуфераОбмена();
Если БуферОбмена.Источник = ИмяИсточника Тогда // новая запись
НачальныеДанные = БуферОбмена.Данные;
Иначе
НачальныеДанные = Неопределено;
КонецЕсли;
ТекущаяДата = ТекущаяДата();
Для Каждого Запись Из ЭтотОбъект Цикл
ТекНачальныеДанные = ?(НачальныеДанные = Неопределено, Неопределено, НачальныеДанные.Найти(Запись.Задача, "Задача"));
Если ТекНачальныеДанные = Неопределено Тогда // запись создана
Запись.ДатаСоздания = ТекущаяДата;
Продолжить;
КонецЕсли;
Если ЗначениеЗаполнено(Запись.Ссылка)
И НЕ Запись.Ссылка = ТекНачальныеДанные.Ссылка Тогда // получена новая ссылка
Запись.ДатаПолученияСсылки = ТекущаяДата;
КонецЕсли;
КонецЦикла;
// очистим буфер обмена
ОбщегоНазначения.СкопироватьВБуферОбмена(Неопределено, ИмяИсточника);
КонецЕсли;
КонецПроцедуры
Функция ПолучитьНачальныеДанные(Задачи)
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| *
|ИЗ
| РегистрСведений.ЗадачиДляОбмена КАК ЗадачиДляОбмена
|ГДЕ
| ЗадачиДляОбмена.Задача В (&Задачи)";
Запрос.УстановитьПараметр("Задачи", Отбор.Задача.Значение);
Возврат Запрос.Выполнить().Выгрузить();
КонецФункции
1
комментарий
Алексей
24 ноя 2023
Здравствуйте! Ваша статья очень помогла в решении вопроса, есть одно но.
Если сначала прочитать данные регистра (например: для изменения ресурсов, реквизитов), а потом вызвать запись.
То тут будет не новая запись:
"Если БуферОбмена.Источник = ИмяИсточника Тогда // новая запись"
Если сначала прочитать данные регистра (например: для изменения ресурсов, реквизитов), а потом вызвать запись.
То тут будет не новая запись:
"Если БуферОбмена.Источник = ИмяИсточника Тогда // новая запись"
____________________
Перепечатка текста и фотографий разрешена при наличии прямой ссылки на источник