Как исправить ошибку «Переменная не определена (СтандартнаяОбработка)» и настроить поиск при изменении поля в 1С?

Программист 1С v8.3 (Обычные формы) IT и автоматизация бизнеса
← На главную

При разработке и доработке форм в 1С разработчики часто сталкиваются с ситуацией, когда необходимо выполнить одну и ту же логику как при интерактивном выборе элемента из списка, так и при ручном вводе значения в поле ввода. Попытка напрямую вызвать обработчик события ОбработкаВыбора из процедуры ПриИзменении приводит к ошибке «Переменная не определена (СтандартнаяОбработка)» или к тому, что запрос перестает находить данные.

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

Причины возникновения ошибки

Проанализируем ситуацию, в которой происходит данная ошибка:

  1. Прямой вызов обработчика событий: Процедура ОбработкаВыбора имеет стандартную сигнатуру платформы: (Элемент, ВыбранноеЗначение, СтандартнаяОбработка). Переменная СтандартнаяОбработка передается платформой только в момент наступления интерактивного события выборки. В событии ПриИзменении(Элемент) такой переменной нет. Если вызвать ИнвентарныйНомерПолеВводаОбработкаВыбора(Элемент, Элемент.Значение, СтандартнаяОбработка) напрямую, компилятор выдаст ошибку отсутствия переменной.
  2. Различие типов данных (Ссылка vs Строка): Даже если передать в качестве третьего параметра значение Истина, обработчик вызовется, но запрос внутри него не вернет строк. Это происходит из-за того, что при выборе из справочника в ВыбранноеЗначение передается объект типа СправочникСсылка.ОсновныеСредства, а при ручном вводе текста в Элемент.Значение попадает обычная Строка. В запросе при сравнении поля ссылочного типа со строковым значением (ОсновныеСредства.Ссылка = &ИнвНомер) условие всегда возвращает Ложь.

Решение 1: Вынос логики заполнения в отдельную процедуру

Прямой вызов обработчиков событий — это антипаттерн разработки. Правильным решением является вынесение бизнес-логики (выполнения запроса и заполнения реквизитов) в отдельную служебную процедуру формы, которую будут вызывать оба события.

Рассмотрим пример реализации с проверкой и приведением типа:


Процедура ЗаполнитьДанныеПоИнвентарномуНомеру(ЗначениеПоиска)
	
	Если Не ЗначениеЗаполнено(ЗначениеПоиска) Тогда
		Возврат;
	КонецЕсли;
	
	// Если передана строка (ручной ввод), ищем ссылку в справочнике по коду
	СсылкаНаОбъект = Неопределено;
	Если ТипЗнч(ЗначениеПоиска) = Тип("Строка") Тогда
		СсылкаНаОбъект = Справочники.ОсновныеСредства.НайтиПоКоду(СокрЛП(ЗначениеПоиска));
	Иначе
		СсылкаНаОбъект = ЗначениеПоиска;
	КонецЕсли;
	
	Если Не ЗначениеЗаполнено(СсылкаНаОбъект) Тогда
		Возврат;
	КонецЕсли;
	
	Запрос = Новый Запрос;
	Запрос.Текст = 
		"ВЫБРАТЬ
		|	ОсновныеСредства.Наименование КАК Наименование,
		|	ОсновныеСредства.ПервоначальнаяСтоимость КАК ПервоначальнаяСтоимость,
		|	ОсновныеСредства.КодПоОКОФ КАК КодПоОКОФ,
		|	ОсновныеСредства.АмортизационнаяГруппа КАК АмортизационнаяГруппа,
		|	МестонахождениеОССрезПоследних.Состояние КАК Состояние,
		|	ОсновныеСредства.ЗаводскойНомер КАК ЗаводскойНомер,
		|	СобытияОСПринятоКУчету.ДатаСобытия КАК ПринятоКУчету,
		|	ЕСТЬNULL(СобытияОССнятосУчета.ДатаСобытия, ДАТАВРЕМЯ(1, 1, 1)) КАК СнятоСУчета,
		|	ОсновныеСредства.Код КАК Код
		|ИЗ
		|	Справочник.ОсновныеСредства КАК ОсновныеСредства
		|	ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.МестонахождениеОС.СрезПоследних КАК МестонахождениеОССрезПоследних
		|		ПО МестонахождениеОССрезПоследних.ИнвНомер = ОсновныеСредства.Ссылка
		|	ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.СобытияОС КАК СобытияОСПринятоКУчету
		|		ПО СобытияОСПринятоКУчету.ИнвНомер = ОсновныеСредства.Ссылка
		|		И СобытияОСПринятоКУчету.Событие = &Событие1
		|	ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.СобытияОС КАК СобытияОССнятосУчета
		|		ПО СобытияОССнятосУчета.ИнвНомер = ОсновныеСредства.Ссылка
		|		И СобытияОССнятосУчета.Событие = &Событие2
		|ГДЕ
		|	ОсновныеСредства.Ссылка = &ИнвНомер";
		
	Запрос.УстановитьПараметр("ИнвНомер", СсылкаНаОбъект);
	Запрос.УстановитьПараметр("Событие1", Перечисления.ВидыСобытийОС.ПринятиеКУчету);
	Запрос.УстановитьПараметр("Событие2", Перечисления.ВидыСобытийОС.Списание);
	
	Выборка = Запрос.Выполнить().Выбрать();
	Если Выборка.Следующий() Тогда
		НаименованиеОбъекта = Выборка.Наименование;
		ПервоначальнаяСтоимостьПолеВвода = Выборка.ПервоначальнаяСтоимость;
		ИдентификационныйНомерПолеВвода = Выборка.Код;
		ОКОФПолеВвода = Выборка.КодПоОКОФ;
		АмортизационнаяГруппаПолеВвода = Выборка.АмортизационнаяГруппа;
		ЗаводскойНомерПолеВвода = Выборка.ЗаводскойНомер;
		СостояниеОСПолеВвода = Выборка.Состояние;
		ДатаПринятияКУчету = Выборка.ПринятоКУчету;
		ДатаСнятияСУчета = Выборка.СнятоСУчета;
	КонецЕсли;

КонецПроцедуры

Теперь подсоединим вызов служебной процедуры к имеющимся обработчикам событий формы:


Процедура ИнвентарныйНомерПолеВводаОбработкаВыбора(Элемент, ВыбранноеЗначение, СтандартнаяОбработка)
	ЗаполнитьДанныеПоИнвентарномуНомеру(ВыбранноеЗначение);
КонецПроцедуры

Процедура ТаблицаТоваровИнвНомерПриИзменении(Элемент)
	ЗаполнитьДанныеПоИнвентарномуНомеру(Элемент.Значение);
КонецПроцедуры

Решение 2: Использование события «ОкончаниеВводаТекста»

Если необходимо организовать поиск непосредственно при вводе текста в поле (без необходимости создавать событие ПриИзменении), рекомендуется использовать предназначенное для этого событие элемента управления ОкончаниеВводаТекста.

В данном событии платформа передает параметры Текст, Значение и СтандартнаяОбработка:


Процедура ИнвентарныйНомерПолеВводаОкончаниеВводаТекста(Элемент, Текст, Значение, СтандартнаяОбработка)
	
	// Отключаем стандартный поиск 1С по введенной строке
	СтандартнаяОбработка = Ложь;
	
	// Выполняем поиск объекта по коду
	НайденнаяСсылка = Справочники.ОсновныеСредства.НайтиПоКоду(СокрЛП(Текст));
	
	Если ЗначениеЗаполнено(НайденнаяСсылка) Тогда
		Значение = НайденнаяСсылка;
		ЗаполнитьДанныеПоИнвентарномуНомеру(НайденнаяСсылка);
	Иначе
		Предупреждение("Объект с инвентарным номером " + Текст + " не найден!");
	КонецЕсли;

КонецПроцедуры

При таком подходе отключается стандартный поиск платформы, корректно обрабатывается введенная строка и гарантируется передача ссылки нужного типа в процедуры обработки.

← На главную