При разработке на платформе 1С:Предприятие 8.3 часто возникает задача преобразования данных из плоских списков или колонок таблицы в коллекцию типа "ключ-значение". На первый взгляд, использование объекта Структура кажется идеальным решением. Однако начинающие разработчики часто сталкиваются с системной ошибкой: "Задано неправильное имя атрибута структуры". Рассмотрим подробнее, почему это происходит, и как правильно реализовать заполнение структуры на основе массивов.
В языке 1С объект Структура имеет жесткое ограничение: его ключи должны соответствовать правилам написания идентификаторов. Проанализируем эти правила:
Когда мы пытаемся выполнить код Структура.Вставить(Строка(Массив1[Индекс]), Массив2[Индекс]), где в первом массиве хранятся годы (например, 2022), функция Строка() преобразует число по умолчанию с использованием региональных настроек. В результате число "2022" превращается в строку "2 022" (с неразрывным пробелом в качестве разделителя разрядов). Пробел является недопустимым символом для ключа структуры, что и вызывает ошибку.
Самый надежный способ использовать числовое значение в качестве ключа структуры — это преобразовать его в строку без разделителей групп разрядов. Посмотрим на пример кода, который решает эту задачу:
// Выгружаем данные из таблицы значений
Массив1 = Табл.ВыгрузитьКолонку("Год");
Массив2 = Табл.ВыгрузитьКолонку("Выходной");
СтруктураВыходные = Новый Структура();
Для Индекс = 0 По Массив1.Количество() - 1 Цикл
// Используем параметр "ЧГ=0", чтобы убрать группировку разрядов
КлючСтр = Формат(Массив1[Индекс], "ЧГ=0");
// Добавляем префикс, так как ключ не может начинаться с цифры
КлючСтр = "Год_" + КлючСтр;
СтруктураВыходные.Вставить(КлючСтр, Массив2[Индекс]);
КонецЦикла;
В данном примере мы применили Формат(Значение, "ЧГ=0"). Параметр ЧГ=0 (Число: Группировка = 0) гарантирует, что в строке не будет лишних пробелов, независимо от настроек сервера или операционной системы.
Если нам критически важно использовать именно числовые значения в качестве ключей (без префиксов типа "Год_") или если ключи могут содержать любые символы, нам следует рассмотреть объект Соответствие. Проанализируем ситуацию: в отличие от структуры, Соответствие позволяет использовать в качестве ключа значение любого типа.
Массив1 = Табл.ВыгрузитьКолонку("Год");
Массив2 = Табл.ВыгрузитьКолонку("Выходной");
// Создаем Соответствие вместо Структуры
ДанныеВыходных = Новый Соответствие();
Для Индекс = 0 По Массив1.Количество() - 1 Цикл
// Ключом будет само Число (год), преобразование в строку не требуется
ДанныеВыходных.Вставить(Массив1[Индекс], Массив2[Индекс]);
КонецЦикла;
// Получение значения также просто:
ВыходныеВ2022 = ДанныеВыходных.Получить(2022);
Важный момент: к свойствам Структуры можно обращаться через точку (Структура.ИмяКлюча), а к элементам Соответствия — только через метод Получить(Ключ) или через квадратные скобки. Если вы работаете с динамическими данными, Соответствие часто оказывается более гибким инструментом.
Иногда данные приходят уже в виде строк, содержащих скрытые символы. Выясним причину, почему обычный метод СтрЗаменить(Строка, " ", "") может не помочь. В 1С разделителем разрядов часто выступает не обычный пробел (код 32), а неразрывный пробел (код 160). Чтобы гарантированно очистить строку, используйте конструкцию:
// Очистка строки от неразрывных пробелов
ЧистаяСтрока = СтрЗаменить(СтрокаСПробелом, Символы.НПП, "");
// Дополнительно убираем обычные пробелы
ЧистаяСтрока = СтрЗаменить(ЧистаяСтрока, " ", "");
Это позволит подготовить строку к использованию в качестве идентификатора ключа, если вы всё же решили использовать Структуру.
Проанализируем еще один аспект: синхронность данных. В исходном вопросе автор выгружает две колонки в разные массивы. Рассмотрим риски: если таблица Табл между выгрузкой первой и второй колонки будет отсортирована или в ней изменятся данные в другом потоке, индексы массивов могут перестать соответствовать друг другу.
Безопаснее и эффективнее обходить таблицу значений напрямую в одном цикле, не создавая промежуточные массивы:
СтруктураВыходные = Новый Структура();
Для Каждого СтрокаТЗ Из Табл Цикл
// Сразу формируем правильный ключ из строки таблицы
Ключ = "Год" + Формат(СтрокаТЗ.Год, "ЧГ=0");
СтруктураВыходные.Вставить(Ключ, СтрокаТЗ.Выходной);
КонецЦикла;
Этот подход экономит память (мы не дублируем данные в массивах) и гарантирует, что год и количество выходных будут взяты из одной и той же строки таблицы.
Подведем итоги нашего разбора:
Строка() для чисел часто добавляет пробелы — используйте Формат(Число, "ЧГ=0").Символы.НПП) при обработке строковых данных.Выбирайте подходящий тип коллекции в зависимости от ваших задач, и ваш код будет работать стабильно и без ошибок!