[C#] EPPlus 讀寫(read/write) Excel檔案 懶人包範例程式碼

[C#] EPPlus 讀寫(read/write) Excel檔案 懶人包範例程式碼

聽說EPPlus讀寫Excel檔寫法較簡潔,用了後真的感覺不錯

抄個筆記…

.ddl檔下載(Visual Studio要加入參考):http://epplus.codeplex.com/

※2014-07-16 修正第一個範例程式碼,使用using語法釋放物件,for迴圈走訪Excel Row Range時略過空白列,所謂空白列就是紅框處(任何無填寫資料的列)↓

image

因為實務上我碰過,使用者刪除資料是選擇一個列,然後按Delete鍵,結果變成,它是一個空白資料列,但endRowNumber仍然會指到該地方,造成程式抓資料有問題

※正常User操作刪除Excel列應該是↓點選列編號右鍵=>刪除

bruceDemo

為了配合User操作習慣也為了讓程式更完美一點,請見以下範例程式碼:

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

namespace ConsoleReadEmptyRow
{
    class Program
    {
        static void Main(string[] args)
        {
            //開檔
            using (FileStream fs = new FileStream(@"C:\Read.xlsx", FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
            {
                //載入Excel檔案
                using (ExcelPackage ep = new ExcelPackage(fs))
                {
                    ExcelWorksheet sheet = ep.Workbook.Worksheets[1];//取得Sheet1
                    int startRowNumber = sheet.Dimension.Start.Row;//起始列編號,從1算起
                    int endRowNumber = sheet.Dimension.End.Row;//結束列編號,從1算起
                    int startColumn = sheet.Dimension.Start.Column;//開始欄編號,從1算起
                    int endColumn = sheet.Dimension.End.Column;//結束欄編號,從1算起
                     

                    bool isHeader = true;
                    if (isHeader)//有包含標題
                    {
                        startRowNumber += 1;
                    }

                    ////寫入標題文字
                    sheet.Cells[1, 1].Value = "第1欄";
                    sheet.Cells[1, 2].Value = "第2欄";
                    for (int currentRow = startRowNumber; currentRow <= endRowNumber; currentRow++)
                    {
                         ExcelRange range = sheet.Cells[currentRow, startColumn, currentRow, endColumn];//抓出目前的Excel列
                         if (range.Any(c=> !string.IsNullOrEmpty(c.Text))==false)//這是一個完全空白列(使用者用Delete鍵刪除動作)
                         {
                             continue;//略過此列
                         }
                         //讀值
                         string cellValue = sheet.Cells[currentRow, 1].Text;//讀取格式化過後的文字(讀取使用者看到的文字)
                         
                        //寫值
                        sheet.Cells[currentRow, 1].Value = cellValue + "test";

                    }

                    
                    //建立檔案
                    using (FileStream createStream = new FileStream(@"C:\output.xlsx", FileMode.Create, FileAccess.Write, FileShare.ReadWrite))
                    {
                        ep.SaveAs(createStream);//存檔
                    }//end using 
                }//end   using 
            }//end using 
             
          

        }
    }
}

 

2014/04/29 追記說明為何使用Cells[i,i].Text讀值

如果使用者在Cell裡輸入一個字串「2014/01/01」,Excel程式會很雞婆地把該字串轉成日期格式的「2014/1/1」

這時候用

Convert.ToString(Cells[i,i].Value)或Cells[i,i].Text 方法

來讀值的話就會有差異

用Convert.ToString(Cells[i,i].Value)讀日期的話會包含時間資訊(但使用者不會在Excel上看到),用Cells[i,i].Text讀日期的話則是讀取使用者看到的文字

image

 

 

2013.5.8 追記如何建立Excel檔案

/// <summary>
        /// 寫入Excel
        /// </summary>
        /// <param name="strFilePath">寫檔路徑</param>
        static void SheetWrite(string strFilePath, DataTableCollection objDTC1,DataTableCollection objDTC2 ,DataTableCollection objDTC3)
        {
            //檔案已存在 
            if (File.Exists(strFilePath))
            {
                //刪除檔案
                File.Delete(strFilePath);
            }
          
            
                //在記憶體中建立一個Excel物件
                ExcelPackage ep = new ExcelPackage();
                //加入一個Sheet
                ep.Workbook.Worksheets.Add("MySheet");
                //注意sheetName不可包含特殊字元,否則Exception
                //sheetName只能31個字,超過部份會自動被截斷,且無Exception拋出

                //取得剛剛加入的Sheet(實體Sheet就叫MySheet)
                ExcelWorksheet sheet1 = ep.Workbook.Worksheets["MySheet"];//取得Sheet1 
                sheet1.Cells[1, 1].Value = "欄位1";//加入標頭
                sheet1.Cells[1, 2].Value = "欄位2";//同上
                //迴圈部份自由料理
                if (objDTC1.Count>0 && objDTC1[0].Rows.Count>0)
                {
                    for (int i = 0; i < objDTC1[0].Rows.Count;i++ )
                    {
                        sheet1.Cells[i+2, 1].Value = objDTC1[0].Rows[i][0].ToString();
                        sheet1.Cells[i+2, 2].Value = objDTC1[0].Rows[i][1].ToString();
                    }
                }
                 //建立檔案串流
                FileStream OutputStream = new FileStream(strFilePath, FileMode.Create, FileAccess.Write, FileShare.ReadWrite);
                //把剛剛的Excel物件真實存進檔案裡
                ep.SaveAs(OutputStream);
                //關閉串流
                OutputStream.Close();
               

        }

 

2013.8.13追記:如果想在記憶體中建立Excel並輸出給Client下載的話

ASP.net MVC範例

        [HttpGet]
        public ActionResult Export()
        {           
            //在記憶體中建立一個Excel物件 
            ExcelPackage ep = new ExcelPackage();
            //加入一個Sheet 
            ep.Workbook.Worksheets.Add("MySheet");
            //取得剛剛加入的Sheet(實體Sheet就叫MySheet) 
            ExcelWorksheet sheet1 = ep.Workbook.Worksheets["MySheet"];//取得Sheet1  
            sheet1.Cells[1, 1].Value = "欄位1";//加入標頭 
            sheet1.Cells[1, 2].Value = "欄位2";//隨便寫值,型別最好都給字串,如果給數字的話,在Excel有可能被自動轉成科學記號
           
           
             

             byte[] file = ep.GetAsByteArray();
             return File(file, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", "Export.xlsx");
           
           
 
        }

ASP.net WebForm匯出下載範例


        /// <summary>
        /// 匯出Excel報表
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void btnExport_Click(object sender, EventArgs e)
        { 
            //在記憶體中建立一個Excel物件 
            ExcelPackage ep = new ExcelPackage();
            //加入一個Sheet,並取得剛剛加入的Sheet 
            ExcelWorksheet sheet1 =  ep.Workbook.Worksheets.Add("MySheet");
             

            sheet1.Cells[1, 1].Value = "欄位1";//加入標頭 
            sheet1.Cells[1, 2].Value = "欄位2";//隨便寫值 

            //將檔案轉成byte陣列
            byte[] file = ep.GetAsByteArray();
             
            //先清除Response中雜七雜八資料
            Response.Clear();
            //設定MIME類型
            Response.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
            //設定預設檔名                         
            Response.AddHeader("content-disposition", "attachment;filename="  + "Export.xlsx");
            //用 BinaryWrite 輸出byte[]檔案
            Response.BinaryWrite(file);
            Response.End();
        }//end click

 

 

2013.11.6 讓每個Column靠左對齊,Cell寬度自動調整

                int startColumn = sheet1.Dimension.Start.Column;
                int endColumn = sheet1.Dimension.End.Column;
                for (int i = startColumn; i <=   endColumn; i++)
                {
                    sheet1.Column(i).Style.HorizontalAlignment = ExcelHorizontalAlignment.Left;//靠左對齊

                   
                       // sheet1.Column(i).Width = 80;//固定寬度寫法
                 
                        sheet1.Column(i).AutoFit();//依內容fit寬度
                         
        
                }//End for
            

 

 

2013.11.19

Cell斷行的寫法

  sheet1.Cells[1, 1].Value = "店名\n(公司名稱)";
  sheet1.Cells[1, 1].Style.WrapText = true;

 

2014.3.18追記,如果cell為數字,讀取日期的方法:Reading Datetime value From Excel sheet

2014.3.24追記,設定儲存格背景顏色方法:Set custom BackgroundColor of a Excel sheet cell using epplus c#

2020.11.13追記 字體&儲存格背景色程式碼如下:


ExcelRange range = sheet.Cells[1, 1, 1, 8];
//粗體
range.Style.Font.Bold = true;  
//字顏色
range.Style.Font.Color.SetColor(System.Drawing.Color.White);//白字
//背景色
range.Style.Fill.PatternType = OfficeOpenXml.Style.ExcelFillStyle.Solid;//必填
range.Style.Fill.BackgroundColor.SetColor(0, 128, 128, 0);//綠底

2021-05-24追記:設定儲存格格式為文字字串

sheet.Cells[0, 0].Style.Numberformat.Format = "@";