使用NPOI導出Excel,並在Excel指定單元格插入圖片


一、添加Nuget引用

 

 二、彈框選擇保存路徑

         string fileName = $"記錄_{DateTime.Now.ToString("yyyyMMdd_HHmmss")}";
                string saveFileName = "";
                SaveFileDialog saveFileDialog = new SaveFileDialog();
                saveFileDialog.DefaultExt = "xls";
                //saveFileDialog.Filter = "Excel 工作簿|*.xlsx|Excel 97-2003 工作簿|*.xls";
                saveFileDialog.Filter = "Excel 97-2003 工作簿|*.xls";
                saveFileDialog.FileName = fileName;
                saveFileDialog.ShowDialog();

                saveFileName = saveFileDialog.FileName;
                if (saveFileName?.IndexOf(":") < 0) return;//點擊了取消

三、主要代碼:

        public enum StyleXlsEnum
        {
            Head,
            ColumnHead,
            Default
        }

        private static IWorkbook m_workbook;
        private static ISheet m_sheet;
        private static List<string> m_sheets = new List<string>();
        private static ICellStyle m_cellStyle;
        private static IDataFormat m_dataStyle;
        private static IFont m_font16;
        private static IFont m_font12;
        private static IFont m_font;  
     /// <summary>
        /// 導出Excel
        /// </summary>
        /// <param name="dt">DataTable數據</param>
        /// <param name="saveFileName">Excel文件全路徑</param>
        /// <param name="sheetName">Sheet名稱</param>
        /// <param name="headerName">標題名稱</param>
        /// <returns></returns>
        private bool ExportExcel(DataTable dt, string saveFileName, string sheetName, string headerName)
        {
            ICellStyle cellStyle = null;try
            {
                #region 創建Excel對象

                //如果Excel存在就獲取IWorkbook對象,否則就重新創建
                if (File.Exists(saveFileName))
                {
                    FileStream fs = new FileStream(saveFileName, FileMode.Open, FileAccess.Read);
                    m_workbook = new XSSFWorkbook(fs);
                    if (saveFileName.IndexOf(".xlsx") > 0) // 2007版本
                        m_workbook = new XSSFWorkbook(fs);
                    else if (saveFileName.IndexOf(".xls") > 0) // 2003版本
                        m_workbook = new HSSFWorkbook(fs);
                }
                else
                {
                    //創建一個工作簿
                    m_workbook = new HSSFWorkbook();
                }

                if (m_workbook != null)
                {
                    //獲取所有SheetName
                    int count = m_workbook.NumberOfSheets;
                    if (count < 1)
                    {
                        m_sheet = m_workbook.CreateSheet(sheetName);
                    }
                    else
                    {
                        m_sheets.Clear();
                        for (int i = 0; i < count; i++)
                        {
                            m_sheet = m_workbook.GetSheetAt(1);
                            m_sheets.Add(m_sheet.SheetName);
                        }

                        if (m_sheets.Contains(sheetName))
                        {
                            m_sheet = m_workbook.CreateSheet(sheetName + System.DateTime.Now.ToString("HH-mm-ss") + "副本");
                        }
                        else
                        {
                            m_sheet = m_workbook.CreateSheet(sheetName);
                        }
                    }
                }
                else
                {
                    return false;
                }

                #endregion

                #region 設置表頭

                m_sheet.AddMergedRegion(new NPOI.SS.Util.CellRangeAddress(0, 0, 0, dt.Columns.Count - 1)); //合並單元格
                IRow row0 = m_sheet.CreateRow(0);  //創建一行
                row0.Height = 50 * 20;
                ICell icelltop0 = row0.CreateCell(0);  //創建一個單元格
                IFont font = m_workbook.CreateFont();
                font.FontHeightInPoints = 30;
                icelltop0.CellStyle = Getcellstyle(m_workbook, StyleXlsEnum.Head);
                icelltop0.SetCellValue(headerName);

                #endregion  

                // 設置列寬,excel列寬每個像素是1/256
                m_sheet.SetColumnWidth(0, 9 * 256);
                m_sheet.SetColumnWidth(1, 18 * 256);
                m_sheet.SetColumnWidth(2, 36 * 256);
                m_sheet.SetColumnWidth(3, 25 * 256);
                m_sheet.SetColumnWidth(4, 20 * 256);
                m_sheet.SetColumnWidth(5, 20 * 256);
                m_sheet.SetColumnWidth(6, 20 * 256);
                m_sheet.SetColumnWidth(7, 25 * 256);
                m_sheet.SetColumnWidth(8, 25 * 256);
                m_sheet.SetColumnWidth(9, 25 * 256);
                m_sheet.SetColumnWidth(10, 25 * 256);

                #region 設置列
                IRow rowH = m_sheet.CreateRow(1);
                cellStyle = Getcellstyle(m_workbook, StyleXlsEnum.ColumnHead);
                //設置列名
                foreach (DataColumn col in dt.Columns)
                {
                    //創建單元格並設置單元格內容
                    rowH.CreateCell(col.Ordinal).SetCellValue(col.Caption);

                    //設置單元格格式
                    rowH.Cells[col.Ordinal].CellStyle = cellStyle;
                }
                #endregion

                #region 寫入數據

                cellStyle = Getcellstyle(m_workbook, StyleXlsEnum.Default);
                for (int i = 0; i < dt.Rows.Count; i++)
                {
                    //跳過前兩行,第一行為標題,第二行為列名 
                    IRow row = m_sheet.CreateRow(i + 2);
                    row.Height = 70 * 20;
                    ICell cell = row.CreateCell(0);
                    for (int j = 0; j < dt.Columns.Count; j++)
                    {
                        if (dt.Columns[j].ColumnName == "圖片")
                        {
                            cell = row.CreateCell(j);
                            cell.CellStyle = cellStyle;

                            saveFileName=  Path.GetDirectoryName(saveFileName);

                            //將圖片文件讀入一個字符串
                            byte[] bytess = System.IO.File.ReadAllBytes(dt.Rows[i]["圖片"].ToString());
                            int pictureIdx = m_workbook.AddPicture(bytess, PictureType.JPEG);
                            HSSFPatriarch patriarch = (HSSFPatriarch)m_sheet.CreateDrawingPatriarch();

                //前四個參數(dx1,dy1,dx2,dy2)為圖片在單元格的邊距
                            //col1,col2表示圖片插在col1和col2之間的單元格,索引從0開始
                            //row1,row2表示圖片插在第row1和row2之間的單元格,索引從1開始
                // 參數的解析: HSSFClientAnchor(int dx1,int dy1,int dx2,int dy2,int col1,int row1,int col2,int row2)
                     //dx1:圖片左邊相對excel格的位置(x偏移) 范圍值為:0~1023;即輸100 偏移的位置大概是相對於整個單元格的寬度的100除以1023大概是10分之一
                     //dy1:圖片上方相對excel格的位置(y偏移) 范圍值為:0~256 原理同上。
                     //dx2:圖片右邊相對excel格的位置(x偏移) 范圍值為:0~1023; 原理同上。
                     //dy2:圖片下方相對excel格的位置(y偏移) 范圍值為:0~256 原理同上。
                     //col1和row1 :圖片左上角的位置,以excel單元格為參考,比喻這兩個值為(1,1),那么圖片左上角的位置就是excel表(1,1)單元格的右下角的點(A,1)右下角的點。
                     //col2和row2:圖片右下角的位置,以excel單元格為參考,比喻這兩個值為(2,2),那么圖片右下角的位置就是excel表(2,2)單元格的右下角的點(B,2)右下角的點。 HSSFClientAnchor anchor
= new HSSFClientAnchor(0, 0, 0, 0, 8, i+2, 7, i + 3); //把圖片插到相應的位置 HSSFPicture pict = (HSSFPicture)patriarch.CreatePicture(anchor, pictureIdx); } else { cell = row.CreateCell(j); cell.SetCellValue(dt.Rows[i][j].ToString()); cell.CellStyle = cellStyle; } } } #endregion //創建一個 IO 流 MemoryStream ms = new MemoryStream(); //寫入到流 m_workbook.Write(ms); //轉換為字節數組 byte[] bytes = ms.ToArray(); //保存為Excel文件 using (FileStream fs = new FileStream(saveFileName, FileMode.Create, FileAccess.Write)) { fs.Write(bytes, 0, bytes.Length); fs.Flush(); } //釋放資源 bytes = null; ms.Close(); ms.Dispose(); m_workbook.Close(); m_sheet = null; m_workbook = null; m_cellStyle = null; m_dataStyle = null; m_font = null; m_font12 = null; m_font16 = null; return true; } catch (Exception e) { Console.WriteLine(e); return false; } }      private ICellStyle Getcellstyle(IWorkbook wb, StyleXlsEnum style) { try { //CreateFont()不能頻繁創建,會導致打開EXCEL表的時候報如下錯誤: //此文件中的某些文本格式可能已經更改,因為它已經超出最多允許的字體數。 if (m_font16 == null) { m_font16 = wb.CreateFont(); m_font16.FontHeightInPoints = 16; m_font16.FontName = "微軟雅黑"; m_font16.Boldweight = (short)FontBoldWeight.Bold; } if (m_font12 == null) { m_font12 = wb.CreateFont(); m_font12.FontHeightInPoints = 12; m_font12.FontName = "微軟雅黑"; m_font12.Boldweight = (short)FontBoldWeight.Bold; } if (m_font == null) { m_font = wb.CreateFont(); m_font.FontName = "微軟雅黑"; } m_cellStyle = wb.CreateCellStyle(); //邊框 m_cellStyle.BorderBottom = NPOI.SS.UserModel.BorderStyle.Medium; m_cellStyle.BorderLeft = NPOI.SS.UserModel.BorderStyle.Medium; m_cellStyle.BorderRight = NPOI.SS.UserModel.BorderStyle.Medium; m_cellStyle.BorderTop = NPOI.SS.UserModel.BorderStyle.Medium; //邊框顏色 //m_cellStyle.BottomBorderColor = HSSFColor.OliveGreen.Blue.Index; //m_cellStyle.TopBorderColor = HSSFColor.OliveGreen.Blue.Index; //背景圖形 //m_cellStyle.FillForegroundColor = HSSFColor.White.Index; //m_cellStyle.FillBackgroundColor = HSSFColor.Blue.Index; //水平對齊 m_cellStyle.Alignment = NPOI.SS.UserModel.HorizontalAlignment.Center; //垂直對齊 m_cellStyle.VerticalAlignment = VerticalAlignment.Center; //自動換行 m_cellStyle.WrapText = false; //縮進 //cellStyle.Indention = 0; //} //創建格式 if (m_dataStyle == null) { m_dataStyle = wb.CreateDataFormat(); } //上面基本都是設共公的設置 //下面列出了常用的字段類型 switch (style) { case StyleXlsEnum.Head: //cellStyle.FillPattern = FillPatternType.LEAST_DOTS; //設置為文本格式,也可以為 text,即 dataFormat.GetFormat("text"); m_cellStyle.DataFormat = m_dataStyle.GetFormat("@"); m_cellStyle.SetFont(m_font16); break; case StyleXlsEnum.ColumnHead: m_cellStyle.DataFormat = m_dataStyle.GetFormat("@"); m_cellStyle.SetFont(m_font12); break; case StyleXlsEnum.Default: m_cellStyle.SetFont(m_font); break; } return m_cellStyle; } catch { return m_cellStyle; } }

四、效果圖:

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM