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

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

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

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

Документ в 1С нередко содержит несколько табличных частей: например, «Товары» и «Серии», «Начисления» и «Распределение по подразделениям», «Материалы» и «Спецификации». Чтобы строки одной части корректно соответствовали строкам другой, их нужно связать — через реквизит-ключ связи, по номенклатуре или по служебному идентификатору. Без такой связи программа не сможет понять, к какой строке товаров относятся серии, и при проведении возникнут ошибки или потеря данных.

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

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

Когда нужна связь табличных частей и как она устроена

Связь табличных частей требуется, когда одна строка «главной» части порождает одну или несколько строк в «подчинённой». Классические примеры из типовых конфигураций: табличная часть «Товары» и «Серии номенклатуры» в документах поступления, «Начисления» и «НДФЛ» в кадровых документах, «Оплата» и «Расшифровка платежа». Во всех этих случаях подчинённая часть хранит детализацию, которая не имеет смысла без родительской строки.

Технически связь реализуется как обычный реквизит в обеих табличных частях. Чаще всего это числовое поле «КлючСвязи» или «КлючСтроки»: при добавлении строки в главную часть ей присваивается очередное значение, и все дочерние строки получают то же значение. Поиск связанных строк выполняется методом НайтиСтроки() с отбором по ключу.

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

Настройка связи в конфигураторе

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

Если подчинённая табличная часть должна отображать только строки, относящиеся к текущей строке главной части, настройте связь на форме. Для элемента формы подчинённой таблицы укажите отбор по ключу: в обработчике ПриАктивизацииСтроки главной таблицы устанавливайте отбор динамически через Элементы.Серии.ОтборСтрок:

&НаКлиенте

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

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

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

Возврат;

КонецЕсли;

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

Элементы.Серии.ОтборСтрок = Отбор;

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

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

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

Программное назначение и заполнение ключей

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

Функция НовыйКлючСвязи(ТабличнаяЧасть)

МаксКлюч = 0;

Для Каждого Строка Из ТабличнаяЧасть Цикл

Если Строка.КлючСвязи > МаксКлюч Тогда

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

КонецЕсли;

КонецЦикла;

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

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

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

Альтернатива числовому ключу — уникальный идентификатор строки. Метод ПолучитьИдентификатор() даёт числовой идентификатор строки, но он существует только в контексте формы и не сохраняется в базе. Для хранимой связи лучше использовать собственный реквизит типа «Строка» с Новый УникальныйИдентификатор() — такой ключ устойчив к перенумерации и копированию документов.

Работа со связанными строками при проведении

В модуле объекта документа, в обработчике ОбработкаПроведения, связанные строки получают отбором. Для каждой строки товаров ищутся её серии, и движения формируются уже с учётом детализации:

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

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

СтрокиСерий = Серии.НайтиСтроки(Отбор);

Если СтрокиСерий.Количество() = 0 Тогда

// движение без серии

Иначе

Для Каждого СтрокаСерии Из СтрокиСерий Цикл

// движение по конкретной серии

КонецЦикла;

КонецЕсли;

КонецЦикла;

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

При большом объёме табличных частей (тысячи строк) многократный вызов НайтиСтроки() внутри цикла работает медленно, так как каждый вызов перебирает всю коллекцию. Оптимизация — один раз выгрузить подчинённую часть в таблицу значений, создать индекс по ключу связи и искать по индексированной таблице, либо сгруппировать данные запросом с соединением по ключу.

Альтернативные способы связи и их ограничения

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

Сравнение способов связи

Числовой ключ связи

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

Строковый GUID

Устойчив к копированию и объединению данных, не требует поиска максимума. Недостаток — более длинное поле и чуть медленнее сравнение.

Связь по комбинации полей

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

Связь по комбинации полей (например, по номенклатуре) — самый хрупкий вариант. Если в табличной части «Товары» две строки с одной номенклатурой, но разными складами, подчинённые строки невозможно однозначно отнести к одной из них. Такой способ допустим только при гарантированной уникальности комбинации, что редко выполняется в реальных документах.

Ещё один вариант — одна табличная часть с иерархией вместо двух связанных. Он подходит, когда дочерних строк немного и они однотипны с родительскими. Но для разнородных данных (товары и серии, начисления и удержания) раздельные табличные части с ключом связи остаются правильным решением.

Типичные ошибки и их последствия

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

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

Особенно коварна вторая ошибка: документ, созданный обработкой загрузки или обменом, выглядит заполненным, но при проведении связанные строки не находятся. Поэтому назначение ключа лучше дублировать на уровне модуля объекта — например, в ПередЗаписью проверять, что у всех строк ключ заполнен, и назначать недостающие.

Ещё одна ловушка — обработка заполнения табличной части целиком. Если обработчик очищает главную часть (Товары.Очистить()), подчинённую нужно очищать тоже, иначе старые серии «прилипнут» к новым строкам с совпавшими ключами.

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

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

Добавьте строку товара и серии к ней
Норма

Серии видны только при активной строке своего товара

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

Серии видны для всех строк или не находятся при проведении

Удалите строку товара
Норма

Связанные серии удаляются вместе с ней

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

Серии остаются в табличной части

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

Движения сформированы по каждой связанной строке, суммы сходятся

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

Ошибки «не найдена строка» или расхождение количеств

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

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

Да. Принцип тот же: ключ добавляется в родительскую часть и во все подчинённые. Цепочки вида «Товары → Серии → Дополнительные характеристики серии» тоже возможны — тогда промежуточная часть хранит два ключа: свой собственный и ключ родителя.

Что делать, если в существующих документах ключи связи не заполнены?

Нужна сервисная обработка: перебрать документы, назначить ключи строкам главной части и попытаться сопоставить подчинённые строки по оставшимся признакам (номенклатура, порядок следования). Если однозначного сопоставления нет, такие документы лучше вывести в список для ручной разборки. Перед запуском обработки обязательно сделайте резервную копию.

Обязательно ли скрывать ключ связи от пользователя?

Не обязательно, но настоятельно рекомендуется. Если поле доступно для редактирования, пользователь может случайно изменить значение и разорвать связь. Стандартный подход — поле существует в данных, но не выводится на форму.

Почему при копировании документа связи сохраняются, а при копировании строки — нет?

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

Как связать табличные части разных документов, а не одного?

Через реквизит типа «ДокументСсылка» плюс ключ строки. Например, в документе-основании строка имеет ключ, а в подчинённом документе хранится ссылка на основание и тот же ключ. Так работает связь заказа и реализации по строкам в типовых конфигурациях.

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

Сама связь почти не влияет — влияет способ поиска связанных строк. Отбор через НайтиСтроки в цикле при больших объёмах заметно тормозит проведение. Решение — запрос с соединением табличных частей по ключу или индексированная таблица значений.

Итог

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

Связь табличных частей строится на общем реквизите-ключе: назначение при добавлении, отбор на форме, поиск связанных строк при проведении и обязательная очистка при удалении. Контроль целостности и сумм до проведения защищает от ошибок, а производительность при больших объёмах обеспечивается запросами и индексами, а не перебором.