В типовых конфигурациях на обычных формах (таких как УПП 1.3, Комплексная автоматизация 1.1 и других) документ КорректировкаЗаписейРегистров устроен достаточно сложно. Его форма содержит многоуровневую структуру закладок для работы с различными типами регистров: регистрами бухгалтерии, накопления и сведений. При разработке дополнительного функционала (например, группового копирования или вставки значений колонок) часто возникает задача: в обработчике нажатия кнопки программно определить, на какой именно закладке и в какой колонке табличного поля находится пользователь.
Разберем детально, почему стандартные подходы могут давать сбой, как правильно обойти структуру страниц формы и как обойти проблему перехвата фокуса кнопкой.
При попытке определить активный элемент управления разработчики часто сталкиваются со следующими проблемами:
Кнопка, то в момент клика мышью фокус ввода сразу переходит на саму кнопку. В результате обращение к ЭтаФорма.ТекущийЭлемент вернет ссылку на эту кнопку, а не на табличное поле, в котором пользователь только что выделял ячейку.ПанельРегистров) и подчиненных панелей (ПанельРегистровБухгалтерии, ПанельРегистровНакопления, ПанельРегистровСведений). Чтобы добраться до конкретного табличного поля, необходимо последовательно проанализировать активные страницы на каждом уровне.Рассмотрим практическое решение, которое последовательно опрашивает свойства ТекущаяСтраница у всех задействованных панелей формы. Этот способ позволяет точно вычислить имя регистра и получить соответствующее ТабличноеПоле, а затем прочитать имя текущей колонки и данные строки.
Процедура КопироватьДанныеКолонкиНажатие(Элемент)
// Определяем активную страницу главной панели
ИмяГлавнойЗакладки = ЭлементыФормы.ПанельРегистров.ТекущаяСтраница.Имя;
ТекущаяПанель = Неопределено;
ИмяРегистра = Неопределено;
ТабличноеПолеНаЗакладке = Неопределено;
Если ИмяГлавнойЗакладки = "РегистрыБухгалтерии" Тогда
ИмяВложеннойЗакладки = ЭлементыФормы.ПанельРегистровБухгалтерии.ТекущаяСтраница.Имя;
ТекущаяПанель = ЭлементыФормы.ПанельРегистровБухгалтерии.Страницы[ИмяВложеннойЗакладки];
ИмяРегистра = ТекущаяПанель.Имя;
// Сопоставляем имя регистра с табличным полем на форме
Если ИмяРегистра = "Хозрасчетный" Тогда
ТабличноеПолеНаЗакладке = ЭлементыФормы.ТабличноеПолеДвиженияБУ;
ИначеЕсли ИмяРегистра = "Бюджетирование" Тогда
ТабличноеПолеНаЗакладке = ЭлементыФормы.ТабличноеПолеДвиженияБюджетирование;
ИначеЕсли ИмяРегистра = "Международный" Тогда
ТабличноеПолеНаЗакладке = ЭлементыФормы.ТабличноеПолеДвиженияМУ;
ИначеЕсли ИмяРегистра = "Налоговый" Тогда
ТабличноеПолеНаЗакладке = ЭлементыФормы.ТабличноеПолеДвиженияНУ;
КонецЕсли;
Иначе
Если ИмяГлавнойЗакладки = "РегистрыНакопления" Тогда
ТекущаяПанель = ЭлементыФормы.ПанельРегистровНакопления;
ИмяРегистра = ТекущаяПанель.ТекущаяСтраница.Имя;
ИначеЕсли ИмяГлавнойЗакладки = "РегистрыСведений" Тогда
ТекущаяПанель = ЭлементыФормы.ПанельРегистровСведений;
ИмяРегистра = ТекущаяПанель.ТекущаяСтраница.Имя;
КонецЕсли;
// Проверяем, что выбрана не пустая страница-заглушка
Если ИмяРегистра = "Подсказка" Тогда
ИмяРегистра = Неопределено;
КонецЕсли;
Если ИмяРегистра <> Неопределено Тогда
ТабличноеПолеНаЗакладке = ЭлементыФормы[ИмяРегистра];
КонецЕсли;
КонецЕсли;
// Получаем текущую колонку и данные активной строки
Если ТабличноеПолеНаЗакладке <> Неопределено Тогда
Если ТабличноеПолеНаЗакладке.ТекущаяКолонка <> Неопределено Тогда
ТекущаяКолонка = ТабличноеПолеНаЗакладке.ТекущаяКолонка.Имя;
Сообщить("Выбрана колонка: " + ТекущаяКолонка);
КонецЕсли;
ТекущаяСтрокаДанные = ТабличноеПолеНаЗакладке.ТекущаяСтрока;
КонецЕсли;
КонецПроцедуры
Посмотрим на логику работы этого кода:
ЭлементыФормы.ПанельРегистров.ТекущаяСтраница.Имя, что дает понимание раздела (бухгалтерия, накопление или сведения).ПанельРегистровБухгалтерии с явной адресацией к табличным полям движений (ТабличноеПолеДвиженияБУ, ТабличноеПолеДвиженияНУ и т.д.).ЭлементыФормы[ИмяРегистра].ТекущаяКолонка и ТекущаяСтрока извлекаются параметры выделенной ячейки.Чтобы избежать потери фокуса при нажатии кнопок, рекомендуется изменить способ размещения пользовательских команд:
Действие в объекте КоманднаяПанель при нажатии не забирают фокус ввода на себя. В таком случае в обработчике команды свойство ЭтаФорма.ТекущийЭлемент продолжит указывать на активное табличное поле регистра.Если интерфейс требует наличия отдельных кнопок вне командных панелей, самым надежным решением будет фиксация активного элемента в переменных модуля формы.
Разберем по шагам реализацию этого подхода:
Перем мАктивноеТабличноеПоле;
Перем мАктивнаяКолонка;
ПриАктивизацииЯчейки или ПриАктивизацииКолонки:
Процедура ТабличноеПолеПриАктивизацииЯчейки(Элемент)
мАктивноеТабличноеПоле = Элемент;
мАктивнаяКолонка = Элемент.ТекущаяКолонка;
КонецПроцедуры
Процедура КнопкаВставитьНажатие(Элемент)
Если мАктивноеТабличноеПоле = Неопределено Или мАктивнаяКолонка = Неопределено Тогда
Предупреждение("Не выбрана колонка для вставки!");
Возврат;
КонецЕсли;
ИмяКолонки = мАктивнаяКолонка.Имя;
НаборЗаписей = мАктивноеТабличноеПоле.Значение;
// Выполняем обход строк набора и заполнение
Для Каждого Запись Из НаборЗаписей Цикл
Запись[ИмяКолонки] = СохраненноеЗначение;
КонецЦикла;
ЭтаФорма.Модифицированность = Истина;
КонецПроцедуры
При программной вставке скопированных данных из одного регистра в другой учитывайте следующие особенности платформы 1С:
Значение табличного поля (тип РегистрСведенийНаборЗаписей, РегистрНакопленияНаборЗаписей) обязательно устанавливайте ЭтаФорма.Модифицированность = Истина;. Это гарантирует, что платформа предложит сохранить изменения при закрытии формы.