以编程方式将 Word (docx) 转换为 PDF

2023-11-22

好吧,在您认为“不再有这样的问题”之前,请先阅读此内容。

我有一个应用程序(ASP.NET MVC 3 中的 Web 应用程序),它使用以下命令在 DocX 中生成 Word 文件DocX 库.

该应用程序采用一个模板并用数据库中的所有数据填充它。 现在我想创建所创建的 docx 文件的 PDF 版本。

I know aspose.word是一个选择,但不适合我,因为我的预算很少。其他需要我花钱的库也是不可能的。

我没有共享点服务器,所以文字自动化服务也不是一个选择。

所以我还有两个选项(据我所知),它们都使用iTextSharp。不知道哪个更好。

  1. 我可以使用从 docx 文件生成的 XML,并将其转换为 iTextSharp 可以使用的版本。
  2. 我可以像使用模板创建 docx 一样创建 PDF。

任何人都知道这需要多少工作,这两个中哪一个具有更好的性能,以及是否有可能完成。

我知道第二个选项有一个缺点,即当我更改模板时,我必须为两个版本都更改它。

如果您有更好的解决方案(即免费),欢迎您分享。


另一种选择,即使需要一些工作:在服务器上安装 OpenOffice,并使用 UNO 库(将它们作为应用程序中的程序集),您可以打开 docx 文档并将其直接保存为 PDF。
几分钟后我会发布一个例子......

部分示例:
这是我很久以前创建的一个类,用于将文件转换为pdf

using unoidl.com.sun.star.lang;
using unoidl.com.sun.star.uno;
using unoidl.com.sun.star.container;
using unoidl.com.sun.star.frame;
using unoidl.com.sun.star.beans;
using unoidl.com.sun.star.view;
using System.Collections.Generic;
using System.IO;

namespace QOpenOffice
{
    public enum AppType
    {
        Writer,
        Calc,
        Impress,
        Draw,
        Math
    }

    public enum ExportFilter{
        Word97,
        WriterPDF,
        CalcPDF,
        DrawPDF,
        ImpressPDF,
        MathPDF
    }

    class OpenOffice
    {
        private XComponentContext context;
        private XMultiServiceFactory service;
        private XComponentLoader component;
        private XComponent doc;

        private List<string> filters = new List<string>();

        #region Constructors
        public OpenOffice()
        {
            /// This will start a new instance of OpenOffice.org if it is not running, 
            /// or it will obtain an existing instance if it is already open.
            context = uno.util.Bootstrap.bootstrap();

            /// The next step is to create a new OpenOffice.org service manager
            service = (XMultiServiceFactory)context.getServiceManager();

            /// Create a new Desktop instance using our service manager
            component = (XComponentLoader)service.createInstance("com.sun.star.frame.Desktop");

            // Getting filters
            XNameContainer filters = (XNameContainer)service.createInstance("com.sun.star.document.FilterFactory");
            foreach (string filter in filters.getElementNames())
                this.filters.Add(filter);
        }

        ~OpenOffice()
        {
            if (doc != null)
                doc.dispose();
            doc = null;
        }
        #endregion

        #region Private methods
        private string FilterToString(ExportFilter filter)
        {
            switch (filter)
            {
                case ExportFilter.Word97: return "MS Word 97";
                case ExportFilter.WriterPDF: return "writer_pdf_Export";
                case ExportFilter.CalcPDF: return "calc_pdf_Export";
                case ExportFilter.DrawPDF: return "draw_pdf_Export";
                case ExportFilter.ImpressPDF: return "impress_pdf_Export";
                case ExportFilter.MathPDF: return "math_pdf_Export";
            }
            return "";
        }
        #endregion

        #region Public methods
        public bool Load(string filename, bool hidden)
        {
            return Load(filename, hidden, "", "");
        }
        public bool Load(string filename, bool hidden, int filter_index, string filter_options)
        {
            return Load(filename, hidden, filters[filter_index], filter_options);
        }
        public bool Load(string filename, bool hidden, string filter_name, string filter_options)
        {
            List<PropertyValue> pv = new List<PropertyValue>();
            pv.Add(new PropertyValue("Hidden", 0, new uno.Any(hidden), PropertyState.DIRECT_VALUE));
            if (filter_name != "")
            {
                pv.Add(new PropertyValue("FilterName", 0, new uno.Any(filter_name), PropertyState.DIRECT_VALUE));
                pv.Add(new PropertyValue("FilterOptions", 0, new uno.Any(filter_options), PropertyState.DIRECT_VALUE));
            }

            try
            {
                doc = component.loadComponentFromURL(
                    "file:///" + filename.Replace('\\', '/'), "_blank",
                    0, pv.ToArray());
                return true;
            }
            catch
            {
                doc = null;
                return false;
            }
        }
        public bool Print()
        {
            return Print(1, "");
        }
        public bool Print(int copies, string pages)
        {
            List<PropertyValue> pv = new List<PropertyValue>();
            pv.Add(new PropertyValue("CopyCount", 0, new uno.Any(copies), PropertyState.DIRECT_VALUE));
            if (pages != "")
                pv.Add(new PropertyValue("Pages", 0, new uno.Any(pages), PropertyState.DIRECT_VALUE));
            //if (doc is XPrintable)
            try
            {
                ((XPrintable)doc).print(pv.ToArray());
                return true;
            }
            catch { return false; }
        }
        public bool Save(string filename, ExportFilter filter)
        {
            return Save(filename, FilterToString(filter));
        }
        public bool Save(string filename, string filter)
        {
            List<PropertyValue> pv = new List<PropertyValue>();
            pv.Add(new PropertyValue("FilterName", 0, new uno.Any(filter), PropertyState.DIRECT_VALUE));
            pv.Add(new PropertyValue("Overwrite", 0, new uno.Any(true), PropertyState.DIRECT_VALUE));
            try
            {
                filename = filename.Replace("\\", "/");
                ((XStorable)doc).storeToURL("file:///" + filename, pv.ToArray());
                return true;
            }
            catch { return false; }
        }
        public bool ExportToPdf(string filename)
        {
            filename = Path.ChangeExtension(filename, ".pdf");
            bool ret = Save(filename, "writer_pdf_Export");
            if (!ret) ret = Save(filename, "impress_pdf_Export");
            if (!ret) ret = Save(filename, "calc_pdf_Export");
            if (!ret) ret = Save(filename, "draw_pdf_Export");
            if (!ret) ret = Save(filename, "impress_pdf_Export");
            if (!ret) ret = Save(filename, "math_pdf_Export");
            return ret;
        }
        public void Close()
        {
            doc.dispose();
            doc = null;
        }

        public bool New(AppType app, bool hidden)
        {
            try
            {
                string sapp = "private:factory/";
                switch (app)
                {
                    case AppType.Writer:
                        sapp += "swriter";
                        break;
                    case AppType.Calc:
                        sapp += "scalc";
                        break;
                    case AppType.Impress:
                        sapp += "simpress";
                        break;
                    case AppType.Draw:
                        sapp += "sdraw";
                        break;
                    case AppType.Math:
                        sapp += "smath";
                        break;
                }
                PropertyValue pv = new PropertyValue("Hidden", 0, new uno.Any(hidden), PropertyState.DIRECT_VALUE);
                doc = component.loadComponentFromURL(sapp, "_blank", 0, new PropertyValue[1] { pv });
                return true;
            }
            catch
            {
                doc = null;
                return false;
            }
        }
        #endregion


        #region Properties
        public List<string> Filters
        {
            get { return filters; }
        }
        #endregion
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

以编程方式将 Word (docx) 转换为 PDF 的相关文章

  • “构建”构建我的项目,“构建解决方案”则不构建

    我刚刚开始使用VS2010 我有一个较大的解决方案 已从 VS2008 成功迁移 我已将一个名为 Test 的控制台应用程序项目添加到解决方案中 选择构建 gt 构建解决方案不编译新项目 选择构建 gt 构建测试确实构建了项目 在失败的情况
  • 在结构中使用 typedef 枚举并避免类型混合警告

    我正在使用 C99 我的编译器是 IAR Embedded workbench 但我认为这个问题对于其他一些编译器也有效 我有一个 typedef 枚举 其中包含一些项目 并且我向该新类型的结构添加了一个元素 typedef enum fo
  • 查找c中结构元素的偏移量

    struct a struct b int i float j x struct c int k float l y z 谁能解释一下如何找到偏移量int k这样我们就可以找到地址int i Use offsetof 找到从开始处的偏移量z
  • 嵌套接口:将 IDictionary> 转换为 IDictionary>?

    我认为投射一个相当简单IDictionary
  • 用于登录 .NET 的堆栈跟踪

    我编写了一个 logger exceptionfactory 模块 它使用 System Diagnostics StackTrace 从调用方法及其声明类型中获取属性 但我注意到 如果我在 Visual Studio 之外以发布模式运行代
  • HTTPWebResponse 响应字符串被截断

    应用程序正在与 REST 服务通信 Fiddler 显示作为 Apps 响应传入的完整良好 XML 响应 该应用程序位于法属波利尼西亚 在新西兰也有一个相同的副本 因此主要嫌疑人似乎在编码 但我们已经检查过 但空手而归 查看流读取器的输出字
  • 关于 C++ 转换:参数 1 从“[some_class]”到“[some_class]&”没有已知的转换

    我正在研究 C 并且遇到了一个错误 我不知道确切的原因 我已经找到了解决方案 但仍然想知道原因 class Base public void something Base b int main Base b b something Base
  • 将多个表映射到实体框架中的单个实体类

    我正在开发一个旧数据库 该数据库有 2 个具有 1 1 关系的表 目前 我为每个定义的表定义了一种类型 1Test 1Result 我想将这些特定的表合并到一个类中 当前的类型如下所示 public class Result public
  • 使用 Bearer Token 访问 IdentityServer4 上受保护的 API

    我试图寻找此问题的解决方案 但尚未找到正确的搜索文本 我的问题是 如何配置我的 IdentityServer 以便它也可以接受 授权带有 BearerTokens 的 Api 请求 我已经配置并运行了 IdentityServer4 我还在
  • while 循环中的 scanf

    在这段代码中 scanf只工作一次 我究竟做错了什么 include
  • 如何序列化/反序列化自定义数据集

    我有一个 winforms 应用程序 它使用强类型的自定义数据集来保存数据进行处理 它由数据库中的数据填充 我有一个用户控件 它接受任何自定义数据集并在数据网格中显示内容 这用于测试和调试 为了使控件可重用 我将自定义数据集视为普通的 Sy
  • 如何查看网络连接状态是否发生变化?

    我正在编写一个应用程序 用于检查计算机是否连接到某个特定网络 并为我们的用户带来一些魔力 该应用程序将在后台运行并执行检查是否用户请求 托盘中的菜单 我还希望应用程序能够自动检查用户是否从有线更改为无线 或者断开连接并连接到新网络 并执行魔
  • 如何使用 C# / .Net 将文件列表从 AWS S3 下载到我的设备?

    我希望下载存储在 S3 中的多个图像 但目前如果我只能下载一个就足够了 我有对象路径的信息 当我运行以下代码时 出现此错误 遇到错误 消息 读取对象时 访问被拒绝 我首先做一个亚马逊S3客户端基于我的密钥和访问配置的对象连接到服务器 然后创
  • 对现有视频添加水印

    我正在寻找一种用 C 在视频上加水印的方法 就像在上面写文字一样 图片或文字标签 我该怎么做 谢谢 您可以使用 Nreco 视频转换器 代码看起来像 NReco VideoConverter FFMpegConverter wrap new
  • 通过指向其基址的指针删除 POD 对象是否安全?

    事实上 我正在考虑那些微不足道的可破坏物体 而不仅仅是POD http en wikipedia org wiki Plain old data structure 我不确定 POD 是否可以有基类 当我读到这个解释时is triviall
  • 将控制台重定向到 .NET 程序中的字符串

    如何重定向写入控制台的任何内容以写入字符串 对于您自己的流程 Console SetOut http msdn microsoft com en us library system console setout aspx并将其重定向到构建在
  • C# 模拟VolumeMute按下

    我得到以下代码来模拟音量静音按键 DllImport coredll dll SetLastError true static extern void keybd event byte bVk byte bScan int dwFlags
  • 如何在文本框中插入图像

    有没有办法在文本框中插入图像 我正在开发一个聊天应用程序 我想用图标图像更改值 等 但我找不到如何在文本框中插入图像 Thanks 如果您使用 RichTextBox 进行聊天 请查看Paste http msdn microsoft co
  • C++ 中类级 new 删除运算符的线程安全

    我在我的一门课程中重新实现了新 删除运算符 现在我正在使我的代码成为多线程 并想了解这些运算符是否也需要线程安全 我在某处读到 Visual Studio 中默认的 new delete 运算符是线程安全的 但这对于我的类的自定义 new
  • 如何防止用户控件表单在 C# 中处理键盘输入(箭头键)

    我的用户控件包含其他可以选择的控件 我想实现使用箭头键导航子控件的方法 问题是家长控制拦截箭头键并使用它来滚动其视图什么是我想避免的事情 我想自己解决控制内容的导航问题 我如何控制由箭头键引起的标准行为 提前致谢 MTH 这通常是通过重写

随机推荐

  • JBoss AS 7 的部署内容在哪里

    我是 JBoss AS 7 的新手 我尝试在 JBoss AS 7 上部署我的 war 文件 看起来工作正常 我的问题是在哪里可以看到部署的内容 我希望它像 Tomcat 一样 它应该有一个探索的 war 文件夹 用于保存部署的内容 JBo
  • 用于返回计算机上 .NET Framework 版本的 PowerShell 脚本?

    返回计算机上 NET Framework 版本的 PowerShell 脚本是什么 我的第一个猜测是涉及 WMI 的东西 还有更好的吗 它应该是一行 为每次 NET 安装 在每一行 仅返回最新版本 如果您要使用注册表 则必须递归才能获取 4
  • 带有绑定参数的 MarkupExtension

    我正在定制MarkupExtension其中我需要来自 XAML 的非字符串参数来构造新对象 是否可以在字段上使用非字符串参数绑定DataContext scope 换句话说 我怎样才能做这样的事情呢
  • What(): std::bad_alloc - 我内存不足了吗?

    我的数据集 960 个维度的 500 000 个点 文件大小为 1 9 GB 1 922 000 000 字节 该代码适用于较小的数据集 但为此它每次都会在同一点崩溃 这是一个最小的例子 include
  • 如何使用js或jquery在html中捕获屏幕截图[重复]

    这个问题在这里已经有答案了 我需要我的客户能够使用如下按钮捕获我网站任何页面的屏幕截图
  • Scikit-learn 多线程

    您知道 scikit learn 中的模型是否使用自动多线程或仅使用顺序指令吗 Thanks 不会 默认情况下 所有 scikit learn 估计器仅在单个线程上工作 但话又说回来 这一切都取决于算法和问题 如果算法需要顺序数据 我们就无
  • 使用 AFNetworking POST jpeg 上传

    我一生都无法弄清楚为什么当我使用 AFNetworking 时这不起作用 它与 ASIHTTP 一起工作 这对我来说都是很新鲜的 但我不明白为什么文件不再从 FILES 传输到服务器的硬盘 这是 iOS 代码 IBAction upload
  • Erlang 有 Sinatra 风格的 Web 框架吗?

    我用 Ruby 和 Rails 编程了很长一段时间 然后我爱上了 Sinatra 框架的简单性 它允许我构建一页 Web 应用程序 Erlang 有像 Sinatra 这样的 Web 框架吗 我尝试了 Erlyweb 但它似乎太重量级了 您
  • Swift JSON 错误,无法将类型“__NSArrayM”(0x507b58)的值转换为“NSDictionary”(0x507d74)

    我正在尝试从 url json 文件 获取数据 但在这些行上收到此错误 var jsonResult NSJSONSerialization JSONObjectWithData data options NSJSONReadingOpti
  • C 语言中在“printf”之后使用“fgets”的问题,因为“fgets”在“printf”之前运行[重复]

    这个问题在这里已经有答案了 可能的重复 为什么 printf 在调用后不会刷新 除非格式字符串中有换行符 在C中 我使用时遇到问题printf and fgets就像我的代码中一样printf写得早于 fget 但它不运行 它运行在 fge
  • :除了不在应用程序控制器的 before_filter 中工作。路由问题?

    我的应用程序控制器中有一个 before filter 来保持用户的会话处于活动状态 如果达到超时则将其注销 这应该在除 sessions new 和 sessions destroy 之外的每个操作上调用 它们被路由为 login 和 l
  • 实体框架 - 如何从元数据获取数据库列数据类型

    有没有办法在给定表的 EntityType 的情况下获取数据库列 DataType 长度信息 您可以运行示例 SQL SQL Server 以准确查看我正在查找的信息 select sys tables name as Table Name
  • 使用端口 443 将 iOS 应用程序上传到 AppStore

    我正在尝试使用 altool 从命令行上传我们的应用程序 由于我们的防火墙阻止了某些端口 因此我想在端口 443 上使用 HTTPS 以 DAV 模式传输文件 如果我使用 ApplicationLoader GUI 手动执行此操作 我可以为
  • 一个圆可以塞进多少个正方形?

    多少个正方形的大小a a可以打包成一个半径为圆的圆R 我不需要解决方案 我只需要某种起始想法 我很抱歉写了这么长的答案 我的方法是从理论上的最大值和保证的最小值开始 当您解决问题时 您可以使用这些值来确定您使用的算法有多好 如果您能想到更好
  • Bootstrap表默认排序

    我使用引导表 第一列有默认排序 如何更改默认列并选择另一个并使用 升序 降序 您可以在表中使用 data sort name 和 data sort order 例如 table 文档在这里http bootstrap table wenz
  • 如何使用 C# 显示文件保存到受限位置的 UAC 提示?

    当用户从我的应用程序保存文件时 他们当前无法保存到受限位置 例如 C 我认为这是一个很好的限制 但我想提供一个 UAC 提示来提升权限并允许用户在受限区域中保存 我已经看到了很多围绕这个主题的答案 其中涉及使用 runas 生成具有提升权限
  • 使用 dplyr mutate 查找组中第一次出现的值

    我如何使用组中找到某个值的第一次出现dplyr 以下代码给出了所需的结果 但我想知道是否有更短的方法来做到这一点 另外 我还担心group by or mutate 或者其他一些函数可能会对行进行隐式重新排列 不知道这是否是一个问题 mtc
  • 控制应用程序的音量:通过进程 ID

    我需要控制特定应用程序产生的音频的音量级别 我找到了西蒙对类似问题的简单而简洁的答案here 但它通过 Display Name 枚举音频生成应用程序 对于某些应用程序来说 它是空的 因此不能用于检测目标应用程序 其音量要控制 因此 我正在
  • 如何在不使用本地或临时文件的情况下将存储过程输出直接写入 FTP 上的文件?

    我想要获取存储过程的结果并将它们放入 FTP 位置的 CSV 文件中 但问题是我无法创建可以通过 FTP 传输的本地 临时文件 我采用的方法是使用 SSIS 包创建临时文件 然后在包中使用 FTP 任务通过 FTP 传输文件 但我们的 DB
  • 以编程方式将 Word (docx) 转换为 PDF

    好吧 在您认为 不再有这样的问题 之前 请先阅读此内容 我有一个应用程序 ASP NET MVC 3 中的 Web 应用程序 它使用以下命令在 DocX 中生成 Word 文件DocX 库 该应用程序采用一个模板并用数据库中的所有数据填充它