Как определить текущую закладку, регистр и колонку в документе «Корректировка записей регистров» на обычных формах

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

В типовых конфигурациях на обычных формах (таких как УПП 1.3, Комплексная автоматизация 1.1 и других) документ КорректировкаЗаписейРегистров устроен достаточно сложно. Его форма содержит многоуровневую структуру закладок для работы с различными типами регистров: регистрами бухгалтерии, накопления и сведений. При разработке дополнительного функционала (например, группового копирования или вставки значений колонок) часто возникает задача: в обработчике нажатия кнопки программно определить, на какой именно закладке и в какой колонке табличного поля находится пользователь.

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

Причины сложности и особенности работы фокуса в обычных формах

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

  1. Перехват фокуса элементом управления: если на форму вынесена стандартная отдельная Кнопка, то в момент клика мышью фокус ввода сразу переходит на саму кнопку. В результате обращение к ЭтаФорма.ТекущийЭлемент вернет ссылку на эту кнопку, а не на табличное поле, в котором пользователь только что выделял ячейку.
  2. Вложенность страниц: панель регистров в документе состоит из главной панели (ПанельРегистров) и подчиненных панелей (ПанельРегистровБухгалтерии, ПанельРегистровНакопления, ПанельРегистровСведений). Чтобы добраться до конкретного табличного поля, необходимо последовательно проанализировать активные страницы на каждом уровне.

Способ 1. Анализ иерархии закладок через свойства панелей

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


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

Посмотрим на логику работы этого кода:

  1. Сначала считывается свойство ЭлементыФормы.ПанельРегистров.ТекущаяСтраница.Имя, что дает понимание раздела (бухгалтерия, накопление или сведения).
  2. Для регистров бухгалтерии выполняется проверка вложенной панели ПанельРегистровБухгалтерии с явной адресацией к табличным полям движений (ТабличноеПолеДвиженияБУ, ТабличноеПолеДвиженияНУ и т.д.).
  3. Для регистров сведений и накопления имя страницы совпадает с именем элемента управления табличного поля, что позволяет получить объект через ЭлементыФормы[ИмяРегистра].
  4. Через свойства ТекущаяКолонка и ТекущаяСтрока извлекаются параметры выделенной ячейки.

Способ 2. Использование командной панели или контекстного меню

Чтобы избежать потери фокуса при нажатии кнопок, рекомендуется изменить способ размещения пользовательских команд:

  1. Размещение кнопки в КоманднойПанели: элементы типа Действие в объекте КоманднаяПанель при нажатии не забирают фокус ввода на себя. В таком случае в обработчике команды свойство ЭтаФорма.ТекущийЭлемент продолжит указывать на активное табличное поле регистра.
  2. Добавление пунктов в контекстное меню: если добавить действия «Копировать колонку» и «Вставить в колонку» в контекстное меню табличных полей, команда будет гарантированно вызываться в контексте той таблицы, по которой кликнул пользователь.

Способ 3. Сохранение активной таблицы и колонки через события формы

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

Разберем по шагам реализацию этого подхода:

  1. В начале модуля формы объявляем переменные для хранения контекста:
    
    Перем мАктивноеТабличноеПоле;
    Перем мАктивнаяКолонка;
    
  2. Назначаем для табличных полей регистров обработчик события ПриАктивизацииЯчейки или ПриАктивизацииКолонки:
    
    Процедура ТабличноеПолеПриАктивизацииЯчейки(Элемент)
    	мАктивноеТабличноеПоле = Элемент;
    	мАктивнаяКолонка = Элемент.ТекущаяКолонка;
    КонецПроцедуры
    
  3. В обработчике нажатия отдельной кнопки сразу обращаемся к сохраненным переменным без необходимости сложного обхода панелей:
    
    Процедура КнопкаВставитьНажатие(Элемент)
    	Если мАктивноеТабличноеПоле = Неопределено Или мАктивнаяКолонка = Неопределено Тогда
    		Предупреждение("Не выбрана колонка для вставки!");
    		Возврат;
    	КонецЕсли;
    	
    	ИмяКолонки = мАктивнаяКолонка.Имя;
    	НаборЗаписей = мАктивноеТабличноеПоле.Значение;
    	
    	// Выполняем обход строк набора и заполнение
    	Для Каждого Запись Из НаборЗаписей Цикл
    		Запись[ИмяКолонки] = СохраненноеЗначение;
    	КонецЦикла;
    	
    	ЭтаФорма.Модифицированность = Истина;
    КонецПроцедуры
    

Важные рекомендации при работе с наборами записей

При программной вставке скопированных данных из одного регистра в другой учитывайте следующие особенности платформы 1С:

  1. Совместимость типов данных: колонки разных регистров могут иметь различные типы (число, строка, ссылка определенного справочника). Перед пакетной записью значений проверяйте соответствие типов, чтобы избежать ошибок при записи документа.
  2. Флаг модифицированности: при программном изменении строк через свойство Значение табличного поля (тип РегистрСведенийНаборЗаписей, РегистрНакопленияНаборЗаписей) обязательно устанавливайте ЭтаФорма.Модифицированность = Истина;. Это гарантирует, что платформа предложит сохранить изменения при закрытии формы.
← На главную