报表的开发利器-ExcelQuicker
报表的开发利器-ExcelQuicker
控件名称:
ExcelQuicker
作者:
Eunge
邮箱:
功能:
a)支持Excel文件报表, HTML Web在线报表浏览及其打印
b)快速报表开发,样式化的开发,支持从DataTable、DataGrid直接导出数据
c)稳定的报表框架Framework
d)报表开发的新概念:VBA+XLS 就像 CSS+HTML
开发背景:
a) 背景一:用户群广泛
MS Office Excel自诞生以来,被世界各地的人使用和认可,成为世界上使用最为广泛的办公软件。
b) 背景二:强大的性能
Office中的Excel在日常报表作业当中具有天生的优势,打印单的制作、OLAP数据图标分析、图形分析等。并且,Excel不仅仅支持.xls格式文件,它同样可以导出制作.htm等其他格式的文件。另外,它支持广泛的样式、VBA宏。甚至,很多没有经济实力使用应用软件的Customer使用Excel作为业务管理的载体。
c) 背景三:低廉的售价
相比数万美金的Crystal,几百美金的Office2000/2003,并且大多数的windows用户公司原本就拥有Office的版权,这使得架构在Office系统上的报表系统的额外软件成本几乎为0。
d) 背景四:开发、技术
MS提供的Excel COM接口数量繁多,在茫茫的类、接口当中,我们经常会为我们需要实现的功能犯难,并且,在ASP.NET WEB开发中,稳定性是很大的隐患。对于大多数的Excel二次开发者,他们会发现Excel的异步调用会如此之慢,让人有充分的理由怀疑Excel充当报表框架的可行性。
其实,这部分是因为开发者对Excel操作的不熟悉,另外大部分的原因是因为MS对Excel开发没有进行专门的优化。
ExcelQuicker简介:
是的,通过以上的分析,也许我们会对Office报表有所兴趣,但是我们却没有成功应用的把握,而ExcelQuicker,架构在Excel之上,通过对Excel COM接口的封装,有效的改善了Excel报表的性能和稳定性,并且通过了我所开发的几个大型项目的考证,我很肯定它已经成为是一种较为成熟的方案。
a)性能
伴随着算法的升级,ExcelQuicker在导出大数据量的报表时,各个版本的耗时如下图(对于20000行×10列=20万单元格的报表,在P4 2.6G + 512M配置)
版本 |
耗时 |
描述 |
Excel |
20分钟无结果… |
|
V0.9 |
9分30秒 |
|
V1.1 |
5分30秒 |
|
V1.3 |
4分 |
|
V1.5 |
3分20秒 |
|
V2.0 |
1分25秒 |
|
V2.2 |
1分26秒 |
性能的提升可见一斑 |
*通常我们直接进行C#/VB.NET开发这张Excel报表,得到的结果将会是20分钟以上的遥远等待,而现在的ExcelQuicker2.2,我们可以看到ExcelQuicker可以让我们在性能上不再抱有任何怀疑。
b)功能面
*多样式化的报表;
*支持导出XLS文件报表;
*支持导出HTML Web在线报表,支持在线浏览和打印;
*支持OLAP透视图表;
一种新的实现被应用到ExcelQuicker中,那就是
Css+Html = VBA + Excel
某些报表的布局是相当恼人的,如果可以提供给我一个像开发Windows桌面应用程序那样的编辑器会多好,简单的可视化操作,会让我们在最短的时间类完成高效的设计任务。
然而,或许我们没有发现,Excel本身就是这样的编辑器。我们可以先制作Excel模板文件,然后把剩下的工作交给ExcelQuicker,ExcelQuicker甚至支持在上下两片模板之间插入大批量的数据,以此来简化开发工作。
更强劲的办法是,我们可以像CSS对于Web页面那样,让Excel文档中的VBA脚本对于Excel文档,在没有源代码的情况下,让我们照样可以更改Excel的样式、布局和功能。因为,ExcelQuicker会自动调用Excel模板文档上的“CSS样式”——VBA脚本!而Excel文档的VBA制作极其简单,因为Excel本身提供了“宏”录制!并且对于80%的Excel录制的宏可以直接应用在ExcelQuicker中。这种方式使我们对报表的调整极为方便,甚至我们不需要重新编译整个工程,只需要简单的调整Excel模板文件或者模板文件中的VBA宏
花费:
a)系统
我们将分别对使用Excel和Crystal Report两套报表方案进行比较
Solution |
Price |
|
Office2003 |
$409.99 (3200RMB) |
大不多的公司原本就拥有Office,根本不再需要额外开销。 |
Office2000 |
$289.99 (2400RMB) |
|
Crystal Report(5*License) |
$11200 (约10万RMB) |
5*License Crystal有使用限制,服务器最多只能链接5个终端 |
Crystal Report |
$100000 (约100万RMB) |
由此可见,开源的ExcelQuicker架构在已拥有的Office上,你在报表的开发中,不仅仅可以节省软件费用的开销,甚至在开发的效率上也是大大提升,试想在最短的时间内提供给客户最优秀的报表系统。
a)开发效率
首先Crystal系统不是人人都熟练掌握,正因为它贵,所以它的确大,因此掌握它的人也毕竟没有掌握C#/VB.NET的人多,例如我们这里之前的一个采用Crystal Report(5*License)方案的系统,同样5个人力,
Solution |
Amount |
Spending |
Crystal |
18 |
128人/日 |
ExcelQuicker |
24 |
58人/日 |
对比的这两个方案,都是我们开发人员从陌生到开发出产品所花销的时间,可以看到,要上手Crystal并开发出产品,相对于上手ExcelQuicker的效率还是差了很多。
ExcelQuicker的上手很容易,他的主旨很简单,并且类的数量不多,相信通过ExcelQuicker的数个DEMO示例以及源代码,你可以很快熟悉ExcelQuicker的架构和开发。
ExcelQuicker是开源项目,你可以将它运用在你的商用项目当中或对其进行修改,但ExcelQuicker的版权归我所以,请在修改、重新发布它时,保留版权信息,作为对作者的尊重和开源项目的支持!
ExcelQuicker下载地址
评论
中国的实际情况是,大多数公司连windows的license都没有。而且就算有,windows的license和Office的license也是风马牛不相及的事情呀。 回复
执行这个方法时出现一个异常
this.ReportFiles = objApp.Output(); //Indeed, the result of objApp.Output() is hashtable object contains all type report you sepcialized.
把ExcelQuick加进来后,发现是在
这一行出错
this.mApplication = new Excel.ApplicationClass(); //Construct Excel.
错误: 托管 EE 不理解表达式的语法
请问是何故??
我的Office是2000的,这没关系的吧. 回复
ADD ASPNET account into Administrators group.
还是不行!
“拒绝访问。
ExcelQuicker”
回复
回复
http://www.progame.org/orderprint/ 回复
不知道什么地方错了 回复
因为你没有配置DCOM权限,请参照.chm帮助文档配置DCOM权限。如果操作系统是XP SP2,可能会有异动,建议如果配置DCOM仍然不行,请将ASPNET帐户加入Administrator组,并且取消DCOM配置。
谢谢关注。 回复
你是怎么配置好的。
配置DCOM权限无用后。
ASPNET帐户加入Administrator组,并且取消DCOM配置
也出现错误,还是 没有权限 拒绝访问 回复
国内人很多就像你这样,差劲却很傲气,我最信服的一句话就是:实力作证! 回复
支持 Eunge !支持开源! 回复
然后按照
ASPNET帐户加入Administrator组,并且取消DCOM配置
还是出现: 拒绝访问 回复
回复
回复
在WEb 项目中的web.config中使用模拟,增加下面的语句:
<identity impersonate=”true”/>
可以解决拒绝访问的错误。 回复
Microsoft Jet 数据库引擎打不开文件\’D:\工程\Web Site\EQWebSample\DataBase\DB.mdb\’。 它已经被别的用户以独占方式打开,或没有查看数据的权限。
Microsoft JET Database Engine 回复
未将对象引用设置到对象的实例
是什么原因啊!!! 回复
app = new Excel.Application();
// app.Workbooks.Add(“h:\\book1.xls”);
// int n = app.Workbooks.Count;
Excel.Worksheet shet= (Excel.Worksheet)app.ActiveSheet;
app.Visible = true;
Excel.Workbooks m_objBooks;
Excel._Workbook m_objBook;
Excel.Sheets m_objSheets;
Excel._Worksheet m_objSheet;
Excel.Range m_objRange;
m_objBooks = (Excel.Workbooks)app.Workbooks;
m_objBook = (Excel._Workbook)(m_objBooks.Add(“h:\\book1.xls”));
m_objSheets = (Excel.Sheets)m_objBook.Worksheets;
m_objSheet = (Excel._Worksheet)(m_objSheets.get_Item(1));
// m_objSheets.Add(m_objSheet,m_objSheet,1,0);
// Excel._Worksheet sht ;//= m_objSheet.Creator;
//m_objSheet.Copy(m_objSheet,sht);
//m_objSheet.Delete();
// Excel._Worksheet sht = new Excel._Worksheet();
// m_objSheets.Add(sht);
// Create an array for the headers and add it to cells A1:C1.
object[] objHeaders = {“Order ID”, “Amount”, “Tax”};
m_objRange = m_objSheet.get_Range(“A1”, “C1”);
m_objRange.Value = objHeaders;
// m_objFont = m_objRange.Font;
// m_objFont.Bold=true;
// Create an array with 3 columns and 100 rows and add it to
// the worksheet starting at cell A2.
object[,] objData = new Object[50000,3];
Random rdm = new Random((int)DateTime.Now.Ticks);
double nOrderAmt, nTax;
for(int r=0;r<50000;r++)
{
objData[r,0] = “ORD” + r.ToString(“0000”);
nOrderAmt = rdm.Next(1000);
objData[r,1] = nOrderAmt.ToString(“c”);
nTax = nOrderAmt*0.07;
objData[r,2] = nTax.ToString(“c”);
}
m_objRange = m_objSheet.get_Range(“A2”, “A2”);
m_objRange = m_objRange.get_Resize(50000,3);
m_objRange.Value = objData;
// Save the Workbook and quit Excel.
m_objBook.Save();
回复
对于li_1303提出的数据导出方法,只是ExcelQuicker采用的一种,ExcelQuicker还有更好的方法:先将数据导出成文本文件,以\t和\n标识列和行,再用Excel COM打开这个文本文件,就无需使用Excel COM进行漫长的导出了。具体的方法可以参看ExcelQuicker中相关的源码。
关于临时文件的删除,我当时的作法是:再每次导出Excel文件后,去检查临时文件目录下所有的Excel临时文件,删除LastWriteTime在5分钟之前的文件。
谢谢大家关注。 回复
如果我有时间的话我一定写一个更强的HTML报表了,呵呵。不过最近实在太忙了,而且老实说,在服务器运行EXCEL COM的确不是什么好方法,使用ExcelQuicker现在唯一的理由就是开发快,做2个Excel模板直接套上就是了。对于WEB系统的报表,我更赞成使用WEB的方法来做,用XML、XSL最后导出HTML报表,在客户端一段JS代码允许客户将HTML导出保存为Excel或者PDF,这样扩展性、移植性都很强,而且运行很快,当然开发效率就下去了,不过还得看熟练功。当然也可以用ActiveX控件,如果客户端只使用IE的话。
其实报表的方式很多,甚至还可以用GDI+画,只是对于一般的Beginner来说,懂得解决问题的途径很少而已。 回复
客观的说句,就发布一个控件+一个英文版的函数说明,想用起来的难度还真不小。
能写一些简单的例子来说明就最理想不过了。 回复
不知道你是在Web应用程序还是Winform应用程序呢?你可以给我邮件将问题说得清楚些,或者发在这里更好,最好带上必要的代码,我想有很多热情的朋友会帮助你的(包括我)^_^。 回复
1 客户端得配置DCOM。
2 不能实现真正的客户端打印,还只能调用IE的打印功能。
在局域网里,还能用。
但在互连网上还能用吗?你能让客户去配置DCOM吗? 我的项目里一个报表100多页,你用IE打印得等30分钟。
我知道的能解决所有问题的控件就是 水晶报表10核Activereport for .net 版本,可惜是收费的而且太贵。你通水晶报表的比较没什么意义。其实水晶报表更容易上手。 回复
前面我已经对ExcelQuicker解释过了,这是我一年半以前的作品。
不过对你的无知表示惊讶,配置DCOM是在Server上配置,客户端不需要任何操作,在客户端可以直接打印,因为ExcelQuicker支持导出HTML的WEB报表,而且格式如Excel文档几乎近似。我这里不再宣传ExcelQuicker什么,只是就事论事,ExcelQuicker基于DCOM,非托管,肯定有很多不好的方面的。。。
现在能真正解决问题的其实是技术水平,水平高了,视野就宽广了,Solution就多了。水晶报表10和Activereport.net只是众多Solution中的一种。^_^ 回复
我在web上使用这个控件,生成excel文件之后,是否可以利用EQWebKit.DownloadExcelReport(excel文件名)来让用户选择下载或者打开excel呢?
但是使用了这个方法之后总是提示“StartIndex 不能小于 0。参数名: startIndex ”这个错误,请问怎样才能实现我想要的效果。
系统Win2000Adv,Excel文件已经正常生成。 回复
----------
----------
一个好消息,我现以开发完成电子商务搜索引擎,www.pricesou.com
简介如下:
搜价网是全国首家电子商务搜索引擎,专业为用户提供互联网在线商品搜索服务,使用户能快速地搜索到在线商品及其价格。如果用户接受在线购物,这里将是他们通向商品页面的最佳入口;否则,我们也将为用户提供最好最及时的售价信息指南和查询。
在这里,类似百度、Google,不过他们搜索网页,而搜价网搜索互联网上所有的在线商品和电子商务,专业于电子商务、购物、价格查询。
希望大家给予支持,谢谢。 回复
能给个WindowsFrom的例子吗?谢谢你! 回复
在Graphic目录下:
public class EQImage: EQGraphic
/// <br>//For example, you have a image named: c:\pictures\sun.jpg. And you want to output it on the (2,2) cell of the excel document.</br>
/// <br>EQImage img = new EQImage(@”c:\pictures\sun.jpg”, 2, 2);</br>
/// <br>//img.Width = ?; img.Height = ?; You can resize it by yourself here</br>
/// <br>objEQWorksheet.Add(img);</br>
/// <br>objEQApplication.Add(img);</br>
我试试应该可以的 回复
有一个函数,作用将物理文件路径转换成当前位置的相对路径
public static string GetRelativeFileName(string fileName)
{
string strRequestPage = Path.GetDirectoryName(HttpContext.Current.Request.Url.AbsoluteUri.ToLower()); //Get request uri
string strApplicationName = HttpRuntime.AppDomainAppVirtualPath.ToLower().Replace(“/”,””).Replace(“\\”,””); //Get application name
int pos = strRequestPage.IndexOf(strApplicationName);
strRequestPage = strRequestPage.Substring(pos);
int iLevel = 0; //The level of request page to application virtual path
string strParentPath = strRequestPage;
while(strParentPath != strApplicationName && iLevel<100) //If iLevel reach 100, I think may be there is same problem of this arithmetic
{
iLevel ++;
strParentPath = Directory.GetParent(strRequestPage).Name;
strRequestPage = strRequestPage.Substring(0,(strRequestPage.LastIndexOf(“\\”)-1));
}
string strFileName = fileName.ToLower(); //The report file name
pos = strFileName.IndexOf(strApplicationName);
strFileName = strFileName.Substring(pos + strApplicationName.Length + 1);
string strRelativePath = string.Empty; //The relative path of report file to the current request uri
while(iLevel– > 0)
strRelativePath += “..\\”;
strRelativePath += strFileName;
strRelativePath = strRelativePath.Replace(“\\”,”/”);
return strRelativePath;
}
在while循环中,你应该加上一句话以改变下一步取新目录名的路径
strRequestPage = strRequestPage.Substring(0,(strRequestPage.LastIndexOf(“\\”)-1));
否则,你每次循环都在取同一个目录名,循环100次,只会有100个../,所以尽管生成了文件,但在IE中是取不到文件的 回复