Каталог решений - Парочка интересных багов.

Парочка интересных багов.

Парочка интересных багов.

В наличии

Баги, обнаруженные на платформе 8.3 после перехода с 8.2.

Категория:

Описание

Добрый день, друзья!

Недавно стал участником перехода с платформы 8.2 на 8.3. База старая и сто раз переписанная. К сожалению, непосредственное участие принять не удалось, зато мне выпала честь исправлять появившиеся баги после перехода. Пару самых интересных по моему мнению опишу в этой статье.

Пояснения: переход осуществлялся с версии платформы 8.2.19.130 на 8.3.13.1690. И конфигурация написана на обычных формах (на самом деле там всё смешано, но большая часть на обычных), то есть все случаи будут затрагивать работу в обычном приложении. Ладно, поехали.

Случай 1.

Предисловие.

Мы все хорошо знаем, что при автоподборе текста стандартный алгоритм такой: ищутся первые 50 записей, найденных по реквизитам, указанным в параметре "Ввод по строке" объекта вот здесь:

При обусловненной необходимости этот список можно дополнить, но, естественно, добавляемое поле должно быть проиндексировано. Если есть всего одна найденная запись, то оставшаяся часть строки ввода добавляется; нет нужды всё описывать в подробностях. Если найденных записей не больше пятидесяти, то выпадает список выбора значения, а, если больше, то ничего не происходит.

Теперь посмотрим, как происходит автоподбор текста на разных платформах:

 — 8.2. Всё как обычно.

  — 8.3. После автоподбора курсор переносится в конец подобранной строки.

Для тех, кто смотрит в монитор или пишет быстрее того момента, когда срабатывает обработчик, это, может быть, и не проблема. У остальных же это вызвало, мягко говоря, недовольство. Что поделать, придется переписывать стандартную обработку…

Для начала, нужно получить из метаданных все поля ввода по строке и в соответствии с этим формировать запрос. Прилагаю листинг ниже.

Процедура ПолеВвода1АвтоПодборТекста(Элемент, Текст, ТекстАвтоПодбора, СтандартнаяОбработка)
	СтандартнаяОбработка = Ложь;
	ТекстЗапросаПоле = "";
	ТекстЗапросаУсловие = "";
	КоличествоПолейВводаПоСтроке = Метаданные.Справочники.НомераГТД.ВводПоСтроке.Количество();
	Для ТекСтрока = 1 По КоличествоПолейВводаПоСтроке Цикл
		
		ПолеВводПоСтроке = Метаданные.Справочники.НомераГТД.ВводПоСтроке.Получить(ТекСтрока - 1);
		
		ТекстЗапросаПоле = ТекстЗапросаПоле + "
		|		КОГДА НомераГТД." + ПолеВводПоСтроке.Имя + " ПОДОБНО &Текст
		|			ТОГДА НомераГТД." + ПолеВводПоСтроке.Имя;
		
		ТекстЗапросаУсловие = ?(ТекСтрока = 1, "(", "") + ТекстЗапросаУсловие + "
		| НомераГТД." + ПолеВводПоСтроке.Имя + " ПОДОБНО &Текст" + ?(ТекСтрока = КоличествоПолейВводаПоСтроке, ")", Символы.ПС + "ИЛИ ");
		
	КонецЦикла; 
	
	
	Запрос = Новый Запрос;
	Запрос.УстановитьПараметр("Текст", Текст + "%");
	Запрос.Текст = 
	"ВЫБРАТЬ
	|	ВЫБОР"
	+ ТекстЗапросаПоле + "
	|	КОНЕЦ КАК ТекстАвтоПодбора,
	|	НомераГТД.Представление,
	|	НомераГТД.Ссылка
	|ИЗ
	|	Справочник.НомераГТД КАК НомераГТД
	|ГДЕ " + ТекстЗапросаУсловие;
	РезультатЗапроса = Запрос.Выполнить();
	Если Не РезультатЗапроса.Пустой() Тогда
		Выборка = РезультатЗапроса.Выбрать();
		КоличествоЗаписей = Выборка.Количество();
		Если Выборка.Количество() = 1 Тогда
			Выборка.Следующий();
			ТекстАвтоПодбора = Выборка.ТекстАвтоПодбора;
		ИначеЕсли Выборка.Количество() <= 50 Тогда	
			СписокВыбора = Новый СписокЗначений;
			Пока Выборка.Следующий() Цикл
				СписокВыбора.Добавить(Выборка.Ссылка, 
									  ?(Выборка.ТекстАвтоПодбора = Выборка.Представление, СокрЛП(Выборка.ТекстАвтоПодбора), СокрЛП(Выборка.ТекстАвтоПодбора) + " (" + СокрЛП(Выборка.Представление) + ")"));	
			КонецЦикла;
			ВыбранноеЗначение = ВыбратьИзСписка(СписокВыбора, Элемент);					  
			Если ВыбранноеЗначение <> Неопределено Тогда
				Элемент.Значение = ВыбранноеЗначение.Значение;
			КонецЕсли; 					  
		КонецЕсли; 
	КонецЕсли; 	
КонецПроцедуры

Можно было бы не париться и просто обратиться с поиском по коду. С другой стороны, мы хотим повторить полный функционал платформы и нам нельзя игнорировать настройки, указанные в метаданных. После формирования запроса проверяем количество записей результата: если запись одна, то просто приравниваем результат к параметру ТекстАвтоПодбора. Интересно, что, если вручную установить этот параметр, то баг пропадет. Если записей не больше пятидесяти, то формируем список значений и формируем выбор из списка. Для оптимизации запроса можно, конечно, вписать "ВЫБРАТЬ ПЕРВЫЕ 51", но я подумал, что это может выжечь кому-нибудь глаза, поэтому не стал:)

Вроде готово, смотрим результат:

 — когда найденная запись только одна;

  — когда записей несколько;

Также, когда записей несколько, но они найдены не по полю основного представления, то представление элемента нужно также внести в скобки в списке выбора. Для теста специально добавил в поля ввода ещё один реквизит. Процесс добавления:

 -внес в индекс

  — добавил в поля ввода по строке.

Результат автоподбора текста:

Вот так в итоге получилось.

 

Случай 2.

Предисловие.

В некоторых ситуациях при изменении поля ввода необходимо, чтобы курсор возвращался в это же поле. К примеру, это подходит для тех полей, куда вносится штрих-код: чтобы сработал обработчик ПриИзменении приходится после сканирования вставлять символ переноса каретки, после это поле очищается и курсор переносится туда же.

Итак, вот какой жук нашелся. Для наглядности создам обработку с двумя строчками кода при изменении поля ввода: первая строчка очищает значение элемента, вторая устанавливает свойство ТекущийЭлемент = Элемент. Смотрим:

 — 8.2 всё ок;

 — 8.3 вторая строчка кода не срабатывает…

Окей. Конечно, от этого никто не помрёт, но эмоций, поверьте, много, особенно у тех, кто пользуется сканером штрих-кода… Как это исправить? Что только ни пытался сделать. Пробовал в конце обработчика ставить строчку Элемент.ВыделенныйТекст = " ". В каком-то смысле это помогло, однако, в поле ввода красовался пробел, что совсем нам не нужно.

Нашелся выход из данной ситуации не сказать, что прямо идеальный, но другого выхода не нашлось. С выходом платформы 8.3 на форме появился новый обработчик ОбновлениеОтображения. Хотя в методичке по этому обработчику говорится, что так делать нельзя из-за возможности падения производительности системы, как я уже говорил, другого выхода не нашлось. Итак, пишу листинг:

Перем ЭтоИзменениеНужногоПоля;

Процедура ПолеВводаПостояннымКурсоромПриИзменении(Элемент)
	Элемент.Значение = "";
КонецПроцедуры

Процедура ОбновлениеОтображения()
	Если ЭтоИзменениеНужногоПоля Тогда
		ТекущийЭлемент = ЭлементыФормы.ПолеВводаПостояннымКурсором;
	КонецЕсли; 	
КонецПроцедуры

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

ЭтоИзменениеНужногоПоля = Ложь;

Итак, создаю глобальную переменную формы ЭтоИзменениеНужногоПоля. Она нужна для того, чтобы возврат в нужный элемент формы происходил только после нужного мне события. При окончании ввода текста в нужном поле ввода при заполненном значении устанавливаю значение моей переменной в Истина. После всех обработчиков срабатывает обработчик ОбновлениеОтображения. Там я проверяю, что, если изменено нужное поле, то ставлю ТекущийЭлемент в нужный элемент формы. Вуаля. Результат:

 — норм.

Вроде бы косяки и мелкие, но пришлось достаточно попотеть, чтобы их устранить. После всего я подумал, что на 8.3 лучше работать на управляемых формах… Может, я здесь, конечно, и не прав. В любом случае хочу сказать, что в таких ситуациях, когда перестают работать привычные для тебя методы работы и приходится в быстром порядке придумывать новые, получаешь наибольший опыт. Такой выход из зоны комфорта помогает взглянуть на привычные вещи с другой стороны и ещё это весело. Но это не точно:)

has been added to your cart:
Оформление заказа