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的連續調用是正常的,目前還不知道問題的具體原因,有了解的小伙伴可以告訴我一下。


直接調Office的COM組件有版本兼容的問題,可以采用NetOffice間接調用。
通過Nuget安裝NetOffice,不同的Office文件需要引用不同的Apidll

using NetOffice;
using NetOffice.PowerPointApi;

public static void PPTConvertPDF(string sourcePath, string targetPath)
{
    using (Application _pptApp = new Application())
    {
        var pres = _pptApp.Presentations.Open(sourcePath, NetOffice.OfficeApi.Enums.MsoTriState.msoCTrue, NetOffice.OfficeApi.Enums.MsoTriState.msoFalse, NetOffice.OfficeApi.Enums.MsoTriState.msoFalse);
        pres.SaveAs(targetPath, NetOffice.PowerPointApi.Enums.PpSaveAsFileType.ppSaveAsPDF);
        pres.Close();
    }
}

方法參數需要F12進去看參數提醒描述

基於第三方插件實現的解決方案

這里主要介紹下SpireGemBox兩個插件,他們都可以在服務器上沒有安裝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預覽文件的第一頁作為封面

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


免責聲明!

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



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