1. 程式人生 > >Open-Xml SDK使用介紹

Open-Xml SDK使用介紹

Office Open XML

簡稱為 ooxml ,是Microsoft 在 Office 2007 之後推行的標準格式,用在 Excel, Word, PPT 等檔案。已確定為國際標準。

Open-Xml SDK是Microsoft提供操作ooxml格式的介面類庫,是c#實現的,2014年開源的,

open-xml sdk開源專案地址:https://github.com/OfficeDev/Open-XML-SDK

open-xml sdk官方介紹文件:https://docs.microsoft.com/en-us/office/open-xml/open-xml-sdk

和其他操作ooxml類庫相比,如NPOI,EPPlus等比較,網上說NPOI速度更快些,但是我測試後open-xml sdk更快,只能說其他類庫介面封裝比較容易使用

 

以下是用open-xml sdk 讀寫的示例

using DocumentFormat.OpenXml;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Spreadsheet;
using System;
using System.Data;
using System.Linq;

namespace ExcelExport
{
    public class ExcelOpenXml
    {
        /*
         * excel 物件結構
         * SpreadsheetDocument
         *   》WorkbookPart
         *       》WorksheetPart
         *           》Worksheet
         *            》SheetData
         *       》WorksheetPart
         *          》Worksheet
         *                》SheetData1
         *       》Workbook
         *           》Sheets
         *                》Sheet
         
*/ public static void Create(string filename, DataSet ds) { SpreadsheetDocument spreadsheetDocument = SpreadsheetDocument.Create(filename, SpreadsheetDocumentType.Workbook); WorkbookPart workbookpart = spreadsheetDocument.AddWorkbookPart(); Workbook workbook
= new Workbook(); Sheets sheets = new Sheets(); #region 建立多個 sheet 頁 //建立多個sheet for (int s = 0; s < ds.Tables.Count; s++) { DataTable dt = ds.Tables[s]; var tname = dt.TableName; WorksheetPart worksheetPart = workbookpart.AddNewPart<WorksheetPart>(); Worksheet worksheet = new Worksheet(); SheetData sheetData = new SheetData(); //建立 sheet 頁 Sheet sheet = new Sheet() { //頁面關聯的 WorksheetPart Id = spreadsheetDocument.WorkbookPart.GetIdOfPart(worksheetPart), SheetId = UInt32Value.FromUInt32((uint)s + 1), Name = tname }; sheets.Append(sheet); #region 建立sheet 行 Row row; uint rowIndex = 1; //新增表頭 row = new Row() { RowIndex = UInt32Value.FromUInt32(rowIndex++) }; sheetData.Append(row); for (int i = 0; i < dt.Columns.Count; i++) { Cell newCell = new Cell(); newCell.CellValue = new CellValue(dt.Columns[i].ColumnName); newCell.DataType = new EnumValue<CellValues>(CellValues.String); row.Append(newCell); } //新增內容 object val = null; for (int i = 0; i < dt.Rows.Count; i++) { row = new Row() { RowIndex = UInt32Value.FromUInt32(rowIndex++) }; sheetData.Append(row); for (int j = 0; j < dt.Columns.Count; j++) { Cell newCell = new Cell(); val = dt.Rows[i][j]; newCell.CellValue = new CellValue(val.ToString()); newCell.DataType = new EnumValue<CellValues>(CellValues.String); row.Append(newCell); } } #endregion worksheet.Append(sheetData); worksheetPart.Worksheet = worksheet; worksheetPart.Worksheet.Save(); } #endregion workbook.Append(sheets); workbookpart.Workbook = workbook; workbookpart.Workbook.Save(); spreadsheetDocument.Close(); } public static DataTable GetSheet(string filename, string sheetName) { DataTable dt = new DataTable(); using (SpreadsheetDocument document = SpreadsheetDocument.Open(filename, false)) { WorkbookPart wbPart = document.WorkbookPart; //通過sheet名查詢 sheet頁 Sheet sheet = wbPart .Workbook .Descendants<Sheet>() .Where(s => s.Name == sheetName) .FirstOrDefault(); if (sheet == null) { throw new ArgumentException("未能找到" + sheetName + " sheet 頁"); } //獲取Excel中共享表 SharedStringTablePart sharedStringTablePart = wbPart .GetPartsOfType<SharedStringTablePart>() .FirstOrDefault(); SharedStringTable sharedStringTable = null; if (sharedStringTablePart != null) sharedStringTable = sharedStringTablePart.SharedStringTable; #region 構建datatable //新增talbe列,返回列數 Func<Row, int> addTabColumn = (r) => { //遍歷單元格 foreach (Cell c in r.Elements<Cell>()) { dt.Columns.Add(GetCellVal(c, sharedStringTable)); } return dt.Columns.Count; }; //新增行 Action<Row> addTabRow = (r) => { DataRow dr = dt.NewRow(); int colIndex = 0; int colCount = dt.Columns.Count; //遍歷單元格 foreach (Cell c in r.Elements<Cell>()) { if (colIndex >= colCount) break; dr[colIndex++] = GetCellVal(c, sharedStringTable); } dt.Rows.Add(dr); }; #endregion //通過 sheet.id 查詢 WorksheetPart WorksheetPart worksheetPart = wbPart.GetPartById(sheet.Id) as WorksheetPart; //查詢 sheetdata SheetData sheetData = worksheetPart.Worksheet.Elements<SheetData>().First(); //遍歷行 foreach (Row r in sheetData.Elements<Row>()) { //構建table列 if (r.RowIndex == 1) { addTabColumn(r); continue; } //構建table行 addTabRow(r); } } return dt; } /// <summary> /// 獲取單元格值 /// </summary> /// <param name="cell"></param> /// <param name="sharedStringTable"></param> /// <returns></returns> static string GetCellVal(Cell cell, SharedStringTable sharedStringTable) { var val = cell.InnerText; if (cell.DataType != null) { switch (cell.DataType.Value) { //從共享表中獲取值 case CellValues.SharedString: if (sharedStringTable != null) val = sharedStringTable .ElementAt(int.Parse(val)) .InnerText; break; default: val = string.Empty; break; } } return val; } } }

資料介面

using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Linq;
using System.Text;

namespace TextExcelExport
{
    public class TestData
    {
        private static string _exportDir = @"D:\temp";

        public static string GetNewExcelFileName(string name)
        {
            //return Path.Combine(_exportDir, DateTime.Now.ToString("yyMMdd-HHmmss") + suffix);
            return Path.Combine(_exportDir, name);
        }
        public static string GetFileName(string fileName)
        {
            return Path.Combine(_exportDir
                , fileName);
        }

        public static DataTable GetDataTable(int cols = 100, int rows = 1000, string tabName = "mytable")
        {
            DataTable dt = new DataTable(tabName);
            for (int i = 0; i < cols; i++)
            {
                dt.Columns.Add("col" + i.ToString("D3"));
            }

            DataRow dr = null;
            for (int i = 0; i < rows; i++)
            {
                dr = dt.NewRow();
                for (int j = 0; j < dt.Columns.Count; j++)
                {
                    dr[j] = "val-" + i + "-" + j;
                }
                dt.Rows.Add(dr);
            }

            return dt;
        }
    }
}

單元測試介面程式碼

using System;
using System.Data;
using System.IO;
using ExcelExport;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace TextExcelExport
{
    [TestClass]
    public class TestCreateExcel
    {
        #region openxml
        [TestMethod]
        public void TestOpenXmlCrate()
        {
            var fname = TestData.GetNewExcelFileName("TestOpenXmlCrate.xlsx");

            var dt1 = TestData.GetDataTable(tabName: "tab1");
            var dt2 = TestData.GetDataTable(tabName: "tab2");
            DataSet ds = new DataSet();
            ds.Tables.Add(dt1);
            ds.Tables.Add(dt2);

            ExcelOpenXml.Create(fname, ds);

            Assert.IsTrue(File.Exists(fname));
        }
        [TestMethod]
        public void TestOpenXmlRead()
        {
            var fname = TestData.GetFileName("TestOpenXmlCrate.xlsx");
            var dt = ExcelOpenXml.GetSheet(fname, "tab1");

            Assert.IsTrue(File.Exists(fname));
        }
        #endregion
    }
}

測試發現,寫兩張sheet表,1000行,100列的資料建立需要2秒多,讀取只需433ms

 

詳細可以檢視git倉庫程式碼:https://github.com/marblemm/UtilsHelper