zoukankan      html  css  js  c++  java
  • 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预览文件的第一页作为封面

    预知后事如何,且听下回分解(毕竟我也还没有写完啊!~~~~)。

  • 相关阅读:
    HDU.2899.Strange fuction(牛顿迭代)
    BZOJ.3771.Triple(母函数 FFT 容斥)
    树的实现(2)
    树的练习
    死锁问题
    进程的三种状态
    线程的同步与实现
    进程间通信详解
    进程和线程以及它们的区别
    https协议
  • 原文地址:https://www.cnblogs.com/cplemom/p/12186527.html
Copyright © 2011-2022 走看看