Коллекция «Структура» во встроенном языке 1С: создание, методы, ошибки

· 9 мин

Содержание

Новая структура в 1С — это объект встроенного языка, который создаётся конструктором Новый Структура. Это коллекция пар «ключ — значение», где ключ — строка-идентификатор, а значение — что угодно: число, ссылка, таблица, другая структура. Работает одинаково в любой конфигурации на платформе 8.3: БП, ЗУП, УТ или самописной.

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

Что такое структура в 1С и зачем она нужна

Структура — универсальная коллекция. Она хранит набор именованных значений и позволяет обращаться к ним через точку, как к реквизитам объекта: Параметры.Организация.

Ключевые свойства:

  • 🔑 Ключ — только строка, и только такая, которая годится в имя переменной: буквы, цифры, подчёркивание, не начинается с цифры, без пробелов.
  • 🔤 Регистр ключа не важен: Стр.Сумма и Стр.СУММА — одно и то же поле.
  • 📦 Значение — любого типа, в том числе другая структура или массив структур.
  • 🔁 Ключи уникальны: повторная вставка с тем же ключом не создаёт дубль, а заменяет значение.
  • 🧭 Доступ двумя способами: через точку Стр.Сумма и через квадратные скобки Стр["Сумма"]. Второй нужен, когда имя ключа хранится в переменной.

Где структура встречается в типовых конфигурациях постоянно:

  • параметры открытия формы в ОткрытьФорму(ИмяФормы, Параметры);
  • отбор для РегистрыСведений.ИмяРегистра.Получить(Отбор) и СрезПоследних(Период, Отбор);
  • условие поиска в ТаблицаЗначений.НайтиСтроки(Отбор);
  • свойство Параметры объекта Запрос;
  • результат функции БСП ОбщегоНазначения.ЗначенияРеквизитовОбъекта(Ссылка, "Код, Наименование") — структура с полями по перечисленным реквизитам.

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

Структура, Соответствие и ФиксированнаяСтруктура: сравнение

Новичку в 1С кажется, что все коллекции взаимозаменяемы. На практике у каждой своя ниша. Сравним структуру с ближайшими «соседями».

ПризнакСтруктураСоответствиеФиксированнаяСтруктура
Тип ключастрока-идентификаторлюбой значимый тип (ссылка, число, дата, строка с пробелами)строка-идентификатор
Обращение через точкуданет, только Соотв[Ключ] или Получить()да
Можно менять после созданиядаданет
Обращение к несуществующему ключуошибкаНеопределеноошибка
Где удобнапараметры, возврат нескольких значений, отборыгруппировка по ссылкам, кэш «ключ → значение»кэш в модулях с повторным использованием, константные настройки

Правило выбора короткое:

  1. Ключи известны заранее и это осмысленные имена — Структура.
  2. Ключи появляются в процессе и это ссылки, даты или произвольные строки — Соответствие.
  3. Набор нужно защитить от изменения — ФиксированнаяСтруктура.

Когда использовать новую структуру, а когда нет

Структура выигрывает, когда нужно передать «пакет» именованных значений между процедурами. Код читается лучше: Результат.Ошибка понятнее, чем Результат[2] из массива.

Хорошие сценарии:

  • ✅ функция возвращает несколько значений сразу;
  • ✅ параметры для открытия формы или длительной операции;
  • ✅ отбор по нескольким измерениям регистра;
  • ✅ настройки обработки, которые читаются по имени;
  • ✅ разбор простого JSON, где ключи — латинские или русские слова без пробелов.

Плохие сценарии:

  • ❌ ключ — ссылка на элемент справочника (так нельзя, нужен Соответствие);
  • ❌ ключ приходит извне и может содержать пробел, дефис или цифру в начале;
  • ❌ нужны сортировка, группировка, итоги — для этого есть ТаблицаЗначений;
  • ❌ тысячи однотипных записей — массив структур тяжелее и медленнее, чем таблица значений с колонками.

Как создать и заполнить структуру: пошагово

Шаг 1. Создайте структуру

Пустая структура:

Параметры = Новый Структура;

Структура с ключами сразу. Первый параметр конструктора — строка ключей через запятую, следующие — значения по порядку:

Итоги = Новый Структура("Сумма, Количество, Ошибка", 0, 0, "");

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

Шаг 2. Добавьте или замените значения

Итоги.Вставить("Склад", Склад);   // новый ключ
Итоги.Вставить("Сумма", 1500);    // ключ уже был — значение заменено
Итоги.Количество = 3;             // присвоение через точку существующему ключу

Через точку можно только изменить существующий ключ. Новый ключ добавляется исключительно методом Вставить().

Шаг 3. Прочитайте значение безопасно

Если не уверены, что ключ есть, используйте метод Свойство(). Он возвращает Истина или Ложь, а вторым параметром отдаёт найденное значение:

Значение = Неопределено;
Если Итоги.Свойство("Склад", Значение) Тогда
    Сообщить("Склад: " + Строка(Значение));
Иначе
    Сообщить("Склад не передан");
КонецЕсли;

Шаг 4. Обойдите все элементы

Элемент коллекции при обходе — объект КлючИЗначение:

Для Каждого Элемент Из Итоги Цикл
    Сообщить(Элемент.Ключ + " = " + Строка(Элемент.Значение));
КонецЦикла;

Шаг 5. Удалите лишнее и проверьте размер

Итоги.Удалить("Ошибка");          // удалить один ключ
КоличествоПолей = Итоги.Количество();
Итоги.Очистить();                 // удалить всё

Метод Удалить() для отсутствующего ключа ошибку не вызывает — просто ничего не делает.

Шаг 6. Верните структуру из функции

Полный пример серверной функции, которая считает остаток и сообщает о проблеме:

&НаСервереБезКонтекста
Функция ПроверитьОстаток(Номенклатура, Склад, НужноКоличество)

    Результат = Новый Структура("Достаточно, Остаток, ТекстОшибки", Ложь, 0, "");

    Запрос = Новый Запрос;
    Запрос.Текст =
    "ВЫБРАТЬ
    |    ЕСТЬNULL(СУММА(Остатки.КоличествоОстаток), 0) КАК Остаток
    |ИЗ
    |    РегистрНакопления.ТоварыНаСкладах.Остатки(
    |        , Номенклатура = &Номенклатура И Склад = &Склад) КАК Остатки";
    Запрос.УстановитьПараметр("Номенклатура", Номенклатура);
    Запрос.УстановитьПараметр("Склад", Склад);

    Выборка = Запрос.Выполнить().Выбрать();
    Если Выборка.Следующий() Тогда
        Результат.Остаток = Выборка.Остаток;
    КонецЕсли;

    Результат.Достаточно = (Результат.Остаток >= НужноКоличество);
    Если Не Результат.Достаточно Тогда
        Результат.ТекстОшибки = СтрШаблон("Не хватает %1 ед.",
            Формат(НужноКоличество - Результат.Остаток, "ЧГ=0"));
    КонецЕсли;

    Возврат Результат;

КонецФункции

Имя регистра ТоварыНаСкладах и его ресурс — условные: подставьте те, что есть в вашей конфигурации. Агрегат СУММА нужен, потому что без указания характеристик и серий остатки могут прийти несколькими строками.

Проверьте себя
Как добавить в структуру новый ключ «Склад»?
Что вернёт обращение Стр.Цена, если ключа «Цена» в структуре нет?
Какой ключ структура не примет?

Ошибки при работе со структурой и как их избежать

«Поле объекта не обнаружено»

Самая частая ошибка. Текст в окне сообщений выглядит как Поле объекта не обнаружено (Склад). Причина — обращение через точку к ключу, которого в структуре нет: его забыли вставить, опечатались или структуру собрали в другой ветке кода.

Что делать:

  1. Проверьте написание ключа в месте создания и в месте чтения.
  2. Если ключ необязательный — читайте через Свойство().
  3. Если структура приходит из чужого кода, создайте её «с запасом» через конструктор со всеми ключами, а потом перенесите значения через ЗаполнитьЗначенияСвойств().

«Задано неправильное имя атрибута структуры»

Возникает при Вставить() или в конструкторе, если ключ не годится в идентификатор: начинается с цифры, содержит пробел, точку, дефис. Чаще всего ловится при разборе JSON и при формировании ключей из наименований номенклатуры.

Решение — либо очищать ключ до вставки, либо брать Соответствие, которому такие ключи не страшны.

Изменения «пропали» после вызова сервера

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

Внутри одной стороны (сервер → сервер) структура передаётся по ссылке: правка в вызываемой процедуре видна вызывающей. Это обратная ловушка: функция «просто прочитала параметры» и случайно их испортила.

Испорченный кэш в модуле с повторным использованием

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

Из модулей с повторным использованием возвращайте ФиксированнаяСтруктура, а не Структура. Тогда попытка изменить кэш сразу упадёт с ошибкой и не превратится в «плавающий» баг.

Возврат Новый ФиксированнаяСтруктура(Настройки);

Приёмы, которые ускоряют работу со структурами

Перенос значений одной строкой

Метод ЗаполнитьЗначенияСвойств(Приемник, Источник) копирует значения одноимённых полей. Работает между структурой, строкой таблицы значений, объектом документа, выборкой запроса.

Данные = Новый Структура("Дата, Номер, Организация, СуммаДокумента");
ЗаполнитьЗначенияСвойств(Данные, ДокументОбъект);

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

Третьим и четвёртым параметрами можно задать список свойств для переноса и список исключений — строками через запятую.

Отбор строк таблицы значений

Отбор = Новый Структура("Склад, Номенклатура", Склад, Номенклатура);
НайденныеСтроки = ТаблицаТоваров.НайтиСтроки(Отбор);

Ключи отбора должны совпадать с именами колонок. Для частых поисков по одним и тем же колонкам добавьте индекс: ТаблицаТоваров.Индексы.Добавить("Склад, Номенклатура").

Чтение реквизитов без получения объекта

В конфигурациях на БСП не открывайте объект ради пары полей. Функция ОбщегоНазначения.ЗначенияРеквизитовОбъекта() выполнит лёгкий запрос и вернёт структуру:

Реквизиты = ОбщегоНазначения.ЗначенияРеквизитовОбъекта(Договор, "Владелец, ВалютаВзаиморасчетов");
Контрагент = Реквизиты.Владелец;

Разбор JSON в структуру

ПрочитатьJSON() по умолчанию возвращает структуры для JSON-объектов. Это удобно, пока ключи — нормальные слова. Если в ответе сервиса встречаются ключи вроде "order-id" или "1c_code", чтение упадёт. Передайте вторым параметром Истина — тогда объекты станут соответствиями:

Чтение = Новый ЧтениеJSON;
Чтение.УстановитьСтроку(ТекстОтвета);
Данные = ПрочитатьJSON(Чтение, Истина);   // Соответствие вместо Структуры
Чтение.Закрыть();

Вложенные структуры вместо длинного списка ключей

Когда ключей становится больше десятка, разбейте их на группы. Читать Настройки.Печать.КоличествоКопий проще, чем Настройки.ПечатьКоличествоКопий среди тридцати соседей.

Настройки = Новый Структура;
Настройки.Вставить("Печать", Новый Структура("КоличествоКопий, Принтер", 1, ""));
Настройки.Вставить("Отбор", Новый Структура("Организация, Склад"));

Настройки.Печать.КоличествоКопий = 2;

Вложенную структуру можно поменять через точку, как обычную: Настройки.Печать возвращает ссылку на тот же экземпляр, а не копию. Добавить ключ во вложенную структуру можно только её собственным Вставить(): Настройки.Отбор.Вставить("Подразделение", Подразделение).

Держите создание всех ключей в одной функции-конструкторе, например НовыеНастройкиОбработки(). Тогда полный список полей виден в одном месте, а ошибка «Поле объекта не обнаружено» почти исчезает.

Структура в связке с другими механизмами 1С

Структура — базовый «клей» платформы, и её роль со временем только растёт: асинхронные методы, длительные операции и HTTP-сервисы в типовых конфигурациях обмениваются параметрами именно структурами.

Несколько связок, о которых полезно знать:

  • 📨 Параметры формы. Ключи из структуры, переданной в ОткрытьФорму(), становятся доступны в Параметры открываемой формы, если у формы есть параметры с такими именами. Ключи без одноимённого параметра формы не передаются — частая причина «параметр не дошёл».
  • 💾 Хранение в базе. Структуру можно сохранить в реквизит типа ХранилищеЗначения: Новый ХранилищеЗначения(Настройки). Обратно — методом Получить(). Внутри должны лежать только сериализуемые значения.
  • 🧾 Временное хранилище. Для передачи больших структур между клиентом и сервером положите их во временное хранилище через ПоместитьВоВременноеХранилище() и передавайте только адрес.
  • 🧩 Копирование. Новый Структура(ФиксированнаяСтруктура) и обход с Вставить() дают поверхностную копию: вложенные структуры и массивы останутся общими. Для полной копии в БСП есть ОбщегоНазначения.СкопироватьРекурсивно().

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

Можно ли отсортировать структуру по ключам?
Нет, методов сортировки у структуры нет. Перенесите пары в СписокЗначений или ТаблицаЗначений, отсортируйте там и при необходимости соберите новую структуру.
Как получить список всех ключей структуры?
Обойдите её циклом Для Каждого и соберите Элемент.Ключ в массив. Отдельного метода «Ключи» у структуры нет.
Можно ли сделать реквизит формы типа «Структура»?
Нет, такого типа в списке типов реквизитов формы нет. Используйте переменную модуля формы, временное хранилище или реквизиты обычных типов.
Чем «Новый Структура» отличается от «Новый Соответствие» по скорости?
Для небольшого числа ключей разница несущественна. Выбирайте по типу ключа: строковые имена — структура, ссылки и произвольные значения — соответствие.
Влияет ли регистр букв на поиск ключа?
Нет. Ключи Сумма, сумма и СУММА считаются одним ключом, как и любые идентификаторы во встроенном языке 1С.