[C#] 使用NetOffice、PptxTemplater第三方元件 讀寫PowerPoint

C# read/write/AddPicture PowerPoint 

前言

最近工作有需求要用C#讀寫 PowerPoint,上網找了幾個方案:

1.Microsoft.Office.Interop.PowerPoint

免費(好像也不大對,Server端必須安裝Office軟體XD),傳統方式,不適用於Web多執行緒環境,否則多人同時存取時會發生一堆問題如下

https://support.microsoft.com/zh-tw/kb/257757

2.Open XML SDK

免費,但程式碼繁瑣,難以閱讀

3.Aspose.Slides for .NET、Spire.Presentation for .NET、GemBox.PresentationSyncfusion

免費版有投影片張數限制,付費版價格我負擔不起XD

4.github上的PptxTemplater

免費,開放源碼,底層是Open XML SDK,推薦這個!已能解決大部份需求。

5.NetOffice,底層仍是Interop元件,雖有改善一些問題,但不推薦應用在實務上(尤其是Web環境)

以下分別介紹這幾天試了NetOffice和PptxTemplater這兩個元件使用心得。

 

 

NetOffice:http://netoffice.codeplex.com/

雖然它底層是Microsoft.Office.Interop,但至少解決一些問題※注意仍不適用於Web環境

實作

簡單說明NetOffice此元件該如何使用

1.先到官網下載壓縮檔 http://netoffice.codeplex.com/

2.解壓縮後到以下路徑找這幾個檔案,要複製加入自己的專案參考(自己專案是用.NET 4就到NET 4.0資料夾,若是用.NET 4.5的話就到NET 4.5資料夾)

3.加入參考後,確認該4個「內嵌Interop型別」屬性都設為False

4.預先準備一個PowerPoint檔,當做Template檔案。

如果要無中生有,從頭到尾使用程式碼寫出一份漂亮的PowerPoint,我覺得挺辛苦,很耗開發時間。

我的話,會先建立一份PowerPoint,之後程式碼就抓此檔案修改(或替換掉文字)即可。

上圖矩形內的數字,是我自己寫上去,為加入順序的矩形編號碼,待會程式碼會用到,增加可讀性。

5.使用C#打開PowerPoint,寫入文字和加入圖片
※此範例為Console專案

using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;

//操作檔案的引用
using System.IO;
//操作PowerPoint的引用
using NetOffice;
using PowerPoint = NetOffice.PowerPointApi;
using NetOffice.PowerPointApi.Enums;
using NetOffice.OfficeApi.Enums;
using NetOffice.PowerPointApi;

/*
 * 語法語義都和操作Interop一樣,其他不懂操作的就用Interop關鍵字上網Google
 */
namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
           
            //PowerPoint原始範例檔
            string TemplatePath = @"D:\Template.pptx";
            //複製成一份新的,準備編輯它
            string newFilePath = Path.Combine(@"D:\",Guid.NewGuid().ToString()+".pptx");
            File.Copy(TemplatePath,newFilePath);
            // start powerpoint
            using (PowerPoint.Application app = new PowerPoint.Application())
            {
                //打開檔案  
                Presentation presentation = app.Presentations.Open(newFilePath, MsoTriState.msoFalse, MsoTriState.msoFalse, MsoTriState.msoFalse);
                 
                for (int i = 1; i <= 5; i++)
                {//加入5張投影片 

                    //※PownerPoint的index都從1算起
                    int lastSlideIndex = presentation.Slides.Count;//目前投影片Total數量
                    presentation.Slides[lastSlideIndex].Copy();//複製最後一張投影片,準備編輯投影片 
                    presentation.Slides.Paste();//貼上

                    //取得第i張投影片
                    Slide slide = presentation.Slides[i];
                     
                    //※矩形順序為 當時該矩形加入投影片的順序,如果錯亂的話,就刪掉該矩形重新製作

                    //寫入第一個矩形文字
                    TextRange objTextRng1  = slide.Shapes[1].TextFrame.TextRange;
                    objTextRng1.Text = "我的標題:"+i;


                    //取得第二個矩形
                    Shape shape = slide.Shapes[2];
                    //圖片位置
                    string picturePath = @"D:\MyPicture_M.jpg";
                    slide.Shapes.AddPicture(picturePath,
                        MsoTriState.msoFalse, MsoTriState.msoTrue, shape.Left, shape.Top);
                  
                }//end for
                 
                //把最後一張投影片刪除
                presentation.Slides[presentation.Slides.Count].Delete();
                
                //存檔
                presentation.SaveAs(newFilePath);
                 
                //釋放資源
                app.Quit();
                app.Dispose();
            }//end using 
             
        }
         
    }
}

 

6.結果

 

 

 

GitHub - tkrotoff/PptxTemplater:https://github.com/tkrotoff/PptxTemplater

底層是Open XML SDK,適用於Web環境,現在很多讀寫Office文件的操作微軟都建議別用Interop元件,但Open XML SDK程式碼又很瑣碎,還好有大神整理出此開源碼(Orz膜拜一下~~

不過既然它取名為Templater,顧名思義,此元件沒辦法無中生有地建立一份PowerPoint,必須先手動製作一份PowerPoint,再用程式碼去修改它。

實作

1.先下載壓縮檔 https://github.com/tkrotoff/PptxTemplater

2.解壓縮後到以下路徑找這幾個類別檔案.cs,要複製加入自己的專案

※專案新增一個資料夾放這四個檔案(較好歸類)

3.由於底層是Open XML SDK,所以還必須加入相關參考 

沒辦法找到組件參考的話,要先安裝 Open XML SDK (本文為2.5版本)
https://www.microsoft.com/en-us/download/details.aspx?id=30425

※System.Drawing組件也留意一下,應該也要加入

4.此元件的使用方式一定要預先準備一份PowerPoint檔,當做Template檔案。

之後程式碼就抓此檔案修改(或替換掉文字)即可。

大標題我先寫入{{myTitle}} 此關鍵字,稍後程式碼就抓這個取代文字

想要使用程式碼替換圖片的話,可以先選擇插入美工圖案>empty關鍵字搜尋>點選該透明圖片來插入圖片位置

該圖片還得命名一下,給稍後的程式碼抓

↑取名「照片1」

5.使用C#打開PowerPoint,新刪投影片並取代文字、圖片
※此範例為Console專案

using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;

//操作檔案的引用
using System.IO;

//操作PowerPoint的引用
using PptxTemplater;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {

            //PowerPoint原始範例檔
            string TemplatePath = @"D:\Template.pptx";
            //複製成一份新的,準備編輯它
            string newFilePath = Path.Combine(@"D:\", Guid.NewGuid().ToString() + ".pptx");
            File.Copy(TemplatePath, newFilePath);

             
            Pptx pptx = new Pptx(newFilePath, FileAccess.ReadWrite);
            for (int i = 1; i <= 5; i++)
            {//加入5張投影片 

                //取得每次最後一張slide
                int nbSlides = pptx.SlidesCount();//取得slide數
                PptxSlide lastSlide = pptx.GetSlide(nbSlides - 1);
                PptxSlide newSlide = lastSlide.Clone();//複製slide
                PptxSlide.InsertAfter(newSlide, lastSlide);//插入新slide


                PptxSlide currentSlide = pptx.GetSlide(i - 1);//目前投影片,index從0算起 
                currentSlide.ReplaceTag("{{myTitle}}", "我的標題" + i, PptxTemplater.PptxSlide.ReplacementType.Global);
                //圖片路徑
                string picturePath = @"D:\myPicture.jpg";
                currentSlide.ReplacePicture("照片1", picturePath, "image/jpeg");
                 
            }//end for


            //把最後一張投影片刪除,index 從0算起 
            PptxSlide last = pptx.GetSlide(pptx.SlidesCount() - 1);
            last.Remove();
            //關檔
            pptx.Close();


        }


    }
}

 

6.結果

結語

讀寫Office文件我只剩Word還沒寫過,其他它常見格式都已碰過

該用哪個元件提供個人經驗參考:

Excel:EPPlus > NPOI

PDF:iTextSharp(顯示繁體中文要額外處理,不知道此issue改善了沒)、或是找網頁轉PDF的免費元件 

PowerPoint:PptxTemplater

Word:NPOI