1. 程式人生 > >C#中 EPPlus對Excel的讀寫

C#中 EPPlus對Excel的讀寫

1. EPPlus概述

EPPlus 是使用Open Office XML格式(xlsx)讀寫Excel 2007 / 2010檔案的.net開發庫。EPPlus 支援:
  • 單元格範圍
  • 單元格樣式(邊框,顏色,填充,字型,數字,對齊)
  • 圖表
  • 圖片
  • 形狀
  • 批註
  • 表格
  • 保護
  • 加密
  • 資料透視表
  • 資料驗證
  • 條件格式
  • VBA
  • 公式計算
  • 更多......

2. EPPlus核心類介紹

2.1  ExcelPackage類

ExcelPackage是EPPlus的入口類,解析一個Excel檔案,生成ExcelWorkbook物件來表示一個Excel。該類實現了IDisposable介面,也就是說可以使用using進行物件釋放。

10個建構函式,下面是常用的3個:

public ExcelPackage();

public ExcelPackage(FileInfo newFile);

public ExcelPackage(Stream newStream);

不管建構函式中傳入的引數是否有效,該類的Workbook屬性都會自動建立,無須擔心空指標問題。

2.2 ExcelWorkbook類

ExcelWorkbook類表示了一個Excel檔案,其Worksheets屬性對應著Excel的各個Sheet。Worksheets屬性會自動建立,不用擔心空指標異常,但是其Count可能為0。

ExcelWorkbook的Properties屬性可以對Office的一些屬性進行設定,例如:

public string Author { get; set; }
public string Title { get; set; }
public string Comments { get; set; }

注意:在獲取具體的Sheet時,索引號從1開始,例如:

ExcelWorksheet sheet = package.Workbook.Worksheets[1];

2.3 ExcelWorksheet類

一些常用屬性:

sheet.DefaultColWidth = 10; //預設列寬
sheet.DefaultRowHeight = 30; //預設行高
sheet.TabColor = Color.Blue; //Sheet Tab的顏色
sheet.Cells.Style.WrapText = true; //單元格文字自動換行

對行列的增刪操作:

public void InsertRow(int rowFrom, int rows);

public void InsertColumn(int columnFrom, int columns);

public void DeleteRow(int rowFrom, int rows);

public void DeleteColumn(int columnFrom, int columns);

設定指定行或列的樣式(寬、高、隱藏、自動換行、數字格式、鎖定等):

sheet.Column(1).Width = 10;
sheet.Row(1).Height = 30;

sheet.Column(1).Hidden = true;
sheet.Row(1).Hidden = true;

sheet.Column(1).Style.WrapText = true;

sheet.Column(1).Style.Numberformat.Format = "$#,###.00";

sheet.Row(1).Style.Locked = true;

自適應寬度設定:

public void AutoFit();
public void AutoFit(double MinimumWidth);
public void AutoFit(double MinimumWidth, double MaximumWidth);
//未傳入MinimumWidth時,使用Sheet的DefaultColWidth作為最小值,此時若沒有提前對DefaultColWidth進行設定就會報錯
//此方法時對自動換行和合並的單元格無效

2.4 ExcelRange類

3個獲取單元格範圍的方法:

public ExcelRange this[string Address] { get; }
//Address是指"A1:C5"這種格式

public ExcelRange this[int Row, int Col] { get; }

public ExcelRange this[int FromRow, int FromCol, int ToRow, int ToCol] { get; }

重要屬性:

public object Value { get; set; }
//獲取或設定單元格的值

複製單元格:

public void Copy(ExcelRangeBase Destination);

從二維資料集合中裝載資料:

public ExcelRangeBase LoadFromCollection<T>(IEnumerable<T> Collection);

public ExcelRangeBase LoadFromDataReader(IDataReader Reader, bool PrintHeaders);

public ExcelRangeBase LoadFromText(FileInfo TextFile);
//這裡的檔案是指CSV檔案

//資料裝載時,會與ExcelRange的行列進行對應,將值設定到其中,這些單元格沒有樣式和數字格式

2.5 樣式

樣式包括字型、顏色、對齊、邊框等。

range.Style.Fill.PatternType = ExcelFillStyle.Solid;
range.Style.Fill.BackgroundColor.SetColor(Color.Gray);
//在設定Style.Fill的其他屬性之前,必須設定PatternType 
//設定了Style.Fill.PatternType之後,必須設定Style.Fill.BackgroundColor,否則單元格背景為黑色
//注意Style.Fill.BackgroundColor是個只讀屬性,需要通過SetColor()方法設定顏色
range.Font.Color.SetColor(Color.Red);
range.HorizontalAlignment = ExcelHorizontalAlignment.CenterContinuous;

2.6  數字格式

range.Style.Numberformat.Format = "$#,###.00";

使用數字格式時,一定要自行檢查格式的正確性,因為產生的過程中EPPlus不會檢查其正確性,如果格式有錯,在開啟產生的Excel檔案時會提示檔案格式不正確。

2.7 公式

sheet.Cells[1, 3].range.Formula = "AVERAGE(A1, B1)";
sheet.Cells[1, 3].FormulaR1C1 = "AVERAGE(RC[-2], RC[-1])";
//以上兩個公式表達意思相同——對於第一行,C列的值等於A列和B列的平均值

使用公式和使用數字格式有同樣的注意事項,需要自行檢查正確性。

建議總是記錄當前Sheet有多少行和列,方便使用公式時定位單元格。

建議對公式相關程式碼進行註釋,有助於其他程式設計師理解。

 /// <summary>
        /// 匯入
        /// </summary>
        /// <param name="stream"></param>
        /// <returns></returns>
        public static ICollection<Student> Import(Stream stream)
        {
            ICollection<Student> students = new List<Student>();

            #region read excel
            using (stream)
            {
                ExcelPackage package = new ExcelPackage(stream);

                ExcelWorksheet sheet = package.Workbook.Worksheets[1];

                #region check excel format
                if (sheet == null)
                {
                    return students;
                }
                if (!sheet.Cells[1, 1].Value.Equals("Name") ||
                     !sheet.Cells[1, 2].Value.Equals("Age") ||
                     !sheet.Cells[1, 3].Value.Equals("Gender") ||
                     !sheet.Cells[1, 4].Value.Equals("English Score") ||
                     !sheet.Cells[1, 5].Value.Equals("Math Score"))
                {
                    return students;
                }
                #endregion

                #region get last row index
                int lastRow = sheet.Dimension.End.Row;
                while (sheet.Cells[lastRow, 1].Value == null)
                {
                    lastRow--;
                }
                #endregion

                #region read datas
                for (int i = 2; i <= lastRow; i++)
                {
                    students.Add(new Student
                    {
                        Name = sheet.Cells[i, 1].Value.ToString(),
                        Age = int.Parse(sheet.Cells[i, 2].Value.ToString()),
                        Gender = (Gender)Enum.Parse(typeof(Gender), sheet.Cells[i, 3].Value.ToString()),
                        EnglishScore = int.Parse(sheet.Cells[i, 4].Value.ToString()),
                        MathScore = int.Parse(sheet.Cells[i, 5].Value.ToString())

                    });
                }             
            }


 /// <summary>
        /// 匯出
        /// </summary>
        /// <param name="students"></param>
        /// <returns></returns>
        public static MemoryStream Export(ICollection<Student> students)
        {
            MemoryStream stream = new MemoryStream();
            ExcelPackage package = new ExcelPackage(stream);

            package.Workbook.Worksheets.Add("Students");
            ExcelWorksheet sheet = package.Workbook.Worksheets[1];

            #region write header
            sheet.Cells[1, 1].Value = "Name";
            sheet.Cells[1, 2].Value = "Age";
            sheet.Cells[1, 3].Value = "Gender";
            sheet.Cells[1, 4].Value = "English Score";
            sheet.Cells[1, 5].Value = "Math Score";
            sheet.Cells[1, 6].Value = "Average Score";

            using (ExcelRange range = sheet.Cells[1, 1, 1, 6])
            {
                range.Style.Fill.PatternType = OfficeOpenXml.Style.ExcelFillStyle.Solid;
                range.Style.Fill.BackgroundColor.SetColor(Color.Gray);
                range.Style.Border.Bottom.Style = OfficeOpenXml.Style.ExcelBorderStyle.Thick;
                range.Style.Border.Bottom.Color.SetColor(Color.Black);
                range.AutoFitColumns(4);
            }
            #endregion

            #region write content
            int pos = 2;
            foreach (Student s in students)
            {
                sheet.Cells[pos, 1].Value = s.Name;
                sheet.Cells[pos, 2].Value = s.Age;
                sheet.Cells[pos, 3].Value = s.Gender;
                sheet.Cells[pos, 4].Value = s.EnglishScore;
                sheet.Cells[pos, 5].Value = s.MathScore;
                sheet.Cells[pos, 6].FormulaR1C1 = "AVERAGE(RC[-1], RC[-2])";

                if (s.MathScore > 90 && s.EnglishScore > 90)
                {
                    using (ExcelRange range = sheet.Cells[pos, 1, pos, 6])
                    {
                        range.Style.Font.Color.SetColor(Color.Blue);
                    }
                }
                else if (s.MathScore < 80 && s.EnglishScore < 80)
                {
                    using (ExcelRange range = sheet.Cells[pos, 1, pos, 6])
                    {
                        range.Style.Font.Color.SetColor(Color.Red);
                    }
                }

                using (ExcelRange range = sheet.Cells[pos, 1, pos, 6])
                {
                    range.Style.Border.Bottom.Style = OfficeOpenXml.Style.ExcelBorderStyle.Thin;
                    range.Style.Border.Bottom.Color.SetColor(Color.Black);
                    range.Style.HorizontalAlignment = OfficeOpenXml.Style.ExcelHorizontalAlignment.Left;
                }
                pos++;
            }