Загрузка данных из xls и xlsx во встроенном языке 1С 8.3

· 10 мин

Содержание

Прочитать файл Excel в 1С проще всего объектом ТабличныйДокумент: метод Прочитать() открывает xls и xlsx без установленного Microsoft Excel, на клиенте и на сервере, в Windows и Linux. COM-объект Excel.Application и ADO нужны реже: когда надо выбрать лист по имени, взять значение формулы или работать с очень старым кодом.

Типичная ситуация: поставщик раз в неделю присылает прайс на 3 000 строк, и бухгалтер просит «кнопку, чтобы не вбивать руками». Для неё хватит одной обработки на 150 строк кода, и Excel на компьютере бухгалтера для этого не нужен.

Что подготовить, прежде чем читать Excel в 1С

Сначала решите три вопроса. От ответов зависит, какой способ подойдёт.

  1. Где выполняется код. Тонкий клиент и веб-клиент не видят файлы на диске сервера, а сервер не видит диск пользователя. Файл почти всегда передают на сервер через временное хранилище.
  2. Какая ОС на сервере 1С. На Linux COM нет вообще. Остаётся только ТабличныйДокумент.
  3. Есть ли Excel там, где работает код. COM-способ требует установленного Microsoft Excel на той же машине, где выполняется процедура. На сервере это плохая идея: Microsoft не поддерживает Office в серверных сценариях без пользователя.

Ещё полезно договориться о формате файла с тем, кто его присылает:

  • 📌 первая строка — заголовки колонок, без объединённых ячеек;
  • 📌 данные на первом листе;
  • 📌 без пустых строк-разделителей внутри таблицы;
  • 📌 числа — числами, а не текстом с пробелами.

Чем строже договорённость, тем короче код проверки.

Способ 1. ТабличныйДокумент: чтение xlsx без Microsoft Excel

Это нативный механизм платформы. Файл разбирается самой 1С, внешние программы не нужны. Метод работает в актуальных версиях 8.3 и в клиент-серверном, и в файловом варианте.

Минимальный пример на сервере, когда файл уже лежит на диске:

ТабДок = Новый ТабличныйДокумент;
ТабДок.Прочитать("C:\Загрузка\prajs.xlsx", СпособЧтенияЗначенийТабличногоДокумента.Текст);

Для НомерСтроки = 2 По ТабДок.ВысотаТаблицы Цикл
    Артикул = СокрЛП(ТабДок.Область(НомерСтроки, 1, НомерСтроки, 1).Текст);
    Цена    = СокрЛП(ТабДок.Область(НомерСтроки, 3, НомерСтроки, 3).Текст);
    // дальше — поиск номенклатуры и запись цены
КонецЦикла;

Второй параметр метода задаёт, как читать ячейки:

ЗначениеЧто получитеКогда брать
СпособЧтенияЗначенийТабличногоДокумента.ТекстСтроку в том виде, как её видно в ExcelПочти всегда: предсказуемо, легко проверить
СпособЧтенияЗначенийТабличногоДокумента.ЗначениеТипизированное значение ячейки (число, дата) в свойстве Значение областиКогда важно не потерять точность из-за форматирования

Третьим параметром можно явно указать тип файла, например ТипФайлаТабличногоДокумента.XLSX. Если его не указывать, платформа определяет тип по расширению.

Режим Текст отдаёт то, что отображается. Если в Excel у ячейки формат «0 знаков после запятой», а внутри 12,7, вы прочитаете «13». Для цен и количеств проверьте формат колонки или читайте в режиме Значение.

У способа есть ограничение. Надёжно рассчитывайте на первый лист книги. Если данные на втором листе, попросите поставщика поменять порядок или используйте COM либо ADO, где лист выбирается по имени.

Как передать файл Excel с компьютера пользователя на сервер

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

Код формы обработки целиком:

&НаКлиенте
Процедура ЗагрузитьИзExcel(Команда)
    Оповещение = Новый ОписаниеОповещения("ПослеПомещенияФайла", ЭтотОбъект);
    НачатьПомещениеФайла(Оповещение, , , Истина, УникальныйИдентификатор);
КонецПроцедуры

&НаКлиенте
Процедура ПослеПомещенияФайла(Результат, Адрес, ВыбранноеИмяФайла, ДополнительныеПараметры) Экспорт
    Если Не Результат Тогда
        Возврат; // пользователь закрыл окно выбора
    КонецЕсли;
    Файл = Новый Файл(ВыбранноеИмяФайла);
    Расширение = НРег(Сред(Файл.Расширение, 2)); // ".xlsx" -> "xlsx"
    Если Расширение <> "xlsx" И Расширение <> "xls" Тогда
        Сообщить("Выберите файл Excel (xls или xlsx).");
        Возврат;
    КонецЕсли;
    Строки = ПрочитатьФайлНаСервере(Адрес, Расширение);
    Сообщить("Прочитано строк: " + Формат(Строки.Количество(), "ЧН=0; ЧГ=0"));
КонецПроцедуры

&НаСервереБезКонтекста
Функция ПрочитатьФайлНаСервере(Адрес, Расширение)
    ИмяФайла = ПолучитьИмяВременногоФайла(Расширение);
    ПолучитьИзВременногоХранилища(Адрес).Записать(ИмяФайла);

    ТабДок = Новый ТабличныйДокумент;
    ТабДок.Прочитать(ИмяФайла, СпособЧтенияЗначенийТабличногоДокумента.Текст);
    УдалитьФайлы(ИмяФайла);

    Возврат РазобратьТаблицу(ТабДок);
КонецФункции

Функция РазобратьТаблицу возвращает массив структур: такой результат можно передать с сервера на клиент.

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

Построчная обработка: заголовки, колонки, пустые строки

Самая частая поломка загрузки — поставщик вставил колонку, и «цена» уехала из третьей в четвёртую. Поэтому номера колонок лучше не зашивать в код, а искать по тексту заголовка.

&НаСервереБезКонтекста
Функция РазобратьТаблицу(ТабДок)
    Результат = Новый Массив;

    // 1. Ищем колонки по заголовкам в первой строке
    Колонки = Новый Соответствие;
    Для НомерКолонки = 1 По ТабДок.ШиринаТаблицы Цикл
        Заголовок = НРег(СокрЛП(ТабДок.Область(1, НомерКолонки, 1, НомерКолонки).Текст));
        Если ЗначениеЗаполнено(Заголовок) Тогда
            Колонки.Вставить(Заголовок, НомерКолонки);
        КонецЕсли;
    КонецЦикла;

    КолонкаАртикул = Колонки.Получить("артикул");
    КолонкаЦена    = Колонки.Получить("цена");
    Если КолонкаАртикул = Неопределено Или КолонкаЦена = Неопределено Тогда
        ВызватьИсключение "В первой строке нет заголовков «Артикул» и «Цена».";
    КонецЕсли;

    // 2. Идём по строкам данных
    ПустыхПодряд = 0;
    Для НомерСтроки = 2 По ТабДок.ВысотаТаблицы Цикл
        Артикул = СокрЛП(ТабДок.Область(НомерСтроки, КолонкаАртикул, НомерСтроки, КолонкаАртикул).Текст);
        ЦенаТекст = СокрЛП(ТабДок.Область(НомерСтроки, КолонкаЦена, НомерСтроки, КолонкаЦена).Текст);

        Если Не ЗначениеЗаполнено(Артикул) Тогда
            ПустыхПодряд = ПустыхПодряд + 1;
            Если ПустыхПодряд >= 20 Тогда
                Прервать; // дальше только отформатированные пустые строки
            КонецЕсли;
            Продолжить;
        КонецЕсли;
        ПустыхПодряд = 0;

        Строка = Новый Структура("НомерСтроки, Артикул, ЦенаТекст", НомерСтроки, Артикул, ЦенаТекст);
        Результат.Добавить(Строка);
    КонецЦикла;

    Возврат Результат;
КонецФункции

Что здесь важно:

  • 🔍 Заголовки в нижнем регистре — «Цена», «ЦЕНА» и «цена » с пробелом дают один ключ.
  • 🔍 Счётчик пустых строк. ВысотаТаблицы учитывает строки, где когда-то стояла заливка или рамка. В файле с 500 строками данных высота бывает 65 000. Без выхода по пустым строкам цикл крутится впустую.
  • 🔍 Номер строки в результате. Когда проверка найдёт ошибку, пользователь увидит «строка 418», а не «что-то не так».

Запись в базу (поиск номенклатуры, создание документа «Установка цен» и т. п.) делайте вторым проходом, уже по проверенному массиву. Тогда ошибка в строке 2 900 не оставит в базе половину загрузки.

Способ 2. Чтение данных Excel через COM-объект

COM запускает настоящий Excel в фоне и управляет им из 1С. Работает только в Windows и только там, где Excel установлен. Обычно это клиент толстого клиента или код &НаКлиенте с файлом на диске пользователя.

&НаКлиенте
Процедура ПрочитатьЧерезCOM(ПутьКФайлу)
    Excel = Новый COMОбъект("Excel.Application");
    Excel.DisplayAlerts = Ложь;
    Попытка
        Книга = Excel.Workbooks.Open(ПутьКФайлу, 0, Истина); // 3-й параметр — только чтение
        Лист = Книга.Worksheets("Прайс"); // по имени или по номеру: Worksheets(1)
        Диапазон = Лист.UsedRange;
        ПоследняяСтрока = Диапазон.Row + Диапазон.Rows.Count - 1;

        Для НомерСтроки = 2 По ПоследняяСтрока Цикл
            Артикул = СокрЛП(Лист.Cells(НомерСтроки, 1).Text);
            Цена    = Лист.Cells(НомерСтроки, 3).Value; // число, а не отображаемый текст
            // обработка строки
        КонецЦикла;
        Книга.Close(Ложь);
    Исключение
        Сообщить("Ошибка чтения Excel: " + ОписаниеОшибки());
    КонецПопытки;
    Excel.Quit();
    Excel = Неопределено;
КонецПроцедуры

У ячейки два полезных свойства. Text — строка, как на экране. Value — исходное значение: число без округления формата, результат формулы.

Всегда вызывайте Excel.Quit(), в том числе после ошибки. Иначе в диспетчере задач остаётся процесс EXCEL.EXE, файл заблокирован, и следующая загрузка падает с ошибкой доступа. Поэтому Quit() стоит после блока Попытка, а не внутри него.

Каждое обращение Лист.Cells(...) — отдельный межпроцессный вызов. На файле в 50 000 ячеек это ощутимо медленно. Ускорение — прочитать весь диапазон одним вызовом Диапазон.Value: придёт COMSafeArray, который разбирают уже в памяти. Порядок индексов проверьте в отладчике на маленьком файле 3×2, прежде чем писать цикл.

Способ 3. ADO: Excel как таблица базы данных

Третий вариант — подключиться к книге через драйвер Microsoft ACE OLEDB и читать лист SQL-запросом. Excel не запускается, но драйвер должен быть установлен. Разрядность драйвера должна совпадать с разрядностью процесса 1С: 64-битному серверу нужен 64-битный ACE.

Соединение = Новый COMОбъект("ADODB.Connection");
Соединение.ConnectionString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + ПутьКФайлу
    + ";Extended Properties=""Excel 12.0 Xml;HDR=YES;IMEX=1"";";
Соединение.Open();

Выборка = Соединение.Execute("SELECT * FROM [Прайс$]");
Пока Не Выборка.EOF Цикл
    Артикул = Выборка.Fields.Item(0).Value;
    Цена    = Выборка.Fields.Item(2).Value;
    // обработка строки
    Выборка.MoveNext();
КонецЦикла;

Выборка.Close();
Соединение.Close();

Параметры строки подключения:

  • HDR=YES — первая строка считается заголовками и в выборку не попадает;
  • IMEX=1 — колонки со смешанными данными читаются как текст. Без него драйвер угадывает тип по первым строкам, и артикулы вида «00125» превращаются в число 125 или в пустое значение;
  • [Прайс$] — имя листа со знаком доллара в квадратных скобках.

Для старого формата xls используют Extended Properties=""Excel 8.0;HDR=YES;IMEX=1"".

Какой способ чтения Excel быстрее и где он работает

СпособНужен ExcelLinux-серверВеб-клиентВыбор листаСкорость на больших файлах
ТабличныйДокументНетДаДа (через сервер)Первый листВысокая
COM, по ячейкамДаНетНетПо имениНизкая
COM, весь диапазон сразуДаНетНетПо имениСредняя
ADO (ACE OLEDB)Нет, нужен драйверНетЧерез сервер на WindowsПо имениВысокая

Узкое место COM — не Excel, а число вызовов между процессами. Запуск самого Excel добавляет несколько секунд к каждой загрузке. ТабличныйДокумент читает файл целиком в память 1С, и дальше обращения к ячейкам идут без внешних вызовов.

Практическое правило:

  • новая обработка — ТабличныйДокумент;
  • нужен конкретный лист или формулы, а сервер на Windows — ADO;
  • COM — для старого кода, где переписывать дороже, чем терпеть.
Какой способ взять для вашей загрузки?

Ошибки при чтении Excel и проверка загруженных данных

Ошибки делятся на две группы: файл не открылся и файл открылся, но данные кривые.

Диагностика: выберите симптом

Вторая группа — значения, которые выглядят нормально, но не превращаются в числа и даты. Три приёма закрывают большинство случаев.

Числа с неразрывным пробелом. Excel при выгрузке из других систем часто вставляет между разрядами неразрывный пробел: «1 234,50». Обычный СтрЗаменить(Текст, " ", "") его не убирает.

Функция ТекстВЧисло(Знач Текст, Результат)
    Текст = СокрЛП(Текст);
    Текст = СтрЗаменить(Текст, Символы.НПП, "");
    Текст = СтрЗаменить(Текст, " ", "");
    Текст = СтрЗаменить(Текст, ",", ".");
    Попытка
        Результат = Число(Текст);
        Возврат Истина;
    Исключение
        Возврат Ложь;
    КонецПопытки;
КонецФункции

Даты. В режиме Текст дата приходит строкой «07.10.2026». Разбирайте её явно:

Дата = Дата(Число(Прав(Текст, 4)), Число(Сред(Текст, 4, 2)), Число(Лев(Текст, 2)));

Если пришло число вроде 46 000, это внутренний номер дня Excel. Перевод: Дата(1899, 12, 30) + НомерДня * 86400.

Ведущие нули в кодах. ИНН, артикулы и коды ОКВЭД читайте как текст. Ячейка «0012345678» в режиме Значение или через COM Value может прийти числом 12345678.

Проверку стройте так: сначала прогнать весь массив, собрать список ошибок с номерами строк, показать пользователю. Писать в базу — только если список пуст или пользователь явно согласился пропустить плохие строки.

Перед запуском загрузки в рабочей базе
Выполнено: 0 / 6

Частые вопросы

Можно ли прочитать файл Excel в 1С без установленного Microsoft Office?
Да. Метод ТабличныйДокумент.Прочитать() разбирает xls и xlsx средствами платформы, Office не нужен. ADO тоже обходится без Excel, но требует драйвера ACE.
Читает ли 1С файлы ods из LibreOffice?
Табличный документ умеет работать с форматом ods. Если чтение не проходит, пересохраните файл в xlsx в самом LibreOffice.
Как прочитать файл csv, который открывается в Excel?
CSV — это текст, а не книга Excel. Читайте его объектом ЧтениеТекста и делите строки по разделителю функцией СтрРазделить(). Учтите кодировку: выгрузки из Excel часто в Windows-1251, а не в UTF-8.
Почему через ТабличныйДокумент читается только часть строк?
Чаще всего цикл прерывается по пустым строкам раньше времени: в файле есть пустые строки-разделители внутри таблицы. Увеличьте порог пустых строк подряд или уберите разделители в файле.
Можно ли загружать Excel в фоновом задании?
Да, если чтение идёт через ТабличныйДокумент или ADO на сервере. Файл заранее помещают во временное хранилище и передают адрес в параметрах задания. COM с Excel в фоновом задании использовать не стоит: у сеанса нет рабочего стола пользователя.