emsir
Егор Ширялин
1 комментарий 1 019 14.11.2023

Взаимозависимые поля в таблице формы 1С. Что делать, если не вызывается событие ПриНачалеРедактирования при обходе колонок в режиме редактирования строки

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

Пример:

Допустим у нас есть реквизит, хранящий тип "ДеревоЗначений". В составе дерева есть колонки "Источник" типа "Число" и "Значение" типа "Произвольный". Дерево вместе с колонками вынесено на форму. Мы хотим, чтобы в момент, когда пользователь приступает к редактированию данных в колонке "Значение", он оперировал конкретным типом данных, а не выбирал его из всех, что предлагает платформа. При этом выбор типа данных зависит от значения, установленного в поле "Источник".

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

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

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

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

Предлагаемый подход состоит в том, чтобы воспользоваться следующими событиями:

  1. Событие "ПриНачалеРедактирования" для элемента "ДеревоКолонок";
  2. Событие "ОбработкаВыбора" для элемента "ДеревоКолонокИсточник";
  3. Событие "ПриИзменении" для элемента "ДеревоКолонокИсточник";
  4. Событие "ПриИзменении" для элемента "ДеревоКолонокЗначение".

Событие ПриНачалеРедактирования для элемента "ДеревоКолонок"

Событие нужно, чтобы отловить начало редактирования колонки "ДеревоКолонокЗначение" и установить в нем нужный тип поля в зависимости от каких-то условий. Примерный код обработчика может выглядеть так:

&НаКлиенте // Процедура устанавливает правильный тип данных колонке "Значение" // непосредственно перед началом редактирования этого значения Процедура ДеревоКолонокПриНачалеРедактирования(Элемент, НоваяСтрока, Копирование) Если Элемент.ТекущийЭлемент.Имя <> "ДеревоКолонокЗначение" Тогда Возврат; КонецЕсли; ТекущиеДанные = Элементы[Элемент.Имя].ТекущиеДанные; ТипПоля = ТекущиеДанные.ТипЗначения; Если ТекущиеДанные.Источник = 0 Тогда // файл загрузки ТипПоля = Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(3, 0, ДопустимыйЗнак.Неотрицательный)); КонецЕсли; Элемент.ТекущийЭлемент.ОграничениеТипа = ТипПоля; КонецПроцедуры

Важным свойством, влияющим на ограничение типа данных в колонке, является ОграничениеТипа. Ограничение типа может принимать массив элементов типа "ОписаниеТипов" или единичное значение.

Установка этого значение в процедуре "При начале редактирования" позволит пользователю приступить непосредственно к вводу значения, минуя выбор типа.

Событие "ОбработкаВыбора" для элемента "ДеревоКолонокИсточник"

Обработка выбора подходит для ячеек, значение которых определяется выпадающим списком. Именно такой способ выбора был определен в данном примере, но на практике он может быть любым другим, тогда вы будете использовать более подходящие события.

В данной процедуре мы должны, в зависимости от нашего выбора, сохранить или сбросить данные в колонке "Значение".

Это можно сделать примерно следующим кодом:

&НаКлиенте // Процедура сбрасывает значение в колонке, при изменении источника Процедура ДеревоКолонокИсточникОбработкаВыбора(Элемент, ВыбранноеЗначение, СтандартнаяОбработка) ТекущиеДанные = Элементы.ДеревоКолонок.ТекущиеДанные; СтароеЗначение = ТекущиеДанные.Источник; Если СтароеЗначение <> ВыбранноеЗначение Тогда ТипПоля = ТекущиеДанные.ТипЗначения; Если ВыбранноеЗначение = 0 Тогда // файл загрузки ТипПоля = Новый ОписаниеТипов("Число"); КонецЕсли; ТекущиеДанные.Значение = ТипПоля.ПривестиЗначение(); КонецЕсли; КонецПроцедуры

Здесь мы проверяем меняется ли выбранное значение и, если меняется, то очищаем данные в колонке "Значение". Но почему мы не пишем просто:

ТекущиеДанные.Значение = Неопределенно;

а действуем через ПривестиЗначение()?

Потому что платформенное представление разных типов данных для их значений по умолчанию разное. Например, для числовых значений это 0 (ноль). А для значений типа "СправочникСсылка" - это обычно (если не предопределено программистом) ПустаяСсылка, которая никак не отображается в ячейке.

Идем далее.

Событие "ПриИзменении" для элемента "ДеревоКолонокИсточник"

А вот это, пожалуй, ключевой момент данной статьи. Событие "ПриИзменении" наступает при выходе из режима редактирования колонки, но - надо помнить! - режим редактирования строки в этот момент еще активен. А это значит, что будет осуществлен переход к следующей колонке, но событие "ПриНачалеРедактирования" активировано не будет! И вот тут-то пригодится следующий код:

&НаКлиенте Процедура ДеревоКолонокЗначениеПриИзменении(Элемент) ЗапретитьАвтоПереходКСледующейЯчейке(); КонецПроцедуры

Здесь мы вызываем процедуру ЗапретитьАвтоПереходКСледующейЯчейке(), которая принудительно осуществляет выход из режима редактирования строки. Это позволяет нам заново активировать событие ПриНачалеРедактирования на входе в ячейку колонки "Значение" и осуществить в нем нужные действия по установке типа данных.

Вот нехитрый код самой процедуры:

&НаКлиенте // Процедура решает следующие проблемы: // 1. Запрещает автоматическое перемещение активной ячейки в редактируемой строке по Enter // 2. Запрещает переход к новой строке по Enter Процедура ЗапретитьАвтоПереходКСледующейЯчейке(ОтменаРедактирования = Ложь) Элементы.ДеревоКолонок.ЗакончитьРедактированиеСтроки(ОтменаРедактирования); КонецПроцедуры

Событие "ПриИзменении" для элемента "ДеревоКолонокЗначение"

Здесь пропишем тот же самый код:

&НаКлиенте Процедура ДеревоКолонокЗначениеПриИзменении(Элемент) ЗапретитьАвтоПереходКСледующейЯчейке(); КонецПроцедуры

Таким образом, мы решили проблему выбора типа данных и облегчили пользователю работу с формой.

Теперь, надеюсь, что в вашей практике данная задача будет решаться гораздо быстрее.

Комментарии (1)
Наталья Назарова
07.04.2025 в 10:02
Спасибо огромное, добрый человек!!! Час был убит впустую, пока не нашла это спасение!!! Благодарю!

Для добавления комментария необходимо авторизоваться.

Вход | Регистрация