К статье
Практический материал

Разработка и Конфигурация · 11 мин

Как связать две табличные части в 1С

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

Связь двух табличных частей — типичная задача при разработке документов в 1С: например, в одной таблице хранятся товары, а во второй — серии или скидки по этим товарам. Платформа предлагает несколько механизмов: стандартный «Ключ связи», программную связь по общему реквизиту и связывание через запросы при чтении данных.

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

Ниже разобраны основные подходы с примерами кода, условия их применения, типичные ошибки и способы проверить, что связь работает корректно.

Когда вообще нужна связь между табличными частями

Связь требуется, когда одна строка основной таблицы «владеет» несколькими строками другой. Классические примеры: товары и их серийные номера, номенклатура и распределённые скидки, этапы работ и исполнители по каждому этапу. Без явной связи платформа не знает, какая строка подчинённой таблицы к чему относится.

Признак того, что связь нужна: при удалении строки основной таблицы должны удаляться связанные строки второй, при копировании документа связи должны сохраниться, а в проведении данные двух таблиц объединяются построчно. Если хотя бы одно условие выполняется — проектируйте связь осознанно, а не «по номеру строки».

Связывать строки по совпадающему номеру строки — распространённая ошибка. При сортировке, удалении или программном изменении порядка строк номера «поплывут», и данные разойдутся. Для связи нужен отдельный реквизит-ключ.

Способ 1. Связь через реквизит «Ключ связи»

Это стандартный и наиболее надёжный способ, который применяется в типовых конфигурациях. В обеих табличных частях создаётся реквизит «КлючСвязи» типа «Число» (длина 5–10 обычно достаточно). В основной таблице ключ уникален в пределах документа, в подчинённой — повторяется для всех строк, относящихся к одной строке основной.

Заполнение ключа удобно делать в обработчике «ПриНачалеРедактирования» основной таблицы на форме или программно при добавлении строки:

&НаКлиенте

Процедура ТоварыПриНачалеРедактирования(Элемент, НоваяСтрока, Копирование)

Если НоваяСтрока И Не Копирование Тогда

Элемент.ТекущиеДанные.КлючСвязи = НовыйКлючСвязи();

КонецЕсли;

КонецПроцедуры

&НаСервере

Функция НовыйКлючСвязи()

МаксКлюч = 0;

Для Каждого Строка Из Объект.Товары Цикл

МаксКлюч = Макс(МаксКлюч, Строка.КлючСвязи);

КонецЦикла;

Возврат МаксКлюч + 1;

КонецФункции

Строки подчинённой таблицы добавляются с тем же значением ключа, что и у выбранной строки основной. При удалении строки основной таблицы в обработчике «ПередУдалением» нужно найти и удалить все строки подчинённой с этим ключом — иначе в документе останутся «осиротевшие» строки.

Порядок настройки связи по ключу
  1. 1
    Добавьте реквизит «КлючСвязи» (Число) в обе табличные части
  2. 2
    Заполняйте ключ уникальным значением при создании строки основной таблицы
  3. 3
    При добавлении строки подчинённой таблицы копируйте ключ из текущей строки основной
  4. 4
    В обработчике ПередУдалением основной таблицы удаляйте связанные строки подчинённой
  5. 5
    Проверьте копирование документа: ключи должны копироваться вместе со строками

Способ 2. Отбор строк на форме через связь параметров выбора

Если связь нужна только для удобства работы пользователя на форме — чтобы в подчинённой таблице показывались строки только по текущей строке основной — достаточно настроить отбор. Для динамических списков и таблиц формы это делается через «СвязиПараметровВыбора» или программно через элемент отбора.

Программный вариант универсальнее. В обработчике «ПриАктивизацииСтроки» основной таблицы устанавливается отбор на подчинённую:

&НаКлиенте

Процедура ТоварыПриАктивизацииСтроки(Элемент)

ТекущиеДанные = Элементы.Товары.ТекущиеДанные;

Если ТекущиеДанные = Неопределено Тогда

Возврат;

КонецЕсли;

Отбор = Новый Структура("КлючСвязи", ТекущиеДанные.КлючСвязи);

Элементы.Серии.ОтборСтрок = Новый ФиксированнаяСтруктура(Отбор);

КонецПроцедуры

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

Способ 3. Объединение табличных частей в запросе

Когда связанные данные нужны в проведении, печатной форме или отчёте, табличные части соединяют запросом по ключу связи. Это безопаснее, чем перебор вложенными циклами: запрос выполняется на сервере СУБД и работает быстрее на больших документах.

Запрос = Новый Запрос;

Запрос.Текст =

"ВЫБРАТЬ

| Товары.Номенклатура КАК Номенклатура,

| Товары.Количество КАК Количество,

| Серии.Серия КАК Серия

|ИЗ

| Документ.РеализацияТоваров.Товары КАК Товары

| ЛЕВОЕ СОЕДИНЕНИЕ Документ.РеализацияТоваров.Серии КАК Серии

| ПО Товары.КлючСвязи = Серии.КлючСвязи

|ГДЕ

| Товары.Ссылка = &Ссылка";

Запрос.УстановитьПараметр("Ссылка", ДокументСсылка);

Обратите внимание на левое соединение: если для какой-то строки основной таблицы нет строк в подчинённой, она всё равно попадёт в результат со значением NULL в полях второй таблицы. Внутреннее соединение такие строки отбросит, что часто становится скрытой причиной «потери» товаров в движениях.

Сравнение подходов и критерии выбора

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

Сравнение вариантов связи

Реквизит «Ключ связи»

Подходит для хранимой связи, нужной в проведении и печати. Требует доработки конфигурации и контроля целостности при удалении строк.

Отбор на форме (ОтборСтрок)

Подходит только для удобства интерфейса. Не решает задачу хранения связи и не защищает от рассинхронизации данных.

Соединение в запросе

Подходит для чтения связанных данных в проведении, отчётах и печати. Работает только при наличии общего реквизита-ключа в обеих таблицах.

Связь по номеру строки

Не рекомендуется: ломается при сортировке, удалении и программном изменении порядка строк.

Если конфигурация на поддержке и менять состав реквизитов нельзя, иногда приходится связывать таблицы по совокупности существующих полей (например, номенклатура + характеристика). Это допустимо как временная мера, но такая связь неоднозначна: две одинаковые строки товаров различить уже не получится.

Маршрут решения

Как выбрать способ

Связь нужна в проведении, печати или обменахДобавьте реквизит «КлючСвязи» в обе табличные части
Нужно только показать пользователю строки по текущей позицииИспользуйте ОтборСтрок в обработчике ПриАктивизацииСтроки
Данные нужны в отчёте или движениях документаСоедините табличные части в запросе по ключу
Конфигурация на поддержке без возможности измененийСвязывайте по существующим полям, но зафиксируйте ограничение на дубли строк

Типичные ошибки и как их избежать

Большинство проблем со связанными табличными частями возникает не на этапе создания связи, а при последующих операциях с документом: удалении строк, копировании, загрузке из внешних источников.

Типичные ошибки
01
Связь по номеру строки — рвётся при сортировке и удалении строк
02
Не удаляются строки подчинённой таблицы при удалении строки основной — в документе копятся «осиротевшие» данные
03
При копировании строки основной таблицы ключ не перевыставляется — две строки получают один ключ, и связь становится неоднозначной
04
Внутреннее соединение в запросе вместо левого — строки без пары теряются в движениях
05
Заполнение ключа только на клиенте — при программном создании документа ключи остаются пустыми

Отдельно стоит сказать про программное создание документов. Обработчики формы не срабатывают, когда документ создаётся из кода, обмена или загрузки. Поэтому логику заполнения ключа правильнее дублировать в модуле объекта (например, в «ОбработкеЗаполнения») или выносить в общий модуль, доступный и форме, и объекту.

Проверка результата

После внедрения связи проверьте её на жизненном цикле документа, а не только на добавлении строк. Минимальный набор проверок: создание, добавление и удаление строк, копирование документа, проведение, печать и программная загрузка.

Контрольные точки

Как проверить результат

Удаление строки основной таблицы
Норма

Связанные строки подчинённой таблицы удаляются автоматически

Тревожный признак

В подчинённой таблице остаются строки с ключом, которого нет в основной

Копирование документа
Норма

Ключи скопировались вместе со строками, связи сохранились

Тревожный признак

Ключи обнулились или продублировались между разными строками

Проведение документа
Норма

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

Тревожный признак

Часть строк потерялась из-за внутреннего соединения или пустых ключей

Программное создание документа
Норма

Ключи заполняются и без открытия формы

Тревожный признак

Документы из обмена или загрузки имеют пустые ключи

Полезно добавить контроль в «ОбработкеПроверкиЗаполнения» объекта: проверять, что у каждой строки подчинённой таблицы есть строка с таким же ключом в основной. Это защитит базу от неконсистентных данных при любых способах ввода документа.

Для поиска уже существующих проблем в базе используйте запрос с группировкой: строки подчинённой таблицы, сгруппированные по ключу, у которых ключ отсутствует в основной таблице, — это «осиротевшие» записи, требующие исправления.

Итог

Что важно запомнить

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

Частые вопросы

Можно ли связать табличные части без изменения конфигурации?

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

Какой тип данных выбрать для ключа связи?

Обычно используют «Число» длиной 5–10 — этого хватает для любого реального документа. Строковый ключ (например, уникальный идентификатор) тоже допустим, но занимает больше места и медленнее сравнивается в запросах.

Почему при копировании документа связь ломается?

Чаще всего потому, что ключ генерируется только в обработчике «ПриНачалеРедактирования» формы, а при копировании строки этот обработчик не вызывается или ветка «Копирование» явно пропускает заполнение. Проверьте, что скопированные строки сохраняют свои ключи и они не конфликтуют с существующими.

Как связать табличную часть документа с табличной частью другого объекта?

Напрямую — никак, платформа не поддерживает ссылки на строки табличных частей. Используйте составной ключ: ссылка на документ-владелец плюс номер строки или ключ связи. Такая связь поддерживается только программно — через запросы и обработчики.

Что делать, если в подчинённой таблице несколько строк с одним ключом, а нужна одна?

Это признак того, что связь типа «один ко многим» используется там, где нужна «один к одному». Либо добавьте контроль уникальности ключа в подчинённой таблице в «ОбработкеПроверкиЗаполнения», либо перенесите поля в основную таблицу — отдельная табличная часть для связи «один к одному» обычно не нужна.

Влияет ли связь табличных частей на проведение документа?

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