cell的应用

近年来,随着客户需求不断上升,传统C/S结构程序的不易升级、维护、管理,且只能局限于局域网,不利于扩展等问题逐渐暴露出来,越来越不能满足客户的需求。而B/S结构程序具有:(1)无须开发客户端软件,维护和升级方便;(2)可跨平台操作,任何一台计算机只要装有WWW浏览器软件,均可作为客户机来访问系统;(3)具有良好的开放性和可扩充性;(4)可采用防火墙技术来保证系统的安全性,有效地适应了当前用户对管理信息系统的新需求等特点更适合客户的需求。网络技术日益成熟和硬件配置不断升级的今天,B/S结构存在网络通信数据量高和响应速度慢的问题逐渐被淡化。但是无论C/S结构还是B/S结构开发MIS系统,都会遇到一个令程序员十分痛苦的问题——报表数据的显示和打印!在技术十分成熟的C/S结构中,对于报表数据的显示和打印问题,相对B/S结构来说容易处理的多,而在B/S结构中要处理中国式复杂报表的显示和打印,技术上是不可想象的。


目前很多软件开发商在B/S结构中处理中国式报表打印时都会采用第三方的ActiveX控件来解决,用友华表的CELL插件也是一款基于ActiveX技术的解决中国式报表显示和打印的第三方控件,但是第三方ActiveX控件只能运行在客户端,直接处理客户端数据,而客户的数据都存放在服务器端,这势必要求客户端的ActiveX控件与服务器端进行数据交互。我们知道在B/S结构中对于少量数据的交互是相当方便的,但是在实际的MIS系统中,服务器端和客户端的数据都是大批量的,如何解决客户端ActiveX控件与服务端大批量数据交互已经成为B/S结构开发MIS系统成功的关键。XML技术正是为解决这种大批量数据交互问题孕育而生。


下面以用友华表CELL插件为例,介绍客户端的ActiveX控件与服务器端使用XML技术进行大批量数据交互。和其它第三方ActiveX控件一样,用友华表CELL插件只能运行在客户端,只能使用JAVASCRIPT、VBSCRIPT客户端语言操纵控件,而控件上的数据是从服务器端生成的并且控件上的数据必须提交至服务器,这样就产生上述所说的数据交互问题。实现客户端与服务器端数据交互必须按照两个步骤实现:1、将服务器端数据库中的数据显示在客户端的CELL插件中;2、将客户端CELL插件中的数据上传至服务器端的数据库。下面以简单示例说明如何利用CELL插件实现客户端与服务器端交换数据(示例采用ASP+VBSCRIPT语言):


1.? 环境配置


1.1?? 服务器配置


服务器运行服务器脚本,必须在服务器端安装WEB服务器。本示例程序使用ASP脚本语言,请安装IIS或PWS服务器,以及使用IE 5.5及以上的版本;


1.2?? 添加CELL插件至网页中


有两种方法可以CELL插件引入至网页中:


a. 在开发工具中将CELL插件引入至工程,然后将CELL插件拖至页面中即可。现以Microsoft Visual InterDev 6.0为例,先新建一个HTML页面,点击TOOL菜单中的Customize Toolbox 子菜单项,弹出引入ActiveX控件界面,如下图所示。


将CellWeb5 Control勾上,确定即可将CELL插件添加至工具箱中,如下图所示


双击后添加至页面中。


b. 直接将CELL插件的OBJECT标记添加至网页,


<OBJECT


id=Cell1 style="LEFT: 0px; WIDTH: 388px; TOP: 0px; HEIGHT: 265px"


classid=clsid:3F166327-8030-4881-8BD2-EA25350E574A


CodeBase="..\CellWeb5.cab#version=5,2,6,328"


VIEWASTEXT>


<PARAM NAME="_Version" VALUE="65536">


<PARAM NAME="_ExtentX" VALUE="10266">


<PARAM NAME="_ExtentY" VALUE="7011">


<PARAM NAME="_StockProps" VALUE="0">


</OBJECT>


注:如果用户升级CAB包,先将原先的CAB包替换,再将CodeBase属性中的Version设置为当前CAB包的版本号。用户再次访问时,IE会重新提示下载最新的CAB包。


?


2. 从服务器端读取数据

?

?


?


2.1打开报表模板


在这里之所以在请求XML数据前要先有打开报表模板,是因为如果将报表样式都存放在XML数据中,势必会增加XML数据量,一方面影响网页的运行速度;另一方面,一旦更改报表样式后,就得修改程序代码,从而增加程序开发和代码维护的工作量;而在模板中存放报表格式,查询报表时先打开模板,上传数据和下传数据时只需传送实际的报表数据,从而大大减少传送数据量和工作量;模板文件可以通过外部程序(可以使用CELL自带的报表设计器)设计,模板文件存放至服务器端的某个虚拟目录下,使用CELL的OpenFile方法打开,文件路径可以是相对路径。


在示例程序中除了对模板格式的设计外,还在模板中设置相应的单元格变量(单元格变量可以根据变量名找到它所对应的单元格),这样做有两个好处:1. 在显示和保存数据时快速地根据变量名找到相应的数据单元格(注:示例程序中变量名采用数据库中的字段名,XML数据中各节点名也用字段名,这样做是为了更好地将数据库字段与单元格对应);2. 即使用户调整模板样式(主要是指更改单元格位置)也可以正确找到相应的单元格;3.加快存取速度;

先介绍在CELL中定义单元格变量和遍历单元格变量(VBS代码)


'定义变量???????? 变量名,列号,行号,页号


Cell1.DefineCellVar "数据库中的字段名",1,1,0


用户也可以在华表自定的模板设计器中定义变量,具体操作步骤:


先在点击要在定义变量的单元格,然后在数据菜单中点击名称定义子菜单项如上图所示,在定义名称对话框中添加变量名称即可,如下图所示


?


'遍历变量


for i=0 to Cell1.GetVarCount-1


'根据ID得到变量名称


Cell1.EnumVar i,strName,strType


'根据变量名称 得到变量所指的区域


Cell1.GetCellVar strName,ncol,nrow,nsheet


Next


?


示例程序中打开远程文件的代码放至在OpenRemoteCllFile()方法中(OpenRemoteCllFile()在Index.asp文件中),关键代码如下:

'打开模板文件


iRet=Cell1.OpenFile("<%=sPath%>","")


if iRet<0 then


msgbox "<%=sPath%>模板,返回值="+iRet+",文件打开失败!"


exit sub


end if


?


说明:


a. sPath为模板的路径,

<%Path=getServerHost()+"/CELLTEMP/test.cll"%>


getServerHost函数在GeneraL.asp文件中:

function getServerHost()


?????? prot = Request.ServerVariables("SERVER_PROTOCOL")


?????? prot = left(lcase(prot),instr(prot,"/")-1)+"://"


?????? url=Request.ServerVariables("SERVER_NAME")


?????? url = url+Request.ServerVariables("PATH_INFO")


?????? url = left(url,instr(instr(url,"/")+1,url,"/"))


?????? getServerHost=prot+url


end function


b. OpenFile返回值如果不等于1,则表示打开不成功;此时还应注意如果是WINXP或WIN2003的操作系统还应在服务器上进行MIME配置,具体可参见CELL帮助中的“目录/FAQ/《为什么打不开远程序文件》” 一文。

2.2 服务器端生成XML数据并发送给客户端


客户端打开模板后,根据查询要求向服务器端发送请求,服务器端接收到请求后,组织XML数据,再发送给客户端;

a.?????? 客户端发送请求


关键代码如下(Index.asp):


'发送查询请求命令


OpenRemoteCllFile '打开模板


txtId=txtOrderId.value? ' txtOrderId为查询订单的编辑框


' IE5.5及以上用XMLDOM, 5.5以下用Msxml2.DOMDocument


set xmlDoc=CreateObject("Microsoft.XMLDOM")


?


'创建XMLHTTP发送对象


set HttpSend=CreateObject("Microsoft.XMLHTTP")


str="GetServerData.asp?OrderId="+txtId? '请求地址


HttpSend.open "GET",str,false?? '采用GET方式请求


HttpSend.send


此段代码在Index.asp文件中,xmlDoc对象只在接收到服务器端传回的XML数据进行解析的作用。发送请求数据的目标地址是可带一个或多个参数的,示例程序中添加OrderId参数作为查询条件,用户可根据实际情况添加多个参数作为查询条件向服务器提交。


?


b.?????? 服务器接收到请求,组织数据后,发送给客户端


主要代码如下(GetServer.asp):


strOrderId=Request("OrderId")? '接收单据ID


set rst=server.CreateObject("adodb.Recordset") '创建记录集对象


rst.ActiveConnection="Provider=Microsoft.Jet.OLEDB.4.0;Data Source="&Server.Mappath("Data\Data.mdb")&";Persist Security Info=False"


rst.CursorLocation = 1


rst.LockType = 3


rst.CursorType = 3


rst.Source = "select * from WipeOrder where nOrderId='" & strOrderId & "'"


rst.Open?? '打开记录集


set xmlDoc=Server.CreateObject("Microsoft.XMLDOM") '创建XML文档对象


’组织XML数据


?


'表头

For i=0 to rst.Fields.Count-1


set xmlChildNode=xmlDoc.CreateElement(rst.Fields(i).Name)? '以字段名为表头子节点名


xmlChildNode.setAttribute "DataType",rst.Fields(i).Type? '添加字段类型属性


xmlChildNode.text=CStr(strValue)? '添加节点值


xmlParentNode.AppendChild xmlChildNode? '添加到"表头"节点


Next


'组织表体数据


rst.Source="select * from WipeOrders where nOrderId='" +strOrderId + "'"


rst.Open? '打开记录集


While not rst.EOF


set xmlParentNode=xmlDoc.CreateElement("表体")? '创建"表体"结点,每一行记录生成一个表体节点

For i=0 to rst.Fields.Count-1


set xmlChildNode=xmlDoc.CreateElement(rst.Fields(i).Name)? '以字段名为表头子节点名


xmlChildNode.text=CStr(strValue) ?'添加节点值


xmlParentNode.AppendChild xmlChildNode ?'添加到"表体"节点中


Next


WEnd


xmlDoc.AppendChild xmlEle ?'将"实施报销单"节点添加至XML文档中


?


'发送XML数据


Response.Write? "<?xml version=""1.0"" encoding=""gb2312""?>" & xmlDoc.Xml Response.End


set xmlDoc=nothing


?


服务器端根据客户端提交的参数,组织查询语句,从数据库中取得记录集,生成XML数据,并通过Response对象将XML数据传给客户端。示例程序中XML文件格式:


?


'XML文件数据示例


<?xml version="1.0" encoding="gb2312"?>


<实施报销单>


<表头>


<ID DataType="3">29</ID>


<nOrderID DataType="202">1</nOrderID>


<sDepName DataType="202">开发部</sDepName>


<sWiper DataType="202">张三</sWiper>


<sWipeWays DataType="202">现金</sWipeWays>


<sSuperior DataType="202">李明</sSuperior>


<sManager DataType="202">李四</sManager>


<sfinancer DataType="202">五王</sfinancer>


<sAccountant DataType="202">五王</sAccountant>


<sCashier DataType="202">五王</sCashier>


<sPayee DataType="202">张三</sPayee>


<sOrderDate DataType="202">2005-03-29</sOrderDate>


<sPrintDate DataType="202">2005-03-29</sPrintDate>


</表头>


<表体>


<ID DataType="3">48</ID>


<nOrderId DataType="202">1</nOrderId>


<sCharge DataType="202">实施费</sCharge>


<sProject DataType="202">软件名称1</sProject>


<fSum DataType="4">11</fSum>


<sChargeMemo DataType="202"></sChargeMemo>


<sBudgetName DataType="202"></sBudgetName>


</表体>


<表体>


<ID DataType="3">49</ID>


<nOrderId DataType="202">1</nOrderId>


<sCharge DataType="202">补贴</sCharge>


<sProject DataType="202">软件名称</sProject>


<fSum DataType="4">2000</fSum>


<sChargeMemo DataType="202"></sChargeMemo><


sBudgetName DataType="202"></sBudgetName>


</表体>????????????????????


</实施报销单>


?


说明:总节点<实施报销单>以单据名称命名;主表数据以<表头>节点命名;子表数据以<表体>节点命名;子表每一条记录生成一个<表体>节点,表中数据存放至<表头>或<表体>各子节点,子节点名以主子表中字段名标识,并增加DataType属性以标识字段数据类型。


?


2.3 客户端接收XML数据,分析、填充至CELL中


客户端将服务端传回的XML数据将载到XML文档对象中,然后在XML对象中对数据进行分析,提取,填充。关键代码如下:


?


'创建XML文件头


HttpSend.responseXML.createProcessingInstruction "xml"," version=""1.0"" encoding = ""gb2312"""


set root=HttpSend.responseXML '以XML方式接收


?


xmlDoc.load root? ‘将XML文件加载至XML文档对象中


?


‘解析将填充CELL控件


?


‘表头


For i=0 to Cell1.GetVarCount-1


Cell1.EnumVar i,strName,strType


'根据'单元‘格中存放的字段名称取得XML节'点的值


set xmlTitle=xmlDoc.selectSingleNode("/实施报销单/表头[0]/"&strItem)


Next


?


‘表体


set xmlItems=xmlDoc.selectNodes("/实施报销单/表体")? '选择所有“表体”节点


Cell1.InsertRow 6, xmlItems.length-1,n


For? j=0? to? xmlItems.length-1


set strItem="/实施报销单/表体["+j+"]"? '选择第J个表体节点


For i=0 to Cell1.GetVarCount-1


Cell1.EnumVar i,strName,strType


'根据单元'格中存放的字段名称取得XML节点的值


set xmlTitle=xmlDoc.selectSingleNode(strItem+"/"+strItem)


Next


Next


?


在示例程序中采用遍历模板所有单元格变量(变量名称=表头/表体+字段名称,例如,主表的nOrderId字段则表示为[0]nOrderId),根据变量名称中记录的字段信息在XML文档中取得相关的数据,然后根据DataType属性,确定用单元格的数据类型,采用S或D方法。在一个XML文档只有一个表头节点,所以其子节点可以表示为“表头[0]/节点名”,直接用selectSingleNode 方法取得,而一个XML文档中有多个表体节点,所以先用selectNodes("/实施报销单/表体")方法取得所有表体的对象集,然后再循环遍历每个表体节点的各个子节点。如果客户在单元格中要存储的信息量比较多,单元格变量承载不下时,可以考虑使用单元格标注,通过SetCellNote和GetCellNote方法设置和取得标注内容。


?


3.? 保存数据到服务器端

?


3.1 客户端生成XML数据并传到服务器端


客户端根据CELL控件上的数据组织成XML数据,XML文档格式同上述(从服务器端传回的XML文档)大致相同,只是在各未级子节点没有DataType属性。示例程序中将生成XML程序部分,存至CreateXMLFile()方法中,关键代码如下:


?


'创建XML文件对象


set xmlDoc=CreateObject("Microsoft.XMLDOM")?? 'XML文件头


?


'创建第一个子节点


set xmlRoot=xmlDoc.createElement("实施报销单")


?


'创建表头内容


set xmlTitle=xmlDoc.createElement("表头")


'添加表头子节点


For i=0 to Cell1.GetVarCount()-1


Cell1.EnumVar i,strName,strType


?


set xmlChild=xmlDoc.createElement(strItem) '创建节点


If isnull(xmlChild)=false Then


Cell1.GetCellVar strName,ncol,nrow,nsheet


xmlChild.text=Cell1.GetCellString(ncol,nrow,nsheet)


xmlTitle.appendChild xmlChild '添加节点


End If


Next


?


For i=5 to nMaxBodyRow-1


set xmlBody=xmlDoc.createElement("表体")


For j=0 to Cell1.GetVarCount()-1


Cell1.EnumVar j,strName,strType


?


set xmlChild=xmlDoc.createElement(strItem) '创建节点


xmlBody.appendChild xmlChild '添加节点


Next


?


xmlRoot.appendChild xmlBody


Next


?


xmlDoc.appendChild(xmlRoot); ‘添加“实施报销单”节点至XML文件中


'创建HTTP发送对象


set HttpSend=CreateObject("Microsoft.XMLHTTP")


'打开发送通道


HttpSend.open "POST","SaveClientData.asp",false


HttpSend.send xmlDoc '发送数据


strReturn=HttpSend.ResponseText '接收返回结果


msgbox strReturn '弹出提示


?


示例中求表体的起始行和结束行都非常固定,用户可以增加表体标识精确判断。创建XMLHTTP对象,采用“POST”动作打开通道,发送后根据SaveClientData.asp页面处理返回的结果弹出提示,告知用户。


?


3.2 服务器端接收XML数据,分析、填充至数据库中


SaveClientData.asp页面根据客户端提交的XML数据,接收后,进行分析,并保存至数据库,关键代码如下(ASP):


?


'创建XMLDOM IE5.5以下用Msxml2.DOMDocument


set xmlDoc=server.CreateObject("Microsoft.XMLDOM")


xmlDoc.load Request? '加载远程提交XML文件


?


set xmlTitle=xmlDoc.SelectSingleNode("/实施报销单/表头[0]")? '选择表头,表头只有一个节点


set xmlBody=xmlDoc.SelectNodes("/实施报销单/表体")? '选择表体


?


Response.ContentType = "text/xml; charset=GB2312"


?


‘建立数据库连接


strcon="Provider=Microsoft.Jet.OLEDB.4.0;Data Source="&Server.Mappath("Data\Data.mdb")&";Persist Security Info=False"


set cmd=server.CreateObject("adodb.command")


cmd.ActiveConnection=strcon


?


‘先删除数据库中原表头表体中的数据


cmd.CommandText="delete from WipeOrder where nOrderID='" & Node.text & "'"


cmd.Execute


cmd.CommandText="delete from WipeOrders where nOrderID='" &Node.text & "'"


cmd.Execute


'表头


'组织表头SQL语句


For i=0 to xmlTitle.childnodes.length-1


strSql=strSql & xmlTitle.childnodes(i).nodeName&" ,"


strSubSql=strSubSql&"'"& xmlTitle.childnodes(i).Text&"' ,"


Next


'插入表头数据


strSql= mid(strSql,1,len(strSql)-1)& ")" & mid(strSubSql,1,len(strSubSql)-1)&")"


cmd.CommandText=strSql cmd.Execute ?'插入表头数据


?


'表体


'组织表体SQL语句


For i=0 to xmlBody.length-1


'组织表体的SQL语句

strSql="insert into wipeorders(nOrderID, " strSubSql=" values('" & Node.text& "',"


set xmlChildBody=xmlDoc.SelectSingleNode("/实施报销单/表体["&i&"]")? '得到第i个表体节点

for j=0 to xmlChildBody.childnodes.length-1 ?'遍历第i个表体节点的所有子节点

strSql=strSql & xmlChildBody.childnodes(j).nodeName&" ,"


strSubSql=strSubSql&"'"& xmlChildBody.childnodes(j).Text&"' ,"


Next


strSql= mid(strSql,1,len(strSql)-1)& ")" & mid(strSubSql,1,len(strSubSql)-1)&")"

cmd.CommandText=strSql cmd.Execute ?'插入表体数据


Next


?


set cmd=nothing? '清空对象


Response.Write "保存成功!" ?'返回成功信息


?


服务器端将客户端提交的XML数据,创建XML文档对象,并加载存放在request对象中的XML数据,再解析。示例程序中对XML数据的要求只限定在单据号,用户在实际项目中可以增加判断的条件。为保证数据库中数据的正确性,采用在保存新数据前,先将数据库中原数据记录全部删除 ,再插入新记录的方式。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
原创Matlab通过ODBC的方式调用数据库-CellStrJoinWithSeparator.m 以下内容为Matlab中文论坛会员,Godman原创。 如果需要转载,请联系Godman会员: 如有疑问可以邮件联系 [email protected] Godman 2009.3.30 晚 Good Luck! —————————————————————————————————————————— Matlab数据库编程指南-Godman Matlab与数据库链接有三种方法,本文只讲述其中以ODBC的方式进行链接。 本文件包含四部分,其中第三部分为我自己写的一些数据库函数操作的函数,第四部分为网上的一些资料。 第一部分:读取数据其相关信息查看 1.        配置数据源 “控制面板”----“管理工具”——“数据源(ODBC)”——“添加”——“创建数据源名称和选择数据库文件”(具体操作见GIF图片操作)。 2.        建立链接对象——database 调用格式: conna=database; 如conna=database;其中SampleDB为上文中创建的数据源名称,当默认情况下,数据库文件的username和password为空。 3.        建立并打开游标——exec 调用格式: curs=exec; 如curs=exec 其中conna为上文中链接对象,select * from database表示从表database中选择所有的数据. 4.        把数据库中的数据读取到Matlab中——fetch 调用格式: curs=fetch; Data=curs.Data;%把读取到的数据用变量Data保存. 如curs=fetch; 把所有的数据一次全部读取到Matlab中,RowLimit为每次读取的数据参数的行数,默认为全部读取,但是全部读取会很费时间(和计算机性能很大关系)。 上述四点是matlab从数据库文件中读取数据到matlab中的基本步骤。 5.        数据返回类型 从数据库中读取数据到matlab有三种数据类型(默认为元胞类型cellarray),分别为元胞类型(cellarray),数字型(numeric),结构型(structure)。可以在链接数据库之前通过setdbprefs函数来进行设置。如果数据库文件中全部是数值型数据时最好采用numeric型的数据,这样可以使得读取速度大幅提高,特别是在大型数据读取时非常明显。我曾经从数据库中读取过100万个数据,用cellarray时用了16s,但是用numeric时却只用了8s,速度提高很大啊,对电脑配置不好的来说,很有帮助的。(还有我的电脑很烂,1.3GHz,384M内存,可能让大家见笑了…….) 调用格式: setdbprefs 6.        养成良好习惯,随手关闭链接对象和游标——close 当不再使用数据库的链接对象时要及时关闭,这样才能及时的释放出内存,而且每次链接后所需要的内存量是非常大的,要是不及时关闭的话对后续计算的影响将非常非常的大。 调用格式: close close 7.        查看数据相关信息 Rows-查看数据行数 调用格式:numrows=rows Cols——查看数据列数 调用格式:numcols=cols Attr——查看数据属性 调用格式:attribute=attr

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值