在分享的案例中,我將使用 ASP.NET MVC / C# 利用 Google 搜尋圖片的功能,將關鍵字搜尋到的圖片,導出至 Excel 工作表中的每一列,見圖如下:
匯出的 Excel 內容為搜尋到的每張圖片,不過我沒將圖片完整輸出,而是產生縮圖後才輸出。
因為重點在以 NPOI 產生內嵌圖片的 Excel 工作表,因此我假設讀者都有使用 NPOI 的基礎,只對產生 HSSFWorkbook 的關鍵程式碼說明,其餘的部分可以參考我上傳的 ASP.NET MVC 2 專案,就不另行解釋。
實際上利用 NPOI 產生 workbook 的程式碼如下,關於本文主旨如何利用 NPOI 在 Excel 中插入圖片,特別留意的就是高亮的那幾行程式碼。
private HSSFWorkbook GenerateSearchResult(IEnumerableurls) { int rowIndex = 0; int cellIndex = 0; int pictureIndex = 0; var request = new WebClient(); var workbook = new HSSFWorkbook(); var sheet = workbook.CreateSheet("Search Result"); var patriarch = sheet.CreateDrawingPatriarch(); #region 樣式 HSSFCellStyle headerStyle = workbook.CreateCellStyle(); headerStyle.Alignment = HSSFCellStyle.ALIGN_CENTER; headerStyle.VerticalAlignment = HSSFCellStyle.VERTICAL_CENTER; headerStyle.FillBackgroundColor = HSSFColor.BLACK.index; headerStyle.FillPattern = HSSFCellStyle.SOLID_FOREGROUND; headerStyle.BorderTop = headerStyle.BorderLeft = headerStyle.BorderRight = headerStyle.BorderBottom = 1; HSSFFont headerFont = workbook.CreateFont(); headerFont.Color = HSSFColor.WHITE.index; headerFont.Boldweight = HSSFFont.BOLDWEIGHT_BOLD; headerStyle.SetFont(headerFont); HSSFCellStyle cellStyle = workbook.CreateCellStyle(); cellStyle.Alignment = HSSFCellStyle.ALIGN_LEFT; cellStyle.VerticalAlignment = HSSFCellStyle.VERTICAL_CENTER; cellStyle.BorderTop = cellStyle.BorderLeft = cellStyle.BorderRight = cellStyle.BorderBottom = 1; cellStyle.WrapText = true; #endregion #region 表頭參數 var headers = new[] { new { Caption = "URL", Width = 40 }, new { Caption = "Picture", Width = 20 } }; #endregion #region 表頭 HSSFRow row = sheet.CreateRow(rowIndex++); HSSFCell cell; foreach (var header in headers) { if (header.Width > 0) { sheet.SetColumnWidth(cellIndex, header.Width * 256); } cell = row.CreateCell(cellIndex++); cell.SetCellValue(header.Caption); cell.CellStyle = headerStyle; } HSSFCell colorHeader = row.GetCell(cellIndex - 1); #endregion #region 表身 foreach (var url in urls) { row = sheet.CreateRow(rowIndex++); cellIndex = 0; cell = row.CreateCell(cellIndex++); cell.CellStyle = cellStyle; cell.SetCellValue(url); cell = row.CreateCell(cellIndex++); cell.CellStyle = cellStyle; try { // 下載圖片 var image = Image.FromStream(request.OpenRead(new Uri(url))); // 產生縮圖 decimal sizeRatio = ((decimal)image.Height / image.Width); int thumbWidth = 100; int thumbHeight = decimal.ToInt32(sizeRatio * thumbWidth); var thumbStream = image.GetThumbnailImage(thumbWidth, thumbHeight, () => false, IntPtr.Zero); var memoryStream = new MemoryStream(); thumbStream.Save(memoryStream, ImageFormat.Jpeg); // 將縮圖加入到 workbook 中 pictureIndex = workbook.AddPicture(memoryStream.ToArray(), HSSFWorkbook.PICTURE_TYPE_JPEG); // 將縮圖定位到 worksheet 中 var anchor = new HSSFClientAnchor(0, 0, 0, 0, cell.CellNum, row.RowNum, 0, 0); var picture = patriarch.CreatePicture(anchor, pictureIndex); var size = picture.GetImageDimension(); row.HeightInPoints = size.Height; picture.Resize(); // 為了不讓圖片壓線,必須讓圖片有一點位移,你可以把它移除掉看看會產生什麼情況 // (我得承認這裡是程式中的魔術數字 Orz,但是一時找不到更好的方法) anchor.Dx1 = 5; anchor.Dy1 = 2; } catch (Exception ex) { // 圖片載入失敗,顯示錯誤訊息 cell.SetCellValue(ex.Message); } } #endregion return workbook; }
參考資料
- 本文程式碼下載:ExcelEmbedPictures.rar
- NPOI
- Excel 的規格及限制
11 則留言:
感謝您的分享 讓人獲益良多
站長大人, 您好:
因為程式需求, 需要在EXCEL插入產品圖片, 剛好拜讀到您所寫的範例, 的確有所收穫。但是我按照您的範例所修改的程式, 只秀出來第一張圖片, 而沒能像站長您所提供的範例一般, 每列都可以秀出圖片。不曉得是不是有哪些地方, 我沒有注意到的呢?
冒昧的請您幫忙, 真是不好意思。謝謝。
我猜有可能是圖疊圖了,你可將圖片拖拉看看檢查一下;或者不妨將你的 code 貼上來 ^^
站長大人, 您好:
本來也以為是圖疊圖的關係, 但拖拉之後, 確定只有第一張圖有出現。也試著用trace找出問題, 確定有執行到且也有帶入正確的圖檔, 路徑等資訊。如果刻意讓程式產生exception, 該插入圖片的地方, 則會有 exception message。
因為功力不夠, 我的程式碼又臭又長, 超過了意見的限定, 不曉得站長大人還有沒有什麼建議? 感恩。
站長大人, 您好:
重新檢視及比對範例程式碼後, 問題已經解決了。問題應該是誤將
Dim patriarch As HSSFPatriarch = MySheet.CreateDrawingPatriarch()
放到迴圈之中, 導致問題的發生。多次打擾, 真不好意思, 最後再次謝謝您。
to anderson,
good job!
感謝分享
我想知道圖片可以放置於"頁首頁尾"嗎?
在EXCEL操作上是可以的,但是用NPOI卻不清楚
官網也沒特意說明這些XD
@陳建穎
基本上這個作法是將絕對定位的圖片位置, 對齊於儲存格(Cell), 參考 line 87
如果沒有誤會你的意思, 頁首頁尾的需求應該是有可能用建立儲存格的方式再對齊圖片達成的喔
請問一下可以在Excel中才壓縮圖碼?因為壓縮了才放入Excel質素會差了
@Andy Ip
可以不壓縮圖片的 , 只是可想而知生成的 excel 檔案會隨之變大
我的範例只是順手作了縮圖處理 , 並非一定需要 :)
不,我需要壓縮圖片,但不是在C#壓縮,需要在Excel內壓縮
想問NPOI有resize圖功能嗎?
張貼留言