Как программно добавить реквизиты в 1С при импорте из Excel и почему возникает ошибка «Недопустимое значение параметра»?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При реализации механизмов импорта данных из внешних файлов (например, таблиц Excel) разработчики часто сталкиваются с необходимостью автоматического сопоставления колонок файла с реквизитами объектов в базе данных 1С. Типичный сценарий: считать шапку таблицы, проверить наличие соответствующих полей в справочнике и, если они отсутствуют, создать их. Однако при попытке реализовать это «в лоб» начинающие программисты часто совершают две критические ошибки: путают реквизиты формы с метаданными базы данных и нарушают правила именования идентификаторов в платформе 1С. Проанализируем эти ошибки, разберем причины сбоев и найдем правильные архитектурные решения.

Выясняем причину ошибки: Реквизиты формы vs Реквизиты базы данных

Рассмотрим исходный код, который привел к ошибке «Недопустимое значение параметра (параметр номер 1)»:


Если НЕ ЕстьРеквизитДокумента(ИмяБезПробелов, Метаданные.Справочники.Nomencaltura, "Артикул") Тогда
    Сообщить("Не найден реквизит с именем " + ИмяБезПробелов + "! Колонка не будет загружена!");
    ДобавляемыеРеквизиты = Новый Массив;
    МассивТипов = новый Массив;
    МассивТипов.Добавить(Тип("Строка"));
    Реквизит = Новый РеквизитФормы(ИмяБезПробелов, новый ОписаниеТипов(МассивТипов), , ИмяБезПробелов, Истина);
    ДобавляемыеРеквизиты.Добавить(Реквизит);
    ИзменитьРеквизиты(ДобавляемыеРеквизиты);
    Сообщить("Реквизит " + ИмяБезПробелов + " создан");
КонецЕсли;

В этом фрагменте кода кроется главное концептуальное заблуждение. Автор пытается использовать объект РеквизитФормы и метод управляемой формы ИзменитьРеквизиты() для того, чтобы расширить структуру справочника «Номенклатура» в базе данных. Давайте разберем по шагам, почему этот подход принципиально неработоспособен для решения поставленной задачи:

  1. Реквизиты формы (УФ) — это временные программные сущности, которые существуют исключительно в оперативной памяти текущего сеанса пользователя и только до тех пор, пока открыто окно конкретной формы. Метод ИзменитьРеквизиты() позволяет динамически выводить новые поля на экран, создавать программные элементы интерфейса (например, колонки в таблице на форме), но он абсолютно никак не влияет на структуру таблиц в СУБД. Как только пользователь закроет форму, все созданные динамические реквизиты будут стерты из памяти.
  2. Реквизиты базы данных (Метаданные) — это физические колонки в таблицах базы данных (MS SQL Server, PostgreSQL или файловой базы), где непосредственно сохраняются данные объектов. Платформа «1С:Предприятие 8» строго разделяет процессы разработки и выполнения. Изменять структуру метаданных (добавлять новые реквизиты в справочники) в режиме «1С:Предприятие» программно «на лету» невозможно. Любые изменения структуры данных должны выполняться разработчиком в режиме «Конфигуратор» или с помощью расширений конфигурации.

Таким образом, попытка записать данные из Excel в динамически созданный РеквизитФормы не приведет к сохранению данных в справочнике «Номенклатура» после закрытия обработки загрузки.

Анализ ограничений на имена идентификаторов в 1С

Вторая явная причина ошибки в коде автора — это некорректные имена колонок, считываемые из файла Excel. В примере фигурирует колонка с названием "Цена, руб.".

В платформе 1С существуют жесткие требования к именам переменных, реквизитов и любых объектов метаданных (так называемым идентификаторам). Имя должно соответствовать следующим правилам:

При попытке передать строку "Цена, руб." в конструктор Новый РеквизитФормы() в качестве первого параметра (Имя), платформа мгновенно генерирует исключение «Недопустимое значение параметра», так как запятая и пробел недопустимы в идентификаторе. То же самое произойдет с колонками вида "Ед. изм." или "Вес (кг)".

Для исправления этой проблемы перед использованием имени колонки в качестве идентификатора его необходимо нормализовать — удалить или заменить все запрещенные символы. Рассмотрим пример функции очистки строки:


Функция ОчиститьИмяКолонки(ИсходноеИмя) Экспорт
    // Убираем лишние пробелы по краям
    ИмяОчищенное = СокрЛП(ИсходноеИмя);
    
    // Заменяем популярные спецсимволы на подчеркивание
    ИмяОчищенное = СтрЗаменить(ИмяОчищенное, " ", "_");
    ИмяОчищенное = СтрЗаменить(ИмяОчищенное, ",", "_");
    ИмяОчищенное = СтрЗаменить(ИмяОчищенное, ".", "_");
    ИмяОчищенное = СтрЗаменить(ИмяОчищенное, "-", "_");
    ИмяОчищенное = СтрЗаменить(ИмяОчищенное, "(", "");
    ИмяОчищенное = СтрЗаменить(ИмяОчищенное, ")", "");
    ИмяОчищенное = СтрЗаменить(ИмяОчищенное, "/", "_");
    
    // Проверим, не начинается ли имя с цифры
    Если СтрДлина(ИмяОчищенное) > 0 Тогда
        ПервыйСимвол = Лев(ИмяОчищенное, 1);
        Если Найти("0123456789", ПервыйСимвол) > 0 Тогда
            ИмяОчищенное = "_" + ИмяОчищенное;
        КонецЕсли;
    КонецЕсли;
    
    Возврат ИмяОчищенное;
КонецФункции

При использовании этой функции строка "Цена, руб." превратится в валидный идентификатор Цена__руб_ (или Цена_руб после дополнительной очистки от двойных подчеркиваний), который платформа примет без ошибок.

Особая логика для реквизита «Группа»

В списке колонок автора присутствует поле «Группа». Попытка создать одноименный реквизит в справочнике приведет к конфликту.

В иерархических справочниках 1С (к которым относится и «Номенклатура») понятие группы является системным. Позиционирование элемента внутри определенной папки (группы) регулируется стандартным реквизитом Родитель.

Поэтому при импорте колонку «Группа» нужно обрабатывать отдельно: программа должна найти в справочнике группу с указанным именем (или создать ее, если папка не найдена) и записать ссылку на эту группу в реквизит Родитель загружаемой номенклатуры. Рассмотрим, как это можно реализовать программно:


Функция ПолучитьГруппуНоменклатуры(НаименованиеГруппы)
    Если ПустаяСтрока(НаименованиеГруппы) Тогда
        Возврат Справочники.Номенклатура.ПустаяСсылка();
    КонецЕсли;
    
    // Ищем группу по наименованию среди папок справочника
    НайденнаяГруппа = Справочники.Номенклатура.НайтиПоНаименованию(НаименованиеГруппы, Истина);
    
    Если НайденнаяГруппа.Пустая() Тогда
        // Если группа не найдена, создадим её программно
        НоваяГруппа = Справочники.Номенклатура.СоздатьГруппу();
        НоваяГруппа.Наименование = НаименованиеГруппы;
        НоваяГруппа.Записать();
        Возврат НоваяГруппа.Ссылка;
    Иначе
        Возврат НайденнаяГруппа;
    КонецЕсли;
КонецФункции

Правильное архитектурное решение: Дополнительные реквизиты (БСП)

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

Вместо изменения конфигурации мы можем программно создавать новые элементы в Плане видов характеристик ДополнительныеРеквизитыИСведения и привязывать их к набору свойств номенклатуры. При этом в самих элементах номенклатуры значения будут храниться в табличной части ДополнительныеРеквизиты.

Разберем по шагам, как реализовать этот алгоритм программно при загрузке из Excel.

Шаг 1. Программное создание дополнительного реквизита

Если колонка из Excel отсутствует в метаданных справочника и мы хотим создать для нее дополнительный реквизит, выполним следующий код:


Функция СоздатьДополнительныйРеквизит(ИмяСвойства, СинонимСвойства)
    // Шаг 1.1. Проверим, нет ли уже такого свойства в системе
    СвойствоСсылка = ПланыВидовХарактеристик.ДополнительныеРеквизитыИСведения.НайтиПоНаименованию(СинонимСвойства);
    
    Если НЕ СвойствоСсылка.Пустая() Тогда
        Возврат СвойствоСсылка; // Реквизит уже существует
    КонецЕсли;
    
    // Шаг 1.2. Создаем новое свойство
    НовоеСвойство = ПланыВидовХарактеристик.ДополнительныеРеквизитыИСведения.СоздатьЭлемент();
    НовоеСвойство.Наименование = СинонимСвойства;
    НовоеСвойство.Имя = ИмяСвойства;
    НовоеСвойство.Записать();
    
    // Шаг 1.3. Привязываем свойство к набору дополнительных реквизитов "Номенклатура"
    // Обычно имя набора совпадает с именем справочника или имеет предопределенное значение
    НаборСвойствСсылка = Справочники.НаборыДополнительныхРеквизитовИСведений.НайтиПоНаименованию("Номенклатура");
    
    Если НЕ НаборСвойствСсылка.Пустая() Тогда
        НаборОбъект = НаборСвойствСсылка.ПолучитьОбъект();
        
        // Проверяем, не входит ли свойство в набор
        СтрокаНабора = НаборОбъект.ДополнительныеРеквизиты.Найти(НовоеСвойство.Ссылка, "Свойство");
        Если СтрокаНабора = Неопределено Тогда
            НоваяСтрока = НаборОбъект.ДополнительныеРеквизиты.Добавить();
            НоваяСтрока.Свойство = НовоеСвойство.Ссылка;
            НаборОбъект.Записать();
        КонецЕсли;
    КонецЕсли;
    
    Возврат НовоеСвойство.Ссылка;
КонецФункции

Шаг 2. Запись значения дополнительного реквизита в Номенклатуру

При непосредственном создании новой карточки номенклатуры в цикле загрузки, мы записываем динамические данные в ее табличную часть:


Процедура ЗаполнитьДополнительныйРеквизитНоменклатуры(ОбъектНоменклатуры, СвойствоСсылка, ЗначениеСвойства)
    // Ищем строку с этим свойством в табличной части объекта номенклатуры
    СтрокаТЧ = ОбъектНоменклатуры.ДополнительныеРеквизиты.Найти(СвойствоСсылка, "Свойство");
    
    Если СтрокаТЧ = Неопределено Тогда
        СтрокаТЧ = ОбъектНоменклатуры.ДополнительныеРеквизиты.Добавить();
        СтрокаТЧ.Свойство = СвойствоСсылка;
    КонецЕсли;
    
    СтрокаТЧ.Значение = ЗначениеСвойства;
КонецПроцедуры

Резюмируем преимущества использования БСП:

  1. Вы не изменяете метаданные конфигурации, база данных остается типовой и легко обновляется.
  2. В дополнительных реквизитах допускаются любые символы в наименовании (например, "Цена, руб."), так как для пользователя это просто представление (синоним), а физически данные хранятся в стандартизированной табличной части.
  3. Данные надежно сохраняются в базе данных навсегда и доступны для вывода в отчеты, формы списков и печатные формы стандартными средствами 1С.
← На главную