通过使用COM技术我们用微软Office应用程序能够建立很多应用程序扩展但是Java开发人员却无法享受它带来的便利除非他们拥有方便的Java访问COM的途径(JavatoCOM桥)使用JCom的时候你可以在Java中控制几乎所有的COM对象而且它还带有一些用于Excel的强大的辅助类
在你每次编写用HTML表格样式或Java表格对象显示数据的应用程序的时候通常都需要带有导出到Excel功能那么头疼的问题就出现了怎么样实现这种功能呢?在HTML中显示的可以在Office 中处理吗?没有这么好!你还必须支持Office !
你只能去找一个符合当前需求的工具了但是接着收到更多的要求了这能在Word中做到吗?Powerpoint能做到吗?能不能用调制解调器拨号到远程服务器上并发布数据?Java无法实现这些功能是什么意思啊?Java可以实现任何功能
感谢作为Java和COM桥梁的框架组件它使你在遇到这些情况的时候都可以回答YesJavaCOM桥梁使你能够根据自己的需要操作Windows组件以前这是VBC++和NET开发人员的领地你通过实现一个与DCOM后端(back end)对话的Java前端(front end)可以远离端对端(endtoend)的COM系统在本文的末尾你可以使用其中一个JavatoCOM桥它可以被命名为JCom
Excel基础知识
开始之前你需要首先从Sourceforge网站下载API它包含了JCom所使用的Java类的所有源代码C++代码和JCom用于配置Java和COM的编译好的DLL把这个DLL放到你的Java主目录的/bin/目录下面否则会出现问题同时为了不出现问题还要正确地设置JAVA_HOME环境变量JCom的大多数文档目前都是用日语写的但是翻译工作正在进行中因此以后会有些改进的
下载和安装过程完成以后用列表中的代码试一试这段代码会建立到Excel的JCom接口并把Hello World写入第一个单元格中你可以看到如图所示的结果尽管JCom是一个通用的COM类库但是还是带有很多用于Excel的辅助类这是因为Excel可能是最常用的自动化COM应用程序这些辅助类可以为我们节省很多时间它们使JCOM成为一个更好的类库了
列表开始使用JCOM和Excel
import jpneso_netgano_jijcomexcel*;
import jpneso_netgano_jijcom*;
public class testSimple
{
public static void main(String[] args) throws Exception {
ReleaseManager rm = new ReleaseManager();
try {
Systemoutprintln(EXCEL is Starting);
ExcelApplication excel = new ExcelApplication(rm);
excelVisible(true);
ExcelWorkbooks xlBooks = excelWorkbooks();
ExcelWorkbook xlBook = xlBooksAdd();
ExcelWorksheets xlSheets = xlBookWorksheets();
ExcelWorksheet xlSheet = xlSheetsItem();
ExcelRange xlRange = xlSheetCells();
xlRangeItem()Value(Hello World! );
}
catch(Exception e) { eprintStackTrace(); }
finally { rmrelease(); }
}
}
图Java中使用Excel的第一个COM自动化
如果曾经使用VB或VBA来自动化Excel那么你应该很熟悉列表中的代码了ExcelApplication类暴露了Workbooks()属性它列举出Excel中当前打开的工作薄(workbook)并允许你向运行的Excel副本增加或删除工作薄使用Add()方法增加工作薄这个方法会返回一个工作薄的引用
在Excel中工作薄用于保存输入的数据工作薄是XLS文件的基础一个工作薄由多个工作表(worksheet在图中有三个工作表分别叫做SheetSheet和Sheet)工作表通过Item属性来枚举你可以使用这个属性访问特定的工作表在图中Sheet 是第一个工作表因此你可以使用xlSheetsItem()来获取对它的引用
有了工作表之后你就可以使用range(范围)来操作它上面的数据Range是一个单元格或多个单元格例如单元格A可以使用range ()来引用接着可以使用Value属性把数据载入单元格中
更有意义的例子
假设你希望把Excel作为数据库中某些数据的表现层在Java中你希望通过JDBC获取数据并把数据显示在Excel前端这种假设是很好的因为复杂业务逻辑中的用例(use case)已经用Excel前端显示了更不用说工作流中的其它的数据项的显示和交互操作了现在你不需要了解业务逻辑或分析就可以使用原始的电子表格并使用Java中的自动化来填充它们之间的裂痕
我将给出一个演示这种操作的简单示例本文下载中所包含的内容是建立比较销售行为的一个简单的MySQL数据库的它有三个表
· Sales是销售的细节信息包括销售项数量销售价格是谁销售的以及销售地区
· People包含销售人员的姓名和佣金
· Districts包含了销售地区的名称和税率
生成报表的时候你需要使用下面的业务逻辑来算出真正的数值
· 毛销售额等于销售项乘以销售价格加上地税金额
· 纯销售额等于毛销售额减去销售人员提取的税前佣金
这都是一些在Java中可以实现的简单直接的计算过程但是我在本文中使用它们的目的是演示如何把这些数据写入Excel电子表格并让Excel自动计算对于更复杂的情况(使用了更复杂的Excel公式)原理也是一样的
此外下载的内容中还包含了如图所示的电子表格它是作为模板供你填充适当的数据的电子表格
图用于前端填充数据的Excel模板
使用JCOM的时候查询数据库中所有销售数据需要使用下面的SQL
SELECT salesid salesdescription salesquantity salesprice districtsdistrictnamedistrictssalestaxpeoplenamemission
FROM salesdistrictspeople
WHERE (salesdistrict = districtsid) AND (salessalesperson = peopleid)
接着使用自动化(automation)把每条记录都写入Excel电子表格的适当的列中下载的内容中包含了完整的代码(列表所示)在下面的部分我将为你解释代码中使用JCOM的自动化部分
列表从数据库中获取数据并载入Excel中的代码
// 首先建立Excel的引用
ExcelApplication excel = new ExcelApplication(rm);
// 使它可视
excelVisible(true);
// 接着打开我们将使用的模板工作薄
ExcelWorkbooks xlBooks = excelWorkbooks();
ExcelWorkbook xlBook = xlBooksOpen(c:\\salesxls);
// 接着获取我们将修改的范围的引用
ExcelWorksheets xlSheets = xlBookWorksheets();
ExcelWorksheet xlSheet = xlSheetsItem();
ExcelRange xlRange = xlSheetCells();
…
// 此处放置数据库链接和查询建立代码
…
if (stmtexecute(strSql))
{
rs = stmtgetResultSet();
}
int nColCount = rsgetMetaData()getColumnCount();
int nRow=;
int nCol=;
// 在记录集中循环
while(rsnext())
{
// 记录集中的每行都是电子表格中的一行
nRow++;
for(int i=;i<=nColCount;i++)
{
// 匹配DB列和电子表格列
nCol = getExcelColumn(i);
// 查找于行和列对应的单元格,并把它设置为适当的记录集字段
xlRange.Item(nRow,nCol).Value(rs.getObject(i).toString());
}
// 填入公式
xlRange.Item(nRow,7).Value("=RC[-2]*RC[-1]");
xlRange.Item(nRow,9).Value("=RC[-2]*RC[-1]/100");
xlRange.Item(nRow,10).Value("=RC[-3]+RC[-1]");
xlRange.Item(nRow,11).Value("=RC[-4]*((100-RC[2])/100)");
}
在列表2的第一部分中,其目标是获取希望修改的单元格的控制权。tw.wiNgwiT.CoM这会花费了一定的开销。
· 首先你必须获取表现Excel本身的对象,有了JCOM辅助类的帮助以后,这一步操作相当直接。
ExcelApplication excel = new ExcelApplication(rm);
· 下一步,你希望获取对工作薄集合的访问权。你希望打开自己的模板工作薄(本示例中这个模板在C:\sales.xls中),在工作薄集合中打开它。
ExcelWorkbooks xlBooks = excel.Workbooks();
· 下一步,你希望打开自己的工作薄并获取该工作薄集合的引用。
ExcelWorkbook xlBook = xlBooks.Open("c:\\sales.xls");
ExcelWorksheets xlSheets = xlBook.Worksheets();
· 最后,你希望获取集合中的第一个工作表,并把工作范围定义为整个工作表。
ExcelWorksheet xlSheet = xlSheets.Item(1);
ExcelRange xlRange = xlSheet.Cells();
完成这些工作以后,你的xlRange对象将允许你在单元中放入值和公式了。通过在前面的记录集(从提交给数据库的SQL命令中返回的)中循环,使用xlRange.Item(nRow,nCol).Value("whatever")语法,逐行逐列地把记录集中的值插入到电子表格中(语法中的whatever来自于记录集)。通过使用rs.getObject(i).toString可以得到当前行中I列的值