В процессе разработки интерфейсов на платформе 1С часто возникает задача, когда действия в одной таблице должны мгновенно отражаться в другой. Например, при выборе категории в основной таблице «Нарушения», соответствующая категория должна автоматически проставляться или фильтроваться в связанной таблице «Аудируемые». В этой статье мы разберем, как правильно организовать связь между двумя таблицами, избегая типичных ошибок начинающих разработчиков.
Рассмотрим ситуацию, с которой сталкиваются многие: попытка напрямую присвоить значение из одной таблицы в другую. Часто новички пишут код, подобный этому:
Процедура НарушенияПриАктивизацииСтроки(Элемент)
ЭлементыФормы.Аудируемые.Категория = ЭлементыФормы.КатегорияРеакцияРаботника.Категория;
КонецПроцедуры
Проанализируем этот фрагмент. Проблема здесь в том, что ЭлементыФормы.Аудируемые — это сам элемент управления (табличное поле), а не конкретная строка данных. У элемента управления нет свойства Категория. Чтобы обратиться к данным, нужно использовать свойство ТекущиеДанные. Однако даже правильное обращение к ТекущиеДанные требует понимания того, в какой именно строке второй таблицы мы хотим изменить значение.
Наиболее надежный метод связать две таблицы — это создание так называемого ключа связи. Это скрытая колонка (например, с именем КлючСвязи), которая содержит уникальный идентификатор, общий для связанных строк в обеих таблицах.
Разберем по шагам, как это реализовать:
КлючСвязи с типом Число или УникальныйИдентификатор.Теперь рассмотрим код, который будет синхронизировать данные при изменении категории в первой таблице:
Процедура КатегорияРеакцияРаботникаПриИзменении(Элемент)
// 1. Получаем текущие данные первой таблицы (откуда берем данные)
ТекущаяСтрока1 = ЭлементыФормы.КатегорияРеакцияРаботника.ТекущиеДанные;
Если ТекущаяСтрока1 = Неопределено Тогда
Возврат;
КонецЕсли;
// 2. Ищем связанную строку во второй таблице по Ключу Связи
// Предположим, вторая таблица называется "Аудируемые"
ПараметрыОтбора = Новый Структура("КлючСвязи", ТекущаяСтрока1.КлючСвязи);
НайденныеСтроки = Объект.Аудируемые.НайтиСтроки(ПараметрыОтбора);
// 3. Обновляем данные во всех найденных строках
Для Каждого СтрокаТЧ2 Из НайденныеСтроки Цикл
СтрокаТЧ2.Категория = ТекущаяСтрока1.Категория;
КонецЦикла;
КонецПроцедуры
Если нам не нужно искать строки во всей таблице, а требуется лишь передать значение в выделенную строку второй таблицы, мы должны четко разделять переменные для каждой таблицы. Выясним причину ошибки, когда разработчики используют одну и ту же переменную ТД для разных объектов.
Посмотрим на правильный пример работы с двумя таблицами одновременно:
Процедура СинхронизироватьКатегории()
// Получаем данные текущей строки из первой таблицы
ДанныеПервойТаблицы = ЭлементыФормы.Таблица1.ТекущиеДанные;
// Получаем данные текущей строки из второй таблицы
ДанныеВторойТаблицы = ЭлементыФормы.Таблица2.ТекущиеДанные;
// Обязательно проверяем на Неопределено, чтобы избежать критической ошибки
Если ДанныеПервойТаблицы <> Неопределено И ДанныеВторойТаблицы <> Неопределено Тогда
ДанныеВторойТаблицы.Категория = ДанныеПервойТаблицы.Категория;
КонецЕсли;
КонецПроцедуры
Важно помнить, что в Обычных формах (1С 8.2 и режим совместимости 8.3) после программного изменения данных в таблице может потребоваться визуальное обновление элемента формы. Для этого используйте метод ЭлементыФормы.ИмяТаблицы.Обновить().
В современных Управляемых формах принцип работы меняется: мы работаем не с элементами формы, а непосредственно с данными объекта. Разберем ситуацию синхронизации данных через событие ПриИзменении на клиенте:
&НаКлиенте
Процедура СписокНарушенийКатегорияПриИзменении(Элемент)
// Получаем текущую строку через идентификатор
ИдентификаторСтроки = Элементы.СписокНарушений.ТекущаяСтрока;
ДанныеСтроки = Объект.СписокНарушений.НайтиПоИдентификатору(ИдентификаторСтроки);
Если ДанныеСтроки <> Неопределено Тогда
// Вызываем серверную процедуру для поиска и обновления второй таблицы
ОбновитьКатегорииВоВторойТаблице(ДанныеСтроки.КлючСвязи, ДанныеСтроки.Категория);
КонецЕсли;
КонецПроцедуры
&НаСервере
Процедура ОбновитьКатегорииВоВторойТаблице(Ключ, НоваяКатегория)
ПараметрыПоиска = Новый Структура("КлючСвязи", Ключ);
СтрокиДляОбновления = Объект.Аудируемые.НайтиСтроки(ПараметрыПоиска);
Для Каждого ТекущаяСтрока Из СтрокиДляОбновления Цикл
ТекущаяСтрока.Категория = НоваяКатегория;
КонецЦикла;
КонецПроцедуры
Проанализируем основные причины, по которым механизм связи может не работать:
ТекущиеДанные.Категория вызовет аварийное завершение программы.ТД = ЭлементыФормы.Таблица1.ТекущиеДанные; ТД = ЭлементыФормы.Таблица2.ТекущиеДанные; ТД.Поле = ТД.Поле; абсолютно бесполезен, так как во второй строке переменная ТД перезаписывается и теряет связь с первой таблицей.ПриАктивизацииСтроки происходит очень часто (при каждом клике или перемещении стрелками). Если в нем прописана тяжелая логика поиска по тысячам строк, интерфейс будет "тормозить". Для изменения данных лучше использовать ПриИзменении конкретной колонки.Если ваша задача — не физическое копирование данных, а просто фильтрация (показать во второй таблице только те строки, которые относятся к категории из первой), рассмотрите возможность использования Связи по параметру. В свойствах динамического списка или табличной части на форме можно указать "Отбор", который будет автоматически обновляться при смене текущей строки в главной таблице. Это избавляет от необходимости писать программный код вовсе.
Резюмируем: Для успешной связи двух таблиц всегда четко разделяйте объекты данных каждой таблицы, используйте уникальные ключи (идентификаторы) для поиска соответствий и никогда не забывайте проверять наличие выделенной строки перед обращением к её свойствам.