记完成delphi7中Excel转PDF的心历路程

        公司有个老控件,是用Delphi7写的,其中有个导出Excel的功能。之前是用Com组件的方式实现的。这种方式要求客户电脑上必须要安装Excel程序,如果安装的是高版本的,可能还需要安装某个兼容低版本的插件。很麻烦,而且导出还很慢。之前使用过XLSReadWriteII控件,那速度,纲刚的!所以决定换控件!

        经过几天的折腾,控件终于换好了!但新的问题又来了,之前导PDF的功能是Com组件自身就具有的功能,但是XLSReadWriteII没有导出PDF的功能!最初,感觉无非就是再找个Excel转PDF的控件罢了,可谁知就是这个控件,差点要了老夫的“老命”!

        翻遍了国内外,大大小小,知名的不知名的网站,问遍了ChatGPT,文心一言、通译千问等等一些列的人工智能,都没找到一个Delphi上能用的控件!有的控件只支持高版本的delphi,如FlexCel。有的控件,只有安装版,还要收费,最主要的是没有源码,没源码的话,对一个陌生的控件没法学习啊!期间想过用高版本的封装一个dll,再在delphi7的项目里去调用。但是因为这个功能是写在一个控件里的,这个控件拖着一个Dll,使用的时候还得放在主程序的目录里,这感觉比吃翔都难受!所以这个方向也就没再坚持,就一直在网上找控件,找啊找找啊找,找了一天,最后认清现实了!只有封装dll一条路可走了。

        于是,先拿DelphiXE10写了一个程序,调用FlexCel,可以顺利将Excel转成PDF。然后,着手用DelphiXE10写了一个dll,将Excel转PDF的核心过程放到了这个dll中。用测试程序调用这个dll,完美转换!!!心中窃喜,马上就要大功告成了!代码如下:

function ExcelToPDF(ExcelFileName: PAnsiChar; PDFFileName: PAnsiChar; SheetIndex:Integer):Integer; stdcall;
var
  Xls: TXlsFile;
  Pdf: TFlexCelPdfExport;
begin
  Result := 0;
  if SheetIndex <= 0 then
  begin
    SheetIndex := 1;
  end;

  //读取Excel文件
  Xls := TXlsFile.Create(ExcelFileName);
  //关联导出的文档
  Pdf := TFlexCelPdfExport.Create(Xls, True);
  try
    if SheetIndex > Xls.SheetCount then
    begin
      Exit;
    end;
    //设置要导出的工作表
    Xls.ActiveSheet := SheetIndex;
    //导出当前活动的工作表到文件
    Pdf.Export(PDFFileName); // 就是这里报错
    Result := 1;
  finally
    Pdf.Free;
    Xls.Free;
  end;
end;

于是立马将实现过程搬到了正式项目里,运行,果不其然,报错了!!!报了一个内存地址错误。

        心里这个气啊,到底是哪里出错了呢?

        最初,以为是这个dll运行需要高版本的Delphi提供某些环境,低版本的Delphi可能提供不了。但是,转念一想,不对啊,dll理论上是可以被任何程序调用的,不可能还依赖Delphi环境的啊。

        后来,猜想会不会是这个dll某些运行时需要的控件没有打进来?于是,尝试去Delphi的Project-->Options-->Packages-->RunTime Packages菜单下,将Link With RunTime Packages的勾去掉了,运行后还是报错!

        因为后来下班了,可心里一直在想怎么解决这个问题。晚上就在家里有重新安装了一遍这个控件,重新写了一个Demo去测试。这里有个小插曲,在公司时,我最初调用dll的测试程序(DelphiXE10写的),是有引用flexCel控件的单元文件的。当时没删,直接在这个程序上改的。而我在家时,写这个调用Dll的测试程序时,没有引用这些单元文件,运行时居然报错了。原来是低版本delphi程序调用高版本Delphi写的Dll报错,现在是高版本Delphi程序,调用高版本的Delphi写的Dll也报错!忽然意识到,可能是这个FlexCel控件,在Dll中没有进行某些初始化操作啊?

        因为这个控件就引用了3个单元文件,如下:

uses
  VCL.FlexCel.Core,  FlexCel.XlsAdapter,  FlexCel.Render;

我在测试程序中先将这三个单元文件都引用上。然后依次删除,看删除哪个单元文件后,测试程序运行会报错!最后确认是VCL.FlexCel.Core这个单元。于是打开这个单元文件去搜索,看看能不能搜索到某些带初始化字样(如,包含init)的过程。还别说,真找到了一个这样的过程,如下:

抱着试一试的态度,将FlexCelDllInit过程写在了dll的初始化部分,代码如下:

library ExcelConvertPDF;

{ Important note about DLL memory management: ShareMem must be the
  first unit in your library's USES clause AND your project's (select
  Project-View Source) USES clause if your DLL exports any procedures or
  functions that pass strings as parameters or function results. This
  applies to all strings passed to and from your DLL--even those that
  are nested in records and classes. ShareMem is the interface unit to
  the BORLNDMM.DLL shared memory manager, which must be deployed along
  with your DLL. To avoid using BORLNDMM.DLL, pass string information
  using PChar or ShortString parameters. }

uses
  System.SysUtils,
  System.Classes,
  VCL.FlexCel.Core,
  uFunction in 'uFunction.pas';

{$R *.res}



exports
  ExcelToPDF;

begin
  FlexCelDllInit;
end.

再次运行,成功将Excel转成了PDF。顿时如释重负!

  • 19
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

时代奋青

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值