Office系列---將Office文件(Word、PPT、Excel)轉換爲PDF文件,提取Office文件(Word、PPT)中的所有圖片

1、Office系列—將Office文件(Word、PPT、Excel)轉換爲PDF文件

將Office文件作爲文章並在網頁上預覽,主要爲(Word、PPT、Excel)3種類型文件。

將Office轉換爲PDF在網頁中預覽:

1.1 基於Office實現的解決方案

實現方式:在本地服務器上安裝Microsoft Office,通過C#代碼調用服務器上的COM接口,將Office文件轉換爲PDF(類似於用Office軟件打開Word文檔,然後另存爲PDF文件)。

不要直接調Office的COM組件,用NetOffice間接調:https://netoffice.io

通過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程序)。

直接調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();
    }
}

1.2 基於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添加到程序中後,程序集命名空間名稱。

2、提取Office文件(Word、PPT)中的所有圖片

2.1 基於OpenXml的解決方案

Office Open XML 是由Microsoft開發的一種以XML爲基礎並以ZIP格式壓縮的電子文件規範,支持文件、表格、備忘錄、幻燈片等文件格式。

簡單來說一個PPT文件(.pptx後綴),其實是一個ZIP格式壓縮的電子文件,壓縮文件內通過XML標記了文檔的內容,比如,引用的圖片、文字的排列方式等等。
常用的幾種Office文件中的,Word文件有.doc和.docx兩種後綴,PowerPoint文件有.ppt和.pptx兩種後綴,Excel文件有.xls和.xlsx兩種後綴。這其實就是文件版本的差異。 OpenXml也只能用在2007及以後的文件版本中(後綴爲.docx、.pptx、.xlsx)。

測試:準備同一PPT文件分別另存爲.ppt和.pptx兩個版本,直接修改文件後綴爲.zip。
在這裏插入圖片描述
通過Nuget包管理安裝需要用到的包

DocumentFormat.OpenXml
using DocumentFormat.OpenXml.Packaging;

/// <summary>
/// 導出PPT文件中所有圖片
/// </summary>
/// <param name="sourcePath">源文件路徑</param>
/// <param name="targetDir">目標文件存放目錄</param>
/// <returns></returns>
public static void ExportPPTImages(string sourcePath,string targetDir)
{
    using (PresentationDocument presentationDocument = PresentationDocument.Open(sourcePath, isEditable: false))
    {
        PresentationPart presentationPart = presentationDocument.PresentationPart;
        DocumentFormat.OpenXml.Presentation.Presentation presentation = presentationPart.Presentation;
        List<ImagePart> list = new List<ImagePart>();
        foreach (DocumentFormat.OpenXml.Presentation.SlideId item in presentation.SlideIdList.OfType<DocumentFormat.OpenXml.Presentation.SlideId>())
        {
            SlidePart slidePart = presentationPart.GetPartById(item.RelationshipId) as SlidePart;
            list.AddRange(slidePart.ImageParts);
        }
        List<IGrouping<string, ImagePart>> list2 = list.GroupBy(d => d.Uri.OriginalString).ToList();

        //導出PPT所有的圖片
        for (int i = 0; i < list2.Count; i++)
        {
            ImagePart imagePart = list2[i].FirstOrDefault();
            string tempFileName = Path.Combine(targetDir, $"image_{i}.jpg");
            using (Stream stream = imagePart.GetStream(FileMode.Open))
            {
                using (Bitmap bitmap = new Bitmap(stream))
                {
                    bitmap.Save(tempFileName, System.Drawing.Imaging.ImageFormat.Jpeg);
                }
            }
        }
        //presentation.Save();
    }
}

/// <summary>
/// 導出Word文件中所有圖片
/// </summary>
/// <param name="sourcePath">源文件路徑</param>
/// <param name="targetDir">目標文件存放目錄</param>
/// <returns></returns>
public static void ExportWordImages(string sourcePath,string targetDir)
{
    using (WordprocessingDocument wordDocument = WordprocessingDocument.Open(sourcePath, isEditable: false))
    {
        var list2 = wordDocument.MainDocumentPart.ImageParts.GroupBy(d => d.Uri.OriginalString).ToList();
        for (int i = 0; i < list2.Count; i++)
        {
            ImagePart imagePart = list2[i].FirstOrDefault();
            string tempFileName = Path.Combine(targetDir, $"image_{i}.jpg");
            using (Stream stream = imagePart.GetStream(FileMode.Open))
            {
                using (Bitmap bitmap = new Bitmap(stream))
                {
                    bitmap.Save(tempFileName, System.Drawing.Imaging.ImageFormat.Jpeg);
                }
            }
        }
    }
}

2.2 基於第三方插件的解決方案

Spire,用Spire正式版插件導出來的圖片沒有水印。

using Spire.Presentation;

/// <summary>
/// 導出PPT文件中所有圖片
/// </summary>
/// <param name="sourcePath">源文件路徑</param>
/// <param name="targetDir">目標文件存放目錄</param>
/// <returns></returns>
public static void ExportPPTImages2(string sourcePath, string targetDir)
{
    using (Presentation pres = new Presentation())
    {
        pres.LoadFromFile(sourcePath);
        for (int i = 0; i < pres.Images.Count; i++)
        {
            Image image = pres.Images[i].Image;
            string tempFileName = Path.Combine(targetDir, $"image_{i}.jpg");
            image.Save(tempFileName);
        }
    }
}
發佈了399 篇原創文章 · 獲贊 225 · 訪問量 33萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章