Обычная задача — перед записью поймать изменение реквизита (пусть это будет реквизит ВремяНачала)и выполнить некоторое действие.
Раньше оно было совсем просто в процедуре ПередЗаписью
Если Ссылка.ВремяНачала <> Объект.ВремяНачала Тогда
// реквизит изменен - выполняем нужные действия
КонецЕсли
Сейчас такой фокус не пройдет — придется написать чуть побольше кода.
&НаСервере
Функция ИзменениеВРасписании(ВремяНачалаАктуальное)
Запрос = Новый Запрос;
Запрос.Текст = "ВЫБРАТЬ
| ОказаниеУслуг.ВремяНачала
|ИЗ
| Документ.ОказаниеУслуг КАК ОказаниеУслуг
|ГДЕ
| ОказаниеУслуг.Ссылка = &Ссылка";
Запрос.УстановитьПараметр("Ссылка", Объект.Ссылка);
Результат = Запрос.Выполнить();
Выборка = Результат.Выбрать();
Если Выборка.Следующий() Тогда
ВремяНачалаСохраненное = Выборка.ВремяНачала;
Если ВремяНачалаСохраненное <> ВремяНачалаАктуальное Тогда
Возврат Истина;
КонецЕсли;
КонецЕсли;
Возврат Ложь;
КонецФункции
Ну и используем новую функцию в процедуре ПередЗаписью
&НаКлиенте
Процедура ПередЗаписью(Отказ, ПараметрыЗаписи)
Если ИзменениеВРасписании(Объект.ВремяНачала) Тогда
// реквизит изменен - выполняем нужные действия
КонецЕсли;
КонецПроцедуры
Как при записи элемента справочника определить, какие именно реквизиты изменены? |
Я |
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С 8.3:
//by telegram t.me/yellow_pad (Жёлтая тетрадь Блог программиста 1C)
Проверить изменение поля регистра сведений ПередЗаписью. В отличие от объектов ссылочного типа, при изменении регистра платформа сперва записывает пустой набор записей, а затем набор записей с данными. Выходит, что в момент записи фиксируемых данных прежних данных в базе уже нет, и сверить новые значения полей не с чем.
Вариант решения — перед записью пустого набора получить запросом текущие данные регистра и закешировать их во временное хранилище, передав во вторую итерацию ссылку на это хранилище (например, через параметр сеанса). БСП: БуферОбмена — кеширование любых данных без передачи адреса хранилища
В БСП реализован универсальный механизм — БуферОбмена, и он никак не связан с буфером обмена ОС. Он принимает любые данные, сохраняет их во временное хранилище, а адрес временного хранилища записывает в параметр сеанса БуферОбмена. Механизмом можно пользоваться для передачи данных в коде без возможности передать напрямую адрес временного хранилища. В типовых конфигурациях используется для передачи строк табличных частей и вложенных файлов.
ОбщегоНазначения.СкопироватьВБуферОбмена(Данные);
БуферОбмена = ОбщегоНазначения.СтрокиИзБуфераОбмена();
Данные = БуферОбмена.Данные;
Пример использования механизма — отслеживание изменений полей регистра сведений ПередЗаписью:
Пример кода в 1С 8.3:
Процедура ПередЗаписью(Отказ, Замещение)
Если ОбменДанными.Загрузка Тогда
Возврат;
КонецЕсли;
ИмяИсточника = ОбщегоНазначения.КонтрольнаяСуммаСтрокой(Новый Структура(«Пользователь, Отборы», ИмяПользователя(), Отбор.Задача.Значение));
Если ЭтотОбъект.Количество() = 0 Тогда
ОбщегоНазначения.СкопироватьВБуферОбмена(ПолучитьНачальныеДанные(Отбор.Задача.Значение), ИмяИсточника);
Иначе
БуферОбмена = ОбщегоНазначения.СтрокиИзБуфераОбмена();
Если БуферОбмена.Источник = ИмяИсточника Тогда // новая запись
НачальныеДанные = БуферОбмена.Данные;
Иначе
НачальныеДанные = Неопределено;
КонецЕсли;
ТекущаяДата = ТекущаяДата();
Для Каждого Запись Из ЭтотОбъект Цикл
ТекНачальныеДанные = ?(НачальныеДанные = Неопределено, Неопределено, НачальныеДанные.Найти(Запись.Задача, «Задача»));
Если ТекНачальныеДанные = Неопределено Тогда // запись создана
Запись.ДатаСоздания = ТекущаяДата;
Продолжить;
КонецЕсли;
Если ЗначениеЗаполнено(Запись.Ссылка)
И НЕ Запись.Ссылка = ТекНачальныеДанные.Ссылка Тогда // получена новая ссылка
Запись.ДатаПолученияСсылки = ТекущаяДата;
КонецЕсли;
КонецЦикла;
// очистим буфер обмена
ОбщегоНазначения.СкопироватьВБуферОбмена(Неопределено, ИмяИсточника);
КонецЕсли;
КонецПроцедуры
Функция ПолучитьНачальныеДанные(Задачи)
Запрос = Новый Запрос;
Запрос.Текст =
«ВЫБРАТЬ
| *
|ИЗ
| РегистрСведений.ЗадачиДляОбмена КАК ЗадачиДляОбмена
|ГДЕ
| ЗадачиДляОбмена.Задача В (&Задачи)»;
Запрос.УстановитьПараметр(«Задачи», Отбор.Задача.Значение);
Возврат Запрос.Выполнить().Выгрузить();
КонецФункции
Copyright©, «Программист 1С в г.Минске», 25.06.2021
Перепечатка текста и фотографий разрешена при наличии прямой ссылки на источник
Определяем модифицированность объекта на сервере.
Задача для примера:
При записи документа «Заказ клиента», если у него при редактировании изменилось значение реквизита «Пометка удаления», нужно выполнить какой-то программный алгоритм. Если значение не изменилось, то алгоритм выполнять не нужно. В общем, цель – определить, изменилось ли значение реквизита «Пометка удаления» перед тем, как документ будет записан.
У управляемой формы есть свойство Модифицированность. Но в данном случае оно вряд ли пригодится, так как пометка удаления может устанавливаться не из формы документа. Дальше приходит на ум использовать метод объекта метаданых «ДокументОбъект» Модифицированность(). Однако в отладчике видно, что даже если ничего не менять в документе, то при записи метод Модифицированность() всё равно принимает значение Истина.
Но выход есть. Отследить и обработать изменение реквизита «Пометка удаления» можно с помощью метода ДополнительныеСвойства. Для этого нам понадобится внести небольшие дополнения в процедуры модуля объекта документа.
Процедура ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения) Если НЕ Ссылка.ПометкаУдаления = ПометкаУдаления Тогда ДополнительныеСвойства.Вставить("ПометкаУдаленияИзменена", Истина); КонецЕсли; КонецПроцедуры
В процедуре ПередЗаписью() мы сравниваем значение реквизита «Пометка удаления» редактируемого документа с значением, которое записано в базе. Если значения не равны, то записываем признак изменённости в дополнительные свойства, и далее используем его в процедуре ПриЗаписи():
Процедура ПриЗаписи(Отказ) Если ДополнительныеСвойства.Свойство("ПометкаУдаленияИзменена", Истина) Тогда // Произвольная обработка условия... КонецЕсли; КонецПроцедуры
- Информация о материале
- Категория: Программирование 1С
-
Опубликовано: 12 сентября 2018
Сообщение от Tklwegsd
Если Модифицированность() тогда а=0; КонецЕсли;
так не работает, выдает ошибку
1C | ||
|
Модифицированность() — это свойство формы или объекта в памяти (но уж точно не ссылки)
это надо понимать так?
1C | ||
|
так тоже не понимает
1C | ||
|
Сообщение от Yulunga
чувство юмора это хорошо, а решение где, поспешил вам плюс поставить)
Добавлено через 17 минут
Или ошибка в том, что я проверяю в Модуле менеджера справочника в событии Перед записью, а надо проверять в Модуле Формы?
еще потестировал, в модуле объекта Справочника номенклатуры работает.
Работает и просто в форме по событию ПриИзменении элемента, но использовал это событие чисто для тестирования. В идеале нужно, что бы работало в Модуле Объекта ПередЗаписью().
Результат положительный, но пока нет четкого понимания, как это работает.
Добавлено через 24 минуты
Сообщение от Tklwegsd
А так?
1C
Выделить код
1
2
3
Если Модифицированность() тогда
а=0;
КонецЕсли;
еще потестировал
Оказалось, что даже если выбран тот же самый реквизит, программа думает что данные в форме изменилась, причем так думает и сама форма и Модуль объекта перед записью?
Можно ли где то узнать алгоритм этой функции, 1С ведь на си вроде написана, эти модули есть где нибудь или нет? Или может есть описание таких функциональных модулей?
Не по теме:
интернет видимо медленный и проходит дребезг клавиши, почему то иногда выходят повторы ответов через 15 сек)
Добавлено через 1 час 34 минуты
Пока получается так
Разные действия на форме име.ют разные действия:
1. Если меняем реквизит на другой признак Модифицированности
устанавливается в ИСТИНУ, * в шапке
2. Если не меняем реквизит, но открываем форму реквизита (если это ссылка) => Модифицированность
в ИСТИНУ и * в шапке формы.
3. Если нажимаем на крестик в открывшейся форме, => Модифицированность ложь и * НЕТ
Добавлено через 42 минуты
вот Синтаксис помощник
1C | ||
|
как это правильно применить в коде?
У объекта — Метод, у формы — свойство — в чем зазница?
У объекта событие ПередЗаписью, у формы событие ПередЗакрытием
Логика понятна.
Объект — прочитали данные из базы, что то изменили и пробуем записать обратно, все поля можно проверить , в базе они отличаются от новых.
Форма — поля формы вроде бы не где не сохраняются и их изменение при закрытии формы разве можно как то проверить сразу все на уровне программы?
У формы по идее в программе настроен простой механизм, если был открыт хоть один реквизит на изменение и не важно изменили там что либо или нет, проверяется только сам факт, сохранили действие или отменили по крестику к примеру и все флаг Модификации перещелкивается и при закрытии формы, проверяется просто его значение ложь или истина.
так или нет?
Хотя при сохранению в базу программа может и не проверять поля (старые и новые) [такой вывод можно сделать из статьи https://forum.infostart.ru/forum9/topic129997/ там сохраняется каждое поле и потом сверяется перед записью], а тоже работать только по этому флагу
Форма — поля формы вроде бы не где не сохраняются и их изменение при закрытии формы разве можно как то проверить сразу все на уровне программы?
У формы по идее в программе настроен простой механизм, если был открыт хоть один реквизит на изменение и не важно изменили там что либо или нет, проверяется только сам факт, сохранили действие или отменили по крестику к примеру и все флаг Модификации перещелкивается и при закрытии формы, проверяется просто его значение ложь или истина.
так или нет?
Хотя при сохранению в базу программа может и не проверять поля (старые и новые) [такой вывод можно сделать из статьи https://forum.infostart.ru/forum9/topic129997/ там сохраняется каждое поле и потом сверяется перед записью], а тоже работать только по этому флагу
Как при записи элемента справочника определить, какие именно реквизиты изменены? Возможно ли это и как реализовать?
Через объект метаданных и элемент формы
Суть задачи, при изменении только Родителя — никаких проверок при записи не делать, во всех остальных случаях осуществлять ряд проверок.
а) Хранить структуру реквизитов до измения б) Взять предыдущие из БД ПередЗаписью (по ссылке)
а как пробежаться по всем реквизитам?
а) Из метаданных б) Выбрать *
А тебе нужно конкретно знать, что изменено или пофиг?
Да, прав, можно использовать модифицированность, при таковой сравнивать только Родителя (если )
Забыл: СписокРеквизитов = ЭтотОбъект.Метаданные.Реквизиты;
Что написать — зависит от того, что находится в СписокРеквизитов
Мне нужно определить, что не изменилось ничего кроме родителя
Т.е. перебрать все реквизиты надо
Если Ссылка[текРеквизит.Имя]<>ЭтотОбъект[текРеквизит.Имя] Хотя меня лично коробит множественное обращение по ссылке
и — взаимоисключающие утверждения
запросом вытащить предварительно можно
Фигня какая-то… Информация может храниться в регистрах сведений и/или подчиненных справочниках… Как их проверять будешь?
как же они взаимоисключающие? Мне нужно получить список измененных реквизитов, если он будет состоять только из Родителя — тогда Возврат, иначе — проверки.
Интересуют только реквизиты!
Интересуют только реквизиты самого объекта!
ну а иначе никак… либо перед записью в таблицу все реквизиты текущего объекта просто выгружать… В результате обращение к объекту будет одно.
Спасибо за советы, сейчас буду мудрить
а) Получить запросом б) Создать временный объект — копию: ОбъектДоИзменения=Ссылка.ПолучитьОбъект
не, там и так всё в порядке. По ссылке один раз получается объект и дальше уже он используется. То есть временный объект сам создается платформой. Не нужно заморачиваться.
некрасиво просто. я за запрос!
Всем спасибо большое! Сделал так в модуле ПередЗаписью
Есть один косяк, СписокРеквизитов = ЭтотОбъект.Метаданные.Реквизиты — в список Родитель не попадает, и другие стандартные реквизиты
Нормально вполне себе, молодца
КолонкиИзЗапроса = Запрос.Выполнить.Колонки;
А тебе надо отследить изменения в объекте при редактировании через форму или при любых изменениях объекта? Просто если через форму, тогда можно проще — завести флаг и его выставлять при изменении реквизитов в форме.
при любых, как обработкой, так и обменом
а чего у вас там постоянно родителя туда-сюда меняют у элементов? Может не стоит такую офигенную проверку устраивать каждый раз, а сделать с родителем так же.
тот флаг о котором ты говоришь итак есть стандартно, ЭтотОбъект.Модифицированность
справочник обрабатывается как ручками, так и обработками различными. Если подскажешь как мне определить, что происходит событие смены родителя, то буду благодарен
ну легко: ПриСменеТекущегоРодителя (OnCurrentParentChange) Синтаксис: ПриСменеТекущегоРодителя Описание: Возникает при изменении текущего родителя в режиме иерархического списка.
подписку на событие не предлагать?
Ага, только рассмотрите еще один момент, помимо родителя я одновременно могу например еще и наименование изменить, и т.п.
— собитие при записи все равно ведь выполнится с кучей проверок внутри?
Тэги: 1С 8
Комментарии доступны только авторизированным пользователям
+3
1С 8.x : Событие ПередЗаписью регистра сведений. Как перед записью изменить значение реквизита записи?
Событие ПередЗаписью возникает перед выполнением записи набора регистра сведений. Процедура-обработчик вызывается после начала транзакции записи, но до начала записи набора регистра сведений.
Пример проверки на условие и заполнение реквизита Цвет:
Код 1C v 8.х
Процедура ПередЗаписью(Отказ, Замещение)
Для Каждого ТекЗапись Из ЭтотОбъект Цикл
Если ТекЗапись.СерияНоменклатуры.Восстановленный Тогда
ТекЗапись.Цвет="2551650";
Иначе
ТекЗапись.Цвет="";
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Ниже приведен пример процедуры ПередЗаписью для регистра сведений «Курсы», который содержит курсы валют по периодам. При попытке ввести или изменить курс валюты период которого раньше даты регистрации фирмы будет выведено два сообщения:
Код 1C v 8.2 УП
Процедура ПередЗаписью (Отказ, Замещение)
ДатаРегистрации = Константы.ДатаРегистрации.Получить ();
Для Каждого ТекЗапись Из ЭтотОбъект Цикл
Если ТекЗапись.Период < ДатаРегистрации Тогда
// Если период раньше даты регистрации
Отказ = Истина; // отказ от записи
Сообщить(" Запись от " + ТекЗапись.Период +
" с курсом " + ТекЗапись.Курс +
" раньше даты регистрации фирмы!");
КонецЕсли;
КонецЦикла;
Если Отказ Тогда
Сообщить ("Запись не выполнена!");
КонецЕсли;
КонецПроцедуры