1. 程式人生 > >Office系列(1)---將Office檔案(Word、PPT、Excel)轉換為PDF檔案

Office系列(1)---將Office檔案(Word、PPT、Excel)轉換為PDF檔案

需求: 將Office檔案作為文章並在網頁上預覽,主要為(Word、PPT、Excel)3種類型檔案。

研究了一下,找到了兩種解決方案

  • 直接呼叫微軟的線上預覽功能實現(預覽前提:預覽資源必須可以直接通過公網訪問到)微軟介面文件
https://view.officeapps.live.com/op/view.aspx?src=http%3a%2f%2fvideo.ch9.ms%2fbuild%2f2011%2fslides%2fTOOL-532T_Sutter.pptx

src後面拼接的就是要預覽的檔案地址(上面地址為官方預覽案例,可以直接在網頁中檢視)

  • 將Office轉換為PDF在網頁中預覽

基於Office實現的解決方案

實現方式:在本地伺服器上安裝Microsoft Office,通過C#程式碼呼叫伺服器上的COM介面,將Office檔案轉換為PDF(類似於用Office軟體開啟Word文件,然後另存為PDF檔案)。

通過Nuget包管理器安裝需要的包(這些包只能在.Net FrameWork版本專案中使用)

Microsoft.Office.Interop.Word
Microsoft.Office.Interop.PowerPoint
Microsoft.Office.Interop.Excel

程式碼:

public class OfficeHelper
{
    static Word.Application wordApplication = new Word.Application();
    static Excel.Application excelApplication = new Excel.Application();
    static PowerPoint.Application pptApplication = new PowerPoint.Application();
    
    /// <summary>
    /// 將Word文件轉換成PDF格式
    /// </summary>
    /// <param name="sourcePath">原始檔路徑</param>
    /// <param name="targetPath">目標檔案路徑</param>
    /// <returns></returns>
    public static bool WordConvertPDF(string sourcePath, string targetPath)
    {
        bool result;
        Word.Document wordDocument = null;
        try
        {
            wordDocument = wordApplication.Documents.Open(ref sourcePath);
            if (wordDocument != null)
            {
                wordDocument.SaveAs2(targetPath, WdExportFormat.wdExportFormatPDF);
                //wordDocument.ExportAsFixedFormat(targetPath, WdExportFormat.wdExportFormatPDF);
                result = true;
            }
        }
        catch (Exception ex)
        {
            result = false;
            LogHelper.Log($"檔案:{sourcePath} 生成失敗,原因:{ex.Message}", ex.StackTrace);
        }
        finally
        {
            if (wordDocument != null)
            {
                wordDocument.Close();
                wordDocument = null;
            }
        }
        return result;
    }
    
    
    /// <summary>
    /// 將Excel文件轉換成PDF格式
    /// </summary>
    /// <param name="sourcePath">原始檔路徑</param>
    /// <param name="targetPath">目標檔案路徑</param>
    /// <returns></returns>
    public static bool ExcelConvertPDF(string sourcePath, string targetPath)
    {
        bool result;
        Workbook workBook = null;
        try
        {
            workBook = excelApplication.Workbooks.Open(sourcePath);
            if (workBook != null)
            {
                workBook.ExportAsFixedFormat(XlFixedFormatType.xlTypePDF, targetPath);
                result = true;
            }
        }
        catch (Exception ex)
        {
            result = false;
            LogHelper.Log($"檔案:{sourcePath} 生成失敗,原因:{ex.Message}", ex.StackTrace);
        }
        finally
        {
            if (workBook != null)
            {
                workBook.Close();
                workBook = null;
            }
        }
        return result;
    }

    /// <summary>
    /// 將PPT文件轉換成pdf格式
    /// </summary>
    /// <param name="sourcePath">原始檔路徑</param>
    /// <param name="targetPath">目標檔案路徑</param> 
    /// <returns></returns>
    public static bool PPTConvertPDF(string sourcePath, string targetPath)
    {
        bool result;
        object missing = Type.Missing;
        Presentation persentation = null;
        try
        {
            persentation = pptApplication.Presentations.Open(sourcePath, MsoTriState.msoTrue, MsoTriState.msoFalse, MsoTriState.msoFalse);
            if (persentation != null)
            {
                persentation.SaveAs(targetPath, PpSaveAsFileType.ppSaveAsPDF, Microsoft.Office.Core.MsoTriState.msoTrue);
                //persentation.ExportAsFixedFormat(targetPath, PpFixedFormatType.ppFixedFormatTypePDF);
                result = true;
            }
        }
        catch (Exception ex)
        {
            result = false;
            LogHelper.Log($"檔案:{sourcePath} 生成失敗,原因:{ex.Message}", ex.StackTrace);
        }
        finally
        {
            if (persentation != null)
            {
                persentation.Close();
                persentation = null;
            }
        }
        return result;
    }
}

Office COM API提供SaveAsExportAsFixedFormat兩個方法來生成文件,需要注意呼叫時引數不同,大部分使用預設值就可以了(介面文件地址)。

上面程式碼中將wordApplication作為一個靜態變數提出來,每次在載入檔案時,再通過它開啟(相當於一直開著Office.Word程式)。在我本地測試時,本地安裝的是Microsoft Office 2016版本,程式碼執行一直正常。當我把程式給發給別人使用時,發現只有在第一次處理Word檔案時轉換成功,之後的檔案轉換都失敗了。
經檢查,由於對方電腦上安裝的是Office365版本,有可能是在第一次處理完檔案後wordApplication

物件就關閉了,從而導致後面的檔案都無法正常轉換。修改程式碼,每次轉換前都去重新例項化Word.Application(相當於重新開啟一遍Office.Word程式),雖然每次例項化導致效率很低,但是所有檔案都處理成功了。最神奇的是同一環境下pptApplication的連續呼叫是正常的,目前還不知道問題的具體原因,有了解的小夥伴可以告訴我一下。

基於第三方外掛實現的解決方案

這裡主要介紹下Spire和GemBox兩個外掛,他們都可以在伺服器上沒有安裝Office軟體的情況下直接處理檔案。
PS: 正式版收費使用,不然生成的文件中會帶有水印。免費版會有一些限制,比如建立或讀取Office檔案時有頁數限制,若超出限制直接拋異常。

這裡簡單介紹下程式碼,詳細的api可以到外掛官網文件中去探索。

  • Free Spire.Doc for .NET

public static void WordConvertPDF(string sourcePath, string targetPath)
{
    using (var doc = new Document(sourcePath))
    {
        doc.SaveToFile(targetPath, Spire.Doc.FileFormat.PDF);
    }
}
  • GemBox.Document free version

public static void WordConvertPDF(string sourcePath, string targetPath)
{
    // If using Professional version, put your serial key below.
    ComponentInfo.SetLicense("FREE-LIMITED-KEY");
    DocumentModel document = DocumentModel.Load(sourcePath);
    document.Save(targetPath, SaveOptions.PdfDefault);
}

基於WPS實現的解決方案

這個和基於Office的解決方案一樣,通過程式碼呼叫COM介面,實現檔案的轉換。當然需要提前在伺服器上安裝WPS軟體。

在本地的WPS安裝目錄中,找到以下幾個dll檔案,並將其引用到專案中,

wpsapi.dll
wpsapiex.dll

程式碼:

public static void WordConvertPDF(string sourcePath, string targetPath)
{
    var app = new Word.Application();
    var doc = app.Documents.Open(sourcePath,Visible: MsoTriState.msoFalse);
    doc.SaveAs2(targetPath, Word.WdExportFormat.wdExportFormatPDF);
    doc.Close();
    app.Close();
}

其中Wordwpsapi.dll新增到程式中後,程式集名稱空間名稱。
呼叫WPS轉換文件我也只是在本機執行成功了,並沒有實際的應用,只能說是多做了一下了解和嘗試吧。

總結

將Office檔案轉為PDF檔案已經成功了,在網頁中預覽PDF檔案就簡單了,甚至有的瀏覽器直接預設可以開啟預覽PDF檔案。這個網上的解決方案已經很多了,最後選擇了通過pdf.js在頁面上預覽。預覽檔案已經有了,剩下的就差一個封面了,乾巴巴的標題太枯燥,圖文並茂才是王道,標題黨也需要一些“切合實際”的圖片來烘托一下氣氛吧!
所以自然而然就有了這個問題,如何給文件設定一個合適的封面圖呢?馬上想到一個辦法自己挑一張順眼的圖片作為封面(好吧這是廢話)。認真思考一下有下面幾種解決方案:

  1. 獲取Office檔案內部的圖片作為封面
  2. 獲取PDF預覽檔案的第一頁作為封面

預知後事如何,且聽下回分解(畢竟我也還沒有寫完啊!~~~~)