Как изменить значение реквизита номенклатуры с типом Перечисление при загрузке из Excel

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

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

В этой статье мы подробно разберем, почему стандартные подходы к заполнению справочников не подходят для перечислений, проанализируем частые ошибки разработчиков и рассмотрим несколько надежных и производительных способов решения этой задачи на платформе 1С:Предприятие 8.3.

В чем главная сложность работы с Перечислениями в 1С?

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

При этом в файле Excel значение может быть записано в двух вариантах:

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

Разберем детально практические способы сопоставления и записи этих данных.

Способ 1. Прямое обращение по системному имени (быстрый способ)

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

Рассмотрим пример кода:


// Получаем текстовое значение из строки Excel
ИмяЗначенияИзФайла = СокрЛП(СтрЗначение.Значение);

Попытка
    // Прямое обращение к менеджеру перечисления по строковому ключу
    НовыйЭлемент.СостояниеТовара = Перечисления.СостояниеТовара[ИмяЗначенияИзФайла];
Исключение
    // Обрабатываем ситуацию, когда в Excel записано некорректное имя
    НовыйЭлемент.СостояниеТовара = ПредопределенноеЗначение("Перечисление.СостояниеТовара.ПустаяСсылка");
КонецПопытки;

Важное предупреждение: этот способ чрезвычайно чувствителен к регистру и символам. Если в Excel будет написано "В_пути" вместо "ВПути", система сгенерирует исключение, и выполнение кода перейдет в блок Исключение. Используйте этот метод только при полной уверенности в качестве загружаемого файла.

Способ 2. Сопоставление по Синонимам через метаданные (универсальный способ)

Чаще всего в файлах Excel содержатся именно пользовательские представления (синонимы), содержащие пробелы и буквы в разном регистре. Прямое обращение по индексу здесь вызовет ошибку. Чтобы решить эту проблему, мы можем перебрать все доступные значения перечисления в метаданных конфигурации и сравнить их синонимы с текстом из файла.

Разберем по шагам создание универсальной функции сопоставления:


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

Применение этой функции в цикле обработки строк Excel будет выглядеть следующим образом:


// Внутри цикла обхода строк файла Excel
ТекЗначениеExcel = СтрЗначение.Значение;
НайденнаяСсылка = ПолучитьЗначениеПеречисленияПоТексту("СостояниеТовара", ТекЗначениеExcel);

Если НайденнаяСсылка <> Неопределено Тогда
    НовыйЭлемент.СостояниеТовара = НайденнаяСсылка;
Иначе
    // Записываем пустую ссылку или выводим предупреждение в лог загрузки
    НовыйЭлемент.СостояниеТовара = Перечисления.СостояниеТовара.ПустаяСсылка();
    ОбщегоНазначенияКлиентСервер.СообщитьПользователю("Не удалось распознать состояние товара: " + ТекЗначениеExcel);
КонецЕсли;

Способ 3. Оптимальный метод для больших файлов Excel (кэширование через Запрос)

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

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

Посмотрим на пример реализации кэширования с использованием запроса:


// ЭТАП 1. Подготовка кэша перед началом цикла загрузки
КэшСостояний = Новый Соответствие;

Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |	СостояниеТовара.Ссылка КАК Ссылка,
    |	ПРЕДСТАВЛЕНИЕ(СостояниеТовара.Ссылка) КАК Представление
    |ИЗ
    |	Перечисление.СостояниеТовара КАК СостояниеТовара";

Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
    // Записываем представление в верхнем регистре в качестве ключа кэша
    КэшСостояний.Вставить(ВРег(Выборка.Представление), Выборка.Ссылка);
КонецЦикла;

// ЭТАП 2. Чтение файла Excel в цикле
Для Каждого СтрЗначение Из Значения Цикл
    
    // Получаем объект номенклатуры для изменения
    НоменклатураОбъект = Справочники.Номенклатура.НайтиПоНаименованию(СтрЗначение.НаименованиеНоменклатуры).ПолучитьОбъект();
    
    Если НоменклатураОбъект = Неопределено Тогда
        Продолжить; // Если номенклатура не найдена, переходим к следующей строке
    КонецЕсли;
    
    // Получаем строковое представление состояния из Excel
    СтрокаСостояния = ВРег(СокрЛП(СтрЗначение.Значение));
    
    // Поиск значения в кэше (происходит мгновенно в оперативной памяти)
    НайденноеСостояние = КэшСостояний.Получить(СтрокаСостояния);
    
    Если НайденноеСостояние <> Неопределено Тогда
        // Изменяем значение реквизита номенклатуры
        НоменклатураОбъект.СостояниеТовара = НайденноеСостояние;
        НоменклатураОбъект.Записать();
    Иначе
        // Обработка ошибок сопоставления
        Сообщить("Для товара " + НоменклатураОбъект.Наименование + " указано неизвестное состояние: " + СтрЗначение.Значение);
    КонецЕсли;
    
КонецЦикла;

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

Способ 4. Использование XML-сериализации

Если данные выгружаются из другой информационной базы 1С или файлы Excel формируются по строгим правилам XML-сериализации (где в качестве значений используются внутренние имена конфигурации), можно применить быстрый системный метод платформы XMLЗначение. Этот подход позволяет преобразовать строку в нужный тип в одну строчку кода:


Попытка
    // Преобразуем строковое имя значения непосредственно в ссылку перечисления
    НовыйЭлемент.СостояниеТовара = XMLЗначение(Тип("ПеречислениеСсылка.СостояниеТовара"), СтрЗначение.Значение);
Исключение
    // Обработка ошибки сопоставления типов
    НовыйЭлемент.СостояниеТовара = Неопределено;
КонецПопытки;

Использование стандартных инструментов 1С без программирования

Если вам требуется выполнить разовую загрузку данных и вы не хотите писать собственный программный код, обратите внимание на типовые возможности вашей конфигурации. В большинстве современных решений 1С (таких как Управление торговлей, ERP Управление предприятием, Комплексная автоматизация или Управление нашей фирмой) встроен стандартный механизм.

Вы можете воспользоваться обработкой «Загрузка данных из табличного документа». Этот инструмент позволяет:

Использование этого инструмента экономит время разработчика и исключает появление стандартных синтаксических ошибок при записи объектов.

← На главную