同事(非编程出身)用 Ruby 写了个程序,生成一个 Excel 文件,把它作为附件发邮件给某些人。Excel 文件中是昨日数据的报告,他让我帮他每天让该程序自动运行一次。因为程序生成 Excel 文件调用的是 win32 OLE,所以是不能在 Linux 里用 cron 定期运行的,只好在一台 Windows 机器上用“任务计划程序”来实现。
奇怪的是到了预定的时间,我们并没有收到电子邮件。到任务计划程序中看,果然任务执行失败了,但是没有更详细的信息,这符合微软的风格──用户不需要知道太多。于是在程序中加入 exception handling,将异常信息写入文件,执行任务后,看到异常是:
OLE error 0x800a03ec: 不能取得类 WorkBook 的 SaveAs 属性
得说明一下,这个 Ruby 程序如果是双击或者在命令行执行,会正常运行。因为指定了 DisplayAlerts = false, 保存文件的时候也不会有提示(假如有提示,就不好自动运行了)。但是在任务计划程序中就出现了这样的错误,我猜想是环境的问题,就像 Linux cron 里的环境变量跟正常登录的 shell 不完全一致一样。
该错误的英文版本是 “Unable to get the SaveAs property of the Workbook class”. 很多时候因为中文的有价值信息太少,我们需要猜测出错信息的英文版本,去搜索英文的资料。不过这次英文资料并没有帮上忙,最后试了一下 SaveCopyAs 这个方法,成功!既然用的是微软的东西,咱也不刨根问底地研究为什么这个方法就可以了──你可能会成为人人景仰的佛,但更可能成为唾弃的疯子。
把 SaveAs 换成 SaveCopyAs 之后,任务计划程序中可以正常运行了,但是在命令行执行时,却会弹出一个需要确认的对话框……同理,不考虑为什么了,直接以暴制暴,用最简单的方式来解决掉它:
begin
workbook.saveas(filename)
rescue Exception => e
workbook.savecopyas(filename)
end
这样,手动执行时使用 SaveAs, 任务计划程序中 SaveAs 会抛出异常,就会使用 SaveCopyAs.
Leave a Reply