Как устроены поля объектов метаданных в 1С

· 9 мин

Содержание

Поле объекта в 1С — это отдельная характеристика, которую хранит объект метаданных: наименование справочника, дата документа, ставка НДС в строке табличной части. В конфигураторе поля называются реквизитами, у каждого есть имя, тип данных и набор свойств. От того, как заданы эти свойства, зависит, что попадёт в базу, как поле отработает в запросе и не замедлит ли оно отбор.

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

Что хранит реквизит и где он живёт

Любой прикладной объект — справочник, документ, регистр — это таблица в базе данных. Строки таблицы это элементы объекта, столбцы — его реквизиты. Реквизит и есть поле: именованная ячейка с одним значением определённого типа.

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

У каждого реквизита есть Имя (латиницей, для кода) и Синоним (как поле подписано в интерфейсе). Имя менять после ввода данных можно, но придётся вручную поправить весь код, где оно встречается.

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

Часть полей платформа заводит автоматически. Для справочника это, например, Код, Наименование, Ссылка, ПометкаУдаления, Родитель, Владелец, ЭтоГруппа, Предопределённый. Для документа — Номер, Дата, Проведён, ПометкаУдаления, Ссылка. Эти поля называются стандартными реквизитами, их состав зависит от вида объекта и его настроек (иерархия, подчинённость).

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

Разница на практике:

  • 🔹 Стандартные реквизиты нельзя удалить, но можно включить/выключить и настроить (длину кода, тип нумерации).
  • 🔹 Пользовательские реквизиты вы создаёте, меняете и удаляете свободно — пока по ним нет данных.
  • 🔹 Удаление реквизита, по которому уже есть значения в базе, приведёт к потере этих данных после обновления структуры.

Какие бывают типы данных у поля

Тип определяет, что поле вообще способно хранить. Типы делятся на две большие группы.

Примитивные типы — значения, которые не ссылаются на другие объекты:

ТипЧто хранитЧто настраивается
ЧислоКоличество, сумму, ставкуДлина (всего знаков) и точность (знаков после запятой)
СтрокаТекст, артикул, комментарийДлина и признак переменной/фиксированной длины
ДатаДату, время или дату со временемСостав даты: Дата, Время, Дата и время
БулевоПризнак «да/нет» (флажок)—

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

Отдельно стоят служебные типы платформы — УникальныйИдентификатор, ХранилищеЗначения (для картинок и файлов внутри базы), перечисления (ПеречислениеСсылка.*). Их тоже можно назначить реквизиту.

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

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

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

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

Составной тип удобен, но у него есть цена:

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

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

В коде тип значения проверяют функцией ТипЗнч:

Если ТипЗнч(Объект.Регистратор) = Тип("ДокументСсылка.РеализацияТоваровУслуг") Тогда
    Номер = Объект.Регистратор.Номер;
КонецЕсли;

Свойства и модификаторы поля

Свойства реквизита задаются в палитре свойств (откройте реквизит в дереве конфигурации). Самые важные для проектирования:

  1. Длина и точность числа. Длина — общее число разрядов, точность — сколько из них после запятой. Для суммы обычно хватает длины 15 и точности 2. Запас не бесплатен: чрезмерная длина раздувает таблицу.
  2. Длина строки и её тип. Строка бывает переменной и фиксированной длины. Строка неограниченной длины (длина 0) хранится в отдельной структуре и не может индексироваться и участвовать в отборах — используйте её только для длинных комментариев.
  3. Индексирование. Три значения: Не индексировать, Индексировать, Индексировать с доп. упорядочиванием. Индекс ускоряет отбор и поиск по полю, но замедляет запись и увеличивает базу. Индексируйте поля, по которым реально фильтруете.
  4. Проверка заполнения. Значение Выдавать ошибку заставит платформу не дать записать объект с пустым полем — удобно для обязательных реквизитов.
  5. Заполнять из данных заполнения. Позволяет автоматически подставлять значение при вводе на основании.

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

Ещё две настройки влияют на удобство ввода. Быстрый выбор подставляет выпадающий список прямо в поле, без открытия отдельной формы выбора — это ускоряет заполнение коротких справочников. Связи параметров выбора ограничивают список значений в зависимости от другого поля: например, в строке показывать только договоры выбранного контрагента, а не все сразу. Эти свойства не меняют хранение, но сильно влияют на то, насколько поле защищено от ошибочного ввода.

Как прочитать и записать значение поля

В коде обращение к полю — это точка после объекта: Объект.Реквизит. Записать значение так же просто, но для справочников и документов изменение фиксируется только после Записать().

// Чтение поля через выборку
Выборка = Справочники.Номенклатура.Выбрать();
Пока Выборка.Следующий() Цикл
    Сообщить(Выборка.Наименование + " / " + Выборка.Артикул);
КонецЦикла;

// Изменение поля конкретного элемента
ЭлементОбъект = Выборка.Ссылка.ПолучитьОбъект();
ЭлементОбъект.Артикул = "НЕ-001";
ЭлементОбъект.Записать();

В языке запросов поля перечисляются после ВЫБРАТЬ. К реквизитам связанного объекта обращаются через точку — платформа сама подставит соединение:

ВЫБРАТЬ
    Номенклатура.Наименование КАК Товар,
    Номенклатура.ЕдиницаИзмерения.Наименование КАК Единица
ИЗ
    Справочник.Номенклатура КАК Номенклатура

Для составного поля прямая точка не сработает — значение сначала приводят к типу оператором ВЫРАЗИТЬ(… КАК …):

ВЫБРАТЬ
    ВЫРАЗИТЬ(Товары.Регистратор КАК Документ.РеализацияТоваровУслуг).Дата КАК ДатаДок
ИЗ
    РегистрНакопления.Товары КАК Товары

Строки, у которых тип в выражении не совпал, вернут NULL — это нормальная цена универсальности составного поля.

Запрос обращается к любым полям таблицы, в том числе к стандартным. Можно отобрать документы по дате, исключить помеченные на удаление и непроведённые:

ВЫБРАТЬ
    Реализация.Ссылка,
    Реализация.Номер,
    Реализация.Дата
ИЗ
    Документ.РеализацияТоваровУслуг КАК Реализация
ГДЕ
    Реализация.Проведён
    И НЕ Реализация.ПометкаУдаления
    И Реализация.Дата МЕЖДУ &Начало И &Конец

Такой отбор работает быстро, если поля Дата и Проведён участвуют в индексе. Для полей, по которым вы регулярно строите подобные выборки, свойство Индексирование окупается.

Табличная часть — набор полей в строках

Табличная часть это вложенная таблица внутри объекта: товары в накладной, начисления в документе зарплаты. У неё свои реквизиты — те же поля, но на уровне строки. В каждой строке табличной части живёт свой набор значений.

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

Итого = 0;
Для Каждого Строка Из Объект.Товары Цикл
    Строка.Сумма = Строка.Количество * Строка.Цена;
    Итого = Итого + Строка.Сумма;
КонецЦикла;
Объект.СуммаДокумента = Итого;

У полей табличной части те же свойства, что у реквизитов шапки: тип, длина, индексирование. Отдельно есть Индексировать на уровне самой табличной части — помогает, когда по её полю часто идёт отбор в запросах.

В запросе к табличной части обращаются как к отдельной таблице через точку от объекта: Документ.РеализацияТоваровУслуг.Товары. Поля строки доступны напрямую, а агрегаты удобно считать прямо в запросе:

ВЫБРАТЬ
    Товары.Ссылка КАК Документ,
    СУММА(Товары.Сумма) КАК ИтогоПоДокументу
ИЗ
    Документ.РеализацияТоваровУслуг.Товары КАК Товары
СГРУППИРОВАТЬ ПО
    Товары.Ссылка

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

Ошибки при проектировании полей

Чаще всего проблемы родом не из кода, а из того, как заданы сами поля. Три типичные:

  • ❌ Составной тип без необходимости. Поле раздувает таблицу и ломает прямые обращения в запросах. Проверьте: если тип по смыслу всегда один — уберите лишние.
  • ❌ Строки с запасом длины или неограниченные там, где нужен короткий код. Неограниченная строка не индексируется и не годится для отбора; код или артикул делайте строкой разумной фиксированной длины.
  • ❌ Нет индекса по полю, по которому постоянно ищут. Отбор по неиндексированному реквизиту на большой таблице заставляет платформу перебирать все строки.
Проверка нового реквизита перед записью в конфигурацию
Выполнено: 0 / 6

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

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

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

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

Чем реквизит отличается от поля?
Это одно и то же в разных контекстах. В конфигураторе и прикладной логике говорят «реквизит», в языке запросов и теории баз данных — «поле таблицы». Технически реквизит объекта хранится как столбец его таблицы.
Можно ли переименовать реквизит без потери данных?
Да, данные при переименовании имени сохраняются — платформа отслеживает поле по внутреннему идентификатору, а не по имени. Но весь код и запросы, где встречалось старое имя, нужно поправить вручную, иначе они перестанут работать.
Почему к составному полю не получается обратиться через точку в запросе?
Платформа не знает заранее, какого типа значение в строке, поэтому не может подставить соединение. Приведите значение к конкретному типу через ВЫРАЗИТЬ(Поле КАК Тип) — после этого реквизиты доступны через точку.
Как узнать тип значения реквизита в коде?
Используйте функцию ТипЗнч(Значение) — она вернёт тип, который сравнивают с результатом Тип("…"). Для составных полей это основной способ ветвить логику по фактическому типу.
Индексировать ли каждое поле на всякий случай?
Нет. Индекс ускоряет чтение, но замедляет запись и увеличивает размер базы. Индексируйте только поля, по которым реально идут отборы, поиск или соединения в запросах.