Связанные табличные части (управляемые формы)

Публикация № 989417

Программирование - Практика программирования

обработка табличная часть управляемая форма отбор строк

6
У нас есть 2 связанные табличные части, и нам надо, чтобы по текущей строке в одной из них мы видели только определенные строки во второй. Были бы у нас динамические списки, мы бы взяли событие "При активизации строки" и стандартный механизм отборов СКД, которая лежит в основе списка. Но вот с табличными частями так не получится. Тут нам надо будет написать несколько строк кода и использовать "ОтборСтрок", доступный для таблицы формы. Тестировалось на платформе 8.3.13.1644, будет работать и на более ранних версиях платформы.

Про "ОтборСтрок" я уже писал в недалеком прошлом поэтому не буду повторяться. Что это и для чего это используется можно изучить в статье Отборы (поиск) в табличной части либо таблице значений (управляемые формы)

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

Конфигурация состоит из двух справочников: "Контрагенты" и "Товары" и одного документа "Поступление товаров". Данный документ имеет 2 соответствующие табличные части и предназначен для получения товаров от разных клиентов в одном документе.

Визуально форма выглядит так:

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

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

Для нашей левой табличной части "Контрагенты" нам надо добавить следующие обработчики событий:

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

&НаКлиенте
Процедура КонтрагентыПриАктивизацииСтроки(Элемент)
	ТекДанные = Элемент.ТекущиеДанные;
	УстановитьОтборПоКлючу(ТекДанные,Элементы.Товары,НаименованиеКлючаСвязи);
КонецПроцедуры

&НаКлиенте
Процедура КонтрагентыПередУдалением(Элемент, Отказ)
	ОбщаяПроцедураУдалитьСтроки(Элемент.ТекущиеДанные,Объект.Товары,НаименованиеКлючаСвязи);
КонецПроцедуры

&НаКлиенте
Процедура КонтрагентыПриОкончанииРедактирования(Элемент, НоваяСтрока, ОтменаРедактирования)
	ТекДанные = Элемент.ТекущиеДанные;
	
	ТекНаименованиеКлюча = НаименованиеКлючаСвязи;
	
	Если ТекДанные[ТекНаименованиеКлюча] <> ТекДанные[ТекНаименованиеКлюча + "Начальный"] Тогда
		
		ПерезаполнитьЗначениеКлюча(ТекДанные[ТекНаименованиеКлюча+"Начальный"],ТекДанные[ТекНаименованиеКлюча],"Товары",ТекНаименованиеКлюча);
		
		ТекДанные[ТекНаименованиеКлюча + "Начальный"] = ТекДанные[ТекНаименованиеКлюча];
		
	КонецЕсли;
	
	УстановитьОтборПоКлючу(ТекДанные,Элементы.Товары,ТекНаименованиеКлюча);
КонецПроцедуры

Сами процедуры обработки:

&НаКлиенте
Процедура УстановитьОтборПоКлючу(ТекДанные,ТекЭлем,НаименованиеКлюча)
	Если ТекДанные = Неопределено Тогда
 		Возврат;
	КонецЕсли;

	// Создаем структуру отбора
	Отбор = Новый Структура;
	Отбор.Вставить(НаименованиеКлюча, ТекДанные[НаименованиеКлюча]);
	// Задаем фиксированную структуру отбора для таблицы формы
	ТекЭлем.ОтборСтрок = Новый ФиксированнаяСтруктура(Отбор);
КонецПроцедуры

&НаКлиенте 
Процедура ОбщаяПроцедураУдалитьСтроки(ТекДанные,ТекЭлем,НаименованиеКлюча)
	Если ТекДанные <> Неопределено Тогда
		МассивСтрок = ТекЭлем.НайтиСтроки(Новый Структура (НаименованиеКлюча,ТекДанные[НаименованиеКлюча]));
		Для Каждого СтрМассива ИЗ МассивСтрок Цикл
			ТекЭлем.Удалить(СтрМассива);
		КонецЦикла;
	КонецЕсли;
КонецПроцедуры

&НаСервере
Процедура ПерезаполнитьЗначениеКлюча (ЗначениеКлючаНачальный,ЗначениеКлюча,НаименованиеТабЧасти,НаименованиеКлюча)
	Если ЗначениеЗаполнено(ЗначениеКлючаНачальный) Тогда
		ТекЭлем = Объект[НаименованиеТабЧасти];
		МассивСтрок = ТекЭлем.НайтиСтроки(Новый Структура (НаименованиеКлюча,ЗначениеКлючаНачальный));
		Для Каждого СтрМассива ИЗ МассивСтрок Цикл
			СтрМассива[НаименованиеКлюча] = ЗначениеКлюча;
		КонецЦикла;
	КонецЕсли;
КонецПроцедуры

Для правой табличной части "Товары" нам также надо обработать несколько событий:

Мы должны отклонить выбор номенклатуры если у нас нет или не выбран контрагент и автоматически заполнять значение ключа связи - в нашем случае это ссылка на контрагента. Сами процедуры:

&НаКлиенте
Процедура ТоварыПередНачаломДобавления(Элемент, Отказ, Копирование, Родитель, Группа, Параметр)
	Если Элементы.Контрагенты.ТекущиеДанные = Неопределено Тогда
		Отказ = Истина;
	КонецЕсли;
КонецПроцедуры

&НаКлиенте
Процедура ТоварыПриНачалеРедактирования(Элемент, НоваяСтрока, Копирование)
	Если НоваяСтрока И НЕ Копирование Тогда
		Элемент.ТекущиеДанные[НаименованиеКлючаСвязи] = Элементы.Контрагенты.ТекущиеДанные[НаименованиеКлючаСвязи];
	КонецЕсли;
КонецПроцедуры

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

&НаКлиенте
Процедура ОчиститьОтбор(Команда)
	СнятьОтборСЭлементов(Элементы.Товары);
КонецПроцедуры

UPD 1. 26.01.2019

Для того, чтобы учесть возможность смены самого контрагента, мы добавили в форме реквизит табличной части :

Сделали его заполнение при открытии формы и обрабатываем его изменение в коде:

&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
	//Определим ключ связи
	НаименованиеКлючаСвязи = "Контрагент";
	
	ДозаполнитьТабЧасть();
КонецПроцедуры

&НаСервере
Процедура ПослеЗаписиНаСервере(ТекущийОбъект, ПараметрыЗаписи)
	ДозаполнитьТабЧасть();
КонецПроцедуры

&НаСервере
Процедура ДозаполнитьТабЧасть ()
	Для Каждого СтрТаб ИЗ Объект.Контрагенты Цикл
		СтрТаб[НаименованиеКлючаСвязи+"Начальный"] = СтрТаб[НаименованиеКлючаСвязи];
	КонецЦикла;
КонецПроцедуры

Для большей универсальности стал использовать реквизит формы "НаименованиеКлючаСвязи", который устанавливаю 1 раз и использую потом везде.

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

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

Механизм реализации такой абсолютно такой же.

6

Скачать файлы

Наименование Файл Версия Размер
Связанные табличные части (демо конфигурация):
.cf 19,67Kb
25.01.19
1
.cf 1.0.2 19,67Kb 1 Скачать

См. также

Специальные предложения

Комментарии
Избранное Подписка Сортировка: Древо
1. ltfriend 309 26.01.19 09:41 Сейчас в теме
Изменили контрагента и имеем несвязанные строки номенклатуры, которые ни кто не увидит и которые так и будут «болтаться» вечно в документе.
2. Kim1C 75 26.01.19 13:24 Сейчас в теме
(1) Да, согласен, не продумал. Исправил статью и конфигурацию и добавил возможность менять контрагента
Оставьте свое сообщение