使用 C# 将 Excel 工作表存储到 system.data.datatable 的更快方法

Faster way of storing Excel worksheet to system.data.datatable using C#

我正在尝试找到一种更快的方法来读取可以在 Excel 2010 年打开的 XML 文件。我无法立即使用 readxml 方法读取 XML 文件,因为它包含工作簿、样式、单元格、数据等标签。所以我的方法是在 Excel 中打开它,然后只获取 sheet 2 上的数据。示例文件包含 9,000 多行,存储在数据表中大约需要 2 分 49 秒。实际文件有 25,000 多行。这是我试过的:

private void bulkInsert()
        {
            var s = new Stopwatch();

            s.Start();
            try
            {
                KillExcel();
                GCollector();
                Excel.Application app = null;
                app = new Excel.Application();
                Excel.Worksheet sheet = null;
                Excel.Workbook book = null;

                book = app.Workbooks.Open(@"my directory for the file");

                sheet = (Worksheet)book.Sheets[2];
                sheet.Select(Type.Missing);

                var xlRange = (Excel.Range)sheet.Cells[sheet.Rows.Count, 1];
                int lastRow = (int)xlRange.get_End(Excel.XlDirection.xlUp).Row;
                int newRow = lastRow + 1;
                var cellrow = newRow;
                int columns = sheet.UsedRange.Columns.Count;
                Excel.Range test = sheet.UsedRange;
                System.Data.DataTable dt = new System.Data.DataTable();
                dt.Columns.Add("Node_SegmentName");
                dt.Columns.Add("Type");
                dt.Columns.Add("Sub-Type");
                dt.Columns.Add("Description");
                dt.Columns.Add("Parameter_DataIdentifier");
                dt.Columns.Add("RuntimeValue");
                dt.Columns.Add("Category");
                dt.Columns.Add("Result");
                dt.TableName = "SsmXmlTable";
//slow part
                for (i = 0; i < lastRow; i++)
                {
                    DataRow excelRow = dt.NewRow();

                    for (int j = 0; j < columns; j++)
                    {
                        excelRow[j] = test.Cells[i + 2, j + 1].Value2;

                    }
                    dt.Rows.Add(excelRow);

                }
                dataGridView1.DataSource = dt;

                DataSet ds = new DataSet();
                ds.Tables.Add(dt);
                ds.WriteXml(AppDomain.CurrentDomain.BaseDirectory + String.Format("\XMLParserOutput{0}.xml", DateTime.Now.ToString("MM-d-yyyy")));



                DataSet reportData = new DataSet();
                reportData.ReadXml(AppDomain.CurrentDomain.BaseDirectory + String.Format("\XMLParserOutput{0}.xml", DateTime.Now.ToString("MM-d-yyyy")));
                SqlConnection connection = new SqlConnection("Data Source=YOURCOMPUTERNAME\SQLEXPRESS;Initial Catalog=YOURDATABASE;Integrated Security=True;Connect Timeout=0");
                connection.Open();
                SqlBulkCopy sbc = new SqlBulkCopy(connection);
                sbc.DestinationTableName = "Test";
                sbc.WriteToServer(reportData.Tables["SsmXmlTable"]);
                connection.Close();
                s.Stop();
                var duration = s.Elapsed;

                MessageBox.Show(duration.ToString() + " bulk insert way");
                MessageBox.Show(ds.Tables["SsmXmlTable"].Rows.Count.ToString());//439 rows
            }
            catch (Exception ex)
            {

                KillExcel();
                GCollector();
                MessageBox.Show(ex.ToString() + i.ToString());
            }
        }

没有从 Excel 部分读取,使用批量复制插入数据只需要几秒钟(449 行 0.5 秒)。

对于遇到同样问题的其他人,我所做的是:

  • 将 xml 另存为 xlsx 文件
  • 使用oledb读取xlsx文件
  • 使用 OleDbAdapter(Fill() 方法)存储在数据集中
  • 批量插入

这是我用来执行此操作的代码(更改连接字符串):

Stopwatch s = new Stopwatch();
s.Start();
string sSheetName = null;
string sConnection = null;
System.Data.DataTable sheetData = new System.Data.DataTable();
System.Data.DataTable dtTablesList = default(System.Data.DataTable);
OleDbConnection oleExcelConnection = default(OleDbConnection);
sConnection = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + @"C:\Users\YOURUSERNAME\Documents\Visual Studio 2012\Projects\TestXmlParser\TestXmlParser\bin\Debug\ConsolidatedSSMFiles.xlsx" + ";Extended Properties=\"Excel 8.0;HDR=Yes;IMEX=1\"";
oleExcelConnection = new OleDbConnection(sConnection);
oleExcelConnection.Open();
dtTablesList = oleExcelConnection.GetSchema("Tables");

if (dtTablesList.Rows.Count > 0)
{
sSheetName = dtTablesList.Rows[0]["TABLE_NAME"].ToString();
}
dtTablesList.Clear();
dtTablesList.Dispose();

if (!string.IsNullOrEmpty(sSheetName))
{
OleDbDataAdapter sheetAdapter = new OleDbDataAdapter("select * from [TEST$]", oleExcelConnection);
sheetAdapter.Fill(sheetData);
} s.Stop();
var duration = s.Elapsed;


oleExcelConnection.Close();
dataGridView1.DataSource = sheetData;
MessageBox.Show(sheetData.Rows.Count.ToString()+"rows - "+ duration.ToString());

这会将 25000 多行 excel 数据读取到一个数据表中,时间约为。 1.9 到 2.0 秒。