[開發經驗分享][.NET C#]如何在Excel表單加入浮水印

分享關於如何在Excel上加入浮水印的解決方法

前言

在之前的文章當中有提到過,如何將Excel匯出為PDF,且不使用 Microsoft Office的套件,經過好多曲折離奇的嘗試之後,終於達成需求,不過這回客戶又有新的需求了,那就是要在Excel以及PDF上加入浮水印,但是因為Excel畢竟不是真正的報表軟體,它是其實是試算表(但很多客戶喜歡把它當報表來用,我也不知道為什麼),所以並沒有真正意義上的浮水印功能,所以我把方向稍稍改變,變成是在Excel背景加入淡化的圖片,同樣能達成浮水印的目標,以下是我所嘗試的解決方法,開始囉。

正解(?):在頁首頁尾插入圖片

由於是Excel,加上原本電腦就有安裝 Microsoft Office,已經用習慣了,所以很理所當然地先用Microsoft Excel打開xlsx檔案,先看要怎麼從MS Excel加入浮水印。

同樣,有問題就先找Google大師,在搜尋了Excel 浮水印這個簡單的關鍵字後,發現官方有提供解法,但官方也講得很明白,Excel並沒有提供浮水印的功能,不過可以用在頁首頁尾加入圖片來實現浮水印的功能,看來官方也了解到會有這種(特異的)需求,還開了一頁做說明:D

官方文章:在 Excel 中新增浮水印

按照步驟設定完之後,在編輯畫面上,並不會出現圖片,如下。

https://ithelp.ithome.com.tw/upload/images/20200203/201162044QnZiBu1rO.jpg

這是因為,頁首頁尾只會在列印的時候被列印出來,所以如果改成預覽列印,就會出現所設定的圖片。

https://ithelp.ithome.com.tw/upload/images/20200203/20116204ci2FrIrKRl.jpg

實驗成功後,接下來就是把這個步驟設定頁首→中間插入圖片,轉換成程式碼,EPPLUS套件要插入頁首圖片的程式碼也相當簡單。

//偶數頁設定頁首圖片
sheet.HeaderFooter.EvenHeader.InsertPicture(new
    FileInfo(HttpContext.Current.Server.MapPath("~/Content/images/excelbk.png")),
    PictureAlignment.Centered);
//奇數頁設定頁首圖片
sheet.HeaderFooter.OddHeader.InsertPicture(new
    FileInfo(HttpContext.Current.Server.MapPath("~/Content/images/excelbk.png")),
    PictureAlignment.Centered);

打完收工,一切是這麼的順利且完美。

事情沒有這麼順利

正當我興高采烈的執行測試,產生Excel之後,打開卻赫然發現圖片不見了,這是發生甚麼事了??

其實線索十分明確,聰明(?)的我,也不會忘記,產生Excel檔案用的並不是MS Excel的套件,而是使用LibreOffice的sdk,所以就朝這方向去找問題,馬上將有圖片的那個Excel檔案用LibreOffice打開看看,發現一樣不會出現圖片,那應該就不是C#程式碼的問題了。

下圖,一樣的檔案,左邊用MS Excel打開會有圖片,右邊用LibreOffice打開就沒有圖片。

https://ithelp.ithome.com.tw/upload/images/20200203/20116204UG0MCOmJ4o.jpg

於是乎,試著用LibreOffice來插入頁首的圖片看看,結果發現,LibreOffice並沒有可以在頁首插入圖片的功能,頁首頁尾設定的項目,由左至右分別是:

  • 文字特性
  • 標題、檔案名稱、路徑/檔案名稱
  • 工作表名稱
  • 頁碼
  • 總頁數
  • 日期
  • 時間 並沒有一個選項可以選擇插入圖片,也因為這樣,所以在頁首頁尾插入圖片當作浮水印,結論是GG

https://ithelp.ithome.com.tw/upload/images/20200203/20116204eAMbtSXZFi.jpg

替代方案:背景圖片

正規(?)的方法不行,那就只好想替代方案了,那就是一開始所想到的,給它一個背景圖就好,沒有採用是因為,背景圖只會出現一遍,不能適用於有分頁的報表,而頁首頁尾可以自動在每頁都加上圖片,比較方便,所以就先試頁首頁尾,現在既然頁首頁尾不行,那就變回插入背景圖,然後在計算它每一頁大約的資料量,就可以在每一頁都出現這個背景圖,也就達成浮水印的功能了。

//6是表頭的資料行數
//30是每頁會出現的資料行數
//這兩個數字請自行判斷
for (var i = 6; i <= data.Data.Count; i += 30)
{
    //圖片路徑
    var img = sheet.Drawings.AddPicture($"bkImage{i}",
        new FileInfo(HttpContext.Current.Server.MapPath("~/Content/images/excelbk.png")));
    //圖片位置依序為:行、RowOffsetPixel、列、ColumnOffsetPixel
    //RowOffsetPixel與ColumnOffsetPixel可以不用設定
    img.SetPosition(i, 0, 2, 0);
}

修改後結果顯示如下,左邊是MS Excel編輯畫面,右邊是LibreOffice編輯畫面,使用這種方法,在編輯畫面也看得到圖片,當然列印也可以。

https://ithelp.ithome.com.tw/upload/images/20200203/201162040O5V7rjIpi.jpg

總結

用插入圖片這種替代方案,固然是可以解決需求,不過缺點是,編輯畫面可以隨意拖拉圖片,不過這也是無可奈何的解法,畢竟Excel本來就沒有浮水印的功能,如果也有夥伴們遇到需要在Excel上加入浮水印的需求的話,然後又有買MS Office授權,就直接用MS Excel插入頁首頁尾吧!但如果只能用免費的OpenOffice來做的話,這邊提供一個替代的解決方案,以上謝謝各位收看。