Обычная задача — перед записью поймать изменение реквизита (пусть это будет реквизит ВремяНачала)и выполнить некоторое действие.
Раньше оно было совсем просто в процедуре ПередЗаписью
Если Ссылка.ВремяНачала <> Объект.ВремяНачала Тогда
// реквизит изменен - выполняем нужные действия
КонецЕсли
Сейчас такой фокус не пройдет — придется написать чуть побольше кода.
&НаСервере
Функция ИзменениеВРасписании(ВремяНачалаАктуальное)
Запрос = Новый Запрос;
Запрос.Текст = "ВЫБРАТЬ
| ОказаниеУслуг.ВремяНачала
|ИЗ
| Документ.ОказаниеУслуг КАК ОказаниеУслуг
|ГДЕ
| ОказаниеУслуг.Ссылка = &Ссылка";
Запрос.УстановитьПараметр("Ссылка", Объект.Ссылка);
Результат = Запрос.Выполнить();
Выборка = Результат.Выбрать();
Если Выборка.Следующий() Тогда
ВремяНачалаСохраненное = Выборка.ВремяНачала;
Если ВремяНачалаСохраненное <> ВремяНачалаАктуальное Тогда
Возврат Истина;
КонецЕсли;
КонецЕсли;
Возврат Ложь;
КонецФункции
Ну и используем новую функцию в процедуре ПередЗаписью
&НаКлиенте
Процедура ПередЗаписью(Отказ, ПараметрыЗаписи)
Если ИзменениеВРасписании(Объект.ВремяНачала) Тогда
// реквизит изменен - выполняем нужные действия
КонецЕсли;
КонецПроцедуры
Как при записи элемента справочника определить, какие именно реквизиты изменены? |
Я |
17.05.12 — 10:01
Как при записи элемента справочника определить, какие именно реквизиты изменены?
Возможно ли это и как реализовать?
1 — 17.05.12 — 10:02
Через объект метаданных и элемент формы
2 — 17.05.12 — 10:02
Суть задачи, при изменении только Родителя — никаких проверок при записи не делать, во всех остальных случаях осуществлять ряд проверок.
3 — 17.05.12 — 10:03
Если Наименование <> Ссылка.Наименование Тогда
Сообщить(«Наименование изменено»);
КонецЕсли;
4 — 17.05.12 — 10:03
а) Хранить структуру реквизитов до измения
б) Взять предыдущие из БД ПередЗаписью (по ссылке)
5 — 17.05.12 — 10:04
(3)+1
6 — 17.05.12 — 10:04
(3) а как пробежаться по всем реквизитам?
7 — 17.05.12 — 10:05
(6)
а) Из метаданных
б) Выбрать *
8 — 17.05.12 — 10:07
(6) А тебе нужно конкретно знать, что изменено или пофиг?
9 — 17.05.12 — 10:09
Да, (8) прав, можно использовать модифицированность, при таковой сравнивать только Родителя (если (2))
10 — 17.05.12 — 10:10
Для Каждого текРеквизит из СписокРеквизитов Цикл
Если // а вот как тут проверку написать? Тогда
Сообщить(«Реквизит » + текРеквизит + » изменен!»);
КонецЕсли;
КонецЦикла;
11 — 17.05.12 — 10:11
Забыл:
СписокРеквизитов = ЭтотОбъект.Метаданные().Реквизиты;
12 — 17.05.12 — 10:11
(10) Что написать — зависит от того, что находится в СписокРеквизитов
13 — 17.05.12 — 10:11
Мне нужно определить, что не изменилось ничего кроме родителя
14 — 17.05.12 — 10:11
Т.е. перебрать все реквизиты надо
15 — 17.05.12 — 10:12
(11)
Если Ссылка[текРеквизит.Имя]<>ЭтотОбъект[текРеквизит.Имя]
Хотя меня лично коробит множественное обращение по ссылке
16 — 17.05.12 — 10:13
(13) и (14) — взаимоисключающие утверждения
17 — 17.05.12 — 10:13
(15) запросом вытащить предварительно можно
18 — 17.05.12 — 10:13
(13) Фигня какая-то… Информация может храниться в регистрах сведений и/или подчиненных справочниках… Как их проверять будешь?
19 — 17.05.12 — 10:13
(16) Поторопился —
20 — 17.05.12 — 10:14
(17) Я так и предлагаю
21 — 17.05.12 — 10:14
(16) как же они взаимоисключающие? Мне нужно получить список измененных реквизитов, если он будет состоять только из Родителя — тогда Возврат, иначе — проверки.
22 — 17.05.12 — 10:15
Интересуют только реквизиты!
23 — 17.05.12 — 10:15
(18) Интересуют только реквизиты самого объекта!
24 — 17.05.12 — 10:17
(15) ну а иначе никак… либо перед записью в таблицу все реквизиты текущего объекта просто выгружать… В результате обращение к объекту будет одно.
25 — 17.05.12 — 10:17
Спасибо за советы, сейчас буду мудрить
26 — 17.05.12 — 10:20
(24) Можно оптимизировать
а) Получить запросом
б) Создать временный объект — копию:
ОбъектДоИзменения=Ссылка.ПолучитьОбъект()
//блабла
Если ОбъектДоИзменения[текРеквизит.Имя]<>ЭтотОбъект[текРеквизит.Имя]
// Так читабельней и меня меньше коробит
27 — 17.05.12 — 10:22
(26) не, там и так всё в порядке. По ссылке один раз получается объект и дальше уже он используется. То есть временный объект сам создается платформой. Не нужно заморачиваться.
28 — 17.05.12 — 10:23
(27) некрасиво просто. я за запрос!
29 — 17.05.12 — 10:37
Всем спасибо большое! Сделал так в модуле ПередЗаписью()
Если НЕ ЭтоНовый() Тогда
Запрос = Новый Запрос;
Запрос.Текст =
«ВЫБРАТЬ *
|ИЗ
| Справочник.Номенклатура КАК Номенклатура
|ГДЕ
| Номенклатура.Ссылка = &Ссылка»;
Запрос.УстановитьПараметр(«Ссылка», ЭтотОбъект.Ссылка);
Результат = Запрос.Выполнить().Выбрать();
Если Результат.Количество() > 0 Тогда
Результат.Следующий();
СписокРеквизитов = ЭтотОбъект.Метаданные().Реквизиты;
Для Каждого текРеквизит из СписокРеквизитов Цикл
Если Результат[текРеквизит.Имя] <> ЭтотОбъект[текРеквизит.Имя] Тогда
Сообщить(«Реквизит » + текРеквизит + » изменен!»);
КонецЕсли;
КонецЦикла;
КонецЕсли;
КонецЕсли;
30 — 17.05.12 — 10:44
Есть один косяк, СписокРеквизитов = ЭтотОбъект.Метаданные().Реквизиты — в список Родитель не попадает, и другие стандартные реквизиты
31 — 17.05.12 — 10:45
СписокРеквизитов = ЭтотОбъект.Метаданные().СтандартныеРеквизиты;
Вопрос снят
32 — 17.05.12 — 10:46
(29)(31) Нормально вполне себе, молодца
33 — 17.05.12 — 10:48
(30) КолонкиИзЗапроса = Запрос.Выполнить().Колонки;
34 — 17.05.12 — 10:48
А тебе надо отследить изменения в объекте при редактировании через форму или при любых изменениях объекта? Просто если через форму, тогда можно проще — завести флаг и его выставлять при изменении реквизитов в форме.
35 — 17.05.12 — 10:52
(34) при любых, как обработкой, так и обменом
36 — 17.05.12 — 10:53
(31) а чего у вас там постоянно родителя туда-сюда меняют у элементов? Может не стоит такую офигенную проверку устраивать каждый раз, а сделать с родителем так же.
37 — 17.05.12 — 10:53
(34) тот флаг о котором ты говоришь итак есть стандартно, ЭтотОбъект.Модифицированность()
38 — 17.05.12 — 10:54
(36) справочник обрабатывается как ручками, так и обработками различными. Если подскажешь как мне определить, что происходит событие смены родителя, то буду благодарен
39 — 17.05.12 — 10:57
(38) ну легко:
ТабличноеПоле (TableBox)
ПриСменеТекущегоРодителя (OnCurrentParentChange)
Синтаксис:
ПриСменеТекущегоРодителя()
Описание:
Возникает при изменении текущего родителя в режиме иерархического списка.
40 — 17.05.12 — 11:02
(38) подписку на событие не предлагать?
41 — 17.05.12 — 11:57
Ага, только рассмотрите еще один момент, помимо родителя я одновременно могу например еще и наименование изменить, и т.п.
Михаил Анянов
42 — 17.05.12 — 12:00
(39) — собитие при записи все равно ведь выполнится с кучей проверок внутри?
Определяем модифицированность объекта на сервере.
Задача для примера:
При записи документа «Заказ клиента», если у него при редактировании изменилось значение реквизита «Пометка удаления», нужно выполнить какой-то программный алгоритм. Если значение не изменилось, то алгоритм выполнять не нужно. В общем, цель – определить, изменилось ли значение реквизита «Пометка удаления» перед тем, как документ будет записан.
У управляемой формы есть свойство Модифицированность. Но в данном случае оно вряд ли пригодится, так как пометка удаления может устанавливаться не из формы документа. Дальше приходит на ум использовать метод объекта метаданых «ДокументОбъект» Модифицированность(). Однако в отладчике видно, что даже если ничего не менять в документе, то при записи метод Модифицированность() всё равно принимает значение Истина.
Но выход есть. Отследить и обработать изменение реквизита «Пометка удаления» можно с помощью метода ДополнительныеСвойства. Для этого нам понадобится внести небольшие дополнения в процедуры модуля объекта документа.
Процедура ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения) Если НЕ Ссылка.ПометкаУдаления = ПометкаУдаления Тогда ДополнительныеСвойства.Вставить("ПометкаУдаленияИзменена", Истина); КонецЕсли; КонецПроцедуры
В процедуре ПередЗаписью() мы сравниваем значение реквизита «Пометка удаления» редактируемого документа с значением, которое записано в базе. Если значения не равны, то записываем признак изменённости в дополнительные свойства, и далее используем его в процедуре ПриЗаписи():
Процедура ПриЗаписи(Отказ) Если ДополнительныеСвойства.Свойство("ПометкаУдаленияИзменена", Истина) Тогда // Произвольная обработка условия... КонецЕсли; КонецПроцедуры
- Информация о материале
- Категория: Программирование 1С
-
Опубликовано: 12 сентября 2018
Перейти в раздел примеры кода 1С 8.3:
//by telegram t.me/yellow_pad (Жёлтая тетрадь Блог программиста 1C)
Проверить изменение поля регистра сведений ПередЗаписью. В отличие от объектов ссылочного типа, при изменении регистра платформа сперва записывает пустой набор записей, а затем набор записей с данными. Выходит, что в момент записи фиксируемых данных прежних данных в базе уже нет, и сверить новые значения полей не с чем.
Вариант решения — перед записью пустого набора получить запросом текущие данные регистра и закешировать их во временное хранилище, передав во вторую итерацию ссылку на это хранилище (например, через параметр сеанса). БСП: БуферОбмена — кеширование любых данных без передачи адреса хранилища
В БСП реализован универсальный механизм — БуферОбмена, и он никак не связан с буфером обмена ОС. Он принимает любые данные, сохраняет их во временное хранилище, а адрес временного хранилища записывает в параметр сеанса БуферОбмена. Механизмом можно пользоваться для передачи данных в коде без возможности передать напрямую адрес временного хранилища. В типовых конфигурациях используется для передачи строк табличных частей и вложенных файлов.
ОбщегоНазначения.СкопироватьВБуферОбмена(Данные);
БуферОбмена = ОбщегоНазначения.СтрокиИзБуфераОбмена();
Данные = БуферОбмена.Данные;
Пример использования механизма — отслеживание изменений полей регистра сведений ПередЗаписью:
Пример кода в 1С 8.3:
Процедура ПередЗаписью(Отказ, Замещение)
Если ОбменДанными.Загрузка Тогда
Возврат;
КонецЕсли;
ИмяИсточника = ОбщегоНазначения.КонтрольнаяСуммаСтрокой(Новый Структура(«Пользователь, Отборы», ИмяПользователя(), Отбор.Задача.Значение));
Если ЭтотОбъект.Количество() = 0 Тогда
ОбщегоНазначения.СкопироватьВБуферОбмена(ПолучитьНачальныеДанные(Отбор.Задача.Значение), ИмяИсточника);
Иначе
БуферОбмена = ОбщегоНазначения.СтрокиИзБуфераОбмена();
Если БуферОбмена.Источник = ИмяИсточника Тогда // новая запись
НачальныеДанные = БуферОбмена.Данные;
Иначе
НачальныеДанные = Неопределено;
КонецЕсли;
ТекущаяДата = ТекущаяДата();
Для Каждого Запись Из ЭтотОбъект Цикл
ТекНачальныеДанные = ?(НачальныеДанные = Неопределено, Неопределено, НачальныеДанные.Найти(Запись.Задача, «Задача»));
Если ТекНачальныеДанные = Неопределено Тогда // запись создана
Запись.ДатаСоздания = ТекущаяДата;
Продолжить;
КонецЕсли;
Если ЗначениеЗаполнено(Запись.Ссылка)
И НЕ Запись.Ссылка = ТекНачальныеДанные.Ссылка Тогда // получена новая ссылка
Запись.ДатаПолученияСсылки = ТекущаяДата;
КонецЕсли;
КонецЦикла;
// очистим буфер обмена
ОбщегоНазначения.СкопироватьВБуферОбмена(Неопределено, ИмяИсточника);
КонецЕсли;
КонецПроцедуры
Функция ПолучитьНачальныеДанные(Задачи)
Запрос = Новый Запрос;
Запрос.Текст =
«ВЫБРАТЬ
| *
|ИЗ
| РегистрСведений.ЗадачиДляОбмена КАК ЗадачиДляОбмена
|ГДЕ
| ЗадачиДляОбмена.Задача В (&Задачи)»;
Запрос.УстановитьПараметр(«Задачи», Отбор.Задача.Значение);
Возврат Запрос.Выполнить().Выгрузить();
КонецФункции
Copyright©, «Программист 1С в г.Минске», 25.06.2021
Перепечатка текста и фотографий разрешена при наличии прямой ссылки на источник