1С массив в структуру: БСП, структуры и соответствия
Функции МассивВСтруктуру в БСП нет. Массив в структуру 1С переводит обычный
цикл с Вставить(), и это корректное решение: ключом структуры может быть только валидный
идентификатор — строка из букв, цифр и подчёркивания, начинающаяся не с цифры. Если элементы массива —
ссылки, числа или строки с пробелами и точками, нужна не структура, а Соответствие.
Что БСП действительно даёт для таких коллекций:
ОбщегоНазначенияКлиентСервер.ДополнитьСтруктуру() и ДополнитьСоответствие() —
слияние с управляемым поведением на пересечении ключей,
СвойствоСтруктуры() — чтение ключа со значением по умолчанию,
ОбщегоНазначения.СкопироватьРекурсивно() — глубокая копия вложенных коллекций.
1С массив в структуру: БСП-функции нет, есть корректный цикл
Запрос «массив в структуру 1с 8.3 бсп» подразумевает, что в общем модуле есть готовая обёртка. Её там нет:
в ОбщегоНазначенияКлиентСервер для массивов реализованы ДополнитьМассив()
и ЗначениеВМассиве(), но не преобразование в структуру. Причина техническая — у структуры
жёсткие требования к ключу, и универсальная функция «массив → структура» падала бы на большинстве данных.
Первый рабочий сценарий: массив содержит имена — реквизиты, поля, свойства. Тогда его элементы становятся ключами, а значения заполняются позже:
ИменаРеквизитов = Новый Массив;
ИменаРеквизитов.Добавить("Контрагент");
ИменаРеквизитов.Добавить("Договор");
ИменаРеквизитов.Добавить("Организация");
// Вариант 1: цикл. Вставить с одним аргументом кладёт Неопределено
СтруктураРеквизитов = Новый Структура;
Для Каждого ИмяРеквизита Из ИменаРеквизитов Цикл
СтруктураРеквизитов.Вставить(ИмяРеквизита);
КонецЦикла;
// Вариант 2: конструктор структуры принимает список ключей строкой
СтруктураРеквизитов = Новый Структура(СтрСоединить(ИменаРеквизитов, ","));
ЗаполнитьЗначенияСвойств(СтруктураРеквизитов, ДокументОбъект);
Второй сценарий встречается чаще: массив содержит строки таблицы значений, ссылки или структуры, и нужен быстрый доступ по ключу — то есть индекс. Здесь структура не подходит принципиально, потому что ключом должна стать ссылка или произвольная строка:
// Индекс строк товаров по номенклатуре: ключ — ссылка, значит Соответствие
ИндексПоНоменклатуре = Новый Соответствие;
Для Каждого СтрокаТовара Из Объект.Товары Цикл
ИндексПоНоменклатуре.Вставить(СтрокаТовара.Номенклатура, СтрокаТовара);
КонецЦикла;
// Свёртка количеств по номенклатуре в один проход
КоличествоПоНоменклатуре = Новый Соответствие;
Для Каждого СтрокаТовара Из Объект.Товары Цикл
Накоплено = КоличествоПоНоменклатуре[СтрокаТовара.Номенклатура];
КоличествоПоНоменклатуре.Вставить(СтрокаТовара.Номенклатура,
?(Накоплено = Неопределено, 0, Накоплено) + СтрокаТовара.Количество);
КонецЦикла;
В конфигурациях на базе БСП встречается прикладной аналог, но он не библиотечный:
ОбщегоНазначенияУТКлиентСервер.ПреобразоватьМассивВСтруктуруИлиСоответствие(ИсходныеДанные,
ПреобразовыватьВСтруктуру) в «Управлении торговлей» кладёт каждый элемент массива и в ключ,
и в значение. Это функция конфигурации, а не БСП: в типовой на другой платформе её не будет,
и переносить вызов «вслепую» нельзя.
Структура или соответствие: как выбрать под задачу
Выбор определяется типом ключа и тем, нужен ли доступ через точку. Короткая матрица решения:
-
Ключ — имя, известное на этапе разработки (реквизит, параметр, поле формы) →
Структура. Даёт записьПараметры.Организация, работает сЗаполнитьЗначенияСвойств(), передаётся в параметры формы и фоновых заданий. -
Ключ — данные (ссылка, число, дата, произвольная строка, УникальныйИдентификатор) →
Соответствие. Ключом может быть значение любого типа, обращение — только через квадратные скобки. -
Ключей много и они меняются в рантайме →
Соответствие: у структуры нет удобного «есть ли такой ключ» кромеСвойство(), и она хуже переносит динамику. -
Коллекцию нужно защитить от изменения →
ФиксированнаяСтруктураилиФиксированноеСоответствие; в них конвертируетСкопироватьРекурсивно()с параметромФиксироватьДанные = Истина.
Практический маркер ошибки: если при переводе массива в структуру приходится «чинить» ключ
через СтрЗаменить(Ключ, " ", "_") или добавлять префикс к числу — задача решается
соответствием, а не структурой.
1С БСП: получить значение по ключу — СвойствоСтруктуры
Прямое обращение Структура.Ключ к отсутствующему свойству бросает исключение, а связка
Свойство() + переменная занимает четыре строки. БСП сворачивает это в одну функцию —
это самый частый способ в БСП получить значение с подстраховкой:
// ОбщегоНазначенияКлиентСервер, строка 991
ДопустимоеОтклонение = ОбщегоНазначенияКлиентСервер.СвойствоСтруктуры(
ПараметрыОбработки, "ДопустимоеОтклонение", 0);
ТолькоПроверка = ОбщегоНазначенияКлиентСервер.СвойствоСтруктуры(
ПараметрыОбработки, "ТолькоПроверка", Ложь);
// Источник может быть и Неопределено — функция вернёт значение по умолчанию
Настройки = ОбщегоНазначенияКлиентСервер.СвойствоСтруктуры(
ДополнительныеПараметры, "Настройки");
Две детали, которые видны только в теле функции. Первая: Структура = Неопределено
обрабатывается штатно — вернётся значение по умолчанию, поэтому проверять источник перед вызовом
не нужно. Вторая: если ключ существует и хранит Неопределено, вернётся именно
Неопределено, а не значение по умолчанию — функция различает «нет ключа» и «пустое значение».
Третий аргумент вычисляется до вызова, поэтому в него передают только дешёвые значения: число, булево, пустую строку. Создание массива, соответствия или запрос к базе прямо в аргументе выполнится всегда, даже когда ключ на месте, — такую инициализацию выносят после проверки результата.
СвойствоСтруктуры с безопасными значениями по умолчанию.
Он выполнит код на вашей базе и покажет, каких ключей в реальных данных не оказалось, — это быстрее,
чем ловить «Поле объекта не обнаружено» в отладчике.
ДополнитьСтруктуру: слияние двух структур
Задача «наложить пользовательские параметры на значения по умолчанию» решается одной процедурой. Ключевой момент — третий параметр, который определяет поведение на пересечении ключей:
// ОбщегоНазначенияКлиентСервер, строка 643
ПараметрыПоУмолчанию = Новый Структура;
ПараметрыПоУмолчанию.Вставить("ПоказыватьПредупреждения", Истина);
ПараметрыПоУмолчанию.Вставить("РазмерПорции", 1000);
// Заменять = Истина: значения приемника перекрываются переданными
ОбщегоНазначенияКлиентСервер.ДополнитьСтруктуру(
ПараметрыПоУмолчанию, ПараметрыВызова, Истина);
// Заменять = Ложь: существующие ключи приемника сохраняются
ОбщегоНазначенияКлиентСервер.ДополнитьСтруктуру(
ПараметрыПоУмолчанию, ПараметрыВызова, Ложь);
Значение по умолчанию у Заменять — Неопределено, и это не
«молча дополнить». При совпадении ключа процедура выбрасывает исключение с текстом
«Пересечение ключей источника и приемника». Режим задуман как контроль: если коллекции обязаны быть
непересекающимися, вызов без третьего аргумента сам поймает конфликт вместо тихой потери данных.
Приемник изменяется по ссылке, функция ничего не возвращает. Вариант Заменять = Истина
самый быстрый — он не вызывает Свойство() для проверки, а сразу выполняет
Вставить(). Процедура доступна в клиент-серверном модуле, значит вызывается
и из клиентского кода, и с сервера.
ДополнитьСоответствие и его отличие по проверке ключа
Симметричная процедура для соответствий имеет ту же сигнатуру и ту же семантику третьего параметра,
но проверяет существование ключа иначе — сравнением значения с Неопределено:
// ОбщегоНазначенияКлиентСервер, строка 671
КешПоСсылкам = Новый Соответствие;
КешПоСсылкам.Вставить(НоменклатураСсылка, ДанныеНоменклатуры);
// Добавляем порцию, не затирая уже закешированное
ОбщегоНазначенияКлиентСервер.ДополнитьСоответствие(
КешПоСсылкам, НоваяПорцияДанных, Ложь);
Отсюда следует важное ограничение: ключ, у которого значение равно Неопределено,
считается отсутствующим. При Заменять = Ложь такой ключ всё равно будет перезаписан,
а при Заменять = Неопределено исключение о пересечении не возникнет. Если по семантике
вашего кеша Неопределено — это валидное значение («искали, не нашли»), храните вместо него
явный маркер: пустую ссылку, Ложь или структуру-обёртку.
СкопироватьРекурсивно: глубокое копирование коллекций
Структуры и соответствия — объектные значения: присваивание копирует ссылку, а не данные. Для вложенных коллекций (структура со структурами, соответствие с массивами) нужна глубокая копия:
// ОбщегоНазначения, строка 3186 (сервер)
// ОбщегоНазначенияКлиент, строка 507 (клиент)
КопияНастроек = ОбщегоНазначения.СкопироватьРекурсивно(Настройки);
КопияНастроек.Отборы.Вставить("Склад", СкладСсылка); // оригинал не затронут
// Зафиксировать результат целиком
ФиксированныеНастройки = ОбщегоНазначения.СкопироватьРекурсивно(Настройки, Истина);
// Снять фиксацию с ФиксированнойСтруктуры и вернуть изменяемую копию
ИзменяемыеНастройки = ОбщегоНазначения.СкопироватьРекурсивно(ФиксированныеНастройки, Ложь);
Функция рекурсивно обходит вложенные коллекции и копирует их по типу. Значения, которые не являются
коллекциями, переносятся как есть — в том числе объектные: СправочникОбъект,
ДокументОбъект и подобные не клонируются, в копии окажется ссылка
на тот же объект. Примитивы и ссылки при этом безопасны по своей природе.
Есть внутренний помощник СкопироватьСтруктуру(), но в актуальном контуре БСП он
неэкспортный (ОбщегоНазначения, строка 10184) и вызывается только из
СкопироватьРекурсивно(). В прикладном коде обращайтесь к
СкопироватьРекурсивно(): она сама определит тип источника и вернёт структуру,
соответствие, массив или таблицу значений.
КлючиСтруктурыВСтроку: перечень ключей одной строкой
Обратная операция к конструктору Новый Структура("А,Б,В"). Нужна там, где список полей
передаётся строкой: в ЗаполнитьЗначенияСвойств(), в поля запроса, в диагностику:
// ОбщегоНазначенияКлиентСервер, строка 963
Реквизиты = Новый Структура("Контрагент, Договор, Организация");
СписокПолей = ОбщегоНазначенияКлиентСервер.КлючиСтруктурыВСтроку(Реквизиты);
// "Контрагент,Договор,Организация"
// Скопировать в объект только те свойства, что есть в структуре
ЗаполнитьЗначенияСвойств(ДокументОбъект, Реквизиты, СписокПолей);
// Свой разделитель — для сообщений пользователю
Перечень = ОбщегоНазначенияКлиентСервер.КлючиСтруктурыВСтроку(Реквизиты, ", ");
Разделитель по умолчанию — "," именно без пробела, что удобно для машинного разбора
и годится для конструктора структуры. Для текста, который увидит пользователь, передавайте
", " вторым аргументом. Порядок ключей в результате — порядок обхода структуры,
то есть порядок вставки; на него не стоит опираться как на контракт.
ЕстьРеквизитИлиСвойствоОбъекта: проверка без метаданных
Когда на вход приходит «что-то с полями» — объект, форма, ДанныеФормыСтруктура, строка
таблицы значений — обращение к метаданным либо дорого, либо невозможно. БСП решает это трюком
с уникальным маркером:
// ОбщегоНазначенияКлиентСервер, строка 766
Если ОбщегоНазначенияКлиентСервер.ЕстьРеквизитИлиСвойствоОбъекта(Объект, "Комментарий") Тогда
Объект.Комментарий = ТекстКомментария;
КонецЕсли;
// Работает и на форме, и на произвольной структуре параметров
Если ОбщегоНазначенияКлиентСервер.ЕстьРеквизитИлиСвойствоОбъекта(Форма, "АдресВоВременномХранилище") Тогда
Адрес = Форма.АдресВоВременномХранилище;
КонецЕсли;
Внутри создаётся структура с одним ключом и значением Новый УникальныйИдентификатор,
затем вызывается ЗаполнитьЗначенияСвойств(). Если у объекта такое свойство есть,
маркер затирается его значением; если нет — остаётся на месте. Ложных срабатываний быть не может:
совпасть со свежесозданным УникальныйИдентификатор реальное значение не способно.
Ограничение вытекает из реализации: ИмяРеквизита должно быть допустимым ключом структуры.
Составной путь вида "Товары.Номенклатура" не поддерживается — проверяйте по одному уровню.
Для обычной структуры функция избыточна: там достаточно штатного Свойство().
Частые ошибки при работе со структурами и соответствиями
-
Поиск несуществующей функции БСП.
МассивВСтруктуру,СтруктураИзМассиваи подобных обёрток в общих модулях БСП нет. Преобразование пишется циклом сВставить(); найденная в типовойПреобразоватьМассивВСтруктуруИлиСоответствие— код конфигурации УТ, а не библиотеки. -
Ссылка или число в ключе структуры. Ключ структуры — идентификатор, а не любое
значение. Попытка положить туда
СправочникСсылкаили строку с пробелом даст ошибку либо неработоспособный ключ. НуженСоответствие. -
Вызов ДополнитьСтруктуру без третьего параметра на пересекающихся данных.
Значение по умолчанию
Неопределеноозначает исключение при совпадении ключей, а не тихое слияние. ЗадавайтеИстинаилиЛожьосознанно. -
Значение Неопределено в соответствии.
ДополнитьСоответствие()считает такой ключ отсутствующим и перезапишет его даже приЗаменять = Ложь. Для «пустого, но существующего» значения используйте явный маркер. -
Присваивание вместо копирования.
НоваяСтруктура = СтараяСтруктуракопирует ссылку — правки видны в обоих местах. Для независимой копии вложенной коллекции нуженСкопироватьРекурсивно(). -
Ожидание клонирования объектов.
СкопироватьРекурсивно()копирует коллекции, но значения объектных типов переносит по ссылке. ИзменениеДокументОбъектвнутри «копии» затронет оригинал. - Тяжёлое значение по умолчанию в СвойствоСтруктуры. Третий аргумент вычисляется всегда, даже когда ключ есть. Запрос к базе или создание объекта в этом месте — лишняя работа на каждом вызове.
-
Устаревшие копирующие обёртки. В
ОбщегоНазначенияКлиентСерверфункцииСкопироватьРекурсивно()(строка 3264) иСкопироватьСтруктуру()(строка 3302) помечены как устаревшие. В новом коде вызывайтеОбщегоНазначения.СкопироватьРекурсивно()на сервере иОбщегоНазначенияКлиент.СкопироватьРекурсивно()на клиенте.
Частые вопросы о структурах и соответствиях в БСП
Есть ли в БСП готовая функция МассивВСтруктуру?
Нет. В общих модулях БСП такой функции не существует, преобразование пишется циклом
с Вставить(). Ограничение осмысленное: ключом структуры может быть только
валидный идентификатор, поэтому массив ссылок или произвольных строк в структуру не переводится —
для него нужно Соответствие.
Почему ДополнитьСтруктуру выбрасывает исключение о пересечении ключей?
Потому что третий параметр Заменять не задан. По умолчанию он равен
Неопределено, и это режим контроля: при совпадении ключей источника и приемника
процедура прерывает выполнение. Передайте Истина, чтобы перезаписывать значения
приемника, или Ложь, чтобы пропускать уже существующие ключи.
Как в БСП получить значение из структуры, если ключа может не быть?
Через ОбщегоНазначенияКлиентСервер.СвойствоСтруктуры(Структура, Ключ, ЗначениеПоУмолчанию).
Функция возвращает значение по умолчанию, если ключа нет или сам источник равен
Неопределено. Существующий ключ со значением Неопределено вернёт
Неопределено, а не значение по умолчанию.
ИИ Консоль кода 1С
Лайт
Для ознакомления с возможностями
- Полный набор инструментов без урезаний
- Без ввода карты
Старт
Для индивидуального использования
- До 5 конфигураций
- Встроенный агент запросов 1С
-
≈ 100 задач Подробнее про лимиты
- Техническая поддержка
Продвинутый
Популярный выборДля интенсивного использования или команд
- До 15 конфигураций
- Встроенный агент запросов 1С
-
≈ 300 задач Подробнее про лимиты
-
Свои подписки Codex, Claude и любые OpenAI-совместимые
-
Внешние обработки без Конфигуратора
- Приоритетная техническая поддержка