Как загрузить файл Excel в табличный документ 1С и разобрать ячейки
Содержание
Прочитать Excel файл как ТабличныйДокумент в 1С 8.3 можно одной строкой: ТабДок.Прочитать(ИмяФайла, СпособЧтенияЗначенийТабличногоДокумента.Значение). Для формата xlsx платформа обходится без установленного Excel, поэтому код работает и на сервере под Linux.
Частое заблуждение — что для чтения Excel обязательно нужен COM-объект Excel.Application. Это путь из времён 8.2: он медленный, требует Excel на машине и падает на серверах без офиса. Встроенный метод проще и надёжнее, а COM остаётся запасным вариантом для редких задач.
Что подготовить до чтения и какой способ выбрать
Перед тем как писать код, ответьте на три вопроса.
- 📁 Где лежит файл. Если пользователь выбирает его на своём компьютере, а код загрузки выполняется на сервере, файл придётся передать через временное хранилище. Сервер не видит диск клиента.
- 📄 Какой формат. xlsx и mxl читаются платформой напрямую. Старый xls лучше заранее пересохранить в xlsx: так меньше сюрпризов с кодировками и форматами ячеек.
- 🔢 Нужны ли типы. Если важны числа и даты как значения, а не как строки, читайте в режиме
Значение. Если нужна строка ровно так, как она видна в Excel (например, артикул с ведущими нулями), подойдёт режимТекст.
Сравнение способов, которые встречаются на практике:
| Способ | Когда подходит | Ограничения и риски |
|---|---|---|
ТабличныйДокумент.Прочитать() | Основной вариант для xlsx и mxl | Сложные книги с несколькими листами и сводными таблицами читаются не всегда так, как ждёшь |
COM Excel.Application | Нужно работать с конкретным листом, формулами, макросами | Только Windows, нужен Excel, медленно, зависшие процессы EXCEL.EXE |
| ADO / OLE DB (провайдер Microsoft ACE) | Плоская таблица, нужен SQL-отбор по листу | Только Windows, нужен установленный провайдер нужной разрядности |
| Разбор xlsx как zip + XML | Нет Excel и нужен полный контроль над структурой | Много кода, общие строки и стили приходится разбирать вручную |
Для типовых задач — загрузка прайса, остатков, списка сотрудников — хватает метода Прочитать. Остальные способы берите, только если упёрлись в его ограничения.
Алгоритм: читаем Excel файл в объект ТабличныйДокумент
Типичная схема в управляемой форме выглядит так:
- На клиенте пользователь выбирает файл, и он помещается во временное хранилище.
- На сервере двоичные данные записываются во временный файл.
- Временный файл читается методом
Прочитатьв табличный документ. - Временный файл удаляется, документ разбирается построчно.
Клиентская часть: выбор и передача файла
&НаКлиенте
Процедура ЗагрузитьИзExcel(Команда)
Оповещение = Новый ОписаниеОповещения("ПослеПомещенияФайла", ЭтотОбъект);
НачатьПомещениеФайла(Оповещение, , , Истина, УникальныйИдентификатор);
КонецПроцедуры
&НаКлиенте
Процедура ПослеПомещенияФайла(Результат, Адрес, ВыбранноеИмяФайла, ДополнительныеПараметры) Экспорт
Если Не Результат Тогда
Возврат; // пользователь отказался от выбора
КонецЕсли;
ЗагрузитьНаСервере(Адрес);
КонецПроцедуры
Последний параметр УникальныйИдентификатор привязывает данные во хранилище к форме. Когда форма закроется, платформа их освободит сама.
Серверная часть: чтение в табличный документ
&НаСервере
Процедура ЗагрузитьНаСервере(Адрес)
ДвоичныеДанные = ПолучитьИзВременногоХранилища(Адрес);
ИмяФайла = ПолучитьИмяВременногоФайла("xlsx");
ДвоичныеДанные.Записать(ИмяФайла);
ТабДок = Новый ТабличныйДокумент;
Попытка
ТабДок.Прочитать(ИмяФайла, СпособЧтенияЗначенийТабличногоДокумента.Значение);
Исключение
УдалитьФайлы(ИмяФайла);
ВызватьИсключение "Не удалось прочитать файл: " + КраткоеПредставлениеОшибки(ИнформацияОбОшибке());
КонецПопытки;
УдалитьФайлы(ИмяФайла);
ОбработатьТабличныйДокумент(ТабДок);
КонецПроцедуры
Расширение во временном имени — xlsx. Платформа определяет формат в том числе по нему, поэтому имя без расширения может дать ошибку чтения.
Хотите, чтобы пользователь сначала увидел, что загрузилось? Сделайте реквизит формы типа ТабличныйДокумент, выведите его на форму полем и присвойте ему прочитанный документ. Пользователь проверит данные глазами и только потом нажмёт «Загрузить».
Как обходить строки, колонки и области прочитанного документа
После чтения у документа есть два ключевых свойства: ВысотаТаблицы — номер последней заполненной строки, ШиринаТаблицы — номер последней колонки. Ячейка берётся методом Область(Строка, Колонка).
&НаСервере
Процедура ОбработатьТабличныйДокумент(ТабДок)
ПерваяСтрокаДанных = 2; // в первой строке заголовки
Для НомерСтроки = ПерваяСтрокаДанных По ТабДок.ВысотаТаблицы Цикл
Артикул = СокрЛП(ТабДок.Область(НомерСтроки, 1).Текст);
Если ПустаяСтрока(Артикул) Тогда
Продолжить; // пустые и служебные строки пропускаем
КонецЕсли;
Наименование = СокрЛП(ТабДок.Область(НомерСтроки, 2).Текст);
Цена = ЗначениеЯчейки(ТабДок, НомерСтроки, 3, 0);
Количество = ЗначениеЯчейки(ТабДок, НомерСтроки, 4, 0);
// дальше — поиск номенклатуры и запись в документ или регистр
КонецЦикла;
КонецПроцедуры
Колонки по заголовкам, а не по номерам
Жёсткие номера колонок ломаются, как только поставщик добавит в прайс столбец. Надёжнее один раз прочитать строку заголовков и запомнить, где какая колонка:
Колонки = Новый Соответствие;
Для НомерКолонки = 1 По ТабДок.ШиринаТаблицы Цикл
Заголовок = НРег(СокрЛП(ТабДок.Область(1, НомерКолонки).Текст));
Если Не ПустаяСтрока(Заголовок) Тогда
Колонки.Вставить(Заголовок, НомерКолонки);
КонецЕсли;
КонецЦикла;
КолонкаЦены = Колонки.Получить("цена");
Если КолонкаЦены = Неопределено Тогда
ВызватьИсключение "В файле нет колонки «Цена»";
КонецЕсли;
Области и диапазоны
Область можно взять и прямоугольником: ТабДок.Область(2, 1, ТабДок.ВысотаТаблицы, 5). Есть и адресация в стиле R2C1:R100C5 — ТабДок.Область("R2C1:R100C5"). Это удобно, когда данные в файле начинаются не с первой строки, а после шапки из логотипа и реквизитов.
Несколько листов в книге
Метод Прочитать рассчитан на книгу, где данные лежат на одном листе. Если в файле несколько листов, не рассчитывайте, что вы получите именно нужный. Практичный выход — договориться с теми, кто готовит файл: данные на первом листе, без сводных таблиц. Если формат файла вам не подвластен, читайте конкретный лист через COM или ADO.
Как привести текст ячеек к числам, датам и ссылкам
В режиме Значение у области ячейки заполнено свойство Значение, а признак СодержитЗначение равен Истина. Числа приходят числами, даты — датами. В режиме Текст всё приходит строкой в том виде, как показывает Excel.
На практике одна и та же колонка бывает смешанной: часть цен введена числом, часть — текстом «1 250,00». Поэтому удобно иметь функцию, которая сама разберётся:
&НаСервере
Функция ЗначениеЯчейки(ТабДок, НомерСтроки, НомерКолонки, ПоУмолчанию)
Ячейка = ТабДок.Область(НомерСтроки, НомерКолонки);
Если Ячейка.СодержитЗначение И ТипЗнч(Ячейка.Значение) = Тип("Число") Тогда
Возврат Ячейка.Значение;
КонецЕсли;
Текст = СокрЛП(Ячейка.Текст);
Текст = СтрЗаменить(Текст, Символы.НПП, "");
Текст = СтрЗаменить(Текст, " ", "");
Текст = СтрЗаменить(Текст, ",", ".");
Если ПустаяСтрока(Текст) Тогда
Возврат ПоУмолчанию;
КонецЕсли;
Попытка
Возврат Число(Текст);
Исключение
Возврат ПоУмолчанию;
КонецПопытки;
КонецФункции
Неразрывный пробел Символы.НПП Excel любит ставить как разделитель тысяч. Обычный СтрЗаменить(Текст, " ", "") его не уберёт, и Число() упадёт.
Что ещё приходится приводить:
- 📅 Даты. В режиме
Значениедата приходит типомДата. Если в файле дата записана текстом «15.03.2025», разберите её черезСтрРазделить(Текст, ".")иДата(Год, Месяц, День). - 🔤 Артикулы и коды. Ячейку «00125» Excel хранит как число 125, если её не отформатировали как текст. Берите
Текст, а неЗначение, и дополняйте нулями слева, если длина кода фиксированная. - 🔗 Ссылки на справочники. Наименование из файла превращайте в ссылку поиском по коду, артикулу или ИНН — так надёжнее, чем по наименованию. Ненайденные строки складывайте в отдельный список и показывайте пользователю после загрузки.
- ✅ Булево. «Да», «да», «1», «+» — нормализуйте через
НРег()и список допустимых значений.
Ошибки чтения и нестандартные файлы
xlsx.Ещё две ситуации, которые ловят на внедрениях:
- 🙈 Скрытые строки и столбцы. Они тоже попадают в документ. Если поставщик прячет в файле служебные колонки, ориентируйтесь на заголовки, а не на номера.
- 🧾 Апостроф в начале ячейки. Excel использует его как признак текста и не показывает. В свойство
Текстон обычно не попадает, но если видите его в данных — уберите черезСтрЗаменить.
Проверка файла до записи в базу
Хорошая загрузка сначала проверяет весь файл и только потом пишет. Порядок такой:
- Прочитайте строку заголовков и убедитесь, что все обязательные колонки на месте. Нет колонки — остановитесь с понятным сообщением, а не на сотой строке с непонятной ошибкой преобразования типа.
- Пройдите по строкам и соберите ошибки в таблицу значений: номер строки, колонка, что не так («артикул не найден», «цена не число»).
- Если ошибок нет — пишите данные. Если есть — покажите таблицу пользователю. Номер строки в ней совпадает с номером строки в Excel, поэтому исправлять файл легко.
Такой отчёт об отклонённых строках снимает почти все вопросы «почему не загрузилось» ещё до звонка разработчику.
Загрузку в рабочую базу сначала прогоните на копии. Ошибка в сопоставлении колонок легко превращает цену в количество — и исправлять потом сотни документов дольше, чем один раз проверить.
Как ускорить импорт тысяч строк
Цикл по Область(Стр, Кол) на файле в 50–100 тысяч строк идёт заметно долго: каждое обращение создаёт объект области. Есть приём, который знают немногие: отдать область табличного документа построителю запроса и получить сразу таблицу значений.
Область = ТабДок.Область(1, 1, ТабДок.ВысотаТаблицы, ТабДок.ШиринаТаблицы);
Построитель = Новый ПостроительЗапроса;
Построитель.ИсточникДанных = Новый ОписаниеИсточникаДанных(Область);
Построитель.Выполнить();
ТаблицаДанных = Построитель.Результат.Выгрузить();
Колонки таблицы значений получат имена из первой строки области. Поэтому заголовки должны быть уникальными и непустыми, иначе часть колонок назовётся служебными именами. Дальше с таблицей работают обычными методами: Найти, Свернуть, передача в запрос как источник через параметр.
Другие способы снять нагрузку:
- Поиск ссылок одним запросом. Не ищите номенклатуру по артикулу на каждой строке. Соберите все артикулы в массив, выполните один запрос с условием
В (&Артикулы)и положите результат в соответствие «артикул → ссылка». - Запись наборами. Для регистров сведений заполняйте один набор записей и записывайте его целиком, а не по одной записи.
- Порции и транзакции. Большой файл пишите порциями, например по 1000 строк в транзакции. Одна гигантская транзакция держит блокировки и при ошибке откатывает всё.
- Фоновое задание. Если загрузка идёт дольше минуты, запустите её в фоне. Форма не зависнет, а пользователь увидит прогресс.
Нужно хранить загруженный файл как документ 1С, без привязки к Excel? Сохраните его в собственном формате: ТабДок.Записать(ИмяФайла, ТипФайлаТабличногоДокумента.MXL). Так же работает и обратная конвертация — запись в ТипФайлаТабличногоДокумента.XLSX.
Частые вопросы
Нужен ли установленный Excel для метода Прочитать?
Можно ли прочитать Excel на клиенте, без передачи на сервер?
Чем режим Значение отличается от режима Текст?
Почему после чтения слетели форматы и ширина колонок?
Как загрузить файл csv тем же способом?
ЧтениеТекста и СтрРазделить по разделителю. Табличный документ здесь лишний шаг.