+3
1С 8.3 : Событие ПередЗаписью регистра сведений. Как перед записью изменить значение реквизита записи?
Событие ПередЗаписью возникает перед выполнением записи набора регистра сведений. Процедура-обработчик вызывается после начала транзакции записи, но до начала записи набора регистра сведений.
Пример проверки на условие и заполнение реквизита Цвет:
Код 1C v 8.х
Процедура ПередЗаписью(Отказ, Замещение)
Для Каждого ТекЗапись Из ЭтотОбъект Цикл
Если ТекЗапись.СерияНоменклатуры.Восстановленный Тогда
ТекЗапись.Цвет="2551650";
Иначе
ТекЗапись.Цвет="";
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Ниже приведен пример процедуры ПередЗаписью для регистра сведений «Курсы», который содержит курсы валют по периодам. При попытке ввести или изменить курс валюты период которого раньше даты регистрации фирмы будет выведено два сообщения:
Код 1C v 8.2 УП
Процедура ПередЗаписью (Отказ, Замещение)
ДатаРегистрации = Константы.ДатаРегистрации.Получить ();
Для Каждого ТекЗапись Из ЭтотОбъект Цикл
Если ТекЗапись.Период < ДатаРегистрации Тогда
// Если период раньше даты регистрации
Отказ = Истина; // отказ от записи
Сообщить(" Запись от " + ТекЗапись.Период +
" с курсом " + ТекЗапись.Курс +
" раньше даты регистрации фирмы!");
КонецЕсли;
КонецЦикла;
Если Отказ Тогда
Сообщить ("Запись не выполнена!");
КонецЕсли;
КонецПроцедуры
|
|||
elian_hunter
04.09.15 — 22:47 |
У справочника один реквизит типа булево. Процедура ПриЗаписи(Отказ) Если открыть форму объекта и нажать кнопку «Записать и закрыть» — эффекта никакого. То есть Реквизит1 остаетеся в значении «Ложь». Но если на форме нажать кнопку «Записать», то всё работает как надо!
ЭТО ПОЧЕМУ ТАК? |
||
Armando
1 — 04.09.15 — 22:53 |
Почитай описание, когда возникает событие «ПриЗаписи» |
||
elian_hunter
2 — 04.09.15 — 23:02 |
(1) ну а кроме «умников» есть нормальные люди? |
||
elian_hunter
3 — 04.09.15 — 23:03 |
(1) Событие возникает всегда. Отладчиком я ловлю отработку этой строки в любом случае, но в первом варианте это не даёт нужного эффекта. |
||
Armando
4 — 04.09.15 — 23:03 |
http://its.1c.ru/db/v8std#content:2149184114:hdoc |
||
elian_hunter
5 — 04.09.15 — 23:06 |
(4) вот теперь понял… спасибо |
||
palsergeich
6 — 04.09.15 — 23:07 |
ПРИзаписи — Транзакция еще идет, Объект уже записан в ИБ. Изменять реквизиты объекта в ПРИЗаписи — бесполезно, он сделан для другого. |
||
elian_hunter
7 — 04.09.15 — 23:08 |
(6) Спасибо! Понял. |
||
palsergeich
8 — 04.09.15 — 23:26 |
Немного теории, на будущее пригодится. |
||
palsergeich 9 — 04.09.15 — 23:28 |
http://catalog.mista.ru/public/153748/ тут достаточно подробно все описано, рекомендую к прочтению. |
TurboConf — расширение возможностей Конфигуратора 1С
Попал в какую-то непонятную ситуацию, говорящую о том, что не хватает каких-то, похоже элементарных, базовых знаний.
Итак простейшая задача, при записи/перезаписи/проведении документа установить значение реквизита объекта.
Весь код приводить нет смысла, вот упрощенный фрагмент
1C | ||
|
И вот ничерта не пойму. Почему
1C | ||
|
устанавливает нужное значение Комментарий текущего объекта = «123», а комментарий ЭтотОбъект.Объект.Комментарий остается прежним, не меняется.
И так же, оставляю в коде только
1C | ||
|
так же устанавливает нужное значение «123» у Объект.Комментарий, но не меняет его у Текущего объекта.
Получается ТекущийОбъект и ЭтотОбъект.Объект это не одно и тоже????? В голове не укладывается, но каждая строка установленная в коде по одной в итоге НИЧЕГО не меняет, Комментарий в документе остается прежним как до записи и лишь сочетание двух строк, как в приведенном коде, дает результат, Комментарий записывается так как надо (устанавливает значение «123»).
Помогите разобраться как-то шарики за ролики уже убежали, никак не пойму
Добавлено через 7 минут
Перечитал, уточняю, чтобы не было кривотолков. Прекрасно понимаю, что ТекущийОбъект — это ДокументОбъект, а ЭтотОбъект.Объект — ДанныеФормыСтруктура. Но почему, чтобы вывести новое значение недостаточно установить его только в одном месте?
&НаСервере
Процедура Изменение_значения_реквизита_объекта(ДокСсылка, Новое_значение_реквизита)// Процедура программно меняет значение реквизита объекта (документа)
// ДокСсылка — документ в котором необходимо изменить реквизит
// Новое_значение_реквизита — новое значение реквизита «Реквизит_для_корректировки»
// или так: ДокументССылка=Документы.ТТН.НайтиПоНомеру(СокрЛП(Ном),Дата(‘2021-05-16’));
Если Не ДокСсылка.Пустая() ТогдаДокОбъект=ДокСсылка.ПолучитьОбъект();
ДокОбъект.Реквизит_для_корректировки = Новое_значение_реквизита;
ДокОбъект.Записать(РежимЗаписиДокумента.Запись);
Попытка
ДокОбъект.Записать(РежимЗаписиДокумента.Проведение);
Исключение
Сообщить(ОписаниеОшибки());
КонецПопытки
Иначе
Сообщить(Новое_значение_реквизита+» не записано в «+ДокСсылка+«! Документ не определен»);
КонецЕсли
КонецПроцедуры
Как измени реквизит справочника при проведении документа
Автор Gendelf, 18 ноя 2013, 17:27
0 Пользователей и 1 гость просматривают эту тему.
Добрый день. В документе ПоступлениеКниги, при проведении, нужно прописать кусок кода который будет менять реквизит справочника Книга (реквизит Состояние). Проблеммы с сылкой к реквизиту справочника… как до него добраться, я не знаю.
Вот что получилось, конечно же не работает.
PS ТЧКнига — табчасть документа, в ней реквизит Книга с ссылкой к справочнику Книга.
//Смена состояния книги
Для каждого СтрокаТЧ Из ТЧКнига Цикл
ТЧКнига.Книга.Состояние = Перечисления.СостояниеКниги.ВНаличии;
КонецЦикла;
Логика приведёт вас от А к В. Воображение доставит вас куда угодно.
Сайт про аквариум, аквариумные рыбки и аквариумные растения http://myaquainfo.ru/
СтрокаТЧ.Книга.Состояние = Перечисления.СостояниеКниги.ВНаличии;
Логика приведёт вас от А к В. Воображение доставит вас куда угодно.
Сайт про аквариум, аквариумные рыбки и аквариумные растения http://myaquainfo.ru/
//Смена состояния книги
Для каждого СтрокаТЧ Из ТЧКнига Цикл
Если ЗначениеЗаполнено(ТЧКнига.Книга)
СпрОбъект = ТЧКнига.Книга.ПолучитьОбъект();
СпрОбъект.Состояние = Перечисления.СостояниеКниги.ВНаличии;
СпрОбъект.Записать();
КонецЦикла;
При
Для каждого СтрокаТЧ Из ТЧКнига Цикл
Если ЗначениеЗаполнено(ТЧКнига.Книга) Тогда
СпрОбъект = ТЧКнига.Книга.ПолучитьОбъект();
СпрОбъект.Состояние = Перечисления.СостояниеКниги.ВНаличии;
СпрОбъект.Записать();
КонецЕсли;
КонецЦикла;
Поле объекта не обнаружено (Книга)
ругается на Если….
Логика приведёт вас от А к В. Воображение доставит вас куда угодно.
Сайт про аквариум, аквариумные рыбки и аквариумные растения http://myaquainfo.ru/
Найди его в справочнике и сделай следующее
//Начало твоего цикла
//то, что ты написал
ТекущаяКнига = ТЧКнига.Книга.Ссылка; //получил ссылку на объект
ТекущаяКнига.Состояние = Перечисления.СостояниеКниги.ВНаличии;// присвоил значение реквизиту
ТекущаяКнига.Записать(); // записал элемент
//конецтвоего цикла
Добавлено: 18 ноя 2013, 17:38
Цитата: Gendelf от 18 ноя 2013, 17:34
ПриДля каждого СтрокаТЧ Из ТЧКнига Цикл
Если ЗначениеЗаполнено(ТЧКнига.Книга) Тогда
СпрОбъект = ТЧКнига.Книга.ПолучитьОбъект();
СпрОбъект.Состояние = Перечисления.СостояниеКниги.ВНаличии;
СпрОбъект.Записать();
КонецЕсли;
КонецЦикла;Поле объекта не обнаружено (Книга)
ругается на Если….
А с чего ты или точнее как ты собираешь ТЧКнигу?
Правильно ведите учет или пишите программы и вам воздастся!…
(Кстати — кнопочку Сказать Спасибо — никто не отменял)
Прошу прощения ступил
//Смена состояния книги
Для каждого СтрокаТЧ Из ТЧКнига Цикл
Если ЗначениеЗаполнено(СтрокаТЧ.Книга) Тогда
СпрОбъект = СтрокаТЧ.Книга.ПолучитьОбъект();
СпрОбъект.Состояние = Перечисления.СостояниеКниги.ВНаличии;
СпрОбъект.Записать();
КонецЕсли;
КонецЦикла;
//Начало твоего цикла
//то, что ты написал
ТекущаяКнига = СтрокаТЧ.Книга.Ссылка; //получил ссылку на объект // и я ступил — понедельник день тяжелый!!
ТекущаяКнига.Состояние = Перечисления.СостояниеКниги.ВНаличии;// присвоил значение реквизиту
ТекущаяКнига.Записать(); // записал элемент
//конецтвоего цикла
Правильно ведите учет или пишите программы и вам воздастся!…
(Кстати — кнопочку Сказать Спасибо — никто не отменял)
ребят, вы меня запутали… как должен выглядить код?
Добавлено: 18 ноя 2013, 18:12
Для каждого СтрокаТЧ Из ТЧКнига Цикл
Если ЗначениеЗаполнено(ТЧКнига.Книга) Тогда
ТекущаяКнига = СтрокаТЧ.Книга.Ссылка; //получил ссылку на объект // и я ступил - понедельник день тяжелый!!
ТекущаяКнига.Состояние = Перечисления.СостояниеКниги.ВНаличии;// присвоил значение реквизиту
ТекущаяКнига.Записать(); // записал элемент
КонецЕсли;
КонецЦикла;
так вроде?
Добавлено: 18 ноя 2013, 18:15
Поле объекта не обнаружено (Книга)
на 2 строке…
ужас, как сложно то.
Логика приведёт вас от А к В. Воображение доставит вас куда угодно.
Сайт про аквариум, аквариумные рыбки и аквариумные растения http://myaquainfo.ru/
Получение старого значения реквизита в момент записи объекта или OLD
Реляционные системы управления базами данных, такие как InterBase или FireBird, в своих триггерах поддерживают контекстные переменный NEW и OLD. Контекстная переменная NEW содержит новые значения записи, а вот переменная OLD содержит старые значения записи, следовательно, при обновлении записи (допустим BEFORE UPDATE) разработчик имеет доступ к записи до её обновления и после.
Стоит заметить что переменные OLD и NEW доступны не во всех типах триггера. Платформа 1С так же позволяет разработчику иметь доступ к старым значениям реквизита (до обновления) и одновременно к новым значениям реквизита (после обновления), но при одном условии, разработчик должен использовать события перед записью!
Допустим, у нас имеется справочник Договоры, у которого имеется реквизит ДатаПодписания. Что бы сравнить старое и новое значение реквизита, воспользуемся событием модуля объекта ПередЗаписью. Далее два варианта развития события.
1. Выполнить явный запрос
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Договоры.ДатаПодписания КАК ДатаПодписанияСтароеЗначение
|ИЗ
| Справочник.Договоры КАК Договоры
|ГДЕ
| Договоры.Ссылка = &Ссылка";
Запрос.УстановитьПараметр("Ссылка", ЭтотОбъект.Ссылка);
Результат = Запрос.Выполнить();
ВыборкаДетальныеЗаписи = Результат.Выбрать();
Пока ВыборкаДетальныеЗаписи.Следующий() Цикл
Если ЭтотОбъект.ДатаПодписания = ВыборкаДетальныеЗаписи.ДатаПодписанияСтароеЗначение Тогда
// Вставить обработку
КонецЕсли;
КонецЦикла;
2. Выполнить неявный запрос
ДатаПодписанияСтароеЗначение = ЭтотОбъект.Ссылка.ДатаПодписания; // <-- неявный запрос
Если ЭтотОбъект.ДатаПодписания = ДатаПодписанияСтароеЗначение Тогда
// Вставить обработку
КонецЕсли;
Через переменную ЭтотОбъект доступно новое значение реквизита, а вот что бы получить старое значение реквизита, необходимо его прочитать из базы данных, поэтому мы используем событие ПередЗаписью.
Обычная задача — перед записью поймать изменение реквизита (пусть это будет реквизит ВремяНачала)и выполнить некоторое действие.
Раньше оно было совсем просто в процедуре ПередЗаписью
Если Ссылка.ВремяНачала <> Объект.ВремяНачала Тогда
// реквизит изменен - выполняем нужные действия
КонецЕсли
Сейчас такой фокус не пройдет — придется написать чуть побольше кода.
&НаСервере
Функция ИзменениеВРасписании(ВремяНачалаАктуальное)
Запрос = Новый Запрос;
Запрос.Текст = "ВЫБРАТЬ
| ОказаниеУслуг.ВремяНачала
|ИЗ
| Документ.ОказаниеУслуг КАК ОказаниеУслуг
|ГДЕ
| ОказаниеУслуг.Ссылка = &Ссылка";
Запрос.УстановитьПараметр("Ссылка", Объект.Ссылка);
Результат = Запрос.Выполнить();
Выборка = Результат.Выбрать();
Если Выборка.Следующий() Тогда
ВремяНачалаСохраненное = Выборка.ВремяНачала;
Если ВремяНачалаСохраненное <> ВремяНачалаАктуальное Тогда
Возврат Истина;
КонецЕсли;
КонецЕсли;
Возврат Ложь;
КонецФункции
Ну и используем новую функцию в процедуре ПередЗаписью
&НаКлиенте
Процедура ПередЗаписью(Отказ, ПараметрыЗаписи)
Если ИзменениеВРасписании(Объект.ВремяНачала) Тогда
// реквизит изменен - выполняем нужные действия
КонецЕсли;
КонецПроцедуры