Из чего состоят данные 1С:Предприятия 8.3: примитивные типы, ссылки, коллекции и составные поля
Содержание
Значение в 1С — это любая единица данных, с которой работает платформа: число, строка, дата, ссылка на элемент справочника, документ или целая таблица. У каждого значения есть тип, и его всегда можно узнать функцией ТипЗнч(). Справочник, документ и константа — это не типы значений, а объекты конфигурации, которые хранят значения по-разному: справочник ведёт список, документ фиксирует событие на дату, константа держит одно значение на всю базу.
Отсюда простое правило для разработчика и внимательного пользователя. Сначала понять, какого типа значение лежит в поле. Потом — где оно хранится и как его достать. Всё ниже про платформу 1С:Предприятие 8.3, конфигурация роли не играет.
Базовые типы значений в 1С: что умеет платформа без конфигурации
Есть набор типов, которые существуют в любой базе, даже пустой. Их называют примитивными.
| Тип | Пример значения | Пустое значение | Что учесть |
|---|---|---|---|
| Число | 1250.50 | 0 | В реквизите задают длину и точность; лишние знаки после запятой обрезаются при записи |
| Строка | "ООО Ромашка" | "" | Строка неограниченной длины плохо работает в запросах: её нельзя напрямую сравнивать и группировать |
| Дата | '20260107103000' | '00010101' | Состав задают в свойствах: только дата, только время или дата и время |
| Булево | Истина | Ложь | Пустого значения отдельно нет |
| Неопределено | Неопределено | — | Пустое значение составного типа и результат «ничего не нашли» |
| Null | NULL | — | Приходит из запроса, когда в левом соединении нет пары |
| Тип | Тип("Строка") | — | Значение, описывающее другой тип |
Проверка типа выглядит так:
Если ТипЗнч(Значение) = Тип("Число") Тогда
Сумма = Сумма + Значение;
ИначеЕсли ТипЗнч(Значение) = Тип("Строка") Тогда
Сумма = Сумма + Число(Значение);
КонецЕсли;
💡 Чтобы не перебирать варианты пустоты (0, "", пустая дата, пустая ссылка, Неопределено), используйте ЗначениеЗаполнено(Значение). Функция возвращает Ложь для любого пустого значения любого типа.
Строку фиксированной длины платформа дополняет пробелами до заданной длины. Поэтому при сравнении с введённым текстом применяйте СокрЛП(), иначе "ООО " и "ООО" окажутся разными значениями.
Значение-ссылка и объект метаданных
Как только в конфигурации появляется справочник «Номенклатура», у платформы появляются новые типы значений: СправочникСсылка.Номенклатура, СправочникОбъект.Номенклатура, СправочникВыборка.Номенклатура и другие. То же для документов, перечислений, планов счетов и планов видов характеристик.
Главные из них — ссылка и объект.
- 🔗 Ссылка — указатель на запись в базе. Внутри хранится уникальный идентификатор (GUID). Именно ссылка лежит в реквизите «Контрагент» документа. Ссылку можно передавать, сравнивать, хранить, но нельзя изменить через неё данные.
- ✏️ Объект — запись, загруженная в память целиком, со всеми реквизитами и табличными частями. Его получают методом
ПолучитьОбъект(), меняют и записывают.
Объект = Ссылка.ПолучитьОбъект();
Объект.Наименование = "Новое наименование";
Объект.Записать();
⚠️ Каждое обращение через точку вида Ссылка.Реквизит читает данные из базы (или из кэша). Если внутри цикла по тысяче строк писать Строка.Номенклатура.Артикул, получится тысяча скрытых запросов. Нужные реквизиты лучше получить одним запросом. В типовых конфигурациях на БСП для одного-двух полей есть функция ОбщегоНазначения.ЗначениеРеквизитаОбъекта().
Связь значения с метаданными видна из кода. Ссылка.Метаданные() вернёт описание объекта конфигурации, а через Метаданные.Справочники.Номенклатура можно получить список реквизитов, синоним, состав табличных частей. Это основа для универсальных обработок, которые работают с любым справочником.
У каждой ссылки есть «пустое» значение. Получить его можно двумя способами:
Пустая = Справочники.Номенклатура.ПустаяСсылка();
Если Ссылка.Пустая() Тогда
// реквизит не заполнен
КонецЕсли;
В тексте запроса пустая ссылка записывается как ЗНАЧЕНИЕ(Справочник.Номенклатура.ПустаяСсылка).
Справочник, документ или константа: куда положить значение
Вопрос «это справочник или документ» возникает и у программиста, который проектирует конфигурацию, и у бухгалтера, который ищет данные. Различия такие.
| Признак | Справочник | Документ | Константа |
|---|---|---|---|
| Что хранит | Список однотипных элементов: товары, контрагенты, склады | Событие: продажа, поступление, начисление | Одно значение на всю базу |
| Идентификация | Код и наименование | Номер и дата | Имя константы |
| Время | Не привязан к дате | Всегда имеет дату и время | Не привязана к дате |
| Иерархия | Может быть: группы, подчинение владельцу | Нет | Нет |
| Движения по регистрам | Нет | Да, при проведении | Нет |
| Пример обращения | Справочники.Склады.НайтиПоКоду("00001") | Документы.РеализацияТоваровУслуг.НайтиПоНомеру(...) | Константы.ИмяКонстанты.Получить() |
Короткая логика выбора:
- 📇 значение повторяется и выбирается из списка — справочник;
- 📅 факт произошёл в конкретный момент и должен повлиять на остатки или обороты — документ;
- ⚙️ настройка одна на всю программу (основная валюта, флажок «использовать склады») — константа;
- 📈 значение меняется во времени и нужна история (цены, курсы, должность сотрудника) — периодический регистр сведений , а не справочник с реквизитом.
Константа хранит значение любого допустимого типа, в том числе ссылку. Записать её можно так: Константы.ИмяКонстанты.Установить(Значение). Права на чтение и запись констант задаются в ролях отдельно для каждой константы.
Таблица значений и другие коллекции
Кроме одиночных значений, платформа работает с коллекциями. Самая популярная — таблица значений: двумерная таблица в памяти с колонками и строками. Её не хранят в базе, она живёт, пока выполняется код.
Чаще всего таблица значений получается из запроса:
Запрос = Новый Запрос;
Запрос.Текст = "ВЫБРАТЬ Номенклатура, Количество, Сумма
|ИЗ Документ.РеализацияТоваровУслуг.Товары
|ГДЕ Ссылка = &Документ";
Запрос.УстановитьПараметр("Документ", СсылкаНаДокумент);
Таблица = Запрос.Выполнить().Выгрузить();
Таблицу можно собрать и вручную. Тип колонки задают через ОписаниеТипов, иначе в колонке окажется значение любого типа и запросы по такой таблице будут работать медленнее:
Таблица = Новый ТаблицаЗначений;
Таблица.Колонки.Добавить("Товар", Новый ОписаниеТипов("СправочникСсылка.Номенклатура"));
Таблица.Колонки.Добавить("Сумма", Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(15, 2)));
НоваяСтрока = Таблица.Добавить();
НоваяСтрока.Товар = Товар;
НоваяСтрока.Сумма = 1500;
Что умеет таблица значений без лишних циклов:
Таблица.Свернуть("Товар", "Сумма")— сгруппировать по товару и сложить суммы.Таблица.Сортировать("Сумма Убыв")— отсортировать.Таблица.НайтиСтроки(Новый Структура("Товар", Товар))— получить массив строк по отбору.Таблица.Итог("Сумма")— посчитать итог по колонке.Таблица.ВыгрузитьКолонку("Товар")— получить массив значений одной колонки.
Другие коллекции и когда их брать:
| Коллекция | Для чего | Ключевая особенность |
|---|---|---|
| Массив | Простой список значений | Доступ по индексу с нуля |
| Структура | Набор именованных значений | Ключ — строка, похожая на имя переменной |
| Соответствие | Словарь «ключ → значение» | Ключом может быть любое значение, в том числе ссылка |
| Список значений | Список с представлениями и пометками | Удобен для выбора в форме |
| Дерево значений | Иерархия строк | Аналог таблицы значений с подчинёнными строками |
⚠️ Таблица значений недоступна на тонком клиенте. В форме она превращается в коллекцию данных формы. Для перехода туда и обратно служат ЗначениеВРеквизитФормы() и РеквизитФормыВЗначение(), и вызываются они на сервере.
Хранение значений в базе и сериализация
Значение, записанное в реквизит, платформа раскладывает по полям таблиц СУБД. Число становится числовым полем, строка — строковым, ссылка — двоичным полем с GUID. Прямое редактирование этих таблиц средствами СУБД ломает логику платформы, поэтому все изменения идут через объекты 1С.
Когда значение нужно передать за пределы базы или положить в поле «как есть», его сериализуют — превращают в строку или поток байтов.
| Способ | Что получается | Когда использовать |
|---|---|---|
ЗначениеВСтрокуВнутр() / ЗначениеИзСтрокиВнутр() | Строка во внутреннем формате 1С | Временное хранение внутри одной базы |
ХранилищеЗначения | Упакованное значение в реквизите | Хранить файл, картинку, настройку целиком |
СериализаторXDTO + ЗаписьXML | XML | Обмен между базами 1С, выгрузка данных |
ЗаписатьJSON() | JSON | Обмен с внешними сервисами, HTTP-запросы |
Хранилище значения подходит, когда в реквизите нужно держать не простое значение, а, например, таблицу настроек или двоичные данные файла:
Объект.Настройки = Новый ХранилищеЗначения(ТаблицаНастроек, Новый СжатиеДанных(9));
// ...
ТаблицаНастроек = Объект.Настройки.Получить();
Тип реквизита при этом должен быть ХранилищеЗначения. По содержимому такого поля нельзя отбирать в запросе: для платформы это закрытый «чёрный ящик».
Выгрузка ссылки в XML:
Запись = Новый ЗаписьXML;
Запись.УстановитьСтроку();
СериализаторXDTO.ЗаписатьXML(Запись, Ссылка);
ТекстXML = Запись.Закрыть();
💡 Простой ЗаписатьJSON() понимает примитивные типы, массивы, структуры и соответствия со строковыми ключами. Ссылку он записать не может. Перед выгрузкой превратите ссылку в строку: например, уникальный идентификатор через Строка(Ссылка.УникальныйИдентификатор()) или код и наименование.
Формат ЗначениеВСтрокуВнутр() не документирован и может меняться между версиями платформы. Для обмена с другими программами и долгого хранения берите XML или JSON.
Составной тип: одно поле на несколько типов значений
Реквизит может принимать значения разных типов. Классический пример — регистратор в регистре: это может быть любой из документов, которые делают движения. В свойствах реквизита такой тип собирают из нескольких флажков, его и называют составным.
Как платформа хранит составной тип в базе. Вместо одного поля появляется несколько: служебное поле с видом значения, поле с номером таблицы для ссылки, поле с самой ссылкой и отдельные поля под каждый примитивный тип. Отсюда цена составного типа: больше места и сложнее запросы.
Работа с составным значением в коде:
Если ТипЗнч(Регистратор) = Тип("ДокументСсылка.РеализацияТоваровУслуг") Тогда
// обработка продажи
ИначеЕсли ЗначениеЗаполнено(Регистратор) Тогда
// другой документ
КонецЕсли;
В запросе тип проверяют оператором ССЫЛКА, а к нужному типу приводят через ВЫРАЗИТЬ:
ВЫБРАТЬ
ВЫРАЗИТЬ(Движения.Регистратор КАК Документ.РеализацияТоваровУслуг).Контрагент КАК Контрагент
ИЗ
РегистрНакопления.ИмяРегистра КАК Движения
ГДЕ
Движения.Регистратор ССЫЛКА Документ.РеализацияТоваровУслуг
⚠️ Обращение через точку к полю составного типа без ВЫРАЗИТЬ заставляет платформу соединить запрос со всеми таблицами, которые входят в тип. Если в составе тридцать документов, получится тридцать соединений и медленный отчёт.
Правила, которые экономят время:
- ✅ включайте в составной тип только то, что реально нужно;
- ✅ для пустого значения такого поля ждите
Неопределено, а не пустую ссылку конкретного типа; - ✅ если набор типов повторяется в нескольких местах, используйте определяемый тип — он задаётся один раз в общих объектах конфигурации;
- ❌ не выбирайте тип «Любая ссылка» ради удобства: потеряете контроль над тем, что попадает в поле.
Где ошибаются при работе со значениями
Несколько ловушек, которые встречаются чаще всего.
Путают Null и Неопределено. Null приходит из запроса при левом соединении, Неопределено — пустое значение переменной или составного поля. Проверка Значение = Неопределено для результата запроса не сработает. Надёжнее либо ЗначениеЗаполнено(), либо ЕСТЬNULL() прямо в тексте запроса.
Сравнивают ссылку с наименованием. Условие Контрагент = "ООО Ромашка" всегда ложно: слева ссылка, справа строка. Сравнивайте со ссылкой или с Контрагент.Наименование.
Склеивают число со строкой без форматирования. "Сумма: " + 1500000 даст строку с пробелом-разделителем разрядов. Для кода, номеров и выгрузок используйте Формат(Сумма, "ЧГ=0").
Пишут в ссылку. Попытка присвоить Ссылка.Наименование = ... приведёт к ошибке: через ссылку данные только читаются. Нужен ПолучитьОбъект().
Передают таблицу значений на клиент. Вызов серверной функции, которая возвращает таблицу значений, из клиентского кода приведёт к ошибке, потому что на тонком клиенте такого типа нет. Возвращайте массив структур или помещайте данные во временное хранилище.
Частые вопросы
Чем значение отличается от переменной в 1С?
Как узнать тип значения в поле, если его не видно на форме?
ТипЗнч(Значение) в отладчике или вывести Строка(ТипЗнч(Значение)) сообщением. Для ссылочного типа полное имя объекта даст Значение.Метаданные().ПолноеИмя().Можно ли хранить в константе таблицу?
ХранилищеЗначения. Таблицу помещают в хранилище и записывают в константу. Отобрать данные по содержимому такой константы в запросе не получится.