1C-CodeОсновы 1С → Справочники: списки того, что существует

Справочники: списки того, что существует

Первый объект, который заводит любой разработчик. Ссылка и объект, реквизиты и предопределённые элементы, иерархия и владелец.

Глава 17 из 36 · чтение примерно 26 минут

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

С него начинают почти всякую задачу: «нам нужно учитывать договоры» — значит, скорее всего, нужен справочник.

Что у справочника есть с рождения

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

Код — короткий идентификатор, обычно нумеруется сам. Наименование — то, что человек видит в списке. ПометкаУдаления — признак «помечен на удаление». Ссылка — то, чем на элемент ссылаются отовсюду.

Длину кода и наименования задают в свойствах. Ноль в длине кода означает «кода нет вовсе» — так делают, когда нумерация не нужна.

Ссылка и объект — разные вещи

Это различие путают чаще всего, и из него растёт половина ошибок первого месяца.

Ссылка — это указание «вот тот элемент». Она лёгкая, её кладут в реквизиты документов, передают, сравнивают. Читать через неё можно: Товар.Артикул.

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

Попытка написать Товар.Наименование = "Новое" прямо по ссылке — самая частая ошибка новичка. Ссылка на запись не рассчитана.

Прочитать и изменить — разный код

Название = Товар.Наименование;
Объект = Товар.ПолучитьОбъект();
Объект.Наименование = "Новое";
Объект.Записать();
ЧастьЧто означает
Товар.Наименованиечтение по ссылке — так можно и нужно
ПолучитьОбъект()берём элемент для изменения; это поход в базу
Объект.Наименование =меняем поле объекта, а не ссылки
Записать()без него изменения останутся только в памяти

Как найти элемент

Три способа, и выбор между ними — вопрос не вкуса, а скорости.

НайтиПоКоду и НайтиПоНаименованию — просты и привычны. Возвращают пустую ссылку, если не нашли: проверять надо через ЗначениеЗаполнено().

НайтиПоРеквизиту — по любому своему полю, например по артикулу или ИНН.

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

На чём спотыкаются

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

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

Ставят НайтиПоНаименованию в цикл. Классическая причина «обработка идёт сорок минут». Один запрос вместо тысячи поисков.

Предопределённые элементы

Иногда элемент нужен коду по имени: «основной склад», «наша организация», «ставка НДС 20%». Такие заводят предопределёнными — прямо в конфигураторе, и они попадают в базу при первом запуске.

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

Ловушка предопределённых

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

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

Иерархия и владелец

Два способа связать элементы, и их постоянно путают.

Иерархия — папки внутри того же справочника. Номенклатура лежит в группах «Инструмент», «Крепёж». Включается свойством «Иерархический». Бывает двух видов: «групп и элементов» (папка не товар) и «элементов» (любой элемент может быть родителем).

Владелец — связь с другим справочником. Договоры принадлежат контрагенту: у справочника «ДоговорыКонтрагентов» владелец — «Контрагенты». Элемент без владельца там не заводится.

Простое правило: «внутри себя» — иерархия, «принадлежит чужому» — владелец.

Группы: элемент, который не элемент

У иерархического справочника строки бывают двух сортов, и лежат они в одной таблице. Отличает их флаг ЭтоГруппа.

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

Поэтому в запросах по иерархическим справочникам почти всегда стоит ГДЕ НЕ ЭтоГруппа. В демо-базе групп две — а в рабочей их бывает больше, чем элементов.

Два вида иерархии

ВидКто кому подчинёнПример
Иерархия групп и элементовэлемент лежит в группе, группа — в группеНоменклатура: папка «Крепёж» и в ней гвозди
Иерархия элементовэлемент подчинён элементу, групп нетПодразделения: отдел внутри отдела
Подчинение (владелец)справочник подчинён ДРУГОМУ справочникуДоговоры подчинены Контрагентам

Владелец — это не родитель

Два похожих поля, и путают их постоянно.

Родитель — это иерархия внутри того же справочника: группа, в которой лежит элемент.

Владелец — это другой справочник: договор принадлежит контрагенту, и без контрагента договора не существует.

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

Обход иерархии в запросе

Вопрос «все товары этой группы, включая вложенные» решается не рекурсией, а одним словом в условии.

ГДЕ Ссылка В ИЕРАРХИИ (&Группа) — и платформа сама спустится по всем уровням. Обходить подгруппы кодом, как это делают по незнанию, и дольше, и ошибётся на глубоких деревьях.

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

Реквизиты и табличные части справочника

У справочника есть свои реквизиты — и с ними связана самая дорогая ошибка новичка в работе с данными.

Ссылка.Реквизит — это обращение к базе. Одно на каждый реквизит, каждый раз. В цикле по тысяче элементов это тысяча запросов, и выглядит она как невинная точка в коде.

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

Упражнение 2. Только элементы, без групп

Напишите ТолькоТовары(): сколько в справочнике Номенклатура строк, которые не являются группами. Всего строк 25, групп из них две.

Решается в тренажёре: код запускается и проверяется сразу.

Пометка удаления и настоящее удаление

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

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

Настоящее удаление делает отдельная обработка — «Удаление помеченных объектов». Она сначала ищет ссылки и удаляет только то, на что никто не ссылается.

Из этого следует практическое: в запросах почти всегда нужно ГДЕ НЕ ПометкаУдаления. Иначе в отчёт попадут вычеркнутые элементы, и это заметит бухгалтер, а не вы.

Битая ссылка: как выглядит и откуда берётся

Если удалить объект в обход проверок — например, прямым удалением из кода, — ссылки на него останутся. Выглядит это в интерфейсе как «<Объект не найден> (12:8a3f…)».

Чинится только поиском и заменой ссылок, а по-хорошему не допускается вовсе: Объект.Удалить() в коде применяют осознанно и редко, а обычный путь — УстановитьПометкуУдаления(Истина).

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

Упражнение 1. Найти и прочитать

Функция АртикулТовара(Наименование) должна найти товар в справочнике Номенклатура по наименованию и вернуть его артикул. Если товара нет — вернуть строку "не найден".

Решается в тренажёре: код запускается и проверяется сразу.

Короткий свод

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

Как закрепить

Читать про код и писать код — разные умения. В тренажёре к этой главе идут упражнения: вы пишете решение, оно запускается на настоящем интерпретаторе 1С и проверяется сразу, без установки платформы.

Открыть эту главу в тренажёре

Конфигуратор и дерево метаданных
Документы и проведение: что случилось