Загрузка данных из внешних файлов, таких как Excel, является одной из самых частых задач для разработчика 1С. Начинающие программисты часто сталкиваются с ситуацией, когда данные из таблицы вроде бы считываются, но при попытке записать их в справочник возникают ошибки или поля остаются пустыми. Чаще всего это происходит из-за непонимания разницы между строковыми данными из файла и ссылочными типами данных в системе 1С.
В этой статье мы подробно разберем, как реализовать алгоритм загрузки, правильно найти существующие элементы, создать новые и корректно заполнить реквизиты различных типов: справочники и перечисления.
Проанализируем типичную ситуацию. У нас есть файл Excel с колонками: "Номенклатура", "Вид номенклатуры", "Единица измерения". При чтении файла 1С получает обычные строки. Однако реквизит ВидНоменклатуры в справочнике Номенклатура имеет тип СправочникСсылка.ВидыНоменклатуры. Если вы попытаетесь напрямую присвоить строку реквизиту ссылки, система либо выдаст ошибку, либо проигнорирует значение.
Рассмотрим ошибочный код, который часто пишут новички:
НовыйЭлемент.ВидНоменклатуры = Справочники.ВидыНоменклатуры.НайтиПоНаименованию(ИмяИзЭкскль).Наименование;
В данном примере метод НайтиПоНаименованию возвращает ссылку, но обращение через точку к свойству Наименование превращает её обратно в строку. В итоге вы пытаетесь записать текст там, где должна быть ссылка. Правильный подход — всегда получать и сохранять именно ссылку.
Прежде чем создавать новый элемент, хорошим тоном считается проверка: а нет ли уже такой номенклатуры в базе? Поиск лучше всего осуществлять по наименованию или артикулу. Разберем по шагам, как организовать цикл обхода загруженных из Excel данных (предположим, они уже находятся в Таблице Значений ЗагруженныеДанные).
Рассмотрим структуру цикла:
Для каждого СтрокаДанных Из ЗагруженныеДанные Цикл
// 1. Пытаемся найти существующий элемент
СсылкаНаНоменклатуру = Справочники.Номенклатура.НайтиПоНаименованию(СтрокаДанных.Номенклатура, Истина);
Если СсылкаНаНоменклатуру.Пустая() Тогда
// 2. Если не нашли, создаем новый объект
НовыйОбъект = Справочники.Номенклатура.СоздатьЭлемент();
НовыйОбъект.Наименование = СтрокаДанных.Номенклатура;
// Заполняем остальные реквизиты (об этом ниже)
// ...
НовыйОбъект.Записать();
ИнформационнаяСсылка = НовыйОбъект.Ссылка;
Иначе
// Если нашли, можем либо обновить данные, либо просто пропустить
ИнформационнаяСсылка = СсылкаНаНоменклатуру;
КонецЕсли;
КонецЦикла;
Выясним, как заполнять такие поля, как ВидНоменклатуры и ЕдиницаИзмерения. Для каждого из них нам нужно выполнить поиск в соответствующем справочнике. Если значение не найдено, его также можно создать программно или вывести ошибку пользователю.
Проанализируем пример заполнения реквизитов:
// Поиск вида номенклатуры
ВидНомСсылка = Справочники.ВидыНоменклатуры.НайтиПоНаименованию(СтрокаДанных.ВидНоменклатуры, Истина);
Если НЕ ВидНомСсылка.Пустая() Тогда
НовыйОбъект.ВидНоменклатуры = ВидНомСсылка;
КонецЕсли;
// Поиск единицы измерения в классификаторе
ЕдИзмСсылка = Справочники.КлассификаторЕдиницИзмерения.НайтиПоНаименованию(СтрокаДанных.ЕдиницаИзмерения, Истина);
Если НЕ ЕдИзмСсылка.Пустая() Тогда
НовыйОбъект.ЕдиницаИзмерения = ЕдИзмСсылка;
КонецЕсли;
Работа с перечислениями (например, СтавкаНДС) отличается от работы со справочниками. В перечислениях нельзя создать новый элемент программно, и у них нет метода НайтиПоНаименованию. Вам нужно четко сопоставить текст из Excel с конкретным значением перечисления в конфигурации.
Посмотрим на пример установки ставки НДС:
// Если в файле указано "20%", сопоставим это со значением перечисления
Если СтрокаДанных.СтавкаНДС = "20%" Тогда
НовыйОбъект.ВидСтавкиНДС = Перечисления.ВидыСтавокНДС.НДС20;
ИначеЕсли СтрокаДанных.СтавкаНДС = "Без НДС" Тогда
НовыйОбъект.ВидСтавкиНДС = Перечисления.ВидыСтавокНДС.БезНДС;
Иначе
// Значение по умолчанию
НовыйОбъект.ВидСтавкиНДС = Перечисления.ВидыСтавокНДС.Общая;
КонецЕсли;
Использование метода НайтиПоНаименованию внутри цикла — самый простой, но не самый быстрый способ. Если в вашем файле Excel 5000 строк, система сделает 5000 отдельных запросов к базе данных, что может занять много времени.
Рассмотрим профессиональный подход к оптимизации:
ОбменДанными.Загрузка = Истина. Это отключит лишние проверки в модулях объекта и подписках на события, что значительно ускорит процесс.Пример использования режима загрузки:
НовыйОбъект = Справочники.Номенклатура.СоздатьЭлемент();
НовыйОбъект.ОбменДанными.Загрузка = Истина; // Отключаем лишние проверки
НовыйОбъект.Наименование = СтрокаДанных.Номенклатура;
// ... заполнение ...
НовыйОбъект.Записать();
Подведем итог. Чтобы ваша обработка работала надежно, придерживайтесь следующей последовательности действий:
ТаблицуЗначений.НачатьТранзакцию().НайтиПоНаименованию (или поиск по коду/артикулу). Если перечисление — используйте логику Если...ИначеЕсли.ОбменДанными.Загрузка = Истина.ЗафиксироватьТранзакцию() после успешного завершения цикла.Следуя этим правилам, вы сможете избежать ошибок типизации и создадите эффективный инструмент для импорта данных, который будет понятен и вам, и вашим коллегам.