在福州出差ing……使用华表Cell和Sybase、Cognos做项目……这段经历被前辈称为地狱历险记,用的sybase是12.5,Cognos是8.1,华表Cell版本,等等,我查一下,哦,是5.2.6.0809……
翻看华表Cell组件的示例程序,官方的例子十分可怕,在浏览器里加载ActiveX控件(这并不可怕,可怕的是),接着调用华表API中的方法SetCellString()来逐个单元格写入数据到ActiveX控件中——这是从Cell文件加载数据到界面的控件。
来说说功能需求,要从Cell文件中读取报表数据,导入到数据库中,看似简单唯美,但依据官方的例子实难完成。
按官方的例子,首先创建Cell组件的ActiveX控件在页面上,假定为
<object id="DCellWeb1" style="left: 0px; width: 100%; top: 0px; height: 900px;"
codebase="CellWeb5.cab#version=5,3,8,0429" classid="clsid:3F166327-8030-4881-8BD2-EA25350E574A" >
<param name="_Version" value="65536" />
<param name="_ExtentX" value="10266" />
<param name="_ExtentY" value="7011" />
<param name="_StockProps" value="0" />
</object>
使用Cell组件打开本地的某个Cell文件,这样Cell文件中的数据就加载到了Cell控件中
document.getElementById("DCellWeb1").openfile("D:\\temp\\test.cll","");
获取Cell控件中的数据内容,代码如下:
var dcell = document.getElementById("DCellWeb1"); var sendTxt = ""; // Sheet页数 var sheetCount = dcell.GetTotalSheets(); for(var sheet=0; sheet<sheetCount; i++){ dcell.SetCurSheet(sheet); // 获取当前页总列数、行数 var colCount = dcell.GetCols(sheet); var rowCount = dcell.GetRows(sheet); // 获取当前页数据区域的起始列数、行数 var leftCol = dcell.GetLeftCol(); var topRow = dcell.GetTopRow(); // 按行、列,获取所有单元格的数据 for (row=topRow; row<rowCount; row++) { for (col=leftCol; col<colCount; col++) { var sValue = dcell.GetCellString(col, row, sheet); if(sValue=="") sValue=" "; sendTxt+=sValue; if(col < colCount - 1) sendTxt+=","; } if(row < rowCount - 1) sendTxt+="!"; } }
按上面的方法,逐个单元格遍历数据,而后组装起来,使用Ajax等方式向后台传输即可。但是这样做其实不对,因为日常办公面对的统计表格通常都有200多行,100多列,Sheet页都有20个左右,粗略计算一下,GetCellString方法的调用次数多达40多万次,在IE下跑了一下,大约组装过程需要40秒左右。
放弃这条思路,往如何获取整块数据的思路上去搜索API,由于官方论坛在维护,API文档组织上的问题,查了很久才找到如下2个方法:
SaveToXML
ReadFromXML
用这两个方法可以整体获取或写入Cell控件中的数据内容。示例如下:
// 以xml形式,获取dcell中的内容 var xmlcontent = dcell.SaveToXML(''); // xmlcontent为xml形式组织的数据内容,将这些内容写入到dcell组件中 dcell.ReadFromXML(xmlcontent);
这样就完整的获取了Cell组件中的数据内容,调用效率自然是相当的高,大约同上面的报表数据量,只需要0.2秒左右。剩下来的工作就是将这些内容传递到后台,并使用Dom4j或XStream等工具包对XML数据内容进行解析处理。