You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

关于使用PdfCreator .NET COM包装器打印Excel工作表及旧版本适配的技术问询

PDFCreatorHelper 优化与PDF Creator 2.0+兼容指南

嘿,针对你手里的旧版PDFCreatorHelper类,我整理了使用优化和新版本兼容的具体方案,咱们一步步来看:

首先先贴出你提供的现有代码片段,方便对照:

public class PDFCreatorHelper { //全局声明
private clsPDFCreator _pdfcreator = null;
public string CreatedFile { get; private set; }
public bool ActiveXError { get { return _ActiveXError; } }
private bool _ActiveXError = false;
private void _pdfcreator_eError() { MessageBox.Show("PDF Cre..."); }

一、现有工具类的使用优化建议

1. 完善资源生命周期管理

旧版代码最大的问题是没处理clsPDFCreator这个ActiveX控件的资源释放,长期运行容易导致内存泄漏和ActiveX资源占用。建议实现IDisposable接口,主动清理COM资源:

public class PDFCreatorHelper : IDisposable
{
    private clsPDFCreator _pdfcreator = null;
    public string CreatedFile { get; private set; }
    public bool ActiveXError { get; private set; }

    public PDFCreatorHelper()
    {
        try
        {
            _pdfcreator = new clsPDFCreator();
            _pdfcreator.eError += _pdfcreator_eError;
        }
        catch (Exception ex)
        {
            ActiveXError = true;
            // 这里换成日志记录比弹框更友好,非UI场景也能用
            // Logger.Error("Failed to initialize PDFCreator ActiveX", ex);
        }
    }

    private void _pdfcreator_eError()
    {
        ActiveXError = true;
        // 别硬编码弹窗了,改成事件通知或者抛出具体异常,灵活度更高
        // OnErrorOccurred?.Invoke("PDF Creator runtime error");
    }

    // 实现IDisposable,确保COM资源被释放
    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    protected virtual void Dispose(bool disposing)
    {
        if (disposing && _pdfcreator != null)
        {
            _pdfcreator.Close();
            System.Runtime.InteropServices.Marshal.ReleaseComObject(_pdfcreator);
            _pdfcreator = null;
        }
    }

    ~PDFCreatorHelper()
    {
        Dispose(false);
    }
}

2. 增强错误处理与灵活性

  • 移除硬编码的MessageBox.Show:弹窗在后台服务或控制台程序里完全没用,改成事件回调或者抛出自定义异常,让调用方决定如何处理错误。
  • 补充日志记录:只靠ActiveXError标志很难排查问题,建议加入日志框架(如Serilog、NLog)记录错误详情。

3. 参数化核心逻辑

把Excel文件路径、工作表名称、输出PDF路径这些做成方法参数,不要硬编码,让工具类更通用:

public bool PrintExcelSheetToPdf(string excelFilePath, string sheetName, string outputPdfPath)
{
    if (ActiveXError || _pdfcreator == null)
        return false;

    try
    {
        // 这里用Office Interop处理Excel打印,记得也要释放Excel的COM资源
        var excelApp = new Microsoft.Office.Interop.Excel.Application();
        var workbook = excelApp.Workbooks.Open(excelFilePath);
        var worksheet = workbook.Sheets[sheetName];

        // 指定PDF Creator打印机
        excelApp.ActivePrinter = "PDFCreator";
        worksheet.PrintOut(OutputFileName: outputPdfPath);

        CreatedFile = outputPdfPath;

        // 清理Excel资源
        workbook.Close(false);
        System.Runtime.InteropServices.Marshal.ReleaseComObject(worksheet);
        System.Runtime.InteropServices.Marshal.ReleaseComObject(workbook);
        System.Runtime.InteropServices.Marshal.ReleaseComObject(excelApp);

        return true;
    }
    catch (Exception ex)
    {
        ActiveXError = true;
        // 记录错误日志
        return false;
    }
}

二、PDF Creator 2.0+ 版本兼容方案

PDF Creator 2.0之后彻底弃用了旧的clsPDFCreator ActiveX接口,改用全新的COM API(命名空间PDFCreator.COM),以下是适配步骤:

1. 引用新版本COM组件

在项目的“添加引用”→“COM”列表里找到PDFCreator COM Library(新版本名称可能略有不同),添加引用到项目中。

2. 替换旧的ActiveX对象

PDFCreatorApplicationPrinter类代替旧的clsPDFCreator,示例代码:

using PDFCreator.COM;

public class PDFCreatorNewHelper : IDisposable
{
    private PDFCreatorApplication _pdfApp;
    private Printer _pdfPrinter;
    public string CreatedFile { get; private set; }
    public bool InitializationError { get; private set; }

    public PDFCreatorNewHelper()
    {
        try
        {
            _pdfApp = new PDFCreatorApplication();
            _pdfApp.Initialize();
            _pdfPrinter = _pdfApp.Printer;
            // 可以指定PDF Creator的配置文件,比如"Default"
            _pdfPrinter.DefaultProfile = "Default";
        }
        catch (Exception ex)
        {
            InitializationError = true;
            // 记录初始化错误日志
        }
    }

    public bool PrintExcelSheetToPdf(string excelFilePath, string sheetName, string outputPdfPath)
    {
        if (InitializationError || _pdfApp == null)
            return false;

        try
        {
            var excelApp = new Microsoft.Office.Interop.Excel.Application();
            var workbook = excelApp.Workbooks.Open(excelFilePath);
            var worksheet = workbook.Sheets[sheetName];

            // 用PDF Creator的实际打印机名称
            excelApp.ActivePrinter = _pdfPrinter.Name;
            // 打印到PDF Creator队列
            worksheet.PrintOut();

            // 等待打印作业完成,新版本必须等作业结束才能保存
            var job = _pdfApp.Jobs.Last;
            while (!job.IsFinished)
            {
                System.Threading.Thread.Sleep(100);
            }

            // 保存生成的PDF到指定路径
            job.SaveAs(outputPdfPath);
            CreatedFile = outputPdfPath;

            // 清理资源
            job.Release();
            workbook.Close(false);
            System.Runtime.InteropServices.Marshal.ReleaseComObject(worksheet);
            System.Runtime.InteropServices.Marshal.ReleaseComObject(workbook);
            System.Runtime.InteropServices.Marshal.ReleaseComObject(excelApp);

            return true;
        }
        catch (Exception ex)
        {
            InitializationError = true;
            // 记录错误日志
            return false;
        }
    }

    public void Dispose()
    {
        if (_pdfApp != null)
        {
            _pdfApp.Shutdown();
            System.Runtime.InteropServices.Marshal.ReleaseComObject(_pdfApp);
            _pdfApp = null;
        }
        if (_pdfPrinter != null)
        {
            System.Runtime.InteropServices.Marshal.ReleaseComObject(_pdfPrinter);
            _pdfPrinter = null;
        }
    }
}

3. 关键注意事项

  • 权限配置:打开PDF Creator的设置,找到“COM访问”选项并开启,同时确保你的应用程序有足够权限(比如管理员权限,避免UAC拦截)。
  • 打印机名称:不要硬编码打印机名称,通过_pdfPrinter.Name获取正确的名称,避免环境差异导致的问题。
  • 作业状态等待:新版本的打印作业需要等待完成后才能保存,否则会出现文件未生成或损坏的情况。

三、额外优化建议

  • 摆脱Office Interop依赖:如果不想部署Office组件,可以改用EPPlus、NPOI等开源库读取Excel内容,再用iTextSharp或PdfSharp生成PDF,减少部署复杂度。
  • 批量处理支持:增加批量打印多个工作表或多个Excel文件的方法,提高处理效率。
  • 配置文件驱动:把PDF Creator的打印机名称、默认配置文件等参数存入appsettings.json或配置文件,避免硬编码,方便环境切换。

内容的提问来源于stack exchange,提问作者Vojtěch Dohnal

火山引擎 最新活动