Справочники
Справочник — это списки, которые живут в базе месяцами: товары, клиенты, склады, сотрудники.
Справочник — прикладной объект 1С для хранения условно-постоянной информации: списков однотипных сущностей, которые меняются редко и используются многократно.
Представьте магазин. Товары в нём заводят один раз, а потом ссылаются на них в каждой продаже месяцами. Клиенты, поставщики, склады, статьи затрат — всё это заводится заранее и переиспользуется. Именно такие данные и хранят справочники. Их называют условно-постоянными: не константа на всю жизнь, но и не меняется от операции к операции. В типовой «1С:Бухгалтерии» справочников десятки — «Номенклатура», «Контрагенты», «Организации», «Физические лица», «Валюты».
Зачем это нужно на практике
Без справочников пришлось бы в каждом документе продажи заново набирать название товара, его артикул и единицу измерения. Ошиблись в букве — и отчёт «съест» товар как отдельную позицию. Справочник решает это: товар заводится один раз, а везде дальше мы ставим ссылку на элемент справочника. Изменили наименование в одном месте — оно поменялось во всех документах, потому что они хранят не текст, а ссылку.
Код и наименование
У каждого справочника по умолчанию есть два стандартных реквизита: Код и Наименование. Код — короткий идентификатор (часто автонумеруемый: 000000001, 000000002), наименование — то, что видит пользователь. Оба можно настроить: длину кода, тип (числовой или строковый), автонумерацию.
Обратиться к элементу справочника из кода можно через глобальное свойство Справочники — это менеджер, точка входа ко всем справочникам конфигурации:
// Находим товар по коду
Товар = Справочники.Номенклатура.НайтиПоКоду("000000042");
Если ЗначениеЗаполнено(Товар) Тогда
Сообщить("Нашли: " + Товар.Наименование);
Иначе
Сообщить("Товар с таким кодом не найден");
КонецЕсли;
Результат:
Нашли: Ноутбук Lenovo IdeaPad
Важный момент: НайтиПоКоду и НайтиПоНаименованию всегда возвращают ссылку. Если ничего не нашлось — вернётся пустая ссылка, а не ошибка. Поэтому результат проверяют через ЗначениеЗаполнено(), а не сравнением с Неопределено.
Реквизиты
Кода и наименования почти всегда мало. Реквизит — это дополнительное поле элемента справочника. У «Номенклатуры» это может быть «Артикул», «ЕдиницаИзмерения», «СтавкаНДС», «Производитель». У «Контрагентов» — «ИНН», «КПП», «ЮридическийАдрес». Реквизиты добавляются в конфигураторе, а из кода читаются как свойства через точку:
Товар = Справочники.Номенклатура.НайтиПоНаименованию("Ноутбук Lenovo IdeaPad");
Сообщить("Артикул: " + Товар.Артикул);
Сообщить("Ставка НДС: " + Товар.СтавкаНДС);
// Проверим обязательное поле перед использованием
Если НЕ ЗначениеЗаполнено(Товар.ЕдиницаИзмерения) Тогда
Сообщить("У товара не заполнена единица измерения!");
КонецЕсли;
Создание нового элемента
Завести элемент кодом можно так: у менеджера справочника вызываем СоздатьЭлемент(), заполняем реквизиты и вызываем Записать(). Метод Записать() сохраняет объект в базу.
НовыйТовар = Справочники.Номенклатура.СоздатьЭлемент();
НовыйТовар.Наименование = "Мышь беспроводная Logitech";
НовыйТовар.Артикул = "MS-2024";
НовыйТовар.СтавкаНДС = Перечисления.СтавкиНДС.НДС20;
НовыйТовар.Записать();
Сообщить("Создан элемент, код присвоен автоматически: " + НовыйТовар.Код);
Здесь всплывает деталь, о которую спотыкаются новички: реквизит СтавкаНДС у нас — значение перечисления, поэтому и присваиваем мы ему не строку "20%", а конкретное значение Перечисления.СтавкиНДС.НДС20. Тип реквизита задаётся в конфигураторе, и код обязан этому типу соответствовать: строке — строку, ссылке на справочник — ссылку, числу — число.
Ссылка и представление
Ссылка на элемент — это внутренний идентификатор, а не читаемый текст. Когда ссылку выводят пользователю (в списке, в поле формы), 1С показывает не её, а представление — обычно наименование. В коде представление можно получить явно, не читая реквизит вручную:
Товар = Справочники.Номенклатура.НайтиПоКоду("000000042");
// Универсальный способ получить читаемый текст по любой ссылке
Текст = Строка(Товар); // вызовет представление объекта
Сообщить("Представление: " + Текст);
// То же самое даёт стандартная функция
Сообщить(ПредставлениеОбъекта(Товар.Ссылка));
Это удобно в универсальном коде, который работает с разными объектами и не знает заранее, как именно у них называется «главное» поле. Для справочника это, как правило, наименование, но настройкой представления можно управлять.
Табличные части
Иногда одному элементу нужно хранить список вложенных строк. Например, у контрагента может быть несколько банковских счетов, а у товара — несколько штрихкодов. Для этого есть табличная часть — таблица внутри элемента справочника со своим набором колонок.
Контрагент = Справочники.Контрагенты.НайтиПоНаименованию("ООО Ромашка").ПолучитьОбъект();
// Перебираем строки табличной части "БанковскиеСчета"
Для Каждого СтрокаСчёта Из Контрагент.БанковскиеСчета Цикл
Сообщить(СтрокаСчёта.Банк.Наименование + ": " + СтрокаСчёта.НомерСчёта);
КонецЦикла;
// Добавим новый счёт
НоваяСтрока = Контрагент.БанковскиеСчета.Добавить();
НоваяСтрока.НомерСчёта = "40702810000000012345";
Контрагент.Записать();
Обратите внимание на ПолучитьОбъект(): чтобы менять элемент, ссылки недостаточно — нужен объект. Об этом подробнее ниже.
Иерархия
Справочник можно сделать иерархическим — тогда элементы группируются в папки. «Номенклатуру» удобно разложить по группам «Ноутбуки», «Мыши», «Клавиатуры». В 1С два вида иерархии: иерархия групп и элементов (папки отдельно, товары отдельно) и иерархия элементов (родителем может быть любой элемент). У элемента появляется стандартный реквизит Родитель, а у групп — свойство ЭтоГруппа.
Выборка = Справочники.Номенклатура.Выбрать();
Пока Выборка.Следующий() Цикл
Если Выборка.ЭтоГруппа Тогда
Сообщить("Группа: " + Выборка.Наименование);
Иначе
Сообщить(" Товар: " + Выборка.Наименование
+ " (в группе " + Выборка.Родитель.Наименование + ")");
КонецЕсли;
КонецЦикла;
Как это работает
Под капотом каждый справочник — это таблица в СУБД (PostgreSQL, MS SQL и др.), которую платформа создаёт автоматически по описанию из конфигуратора. У каждого элемента есть невидимая уникальная ссылка — GUID из 16 байт. Когда документ «ссылается» на товар, в его поле хранится именно этот GUID, а не текст наименования. Поэтому переименование товара мгновенно отражается всюду — данные-то не дублируются.
Ключевое различие, которое путают новички: ссылка (тип СправочникСсылка.Номенклатура) — это указатель «только для чтения», по нему можно читать реквизиты, но нельзя менять. Объект (тип СправочникОбъект.Номенклатура) — это загруженный в память элемент, который можно править и записывать. Из ссылки объект получают методом ПолучитьОбъект(), обратно — свойством .Ссылка.
Частые ошибки
- Пытаться изменить реквизит через ссылку. Строка
Товар.Артикул = "новый", гдеТовар— ссылка, вызовет ошибку: у ссылки поля доступны только на чтение. СначалаОбъект = Товар.ПолучитьОбъект(), потом правим иЗаписать(). - Забыть
Записать(). Изменили объект в памяти, но не записали — база осталась прежней. Частая причина «почему не сохранилось». - Сравнивать результат поиска с
Неопределено.НайтиПоКодупри неудаче возвращает пустую ссылку, а неНеопределено. Правильная проверка —ЗначениеЗаполнено(результат). - Искать по наименованию как по уникальному ключу. Наименования могут повторяться, а
НайтиПоНаименованиювернёт только первый совпавший элемент. Для гарантированной уникальности используйте код или отдельный реквизит.
Итоги
- Справочник хранит условно-постоянные списки: товары, контрагенты, склады — заводятся редко, используются часто.
- Стандартные реквизиты — Код и Наименование; свои поля добавляют как реквизиты, вложенные списки — как табличные части.
- Поиск:
НайтиПоКоду()иНайтиПоНаименованию()возвращают ссылку; проверяйте её черезЗначениеЗаполнено(). - Ссылка — только чтение; чтобы менять элемент, берите объект через
ПолучитьОбъект()и сохраняйтеЗаписать(). - Иерархия превращает плоский список в дерево групп; признак папки —
ЭтоГруппа, родитель — реквизитРодитель.