Чтение Excel в 1С проще всего делать методом Прочитать табличного документа: начиная с платформы 8.3.6 он открывает файлы Excel средствами самой платформы, без установленного Microsoft Office, и работает на сервере как под Windows, так и под Linux. Другие способы — COM-объект Excel.Application, ADO-драйвер и внешний источник данных — зависят от того, что установлено на компьютере, где выполняется код, и подходят для частных случаев.

Ниже — сравнение способов, полный рабочий пример загрузки через табличный документ с передачей файла с клиента на сервер и разбор ошибок, из-за которых загрузки из Excel ломаются чаще всего.

Способы чтения Excel в 1С: сравнение

СпособЧто нужноГде работаетСкоростьКогда выбирать
Табличный документ ПрочитатьТолько платформаКлиент и сервер, Windows и LinuxВысокаяПо умолчанию
COM Excel.ApplicationУстановленный ExcelТолько WindowsНизкаяНужны функции Excel: пересчёт формул, макросы
ADO (OLE DB)Драйвер на WindowsТолько WindowsВысокаяУнаследованный код, чтение листа «как таблицы»
Внешний источник данныхДрайвер ODBC, объект в конфигурацииWindows (с драйвером)ВысокаяРегулярное чтение файла одной структуры запросом
Ручной разбор XLSXТолько платформаВездеСредняяЭкзотика: доступ к стилям или структуре файла
Вставка из буфера в табличный документ на формеТолько платформаКлиент—Пользователь загружает кусок таблицы

На проектах я почти всегда использую табличный документ. COM остаётся для сценариев, где нужен именно Excel — например, пересчитать формулы перед чтением.

Способ 1. Табличный документ — основной

Передаём файл на сервер

В клиент-серверной базе файл лежит у пользователя, а читать его нужно на сервере. Передаём через временное хранилище:

Чтение Excel в 1С: файл передаётся с компьютера пользователя на сервер и разворачивается в таблицу
Чтение Excel в 1С: файл передаётся с компьютера пользователя на сервер и разворачивается в таблицу
1С
&НаКлиенте
Процедура ЗагрузитьИзExcel(Команда)

	ПараметрыДиалога = Новый ПараметрыДиалогаПомещенияФайлов;
	ПараметрыДиалога.Фильтр = НСтр("ru = 'Файлы Excel'") + " (*.xlsx;*.xls)|*.xlsx;*.xls";

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

КонецПроцедуры

&НаКлиенте
Процедура ЗагрузитьИзExcelЗавершение(ПомещенныйФайл, ДополнительныеПараметры) Экспорт

	Если ПомещенныйФайл = Неопределено Или ПомещенныйФайл.ПомещениеФайлаОтменено Тогда
		Возврат;
	КонецЕсли;

	Расширение = ПомещенныйФайл.СсылкаНаФайл.Расширение;
	ЗагрузитьНаСервере(ПомещенныйФайл.Адрес, Расширение);

КонецПроцедуры

Читаем на сервере

1С
&НаСервере
Процедура ЗагрузитьНаСервере(АдресФайла, Расширение)

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

	ТабДок = Новый ТабличныйДокумент;
	Попытка
		ТабДок.Прочитать(ИмяФайла, СпособЧтенияЗначенийТабличногоДокумента.Значение);
	Исключение
		УдалитьФайлы(ИмяФайла);
		ВызватьИсключение НСтр("ru = 'Не удалось прочитать файл. Проверьте, что это книга Excel.'");
	КонецПопытки;
	УдалитьФайлы(ИмяФайла);

	Данные = ТаблицаИзТабличногоДокумента(ТабДок);
	// Дальше — проверка и загрузка строк в объекты

КонецПроцедуры

Режим СпособЧтенияЗначенийТабличногоДокумента.Значение сохраняет в ячейках значения (числа, даты), а не только отображаемый текст. Если в вашей версии платформы второго параметра нет, читайте текст и приводите типы вручную.

Табличный документ → таблица значений по заголовкам

Обращаться к ячейкам по номерам колонок хрупко: пользователь переставит колонки — загрузка молча перепутает цену с количеством. Надёжнее найти колонки по заголовкам в первой строке:

1С
// Преобразует табличный документ с заголовками в первой строке в таблицу значений.
//
// Параметры:
//  ТабДок - ТабличныйДокумент
//
// Возвращаемое значение:
//  ТаблицаЗначений - колонки Код, Наименование, Количество, Цена
//
Функция ТаблицаИзТабличногоДокумента(ТабДок)

	Колонки = Новый Соответствие;
	Колонки.Вставить("код", "Код");
	Колонки.Вставить("наименование", "Наименование");
	Колонки.Вставить("количество", "Количество");
	Колонки.Вставить("цена", "Цена");

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

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

	Для Каждого Элемент Из Колонки Цикл
		Если НомераКолонок[Элемент.Значение] = Неопределено Тогда
			ВызватьИсключение СтрШаблон(НСтр("ru = 'В файле нет колонки «%1»'"), Элемент.Значение);
		КонецЕсли;
	КонецЦикла;

	Для НомерСтроки = 2 По ТабДок.ВысотаТаблицы Цикл
		Код = СокрЛП(ТабДок.Область(НомерСтроки, НомераКолонок["Код"]).Текст);
		Если ПустаяСтрока(Код) Тогда
			Продолжить; // пропускаем пустые и служебные строки
		КонецЕсли;
		Строка = Результат.Добавить();
		Строка.Код = Код;
		Строка.Наименование = СокрЛП(ТабДок.Область(НомерСтроки, НомераКолонок["Наименование"]).Текст);
		Строка.Количество = ЧислоИзЯчейки(ТабДок.Область(НомерСтроки, НомераКолонок["Количество"]));
		Строка.Цена = ЧислоИзЯчейки(ТабДок.Область(НомерСтроки, НомераКолонок["Цена"]));
	КонецЦикла;

	Возврат Результат;

КонецФункции

// Возвращает число из ячейки: значение, если оно числовое, иначе разбор текста.
Функция ЧислоИзЯчейки(Область)

	Если ТипЗнч(Область.Значение) = Тип("Число") Тогда
		Возврат Область.Значение;
	КонецЕсли;

	Текст = СтрЗаменить(СтрЗаменить(СокрЛП(Область.Текст), " ", ""), ",", ".");
	ОписаниеЧисла = Новый ОписаниеТипов("Число");
	Возврат ОписаниеЧисла.ПривестиЗначение(Текст);

КонецФункции

Обращение Область(Строка, Колонка) с числами читается проще, чем сборка строки вида "R2C3". Свойство Значение области заполнено, если файл прочитан в режиме значений; иначе используется разбор текста.

Альтернатива — передать область табличного документа построителю запроса (Новый ОписаниеИсточникаДанных(ТабДок.Область())) и выгрузить результат в таблицу значений: первая строка станет именами колонок. Это быстро пишется, но проверку заголовков и типов всё равно придётся делать.

Способ 2. COM-объект Excel.Application

Подходит, когда Excel установлен там, где выполняется код, и нужны его возможности. Главное правило — всегда закрывать Excel, в том числе при ошибке:

1С
Функция ПрочитатьЧерезExcel(ИмяФайла)

	Данные = Новый Массив;
	Excel = Неопределено;
	Книга = Неопределено;

	Попытка
		Excel = Новый COMОбъект("Excel.Application");
		Excel.DisplayAlerts = Ложь;
		Excel.Visible = Ложь;

		Книга = Excel.Workbooks.Open(ИмяФайла, , Истина); // только чтение
		Лист = Книга.Sheets(1);
		ПоследняяСтрока = Лист.Cells.SpecialCells(11).Row; // xlCellTypeLastCell

		Для НомерСтроки = 2 По ПоследняяСтрока Цикл
			Данные.Добавить(Новый Структура("Код, Цена",
				Лист.Cells(НомерСтроки, 1).Value, Лист.Cells(НомерСтроки, 4).Value));
		КонецЦикла;

		Книга.Close(Ложь);
		Excel.Quit();
	Исключение
		Если Книга <> Неопределено Тогда
			Книга.Close(Ложь);
		КонецЕсли;
		Если Excel <> Неопределено Тогда
			Excel.Quit();
		КонецЕсли;
		ВызватьИсключение;
	КонецПопытки;

	Возврат Данные;

КонецФункции

Минусы: каждое обращение к ячейке — межпроцессный вызов, поэтому на десятках тысяч строк это медленно. Ускоряет чтение блока целиком через Range(...).Value (возвращается двумерный массив), но сам подход всё равно привязан к Windows и лицензии Office. Для серверной загрузки я его не использую.

Способ 3. ADO и внешний источник данных

ADO читает лист как таблицу базы данных SQL-запросом SELECT * FROM [Лист1$]. Нужен OLE DB-провайдер для Excel на Windows-машине, где выполняется код; старый провайдер Jet работает только с XLS и только в 32-битном окружении, для XLSX нужен провайдер ACE. Способ быстрый, но капризный в установке.

Внешний источник данных — объект конфигурации, который подключается к файлу через ODBC-драйвер Excel и позволяет читать лист обычным запросом 1С:

1С
ПараметрыСоединения = Новый ПараметрыСоединенияВнешнегоИсточникаДанных;
ПараметрыСоединения.СтрокаСоединения =
	"Driver={Microsoft Excel Driver (*.xls, *.xlsx, *.xlsm, *.xlsb)};DBQ=" + ИмяФайла + ";";

ВнешниеИсточникиДанных.Прайс.УстановитьОбщиеПараметрыСоединения(ПараметрыСоединения);
ВнешниеИсточникиДанных.Прайс.УстановитьСоединение();

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

Способ 4. Загрузка вставкой из буфера

Для пользователей, которым нужно загрузить кусок таблицы, а не весь файл: на форме размещается реквизит-табличный документ с разрешённым редактированием, в первой строке — заголовки. Пользователь копирует диапазон из Excel, вставляет в поле и нажимает «Загрузить». Обработка та же — ТаблицаИзТабличногоДокумента. Никаких файлов и драйверов.

Типичные ошибки

  • Колонки по номерам. Файл с переставленными колонками загружается «успешно», но с перепутанными данными. Ищите колонки по заголовкам и падайте с понятной ошибкой, если колонки нет.
  • Пустые строки и итоги внизу листа. ВысотаТаблицы включает отформатированные пустые строки. Пропускайте строки без ключевого поля и строки «Итого».
  • Числа с пробелами и запятыми. «1 250,50» не приводится к числу без очистки текста.
  • Даты как текст. При чтении текста дата зависит от формата ячейки. Читайте значения или разбирайте дату по известному формату.
  • Зависшие процессы Excel. COM без закрытия книги и Quit в ветке ошибки оставляет на сервере десятки процессов EXCEL.EXE.
  • Чтение файла на сервере по пути с клиента. Путь C:\Users\... существует у пользователя, но не на сервере. Передавайте файл через временное хранилище.
  • Неудалённые временные файлы. Каталог временных файлов сервера постепенно забивается — удаляйте файл сразу после чтения.
Табличный документ закрывает почти все задачи загрузки из Excel. Внешние зависимости — COM, драйверы, Office на сервере — оставляйте для случаев, где без них действительно никак.

Загрузки прайсов, остатков и справочников из Excel, а также регулярные обмены с внешними системами я делаю в рамках доработки 1С и интеграции 1С по API.

Итог

  • Основной способ — ТабличныйДокумент.Прочитать на сервере: без Office, на Windows и Linux.
  • В клиент-серверной базе передавайте файл через временное хранилище и временный файл, затем удаляйте его.
  • Ищите колонки по заголовкам, пропускайте пустые строки, приводите числа и даты явно.
  • COM Excel.Application — только когда нужны функции Excel, и всегда с закрытием в ветке ошибки.
  • ADO и внешний источник данных — быстрые, но требуют драйверов на Windows.