Реквизит в 1С и его значение: типы, чтение и запись
Содержание
Реквизит в 1С — это именованное поле объекта конфигурации: справочника, документа, плана видов характеристик и других. «Значение реквизита» — то, что в этом поле лежит в конкретной записи: строка «ООО Ромашка» в реквизите ИНН, дата в реквизите Дата, ссылка на склад в реквизите Склад. Структуру реквизитов описывает разработчик в конфигураторе, значения вводит пользователь или заполняет программа.
Для пользователя реквизит — это поле в форме. Для программиста — свойство объекта, которое читается и пишется через точку. Ниже — как значения устроены, откуда их брать и где при этом ошибаются.
Что такое реквизит и чем он отличается от соседних понятий
Реквизиты бывают у разных объектов, и называются они не всегда одинаково:
- 📄 Справочник — реквизиты в самом справочнике (например,
ИНН,КПП,Родитель). Код и наименование — стандартные реквизиты. - 🧾 Документ — реквизиты шапки (
Дата,Номер,Организация,Контрагент) и реквизиты табличных частей (колонки таблицы товаров). - 📊 Регистр сведений и накопления — здесь поля делятся на три группы: измерения, ресурсы и реквизиты. Реквизит регистра — это дополнительная информация, по ней не группируют и не ищут записи.
- 🧩 Обработка и форма — реквизиты формы, которые существуют только пока открыта форма и не хранятся в базе.
Разница между группами важна на практике. Измерение регистра входит в ключ записи, ресурс складывается при итогах, а реквизит просто хранит данные. Если вы ищете «реквизит» в регистре накопления, а нужное поле оказалось ресурсом, обращение по имени всё равно сработает — но в запросе его придётся брать из другой группы виртуальной таблицы.
Реквизит объекта и реквизит формы
Это самая частая путаница у начинающих. Реквизит объекта хранится в базе данных. Реквизит формы — временный: он нужен, чтобы показать на экране значение, которого нет в объекте (например, итог для отображения или флажок «показывать закрытые»).
Реквизит формы с основным типом «Объект» (его создаёт платформа для формы документа или справочника) связывает форму с данными. Поэтому в коде формы пишут Объект.Контрагент, а в модуле объекта — просто Контрагент.
Типы значений реквизита
Тип реквизита задаётся при создании и определяет, что можно в него положить. Основные варианты:
| Тип | Что хранит | Пример значения |
|---|---|---|
| Строка | Текст, длина фиксированная или неограниченная | "Иванов И.И." |
| Число | Целое или дробное, задаются разрядность и точность | 1250.50 |
| Дата | Дата, время или оба сразу | '20261007' |
| Булево | Истина или Ложь | флажок «Закрыт» |
| Ссылка на справочник | Ссылка на элемент справочника | СправочникСсылка.Контрагенты |
| Ссылка на документ | Ссылка на конкретный документ | ДокументСсылка.ПоступлениеТоваровУслуг |
| Перечисление | Одно из заранее заданных значений | ПеречислениеСсылка.ВидыКонтрагентов |
| Составной тип | Любой из нескольких перечисленных типов | ссылка на разные справочники |
Для ссылочных реквизитов значение — это не сам объект, а указатель на него. Пока вы не обратились к полям этой ссылки, данные объекта из базы не читаются. Это даёт важный эффект: ссылка может «висеть» на удалённый элемент, и значение реквизита формально есть, а объект по нему уже не найти.
Пустое значение и Неопределено
У каждого типа есть пустое значение. Пустая строка, ноль, пустая дата ('00010101'), Ложь, пустая ссылка. Оно не то же самое, что Неопределено.
- Пустая ссылка — значение типа
СправочникСсылка.Контрагенты, у которого просто нет объекта. Неопределено— отдельный тип «ничего нет». Он появляется, если реквизит составного типа никогда не заполнялся, или когда функция не нашла результат.Null— значение, которое отдаёт запрос при соединении, если справа не нашлось записи.
Проверку на пустоту делают методом Пустая() у ссылки или функцией ЗначениеЗаполнено(). Прямое сравнение с Неопределено для ссылочных реквизитов срабатывает редко и вводит в заблуждение.
Тип значения проверяют функцией ТипЗнч(). Если реквизит составного типа, сначала смотрите тип, потом читайте поля: у числа нет свойства Наименование.
Как получить значение реквизита
Способов несколько, и они различаются ценой. Выбирайте по задаче: прочитать один раз для показа, обработать тысячу строк или собрать отчёт.
Обращение через точку
Самый простой путь. Если у вас есть ссылка на объект, поле читается так:
ИННКонтрагента = Контрагент.ИНН;
На сервере это приводит к обращению к базе: платформа читает запись целиком и вернёт одно поле. Для единичного чтения в форме это нормально. В цикле по тысяче элементов — уже заметная нагрузка, потому что каждое обращение — отдельное чтение.
Через точку можно идти по цепочке: Документ.Контрагент.ГоловнойКонтрагент.ИНН. Каждая точка — ещё одно чтение. Если на каком-то шаге ссылка пустая, получите пустое значение, а не ошибку: платформа вернёт значение по умолчанию для типа поля.
Получение объекта и чтение его полей
Когда нужно изменять данные, ссылку превращают в объект:
Объект = Контрагент.ПолучитьОбъект();
ИННКонтрагента = Объект.ИНН;
Объект загружается в память целиком вместе с табличными частями. Для одного чтения это избыточно, но если дальше вы будете и читать, и менять, и записывать, — получайте объект один раз.
Запрос
Если нужно прочитать реквизиты многих элементов, используйте запрос: он делает одно обращение вместо тысячи.
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Контрагенты.Ссылка КАК Ссылка,
| Контрагенты.ИНН КАК ИНН
|ИЗ
| Справочник.Контрагенты КАК Контрагенты
|ГДЕ
| Контрагенты.Родитель = &Родитель";
Запрос.УстановитьПараметр("Родитель", Группа);
Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
Сообщить(Выборка.Ссылка.Код + ": " + Выборка.ИНН);
КонецЦикла;
Обратите внимание, что в этом примере код читается через Выборка.Ссылка.Код, то есть снова через точку. В запросе лучше сразу выбрать нужное поле, чтобы не делать повторных обращений.
Готовые функции библиотеки стандартных подсистем
В конфигурациях на базе БСП есть общий модуль ОбщегоНазначения. В нём есть функции для чтения реквизитов без загрузки всего объекта:
Наименование = ОбщегоНазначения.ЗначениеРеквизитаОбъекта(Контрагент, "Наименование");
Реквизиты = ОбщегоНазначения.ЗначенияРеквизитовОбъекта(Контрагент, "ИНН, КПП");
Вторая функция возвращает структуру, ключи которой совпадают с именами реквизитов. Под капотом она строит запрос, поэтому работает дешевле обращения через точку. Если вы пишете для конфигурации без БСП, этих функций не будет — используйте запрос.
Сравнение способов
| Способ | Когда использовать | Что учесть |
|---|---|---|
| Через точку | Единичное чтение, цепочка 1–2 уровня | В цикле создаёт нагрузку на сервер |
ПолучитьОбъект() | Читаете и меняете, потом записываете | Объект целиком в памяти |
| Запрос | Много элементов, отчёты, фильтры | Нужно знать язык запросов |
ЗначениеРеквизитаОбъекта | Один-несколько реквизитов из БСП | Только в конфигурациях с БСП |
Как изменить значение реквизита
Читать можно что угодно, а менять — только то, что разрешено. Путь зависит от того, кто меняет.
Пользователь в форме
Пользователь вводит значение прямо в поле. Если поле нельзя редактировать, причина может быть одной из нескольких:
- Разработчик выставил полю свойство «Только просмотр».
- У пользователя нет права на изменение объекта (роль в профиле доступа).
- Документ проведён и форма закрыта от правки специальной настройкой (например, запрет редактирования после закрытия периода).
- Включена настройка «Запрет изменения данных прошлых периодов» — она есть в администрировании и блокирует правки по дате.
Если поле «серое» не из-за вашей ошибки, не обходите блокировку через правку в конфигураторе. Сначала узнайте у администратора, зачем она включена.
Код: изменение в объекте
В модуле объекта или в обработке меняют так:
Объект = Контрагент.ПолучитьОбъект();
Объект.КПП = "770101001";
Объект.Записать();
Присвоить значение недостаточно. Пока не вызван метод Записать(), изменение живёт только в памяти. Для документа вместо него вызывают Записать(РежимЗаписиДокумента.Проведение), если нужно ещё и провести.
Изменить значение через ссылку нельзя: Контрагент.КПП = "…" вызовет ошибку, потому что ссылка только читается.
Ограничения, на которые натыкаются чаще всего
- 🔒 Блокировка объекта. Если другой пользователь уже редактирует элемент в режиме управляемых блокировок, запись упадёт с ошибкой.
- 🔒 Контроль заполнения. Для обязательных реквизитов платформа выдаёт сообщение и отказывает в записи, пока поле пусто.
- 🔒 Несоответствие типа. Строку в числовой реквизит платформа попытается преобразовать, и при неудаче будет ошибка.
- 🔒 Длина строки. Слишком длинное значение в строковом реквизите ограниченной длины обрезается молча или вызывает ошибку, в зависимости от места присвоения. Проверьте длину заранее.
Типичные ошибки при работе со значениями
Здесь только то, чего нет в описании способов выше.
«Поле объекта не обнаружено». Имя реквизита написано с опечаткой или реквизит принадлежит другому объекту. Проверьте имя в конфигураторе: оно должно совпадать посимвольно. Ошибка выпадает во время выполнения, а не при проверке синтаксиса, если переменная не типизирована.
Чтение у пустой ссылки. Обращение к полю пустой ссылки не падает, а возвращает пустое значение. Из-за этого ошибка прячется: отчёт строится, но в колонке пусто. Проверяйте ЗначениеЗаполнено(Ссылка) до чтения.
Сравнение строки с числом. "10" = 10 вернёт Ложь, и условие не сработает. Приводите типы явно через Число() или Строка().
Склейка числа и строки. Число превратится в строку с пробелами-разделителями тысяч: 1 250. Если значение нужно без них, используйте Формат(Число, "ЧГ=0") или СтрШаблон.
Повторное чтение в цикле. Классика: внутри цикла по документам снова и снова читают Документ.Контрагент.ИНН. На ста документах разница не заметна, на ста тысячах — это минуты. Вынесите чтение в запрос.
Реквизит формы вместо реквизита объекта. Значение поменяли в ЭтаФорма.Реквизит, а в базу оно не попало. Если поле должно сохраниться, оно обязано быть реквизитом объекта.
Примеры кода: типовые задачи
Найти элемент справочника и прочитать значение
Контрагент = Справочники.Контрагенты.НайтиПоКоду("00000123");
Если Не Контрагент.Пустая() Тогда
ИНН = Контрагент.ИНН;
Сообщить("ИНН: " + ИНН);
КонецЕсли;
НайтиПоКоду возвращает пустую ссылку, если ничего не найдено, и проверка Пустая() защищает от чтения пустоты.
Проверить тип составного реквизита
Если ТипЗнч(Документ.Основание) = Тип("ДокументСсылка.РеализацияТоваровУслуг") Тогда
Сообщить("Основание — реализация");
КонецЕсли;
Обойти табличную часть и прочитать колонку
Для Каждого Строка Из Документ.Товары Цикл
Сообщить(Строка.Номенклатура + ": " + Строка.Количество);
КонецЦикла;
Колонки табличной части — те же реквизиты, только у строки. Чтобы получить табличную часть документа по ссылке, достаточно обратиться через точку, как к обычному реквизиту.
Изменить значение реквизита у группы элементов
Для разовой правки через интерфейс подойдёт групповая обработка справочников и документов: она есть в типовых конфигурациях на базе БСП и меняет выбранный реквизит у выделенных элементов. Точное название и путь вызова зависят от конфигурации, поэтому найдите команду в списке: она находится в меню команд над списком, в разделе «Все функции» или в «Администрировании». В коде групповое изменение выглядит как цикл с ПолучитьОбъект() и Записать(), поэтому обязательно делайте его пакетами и с обработкой исключений.
Значения реквизитов при обмене данными
Когда две базы обмениваются данными, значение реквизита нужно перенести из одной в другую. Тут возникает несколько тонкостей.
Ссылки не переносятся как есть
Ссылка в одной базе — внутренний идентификатор. В другой базе тот же элемент имеет другой идентификатор, если его создали независимо. Поэтому правила обмена сопоставляют элементы по уникальному идентификатору, коду, наименованию или ИНН — так называемым свойствам поиска. Если свойств поиска не хватает, получаются дубли: в приёмнике появляется второй «Рога и копыта».
Что проверить перед обменом
- Совпадают ли типы реквизитов в двух базах: число в одной, строка в другой — источник тихих потерь.
- Есть ли в приёмнике справочник, на который ссылается значение (контрагент, номенклатура, склад). Иначе обмен создаст пустую ссылку или выдаст ошибку.
- Как заполняются реквизиты, которые приёмник считает обязательными, а источник — нет.
Для визуального сопоставления полей в правилах конвертации удобна таблица соответствия.
Если в приёмнике реквизит заполняется программно при записи, значение из обмена может затереться. Проверьте обработчики записи и перед загрузкой, и после неё на тестовой базе.
Как работать с реквизитами быстрее и надёжнее
Несколько приёмов, которые различают рабочий код и код, который тормозит.
- Читайте пачкой. Если нужны три поля объекта, получите их одной структурой или одним запросом, а не тремя обращениями через точку.
- Не получайте объект ради одного поля.
ПолучитьОбъект()тянет табличные части, которые вам не нужны. - Выносите чтение из циклов. Запрос до цикла, результат — в таблицу значений, дальше работаете в памяти.
- Проверяйте заполнение до чтения. Пустые ссылки и
Неопределеноне должны попадать в расчёты. - Выбирайте тип под задачу. Для флага — Булево, для фиксированного набора — Перечисление, а не строка с «да/нет». Тогда опечатки в значениях невозможны.
- Не злоупотребляйте составным типом. Он гибкий, но каждое чтение требует проверки типа, а индексы по такому реквизиту работают хуже.
Частые вопросы
Чем реквизит отличается от измерения и ресурса?
Можно ли поменять тип реквизита, если в нём уже есть данные?
Как узнать, какие реквизиты есть у объекта?
Почему значение реквизита в форме не сохраняется?
Чем `Пустая()` отличается от проверки на `Неопределено`?
Пустая() работает у ссылки и отвечает, указывает ли она на объект. Неопределено — отдельное значение типа «ничего», оно встречается у составных типов и в результатах функций.