Загрузка файла xlsx в табличный документ 1С 8.3 без Excel на компьютере
Содержание
Чтобы прочитать Excel в 1С как табличный документ, хватит двух строк: ТабДок = Новый ТабличныйДокумент; и ТабДок.Прочитать(ИмяФайла, СпособЧтенияЗначенийТабличногоДокумента.Значение);. Метод Прочитать разбирает файлы xls, xlsx и ods средствами самой платформы 8.3. Установленный Microsoft Excel для этого не нужен ни на клиенте, ни на сервере.
Частое заблуждение — что импорт из Excel в 1С возможен только через Новый COMОбъект("Excel.Application"). Это старый путь. Он работает лишь под Windows, требует лицензии Office на сервере и медленно перебирает ячейки. Табличный документ закрывает ту же задачу быстрее и работает на сервере под Linux.
Чем ТабличныйДокумент удобнее COM-объекта Excel
COM-подход запускает в фоне настоящий процесс EXCEL.EXE и обращается к нему через межпроцессный вызов. Каждое чтение ячейки — отдельный вызов. На файле в 20 000 строк и 10 колонок это 200 000 обращений к внешнему процессу.
Чтение в табличный документ устроено иначе: платформа один раз разбирает файл целиком и держит его в памяти. Дальше обращение к ячейке — обычная операция внутри 1С.
| Критерий | COM (Excel.Application) | ТабличныйДокумент.Прочитать |
|---|---|---|
| Нужен Excel на машине | да | нет |
| Сервер под Linux | не работает | работает |
| Веб-клиент | не работает | работает через сервер |
| Скорость на больших файлах | низкая | высокая |
| Зависшие процессы EXCEL.EXE | бывают | нет |
| Выбор листа, формулы, макросы | полный доступ | ограниченно |
💡 COM остаётся оправдан в одном случае: нужно читать формулы как текст, запускать макросы или работать с конкретным листом многолистовой книги. Для обычной загрузки прайсов, остатков и справочников он избыточен.
Что нужно для чтения Excel в табличный документ
Требований немного, но каждое из них ломает загрузку, если его пропустить.
- 🧩 Платформа 8.3. На современных релизах 8.3.2x метод
Прочитатьпонимает форматы xls, xlsx и ods. - 📄 Правильное расширение файла. Платформа определяет формат по расширению. Файл xlsx, сохранённый во временный каталог без расширения, не прочитается.
- 🔒 Файл не открыт в Excel с блокировкой. Если пользователь держит книгу открытой, чтение может завершиться ошибкой доступа.
- 🖥️ Код на сервере. В клиент-серверной базе и в веб-клиенте файл сначала передают на сервер через временное хранилище, а читают уже там.
- 📋 Простая структура листа. Одна строка заголовков, данные с нужной строки, без объединённых ячеек в области таблицы.
В тонком клиенте и веб-клиенте прямой путь к файлу на диске пользователя серверу недоступен. Поэтому схема всегда одна: пользователь выбирает файл, клиент помещает его во временное хранилище, сервер достаёт двоичные данные, пишет их во временный файл и читает.
Как прочитать файл Excel в ТабличныйДокумент: код целиком
Ниже рабочий пример для управляемой формы обработки. На форме — команда ЗагрузитьИзExcel и, по желанию, реквизит Таблица типа ТабличныйДокумент для предпросмотра.
Клиентская часть: выбор файла
&НаКлиенте
Процедура ЗагрузитьИзExcel(Команда)
Оповещение = Новый ОписаниеОповещения("ПослеПомещенияФайла", ЭтотОбъект);
НачатьПомещениеФайла(Оповещение, , , Истина, УникальныйИдентификатор);
КонецПроцедуры
&НаКлиенте
Процедура ПослеПомещенияФайла(Результат, Адрес, ВыбранноеИмяФайла, ДополнительныеПараметры) Экспорт
Если Не Результат Тогда
Возврат; // пользователь отменил выбор
КонецЕсли;
Файл = Новый Файл(ВыбранноеИмяФайла);
ЗагрузитьНаСервере(Адрес, Файл.Расширение);
КонецПроцедуры
Четвёртый параметр Истина открывает диалог выбора файла. УникальныйИдентификатор формы привязывает временное хранилище к форме: после её закрытия данные удалятся сами.
Серверная часть: чтение и разбор
&НаСервере
Процедура ЗагрузитьНаСервере(Адрес, Расширение)
ДвоичныеДанные = ПолучитьИзВременногоХранилища(Адрес);
ИмяФайла = ПолучитьИмяВременногоФайла(СтрЗаменить(Расширение, ".", ""));
ДвоичныеДанные.Записать(ИмяФайла);
ТабДок = Новый ТабличныйДокумент;
Попытка
ТабДок.Прочитать(ИмяФайла, СпособЧтенияЗначенийТабличногоДокумента.Значение);
Исключение
УдалитьФайлы(ИмяФайла);
ВызватьИсключение "Не удалось прочитать файл: " + КраткоеПредставлениеОшибки(ИнформацияОбОшибке());
КонецПопытки;
УдалитьФайлы(ИмяФайла);
Таблица = ТабДок; // предпросмотр на форме
Для НомерСтроки = 2 По ТабДок.ВысотаТаблицы Цикл
Артикул = СокрЛП(ТабДок.Область(НомерСтроки, 1, НомерСтроки, 1).Текст);
Если ПустаяСтрока(Артикул) Тогда
Продолжить;
КонецЕсли;
Наименование = СокрЛП(ТабДок.Область(НомерСтроки, 2, НомерСтроки, 2).Текст);
Цена = ЧислоИзЯчейки(ТабДок.Область(НомерСтроки, 3, НомерСтроки, 3));
// здесь — поиск или создание элемента и запись данных
КонецЦикла;
КонецПроцедуры
Строка 1 файла считается шапкой, данные идут со второй. Временный файл удаляется и при успехе, и при ошибке — иначе каталог временных файлов сервера постепенно забивается копиями прайсов.
Чтение ячеек и листов табличного документа
После Прочитать лист Excel превращается в сетку ячеек с нумерацией с единицы: R1C1 — левая верхняя ячейка, она же A1 в Excel. Колонка B — это C2, колонка D — C4.
Способы обратиться к ячейке
- По координатам:
ТабДок.Область(5, 3, 5, 3)— строка 5, колонка 3 (ячейка C5). - По имени в стиле R1C1:
ТабДок.Область("R5C3"). - Диапазоном:
ТабДок.Область(2, 1, 100, 6)— прямоугольник от A2 до F100.
У области ячеек нужны три свойства:
Текст— то, что видно в ячейке, всегда строка;СодержитЗначение— признак, что в ячейке хранится типизированное значение;Значение— само значение (число, дата, строка), еслиСодержитЗначениеравноИстина.
Границы данных
ТабДок.ВысотаТаблицы и ТабДок.ШиринаТаблицы возвращают число строк и колонок. Excel часто считает «занятыми» строки, где когда-то стояло оформление. Поэтому высота может оказаться 1 048 576 при 300 строках данных.
Защита простая: останавливать цикл после нескольких подряд пустых строк в ключевой колонке.
ПустыхПодряд = 0;
Для НомерСтроки = 2 По ТабДок.ВысотаТаблицы Цикл
Ключ = СокрЛП(ТабДок.Область(НомерСтроки, 1, НомерСтроки, 1).Текст);
Если ПустаяСтрока(Ключ) Тогда
ПустыхПодряд = ПустыхПодряд + 1;
Если ПустыхПодряд >= 20 Тогда
Прервать;
КонецЕсли;
Продолжить;
КонецЕсли;
ПустыхПодряд = 0;
// обработка строки
КонецЦикла;
Колонки по заголовкам, а не по номерам
Пользователи любят вставлять колонку «Примечание» посередине прайса. Если код жёстко читает цену из третьей колонки, после такой правки в цену уйдёт текст. Надёжнее один раз пройти по первой строке и запомнить номера колонок по заголовкам.
Колонки = Новый Соответствие;
Для НомерКолонки = 1 По ТабДок.ШиринаТаблицы Цикл
Заголовок = НРег(СокрЛП(ТабДок.Область(1, НомерКолонки, 1, НомерКолонки).Текст));
Если Не ПустаяСтрока(Заголовок) Тогда
Колонки.Вставить(Заголовок, НомерКолонки);
КонецЕсли;
КонецЦикла;
КолонкаЦена = Колонки.Получить("цена");
Если КолонкаЦена = Неопределено Тогда
ВызватьИсключение "В файле нет колонки «Цена»";
КонецЕсли;
Многолистовые книги
Табличный документ не даёт выбрать лист по имени так, как это делает COM. Надёжный вариант — договориться с поставщиком данных: нужная таблица лежит на первом листе или приходит отдельным файлом. Если книга со сводными листами и справочниками приходит регулярно, проверьте на реальном образце, что именно оказалось в табличном документе после чтения, и только потом пишите разбор.
Типы данных, даты, формулы и оформление при импорте Excel
Второй параметр метода Прочитать решает, что получит код.
| Режим | Что в ячейке | Когда выбирать |
|---|---|---|
СпособЧтенияЗначенийТабличногоДокумента.Текст | только строки, как их показывает Excel | нужен «как видно глазами» текст, артикулы с ведущими нулями |
СпособЧтенияЗначенийТабличногоДокумента.Значение | числа и даты сохраняют тип | суммы, количества, даты документов |
Числа
В текстовом режиме сумма 12 500,50 приходит строкой с неразрывным пробелом-разделителем разрядов. Число() на такой строке упадёт. Надёжная функция чтения учитывает оба режима:
&НаСервере
Функция ЧислоИзЯчейки(Область)
Если Область.СодержитЗначение И ТипЗнч(Область.Значение) = Тип("Число") Тогда
Возврат Область.Значение;
КонецЕсли;
Строка = СтрЗаменить(Область.Текст, Символы.НПП, "");
Строка = СтрЗаменить(Строка, " ", "");
Строка = СтрЗаменить(Строка, ".", ",");
ОписаниеЧисла = Новый ОписаниеТипов("Число");
Возврат ОписаниеЧисла.ПривестиЗначение(Строка);
КонецФункции
ПривестиЗначение не вызывает исключение: строку, которую нельзя превратить в число, она вернёт как 0. Если ноль в цене недопустим, проверяйте результат и пишите строку файла в протокол ошибок.
Даты
В режиме Значение ячейка с форматом даты приходит типом Дата. В режиме Текст — строкой вроде 07.10.2026 или 10/7/26, в зависимости от формата в книге. Второй вариант приходится разбирать вручную через СтрРазделить и Дата(Год, Месяц, День), поэтому для дат почти всегда выгоднее режим Значение.
Если дата в Excel введена как текст (с апострофом или из выгрузки другой программы), режим Значение её не спасёт — в ячейке будет строка. Проверяйте тип через ТипЗнч перед записью в реквизит.
Артикулы и коды с нулями
Код 00125 в числовой ячейке Excel хранится как 125, а нули — лишь формат отображения. Режим Значение вернёт число 125. Если такие коды нужны как есть, читайте эту колонку через Текст: в нём сохраняется то, что показано на экране.
Формулы и оформление
- 🧮 Формулы — в табличный документ попадает результат вычисления, сохранённый в файле. Сама формула при чтении не переносится.
- 🎨 Оформление — шрифты, заливка, границы, ширина колонок, объединения переносятся в близком к оригиналу виде. Для разбора данных они не нужны, но помогают в предпросмотре на форме.
- 🔗 Объединённые ячейки — значение хранится в левой верхней ячейке объединения, остальные ячейки диапазона пустые.
- 📊 Диаграммы, сводные таблицы, макросы — для загрузки данных их нужно игнорировать.
Если файл собирали формулами из других книг, а сохранили без пересчёта, в нём может лежать устаревший результат. Попросите автора открыть книгу, пересчитать и сохранить заново.
Запись табличного документа обратно в Excel
Обратная операция — метод Записать. Он сохраняет табличный документ в файл указанного формата.
&НаСервере
Функция ВыгрузитьВExcelНаСервере()
ТабДок = Новый ТабличныйДокумент;
// ... заполнение макетом или вручную через Область().Текст
ИмяФайла = ПолучитьИмяВременногоФайла("xlsx");
ТабДок.Записать(ИмяФайла, ТипФайлаТабличногоДокумента.XLSX);
Адрес = ПоместитьВоВременноеХранилище(Новый ДвоичныеДанные(ИмяФайла), УникальныйИдентификатор);
УдалитьФайлы(ИмяФайла);
Возврат Адрес;
КонецФункции
На клиенте файл отдают пользователю через НачатьПолучениеФайлаССервера или ПолучитьФайл с адресом из функции. Кроме XLSX, перечисление ТипФайлаТабличногоДокумента содержит XLS, ODS, PDF, MXL и другие форматы.
Типичный сценарий связки «прочитать → обработать → записать»: загрузили прайс поставщика, добавили колонку «Наша цена» и «Найден в базе», сохранили и вернули менеджеру. Ему не нужно открывать 1С, чтобы увидеть, какие позиции не сопоставились.
💡 Пользователь может сохранить любой табличный документ в Excel и без кода: в открытом отчёте или печатной форме есть кнопка сохранения на панели формы, где в списке форматов выбирается «Лист Microsoft Excel 2007».
Ускорение массовой загрузки из Excel
Само чтение файла в табличный документ занимает секунды даже на десятках тысяч строк. Медленно работает то, что код делает после: поиск элементов и запись объектов.
Табличный документ → таблица значений
Сначала соберите данные в ТаблицаЗначений с нужными колонками и типами — одним проходом по строкам. Дальше работайте только с ней: её можно сортировать, сворачивать и передавать в запрос.
Один запрос вместо поиска на каждой строке
Справочники.Номенклатура.НайтиПоРеквизиту("Артикул", ...) на каждой строке — это тысячи отдельных обращений к базе. Передайте таблицу значений в запрос как временную таблицу и сопоставьте всё за раз:
Запрос = Новый Запрос;
Запрос.УстановитьПараметр("Данные", ТаблицаДанных);
Запрос.Текст =
"ВЫБРАТЬ
| Данные.Артикул КАК Артикул,
| Данные.Цена КАК Цена
|ПОМЕСТИТЬ ВТ_Данные
|ИЗ
| &Данные КАК Данные
|;
|ВЫБРАТЬ
| ВТ_Данные.Артикул КАК Артикул,
| ВТ_Данные.Цена КАК Цена,
| Номенклатура.Ссылка КАК Номенклатура
|ИЗ
| ВТ_Данные КАК ВТ_Данные
| ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Номенклатура КАК Номенклатура
| ПО ВТ_Данные.Артикул = Номенклатура.Артикул";
Результат = Запрос.Выполнить().Выгрузить();
Чтобы такой запрос работал, у колонок таблицы значений должны быть заданы типы: ТаблицаДанных.Колонки.Добавить("Артикул", Новый ОписаниеТипов("Строка", , Новый КвалификаторыСтроки(25))). Без типа колонку нельзя использовать в условии соединения.
Запись порциями
Запись 30 000 элементов одной транзакцией держит блокировки долго, а одна ошибка откатывает всё. По одной записи без транзакции — медленно. Рабочий компромисс — порции по 500–1000 объектов в своей транзакции с протоколом ошибок по строкам файла.
Загрузку на десятки тысяч строк запускайте фоновым заданием: форма не зависнет, а пользователь увидит прогресс.