先抱怨一下:最近在写一个极其恶心的程序:生成Excel reporting。说这个程序恶心,是因为,实现这个报表的方法有很多,我却不得不用我心目中最差的一种方式来实现。
先说说我心目中最好的方式:应该是用NPOI这样的开源库来实现。这个开源库可以脱离开Office软件来独立地生成Excel文件(包括.xls格式和.xlsx格式)。其实实现这种功能的开源库很多,为什么用NPOI呢?因为:
但是,因为在这个项目里能说得上话的领导要求不使用任何第三方库,那么我的选择就只有用Office PIA了。这种方式在我心目中是最差解决方案。Office PIA实际上是通过interop的COM组件来调用Office软件本身来实现文件的创建、读取,微软在MSDN里面明明白白地建议开发者:如果想要调用Office 2007,那么就要用Office 2007 PIA。如果想要调用Office 2010软件,那么就要用Office 2010 PIA。这下问题来了:用户的电脑上面部署什么软件,我们是很难控制的——当然我们也可以提要求,要求用户安装什么软件。用户的电脑可能安装Office 2003,也可能安装Office 2007,也可能安装Office 2010,也可能根本没有安装Office。
好吧,现在让我们假设用户的电脑上一定装有Office,但是我们需要兼容Office 2003、Office 2007、Office 2010,那么我们该用哪个版本的Office PIA呢?根据MSDN上的建议,我应该安装最低版本的,Office 2003 PIA。
现在我的问题来了:
先看一下我要实现的效果:
首先我引用了Office 2003 PIA里面的Microsoft.Office.Interop.Excel.dll,然后在命名空间引用里面援引了以下namespace:
using Excel = Microsoft.Office.Interop.Excel;
/// <summary>Default Excel document file format</summary> private const Excel.XlFileFormat DefaultFileFormat = Excel.XlFileFormat.xlExcel7;
/// <summary> /// Gets current Worksheet instance. /// </summary> public Excel.Worksheet CurrentWorksheet { get; private set; } /// <summary> /// Gets current range instance. /// </summary> public Excel.Range CurrentRange { get; private set; }
/// <summary> /// Set current range as specific address in current worksheet. /// Notice: the range address should be provided as string "$E$2:$G$7" or "E2:G7" /// </summary> /// <param name="address">range address</param> public void SetCurrentRange(string address) { this.CurrentRange = !string.IsNullOrEmpty(address) ? this.CurrentWorksheet.get_Range(address) : this.CurrentWorksheet.Cells; }
/// <summary> /// Merge cells in specific range. /// </summary> /// <param name="address">range address</param> public void MergeRange(string address) { this.SetCurrentRange(address); this.CurrentRange.Merge(); }
我还用了以下函数来使单元格里面的文字纵向居中:
/// <summary> /// Set range vertical alignment to be Center. /// </summary> public void SetRangeAlign_VerticalCenter() { this.CurrentRange.HorizontalAlignment = Excel.Constants.xlGeneral; this.CurrentRange.VerticalAlignment = Excel.Constants.xlCenter; }
这个效果有两个问题:
于是在网上一通海查,尝试代码无数,无果。
经过我不懈的努力,发现:如果将文件保存格式设为 XlFileFormat.xlExcel8,那么一切都正常了:
/// <summary>Default Excel document file format</summary> private const Excel.XlFileFormat DefaultFileFormat = Excel.XlFileFormat.xlExcel8;
在这里用到了一个枚举值:XlFileFormat.xlExcel8
令我纠结万分的是:XlFileFormat.xlExcel8 是从Office 2007开始才出现的一个枚举值。我先前引用的Office PIA的版本是2003,所以 XlFileFormat.xlExcel8 是无法编译通过的。
当然如果引用Office 2007 PIA,则编译可通过。
看来我将不得不放弃对Office 2003 Application的支持?