Как устроены поля объектов метаданных в 1С
Содержание
Поле объекта в 1С — это отдельная характеристика, которую хранит объект метаданных: наименование справочника, дата документа, ставка НДС в строке табличной части. В конфигураторе поля называются реквизитами, у каждого есть имя, тип данных и набор свойств. От того, как заданы эти свойства, зависит, что попадёт в базу, как поле отработает в запросе и не замедлит ли оно отбор.
Ниже — из чего складывается поле: какие бывают типы данных, что такое составной тип, чем управляют модификаторы (длина, точность, индексирование), и как прочитать или записать значение реквизита в коде и в языке запросов.
Что хранит реквизит и где он живёт
Любой прикладной объект — справочник, документ, регистр — это таблица в базе данных. Строки таблицы это элементы объекта, столбцы — его реквизиты. Реквизит и есть поле: именованная ячейка с одним значением определённого типа.
Реквизиты объекта видны в дереве конфигурации. Откройте нужный объект, разверните ветку Реквизиты — там перечислены все пользовательские поля. Отдельно, в свойствах объекта, задаются стандартные реквизиты, которые платформа создаёт сама.
У каждого реквизита есть Имя (латиницей, для кода) и Синоним (как поле подписано в интерфейсе). Имя менять после ввода данных можно, но придётся вручную поправить весь код, где оно встречается.
Стандартные и пользовательские поля
Часть полей платформа заводит автоматически. Для справочника это, например, Код, Наименование, Ссылка, ПометкаУдаления, Родитель, Владелец, ЭтоГруппа, Предопределённый. Для документа — Номер, Дата, Проведён, ПометкаУдаления, Ссылка. Эти поля называются стандартными реквизитами, их состав зависит от вида объекта и его настроек (иерархия, подчинённость).
Всё остальное вы добавляете сами — это пользовательские реквизиты. В справочник «Номенклатура» это артикул, единица измерения, ставка НДС; в документ «Реализация» — контрагент, договор, склад. Стандартные реквизиты платформа заполняет и контролирует сама: номер документа выдаётся нумератором, пометка удаления ставится командой интерфейса. Пользовательские поля целиком на вашей ответственности — что в них лежит и как они проверяются, определяете вы.
Разница на практике:
- 🔹 Стандартные реквизиты нельзя удалить, но можно включить/выключить и настроить (длину кода, тип нумерации).
- 🔹 Пользовательские реквизиты вы создаёте, меняете и удаляете свободно — пока по ним нет данных.
- 🔹 Удаление реквизита, по которому уже есть значения в базе, приведёт к потере этих данных после обновления структуры.
Какие бывают типы данных у поля
Тип определяет, что поле вообще способно хранить. Типы делятся на две большие группы.
Примитивные типы — значения, которые не ссылаются на другие объекты:
| Тип | Что хранит | Что настраивается |
|---|---|---|
| Число | Количество, сумму, ставку | Длина (всего знаков) и точность (знаков после запятой) |
| Строка | Текст, артикул, комментарий | Длина и признак переменной/фиксированной длины |
| Дата | Дату, время или дату со временем | Состав даты: Дата, Время, Дата и время |
| Булево | Признак «да/нет» (флажок) | — |
Ссылочные типы — поле хранит ссылку на элемент другого объекта. Если реквизит Контрагент имеет тип СправочникСсылка.Контрагенты, в нём лежит не текст, а указатель на конкретный элемент справочника. Через такую ссылку вы в коде обращаетесь ко всем полям связанного объекта: Объект.Контрагент.ИНН.
Отдельно стоят служебные типы платформы — УникальныйИдентификатор, ХранилищеЗначения (для картинок и файлов внутри базы), перечисления (ПеречислениеСсылка.*). Их тоже можно назначить реквизиту.
Перечисление выбирают, когда у поля короткий фиксированный список значений, который не ведёт пользователь: вид операции, статус, направление. В отличие от справочника, перечисление задаётся на этапе разработки и не меняется из режима предприятия — это делает отборы по нему быстрыми и предсказуемыми.
Для даты важен состав: Дата без времени хранит только день, Дата и время — момент с точностью до секунды. Если поле — срок отгрузки, время лишнее и только мешает группировке; если это момент события в журнале, время обязательно. Пустая дата в 1С это не NULL, а особое «нулевое» значение '00010101000000', и сравнивать её удобнее через функцию ЗначениеЗаполнено.
Составной тип: когда одно поле держит несколько типов
Иногда поле должно хранить значения разного происхождения. Классика — реквизит Регистратор в регистре накопления: движения создаёт и «Реализация», и «Поступление», и «Корректировка». Поле делают составным: в свойстве Тип отмечают сразу несколько типов.
Составной тип удобен, но у него есть цена:
- ⚠️ Платформа хранит такое поле шире — под каждый возможный тип отводится место, плюс служебное поле-дискриминатор.
- ⚠️ В запросах к составному полю нельзя напрямую обратиться к реквизитам связанного объекта — сначала надо привести значение к конкретному типу.
- ⚠️ Отборы и индексы по составному полю работают медленнее, чем по простому ссылочному.
Не делайте реквизит составным «на всякий случай»: если по смыслу там всегда один тип, укажите именно его. Составной тип оправдан там, где разнородные значения — часть логики, а не удобство на будущее.
В коде тип значения проверяют функцией ТипЗнч:
Если ТипЗнч(Объект.Регистратор) = Тип("ДокументСсылка.РеализацияТоваровУслуг") Тогда
Номер = Объект.Регистратор.Номер;
КонецЕсли;
Свойства и модификаторы поля
Свойства реквизита задаются в палитре свойств (откройте реквизит в дереве конфигурации). Самые важные для проектирования:
- Длина и точность числа. Длина — общее число разрядов, точность — сколько из них после запятой. Для суммы обычно хватает длины 15 и точности 2. Запас не бесплатен: чрезмерная длина раздувает таблицу.
- Длина строки и её тип. Строка бывает переменной и фиксированной длины. Строка неограниченной длины (длина 0) хранится в отдельной структуре и не может индексироваться и участвовать в отборах — используйте её только для длинных комментариев.
- Индексирование. Три значения:
Не индексировать,Индексировать,Индексировать с доп. упорядочиванием. Индекс ускоряет отбор и поиск по полю, но замедляет запись и увеличивает базу. Индексируйте поля, по которым реально фильтруете. - Проверка заполнения. Значение
Выдавать ошибкузаставит платформу не дать записать объект с пустым полем — удобно для обязательных реквизитов. - Заполнять из данных заполнения. Позволяет автоматически подставлять значение при вводе на основании.
Для справочника с группами у реквизита есть свойство Использование: Для элемента, Для группы или Для элемента и группы. Если поле нужно только карточкам, а не папкам — ставьте Для элемента, иначе в группах появится лишний столбец.
Ещё две настройки влияют на удобство ввода. Быстрый выбор подставляет выпадающий список прямо в поле, без открытия отдельной формы выбора — это ускоряет заполнение коротких справочников. Связи параметров выбора ограничивают список значений в зависимости от другого поля: например, в строке показывать только договоры выбранного контрагента, а не все сразу. Эти свойства не меняют хранение, но сильно влияют на то, насколько поле защищено от ошибочного ввода.
Как прочитать и записать значение поля
В коде обращение к полю — это точка после объекта: Объект.Реквизит. Записать значение так же просто, но для справочников и документов изменение фиксируется только после Записать().
// Чтение поля через выборку
Выборка = Справочники.Номенклатура.Выбрать();
Пока Выборка.Следующий() Цикл
Сообщить(Выборка.Наименование + " / " + Выборка.Артикул);
КонецЦикла;
// Изменение поля конкретного элемента
ЭлементОбъект = Выборка.Ссылка.ПолучитьОбъект();
ЭлементОбъект.Артикул = "НЕ-001";
ЭлементОбъект.Записать();
В языке запросов поля перечисляются после ВЫБРАТЬ. К реквизитам связанного объекта обращаются через точку — платформа сама подставит соединение:
ВЫБРАТЬ
Номенклатура.Наименование КАК Товар,
Номенклатура.ЕдиницаИзмерения.Наименование КАК Единица
ИЗ
Справочник.Номенклатура КАК Номенклатура
Для составного поля прямая точка не сработает — значение сначала приводят к типу оператором ВЫРАЗИТЬ(… КАК …):
ВЫБРАТЬ
ВЫРАЗИТЬ(Товары.Регистратор КАК Документ.РеализацияТоваровУслуг).Дата КАК ДатаДок
ИЗ
РегистрНакопления.Товары КАК Товары
Строки, у которых тип в выражении не совпал, вернут NULL — это нормальная цена универсальности составного поля.
Запрос обращается к любым полям таблицы, в том числе к стандартным. Можно отобрать документы по дате, исключить помеченные на удаление и непроведённые:
ВЫБРАТЬ
Реализация.Ссылка,
Реализация.Номер,
Реализация.Дата
ИЗ
Документ.РеализацияТоваровУслуг КАК Реализация
ГДЕ
Реализация.Проведён
И НЕ Реализация.ПометкаУдаления
И Реализация.Дата МЕЖДУ &Начало И &Конец
Такой отбор работает быстро, если поля Дата и Проведён участвуют в индексе. Для полей, по которым вы регулярно строите подобные выборки, свойство Индексирование окупается.
Табличная часть — набор полей в строках
Табличная часть это вложенная таблица внутри объекта: товары в накладной, начисления в документе зарплаты. У неё свои реквизиты — те же поля, но на уровне строки. В каждой строке табличной части живёт свой набор значений.
В коде табличная часть это коллекция, по которой можно пройти циклом, а её реквизиты читаются и пишутся так же, как реквизиты шапки:
Итого = 0;
Для Каждого Строка Из Объект.Товары Цикл
Строка.Сумма = Строка.Количество * Строка.Цена;
Итого = Итого + Строка.Сумма;
КонецЦикла;
Объект.СуммаДокумента = Итого;
У полей табличной части те же свойства, что у реквизитов шапки: тип, длина, индексирование. Отдельно есть Индексировать на уровне самой табличной части — помогает, когда по её полю часто идёт отбор в запросах.
В запросе к табличной части обращаются как к отдельной таблице через точку от объекта: Документ.РеализацияТоваровУслуг.Товары. Поля строки доступны напрямую, а агрегаты удобно считать прямо в запросе:
ВЫБРАТЬ
Товары.Ссылка КАК Документ,
СУММА(Товары.Сумма) КАК ИтогоПоДокументу
ИЗ
Документ.РеализацияТоваровУслуг.Товары КАК Товары
СГРУППИРОВАТЬ ПО
Товары.Ссылка
Поле НомерСтроки платформа ведёт сама — это служебный реквизит табличной части, по которому строки упорядочены. Его не нужно заполнять и обычно не стоит менять вручную.
Ошибки при проектировании полей
Чаще всего проблемы родом не из кода, а из того, как заданы сами поля. Три типичные:
- ❌ Составной тип без необходимости. Поле раздувает таблицу и ломает прямые обращения в запросах. Проверьте: если тип по смыслу всегда один — уберите лишние.
- ❌ Строки с запасом длины или неограниченные там, где нужен короткий код. Неограниченная строка не индексируется и не годится для отбора; код или артикул делайте строкой разумной фиксированной длины.
- ❌ Нет индекса по полю, по которому постоянно ищут. Отбор по неиндексированному реквизиту на большой таблице заставляет платформу перебирать все строки.
Ещё одна ошибка — менять тип реквизита, по которому уже есть данные. Платформа при обновлении попытается привести значения к новому типу, и несовместимые просто потеряются. Перед сменой типа выгрузите данные или заведите новое поле и перенесите значения кодом.
Отдельно стоит следить за смыслом поля. Один реквизит — одна характеристика. Если в поле «Комментарий» начинают складывать то телефон, то номер договора, то причину скидки, запросы по нему становятся бесполезны: отобрать данные нечем. Когда у значения появляется самостоятельная роль в отчётах, для него заводят отдельный реквизит нужного типа, а не разбирают строку по подстрокам.
Наконец, не стоит путать реквизит и реквизит формы. Поле объекта хранится в базе, а реквизит формы существует только пока открыта форма и в базу не попадает. Для расчётных и временных значений на форме реквизит объекта заводить не нужно — он лишь раздувает таблицу.
Частые вопросы
Чем реквизит отличается от поля?
Можно ли переименовать реквизит без потери данных?
Почему к составному полю не получается обратиться через точку в запросе?
ВЫРАЗИТЬ(Поле КАК Тип) — после этого реквизиты доступны через точку.Как узнать тип значения реквизита в коде?
ТипЗнч(Значение) — она вернёт тип, который сравнивают с результатом Тип("…"). Для составных полей это основной способ ветвить логику по фактическому типу.