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

25.01.19

Разработка - Механизмы платформы 1С

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

UPD 1. 26.01.2019

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

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

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

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

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

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

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

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

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

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

См. также

Поинтегрируем: сервисы интеграции – новый стандарт или просто коннектор?

Обмен между базами 1C Администрирование СУБД Механизмы платформы 1С Платформа 1С v8.3 Бесплатно (free)

В платформе 8.3.17 появился замечательный механизм «Сервисы интеграции». Многие считают, что это просто коннектор 1С:Шины. Так ли это?

11.03.2024    4454    dsdred    53    

70

Как готовить и есть массивы

Механизмы платформы 1С Платформа 1С v8.3 Бесплатно (free)

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

24.01.2024    5277    YA_418728146    25    

63

Планы обмена VS История данных

Обмен между базами 1C Механизмы платформы 1С Платформа 1С v8.3 Бесплатно (free)

Вы все еще регистрируете изменения только на Планах обмена и Регистрах сведений?

11.12.2023    6396    dsdred    36    

111

1С-ная магия

Механизмы платформы 1С Бесплатно (free)

Язык программирования 1С содержит много нюансов и особенностей, которые могут приводить к неожиданным для разработчика результатам. Сталкиваясь с ними, программист начинает лучше понимать логику платформы, а значит, быстрее выявлять ошибки и видеть потенциальные узкие места своего кода там, где позже можно было бы ещё долго медитировать с отладчиком в поисках источника проблемы. Мы рассмотрим разные примеры поведения кода 1С. Разберём результаты выполнения и ответим на вопросы «Почему?», «Как же так?» и «Зачем нам это знать?». 

06.10.2023    18464    SeiOkami    46    

118

Дефрагментация и реиндексация после перехода на платформу 8.3.22

Механизмы платформы 1С Платформа 1С v8.3 Бесплатно (free)

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

14.09.2023    12074    human_new    27    

74

Валидация JSON через XDTO (включая массивы)

WEB-интеграция Универсальные функции Механизмы платформы 1С Платформа 1С v8.3 Конфигурации 1cv8 Бесплатно (free)

При работе с интеграциями рано или поздно придется столкнуться с получением JSON файлов. И, конечно же, жизнь заставит проверять файлы перед тем, как записывать данные в БД.

28.08.2023    8800    YA_418728146    6    

141

Внешние компоненты Native API на языке Rust - Просто!

Механизмы платформы 1С Платформа 1С v8.3 Конфигурации 1cv8 Бесплатно (free)

Внешние компоненты для 1С можно разработывать очень просто, пользуясь всеми преимуществами языка Rust - от безопасности и кроссплатформенности до удобного менеджера библиотек.

20.08.2023    6273    sebekerga    54    

94

Все скопируем и вставим! (Буфер обмена в 1С 8.3.24)

Механизмы платформы 1С Платформа 1С v8.3 Конфигурации 1cv8 Бесплатно (free)

Рассмотрим новую возможность 8.3.24 и как её можно эффективно использовать

27.06.2023    15968    SeiOkami    31    

103
Комментарии
В избранное Подписаться на ответы Сортировка: Древо развёрнутое
Свернуть все
1. ltfriend 954 26.01.19 09:41 Сейчас в теме
Изменили контрагента и имеем несвязанные строки номенклатуры, которые ни кто не увидит и которые так и будут «болтаться» вечно в документе.
2. Kim1C 178 26.01.19 13:24 Сейчас в теме
(1) Да, согласен, не продумал. Исправил статью и конфигурацию и добавил возможность менять контрагента
3. user1374678 08.03.20 12:00 Сейчас в теме
Я новичок подскажите пожалуйста куда нужно именно писать сами процедуры обработки
4. Kim1C 178 08.03.20 18:32 Сейчас в теме
(3) Все процедуры располагаются в форме. Можно скачать cf - там будет сразу форма с примером рабочая и можно посмотреть, что как работает
5. user723499 27.05.20 10:01 Сейчас в теме
Можно переключить зависимый список в произвольный запрос, там установить параметр для того поля, по которому осуществляется отбор - например хочу смотреть остатки по номенклатуре перемещаясь по справочнику номенклатуры. А потом ПриАктивизацииСтроки делаю такое (Список - это основной список, Остатки - зависимый список)

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


Вроде работает. Подскажите - такой вариант не комильфо или тоже подойдёт?
6. Kim1C 178 28.05.20 15:48 Сейчас в теме
(5) В принципе да, сработает. Но вам нужен произвольный запрос и параметр. В запросе вам придется учесть пустой параметр (если вдруг понадобиться посмотреть весь список) Я бы лучше делал через программную установку отбора. Тогда легко и быстро делается очистка всех отборов. И можно запрос оставлять типовой просто указывая таблицу
7. 7OH 69 13.07.20 16:20 Сейчас в теме
А если контрагента через поиск найти - активизируется строка ?
8. Zamik 5 02.06.21 07:08 Сейчас в теме
А если связь между двумя таблицами идет не через видимое поле, а через некий абстрактный ключ, который пользователь не должен видеть?

Что будет если пользователь в настройках формы скроет столбец Контрагент?
9. Kim1C 178 03.06.21 04:49 Сейчас в теме
А если связь между двумя таблицами идет не через видимое поле, а через некий абстрактный ключ, который пользователь не должен видеть?

В самой конфигурации, если скачаете, тоже добавил такой пример - через ключ связи (см. последний скриншот), который пользователь не видит.
Что будет если пользователь в настройках формы скроет столбец Контрагент?

Что касается связи тч через контрагента, то в левой ТЧ нет смысла скрывать контрагента - там по факту ничего больше нет. в правой его и так не видно. Учитывая, что у нас таблицы значений, а не динамические списки, то проблем не будет.
Для динамических списков если нужна подобная связь надо устанавливать соответствующие отборы (см. методы БСП в модуле ОбщегоНазначенияКлиентСервер для работы с дин. списком)
10. eretic 02.09.21 20:36 Сейчас в теме
что будет если в новой строке пользователь выберет контрагента из предыдущей заполненной строки (который уже с заполненной номенклатурой), и после этого удалит неправильно введенную строку(Контрагента)? Случайно выбрал повторно уже заполненного контрагента и удалил. В этом случае отбор старого контрагента удаляется?
11. Kim1C 178 02.09.21 20:58 Сейчас в теме
(10) Если связь между таблицами построена на контрагенте - то удаление контрагента приведет к удалению данных из второй таблицы. Этот момент надо учитывать программно - например не давать выбирать контрагента, который уже есть в таблице. Либо использовать в качестве ключа связи уникальный ключ - например, число, который при добавлении новой строки примет новое значение и удаление этой строки не приведет к порче ранее добавленных данных
12. user1374678 15.01.23 09:17 Сейчас в теме
Здравствуйте. А как сделать чтоб в печатной форме отображалось первая строка первой ТЧ и все строки прикрепленные из второй ТЧ и т д А то создаю печатную форму показывает все строки первой ТЧ потом все строки второй ТЧ
13. Kim1C 178 15.01.23 13:30 Сейчас в теме
(12) Добрый день. Вам надо алгоритм прописать немного по другому. Вам надо обходить циклом левую ТЧ. И по каждой левой строке нужен еще один вложенный цикл (массив элементов для обхода найти нужно через найтиСтроки для правой ТЧ по ключу строки) - в нем обходите нужные элементы правой строки и выводите их
Оставьте свое сообщение