Запись значения в поле ввода/формы со срабатыванием события ПриИзменении

Публикация № 16985

Программирование - Практика программирования

ПриИзменении полеВвода полеФормы

102
Иногда возникает необходимость после записи значения в какое либо поле ввода/формы вызвать для него обработчик события ПриИзменении, а о вызове самого события приходится только мечтать. В этой статье приводится программный способ вызова этого события.

Для максимальной универсальности нужно создать пустую форму, разумнее всего общую. Назовем ее "Пустышка".

Вот 2 метода с поддержкой обычных и управляемых форм, решающие задачу.

// Интерактивно записывает значение в элемент управления. Интерактивность заключается в срабатывании
// события ПриИзменении у элемента управления.
//
// Параметры:
//  ЭлементУправления – ЭлементУправления – которому присваиваем значение;
//  Значение     – Произвольный – присваиваемое значение;
//  *ФормаИнициатор - Форма, УправляемаяФорма, *Неопределено - которая будет использована в качестве инициатора события;
//               если не указана, то будет создана временная форма-пустышка.
//
Функция ИнтерактивноЗаписатьВЭлементУправленияЛкс(ЭлементУправления, Знач Значение, Знач ФормаИнициатор = Неопределено) Экспорт
	
	Если ФормаИнициатор = Неопределено Тогда
		ФормаИнициатор = ПолучитьОбщуюФорму("Пустышка", ЭлементУправления);
	Иначе
		СтарыйВладелец = ФормаИнициатор.ВладелецФормы;
		СтарыйЗакрыватьПриВыборе = ФормаИнициатор.ЗакрыватьПриВыборе;
		ФормаИнициатор.ВладелецФормы = ЭлементУправления;
		ФормаИнициатор.ЗакрыватьПриВыборе = Ложь;
	КонецЕсли;
	НовоеЗначение = ЭлементУправления.ОграничениеТипа.ПривестиЗначение(Значение);
	Если НовоеЗначение <> Значение Или ЭлементУправления.ТолькоПросмотр Тогда
		Возврат Ложь;
	КонецЕсли; 
	ФормаИнициатор.ОповеститьОВыборе(Значение); 
	Если СтарыйЗакрыватьПриВыборе <> Неопределено Тогда
		ФормаИнициатор.ВладелецФормы = СтарыйВладелец;
		ФормаИнициатор.ЗакрыватьПриВыборе = СтарыйЗакрыватьПриВыборе;
	КонецЕсли;
	
КонецФункции // ИнтерактивноЗаписатьВЭлементУправленияЛкс()

// Интерактивно записывает значение в элемент управления (только поле ввода/формы) колонки табличного поля или таблицы формы.
// Интерактивность заключается в срабатывании события ПриИзменении у элемента управления.
// Строка табличного поля или таблицы формы должна находиться в режиме редактирования,
// иначе никаких изменений данных не произойдет.
//
// Параметры:
//  ТабличноеПоле - ТабличноеПоле, ТаблицаФормы - внутри него строка редактируется;
//  Колонка      – КолонкаТабличногоПоля, ПолеФормы – в ее ячейку будем помещать значение;
//  Значение     – Произвольный – присваиваемое значение;
//  *ФормаИнициатор - Форма, УправляемаяФормы, *Неопределено - которая будет использована в качестве инициатора события;
//               если не указана, то будет создана временная форма-пустышка;
//  *ВосстанавитьТекущуюКолонку – Булево, *Истина;
//  *ВключитьРежимРедактирования – Булево, *Истина.
//
Процедура ИнтерактивноЗаписатьВКолонкуТабличногоПоляЛкс(ТабличноеПоле, Знач Колонка, Знач Значение, Знач ФормаИнициатор = Неопределено,
	Знач ВосстанавитьТекущуюКолонку = Истина, Знач ВключитьРежимРедактирования = Истина) Экспорт
	
	Если ТипЗнч(Колонка) = Тип("КолонкаТабличногоПоля") Тогда
		ЭлементУправления = Колонка.ЭлементУправления;
		Если ТипЗнч(ЭлементУправления) <> Тип("ПолеВвода") Тогда
			ЭлементУправления = Неопределено;
		КонецЕсли;
	Иначе
		ЭлементУправления = Колонка;
		Если ТипЗнч(ЭлементУправления) <> Тип("ПолеФормы") Тогда
			ЭлементУправления = Неопределено;
		КонецЕсли;
	КонецЕсли; 
	Если ЭлементУправления <> Неопределено Тогда
		Если ВосстанавитьТекущуюКолонку Тогда
			Если ТипЗнч(ТабличноеПоле) = Тип("ТабличноеПоле") Тогда
				СтараяТекущаяКолонка = ТабличноеПоле.ТекущаяКолонка;
			Иначе
				СтараяТекущаяКолонка = ТабличноеПоле.ТекущийЭлемент;
			КонецЕсли; 
		КонецЕсли;
		Если ТипЗнч(ТабличноеПоле) = Тип("ТабличноеПоле") Тогда
			ТабличноеПоле.ТекущаяКолонка = Колонка;
		Иначе
                        ТабличноеПоле.ТекущийЭлемент = Колонка;
		КонецЕсли; 
		Если ВключитьРежимРедактирования Тогда
			ТабличноеПоле.ИзменитьСтроку();
		КонецЕсли;
		ИнтерактивноЗаписатьВЭлементУправленияЛкс(ЭлементУправления, Значение, ФормаИнициатор);
		Если ВосстанавитьТекущуюКолонку Тогда
			Если ТипЗнч(ТабличноеПоле) = Тип("ТабличноеПоле") Тогда
				ТабличноеПоле.ТекущаяКолонка = СтараяТекущаяКолонка;
			Иначе
                                ТабличноеПоле.ТекущийЭлемент = СтараяТекущаяКолонка;
			КонецЕсли; 
		КонецЕсли;
	КонецЕсли; 

КонецПроцедуры // ИнтерактивноЗаписатьВКолонкуТабличногоПоляЛкс()

Если в контексте доступна какая то форма, то лучше ее передать в качестве параметра ФормаИнициатор, т.к. это будет быстрее, чем создавать каждый раз форму-пустышку.

Скорость изменения данных таким путем естественно будет заметно ниже, чем при прямой записи в данные, с которыми связан элемент управления, с вызовом обработчика.

Хочу заметить, что подобная техника не зря большей частью "закрыта" от разработчика. Ведь программное оперирование с интерактивными событиями требует хорошей обработки всех возможных ситуаций внутри обработчиков. Например, вы можете вызвать рекурсивный цикл интерактивных событий или просто исключительную ситуацию уровня приложения. Поэтому как можно тщательнее имитируйте действия пользователя с проверкой всех возможных ситуаций. И не прибегайте к таким приемам без необходимости.
102

См. также

Специальные предложения

Комментарии
Избранное Подписка Сортировка: Древо
1. hopter 36 12.07.07 02:59 Сейчас в теме
Отличная штука. Сильно помогает при программном создании документов, когда надо заполнить кучу зависимых реквизитов, а прописывать каждый руками утомительно.
2. PowerBoy 2901 30.08.07 12:50 Сейчас в теме
Классно. Обязательно использую. Спасибо за подробный пример.
3. karat60 01.10.07 12:39 Сейчас в теме
4. fez 45 16.02.10 11:35 Сейчас в теме
Супернужная возможность для автоматического тестирования. Спасибо.
5. BlackLeon 3 05.08.11 12:33 Сейчас в теме
а что подразумевается под режимом редактирования строки?
установить текущую строку и текущую колонку и выполнить ИзменитьСтроку()?

извените. просто не смог запустить:) проблема оказалась в том что форма должна быть открыта:(
6. Girl_Tat 15.02.12 10:46 Сейчас в теме
Большое спасибо за процедуры!!!!! Очень помогли!!!
7. Жолтокнижниг 249 29.03.12 12:56 Сейчас в теме
Огромный жирный плюс, а нет предложений как програмно нажимать кн. "Ок"
у меня только одна идея эмуляция ctrl+enter, но чтот не гут так извращаться
8. agressor 119 21.12.12 11:39 Сейчас в теме
9. rar_xxx 24 29.12.12 13:47 Сейчас в теме
Жирный плюс !!! Можешь помочь с обработкой таблицы управляемой формы ?

Делаю так:
ФормаДок.Элементы.Товары.ТекущаяСтрока = 0;
Получилось в качестве колонки пока только это скормить: ФормаДок.Товары.ПодчиненныеЭлементы.ТоварыЦенаСоСкидкой Но значение на форме не появилось
10. denny_dv 15.04.13 23:31 Сейчас в теме
Супер крутая процедурка!!! Добавил в копилку! Префикс оставлю чтобы помнить. +
11. mcarrowd 13.04.15 13:57 Сейчас в теме
В 8.3 вторая процедура не работает - надо вызывать ТаблицаФормы.ИзменитьСтроку() в процедуре или где-то ранее по коду

Процедура ЛксИнтерактивноЗаписатьВКолонкуТабличногоПоля(ТабличноеПоле, Колонка, Значение, ФормаИнициатор = Неопределено) Экспорт
	
	ТабличноеПоле.ТекущаяКолонка = Колонка;
	ТабличноеПоле.ИзменитьСтроку();
	ЛксИнтерактивноЗаписатьВЭлементУправления(Колонка.ЭлементУправления, Значение, ФормаИнициатор);

КонецПроцедуры
Показать
12. tormozit 5471 13.04.15 14:12 Сейчас в теме
(11) Видимо не читал описание метода?
13. mcarrowd 14.04.15 00:48 Сейчас в теме
(12) видимо только первую строку.
14. ardn 94 22.09.15 17:38 Сейчас в теме
Спасибо,
Внес этот трюк в модуль тестирования обычных форм
15. hopter 36 29.04.16 02:38 Сейчас в теме
а на управляемых формах возможно нечто подобное соорудить?
16. ardn 94 29.04.16 08:03 Сейчас в теме
(15) hopter,
На управляемых формах логичнее использовать автоматизированное тестирование
17. tormozit 5471 29.04.16 08:20 Сейчас в теме
На управляемых формах это тоже работает.
Кстати про тестирование форм (обычных и управляемых) рекомендую посмотреть инструмент "Тестирование метаданных" из подсистемы Инструменты разработчика, где этот прием используется.
18. hopter 36 02.05.16 06:45 Сейчас в теме
ясно, посмотрю про тестирование
19. uri1709 01.08.16 11:55 Сейчас в теме
Все таки не ясно, как должна выглядеть процедура 2 для УФ, там используется вместо ТабличногоПоля, ТаблицаФормы. Методы конечно похожие, но что-то до конца не получилось у меня разобраться. Проверял на УТ 11.2. Вторую процедуру сделал так:

&НаКлиенте
Процедура ЛксИнтерактивноЗаписатьВКолонкуТабличногоПоля(ТабличноеПоле, Колонка, Значение, ФормаИнициатор = Неопределено) Экспорт
	
	ТабличноеПоле.ТекущийЭлемент = Колонка;
	ЛксИнтерактивноЗаписатьВЭлементУправления(ТабличноеПоле.ТекущийЭлемент, Значение, ФормаИнициатор);

КонецПроцедуры // ЛксИнтерактивноЗаписатьВКолонкуТабличногоПоля()

Сделал обработку с полями Партнер, Номенклатура и командой выполнить:

&НаКлиенте
Процедура Заполнить(Команда)
    Форма = ОткрытьФорму("Документ.РеализацияТоваровУслуг.ФормаОбъекта");

	Форма.ЛксИнтерактивноЗаписатьВЭлементУправления(Форма.Элементы.Партнер, Партнер, ЭтаФорма);
	                
	                 
	Форма.Элементы.Товары.ДобавитьСтроку();                   

	Форма.ЛксИнтерактивноЗаписатьВКолонкуТабличногоПоля(Форма.Элементы.Товары, Форма.Элементы.Товары.ПодчиненныеЭлементы.ТоварыНоменклатура, Номенклатура, ЭтаФорма); //Форма.Элементы.ТоварыНоменклатура
	Форма.ЛксИнтерактивноЗаписатьВКолонкуТабличногоПоля(Форма.Элементы.Товары, Форма.Элементы.Товары.ПодчиненныеЭлементы.ТоварыЦена, 100, ЭтаФорма); //Форма.Элементы.ТоварыЦена
	Форма.ЛксИнтерактивноЗаписатьВКолонкуТабличногоПоля(Форма.Элементы.Товары, Форма.Элементы.Товары.ПодчиненныеЭлементы.ТоварыКоличествоУпаковок, 100, ЭтаФорма); 
	
КонецПроцедуры
 
Показать


В результате на форме заполнилось: Партнер,Контрагент
Номенклатура - пустое поле, Цена=100,Количество=100,Сумма=10 000.

Мне не понятен момент почему не заполнилась Номенклатура и не сработало событие "ПриИзменении", ведь для "Цены" и "Количества" это событие сработало.

Хотя воспроизвел, в чистой базе создал документ "РеализациятоваровУслуг" с Партнером и табличной частью Номенклатура,НоменклатураНаименование-строка, Цена, Количество, Сумма
сделал обработчики событий для Номенклатуры при изменении заполняется поле НоменклатураНаименование, для Цены и Количества обработчики при изменении расчета Суммы.

Запустил эту обработку НоменклатураНаименование заполнилось и сумма рассчиталась. Все обработчики событий сработали.
Странно, почему в УТ 11.2 не отработало
20. hopter 36 10.08.16 01:37 Сейчас в теме
(19) uri1709, аналогичная проблема
В ЗУП 3 при заполнении дополнительного отпуска в табличной части вид не проставляется, а даты нормально
пока не разобрался
21. hopter 36 10.08.16 03:54 Сейчас в теме
еще не могу понять можно ли так флажок установить
22. hopter 36 10.08.16 04:19 Сейчас в теме
флажок похоже нельзя, т.к. это не поле ввода
23. tormozit 5471 08.09.16 10:29 Сейчас в теме
(22) Да, нельзя. В теме же написано четко "Поле ввода"
25. SlavaKron 19.09.18 09:17 Сейчас в теме
(22) В УФ можно менять вид поля формы на клиенте. "Поле флажка" можно поменять на "Поле ввода".
24. Toolfan 21.10.16 22:52 Сейчас в теме
По поводу отработки обработчика у Номенклатуры, та же самая проблема, решить не удается
Так и не у кого не получилось решить?
26. tormozit 5471 06.04.19 09:26 Сейчас в теме
Обновил код. Теперь там есть поддержка обычных и управляемых форм (табличных полей и таблиц формы).
27. mszsuz 75 07.04.19 01:42 Сейчас в теме
Если бы такое оформление условий использовалось в типовых, можно было получить вывих мозга
28. tormozit 5471 07.04.19 10:15 Сейчас в теме
29. acsent 1136 08.04.19 11:52 Сейчас в теме
А не проще ли сделать расширение, где будет
Процедура расш_ПриИзменении() экспорт
    ПриИзменении()
КонецПроцедуры
30. tormozit 5471 08.04.19 12:55 Сейчас в теме
(29) Так обработчика может не быть. К тому же есть внутренние обработчики платформы при изменении значения в поле ввода. Они не вызываются при вызове прикладного обработчика.
31. acsent 1136 08.04.19 17:29 Сейчас в теме
(30) А какой тогда пересчет нужно вызвать, если обработчика то и нет?
32. tormozit 5471 08.04.19 17:59 Сейчас в теме
(31) Например очистка связанных полей ввода.
Оставьте свое сообщение