随笔-20  评论-9  文章-1  trackbacks-0

经常看到有些人问怎么把Table的资料转到Excel里面去,很多人在碰到这个问题都先考虑用execl.appliction,使用不太好,首先必需要掌握它的一些内部用法,其次它在客户端使用时涉及安全性,以下介绍三种方法: 


方法一:用单纯的文本格式实现 
 该方法相当简单,以下给出代码,各位就容易明白 
 <% set fso=server.createobject("scripting.filesystemobject") 
  strExcelFile=server.MapPath("txtToExcel.xls") 
  if fso.fileExists(strExcelFile) then fso.deletefile strExcelFile 
  Set xslFile = fso.CreateTextFile(strExcelFile , True) 
  xslFile.WriteLine("df" & vbTab & "345" & vbLf & "fe" & vbTab & "mon" &vbLf) 
  xslFile.Close 
  set fso=nothing 
  response.write "OK" 
 %> 

原理: 
相信大家都知道,Excel是可以打开文本文件的,而对于里面的文本内容Excel则会这样处理:如果遇到[制表符]Tab键则跳下一列,如果遇到[换行符]则换下一行,所以根据这个规则我们整理一下就可以产生单一表格式Excel文件了, 

优点: 
掌握简单,纯粹的文字整理而已。 
缺点: 
效率较低,把一个较多内容的table转成Excel档要则执行较长的循环(),而文档格式只能是规则的行列格式,对表格不能做更多的设置 


方法二:用OWC实现: 
    此方法也简单,只是少为人知而已,同样先给出代码: 
    <script language="javascript"> 
           function exportExcel(atblData){ 
            if (typeof(EXPORT_OBJECT)!="object"){ 
 document.body.insertAdjacentHTML("afterBegin","<OBJECT style=’display:none’ classid=clsid:0002E510-0000-0000-C000-000000000046 id=EXPORT_OBJECT></Object>"); 
   } 
 with (EXPORT_OBJECT){ 
          DataType = "HTMLData"; 
          HTMLData =atblData.outerHTML; 
      try{ 
           ActiveSheet.Export("C:\\owcToExcel.xls", 0); 
  alert(’汇出完毕’); 
            } 
  catch (e){ 
               alert(’汇出Excel表失败,请确定已安装Excel2000(或更高版本),并且没打开同名xls文件’); 
  } 
            } 
 } 
            
  
 <table id="tblData"> 
  <tr><td>gdsssa</td><td>445</td></tr> 
  <tr><td>gdsssa</td><td>445</td></tr> 
 </table> 
  
 <input type="button" value="export" onclick="exportExcel(tblData)"> 

原理: 
大家应该看出这是前端脚本html实现,其实这是利用OWC的功能来转出Excel档,我们只需整理出一个Table档,基本上我们整理出的Table在网页上是什么样子,在Excel上就是什么样子,但要注意:网页里的<style>不会汇出到Excel中,所以网页里的样式表不会在Excel中看到. 
优点: 
掌握也很简单,而且可以在前台实现,并且不会设计权限问题,为前台产生Excel档存到客户端而伤透脑筋的兄弟姐妹们,这个方法. 
缺点: 
客户端必需安装Excel2000或更高版本(不过这个一般都不成问题的了),而且样式表的内容不能输出。 

方法三:利用XML来产生 
     首先讲讲道理,先随便编一个Excel档,然后把它另存为*.htm文件,再用文本编辑器打开,是不是跟我们一般的网页内容非常相似,那么我们是不是只需要整理出这些文字出来就可以了,关键是怎样整理出这份文本文字档案呢 
     我们分析一下这些文字,第一部分是<style>样式表的定义,第二部分是Excel特有的定义内容,第三部分是则是最熟悉的Table数据了,那么对于这三部分,前两部分基本是固定了,我整理一下基本只需要这些: 
     <html xmlns:s="uuid:BDC6E3F0-6DA3-11d1-A2A3-00AA00C14882" xmlns:dt="uuid:C2F41010-65B3-11d1-A29F-00AA00C14882" xmlns:rs="urn:schemas-microsoft-com:rowset" xmlns:z="#RowsetSchema" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:x="urn:schemas-microsoft-com:office:excel" xmlns="::URL::http://www.w3.org/TR/REC-html40">  
  
 <meta http-equiv="Content-Type" content="text/html;"/> 
 <style> 
 xl24{mso-style-parent:style0;mso-number-format:"\@";text-align:right;} 
 </style> 
 <xml> 
 <x:ExcelWorkbook> 
    <x:ExcelWorksheets> 
     <x:ExcelWorksheet> 
       <x:Name>Sheet1</x:Name> 
         <x:WorksheetOptions>                <x:ProtectContents>False</x:ProtectContents> 
              <x:ProtectObjects>False</x:ProtectObjects> 
  <x:ProtectScenarios>False</x:ProtectScenarios> 
         </x:WorksheetOptions> 
       </x:ExcelWorksheet> 
      </x:ExcelWorksheets> 
    </x:ExcelWorkbook> 
 </xml> 
  

     然后是第三部分,我们可以通过recordset来读取数据的指定内容,而且可以通过save来直接把那些内容生成一个xml文件,所以我们只需要根据这个xml文件写一个xsl文件来转换就行了,那么这个方法是我认为最好的,因为我们可以任意设定Table的样式,同时不必诸多循环,有效解决Excel一些自做聪明的小动作 
   这种方法的优点是你可以定制很好的格式的Excel文件,只要你xsl会写,包括统计都可以做出来,所以懂xsl的人估计来到这里比较明白了,而且效率很高,不用再慢慢循环了 
   缺点嘛:就是技术要求高了一点,至于算有多高,各人不同了。 
   最后附上代码: 
  
===========xmlToExcel.asp============= 
<% Set Conn=Server.CreateObject("ADODB.Connection") 
      Conn.Open "Provider = Microsoft.Jet.OLEDB.4.0; Data Source ="& Server.MapPath("comp_apply.mdb") 
  
       ’strSelect="select dept_no,dept_name,dept_check from dept_data" 
        strSelect="select * from user_data"  ’改变该SQL语句则可改变excel的内容 
     Set rs=server.createobject("adodb.recordset") 
  
        rs.open strSelect,conn,1,1 
        set fso=server.createobject("scripting.filesystemobject") 
        strXmlFile=server.MapPath("xmlToExcelTmp.xml") 
        strXslFile=server.MapPath("xmlToExcel.xsl") 
        strExcelFile=server.MapPath("xmlToExcel.xls") 
        if fso.fileExists(strXmlFile) then fso.deletefile strXmlFile 
        rs.save strXmlFile,1 
        rs.close 
        Conn.close 
        set Conn=nothing 
  
 set xmlDoc=server.createobject("microsoft.xmldom") 
 set xslDoc=server.createobject("microsoft.xmldom") 
 xslDoc.load(strXslFile) 
 xmlDoc.load(strXmlFile) 
  
 xmlDoc.loadXml(xmlDoc.transformNode(xslDoc)) 
 if fso.fileExists(strExcelFile) then fso.deletefile strExcelFile 
 Set xslFile = fso.CreateTextFile(strExcelFile , True) 
 xslFile.WriteLine(xmlDoc.xml) 
 xslFile.Close 
 fso.deletefile strXmlFile 
 set fso=nothing 
 response.redirect "xmlToExcel.xls" 
 %> 
  
  
 ==============xmlToExcel.xsl============= 
  
 <xsl:stylesheet version="1.0" xmlns:xsl="::URL::http://www.w3.org/1999/XSL/Transform"  
 xmlns:s=’uuid:BDC6E3F0-6DA3-11d1-A2A3-00AA00C14882’ 
 xmlns:dt=’uuid:C2F41010-65B3-11d1-A29F-00AA00C14882’ 
 xmlns:rs=’urn:schemas-microsoft-com:rowset’ 
 xmlns:z=’#RowsetSchema’> 
  
 <xsl:output method="html" indent="yes" /> 
  
 <xsl:template match="xml/rs:data"> 
 <html xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:x="urn:schemas-microsoft-com:office:excel" xmlns="::URL::http://www.w3.org/TR/REC-html40">  
  
 <meta http-equiv="Content-Type" content="text/html;charset=gb2312" /> 
 <style> 
 .xl24{mso-style-parent:style0;mso-number-format:"\@";text-align:right;} 
 </style> 
 <xml> 
 <x:ExcelWorkbook> 
 <x:ExcelWorksheets> 
 <x:ExcelWorksheet> 
 <x:Name>Sheet1</x:Name> 
 <x:WorksheetOptions> 
        <x:ProtectContents>False</x:ProtectContents> 
        <x:ProtectObjects>False</x:ProtectObjects> 
        <x:ProtectScenarios>False</x:ProtectScenarios> 
 </x:WorksheetOptions> 
 </x:ExcelWorksheet> 
 </x:ExcelWorksheets> 
 </x:ExcelWorkbook> 
 </xml> 
  
   
  
 <table border="1" cellpadding="0" cellspacing="0"> 
 <tr><xsl:for-each select="/xml/s:Schema/s:ElementType/s:AttributeType"> 
                 <th><xsl:value-of select="@name" /></th> 
 </xsl:for-each> 
 </tr> 
 <xsl:apply-templates select="z:row" /> 
 </table> 
  
  
 </xsl:template> 
  
 <xsl:template match="z:row"> 
 <xsl:variable name="position"><xsl:value-of select="position()" /></xsl:variable> 
   
 <tr><xsl:for-each select="/xml/s:Schema/s:ElementType/s:AttributeType">  
                <!-- 读取定义好的数据列名 --> 
 <xsl:variable name="strColumn"><xsl:value-of select="@name" /></xsl:variable> 
                <xsl:variable name="strvalue"><xsl:value-of select="/xml/rs:data/z:row[position()=$position]/@*[name() = $strColumn]" /></xsl:variable> 
 <td class="xl24"> 
 <xsl:value-of select="$strvalue" /> 
 </td> 
 </xsl:for-each> 
 </tr> 
                </xsl:template> 
  
 </xsl:stylesheet> 

        补充一下:对于第三种方法因为Recordset 用 Save方法后有时对于那些null的字段在row中不会有它的字段名,所以我现在通过去ElementType那里读取字段名,以保证不造成到时的Excel的纵列方位出错,但这个问题在.net里的DataSet确很好解决,因为DataSet中如果碰到这种null的数据它也会有<columnName />这样的空节点出现。 

问题: 
能保証select出正確的數據后﹐如果仍沒看到需要的Excel內容的話﹐請確認以下情況: 
1.估計是你的msxml版本低了﹐試試去MS下載個msxmlsp2或更高的版本安裝再看看 
2.請確定你的FSO有足夠的讀寫權限 
3.請保証同名的Excel文件沒在使用中 

怎樣修改標題名﹕ 
這個可以在select 時用別名來命名好標題名﹐但如果用中文的時候有時會出錯﹐我在簡繁體之間就飽受這點的困擾﹔如果不要做到通用的話也可以直接在xsl文件里修改 
B/S模式下实现EXCEL报表的生成与打印 [转]

1. 前言 
报表打印通常是管理信息系统中的一个重要模块,而Excel凭借它功能强大、应用灵活、通用性强等的优势在报表打印中获得了广泛的应用。 
最初的管理信息系统基本上是采用客户机/服务器(C/S)模式开发的,但随着WWW的广泛应用,目前的管理信息系统已经逐渐开始从C/S模式向浏览器/服务器(B/S)模式转变。B/S模式具有传统C/S模式所不及的很多特点,如更加开放、与软硬件无关、应用扩充和系统维护升级方便等等,目前已成为企业网上首选的计算模式,原先在C/S下的很多软件都开始移植到B/S模式下。由于B/S模式的特殊性,在C/S下相对较易实现的Excel报表打印功能在B/S下却成为一个难点。本文根据在实际的项目中总结的经验,以ASP为例,给出了一个较好的通梅椒ā?nbsp; 
2. 功能实现 
为了说明问题,这里举一个例子。系统平台是Windows 2000+SQL Server 2000+IIS 5.0+ASP 3,报表采用的是Excel,要求按照给定的报表格式生成图书销售统计的报表,并能够打印。 
2.1 Excel报表模板的制作 
首先根据给定的报表格式,制作一个Excel模板(就是要打印的报表的表格),当然其中需要从数据库中动态统计生成的数据留着空白。这个报表先在Excel中画好,然后保存为模板,存放在起来,这里为\test\book1.xlt。 
2.2 Excel报表的生成与打印 
这里采用了Excel的Application组件,该组件在安装Excel时安装到系统中。我们的操作也都是针对该组件。 
(1) 建立Excel.Application对象 
set objExcel=CreateObject("Excel.Application") 
(2) 打开Excel模板 
objExcel.Workbooks.Open(server.mappath("\test")&"\book1.xlt") ’打开Excel模板 
objExcel.Sheets(1).select ’选中工作页 
set sheetActive=objExcel.ActiveWorkbook.ActiveSheet   
(3) Excel的常规添加操作 
例如sheetActive.range("g4").value=date() ‘这里添加的是时间,当然也可以是你指定的任何数据 
(4) Excel中添加数据库中的纪录 
这里假设已有一个数据集adoRset,存放由Sql操作生成的统计数据。 
num=7 ‘从Excel的第七行开始 
do until adoRset.EOF ‘循环直至数据集中的数据写完 
strRange="d"&num&":f"&num ‘设定要填写内容的单元区域 
sheetActive.range(strRange).font.size=10 ‘设定字体大小 
sheetActive.range(strRange).WrapText=false ‘设定文字回卷 
sheetActive.range(strRange).ShrinkToFit=true ‘设定是否自动适应表格单元大小 
sheetActive.range(strRange).value=array(adoRset("bookid"),adoRset("bookname"),adoRset("author")) ‘把数据集中的数据填写到相应的单元中 
num=num+1 
adoRset.MoveNext 
loop 
(5) Excel临时报表文件的保存及处理 
实际运行中应该注意每次一个用户进行报表打印时都采用一个临时的Excel文件,而不是硬性规定文件名,因为如果用固定的文件名的话,只有第一次生成是成功的,后面的操作都会因为已存在同名文件而导致失败。所以我们需要每次都产生一个临时的而且不重复的文件名,这里可以采用自定义的getTemporaryFile()函数由来生成,然后存放在变量filename中,用变量filepos表示这些临时文件的路径。 
此外如果这些临时文件不处理的话久而久之会成为文件垃圾,因此在每个用户提交Excel报表打印请求时要先删除临时目录下所有原先产生的临时打印文件。 
临时文件的处理主要代码如下: 
function getTemporaryFile(myFileSystem)   
dim tempFile,dotPos 
tempFile=myFileSystem.getTempName 
dotPos=instr(1,tempFile,".") 
getTemporaryFile=mid(tempFile,1,dotPos)&"xls" 
end function   
set myFs=createObject("scripting.FileSystemObject") 
filePos=server.mappath("\test") & "\tmp\" ’要存放打印临时文件的临时目录 
fileName=getTemporaryFile(myFs) ’取得一个临时文件名 
myFs.DeleteFile filePos&"*.xls" ’删除该目录下所有原先产生的临时打印文件 
set myFs=nothing 
Excel临时文件的保存代码为: 
objExcel.ActiveWorkbook.saveas filePos&filename   
(6) 退出Excel应用 
objExcel.quit 
set objExcel=Nothing 
(7) Excel报表的打印 
前面的步骤已经生成了Excel报表,下一步进行打印,采用的策略可以有两种: 
方案一:提供上面生成的Excel报表临时文件链接给用户,用户可以直接点击在浏览器中打开Excel报表并通过浏览器的打印功能进行打印,也可以点击右键然后另存到本地后再作打印等相关处理。 
方案二:生成Excel报表后直接在客户端加载到浏览器,当然在没有完全加载时应该提示“正在加载,请等待”等字样。 
2.3 系统配置与注意事项 
虽然以上代码很简单,但实际应用不当经常会出现错误,所以下面要讲到的系统配置和注意事项非常关键。 
(1) 千万要保证以上代码输入的正确性,否则一旦运行错误,Excel对象会滞留内存,难以消除,导致下一次调用时速度狂慢,并产生内存不可读写的Windows错误。这时的解决方法就是注销当前用户,如果还不行,就只能Reset了。 
(2) 一定要设置好负责打印功能的asp文件的权限。方法是:在IIS管理中,选择该asp文件,右键然后选“属性”/“文件安全性”/"匿名访问和验证控制“,在这里IIS默认是匿名访问,应该选择验证访问(这里基本验证和集成Windows验证两种方式均可,但前者不够安全),这一点无比重要,否则应用当中会出错的。 
(3) 有的时候报表分为多页,而且我们希望每一页有相同的表头,要求表头每页都自动打印,可以在Excel模板中进行设置。方法如下:选择菜单"文件"/"页面设置"/"工作表",然后在"顶端标题行"输入你表头的行数(如:表头为1-3行即填入::$3)。 

3.总结 
以上我们给出了一个采用ASP写的在B/S模式下实现EXCEL报表的生成与打印的例子,在实际当中已经得到了良好的应用。事实也证明,这个例子的代码虽然不难写,但一定要注意系统的配置,这也是无数次失败后得出的经验。 
ASP操作Excel技术总结 [转]

目录 
一、  环境配置 
二、  ASP对Excel的基本操作 
三、  ASP操作Excel生成数据表 
四、  ASP操作Excel生成Chart图 
五、  服务器端Excel文件浏览、下载、删除方案 
六、  附录 

正文 
一、  环境配置 
服务器端的环境配置从参考资料上看,微软系列的配置应该都行,即: 
1.Win9x+PWS+Office 
2.Win2000 Professional+PWS+Office 
3.Win2000 Server+IIS+Office 
目前笔者测试成功的环境是后二者。Office的版本没有特殊要求,考虑到客户机配置的不确定性和下兼容特性,建议服务器端Office版本不要太高,以防止客户机下载后无法正确显示。 
服务器端环境配置还有两个偶然的发现是: 
1.  笔者开发机器上原来装有金山的WPS2002,结果Excel对象创建始终出现问题,卸载WPS2002后,错误消失。 
2.  笔者开发ASP代码喜欢用FrontPage,结果发现如果FrontPage打开(服务器端),对象创建出现不稳定现象,时而成功时而不成功。扩展考察后发现,Office系列的软件如果在服务器端运行,则Excel对象的创建很难成功。 
服务器端还必须要设置的一点是COM组件的操作权限。在命令行键入“DCOMCNFG”,则进入COM组件配置界面,选择Microsoft Excel后点击属性按钮,将三个单选项一律选择自定义,编辑中将Everyone加入所有权限。保存完毕后重新启动服务器。 
客户端的环境配置没发现什么特别讲究的地方,只要装有Office和IE即可,版本通用的好象都可以。 

二、  ASP对Excel的基本操作 
1、  建立Excel对象 
set objExcelApp = CreateObject("Excel.Application") 
objExcelApp.DisplayAlerts = false    不显示警告 
objExcelApp.Application.Visible = false    不显示界面 
2、  新建Excel文件 
objExcelApp.WorkBooks.add 
set objExcelBook = objExcelApp.ActiveWorkBook 
set objExcelSheets = objExcelBook.Worksheets 
set objExcelSheet = objExcelBook.Sheets(1) 
3、  读取已有Excel文件 
strAddr = Server.MapPath(".") 
objExcelApp.WorkBooks.Open(strAddr & "\Templet\Table.xls") 
set objExcelBook = objExcelApp.ActiveWorkBook 
set objExcelSheets = objExcelBook.Worksheets 
set objExcelSheet = objExcelBook.Sheets(1) 
4、  另存Excel文件 
objExcelBook.SaveAs strAddr & "\Temp\Table.xls" 
5、  保存Excel文件 
objExcelBook.Save    (笔者测试时保存成功,页面报错。) 
6、  退出Excel操作 
objExcelApp.Quit  一定要退出 
set objExcelApp = Nothing 

三、  ASP操作Excel生成数据表 
1、  在一个范围内插入数据 
objExcelSheet.Range("B3:k3").&#118alue = Array("67", "87", "5", "9", "7", "45", "45", "54", "54", "10") 
2、  在一个单元格内插入数据 
objExcelSheet.Cells(3,1).&#118alue="Internet Explorer" 
3、  选中一个范围 
4、  单元格左边画粗线条 
5、  单元格右边画粗线条 
6、  单元格上边画粗线条 
7、  单元格下边画粗线条 
8、  单元格设定背景色 
9、  合并单元格 
10、  插入行 
11、  插入列 

四、  ASP操作Excel生成Chart图 
1、  创建Chart图 
objExcelApp.Charts.Add 
2、  设定Chart图种类 
objExcelApp.ActiveChart.ChartType = 97 
注:二维折线图,4;二维饼图,5;二维柱形图,51 
3、  设定Chart图标题 
objExcelApp.ActiveChart.HasTitle = True 
objExcelApp.ActiveChart.ChartTitle.Text = "A test Chart" 
4、  通过表格数据设定图形 
objExcelApp.ActiveChart.SetSourceData objExcelSheet.Range("A1:k5"),1 
5、  直接设定图形数据(推荐) 
objExcelApp.ActiveChart.SeriesCollection.NewSeries 
objExcelApp.ActiveChart.SeriesCollection(1).Name = "=""333""" 
objExcelApp.ActiveChart.SeriesCollection(1).&#118alues = "={1,4,5,6,2}" 
6、  绑定Chart图 
objExcelApp.ActiveChart.Location 1 
7、  显示数据表 
objExcelApp.ActiveChart.HasDataTable = True 
8、  显示图例 
objExcelApp.ActiveChart.DataTable.ShowLegendKey = True 

五、  服务器端Excel文件浏览、下载、删除方案 
浏览的解决方法很多,“Location.href=”,“Navigate”,“Response.Redirect”都可以实现,建议用客户端的方法,原因是给服务器更多的时间生成Excel文件。 
下载的实现要麻烦一些。用网上现成的服务器端下载组件或自己定制开发一个组件是比较好的方案。另外一种方法是在客户端操作Excel组件,由客户端操作服务器端Excel文件另存至客户端。这种方法要求客户端开放不安全ActiveX控件的操作权限,考虑到通知每个客户将服务器设置为可信站点的麻烦程度建议还是用第一个方法比较省事。 
删除方案由三部分组成: 
A:  同一用户生成的Excel文件用同一个文件名,文件名可用用户ID号或SessionID号等可确信不重复字符串组成。这样新文件生成时自动覆盖上一文件。 
B:  在Global.asa文件中设置Session_onEnd事件激发时,删除这个用户的Excel暂存文件。 
C:  在Global.asa文件中设置Application_onStart事件激发时,删除暂存目录下的所有文件。 
注:建议目录结构 \Src 代码目录 \Templet 模板目录 \Temp 暂存目录 

六、  附录 
出错时Excel出现的死进程出现是一件很头疼的事情。在每个文件前加上“On Error Resume Next”将有助于改善这种情况,因为它会不管文件是否产生错误都坚持执行到“Application.Quit”,保证每次程序执行完不留下死进程。
posted on 2005-09-07 15:55 Kenneth Blog 阅读(1613) 评论(1)  编辑  收藏

评论:
# re: 把Table的资料转到Excel [转] 2009-01-21 02:04 | 挪威克朗
不留下死进程。  回复  更多评论
  

只有注册用户登录后才能发表评论。


网站导航: