خواندن و نوشتن محتوای فایل های Excel بدون استفاده از Excel Automation

پنجشنبه 4 شهریور 1395

در این مقاله با دو روش از روشهای خواندن اطلاعات از فایل های اکسل و نوشتن آنها در DataGridView ،بدون استفاده از Excel Automation (با استفاده از NPOI و ADO.Net )آشنا میشوید .

خواندن و نوشتن محتوای فایل های Excel بدون استفاده از Excel Automation

راه اول : با استفاده از ADO.NET - Microsoft.Jet.OleDb.4.0 (xls) و Microsoft.Jet.ACE.DB.*.0 (xlsx) Providers

Provider Microsoft.Jet.OleDb.4.0 یک راه کاملا ساده برای خواندن و نوشتن فایل های XLS است . این بصورت پیش فرض بروی Windows 2000 به بعد نصب شده است . 

با استفاده از این ، شما توانایی خواندن و نوشتن فایل های XLS رو همانند یک پایگاه داده ، با استفاده از queriy ها دارید . 

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

using System.Data.OleDb;

namespace Read___write_xls___display_in_grid
{
    public partial class Form1 : Form
    {
        OleDbConnection conn;
        OleDbDataAdapter adapter;

        DataTable dt;

        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            // connect to xls file
            // NOTE: it will be created if not exists
            conn = new OleDbConnection("Provider=Microsoft.Jet.OleDb.4.0;" +
                "Data Source=" + Application.StartupPath + "\\test.xls;" +
                "Extended Properties=Excel 8.0");
            conn.Open();

            // create a sheet "Sheet1" if not exists
            // NOTE: no "id" field needed
            // WARNING: spaces in sheet's name are supported if names are in [] (automatically replace with _)
            // spaces in column names NOT supported with OleDbCommandBuilder!
            try
            {
                string cmdText = "CREATE TABLE [Sheet 1] (text_col MEMO, int_col INT)";
                using (OleDbCommand cmd = new OleDbCommand(cmdText, conn))
                {
                    cmd.ExecuteNonQuery();
                }
            }
            catch { }

            // get sheets list into combobox
            dt = conn.GetSchema("Tables");
            for (int i = 0; i < dt.Rows.Count - 1; i++)
            {
                if (dt.Rows[i].ItemArray[dt.Columns.IndexOf
                ("TABLE_TYPE")].ToString() == "TABLE" &&
                    !dt.Rows[i].ItemArray[dt.Columns.IndexOf
                    ("TABLE_NAME")].ToString().Contains("$"))
                {
                    comboBox1.Items.Add(dt.Rows[i].ItemArray[dt.Columns.IndexOf("TABLE_NAME")]);
                }
            }
        }

        private void button1_Click(object sender, EventArgs e)
        {
            adapter = new OleDbDataAdapter("SELECT * FROM " + comboBox1.SelectedItem.ToString(), conn);

            new OleDbCommandBuilder(adapter);

            dt = new DataTable();
            adapter.Fill(dt);
            dataGridView1.DataSource = dt;
        }

        private void Form1_FormClosed(object sender, FormClosedEventArgs e)
        {
            if (adapter == null) return;

            adapter.Update(dt);
        }

        // show tooltip (not intrusive MessageBox) when user trying to input letters into INT column cell
        private void dataGridView1_DataError(object sender, DataGridViewDataErrorEventArgs e)
        {
            if (dt.Columns[e.ColumnIndex].DataType == typeof(Double))
            {
                Rectangle rectColumn;
                rectColumn = dataGridView1.GetColumnDisplayRectangle(e.ColumnIndex, false);

                Rectangle rectRow;
                rectRow = dataGridView1.GetRowDisplayRectangle(e.RowIndex, false);

                toolTip1.ToolTipTitle = "This field is for integers and decimals only.";
                toolTip1.Show(" ",
                          dataGridView1,
                          rectColumn.Left, rectRow.Top + rectRow.Height);
            }
        }

        private void dataGridView1_MouseDown(object sender, MouseEventArgs e)
        {
            toolTip1.Hide(dataGridView1);
        }
    }
}


همچنین شما میتوانید از Microsoft.ACE.OLEDB.*.0 providers برای خواندن فایلهای XLSX استفاده کنید
Microsoft Office شامل یکی از این Providerها میشود . 

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

using System.Data.OleDb;

namespace Read___write_XLSX_via_ADO.NET___display_in_GRID
{
    public partial class Form1 : Form
    {
        OleDbConnection conn;
        OleDbDataAdapter adapter;

        DataTable dt;

        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            // connect to xls file
            // NOTE: it will be created if not exists
            try
            {
                conn = new OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;" +
                    "Data Source=" + Application.StartupPath + "\\test.xlsx;" +
                    "Extended Properties=Excel 12.0 Xml");
                conn.Open();
            }
            catch
            {
                try
                {
                    conn = new OleDbConnection("Provider=Microsoft.ACE.OLEDB.14.0;" +
                        "Data Source=" + Application.StartupPath + "\\test.xlsx;" +
                        "Extended Properties=Excel 14.0 Xml");
                    conn.Open();
                }
                catch
                {
                    try
                    {
                        conn = new OleDbConnection("Provider=Microsoft.ACE.OLEDB.15.0;" +
                            "Data Source=" + Application.StartupPath + "\\test.xlsx;" +
                            "Extended Properties=Excel 15.0 Xml");
                        conn.Open();
                    }
                    catch
                    {
                    }
                }
            }

            // create a sheet "Sheet1" if not exists
            // NOTE: no "id" field needed
            // WARNING: spaces in sheet's name are supported if names are in [] (automatically replace with _)
            // spaces in column names NOT supported with OleDbCommandBuilder!
            try
            {
                string cmdText = "CREATE TABLE [Sheet 1] (text_col MEMO, int_col INT)";
                using (OleDbCommand cmd = new OleDbCommand(cmdText, conn))
                {
                    cmd.ExecuteNonQuery();
                }
            }
            catch { }

            // get sheets list into combobox
            dt = conn.GetSchema("Tables");
            for (int i = 0; i < dt.Rows.Count - 1; i++)
            {
                if (dt.Rows[i].ItemArray[dt.Columns.IndexOf("TABLE_TYPE")].ToString() == "TABLE" &&
                    !dt.Rows[i].ItemArray[dt.Columns.IndexOf("TABLE_NAME")].ToString().Contains("$"))
                {
                    comboBox1.Items.Add(dt.Rows[i].ItemArray[dt.Columns.IndexOf("TABLE_NAME")]);
                }
            }
        }

        private void button1_Click(object sender, EventArgs e)
        {
            adapter = new OleDbDataAdapter("SELECT * FROM " + comboBox1.SelectedItem.ToString(), conn);

            new OleDbCommandBuilder(adapter);

            dt = new DataTable();
            adapter.Fill(dt);
            dataGridView1.DataSource = dt;
        }

        private void Form1_FormClosed(object sender, FormClosedEventArgs e)
        {
            if (adapter == null) return;

            adapter.Update(dt);
        }

        // show tooltip (not intrusive MessageBox) when user trying to input letters into INT column cell
        private void dataGridView1_DataError(object sender, DataGridViewDataErrorEventArgs e)
        {
            if (dt.Columns[e.ColumnIndex].DataType == typeof(Double))
            {
                Rectangle rectColumn;
                rectColumn = dataGridView1.GetColumnDisplayRectangle(e.ColumnIndex, false);

                Rectangle rectRow;
                rectRow = dataGridView1.GetRowDisplayRectangle(e.RowIndex, false);

                toolTip1.ToolTipTitle = "This field is for integers and decimals only.";
                toolTip1.Show(" ",
                          dataGridView1,
                          rectColumn.Left, rectRow.Top + rectRow.Height);
            }
        }

        private void dataGridView1_MouseDown(object sender, MouseEventArgs e)
        {
            toolTip1.Hide(dataGridView1);
        }
    }
}


اما این نکته را در نظر داشته باشید که Provider های Jet  و  ACE برای فایل های اکسل استفاده میشوند و نه به عنوان متدهایی که برای خواندن پایگاه داده استفاده میشوند ، بنابراین ، سرعت خواندن اطلاعات از فایلهای Excel به اندازه خواندن اطلاعات از پایگاه داده ، سریع نیست . 

راه دوم :  استفاده از کتابخانه NPOI 

NPOI یک کتابخانه سه قسمتیِ open-source است که برای خواندن و نوشتن فایل های xls, xlsx, docx مورد استفاده قرار میگیرد . که نیازی به MIcrosoft Excel و هر چیز از سه قسمت از برنامه/کتابخانه را ندارد . 


XLS

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

using System.IO;

using NPOI.HSSF.Model; // InternalWorkbook
using NPOI.HSSF.UserModel; // HSSFWorkbook, HSSFSheet

namespace Read___write_XLS_via_NPOI___display_in_GRID
{
    public partial class Form1 : Form
    {
        HSSFWorkbook wb;
        HSSFSheet sh;

        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            // create xls if not exists
            if (!File.Exists("test.xls"))
            {
                wb = HSSFWorkbook.Create(InternalWorkbook.CreateWorkbook());

                // create sheet
                sh = (HSSFSheet)wb.CreateSheet("Sheet1");
                // 3 rows, 2 columns
                for (int i = 0; i < 3; i++)
                {
                    var r = sh.CreateRow(i);
                    for (int j = 0; j < 2; j++)
                    {
                        r.CreateCell(j);
                    }
                }

                using (var fs = new FileStream("test.xls", FileMode.Create, FileAccess.Write))
                {
                    wb.Write(fs);
                }
            }

            // get sheets list from xls
            using (var fs = new FileStream("test.xls", FileMode.Open, FileAccess.Read))
            {
                wb = new HSSFWorkbook(fs);

                for (int i = 0; i < wb.Count; i++)
                {
                    comboBox1.Items.Add(wb.GetSheetAt(i).SheetName);
                }
            }
        }

        private void button1_Click(object sender, EventArgs e)
        {
            // clear grid before filling
            dataGridView1.Rows.Clear();
            dataGridView1.Columns.Clear();

            // get sheet
            sh = (HSSFSheet)wb.GetSheet(comboBox1.SelectedItem.ToString());

            int i = 0;
            while (sh.GetRow(i) != null)
            {
                // add necessary columns
                if (dataGridView1.Columns.Count < sh.GetRow(i).Cells.Count)
                {
                    for (int j = 0; j < sh.GetRow(i).Cells.Count; j++)
                    {
                        dataGridView1.Columns.Add("", "");
                    }
                }
                
                // add row
                dataGridView1.Rows.Add();
                
                // write row value
                for (int j = 0; j < sh.GetRow(i).Cells.Count; j++)
                {
                    var cell = sh.GetRow(i).GetCell(j);

                    if (cell != null)
                    {
                        // TODO: you can add more cell types capability, e. g. formula
                        switch (cell.CellType)
                        {
                            case NPOI.SS.UserModel.CellType.Numeric:
                                dataGridView1[j, i].Value = sh.GetRow(i).GetCell(j).NumericCellValue;
                                break;
                            case NPOI.SS.UserModel.CellType.String:
                                dataGridView1[j, i].Value = sh.GetRow(i).GetCell(j).StringCellValue;
                                break;
                        }
                    }
                }

                i++;
            }
        }

        private void button2_Click(object sender, EventArgs e)
        {
            for (int i = 0; i < dataGridView1.RowCount - 1; i++)
            {
                if (sh.GetRow(i) == null)
                    sh.CreateRow(i);

                for (int j = 0; j < dataGridView1.ColumnCount; j++)
                {
                    if (sh.GetRow(i).GetCell(j) == null)
                        sh.GetRow(i).CreateCell(j);

                    if (dataGridView1[j, i].Value != null)
                    {
                        sh.GetRow(i).GetCell(j).SetCellValue(dataGridView1[j, i].Value.ToString());
                    }
                }
            }

            using (var fs = new FileStream("test.xls", FileMode.Open, FileAccess.Write))
            {
                wb.Write(fs);
            }
        }
    }
}


XLSX

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

using System.IO; // File.Exists()

using NPOI.XSSF.UserModel; // XSSFWorkbook, XSSFSheet

namespace Read___write_XLSX_via_NPOI___display_in_GRID
{
    public partial class Form1 : Form
    {
        XSSFWorkbook wb;
        XSSFSheet sh;

        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            // create xls if not exists
            if (!File.Exists("test.xlsx"))
            {
                wb = new XSSFWorkbook();

                // create sheet
                sh = (XSSFSheet)wb.CreateSheet("Sheet1");
                // 3 rows, 2 columns
                for (int i = 0; i < 3; i++)
                {
                    var r = sh.CreateRow(i);
                    for (int j = 0; j < 2; j++)
                    {
                        r.CreateCell(j);
                    }
                }

                using (var fs = new FileStream("test.xlsx", FileMode.Create, FileAccess.Write))
                {
                    wb.Write(fs);
                }
            }

            // get sheets list from xlsx
            using (var fs = new FileStream("test.xlsx", FileMode.Open, FileAccess.Read))
            {
                wb = new XSSFWorkbook(fs);

                for (int i = 0; i < wb.Count; i++)
                {
                    comboBox1.Items.Add(wb.GetSheetAt(i).SheetName);
                }
            }
        }

        private void button1_Click(object sender, EventArgs e)
        {
            // clear grid before filling
            dataGridView1.Rows.Clear();
            dataGridView1.Columns.Clear();

            // get sheet
            sh = (XSSFSheet)wb.GetSheet(comboBox1.SelectedItem.ToString());

            int i = 0;
            while (sh.GetRow(i) != null)
            {
                // add neccessary columns
                if (dataGridView1.Columns.Count < sh.GetRow(i).Cells.Count)
                {
                    for (int j = 0; j < sh.GetRow(i).Cells.Count; j++)
                    {
                        dataGridView1.Columns.Add("", "");
                    }
                }
                
                // add row
                dataGridView1.Rows.Add();
                
                // write row value
                for (int j = 0; j < sh.GetRow(i).Cells.Count; j++)
                {
                    var cell = sh.GetRow(i).GetCell(j);

                    if (cell != null)
                    {
                        // TODO: you can add more cell types capability, e. g. formula
                        switch (cell.CellType)
                        {
                            case NPOI.SS.UserModel.CellType.Numeric:
                                dataGridView1[j, i].Value = sh.GetRow(i).GetCell(j).NumericCellValue;
                                break;
                            case NPOI.SS.UserModel.CellType.String:
                                dataGridView1[j, i].Value = sh.GetRow(i).GetCell(j).StringCellValue;
                                break;
                        }
                    }
                }

                i++;
            }
        }

        private void button2_Click(object sender, EventArgs e)
        {
            for (int i = 0; i < dataGridView1.RowCount - 1; i++)
            {
                if (sh.GetRow(i) == null)
                    sh.CreateRow(i);

                for (int j = 0; j < dataGridView1.ColumnCount; j++)
                {
                    if (sh.GetRow(i).GetCell(j) == null)
                        sh.GetRow(i).CreateCell(j);

                    if (dataGridView1[j, i].Value != null)
                    {
                        sh.GetRow(i).GetCell(j).SetCellValue(dataGridView1[j, i].Value.ToString());
                    }
                }
            }

            using (var fs = new FileStream("test.xlsx", FileMode.Open, FileAccess.Write))
            {
                wb.Write(fs);
            }
        }
    }
}

خروجی خواندن و نوشتن فایل xls با استفاده از ADO.net بصورت زیر است :




خروجی خواندن و نوشتن فایل xls با استفاده از NPOI بصورت زیر است :



آموزش سی شارپ

فایل های ضمیمه

برنامه نویسان

نویسنده 3355 مقاله در برنامه نویسان
  • C#.net
  • 4k بازدید
  • 5 تشکر

کاربرانی که از نویسنده این مقاله تشکر کرده اند

در صورتی که در رابطه با این مقاله سوالی دارید، در تاپیک های انجمن مطرح کنید