Загрузка xlsx в 1С 8.3 кодом: от ТабличныйДокумент.Прочитать() до драйвера ACE
Содержание
Чтобы прочитать Excel файл в 1С 8.3, проще всего создать Новый ТабличныйДокумент и вызвать у него метод Прочитать(ИмяФайла): платформа сама откроет xls или xlsx, и дальше вы обходите ячейки по номерам строк и колонок. Excel на компьютере для этого не нужен. COM-объект Excel.Application и драйвер ADO нужны в особых случаях: когда важен конкретный лист, нужна выборка SQL-запросом или программа работает на старой платформе.
Типичная боль — прайс поставщика на 5000 строк, который вручную переносить день. Ниже разобраны три способа с рабочим кодом, приведение типов, ускорение массовой загрузки и ошибки, на которых обычно спотыкаются.
Какой метод чтения Excel выбрать и что подготовить
Начните с вопроса: где выполняется код и что установлено на этой машине. В клиент-серверной базе код на сервере работает под пользователем службы 1С, и Excel там обычно нет.
| Способ | Нужен Excel | Нужны драйверы | Где работает | Когда брать |
|---|---|---|---|---|
ТабличныйДокумент.Прочитать() | нет | нет | сервер, толстый клиент, Windows и Linux | почти всегда |
COM Excel.Application | да | нет | только Windows | нужен конкретный лист, формулы, форматирование |
| ADO + провайдер ACE/Jet | нет | Access Database Engine | только Windows | SQL-выборка по листу, большие плоские таблицы |
| Типовая обработка загрузки | нет | нет | интерактивно | разовая загрузка без программирования |
Подготовка перед любым способом:
- 📄 закройте файл в Excel — открытая книга блокируется, и чтение падает;
- 🧹 уберите из шапки объединённые ячейки или запомните, с какой строки идут данные;
- 🔢 проверьте, что числа в файле — числа, а не текст с пробелами;
- 🖥 узнайте разрядность клиента и сервера 1С (32 или 64 бита) — это важно для COM и ADO.
Если загрузка разовая, сначала проверьте типовой механизм. В БСП-конфигурациях (БП 3.0, УТ 11, ЗУП 3.1) у ряда списков и табличных частей есть команда загрузки из файла: вы вставляете таблицу из Excel и сопоставляете колонки с реквизитами. Код писать не придётся.
Чтение Excel файла как табличного документа
Это родной механизм платформы. Метод Прочитать понимает форматы xls, xlsx, mxl и ods. Он доступен на сервере, в толстом клиенте и во внешнем соединении. В тонком и веб-клиенте его нет, поэтому файл сначала передают на сервер.
Шаг 1. Передать файл с клиента на сервер
&НаКлиенте
Процедура ЗагрузитьИзExcel(Команда)
Оповещение = Новый ОписаниеОповещения("ПослеПомещенияФайла", ЭтотОбъект);
НачатьПомещениеФайла(Оповещение, , , Истина, УникальныйИдентификатор);
КонецПроцедуры
&НаКлиенте
Процедура ПослеПомещенияФайла(Результат, Адрес, ВыбранноеИмяФайла, ДополнительныеПараметры) Экспорт
Если Не Результат Тогда
Возврат;
КонецЕсли;
Расширение = Сред(Новый Файл(ВыбранноеИмяФайла).Расширение, 2); // ".xlsx" -> "xlsx"
ЗагрузитьНаСервере(Адрес, Расширение);
КонецПроцедуры
На платформе 8.3.18 и выше есть более новый метод НачатьПомещениеФайлаНаСервер, но приведённый вариант тоже работает.
Шаг 2. Прочитать файл на сервере
&НаСервере
Процедура ЗагрузитьНаСервере(Адрес, Расширение)
ДвоичныеДанные = ПолучитьИзВременногоХранилища(Адрес);
ИмяФайла = ПолучитьИмяВременногоФайла(Расширение);
ДвоичныеДанные.Записать(ИмяФайла);
ТабДок = Новый ТабличныйДокумент;
ТабДок.Прочитать(ИмяФайла, СпособЧтенияЗначенийТабличногоДокумента.Текст);
УдалитьФайлы(ИмяФайла);
ПерваяСтрокаДанных = 2; // строка 1 — шапка
Для НомерСтроки = ПерваяСтрокаДанных По ТабДок.ВысотаТаблицы Цикл
Артикул = СокрЛП(ТабДок.Область(НомерСтроки, 1, НомерСтроки, 1).Текст);
Наименование = СокрЛП(ТабДок.Область(НомерСтроки, 2, НомерСтроки, 2).Текст);
ЦенаТекстом = ТабДок.Область(НомерСтроки, 3, НомерСтроки, 3).Текст;
Если ПустаяСтрока(Артикул) Тогда
Продолжить;
КонецЕсли;
НоваяСтрока = Объект.Товары.Добавить();
НоваяСтрока.Артикул = Артикул;
НоваяСтрока.Наименование = Наименование;
НоваяСтрока.Цена = ПривестиКЧислу(ЦенаТекстом);
КонецЦикла;
КонецПроцедуры
ВысотаТаблицы и ШиринаТаблицы дают размер заполненной области. Ячейку удобно получать через Область(Верх, Лево, Низ, Право) с одинаковыми номерами — так не нужно собирать строку вида R2C3.
Два режима чтения значений
Второй параметр Прочитать задаёт, что попадёт в ячейки:
- 🔤
СпособЧтенияЗначенийТабличногоДокумента.Текст— всё как строки, в том виде, как видно в Excel. Предсказуемо, но числа и даты надо разбирать самому. - 🔢
СпособЧтенияЗначенийТабличногоДокумента.Значение— платформа пытается сохранить типы. У области ячейки тогда смотрят свойстваСодержитЗначениеиЗначение.
Для загрузки прайсов и остатков режим «Текст» надёжнее: вы сами контролируете разбор и сразу видите мусор в данных.
Внешняя обработка вместо доработки конфигурации
Чтобы не трогать типовую конфигурацию
, код выносят во внешнюю обработку
(.epf). Форма с полем табличного документа даёт ещё один приём: пользователь открывает файл, видит его прямо в форме, проверяет глазами и только потом жмёт «Загрузить». Табличный документ в реквизите формы читается на сервере тем же циклом.
Прочитать берёт один лист книги. Если нужные данные лежат на втором или третьем листе, переместите лист первым или используйте COM или ADO, где лист выбирается явно.
Чтение Excel через COM-объект Excel.Application
COM управляет настоящим Excel. Способ гибкий, но требует установленного Excel и работает только в Windows. На сервере 1С его не любят: служба крутится без рабочего стола, нужны права DCOM для пользователя службы, а Microsoft не поддерживает такой сценарий для Office.
Excel = Новый COMОбъект("Excel.Application");
Excel.DisplayAlerts = Ложь;
Попытка
Книга = Excel.Workbooks.Open(ИмяФайла);
Лист = Книга.Worksheets(1); // номер или имя листа: Книга.Worksheets("Прайс")
ВсегоСтрок = Лист.UsedRange.Rows.Count;
Для НомерСтроки = 2 По ВсегоСтрок Цикл
Артикул = Лист.Cells(НомерСтроки, 1).Text;
Цена = Лист.Cells(НомерСтроки, 3).Value;
// обработка строки
КонецЦикла;
Книга.Close(Ложь);
Исключение
Сообщить(ОписаниеОшибки());
КонецПопытки;
Excel.Quit();
Excel = Неопределено;
Разница свойств ячейки:
Value— исходное значение: число, дата, строка;Text— то, что отображается на экране, с форматированием.
Всегда вызывайте Excel.Quit(), в том числе после ошибки. Иначе в диспетчере задач копятся процессы EXCEL.EXE, и через пару десятков загрузок машина начинает тормозить.
Список листов: Книга.Worksheets.Count и Книга.Worksheets(Н).Name. Так легко дать пользователю выбрать лист перед загрузкой.
Чтение через ADO, ADOX и драйвер Microsoft ACE
Здесь Excel-файл открывается как база данных, а лист — как таблица. Excel не нужен, но нужен провайдер: Microsoft.ACE.OLEDB.12.0 из пакета Microsoft Access Database Engine. Старый Microsoft.Jet.OLEDB.4.0 читает только xls и существует только в 32-битном варианте.
Разрядность драйвера должна совпадать с разрядностью процесса 1С, который выполняет код: 64-битный сервер не увидит 32-битный ACE.
Соединение = Новый COMОбъект("ADODB.Connection");
Соединение.ConnectionString =
"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + ИмяФайла + ";"
+ "Extended Properties=""Excel 12.0 Xml;HDR=YES;IMEX=1"";";
Соединение.Open();
Выборка = Новый COMОбъект("ADODB.Recordset");
Выборка.Open("SELECT * FROM [Прайс$]", Соединение);
Пока Не Выборка.EOF Цикл
Артикул = Выборка.Fields(0).Value;
Цена = Выборка.Fields(2).Value;
// обработка строки
Выборка.MoveNext();
КонецЦикла;
Выборка.Close();
Соединение.Close();
Что значат параметры строки подключения:
| Параметр | Смысл |
|---|---|
Excel 12.0 Xml | формат xlsx; для xls — Excel 8.0 |
HDR=YES | первая строка — имена колонок, их можно писать в SELECT |
IMEX=1 | смешанные колонки читать как текст |
Как получить список листов через ADOX
Имя листа в запросе пишется с $ в квадратных скобках. Если имя заранее неизвестно, перечислите таблицы через каталог ADOX:
Каталог = Новый COMОбъект("ADOX.Catalog");
Каталог.ActiveConnection = Соединение;
Для Индекс = 0 По Каталог.Tables.Count - 1 Цикл
Сообщить(Каталог.Tables(Индекс).Name); // например: Прайс$
КонецЦикла;
Каталог показывает не только листы, но и именованные диапазоны — их имена идут без $ на конце. Отфильтруйте по этому признаку.
Драйвер угадывает тип колонки по первым строкам. Если там числа, а ниже встречается «12-А», такие значения придут пустыми. IMEX=1 снимает большую часть проблем: смешанная колонка читается как текст.
Обработка данных: приведение типов Excel к типам 1С
Сырые строки из Excel редко ложатся в реквизиты как есть. Три вещи, которые ломаются чаще всего.
Числа
В файле встречаются неразрывные пробелы между разрядами, запятая и точка вперемешку, знак валюты. Функция Число() на такой строке вызывает исключение. Очистите строку и приводите через описание типов: оно вернёт 0 вместо ошибки.
Функция ПривестиКЧислу(Знач Текст)
Текст = СтрЗаменить(Текст, Символы.НПП, "");
Текст = СтрЗаменить(Текст, " ", "");
Текст = СтрЗаменить(Текст, "р.", "");
Текст = СтрЗаменить(Текст, ",", ".");
ОписаниеЧисла = Новый ОписаниеТипов("Число");
Возврат ОписаниеЧисла.ПривестиЗначение(Текст);
КонецФункции
Ноль после приведения — повод записать строку в журнал ошибок, а не молча загрузить цену 0.
Даты
Через COM Value и через ADO дата обычно приходит уже датой. В режиме «Текст» придёт строка вида 15.03.2025, её разбирают по частям: Дата(Число(Сред(С, 7, 4)), Число(Сред(С, 4, 2)), Число(Сред(С, 1, 2))).
Если вместо даты видите число вроде 45731, это серийный номер дня Excel. Перевод: Дата(1899, 12, 30) + СерийныйНомер * 86400. Для 45731 получится 15.03.2025.
Ссылки на справочники
Артикул или ИНН из файла надо превратить в ссылку. Не ищите НайтиПоРеквизиту в каждой строке — об этом в следующем разделе.
Ускорение массового импорта из Excel
На файле в сотню строк разницы не видно. На десятках тысяч строк выбор приёма решает, загрузится файл за минуту или за час.
- ⚡ COM: читайте диапазон целиком. Каждое обращение
Cells(i, j)— вызов в другой процесс.Лист.UsedRange.Valueотдаёт весь диапазон одним вызовом какCOMSafeArray, дальше перебор идёт уже в памяти 1С. - 🗂 Справочники — одним запросом. Соберите все артикулы из файла в массив, выполните запрос
ГДЕ Номенклатура.Артикул В (&Артикулы)и положите результат вСоответствие. Поиск ссылки по ключу соответствия почти бесплатный. - 💾 Записывайте порциями. Создание тысяч элементов справочника оборачивайте в транзакции по несколько сотен объектов. Одна гигантская транзакция держит блокировки, а запись без транзакций медленнее.
- 🧾 Табличную часть заполняйте в памяти. Добавьте все строки в
Объект.Товары, а документ запишите один раз в конце. - 🖥 Тяжёлый импорт — на сервер. Вызов сервера из клиента в цикле по строкам — самый частый тормоз во внешних обработках. Передайте файл на сервер один раз и обработайте его там целиком.
Массовую загрузку в рабочую базу запускайте после резервной копии и вне часов пик: она создаёт тысячи объектов, а откатывать неудачную загрузку вручную долго.
Ошибки при чтении Excel в 1С и что с ними делать
Отдельная ловушка — путь к файлу. Строка C:\Users\...\Прайс.xlsx, выбранная на компьютере пользователя, на сервере 1С ничего не значит. Поэтому файл всегда передают через временное хранилище, а на сервере пишут во временный файл через ПолучитьИмяВременногоФайла.