Добавление подчиненных справочников в 1С:Предприятие 8.3 — одна из ключевых задач при разработке сложных конфигураций. Без правильной организации иерархии данных система быстро превращается в хаос из несвязанных сущностей. Эта статья поможет разобраться, как грамотно создать подчиненный справочник, избежать типичных ошибок и оптимизировать структуру базы данных.
Подчиненные справочники используются, когда нужно логически связать одну сущность с другой. Например, справочник "Сотрудники" может иметь подчиненный справочник "Контактные данные", а "Номенклатура" — "Характеристики товаров". Главное отличие от обычных справочников — наличие владельца, который определяет контекст подчиненных записей.
В этой инструкции мы рассмотрим два основных способа создания: через конфигуратор в визуальном режиме и программно с использованием встроенного языка. Особое внимание уделим нюансам настройки прав доступа, индексирования и интеграции с другими объектами конфигурации.
Что такое подчиненный справочник и зачем он нужен
Подчиненный справочник в 1С — это объект метаданных, который существует только в контексте другого справочника (владельца). Его записи не могут существовать самостоятельно и автоматически удаляются при удалении владельца. Такая структура позволяет:
- 📌 Организовывать иерархические данные (например, "Клиенты → Адреса доставки")
- 🔗 Обеспечивать целостность данных через автоматическую привязку
- 🛡️ Упрощать управление правами доступа (настраиваются на уровне владельца)
- 🔍 Оптимизировать поиск по связанным сущностям
Классический пример использования — справочник "Контрагенты" с подчиненным справочником "Банковские счета". Каждый контрагент может иметь несколько счетов, но эти счета не имеют смысла без привязки к конкретному контрагенту. Другой распространенный случай — "Номенклатура" и "Серийные номера", где каждый товарный артикул может иметь множество уникальных серийных номеров.
Важно понимать, что подчиненные справочники не поддерживают подчинение другим подчиненным справочникам — это техническое ограничение платформы 1С:Предприятие. Максимальная глубина иерархии — два уровня: основной справочник и его подчиненный.
Способ 1: Создание через конфигуратор (визуальный редактор)
Наиболее простой метод — использование встроенного конфигуратора. Этот способ подходит для начинающих разработчиков и случаев, когда не требуется сложная логика создания справочника. Пошаговая инструкция:
- Откройте конфигуратор вашей базы 1С в режиме редактирования
- В дереве объектов найдите раздел
Справочники - Выделите справочник, который будет владельцем (например, "Контрагенты")
- Нажмите правой кнопкой и выберите
Добавить → Подчиненный справочник - Задайте имя нового справочника (например, "БанковскиеСчетаКонтрагентов")
- Настройте реквизиты (поля) в открывшемся окне свойств
После создания система автоматически сгенерирует:
- 🔧 Форму списка и форму элемента с базовой функциональностью
- 📝 Стандартные команды (
Добавить,Изменить,Удалить) - 🔍 Индексы для ускорения поиска по владельцу
Обратите внимание на свойство Полное имя в настройках справочника — оно формируется как Владелец.ПодчиненныйСправочник. Это важно для программного обращения к объекту.
Указано осмысленное имя (без пробелов и спецсимволов)|
Настроены все необходимые реквизиты|
Проверены права доступа на уровне владельца|
Созданы формы для удобного ввода данных
-->
Способ 2: Программное создание подчиненного справочника
Для опытных разработчиков более гибкий вариант — создание справочника через встроенный язык. Этот метод позволяет:
- 🛠️ Динамически создавать справочники в зависимости от условий
- 🔄 Автоматизировать развертывание на нескольких базах
- 📦 Включать создание в скрипты миграции и обновления
Пример кода для создания подчиненного справочника "Контакты" для справочника "Контрагенты":
// Получаем ссылку на метаданные владельца
Владелец = Метаданные.Справочники.Контрагенты;
// Создаем новый подчиненный справочник
НовыйСправочник = Владелец.ПодчиненныеСправочники.Добавить();
НовыйСправочник.Имя = "КонтактыКонтрагентов";
НовыйСправочник.Синоним = "Контакты";
НовыйСправочник.Комментарий = "Контактные лица и телефоны контрагентов";
// Добавляем реквизиты
РеквизитТелефон = НовыйСправочник.Реквизиты.Добавить();
РеквизитТелефон.Имя = "Телефон";
РеквизитТелефон.Тип = Новый Тип("Строка", Новый КвалификаторыСтроки(20));
РеквизитEmail = НовыйСправочник.Реквизиты.Добавить();
РеквизитEmail.Имя = "Email";
РеквизитEmail.Тип = Новый Тип("Строка", Новый КвалификаторыСтроки(50));
// Сохраняем изменения
Метаданные.Записать();
После выполнения этого кода в конфигурации появится новый подчиненный справочник. Для его отображения в интерфейсе потребуется дополнительно:
- Создать формы ввода и списка
- Настроить команды в командном интерфейсе
- Добавить права доступа в ролях
Всегда проверяйте существование справочника перед созданием через код, чтобы избежать ошибок при повторном выполнении скрипта. Используйте конструкцию Если Не Метаданные.Справочники.Владелец.ПодчиненныеСправочники.Найти("ИмяСправочника") Тогда...
Настройка свойств подчиненного справочника
Корректная настройка свойств определяет удобство работы и производительность системы. Основные параметры, на которые стоит обратить внимание:
| Свойство | Рекомендуемое значение | Пояснение |
|---|---|---|
Иерархический |
Нет | Подчиненные справочники редко требуют иерархии |
ПроверкаУникальности |
Да | Предотвращает дублирование записей |
ИндексироватьПоИмени |
Да | Ускоряет поиск по наименованию |
ПолноеИмяАвто |
Да | Автоматически формирует полное имя вида "Владелец.Элемент" |
Подсистема |
Соответствующая функциональная область | Определяет видимость в интерфейсе |
Особое внимание уделите свойству ФормаЭлемента и ФормаСписка. Для подчиненных справочников часто требуется:
- 🎨 Кастомизация формы с отображением данных владельца
- 🔄 Автоматическое заполнение некоторых полей на основе владельца
- 🔒 Ограничение прав редактирования в зависимости от статуса владельца
Пример настройки формы элемента для отображения данных владельца:
// В модуле формы элемента подчиненного справочника
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
Владелец = Объект.Владелец.ПолучитьОбъект();
ЭлементыФормы.ПолеВладельца.Значение = Владелец.Наименование;
КонецПроцедуры
Как проверить корректность индексов подчиненного справочника?
Для проверки индексов выполните запрос через консоль запросов:
ВЫБРАТЬ ИНДЕКСЫИЗМЕРЕНИЙ("Справочник.Владелец.ПодчиненныйСправочник") КАК Индексы
Если в результате не отображается индекс по полю владельца (Ссылка.Владелец), его нужно добавить вручную через конфигуратор в разделе "Индексы поиска".
Типичные ошибки и как их избежать
При работе с подчиненными справочниками разработчики часто сталкиваются с типичными проблемами, которые ведут к ошибкам выполнения или неоптимальной работе системы. Рассмотрим наиболее распространенные случаи:
⚠️ Внимание: При удалении владельца все подчиненные записи удаляются без возможности восстановления. Всегда реализуйте механизм архивации критически важных данных перед массовыми операциями удаления.
Ошибка 1: Неправильная привязка владельца
Симптомы: при попытке создать запись в подчиненном справочнике система выдает ошибку "Не указан владелец" или "Некорректная ссылка".
Причина: в коде создания элемента не передается ссылка на владельца.
Решение: всегда явно указывайте владельца при создании:
НовыйЭлемент = Справочники.Контрагенты.БанковскиеСчетаКонтрагентов.СоздатьЭлемент();
НовыйЭлемент.Владелец = ТекущийКонтрагент; // Явная привязка
НовыйЭлемент.Записать();
Ошибка 2: Проблемы с правами доступа
Симптомы: пользователи не видят подчиненный справочник или не могут редактировать записи, несмотря на наличие прав на владельца.
Причина: права на подчиненный справочник настраиваются отдельно от прав на владельца.
Решение: в настройках ролей явно укажите права на:
- 🔓 Чтение подчиненного справочника
- ✏️ Изменение (если требуется)
- 🗑️ Удаление (с осторожностью)
Ошибка 3: Некорректная работа отчетов
Симптомы: в отчетах не отображаются данные из подчиненных справочников или появляются дубли.
Причина: неправильное построение запроса без учета связи владельца.
Решение: используйте конструкцию ВЫБРАТЬ РАЗРЕШЕННЫЕ с явным указанием связи:
ВЫБРАТЬ РАЗРЕШЕННЫЕ
Контрагенты.Ссылка КАК Контрагент,
КонтрагентыБанковскиеСчета.НомерСчета КАК НомерСчета
ИЗ
Справочник.Контрагенты КАК Контрагенты
ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Контрагенты.БанковскиеСчета КАК КонтрагентыБанковскиеСчета
ПО Контрагенты.Ссылка = КонтрагентыБанковскиеСчета.Ссылка.Владелец
Оптимизация производительности
Подчиненные справочники могут существенно влиять на производительность системы, особенно при большом количестве записей. Следующие рекомендации помогут оптимизировать работу:
1. Индексирование полей
Создайте индексы для полей, по которым часто выполняется поиск. Для подчиненных справочников обязательно индексируйте:
- 🔑 Поле
Ссылка.Владелец(создается автоматически) - 🔍 Поля, используемые в условиях отборов
- 📌 Поля, по которым выполняется сортировка
2. Разделение больших справочников
Если подчиненный справочник содержит более 100 000 записей на одного владельца, рассмотрите возможность:
- 🗃️ Архивирования старых данных
- 🔄 Разделения на несколько справочников по функциональному признаку
- 📊 Использования регистров сведений для хранения исторических данных
3. Оптимизация форм
Для ускорения работы интерфейса:
- 🖼️ Ограничивайте количество отображаемых полей в формах списка
- 🔄 Используйте отложенную загрузку данных для второстепенных реквизитов
- 📱 Настраивайте динамические списки с ограничением по 100-200 записей
4. Кэширование часто используемых данных
Для данных, которые редко изменяются но часто запрашиваются:
// Пример кэширования банковских счетов контрагента
Процедура ПолучитьСчетаКонтрагента(Контрагент, Кэш = Неопределено)
Если Кэш = Неопределено Тогда
Кэш = Новый Структура();
КонецЕсли;
Если Не Кэш.Свойство(Контрагент.УникальныйИдентификатор()) Тогда
Запрос = Новый Запрос();
Запрос.Текст =
"ВЫБРАТЬ
| БанковскиеСчетаКонтрагентов.Ссылка КАК Ссылка,
| БанковскиеСчетаКонтрагентов.НомерСчета КАК НомерСчета
|ИЗ
| Справочник.Контрагенты.БанковскиеСчета КАК БанковскиеСчетаКонтрагентов
|ГДЕ
| БанковскиеСчетаКонтрагентов.Ссылка.Владелец = &Владелец";
Запрос.УстановитьПараметр("Владелец", Контрагент.Ссылка);
Кэш.Вставить(Контрагент.УникальныйИдентификатор(), Запрос.Выполнить().Выгрузить());
КонецЕсли;
Возврат Кэш[Контрагент.УникальныйИдентификатор()];
КонецПроцедуры
Для подчиненных справочников с более чем 50 000 записей на одного владельца рассмотрите возможность использования регистра сведений вместо справочника — это может дать прирост производительности в 3-5 раз при выборках.
Интеграция с другими объектами конфигурации
Подчиненные справочники редко используются изолированно — обычно они интегрируются с другими объектами 1С. Рассмотрим основные сценарии интеграции:
1. Связь с документами
Типичный случай — привязка данных из подчиненного справочника к документам. Например, в документе "Заказ покупателя" может указываться:
- 📦 Адрес доставки (из подчиненного справочника "Адреса" контрагента)
- 💳 Банковский счет для оплаты (из подчиненного справочника "БанковскиеСчета")
- 📞 Контактное лицо (из подчиненного справочника "Контакты")
Пример заполнения реквизита документа:
Процедура АдресДоставкиПриИзменении(Элемент)
Если ЗначениеЗаполнено(Объект.Контрагент) Тогда
Запрос = Новый Запрос();
Запрос.Текст =
"ВЫБРАТЬ ПЕРВЫЕ 1
| АдресаКонтрагентов.Ссылка КАК Ссылка
|ИЗ
| Справочник.Контрагенты.Адреса КАК АдресаКонтрагентов
|ГДЕ
| АдресаКонтрагентов.Ссылка.Владелец = &Владелец
| И АдресаКонтрагентов.Основной = ИСТИНА";
Запрос.УстановитьПараметр("Владелец", Объект.Контрагент.Ссылка);
Результат = Запрос.Выполнить();
Если Результат.Количество() > 0 Тогда
Объект.АдресДоставки = Результат.Получить(0).Ссылка;
КонецЕсли;
КонецЕсли;
КонецПроцедуры
2. Использование в отчетах
При построении отчетов данные из подчиненных справочников часто нужно агрегировать. Например, отчет "Анализ продаж по регионам" может использовать адреса контрагентов из подчиненного справочника.
Пример запроса для отчета:
ВЫБРАТЬ
Регионы.Наименование КАК Регион,
СУММА(Документ.РеализацияТоваровУслуг.СуммаДокумента) КАК ОбщаяСумма
ИЗ
Документ.РеализацияТоваровУслуг КАК РеализацияТоваровУслуг
ВНУТРЕННЕЕ СОЕДИНЕНИЕ Справочник.Контрагенты.Адреса КАК АдресаКонтрагентов
ПО РеализацияТоваровУслуг.Контрагент = АдресаКонтрагентов.Ссылка.Владелец
ВНУТРЕННЕЕ СОЕДИНЕНИЕ Справочник.Регионы КАК Регионы
ПО АдресаКонтрагентов.Регион = Регионы.Ссылка
ГДЕ
РеализацияТоваровУслуг.Дата МЕЖДУ &НачалоПериода И &КонецПериода
СГРУППИРОВАТЬ ПО
Регионы.Наименование
3. Обмен данными
При настройке обмена данными (например, через Универсальный формат обмена или EnterpriseData) подчиненные справочники требуют особого внимания:
- 🔄 Настройте правильную последовательность выгрузки (сначала владелец, потом подчиненные записи)
- 🔗 Убедитесь в корректной привязке ссылок при загрузке
- 📋 Проверьте обработку случаев, когда владелец не найден в целевой базе
Особенности обмена подчиненными справочниками в распределенных базах
В распределенных информационных базах подчиненные справочники синхронизируются только вместе с владельцем. Если владелец не помечен для обмена, его подчиненные записи также не будут передаваться. Для принудительной синхронизации используйте метод ПометитьОбменом() для владельца.
FAQ: Ответы на частые вопросы
Можно ли создать подчиненный справочник для подчиненного справочника?
Нет, платформа 1С:Предприятие не поддерживает многоуровневое подчинение справочников. Максимальная глубина иерархии — два уровня: основной справочник и его непосредственный подчиненный. Для реализации более сложных структур используйте:
- 🔗 Связь через реквизиты типа "СправочникСсылка"
- 🗃️ Регистры сведений с измерением "Владелец"
- 📊 Дополнительные объекты конфигурации с программной привязкой
Как перенести данные из обычного справочника в подчиненный?
Для переноса данных:
- Создайте новый подчиненный справочник
- Напишите обработку, которая:
- Проверьте целостность данных после переноса
- Обновите все ссылки в документах и отчетах
// Пример кода для переноса
Для Каждого Элемент Из Справочники.СтарыйСправочник Выбрать() Цикл
НовыйЭлемент = Справочники.Владелец.ПодчиненныйСправочник.СоздатьЭлемент();
НовыйЭлемент.Владелец = НайтиВладельца(Элемент.РеквизитСвязи); // Ваша функция поиска владельца
НовыйЭлемент.Наименование = Элемент.Наименование;
// Перенос других реквизитов
НовыйЭлемент.Записать();
КонецЦикла;
Важно: перед массовым переносом сделайте резервную копию базы!
Почему при удалении владельца не удаляются подчиненные записи?
Это может происходить по нескольким причинам:
- 🔒 На подчиненный справочник установлены права, запрещающие удаление
- 📋 В конфигурации отключена опция "Удалять подчиненные объекты при удалении владельца"
- 🔄 Удаление выполняется через прямой запрос к СУБД, минуя механизмы 1С
- 🛡️ Есть обработчики событий
ПередУдалениемилиПриУдалении, прерывающие операцию
Для диагностики включите Режим отладки и проверьте журнал регистрации.
Как ограничить количество подчиненных записей для одного владельца?
Ограничение можно реализовать:
- Через обработчик события
ПередЗаписью: - Через настройку прав доступа (ограничить создание новых записей)
- Через бизнес-процессы с проверкой условий
Процедура ПодчиненныйСправочникПередЗаписью(Отказ, РежимЗаписи, РежимПроводки)
Если РежимЗаписи = РежимЗаписиОбъекта.Вставка Тогда
Запрос = Новый Запрос();
Запрос.Текст =
"ВЫБРАТЬ
| КОЛИЧЕСТВО(*) КАК Количество
|ИЗ
| Справочник.Владелец.ПодчиненныйСправочник КАК ПодчиненныйСправочник
|ГДЕ
| ПодчиненныйСправочник.Ссылка.Владелец = &Владелец";
Запрос.УстановитьПараметр("Владелец", Объект.Владелец);
Если Запрос.Выполнить().Выгрузить()[0].Количество >= 100 Тогда
Отказ = Истина;
Сообщить("Превышено максимальное количество подчиненных записей (100)!");
КонецЕсли;
КонецЕсли;
КонецПроцедуры
Можно ли сделать подчиненный справочник независимым?
Технически преобразовать подчиненный справочник в независимый нельзя — это требует:
- Создания нового обычного справочника
- Переноса всех данных с сохранением ссылочной целостности
- Обновления всех ссылок в документах и отчетах
- Удаления старого подчиненного справочника
Эту операцию лучше выполнять в несколько этапов с тщательным тестированием на каждой итерации. Для крупных баз данных рекомендуется использовать Конвертацию данных.