天天看點

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提供

SaveAs

ExportAsFixedFormat

兩個方法來生成文檔,需要注意調用時參數不同,大部分使用預設值就可以了(接口文檔位址)。

上面代碼中将

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進去看參數提醒描述

基于第三方插件實作的解決方案

這裡主要介紹下Spire和GemBox兩個插件,他們都可以在伺服器上沒有安裝Office軟體的情況下直接處理檔案。

PS: 正式版收費使用,不然生成的文檔中會帶有水印。免費版會有一些限制,比如建立或讀取

Office

檔案時有頁數限制,若超出限制直接抛異常。

這裡簡單介紹下代碼,詳細的api可以到插件官網文檔中去探索。

  • Free Spire.Doc for .NET
Office系列(1)---将Office檔案(Word、PPT、Excel)轉換為PDF檔案
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
Office系列(1)---将Office檔案(Word、PPT、Excel)轉換為PDF檔案
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();
}
           

其中

Word

wpsapi.dll

添加到程式中後,程式集命名空間名稱。

調用WPS轉換文檔我也隻是在本機運作成功了,并沒有實際的應用,隻能說是多做了一下了解和嘗試吧。

總結

将Office檔案轉為PDF檔案已經成功了,在網頁中預覽PDF檔案就簡單了,甚至有的浏覽器直接預設可以打開預覽PDF檔案。這個網上的解決方案已經很多了,最後選擇了通過

pdf.js

在頁面上預覽。預覽檔案已經有了,剩下的就差一個封面了,幹巴巴的标題太枯燥,圖文并茂才是王道,标題黨也需要一些“切合實際”的圖檔來烘托一下氣氛吧!

是以自然而然就有了這個問題,如何給文檔設定一個合适的封面圖呢?馬上想到一個辦法自己挑一張順眼的圖檔作為封面(好吧這是廢話)。認真思考一下有下面幾種解決方案:

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

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

繼續閱讀