В статье рассмотрен один из вариантов чтения данных из файла Excel.
Для соединения используется провайдер Microsoft ACE OLEDB 12.0,
что позволяет читать файлы без установки Excel.
Чтение данных осуществляется запросом на языке SQL.
Решил выложить небольшой пример по чтению запросом данных из файлов Excel.
Сначала надо скачать и установить на компьютер(сервер) вот этот провайдер:
http://www.microsoft.com/download/en/details.aspx?id=23734
Для доступа к данным Excel используем следующий код:
СтрокаПодключения = "Provider=Microsoft.ACE.OLEDB.12.0; Data Source = "+Путь; СтрокаПодключения = СтрокаПодключения + "; Extended Properties = "+"""Excel 12.0"+";HDR=NO;IMEX=1"";"; // Подключаемся Об_Конект = Новый COMОбъект("ADODB.Connection"); Попытка Об_Конект.Open(СтрокаПодключения); Исключение Сообщить ("Невозможно подключится к Microsoft Excel Driver!!! |Возможно файл ["+Путь+"] открыт другим пользователем."); Возврат; КонецПопытки; СтрЗапроса = " |SELECT * |FROM [A" + Формат(НачальнаяСтрока,"ЧГ=0") + ":CZ" + Формат(КонечнаяСтрока,"ЧГ=0") + "] |"; //данный запрос выбирает все заполненные ячейки листа, однако можно наложить условия отбора. синтаксис SQL Попытка RecordSet = Об_Конект.Execute(СтрЗапроса); Исключение Сообщить("Не удалось выполнить запрос к файлу Excel |"+ ОписаниеОшибки(),СтатусСообщения.Важное); Возврат; КонецПопытки; Пока НЕ RecordSet.EOF() Цикл //Дальше обрабатываем RecordSet ЗначениеКолонки1 = RecordSet.Fields(0).value; ЗначениеКолонки2 = RecordSet.Fields(1).value; .... RecordSet.MoveNext(); КонецЦикла;
&НаКлиенте
Процедура ФайлНачалоВыбора(Элемент, ДанныеВыбора, СтандартнаяОбработка) //необходимо в событии «НачалоВыбора» поля ввода вызвать ДиалогВыбораФайлаДиалог = Новый ДиалогВыбораФайла(РежимДиалогаВыбораФайла.Открытие);
Диалог.Заголовок = «Выберите файл Excel»;
Диалог.ПредварительныйПросмотр = Ложь;
Диалог.Фильтр = «(*.xls,*.xlsx)|*.xls;*.xlsx;|Microsoft Excel 97/2000/XP/2003 (*.xls)|*.xls|Microsoft Excel 2007/2010 (*.xlsx)|*.xlsx»;
Если
ЗначениеЗаполнено(Объект.Файл) Тогда
Диалог.ПолноеИмяФайла= Объект.Файл;
КонецЕсли;
Если
Диалог.Выбрать() Тогда
ВыбранныйФайл = Диалог.ПолноеИмяФайла;
Объект.Файл = ВыбранныйФайл;
ЧтениеExcel_через_ТД(ВыбранныйФайл);
КонецЕсли;
КонецПроцедуры
&НаСервере
Процедура ЧтениеExcel_через_ТД(ВыбранныйФайл)//1) Выводим Excel в табличн.документ
ТаблДок = Новый ТабличныйДокумент;
ТаблДок.Прочитать(ВыбранныйФайл, СпособЧтенияЗначенийТабличногоДокумента.Значение);//2) Выгружаем в таблицу значений
ПЗ = Новый ПостроительЗапроса;
ПЗ.ИсточникДанных = Новый ОписаниеИсточникаДанных(ТаблДок.Область());
ПЗ.ДобавлениеПредставлений = ТипДобавленияПредставлений.НеДобавлять;
ПЗ.ЗаполнитьНастройки();
ПЗ.Выполнить();ТаблицаЗначений = ПЗ.Результат.Выгрузить();
КонецПроцедуры
Весьма частая задача, с которой сталкивается 1С разработчик – это чтение файлов Excel и загрузка их в 1С. Есть как минимум два способа прочитать файл Excel – средствами платформы 1С, или используя COM-объект приложения MS Excel. В статье рассматривается чтение файлов xls, xlsx при помощи табличного документа.
Содержание
Общая информация
В платформе 1С 8 существует объект ТабличныйДокумент, который позволяет формировать и выводить на экран печатные формы в табличном виде. Но у табличного документа есть еще одно применение – чтение данных из табличных файлов. Поддерживаются форматы xls, xlsx и ods. Т.е. можно загружать табличные файлы, созданные в пакете MS Office или OpenOffice Calc.
Значения типа Число или Дата, содержащиеся в ячейках исходного табличного файла, можно считать двумя способами – как значение, либо как текст. Рассмотрим пример: пусть в ячейке содержится число 123,456, и установлен формат с округлением до целого числа; в этом случае отображаться будет текст “123”, а значение будет храниться 123,456
- Если прочитать с указанием способа чтения как “Значение”, в табличный документ 1С будет прочитано исходное значение 123,456
- Если прочитать с указанием способа чтения как “Текст”, значение будет потеряно, и в табличный документ прочитается текст “123”
Использование объекта ВременноеХранилище
Вспомогательные процедуры — диалог выбора файла
Следующий код не является обязательным для решения задачи – путь к исходному файлу можно указать в коде, ввести вручную, скопировать из адресной строки ОС или прочитать из БД – вариантов очень много. Мы же рассмотрим пример, когда пользователь сам указывает файл на клиентском компьютере, и путь к этому файлу помещается в реквизит. В примере будем использовать реквизит формы ПутьКФайлу
Создадим обработчик события НачалоВыбора:
&НаКлиенте
Процедура ПутьКФайлуНачалоВыбора(Элемент, ДанныеВыбора, СтандартнаяОбработка)
СтандартнаяОбработка = Ложь;
ВыбратьФайлНаКлиенте();
КонецПроцедуры
Для того чтобы код был универсальным, и работал в случае отказа от модальных синхронных методов, нам понадобится создать асинхронную процедуру ВыбратьФайлНаКлиенте(). В ней мы создаем диалог выбора для открытия файла, указываем фильтр с нужными форматами – xls и xlsx, а также отключаем множественный выбор файлов. Перед методом ВыбратьАсинх добавляем ключевое слово Ждать, с тем чтобы дальнейший код дождался возвращаемого значения.
&НаКлиенте
Асинх Процедура ВыбратьФайлНаКлиенте()
Перем Диалог;
Диалог = Новый ДиалогВыбораФайла(РежимДиалогаВыбораФайла.Открытие);
Диалог.Фильтр = "Excel файлы(*.xls;*.xlsx)|*.xls;*.xlsx";
Диалог.ИндексФильтра = 0;
Диалог.ПредварительныйПросмотр = Ложь;
Диалог.МножественныйВыбор = Ложь;
РезультатВыбора = Ждать Диалог.ВыбратьАсинх();
Если РезультатВыбора <> Неопределено Тогда
ПутьКФайлу = РезультатВыбора[0];
КонецЕсли;
КонецПроцедуры
Двоичные данные во временное хранилище
Логика кода будет следующая. Нам понадобятся двепроцедуры – клиентский обработчик команды, и серверный метод который и будет непосредственно считывать переданный файл.
Клиентский код:
- проверяем, указан ли путь к файлу. Если не указан – прекращаем выполнение
- Получаем двоичные данные из файла по указанному пути
- Помещаем эти двоичные данные во временное хранилище
- Далее передаем на сервер адрес этого временного хранилища
&НаКлиенте
Процедура ДвоичныеДанныеВоВременноеХранилище(Команда)
Если Не ЗначениеЗаполнено(ПутьКФайлу) Тогда
Возврат;
КонецЕсли;
ДД = Новый ДвоичныеДанные(ПутьКФайлу);
АдресВХ = ПоместитьВоВременноеХранилище(ДД);
ПрочитатьИзВХНаСервере(АдресВХ);
КонецПроцедуры
Серверный код:
- Создаем временный файл с нужным расширением (в примере – xlsx)
- Получаем двоичные данные из временного хранилища
- Записываем во временный файл
- Определяем вариант чтения файла – читать значения табличного документа как текст, или как значения
- Далее используем метод Прочитать, и считываем из временного файла данные в табличный документ
Метод Прочитать лучше делать в попытке, и отдельно продумать и написать код обработки исключения. для упрощения примера мы это исключение никак не обрабатываем. В случае, если передан поврежденный файл, или его невозможно прочитать по какой-то другой причине, он просто не считается в табличный документ.
&НаСервере
Процедура ПрочитатьИзВХНаСервере(АдресВХ, Режим = "Значение")
ИмяВременногоФайла = ПолучитьИмяВременногоФайла("xlsx");
ДД = ПолучитьИзВременногоХранилища(АдресВХ);
ДД.Записать(ИмяВременногоФайла);
Если Режим = "Текст" Тогда
СпособЧтения = СпособЧтенияЗначенийТабличногоДокумента.Текст;
Иначе
СпособЧтения = СпособЧтенияЗначенийТабличногоДокумента.Значение;
КонецЕсли;
Попытка
ТабДок.Прочитать(ИмяВременногоФайла, СпособЧтения);
Исключение
КонецПопытки;
КонецПроцедуры
Рассмотренный пример является достаточно универсальным – процедуру ПрочитатьИзВХНаСервере() можно использовать с любыми двоичными данными, помещенными во временное хранилище. Это могут быть двоичные данные, полученные с веб-сервиса, считанные из базы данных, полученные из макета, созданного в конфигураторе – код от этого не изменится.
Помещение файла на сервер в 1С
Более простой, но менее универсальный способ, предназначенный исключительно для передачи файла с клиента на сервер – это использование метода НачатьПомещениеФайлаНаСервер. В платформе предусмотрено несколько методов для помещения файлов – как одиночных, так и нескольких одновременно. Эти методы делятся на синхронные и асинхронные. Начиная с версии 8.3.18 появились методы, использующие ключевые слова Асинх и Ждать. Аналогичный метод мы рассмотрели при работе с диалогом. Далее разберем “классический” вариант с обработкой оповещения.
Логика кода следующая:
- Создаем описание оповещения и указываем в нем процедуру, которая будет вызвана после окончания помещения файла на сервер
- Указываем параметры диалога выбора файла и добавляем фильтр
- Вызываем помещение файла на сервер
- После того как файл помещен во временное хранилище, используем ту же процедуру, которую мы реализовали в первом примере – ПрочитатьИзВХНаСервере. В этом примере мы для разнообразия используем способ чтения значений как “Текст”.
&НаКлиенте
Процедура ПередачаФайла(Команда)
ОбработкаОкончанияПомещения = Новый ОписаниеОповещения("ОбработчикОкончанияПомещения", ЭтотОбъект);
ПараметрыДиалога = Новый ПараметрыДиалогаПомещенияФайлов;
ПараметрыДиалога.Фильтр = "Excel файлы(*.xls;*.xlsx)|*.xls;*.xlsx";
НачатьПомещениеФайлаНаСервер(ОбработкаОкончанияПомещения, , , АдресВХ, ПараметрыДиалога, ЭтотОбъект.УникальныйИдентификатор);
КонецПроцедуры
&НаКлиенте
Процедура ОбработчикОкончанияПомещения(ОписаниеПомещенногоФайла, ДополнительныеПараметры) Экспорт
АдресФайла = ОписаниеПомещенногоФайла.Адрес;
ПрочитатьИзВХНаСервере(АдресФайла, "Текст");
КонецПроцедуры
Использование потока для чтения файла
В случае, если нам нужно просто передать файл с клиента на сервер для сохранения в базу данных, либо мы хотим прочитать файл в формате ods(Open Documents Spreadsheet) или mxl(встроенный формат табличных документов 1С), мы можем воспользоваться еще одним способом – с использованием потоков данных.
В этом случае нам не понадобится создавать временный файл и следить за его корректным удалением. Код будет очень похож на прерыдущий пример. Мы также выбираем файл с использованием метода НачатьПомещениеФайлаНаСервер, но указываем другой фильтр. А в обработчике оповещения вызываем серверную процедуру ПрочитатьВПоток. В методе Прочитать() нам нужно явным образом указать тип файла табличного документа, который мы считываем.
&НаКлиенте
Процедура ПрочитатьЧерезПоток(Команда)
ОбработкаОкончанияПомещения = Новый ОписаниеОповещения("ОбработчикОкончанияПомещенияПоток", ЭтотОбъект);
ПараметрыДиалога = Новый ПараметрыДиалогаПомещенияФайлов;
ПараметрыДиалога.Фильтр = "файлы ODS или MXL|*.ods;*.mxl";
НачатьПомещениеФайлаНаСервер(ОбработкаОкончанияПомещения, , , АдресВХ, ПараметрыДиалога, ЭтотОбъект.УникальныйИдентификатор);
КонецПроцедуры
&НаКлиенте
Процедура ОбработчикОкончанияПомещенияПоток(ОписаниеПомещенногоФайла, ДополнительныеПараметры) Экспорт
АдресФайла = ОписаниеПомещенногоФайла.Адрес;
ПрочитатьВПоток(АдресФайла);
КонецПроцедуры
&НаСервере
Процедура ПрочитатьВПоток(АдресФайла)
ДД = ПолучитьИзВременногоХранилища(АдресФайла);
Поток = ДД.ОткрытьПотокДляЧтения();
ТабДок.Прочитать(Поток,,ТипФайлаТабличногоДокумента.ODS);
Поток.Закрыть();
КонецПроцедуры
Надеюсь, рассмотренные примеры помогут вам справиться с задачей передать файл с клиента на сервере и прочитать файл Excel в 1С.
23.04.2019
Получение таблицы значений из excel в 1С v8, без COM, внешних источников данных и т.д.
EXCELВТаблицуЗначений() — За 10 строчек кода!
Реализация протестирована на 1С 8.3.12.1714 (x64).
WARNING
Данная статья не претендует на оригинальность и не является конечным решением.
Подходы решения задач и примеры программного кода несут исключительно обучающий характер.
Существует масса подходов загрузки данных из EXCEL в 1С. Большинство решений основаны на COM или еще более сложных возможностях платформы.
Для себя разработал наиболее оптимальный вариант:
EXCEL -> Табличный документ -> Построитель запроса -> Таблица значений
Итак, приступим:
- Прочитать Excel файл на клиенте, для передачи на сервер:
&НаКлиенте Процедура ЗагрузитьEXCEL(Команда) Файл = Новый Файл(ПутьКEXCEL); Если НЕ Файл.Существует() Тогда Возврат; КонецЕсли; ДвоичныеДанные = Новый ДвоичныеДанные(ПутьКEXCEL); ДокументРезультат = EXCELВТаблицуЗначений(ДвоичныеДанные, Файл.Расширение); ДокументРезультат.Показать(); КонецПроцедуры
- Выполнить чтение Excel в таблицу значений:
&НаСервере Функция EXCELВТаблицуЗначений(ДвоичныеДанные, Расширение) ФайлEXCELНаСервере = ПолучитьИмяВременногоФайла(Расширение); ДвоичныеДанные.Записать(ФайлEXCELНаСервере); ТабличныйДокумент = Новый ТабличныйДокумент; ТабличныйДокумент.Прочитать(ФайлEXCELНаСервере); УдалитьФайлы(ФайлEXCELНаСервере); ОбластьТаблицы = ТабличныйДокумент.Область(8, 1, ТабличныйДокумент.ВысотаТаблицы, ТабличныйДокумент.ШиринаТаблицы); ПостроительЗапроса = Новый ПостроительЗапроса; ПостроительЗапроса.ИсточникДанных = Новый ОписаниеИсточникаДанных(ОбластьТаблицы); ПостроительЗапроса.Выполнить(); ТаблицаДанных = ПостроительЗапроса.Результат.Выгрузить(); // теперь поссмторим что в Таблице Возврат ТаблицаЗначенийВТабличныйДокумент(ТаблицаДанных); КонецФункции
-
Визуализировать таблицу значений:
&НаСервереБезКонтекста Функция ТаблицаЗначенийВТабличныйДокумент(ТаблицаДанных) ПостроительОтчета = Новый ПостроительОтчета; ПостроительОтчета.ИсточникДанных = Новый ОписаниеИсточникаДанных(ТаблицаДанных); ДокументРезультат = Новый ТабличныйДокумент; Построительотчета.Вывести(ДокументРезультат); Возврат ДокументРезультат; КонецФункции
Описание преобразования данных:
- Получаем исходный файл на клиенте;
- На основании файла создаем двоичные данные и получаем расширение файла;
- Передаем двоичные данные на сервер;
- Создаем дубль файла excel на сервере;
- Читаем файл в новый табличный документ;
- Получаем область табличного документа, где находятся полезные данные (ТабличныйДокумент.Область(8, 1, ТабличныйДокумент.ВысотаТаблицы, ТабличныйДокумент.ШиринаТаблицы));
- Создаем новый построитель запроса и установим в качестве источника данных — область полезных данных;
- Выполним построитель и получим результат запроса;
- Результат запроса выгрузим в таблицу значений.
Плюсы реализации:
- Скорость работы по сравнению с COM EXCEL
- Возможно выполнять загрузку где EXCEL нет вообще (MAC | LINUX | etc…)
- Простота реализации
Чтение файла Excel в 1С 8.х может проводиться несколькими способами. Одним из самых простых способов программного чтения файлов Excel в 1С является подключение через COMобъект.
Перед тем как перейти к процедурам чтения файла Excel, нужно найти его адрес. Для этого удобно воспользоваться стандартным диалогом открытия файла. Нужно создать текстовое поле с достаточной длиной (адреса бывают длинные). В обработчике события НачалоВыбора нужно прописать следующую процедуру.
Процедура ФайлНачалоВыбора(Элемент, ДанныеВыбора, СтандартнаяОбработка)
Диалог = Новый ДиалогВыбораФайла(РежимДиалогаВыбораФайла.Открытие);
Диалог.ПредварительныйПросмотр = Ложь;
Диалог.Фильтр = «(*.xls)|*.xls»;
Если ЗначениеЗаполнено(Файл) Тогда
Диалог.ПолноеИмяФайла= Файл;
КонецЕсли;
Если Диалог.Выбрать() Тогда
Файл= Диалог.ПолноеИмяФайла;
КонецЕсли;
КонецПроцедуры
После этого в реквизите Файл должен находить полный адрес файла Excel.
Допустим, файл содержит две колонки:
- Артикул.
- Наименование товара.
Данные начинаются с 4 строки. Всего строк в файле 5000.
Процедура будет выглядеть так:
Процедура ИмпортироватьЛистФАдрес ()
Ехсел=Новый COMObject(«Excel.Application»);
Книга=Ехсел.Workbooks;
Книга.Open(Файл);
ТЗ=новый ТаблицаЗначений;
ТЗ.Колонки.Добавить(«Артикул»);
ТЗ.Колонки.Добавить(«Наименование»);
Для СчетчикЦикла=4 По 5000 Цикл
НоваяСтрока=ТЗ.Добавить();
НоваяСтрока.Артикул=СокрЛП(Ехсел.Cells(СчетчикЦикла,1).value);
НоваяСтрока.Наименование=СокрЛП(Ехсел.Cells(СчетчикЦикла,2).value);
КонецЦикла;
Ехсел.Application.Quit(); // Если этого не сделать, процесс EXCEL останется в памяти
КонецПроцедуры
Пустые ячейки файла Excel имеют значение Неопределено. Поэтому, если количество строк в файле заранее не известно, но есть уверенность, что записи идут одна за другой и не прерываются пустыми строками, то процедуру можно модифицировать так.
Процедура ИмпортироватьЛистФАдрес ()
Ехсел=Новый COMObject(«Excel.Application»);
Книга=Ехсел.Workbooks;
Книга.Open(Файл);
ТЗ=новый ТаблицаЗначений;
ТЗ.Колонки.Добавить(«Артикул»);
ТЗ.Колонки.Добавить(«Наименование»);
СчетчикЦикла=4;
Пока СокрЛП(Ехсел.Cells(СчетчикЦикла,1).value)<>Неопределено Цикл
НоваяСтрока=ТЗ.Добавить();
НоваяСтрока.Артикул=СокрЛП(Ехсел.Cells(СчетчикЦикла,1).value);
НоваяСтрока.Наименование=СокрЛП(Ехсел.Cells(СчетчикЦикла,2).value);
СчетчикЦикла=СчетчикЦикла+1;
КонецЦикла;
Ехсел.Application.Quit(); // Если этого не сделать, процесс EXCEL останется в памяти
КонецПроцедуры
Кроме того, можно определить количество строк в файле Excel. Это делается так:
Версия = Лев(Ехсел.Version,Найти(Ехсел.Version,«.»)—1);
Если Версия = «8» тогда
ФайлСтрок = Ехсел.Cells.CurrentRegion.Rows.Count;
ФайлКолонок = Макс(Ехсел.Cells.CurrentRegion.Columns.Count, 13);
Иначе
ФайлСтрок = Ехсел.Cells(1,1).SpecialCells(11).Row;
ФайлКолонок = Ехсел.Cells(1,1).SpecialCells(11).Column;
Конецесли;
После этого можно применять полученные значения количества строк и колонок в коде, аналогичном описанному выше.
Процедура ИмпортироватьЛистФАдрес ()
Ехсел=Новый COMObject(«Excel.Application»);
Книга=Ехсел.Workbooks;
Книга.Open(Файл);
Если Версия = «8» тогда
ФайлСтрок = Ехсел.Cells.CurrentRegion.Rows.Count;
ФайлКолонок = Макс(Ехсел.Cells.CurrentRegion.Columns.Count, 13);
Иначе
ФайлСтрок = Ехсел.Cells(1,1).SpecialCells(11).Row;
ФайлКолонок = Ехсел.Cells(1,1).SpecialCells(11).Column;
Конецесли;
ТЗ=новый ТаблицаЗначений;
ТЗ.Колонки.Добавить(«Артикул»);
ТЗ.Колонки.Добавить(«Наименование»);
Для СчетчикЦикла=4 По ФайлСтрок Цикл
НоваяСтрока=ТЗ.Добавить();
НоваяСтрока.Артикул=СокрЛП(Ехсел.Cells(СчетчикЦикла,1).value);
НоваяСтрока.Наименование=СокрЛП(Ехсел.Cells(СчетчикЦикла,2).value);
КонецЦикла;
Ехсел.Application.Quit(); // Если этого не сделать, процесс EXCEL останется в памяти
КонецПроцедуры