БСП в 1С

1С массив в структуру: БСП, структуры и соответствия

Коротко

Функции МассивВСтруктуру в БСП нет. Массив в структуру 1С переводит обычный цикл с Вставить(), и это корректное решение: ключом структуры может быть только валидный идентификатор — строка из букв, цифр и подчёркивания, начинающаяся не с цифры. Если элементы массива — ссылки, числа или строки с пробелами и точками, нужна не структура, а Соответствие.

Что БСП действительно даёт для таких коллекций: ОбщегоНазначенияКлиентСервер.ДополнитьСтруктуру() и ДополнитьСоответствие() — слияние с управляемым поведением на пересечении ключей, СвойствоСтруктуры() — чтение ключа со значением по умолчанию, ОбщегоНазначения.СкопироватьРекурсивно() — глубокая копия вложенных коллекций.

1С массив в структуру: БСП-функции нет, есть корректный цикл

Запрос «массив в структуру 1с 8.3 бсп» подразумевает, что в общем модуле есть готовая обёртка. Её там нет: в ОбщегоНазначенияКлиентСервер для массивов реализованы ДополнитьМассив() и ЗначениеВМассиве(), но не преобразование в структуру. Причина техническая — у структуры жёсткие требования к ключу, и универсальная функция «массив → структура» падала бы на большинстве данных.

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

ИменаРеквизитов = Новый Массив;
ИменаРеквизитов.Добавить("Контрагент");
ИменаРеквизитов.Добавить("Договор");
ИменаРеквизитов.Добавить("Организация");

// Вариант 1: цикл. Вставить с одним аргументом кладёт Неопределено
СтруктураРеквизитов = Новый Структура;
Для Каждого ИмяРеквизита Из ИменаРеквизитов Цикл
    СтруктураРеквизитов.Вставить(ИмяРеквизита);
КонецЦикла;

// Вариант 2: конструктор структуры принимает список ключей строкой
СтруктураРеквизитов = Новый Структура(СтрСоединить(ИменаРеквизитов, ","));

ЗаполнитьЗначенияСвойств(СтруктураРеквизитов, ДокументОбъект);
Структура.Вставить
Ключимя свойства: буквы, цифры, подчёркивание; не с цифры
Значениеесли не задано — Неопределено

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

// Индекс строк товаров по номенклатуре: ключ — ссылка, значит Соответствие
ИндексПоНоменклатуре = Новый Соответствие;
Для Каждого СтрокаТовара Из Объект.Товары Цикл
    ИндексПоНоменклатуре.Вставить(СтрокаТовара.Номенклатура, СтрокаТовара);
КонецЦикла;

// Свёртка количеств по номенклатуре в один проход
КоличествоПоНоменклатуре = Новый Соответствие;
Для Каждого СтрокаТовара Из Объект.Товары Цикл
    Накоплено = КоличествоПоНоменклатуре[СтрокаТовара.Номенклатура];
    КоличествоПоНоменклатуре.Вставить(СтрокаТовара.Номенклатура,
        ?(Накоплено = Неопределено, 0, Накоплено) + СтрокаТовара.Количество);
КонецЦикла;
Соответствие.Вставить
Ключзначение любого типа, включая ссылку
Значениепроизвольное значение

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

Структура или соответствие: как выбрать под задачу

Выбор определяется типом ключа и тем, нужен ли доступ через точку. Короткая матрица решения:

  • Ключ — имя, известное на этапе разработки (реквизит, параметр, поле формы) → Структура. Даёт запись Параметры.Организация, работает с ЗаполнитьЗначенияСвойств(), передаётся в параметры формы и фоновых заданий.
  • Ключ — данные (ссылка, число, дата, произвольная строка, УникальныйИдентификатор) → Соответствие. Ключом может быть значение любого типа, обращение — только через квадратные скобки.
  • Ключей много и они меняются в рантаймеСоответствие: у структуры нет удобного «есть ли такой ключ» кроме Свойство(), и она хуже переносит динамику.
  • Коллекцию нужно защитить от измененияФиксированнаяСтруктура или ФиксированноеСоответствие; в них конвертирует СкопироватьРекурсивно() с параметром ФиксироватьДанные = Истина.

Практический маркер ошибки: если при переводе массива в структуру приходится «чинить» ключ через СтрЗаменить(Ключ, " ", "_") или добавлять префикс к числу — задача решается соответствием, а не структурой.

1С БСП: получить значение по ключу — СвойствоСтруктуры

Прямое обращение Структура.Ключ к отсутствующему свойству бросает исключение, а связка Свойство() + переменная занимает четыре строки. БСП сворачивает это в одну функцию — это самый частый способ в БСП получить значение с подстраховкой:

// ОбщегоНазначенияКлиентСервер, строка 991
ДопустимоеОтклонение = ОбщегоНазначенияКлиентСервер.СвойствоСтруктуры(
    ПараметрыОбработки, "ДопустимоеОтклонение", 0);

ТолькоПроверка = ОбщегоНазначенияКлиентСервер.СвойствоСтруктуры(
    ПараметрыОбработки, "ТолькоПроверка", Ложь);

// Источник может быть и Неопределено — функция вернёт значение по умолчанию
Настройки = ОбщегоНазначенияКлиентСервер.СвойствоСтруктуры(
    ДополнительныеПараметры, "Настройки");
СвойствоСтруктуры
СтруктураСтруктура или ФиксированнаяСтруктура; допускается Неопределено
Ключимя читаемого свойства
ЗначениеПоУмолчаниюрезультат при отсутствии ключа; по умолчанию Неопределено
Произвольный

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

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

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

ДополнитьСтруктуру: слияние двух структур

Задача «наложить пользовательские параметры на значения по умолчанию» решается одной процедурой. Ключевой момент — третий параметр, который определяет поведение на пересечении ключей:

// ОбщегоНазначенияКлиентСервер, строка 643
ПараметрыПоУмолчанию = Новый Структура;
ПараметрыПоУмолчанию.Вставить("ПоказыватьПредупреждения", Истина);
ПараметрыПоУмолчанию.Вставить("РазмерПорции", 1000);

// Заменять = Истина: значения приемника перекрываются переданными
ОбщегоНазначенияКлиентСервер.ДополнитьСтруктуру(
    ПараметрыПоУмолчанию, ПараметрыВызова, Истина);

// Заменять = Ложь: существующие ключи приемника сохраняются
ОбщегоНазначенияКлиентСервер.ДополнитьСтруктуру(
    ПараметрыПоУмолчанию, ПараметрыВызова, Ложь);
ДополнитьСтруктуру
Приемникструктура, которая изменяется на месте
Источникструктура, откуда берутся пары ключ и значение
ЗаменятьИстина — перезаписывать, Ложь — пропускать, Неопределено (по умолчанию) — исключение при пересечении

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

Приемник изменяется по ссылке, функция ничего не возвращает. Вариант Заменять = Истина самый быстрый — он не вызывает Свойство() для проверки, а сразу выполняет Вставить(). Процедура доступна в клиент-серверном модуле, значит вызывается и из клиентского кода, и с сервера.

ДополнитьСоответствие и его отличие по проверке ключа

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

// ОбщегоНазначенияКлиентСервер, строка 671
КешПоСсылкам = Новый Соответствие;
КешПоСсылкам.Вставить(НоменклатураСсылка, ДанныеНоменклатуры);

// Добавляем порцию, не затирая уже закешированное
ОбщегоНазначенияКлиентСервер.ДополнитьСоответствие(
    КешПоСсылкам, НоваяПорцияДанных, Ложь);
ДополнитьСоответствие
Приемниксоответствие, изменяется на месте
Источниксоответствие из КлючИЗначение
ЗаменятьИстина — перезаписывать, Ложь — пропускать, Неопределено (по умолчанию) — исключение при пересечении

Отсюда следует важное ограничение: ключ, у которого значение равно Неопределено, считается отсутствующим. При Заменять = Ложь такой ключ всё равно будет перезаписан, а при Заменять = Неопределено исключение о пересечении не возникнет. Если по семантике вашего кеша Неопределено — это валидное значение («искали, не нашли»), храните вместо него явный маркер: пустую ссылку, Ложь или структуру-обёртку.

СкопироватьРекурсивно: глубокое копирование коллекций

Структуры и соответствия — объектные значения: присваивание копирует ссылку, а не данные. Для вложенных коллекций (структура со структурами, соответствие с массивами) нужна глубокая копия:

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

// Зафиксировать результат целиком
ФиксированныеНастройки = ОбщегоНазначения.СкопироватьРекурсивно(Настройки, Истина);

// Снять фиксацию с ФиксированнойСтруктуры и вернуть изменяемую копию
ИзменяемыеНастройки = ОбщегоНазначения.СкопироватьРекурсивно(ФиксированныеНастройки, Ложь);
СкопироватьРекурсивно
ИсточникСтруктура, Соответствие, Массив, их фиксированные варианты, СписокЗначений, ТаблицаЗначений, ДеревоЗначений
ФиксироватьДанныеИстина — фиксировать, Ложь — снять фиксацию, Неопределено (по умолчанию) — не изменять
копия источника того же или фиксированного типа

Функция рекурсивно обходит вложенные коллекции и копирует их по типу. Значения, которые не являются коллекциями, переносятся как есть — в том числе объектные: СправочникОбъект, ДокументОбъект и подобные не клонируются, в копии окажется ссылка на тот же объект. Примитивы и ссылки при этом безопасны по своей природе.

Есть внутренний помощник СкопироватьСтруктуру(), но в актуальном контуре БСП он неэкспортный (ОбщегоНазначения, строка 10184) и вызывается только из СкопироватьРекурсивно(). В прикладном коде обращайтесь к СкопироватьРекурсивно(): она сама определит тип источника и вернёт структуру, соответствие, массив или таблицу значений.

КлючиСтруктурыВСтроку: перечень ключей одной строкой

Обратная операция к конструктору Новый Структура("А,Б,В"). Нужна там, где список полей передаётся строкой: в ЗаполнитьЗначенияСвойств(), в поля запроса, в диагностику:

// ОбщегоНазначенияКлиентСервер, строка 963
Реквизиты = Новый Структура("Контрагент, Договор, Организация");

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

// Скопировать в объект только те свойства, что есть в структуре
ЗаполнитьЗначенияСвойств(ДокументОбъект, Реквизиты, СписокПолей);

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

Разделитель по умолчанию — "," именно без пробела, что удобно для машинного разбора и годится для конструктора структуры. Для текста, который увидит пользователь, передавайте ", " вторым аргументом. Порядок ключей в результате — порядок обхода структуры, то есть порядок вставки; на него не стоит опираться как на контракт.

ЕстьРеквизитИлиСвойствоОбъекта: проверка без метаданных

Когда на вход приходит «что-то с полями» — объект, форма, ДанныеФормыСтруктура, строка таблицы значений — обращение к метаданным либо дорого, либо невозможно. БСП решает это трюком с уникальным маркером:

// ОбщегоНазначенияКлиентСервер, строка 766
Если ОбщегоНазначенияКлиентСервер.ЕстьРеквизитИлиСвойствоОбъекта(Объект, "Комментарий") Тогда
    Объект.Комментарий = ТекстКомментария;
КонецЕсли;

// Работает и на форме, и на произвольной структуре параметров
Если ОбщегоНазначенияКлиентСервер.ЕстьРеквизитИлиСвойствоОбъекта(Форма, "АдресВоВременномХранилище") Тогда
    Адрес = Форма.АдресВоВременномХранилище;
КонецЕсли;
ЕстьРеквизитИлиСвойствоОбъекта
Объектпроизвольный объект с реквизитами или свойствами
ИмяРеквизитаимя проверяемого реквизита или свойства
Булево

Внутри создаётся структура с одним ключом и значением Новый УникальныйИдентификатор, затем вызывается ЗаполнитьЗначенияСвойств(). Если у объекта такое свойство есть, маркер затирается его значением; если нет — остаётся на месте. Ложных срабатываний быть не может: совпасть со свежесозданным УникальныйИдентификатор реальное значение не способно.

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

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

Частые ошибки при работе со структурами и соответствиями

  • Поиск несуществующей функции БСП. МассивВСтруктуру, СтруктураИзМассива и подобных обёрток в общих модулях БСП нет. Преобразование пишется циклом с Вставить(); найденная в типовой ПреобразоватьМассивВСтруктуруИлиСоответствие — код конфигурации УТ, а не библиотеки.
  • Ссылка или число в ключе структуры. Ключ структуры — идентификатор, а не любое значение. Попытка положить туда СправочникСсылка или строку с пробелом даст ошибку либо неработоспособный ключ. Нужен Соответствие.
  • Вызов ДополнитьСтруктуру без третьего параметра на пересекающихся данных. Значение по умолчанию Неопределено означает исключение при совпадении ключей, а не тихое слияние. Задавайте Истина или Ложь осознанно.
  • Значение Неопределено в соответствии. ДополнитьСоответствие() считает такой ключ отсутствующим и перезапишет его даже при Заменять = Ложь. Для «пустого, но существующего» значения используйте явный маркер.
  • Присваивание вместо копирования. НоваяСтруктура = СтараяСтруктура копирует ссылку — правки видны в обоих местах. Для независимой копии вложенной коллекции нужен СкопироватьРекурсивно().
  • Ожидание клонирования объектов. СкопироватьРекурсивно() копирует коллекции, но значения объектных типов переносит по ссылке. Изменение ДокументОбъект внутри «копии» затронет оригинал.
  • Тяжёлое значение по умолчанию в СвойствоСтруктуры. Третий аргумент вычисляется всегда, даже когда ключ есть. Запрос к базе или создание объекта в этом месте — лишняя работа на каждом вызове.
  • Устаревшие копирующие обёртки. В ОбщегоНазначенияКлиентСервер функции СкопироватьРекурсивно() (строка 3264) и СкопироватьСтруктуру() (строка 3302) помечены как устаревшие. В новом коде вызывайте ОбщегоНазначения.СкопироватьРекурсивно() на сервере и ОбщегоНазначенияКлиент.СкопироватьРекурсивно() на клиенте.

Частые вопросы о структурах и соответствиях в БСП

Есть ли в БСП готовая функция МассивВСтруктуру?

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

Почему ДополнитьСтруктуру выбрасывает исключение о пересечении ключей?

Потому что третий параметр Заменять не задан. По умолчанию он равен Неопределено, и это режим контроля: при совпадении ключей источника и приемника процедура прерывает выполнение. Передайте Истина, чтобы перезаписывать значения приемника, или Ложь, чтобы пропускать уже существующие ключи.

Как в БСП получить значение из структуры, если ключа может не быть?

Через ОбщегоНазначенияКлиентСервер.СвойствоСтруктуры(Структура, Ключ, ЗначениеПоУмолчанию). Функция возвращает значение по умолчанию, если ключа нет или сам источник равен Неопределено. Существующий ключ со значением Неопределено вернёт Неопределено, а не значение по умолчанию.

Тарифы

ИИ Консоль кода 1С

Лайт

Бесплатно
≈ 1,5 млн токенов

Для ознакомления с возможностями

  • Все функции бесплатно на 2 дня +2 дня за подписку на Telegram или Max
  • Полный набор инструментов без урезаний
  • Без ввода карты
Начать бесплатно

Старт

1990 руб. в месяц
≈ 10 млн токенов

Для индивидуального использования

Выбрать тариф

Продвинутый

Популярный выбор
3990 руб. в месяц
≈ 25 млн токенов

Для интенсивного использования или команд

  • До 15 конфигураций
  • Встроенный агент запросов 1С
  • Свои подписки Codex, Claude и любые OpenAI-совместимые
  • Внешние обработки без Конфигуратора
  • Приоритетная техническая поддержка
Выбрать тариф