Добрый день, друзья!
Недавно стал участником перехода с платформы 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 лучше работать на управляемых формах… Может, я здесь, конечно, и не прав. В любом случае хочу сказать, что в таких ситуациях, когда перестают работать привычные для тебя методы работы и приходится в быстром порядке придумывать новые, получаешь наибольший опыт. Такой выход из зоны комфорта помогает взглянуть на привычные вещи с другой стороны и ещё это весело. Но это не точно:)
С багом из статьи пока не встречался, но зато очень мешает когда при копировании в строку поиска текста например из Excel кроме искомого текста в конце строки подставляется еще и знак переноса строки ¶ и 1с в итоге ничего не находит пока его не удалишь…
Зачем старую перепиленную базу на 8.3 переводить?
(3) А чтоб повеселиться? Скучно ведь, когда все нормально работает….
(3) как вариант чтоб избежать зоопарка платформ, т.к. может стоять параллельно БП и ЗУП которые просят новую платформу.
(5) да, вполне вероятно, когда есть базы, требующие платформы 8.3
(3)
1) Внедрение БСП,
2) JSON
3) SSL
4) Все базы на одной платформе
5) Подсветка кода наконец!
(7) а, ну это аргумент конечно. Чтобы построить новое надо сломать старое.
(1)
Деловые линии на обычных формах, и ч0?
(9) я
не помнюне знаю никаких деловых линий и прочего некрофильского 1С-софта и ч0?У вас сканер не прописан в подключаемом оборудовании что ли? И в целом непонятен пример: зачем очищать поле после сканирования?
Замечание:
Вместо ОбновлениеОтображения() в типовых используют однократный запуск обработчика ожидания с таймаутом 0.1 сек
(12) Зачем так делают в типовых?
А так да, не буду, пожалуй, на 8.2 с 8.3 специализированную конфу переводить…
(11)
В УТ 10.2 нет библиотеки подключаемого оборудования.
Я сделал очистку для наглядности, срабатывает ли команда ТекущийЭлемент = Элемент. А в целом, в поле ввода юзер вбивает штрих-код, при изменении происходит обработка данных в соответствии с введённым штрих-кодом. После обработки поле ввода должно очищаться и текущим элементом должен снова стать элемент ввода кода, чтобы снова вбивать новые штрих-коды.
(1) 🙂 я тут на днях в розничном магазине АРМ 1С77 встретил…. Согласно Вашей логике, они должны были давно в розницу на 8.3 убежать… Только зачем?
А вот перейти на 8.3 с обычными формами не претит, т.к.вендор сказал что наследуется и все хорошо…..
Спасибо! Один в один ситуация описанная в п. 2. Только это не баг 8.2 — 8.3. У меня это проявилось при переходе с 8.3.10 на 8.3.13.1690. Есть две самописки одна на обычных, одна полностью на УФ. Теперь именно из за неизвестных багов на ОФ я боюсь обновлять платформу на 14-15.
(13)
Чтобы перевести курсор на нужное поле (например)
(16) тоже 77 еще используем
(5) Для этого есть режим совместимости.
(20) Для чего есть режим совместимости?
(21)
(22)видимо я потерял мысль, т.к. я отвечал своим 5 постом на вопрос 3 поста.