среда, 18 августа 2010 г.

Импортирование из Excel в DataGrid WPF с помощью средств ADO.NET

Понадобилось мне нынче осуществить импорт данных из Excel в какой-нибудь табличный элемент управления WPF'а. Погуглив, нашла приятного кандидата на эту роль в лице DataGrid, а в качестве импортера - провайдера ADO.NET - OleDB. Простым копипастом процесс не ограничился, пришлось пару тонкостей установить методом научного тыка.

XAML для грида выглядит тривиально:
   1:  <Window x:Class="StoreHouse.MainWindow"
   2:          xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   3:          xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   4:          Title="Тест Грида" Height="350" Width="525">
   5:      <Grid>
   6:          <DataGrid Name="gridProducts" AutoGenerateColumns="True">
   7:          </DataGrid>
   8:      </Grid>
   9:  </Window>


А связанный с ним код так:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Data.OleDb;
using System.Data;

namespace StoreHouse
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            this.importExcel();
        }

        private void importExcel()
        {
            // Create connection string variable. Modify the "Data Source"
            // parameter as appropriate for your environment.
            String sConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;" +
                "Data Source=../../образец_отчета.xls;" +
                "Extended Properties=Excel 8.0;";

            // Create connection object by using the preceding connection string.
            OleDbConnection dbConnection = new OleDbConnection(sConnectionString);

            // Open connection with the database.
            dbConnection.Open();

            // The code to follow uses a SQL SELECT command to display the data from the worksheet.

            // Create new OleDbCommand to return data from worksheet.
            DataTable ExcelSheets = dbConnection.GetOleDbSchemaTable(System.Data.OleDb.OleDbSchemaGuid.Tables
                , new object[] { null, null, null, "TABLE" });
            int sheetNumber = 0; // number of the sheet in the document
            string SpreadSheetName = "[" + ExcelSheets.Rows[sheetNumber]["TABLE_NAME"].ToString() + "]";
            //OleDbCommand objCmdSelect = new OleDbCommand("SELECT * FROM " + SpreadSheetName, dbConnection);
            OleDbCommand objCmdSelect = new OleDbCommand("SELECT * FROM [Лист1$]", dbConnection);

            // Create new OleDbDataAdapter that is used to build a DataSet
            // based on the preceding SQL SELECT statement.
            OleDbDataAdapter adapter = new OleDbDataAdapter();

            // Pass the Select command to the adapter.
            adapter.SelectCommand = objCmdSelect;

            // Create new DataSet to hold information from the worksheet.
            DataSet dataSet = new DataSet();

            // Fill the DataSet with the information from the worksheet.
            adapter.Fill(dataSet, "XLData");

            // Bind data to DataGrid control.
            gridProducts.ItemsSource = dataSet.Tables[0].DefaultView;

            // Clean up objects.
            dbConnection.Close();
        }
    }
}

* This source code was highlighted with Source Code Highlighter.

1. Если неправильно будет указан путь к файлу, то одноименная таблица создастся в bin\Debug\, а приложение упадёт на том, что в таблице не будет ни одного листа:


2. Для выполнения выборки надо указать какое-то имя таблицы:
OleDbCommand objCmdSelect = new OleDbCommand("SELECT * FROM tableName", dbConnection);
Оля ожидает от нас увидеть в нём название листа с якорем в виде доллара, взятое в квадратные скобки, к примеру:   [Sheet1$]. Русские символы тоже проходят.
Можно указать его неявно:
int sheetNumber = 0;
string SpreadSheetName = "[" + ExcelSheets.Rows[sheetNumber]["TABLE_NAME"].ToString() + "]";
OleDbCommand objCmdSelect = new OleDbCommand("SELECT * FROM " + SpreadSheetName, dbConnection);
Где  sheetNumber - порядковый номер листа в документе. Хотя после недавних тестов я уже так не считаю. Это некий номер.. первый лист не обязательно будет 0-ым. Короче да.. там как-то совсем всё туманно и непонятно. И кажется мне, что нулём будет самый старый в плане изменений лист.

3. Как же осуществляется парсинг данных? По умолчанию Оля отбрасывает все пустые ячейки, пока не находит первый кусочек информации, и ячейку, её содержащую, принимает за имя первого столбца и все соседние на строке ячейки принимает за имена других полей таблицы. Если встречается пустая ячейка в строке, то имя формируется по правилу "F"+порядковый_номер_столбца:


Таким образом зная, что в первой строке у нас поля таблицы, можно писать и более разборчивые селекты, на подобие:
OleDbCommand objCmdSelect = new OleDbCommand("SELECT * FROM [people$] where f2 like '%o%'", dbConnection);

Комментариев нет:

Отправить комментарий