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