Провайдеры данных
Для работы с Excel 2003 (.Xls) можно использовать провайдер Microsoft Jet OLE DB 4.0.
SELECT * FROM OPENROWSET(
'Microsoft.Jet.OLEDB.4.0',
'Excel 12.0;Database=d:tmpTimeSheets.xlsx;HDR=YES;IMEX=1',
'SELECT * FROM [Sheet1$]');
Для работы с Excel 2007 (.Xlsx) — Microsoft ACE OLEDB 12.0.
SELECT * FROM OPENROWSET (
'Microsoft.ACE.OLEDB.12.0',
'Excel 12.0;Database=d:tmpTimeSheets.xlsx;HDR=YES;IMEX=1',
'SELECT * FROM [Sheet1$]');
В Windows 10 открыть настройки источников данных ODBC можно написав «Источники данных ODBC» или через Панель управления Администрирование.
Extended Properties
HDR=YES|NO
. HDR=YES означает, что первую строку листа, следует рассматривать как заголовки колонок. Т.о. значение из первой строки можно использовать как имена полей в sql запросах (любых: select, insert, update, delete).IMEX=1|3
. 1 — открыть соединение для чтения. 3 — для записи.
Создание Linked Server в Sql Server для доступа к Excel
EXEC sp_addLinkedServer
@server= N'XLSX_2010',
@srvproduct = N'Excel',
@provider = N'Microsoft.ACE.OLEDB.12.0',
@datasrc = N'd:tmpTimeSheets.xlsx',
@provstr = N'Excel 12.0; HDR=Yes';
GO
После создания связанного сервера можно будет просмотреть имена доступных листов.
Затем, чтобы обратиться к сервису:
SELECT * FROM OPENQUERY (XLSX_2010, 'Select * from [Sheet1$]')
или
SELECT * FROM [XLSX_2010]...[Лист1$]
Обращение к лиcтам, диапазонам, полям
Для обращения к листу из SQL запроса нужно использовать имя листа, например: [Sheet1$]
или [Лист1$]
. Обращение к диапазону: [Sheet1$A16:F16]
.
Вставка данных в произвольное место
Примеры указания диапазона при вставке строк (insert
)
- [table1$B4:E20]
- [table1$S4:U]
- [table1$F:G]
При вставке должны выполняться следующие условия:
- Первая строчка указанного диапазона дожна входить в диапазон ячеек с данными. Чтобы создать на листе диапазон с данными достаточно в углах некоторого прямоугольного диапазона (в левом верхнем и правом нижнем) вписать значение (C4:I7 на скриншоте). Т.е. сама первая строчка указанного в
insert
диапазона данные содержать не обязана, достаточно, чтобы она просто входила в такой диапазон. Иначе возникнет ошибка"This table contains cells that are outside the range of cells defined in this spreadsheet"
- Хвост диапазона должен содержать пустые строки (хотя бы одну).
Пример: Дан лист, где заполнены только 2 ячейки: C4, I7. После выполнения команды INSERT INTO [table1$E6:G] VALUES(2, 'FF','2014-01-03')
результат будет как на скриншоте. Поясним: строка E6:G6 является первой строкой диапазона для вставки. Она входит в заполненный диапазон C4:I7. Поэтому данные были вставлены на следующей пустой строке — 8. Из этого примера становится ясно, что через OleDb нельзя работать с несколькими независимыми диапазонами на одном листе, используя вставку (update
будет работать).
Ошибки
System.Data.OleDb.OleDbException (0x80004005): Operation must use an updateable query
. Соединение открыто для чтение, при этом происходит попытка внести изменения (выполнить insert, update или delete). Решение: открыть соединение для записи, установив свойство провайдера в строке соединения IMEX=3 (см. выше).System.Data.OleDb.OleDbException (0x80004005): "This table contains cells that are outside the range of cells defined in this spreadsheet"
. Такая ошибка возникает при подпытке обновить (update
) или вставить (insert
) значения в диапазоне, в котором отсутствуют данные на листе.- Если нужно произвести запись в определенные ячейки инструкцией update, то
Ссылки
- https://www.codeproject.com/Tips/705470/Read-and-Write-Excel-Documents-Using-OLEDB
- https://stackoverflow.com/questions/36987636/cannot-create-an-instance-of-ole-db-provider-microsoft-jet-oledb-4-0-for-linked
- https://stackoverflow.com/questions/26267224/the-ole-db-provider-microsoft-ace-oledb-12-0-for-linked-server-null
- http://www.ashishblog.com/importexport-excel-xlsx-or-xls-file-into-sql-server/
- https://yoursandmyideas.com/2011/02/05/how-to-read-or-write-excel-file-using-ace-oledb-data-provider/
- https://stackoverflow.com/questions/46373895/how-to-open-a-huge-excel-file-efficiently Несколько способов открыть большой Excel файл, в т.ч. с помощью OleDb.
CData ADO.NET Provider for Excel
Microsoft ACE OLEDB 12.0
Xlsx files
Connect to Excel 2007 (and later) files with the Xlsx file extension. That is the Office Open XML format with macros disabled.
Provider=Microsoft.ACE.OLEDB.12.0;Data Source=c:myFoldermyExcel2007file.xlsx;Extended Properties="Excel 12.0 Xml;HDR=YES";
Treating data as text
Use this one when you want to treat all data in the file as text, overriding Excels column type «General» to guess what type of data is in the column.
Provider=Microsoft.ACE.OLEDB.12.0;Data Source=c:myFoldermyExcel2007file.xlsx;Extended Properties="Excel 12.0 Xml;HDR=YES;IMEX=1";
Xlsb files
Connect to Excel 2007 (and later) files with the Xlsb file extension. That is the Office Open XML format saved in a binary format. I e the structure is similar but it’s not saved in a text readable format as the Xlsx files and can improve performance if the file contains a lot of data.
Provider=Microsoft.ACE.OLEDB.12.0;Data Source=c:myFoldermyBinaryExcel2007file.xlsb;Extended Properties="Excel 12.0;HDR=YES";
Xlsm files
Connect to Excel 2007 (and later) files with the Xlsm file extension. That is the Office Open XML format with macros enabled.
Provider=Microsoft.ACE.OLEDB.12.0;Data Source=c:myFoldermyExcel2007file.xlsm;Extended Properties="Excel 12.0 Macro;HDR=YES";
Excel 97-2003 Xls files with ACE OLEDB 12.0
You can use this connection string to use the Office 2007 OLEDB driver (ACE 12.0) to connect to older 97-2003 Excel workbooks.
Provider=Microsoft.ACE.OLEDB.12.0;Data Source=c:myFoldermyOldExcelFile.xls;Extended Properties="Excel 8.0;HDR=YES";
Microsoft Jet OLE DB 4.0
Standard (Excel)
Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:MyExcel.xls;Extended Properties="Excel 8.0;HDR=Yes;IMEX=1";
Standard alternative
Try this one if the one above is not working. Some reports that Excel 2003 need the exta OLEDB; section in the beginning of the string.
OLEDB;Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:MyExcel.xls;Extended Properties="Excel 8.0;HDR=Yes;IMEX=1";
.NET Framework Data Provider for OLE DB
Microsoft Excel 2007 ODBC Driver
Standard
Driver={Microsoft Excel Driver (*.xls, *.xlsx, *.xlsm, *.xlsb)};DBQ=C:MyExcel.xlsx;
Standard (for versions 97 — 2003)
Driver={Microsoft Excel Driver (*.xls, *.xlsx, *.xlsm, *.xlsb)};DBQ=C:MyExcel.xls;
Microsoft Excel ODBC Driver
Standard
Driver={Microsoft Excel Driver (*.xls)};DriverId=790;Dbq=C:MyExcel.xls;DefaultDir=c:mypath;
Specify ReadOnly
[Microsoft][ODBC Excel Driver] Operation must use an updateable query. Use this connection string to avoid the error.
Driver={Microsoft Excel Driver (*.xls)};Dbq=C:MyExcel.xls;ReadOnly=0;
.NET Framework Data Provider for ODBC
.NET xlReader for Microsoft Excel
В этой статье опишу как прочитать Excel с помощью OleDB.
Иногда бывает нужно вытянуть таблицу из Excel документа, записать в DataTable для последующей обработки.
Не всегда это удобно делать с помощью циклов, поэтому будем считывать таблицы, содержащиеся в документе и запрашивать из них данные с помощью SQL запросов.
Определение строки подключения
Для разных версий Excel будут свои строки подключения.
Строка подключения для Excel 2007 и более новых версий
//Можно использовать, если количество строк менее 65536 Provider=Microsoft.ACE.OLEDB.12.0;Data Source={0};Extended Properties='Excel 8.0;HDR=Yes' //Если строк больше 65536 Provider=Microsoft.ACE.OLEDB.12.0;Data Source={0}; Extended Properties="Excel 12.0 Xml;HDR=YES";
Для работы с данными версиями необходимо установить Microsoft Access Database Engine 2010 Redistributable.
Так же C# может выбрасывать исключения по поводу недостающих драйверов. В этом случае необходимо скачать соответствующие драйверы с сайта Microsoft.
Строка подключения для более ранних версий
Строка подключения для Excel версии 2003 может иметь такой вид:
Provider=Microsoft.Jet.OLEDB.4.0;Data Source={0};Extended Properties='Excel 8.0;HDR=Yes'
Если C# выбросит исключение, скачайте недостающий драйвер, Visual Studio подскажет, какой.
Как сделать SQL запрос из таблицы Excel
Для выполнения SQL запроса нужно найти таблицу в документе и выполнить к ней запрос:
//Объявляем OleDB соединение using(OleDbConnection conn = new OleDbConnection(conStr)) { //Открываем подключение conn.Open(); //Запрашиваем таблицы DataTable schemaTable = conn.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, new object[] { null, null, null, "TABLE" }); DataRow schemaRow = schemaTable.Rows[0]; //Получаеи имя таблицы string sheet = schemaRow["TABLE_NAME"].ToString(); //Объявляем команду OleDbCommand com = conn.CreateCommand(); //Создаем SQL запрос com.CommandText = "SELECT * FROM [" + sheet + "]"; //Выполняем SQL запрос OleDbDataReader reader = com.ExecuteReader(); //Записываем результат в DataTable DataTable table = new DataTable(); table.Load(reader); //Выводим DataTable в таблицу на форму (если нужно) gridControl1.DataSource = table; }
На этом шаге мы имеем считанные данные из Excel документа в DataTable.
После обработки данных можно сохранить данные в другой документ или оформить сводную таблицу.
Как работать с Excel с помощью C# обсуждалось ранее.
Так же можете посмотреть, как работать со сводными таблицами в Excel с помощью C# и редактора VBA, встроенного в Excel.
Просмотрено:
7 446
Содержание
- Подключение файлов MS Excel
- Содержание
- Подключение с помощью Microsoft.ACE.OLEDB.12.0
- Линковка Excel к MSSQL
- Подключение с помощью Microsoft Jet 4.0 Ole DB Provider
- Импорт данных из Excel в SQL Server или базу данных Azure
- Список методов
- Мастер импорта и экспорта
- Службы Integration Services (SSIS)
- OPENROWSET и связанные серверы
- Распределенные запросы
- Связанные серверы
- Предварительное требование — сохранение данных Excel как текст
- Мастер импорта неструктурированных файлов
- Команда BULK INSERT
- Средство BCP
- Мастер копирования (ADF)
- Фабрика данных Azure
- Распространенные ошибки
- «Microsoft.ACE.OLEDB.12.0» не зарегистрирован
- Не удалось создать экземпляр поставщика OLE DB «Microsoft.ACE.OLEDB.12.0» для связанного сервера «(null)».
- 32-разрядный поставщик OLE DB «Microsoft.ACE.OLEDB.12.0» не может быть загружен в процессе на 64-разрядной версии SQL Server.
- Поставщик OLE DB «Microsoft.ACE.OLEDB.12.0» для связанного сервера «(null)» сообщил об ошибке.
- Не удалось проинициализировать объект источника данных поставщика OLE DB «Microsoft.ACE.OLEDB.12.0» для связанного сервера «(null)».
Подключение файлов MS Excel
Содержание
Подключение с помощью Microsoft.ACE.OLEDB.12.0
Провайдер данных Microsoft.ACE.OLEDB.12.0 подходит как для 32-битных, так и для 64 -битных версий SQL-сервера.
В данном параграфе описывается пример подключения Excel-файла sample.xlsx как связанного сервера на примере MSSQL 2008 SP3 x64.
Шаг 1. Для начала работы скачайте установочные файлы провайдера Microsoft.ACE.OLEDB.12.0 по ссылке http://www.microsoft.com/en-us/download/details.aspx?id=13255.
Если у вас 64-битная версия SQL Server используйте установочный файл AccessDatabaseEngine_x64.exe.
Шаг 2. Для установки провайдера используйте запуск файла через командную строку с ключом /passive.
Шаг 3. Получить данные напрямую из файла можно с помощью команды OPENROWSET
Изменить данные можно с помощью запроса:
Убедитесь, что в Excel есть указанное поле [id]. Часто бывает, что столбцы называются [F15]
Ввести строку можно с помощью запроса:
Количество столбцов в Excel и в возвращаемом запросе select должно совпадать.
ВНИМАНИЕ: При возникновении ошибки Cannot get the column information from OLE DB provider «Microsoft.ACE.OLEDB.12.0» for linked server «(null)» выполните следующий запрос:
ВНИМАНИЕ: При возникновении ошибки SQL Server заблокировал доступ к STATEMENT «OpenRowset/OpenDatasource» компонента «Ad Hoc Distributed Queries», поскольку он отключен в результате настройки конфигурации безопасности сервера выполните поочередно два запроса.
Линковка Excel к MSSQL
Чтобы прилинковать Excel файл выполните следующие запросы в SQL Server Management Studio
- XlsLnkSrv — название связанного сервера
- C:Sample.xlsx — абсолютный путь к требуемому Excel-файлу
Если все выполнено правильно, то после обновления обозревателя объектов вы увидите название установленного поставщика Microsoft.ACE.OLEDB.12.0 в Объекты сервера / Связанные серверы / Поставщики
Считать данные можно с помощью команды openquery:
Подключение с помощью Microsoft Jet 4.0 Ole DB Provider
Технология Jet 4.0 работает только на 32-битных версиях MSSQL.
Для создания связанного сервера используйте следующий SQL-запрос:
- ExcelSource — название связанного сервера
- c:MyDataDistExcl.xls — абсолютный путь к Excel-файлу
Для получения данных из Excel файла используется запрос:
Источник
Импорт данных из Excel в SQL Server или базу данных Azure
Применимо к: база данных SQL ServerAzure SQL
Импортировать данные из файлов Excel в SQL Server или базу данных SQL Azure можно несколькими способами. Некоторые методы позволяют импортировать данные за один шаг непосредственно из файлов Excel. Для других методов необходимо экспортировать данные Excel в виде текста (CSV-файла), прежде чем их можно будет импортировать.
В этой статье перечислены часто используемые методы и содержатся ссылки для получения дополнительных сведений. Однако в ней не указано полное описание таких сложных инструментов и служб, как SSIS или Фабрика данных Azure. Дополнительные сведения об интересующем вас решении доступны по ссылкам ниже.
Список методов
Существует несколько способов импортировать данные из Excel. Для использования некоторых из этих инструментов может понадобиться установка SQL Server Management Studio (SSMS).
Для импорта данных из Excel можно использовать следующие средства:
Сначала экспортировать в текст (SQL Server и база данных SQL) | Непосредственно из Excel (только в локальной среде SQL Server) |
---|---|
Мастер импорта неструктурированных файлов | мастер импорта и экспорта SQL Server |
Инструкция BULK INSERT | Службы SQL Server Integration Services |
BCP | Функция OPENROWSET |
Мастер копирования (Фабрика данных Azure) | |
Фабрика данных Azure. |
Если вы хотите импортировать несколько листов из книги Excel, обычно нужно запускать каждое из этих средств отдельно для каждого листа.
Дополнительные сведения см. в разделе Ограничения и известные проблемы загрузки данных в файлы Excel или из них.
Мастер импорта и экспорта
Импортируйте данные напрямую из файлов Excel с помощью мастера импорта и экспорта SQL Server. Также можно сохранить параметры в виде пакета SQL Server Integration Services (SSIS), который можно настроить и использовать повторно в будущем.
В SQL Server Management Studio подключитесь к экземпляру SQL Server Компонент Database Engine.
Разверните узел Базы данных.
Щелкните базу данных правой кнопкой мыши.
Наведите указатель мыши на пункт Задачи.
Выберите Импортировать данные или Экспортировать данные:
Дополнительные сведения см. в следующих статьях:
Службы Integration Services (SSIS)
Если вы работали с SQL Server Integration Services (SSIS) и не хотите запускать мастер импорта и экспорта SQL Server, создайте пакет SSIS, который использует в потоке данных источник «Excel» и назначение «SQL Server».
Дополнительные сведения см. в следующих статьях:
Чтобы научиться создавать пакеты SSIS, см. руководство How to Create an ETL Package (Как создать пакет ETL).
OPENROWSET и связанные серверы
В базе данных SQL Azure невозможно импортировать данные непосредственно из Excel. Сначала необходимо экспортировать данные в текстовый файл (CSV).
Поставщик ACE (прежнее название — поставщик Jet), который подключается к источникам данных Excel, предназначен для интерактивного клиентского использования. Если поставщик ACE используется на сервере SQL Server, особенно в автоматизированных процессах или процессах, выполняющихся параллельно, вы можете получить непредвиденные результаты.
Распределенные запросы
Импортируйте данные напрямую из файлов Excel в SQL Server с помощью функции Transact-SQL OPENROWSET или OPENDATASOURCE . Такая операция называется распределенный запрос.
В базе данных SQL Azure невозможно импортировать данные непосредственно из Excel. Сначала необходимо экспортировать данные в текстовый файл (CSV).
Перед выполнением распределенного запроса необходимо включить параметр ad hoc distributed queries в конфигурации сервера, как показано в примере ниже. Дополнительные сведения см. в статье ad hoc distributed queries Server Configuration Option (Параметр конфигурации сервера «ad hoc distributed queries»).
В приведенном ниже примере кода данные импортируются из листа Excel Sheet1 в новую таблицу базы данных с помощью OPENROWSET .
Ниже приведен тот же пример с OPENDATASOURCE .
Чтобы добавить импортированные данные в существующую таблицу, а не создавать новую, используйте синтаксис INSERT INTO . SELECT . FROM . вместо синтаксиса SELECT . INTO . FROM . из предыдущих примеров.
Для обращения к данным Excel без импорта используйте стандартный синтаксис SELECT . FROM . .
Дополнительные сведения о распределенных запросах см. в указанных ниже разделах.
- Распределенные запросы (Распределенные запросы по-прежнему поддерживаются в SQL Server 2019, но документация по этой функции не обновляется.)
- OPENROWSET
- OPENDATASOURCE
Связанные серверы
Кроме того, можно настроить постоянное подключение от SQL Server к файлу Excel как к связанному серверу. В примере ниже данные импортируются из листа Excel Data на существующем связанном сервере EXCELLINK в новую таблицу базы данных SQL Server с именем Data_ls .
Вы можете создать связанный сервер в SQL Server Management Studio или запустить системную хранимую процедуру sp_addlinkedserver , как показано в примере ниже.
Дополнительные сведения о связанных серверах см. в указанных ниже разделах.
Дополнительные примеры и сведения о связанных серверах и распределенных запросах см. в следующем разделе:
Предварительное требование — сохранение данных Excel как текст
Чтобы использовать другие методы, описанные на этой странице (инструкцию BULK INSERT, средство BCP или фабрику данных Azure), сначала экспортируйте данные Excel в текстовый файл.
В Excel выберите Файл | Сохранить как , а затем выберите текст (с разделителями табуляции) (*.txt) или CSV (с разделителями-запятыми) (*.csv) в качестве целевого типа файла.
Если вы хотите экспортировать несколько листов из книги, выполните эту процедуру для каждого листа. Команда Сохранить как экспортирует только активный лист.
Чтобы оптимизировать использование средств импорта, сохраняйте листы, которые содержат только заголовки столбцов и строки данных. Если сохраненные данные содержат заголовки страниц, пустые строки, заметки и пр., позже при импорте данных вы можете получить непредвиденные результаты.
Мастер импорта неструктурированных файлов
Импортируйте данные, сохраненные как текстовые файлы, выполнив инструкции на страницах мастера импорта неструктурированных файлов.
Как было описано выше в разделе Предварительное требование, необходимо экспортировать данные Excel в виде текста, прежде чем вы сможете импортировать их с помощью мастера импорта неструктурированных файлов.
Дополнительные сведения о мастере импорта неструктурированных файлов см. в разделе Мастер импорта неструктурированных файлов в SQL.
Команда BULK INSERT
BULK INSERT — это команда Transact-SQL, которую можно выполнить в SQL Server Management Studio. В приведенном ниже примере данные загружаются из файла Data.csv с разделителями-запятыми в существующую таблицу базы данных.
Как было описано выше в разделе Предварительное требование, необходимо экспортировать данные Excel в виде текста, прежде чем вы сможете использовать BULK INSERT для их импорта. BULK INSERT не может считывать файлы Excel напрямую. С помощью команды BULK INSERT можно импортировать CSV-файл, который хранится локально или в хранилище BLOB-объектов Azure.
Дополнительные сведения и примеры для SQL Server и базы данных SQL см. в следующих разделах:
Средство BCP
BCP — это программа, которая запускается из командной строки. В приведенном ниже примере данные загружаются из файла Data.csv с разделителями-запятыми в существующую таблицу базы данных Data_bcp .
Как было описано выше в разделе Предварительное требование, необходимо экспортировать данные Excel в виде текста, прежде чем вы сможете использовать BCP для их импорта. BCP не может считывать файлы Excel напрямую. Используется для импорта в SQL Server или базу данных SQL из текстового файла (CSV), сохраненного в локальном хранилище.
Для текстового файла (CSV), хранящегося в хранилище BLOB-объектов Azure, используйте BULK INSERT или OPENROWSET. Примеры см. в разделе Пример.
Дополнительные сведения о программе BCP см. в указанных ниже разделах.
Мастер копирования (ADF)
Импортируйте данные, сохраненные как текстовые файлы, с помощью пошаговой инструкции мастера копирования Фабрики данных Azure (ADF).
Как было описано выше в разделе Предварительное требование, необходимо экспортировать данные Excel в виде текста, прежде чем вы сможете использовать фабрику данных Azure для их импорта. Фабрика данных не может считывать файлы Excel напрямую.
Дополнительные сведения о мастере копирования см. в указанных ниже разделах.
Фабрика данных Azure
Если вы уже работали с фабрикой данных Azure и не хотите запускать мастер копирования, создайте конвейер с действием копирования из текстового файла в SQL Server или Базу данных SQL Azure.
Как было описано выше в разделе Предварительное требование, необходимо экспортировать данные Excel в виде текста, прежде чем вы сможете использовать фабрику данных Azure для их импорта. Фабрика данных не может считывать файлы Excel напрямую.
Дополнительные сведения об использовании этих источников и приемников фабрики данных см. в указанных ниже разделах.
Чтобы научиться копировать данные с помощью фабрики данных Azure, см. указанные ниже разделы.
Распространенные ошибки
«Microsoft.ACE.OLEDB.12.0» не зарегистрирован
Эта ошибка возникает, так как не установлен поставщик OLE DB. Установите его через Распространяемый пакет ядра СУБД Microsoft Access 2010. Не забудьте установить 64-разрядную версию, если Windows и SQL Server — 64-разрядные.
Полный текст ошибки.
Не удалось создать экземпляр поставщика OLE DB «Microsoft.ACE.OLEDB.12.0» для связанного сервера «(null)».
Это означает, что Microsoft OLEDB не был настроен должным образом. Чтобы устранить проблему, выполните приведенный ниже код Transact-SQL.
Полный текст ошибки.
32-разрядный поставщик OLE DB «Microsoft.ACE.OLEDB.12.0» не может быть загружен в процессе на 64-разрядной версии SQL Server.
Это происходит, когда 32-разрядная версия поставщика OLD DB устанавливается вместе с 64-разрядной версией SQL Server. Чтобы устранить эту проблему, удалите 32-разрядную версию и вместо нее установите 64-разрядную версию поставщика OLE DB.
Полный текст ошибки.
Поставщик OLE DB «Microsoft.ACE.OLEDB.12.0» для связанного сервера «(null)» сообщил об ошибке.
Не удалось проинициализировать объект источника данных поставщика OLE DB «Microsoft.ACE.OLEDB.12.0» для связанного сервера «(null)».
Обе эти ошибки обычно указывают на ошибку разрешений между процессом SQL Server и файлом. Убедитесь, что учетная запись, с которой выполняется служба SQL Server, имеет разрешение на полный доступ к файлу. Мы не рекомендуем импортировать файлы с настольного компьютера.
Источник
This article simplifies your work with MS Excel (both xls and xlsx) using Oledb and Microsoft Data Access. Simple demonstration to create/modify/delete Excel for both windows and web is provided.
- Sample tool in C# with XLSX (Office 2007) support — 24.99 KB
- Sample tool in C# — 24.61 KB
- Sample tool in VB.NET with XLSX (Office 2007) Support — 26.88 KB
- Sample tool for VB.NET — 26.28 KB
- Sample CreateWorkBook download in ASP.NET — 21.62 KB
Table of Contents
- Introduction
- Available Ways to work with Excel Workbooks
- Background
- Working with Excel Workbook
- Anatomy of ConnectionString
- Creating Excel Workbook
- Getting Schema Definition
- Retrieve Data By Worksheet Name
- Retrieve Data Using Range
- Manipulating Data (Insert / Update / Delete)
- Drop Excel Worksheet
- Description and Usage of Sample Tool
- Code Explanation and Usage Info
- History
Introduction
Hi folks. It’s been a while since I wrote my last article. Meanwhile, I came across a lot of stuff, and want to share it with you. This article is regarding all we need to work with Excel through our programs.
While searching Google for this topic, I came across some of the links, but none of them gave a clear and concise idea of how to work with data in Excel in the easiest way from .NET. So I decided to jot down everything that may appear with this topic in this article.
To Work With Excel Workbooks, You Can Do Through Three Different Ways
You need 3rd party library which acts as an interface between your program and the Excel.
- You can make use of Excel InterOp Objects, but this requires you to have Excel installed in the development environment. This is a binding if you are going to make a product which is to be distributed.
- You can use OleDb data providers for Excel which comes for free with Windows. But there is one limitation though, you can access only data using this technique. You cannot do formatting through this technique.
- You can use XML to create Excel objects which will open in MSExcel correctly. This is easier, just you need to work with XML through programming. It also supports XML stylesheets. I will also try to discuss this in another article, for the time being, you may look into ExcelXMLDemo.
In this topic, I am going to discuss about the 3rd method which is the most common one that we use while working with Excel.
Background
Excel is the most common and popular format of showing data to the client nowadays. After the most common one (PDF), you need to place another format which may show the reports to the client. Excel would be the right choice for that. Now we often come up with a requirement to generate the data in an Excel Workbook. Recently while developing, I got one requirement to dump some data in Excel sheet. Thus I thought of writing this one.
Another important requirement is to read data from MS Excel 2007 format, which is also an unusual task to learn the entire structure of Excel 2007 objects. Using MDac, one can easily work with both of them without changing any of the code whatsoever.
Working with Excel Workbook
The rows and columns of Excel workbook closely resemble the rows and columns of a database table. We can use MDac (Microsoft Data Access Tool) that comes free with Windows update to work with Excel worksheet. In case of Excel Workbooks, each worksheet acts as a table and each workbook is actually a database. You can create, insert drop Excel objects through OleDb
data clients from your program.
Now Let Us See How the connectionstring Will Look Like
Normal ConnectionString: (work for xls files)
Provider=Microsoft.Jet.OLEDB.4.0;Data Source={0};Extended Properties="Excel 8.0;HDR=YES;""
Office 2007 ConnectionString : (work for xlsx files)
Provider=Microsoft.ACE.OLEDB.12.0;Data Source={0}; Extended Properties="Excel 12.0;HDR=YES;""
Here, Data Source will be placed with a proper filename like C:\test.xls or C:\test.xlsx. If you want to create a workbook, just place the one that is not existing and use Create Table to create a workbook.
The connectionstring has some parts:
- Provider: It is the main
oledb
provider that is used to open the Excel sheet. This will beMicrosoft.Jet.OLEDB.4.0
for Excel 97 onwards Excel file format andMicrosoft.ACE.OLEDB.12.0
for Excel 2007 or higher Excel file format (One with xlsx extension) - Data Source: It is the entire path of the Excel workbook. You need to mention a dospath that corresponds to an Excel file. Thus, it will look like:
Data Source=C:\testApp.xls"
. - Extended Properties (Optional): Extended properties can be applied to Excel workbooks which may change the overall activity of the Excel workbook from your program. The most common ones are the following:
- HDR: It represents Header of the fields in the Excel table. Default is
YES
. If you don’t have fieldnames in the header of your worksheet, you can specifyHDR=NO
which will take the columns of the tables that it finds as f1,f2 etc. - ReadOnly: You can also open Excel workbook in readonly mode by specifying
ReadOnly=true;
By default,Readonly
attribute isfalse
, so you can modify data within your workbook. - FirstRowHasNames: It is the same as HDR, it is always set to
1
( which meanstrue
) you can specify it asfalse
if you don’t have your header row. If HDR is YES, provider disregards this property. You can change the default behaviour of your environment by changing the Registry Value[HKLMSoftwareMicrosoftJet4.0EnginesExcelFirstRowHasNames]
to00
(which isfalse
) - MaxScanRows: Excel does not provide the detailed schema defination of the tables it finds. It need to scan the rows before deciding the data types of the fields.
MaxScanRows
specifies the number of cells to be scanned before deciding the data type of the column. By default, the value of this is8
. You can specify any value from 1 — 16 for 1 to 16 rows. You can also make the value to0
so that it searches all existing rows before deciding the data type. You can change the default behaviour of this property by changing the value of[HKLMSoftwareMicrosoftJet4.0EnginesExcelTypeGuessRows]
which is 8 by default. Currently,MaxScanRows
is ignored, so you need only to depend onTypeGuessRows
Registry value. Hope Microsoft fixes this issue to its later versions. - IMEX: (A Caution) As mentioned above, Excel will have to guess a number or rows to select the most appropriate data type of the column, a serious problem may occur if you have mixed data in one column. Say you have data of both integer and text on a single column, in that case, Excel will choose its data type based on majority of the data. Thus it selects the data for the majority data type that is selected, and returns
NULL
for the minority data type. If the two types are equally mixed in the column, the provider chooses numeric over text.For example, in your eight (8) scanned rows, if the column contains five (5) numeric values and three (3) text values, the provider returns five (5) numbers and three (3) null values.
To work around this problem for data, set «
IMEX=1
» in the Extended Properties section of the connection string. This enforces theImportMixedTypes=Text
registry setting. You can change the enforcement of type by changing[HKLMSoftwareMicrosoftJet4.0EnginesExcelImportMixedTypes]
to numeric as well.Thus if you look into the simple connectionstring with all of them, it will look like:
Provider=Microsoft.Jet.OLEDB.4.0;Data Source=c:\testexcel.xls; Extended Properties="Excel 8.0;HDR=YES;IMEX=1;MAXSCANROWS=15;READONLY=FALSE""
or:
Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\testexcel.xlsx; Extended Properties="Excel 12.0;HDR=YES;IMEX=1;MAXSCANROWS=15;READONLY=FALSE""
We need to place extended properties into Quotes(«) as there are multiple number of values.
- HDR: It represents Header of the fields in the Excel table. Default is
Can We Create Excel Workbook through this Technique?
If you are eager to know if we can create Excel workbook directly through OleDB, your answer is yes. The only thing that you need to do is to specify a non-existing file in the Data Source of the connectionstring
.
string connectionstring = "Provider=Microsoft.Jet.OLEDB.4.0; Data Source=c:\testexcel.xls; Extended Properties"Excel 8.0;HDR=YES""; string createTableScript = "CREATE TABLE newTable(a1 MEMO,a2 INT,a3 CHAR(255))"; using(conObj = new OleDbConnection(connectionstring)) { using (OleDbCommand cmd = new OleDbCommand(createTableScript, conObj) { if (this.Connection.State != ConnectionState.Open) this.Connection.Open(); cmd.ExecuteNonQuery(); } }
This will create a new workbook with one worksheet if the datasource file (testexcel.xls) is not existing in the location.
To Retrieve Schema Information of Excel Workbook
You can get the worksheets that are present in the Excel workbook using GetOleDbSchemaTable
. Use the following snippet:
DataTable dtSchema = null; dtSchema = conObj.GetOleDbSchemaTable( OleDbSchemaGuid.Tables, new object[] { null, null, null, "TABLE" });
Here dtSchema
will hold the list of all workbooks. Say we have two workbooks: wb1
, wb2
. The above code will return a list of wb1
, wb1$
, wb2
, wb2$
. We need to filter out $
elements.
Selecting Data From a WorkBook (Specifying Range)
You can run a simple query to select Data from an Excel workbook. Say your workbook contains tables like w1
, w2
. Now, if write SELECT * FROM [w1]
or SELECT * FROM 'w1'
, it will return you the whole datatable with all the data.
You Can Also Specify the Range of Selection, Just Write Query Like
SELECT * FROM [w1$A10:B10]
Thus it will select the data only from Excel Cell A10 : B10 Range.
string cmdText = "SELECT * FROM [w1$A10:B10]"; using(OleDbCommand cmd = new OleDbCommand(cmdText)) { cmd.Connection = this.Connection; OleDbDataAdapter adpt = new OleDbDataAdapter(cmd); DataSet ds = new DataSet(); adpt.Fill(ds,"w1"); }
NOTE
A caution about specifying worksheets: The provider assumes that your table of data begins with the upper-most, left-most, non-blank cell on the specified worksheet. In other words, your table of data can begin in Row 3, Column C without a problem. However, you cannot, for example, type a worksheeet title above and to the left of the data in cell A1.
A caution about specifying ranges: When you specify a worksheet as your source, the provider adds new records below existing records in the worksheet as space allows. When you specify a range (named or unnamed), Jet also adds new records below the existing records in the range as space allows. However, if you re-query on the original range, the resulting recordset does not include the newly added records outside the range. Using MDAC, you cannot add new rows beyond the defined limits of the range, otherwise, you will receive Exception: "Cannot expand named range"
Running DML Statement
You can run any DML statement in the same way you do for other databases. Samples:
INSERT INTO [w1] VALUES('firsttextcol', 2, '4/11/2009', '10:20');
[We assume First Column is either memo or Char field, 2nd col is int, 3rd is Date, 4th is Time data type]
DELETE FROM [w1] Where secondintcol=2; UPDATE [w1] SET secondintcol = 3 where firsttextcol = 'firsttextcol';
We can use []
(Square brackets) to allow spaces within columnnames
and tablenames
as we do for databases.
Droping Excel WorkSheet
To Drop an Excel Worksheet, Just Use
Drop Table [w1]
This will drop the worksheet.
If this is the last worksheet, it will not delete the workbook file. You need to do it yourself.
Using the Sample Tool
I have added one sample application that demonstrates the problem. It includes one class called ExcelObject
which allows you to work with Excel. You can use the code to work in your own application easily.
- Choose Browse and select an xls file. If you want to create the workbook, just click on Create table to Create a table with workbook.
- Click on Retrieve to get the Tables present in the workbook. These are mainly worksheets.
- You can create tables using the window. Just write the column name and click on Insert. Specify Tablename and a new worksheet will be created for you.
- Generate Insert statements from the dynamic screen.
- You can use Go to get the data loaded into the Grid.
NOTE
This is just a demo application. You can use the Class associated with the application call functions to do your job easy.
Using the Code
The code for ExcelObject
Class will be like this:
using System.IO; using System.Data.OleDb; using System.Text; using System.Data; using System.Windows.Forms; public class ExcelObject { private string excelObject = = "Provider=Microsoft.{0}.OLEDB.{1};Data Source={2}; Extended Properties="Excel {3};HDR=YES""; private string filepath = string.Empty; private OleDbConnection con = null; public delegate void ProgressWork(float percentage); private event ProgressWork Reading; private event ProgressWork Writeing; private event EventHandler connectionStringChange; public event ProgressWork ReadProgress { add { Reading += value; } remove { Reading -= value; } } public virtual void onReadProgress(float percentage) { if (Reading != null) Reading(percentage); } public event ProgressWork WriteProgress { add{ Writeing += value; } remove{ Writeing -= value; } } public virtual void onWriteProgress(float percentage) { if (Writeing != null) Writeing(percentage); } public event EventHandler ConnectionStringChanged { add{ connectionStringChange += value; } remove { connectionStringChange -= value; } } public virtual void onConnectionStringChanged() { if (this.Connection != null && !this.Connection.ConnectionString.Equals(this.ConnectionString)) { if (this.Connection.State == ConnectionState.Open) this.Connection.Close(); this.Connection.Dispose(); this.con = null; } if (connectionStringChange != null) { connectionStringChange(this, new EventArgs()); } } public string ConnectionString { get { if (!(this.filepath == string.Empty)) { FileInfo fi = new FileInfo(this.filepath); if (fi.Extension.Equals(".xls")) { return string.Format(this.excelObject, "Jet", "4.0", this.filepath, "8.0"); } else if (fi.Extension.Equals(".xlsx")) { return string.Format(this.excelObject, "Ace", "12.0", Me.filepath, "12.0"); } } else { return string.Empty; } } } public OleDbConnection Connection { get { if (con == null) { OleDbConnection _con = new OleDbConnection { ConnectionString = this.ConnectionString }; this.con = _con; } return this.con; } } public ExcelObject(string path) { this.filepath = path; this.onConnectionStringChanged(); } public DataTable GetSchema() { DataTable dtSchema = null; if (this.Connection.State != ConnectionState.Open) this.Connection.Open(); dtSchema = this.Connection.GetOleDbSchemaTable( OleDbSchemaGuid.Tables, new object[] { null, null, null, "TABLE" }); return dtSchema; } public DataTable ReadTable(string tableName) { return this.ReadTable(tableName, ""); } public DataTable ReadTable(string tableName, string criteria) { try { DataTable resultTable = null; if (this.Connection.State != ConnectionState.Open) { this.Connection.Open(); onReadProgress(10); } string cmdText = "Select * from [{0}]"; if (!string.IsNullOrEmpty(criteria)) { cmdText += " Where " + criteria; } OleDbCommand cmd = new OleDbCommand(string.Format(cmdText, tableName)); cmd.Connection = this.Connection; OleDbDataAdapter adpt = new OleDbDataAdapter(cmd); onReadProgress(30); DataSet ds = new DataSet(); onReadProgress(50); adpt.Fill(ds, tableName); onReadProgress(100); if (ds.Tables.Count == 1) { return ds.Tables[0]; } else { return null; } } catch { MessageBox.Show("Table Cannot be read"); return null; } } public bool DropTable(string tablename) { try { if (this.Connection.State != ConnectionState.Open) { this.Connection.Open(); onWriteProgress(10); } string cmdText = "Drop Table [{0}]"; using (OleDbCommand cmd = new OleDbCommand( string.Format(cmdText, tablename), this.Connection)) { onWriteProgress(30); cmd.ExecuteNonQuery(); onWriteProgress(80); } this.Connection.Close(); onWriteProgress(100); return true; } catch (Exception ex) { onWriteProgress(0); MessageBox.Show(ex.Message); return false; } } public bool WriteTable(string tableName, Dictionary<string, string> tableDefination) { try { using (OleDbCommand cmd = new OleDbCommand( this.GenerateCreateTable(tableName, tableDefination), this.Connection)) { if (this.Connection.State != ConnectionState.Open) this.Connection.Open(); cmd.ExecuteNonQuery(); return true; } } catch { return false; } } public bool AddNewRow(DataRow dr) { using (OleDbCommand cmd = new OleDbCommand( this.GenerateInsertStatement(dr), this.Connection)) { cmd.ExecuteNonQuery(); } return true; } private string GenerateCreateTable(string tableName, Dictionary<string, string> tableDefination) { StringBuilder sb = new StringBuilder(); bool firstcol = true; sb.AppendFormat("CREATE TABLE [{0}](", tableName); firstcol = true; foreach (KeyValuePair<string, string> keyvalue in tableDefination) { if (!firstcol) { sb.Append(","); } firstcol = false; sb.AppendFormat("{0} {1}", keyvalue.Key, keyvalue.Value); } sb.Append(")"); return sb.ToString(); } private string GenerateInsertStatement(DataRow dr) { StringBuilder sb = new StringBuilder(); bool firstcol = true; sb.AppendFormat("INSERT INTO [{0}](", dr.Table.TableName); foreach (DataColumn dc in dr.Table.Columns) { if (!firstcol) { sb.Append(","); } firstcol = false; sb.Append(dc.Caption); } sb.Append(") VALUES("); firstcol = true; for (int i = 0; i <= dr.Table.Columns.Count - 1; i++) { if (!object.ReferenceEquals(dr.Table.Columns[i].DataType, typeof(int))) { sb.Append("'"); sb.Append(dr[i].ToString().Replace("'", "''")); sb.Append("'"); } else { sb.Append(dr[i].ToString().Replace("'", "''")); } if (i != dr.Table.Columns.Count - 1) { sb.Append(","); } } sb.Append(")"); return sb.ToString(); } }
After looking through the code you are clear that we are actually generating DDL and DML statements based on the Schema Definition. I know we can easily do this using OleDbCommandBuilder
object, but I thought of making them myself. Functions exposed through this class are:
Methods
GetSchema
: It returns the Schema defination datatable of the currently selected xls file. You can call this if you have connected with an existing Excel Workbook.ReadTable
: It automatically generatesSelect
statement on the tablename passed and based on the criteria provided. It returns theDataTable
of the currently selected Excel worksheet.DropTable
: Drops the table name passed, and which results in actual deletion of one worksheet from the workbook. The Function returnstrue
if successful.AddNewRow
: This function creates anInsert
statement and inserts a new row based on theDataRow
passed in.
Properties
ConnectionString
: You can getconnectionstring
of thefilepath
passed.Connection
: ReturnsOleDbConnection
Object.
Events
ReadProgress
: It generates a callback to the calling procedure on the percentage of Read of the file. You can handle this event to get the percentage progress value.WriteProgress
: Same asReadProgress
, only it is called during actual insert of data.ConnectionStringChanged
: This event occurs ifFileName
is changed somehow or a new file is created.
I have also provided the same class in VB.NET for those people who wants it in VB.NET.
You can find both of them from here:
Version 1
- Download ExcelWrite_Csharp.zip — 24.61 KB
- Download ExcelWrite_VB.NET.zip — 26.28 KB
Version 2
- Download ExcelWrite_Csharp_V2.zip — 24.99 KB
- Download ExcelWrite_VBNET_V2.zip — 26.88 KB
- I have also added one example for ASP.NET users to dynamically create one Excel file and download it to clients.
You can find that from here:
- Download ExcelDownload.zip — 21.62 KB
History
- 7th June, 2009: First release
- Looking forward to updating the article with new things. Hope you like this article.
- 10th June, 2009: Second release
- Support for xlsx files (Office 2007 Files). Hope this would help you.
Наверх
Содержание
- 1 Подключение с помощью Microsoft.ACE.OLEDB.12.0
- 2 Линковка Excel к MSSQL
- 3 Подключение с помощью Microsoft Jet 4.0 Ole DB Provider
Подключение с помощью Microsoft.ACE.OLEDB.12.0
Провайдер данных Microsoft.ACE.OLEDB.12.0 подходит как для 32-битных, так и для 64 -битных версий SQL-сервера.
В данном параграфе описывается пример подключения Excel-файла sample.xlsx как связанного сервера на примере MSSQL 2008 SP3 x64.
Шаг 1. Для начала работы скачайте установочные файлы провайдера Microsoft.ACE.OLEDB.12.0 по ссылке http://www.microsoft.com/en-us/download/details.aspx?id=13255.
Если у вас 64-битная версия SQL Server используйте установочный файл AccessDatabaseEngine_x64.exe.
Шаг 2. Для установки провайдера используйте запуск файла через командную строку с ключом /passive.
C:AccessDatabaseEngine_x64.exe /passive
Шаг 3. Получить данные напрямую из файла можно с помощью команды OPENROWSET
select * from OPENROWSET('Microsoft.ACE.OLEDB.12.0', 'Excel 8.0; HDR=Yes; Database=C:Sample.xlsx', 'Select * from [Sheet1$]')
Изменить данные можно с помощью запроса:
UPDATE OPENROWSET('Microsoft.ACE.OLEDB.12.0', 'Excel 8.0; HDR=Yes; Database=C:Sample.xlsx', 'Select * from [Sheet1$]') SET id='123456' WHERE phone='84952294989'
Убедитесь, что в Excel есть указанное поле [id]. Часто бывает, что столбцы называются [F15]
Ввести строку можно с помощью запроса:
INSERT INTO OPENROWSET('Microsoft.ACE.OLEDB.12.0', 'Excel 12.0;Database=C:Sample.xlsx', 'Select * from [Sheet1$]') SELECT id, phone, comment from sqltable
Количество столбцов в Excel и в возвращаемом запросе select должно совпадать.
ВНИМАНИЕ: При возникновении ошибки Cannot get the column information from OLE DB provider «Microsoft.ACE.OLEDB.12.0» for linked server «(null)» выполните следующий запрос:
USE [master] GO EXEC master . dbo. sp_MSset_oledb_prop N'Microsoft.ACE.OLEDB.12.0' , N'AllowInProcess' , 1 GO EXEC master . dbo. sp_MSset_oledb_prop N'Microsoft.ACE.OLEDB.12.0' , N'DynamicParameters' , 1 GO
ВНИМАНИЕ: При возникновении ошибки SQL Server заблокировал доступ к STATEMENT «OpenRowset/OpenDatasource» компонента «Ad Hoc Distributed Queries», поскольку он отключен в результате настройки конфигурации безопасности сервера выполните поочередно два запроса.
sp_configure 'show advanced options', 1; GO reconfigure GO sp_configure 'Ad Hoc Distributed Queries', 1; GO reconfigure GO
Используемые материалы: http://habrahabr.ru/post/219415/ и http://social.msdn.microsoft.com
Линковка Excel к MSSQL
Чтобы прилинковать Excel файл выполните следующие запросы в SQL Server Management Studio
exec sp_addlinkedserver @server = 'XlsLnkSrv', @srvproduct = 'ACE 12.0', @provider = 'Microsoft.ACE.OLEDB.12.0', @datasrc = 'C:Sample.xlsx', @provstr = 'Excel 12.0; HDR=Yes'
где
- XlsLnkSrv — название связанного сервера
- C:Sample.xlsx — абсолютный путь к требуемому Excel-файлу
Если все выполнено правильно, то после обновления обозревателя объектов вы увидите название установленного поставщика Microsoft.ACE.OLEDB.12.0 в Объекты сервера / Связанные серверы / Поставщики
Считать данные можно с помощью команды openquery:
select * from openquery (XlsLnkSrv, 'Select * from [Sheet1$]')
Подключение с помощью Microsoft Jet 4.0 Ole DB Provider
Скачайте установочные файлы провайдера по ссылке http://www.microsoft.com/en-us/download/details.aspx?id=23734.
Технология Jet 4.0 работает только на 32-битных версиях MSSQL.
Для создания связанного сервера используйте следующий SQL-запрос:
EXEC sp_addlinkedserver 'ExcelSource', 'Jet 4.0', 'Microsoft.Jet.OLEDB.4.0', 'c:MyDataDistExcl.xls', NULL, 'Excel 8.0' EXEC sp_addlinkedsrvlogin 'ExcelSource', 'false', NULL, NULL </pre>
где
- ExcelSource — название связанного сервера
- c:MyDataDistExcl.xls — абсолютный путь к Excel-файлу
Для получения данных из Excel файла используется запрос:
Select * From [ExcelSource]...[Лист1$]