asp 与 database (3)
5.4? XML技術報表打印方案
隨著Internet的迅速發展和廣泛普及,XML的出現體現出了它的適用性和重要性。XML是由W3C定義的一種標記語言,由于XML是沒有版權限制的,這樣用戶可以建立屬于自己的一套軟件而無須支付任何費用。利用ASP結合XML技術,可以實現對XML數據的報表打印操作。其原理是:通過XML強大的自定義功能,用戶可以很方便地自定義出所需要的數據結構,然后在服務器端進行動態編碼,通過Web服務器將數據發送到客戶端,在客戶端進行格式解析后,再根據服務器端定義的打印格式,從客戶端直接控制打印機打印出所需要的報表。
5.4.1? 打印XML數據報表
XML的出現推動了Web的發展。在XML文檔中用戶可以自己定義標記,從而明確表達出數據之間的結構關系。在一些數據量不是很大的情況下,可以使用XML文檔作為存儲數據的容器,因為相對于訪問數據庫而言,訪問XML文檔的速度比較快。在ASP應用程序中,可以訪問XML文檔中的數據,從而將其顯示到頁面中進行打印操作。
1.方案分析
XML具有靈活的語法和擴展性,極大地強化了保存數據和處理數據的能力。
XML文檔中的標記是由用戶自己定義的,瀏覽器是不能識別的,這就使得XML文檔的數據和顯示格式是分離的。在ASP中,通過DOM技術可以訪問XML文檔中的數據,然后將其內容顯示到ASP頁面中,再應用打印技術打印此XML數據報表。
打印XML數據報表的流程圖,如圖5.28所示。
圖5.28? 打印XML數據報表流程圖
2.實施過程
? 實例位置:光盤"mr"5"5.4"5.4.1
XML在處理數據的方面應用很廣泛,在ASP中通過使用Microsoft XML類庫,可以訪問和操控XML文檔中的數據,從而實現對數據的有效操作。下面以網上企業辦公自動化管理系統為例,介紹如何將存儲在XML文檔中的員工工資信息讀取到ASP頁面并進行打印操作。運行效果如圖5.29所示。
圖5.29? 打印XML數據報表
在運行本例程之前,需要建立有效的XML文檔,代碼如下:
例程5-16? 代碼位置:光盤"mr"5"5.4"5.4.1"payfor.xml
<?xml version="1.0" encoding="gb2312"?>
<Records>
?? <Record>
?? ??? <num>001</num>
?????? <Name>楊麗麗</Name>
?????? <age>31</age>
?????? <department>研發部</department>
?????? <payfor>5500</payfor>
?????? <other>1000</other>
?? </Record>
?? <Record>
?? ??? <num>002</num>
?????? <Name>劉圓圓</Name>
?????? <age>28</age>
?????? <department>銷售部</department>
?????? <payfor>4600</payfor>
?????? <other>592</other>
?? </Record>
?? <Record>
?? ??? <num>003</num>
?????? <Name>李方方</Name>
?????? <age>25</age>
?????? <department>廣告部</department>
?????? <payfor>4050</payfor>
?????? <other>976</other>
?? </Record>
?? <Record>
?? ??? <num>004</num>
?????? <Name>李明明</Name>
?????? <age>29</age>
?????? <department>采購部</department>
?????? <payfor>4650</payfor>
?????? <other>1050</other>
?? </Record>
</Records>
在員工工資查看程序處理頁面中,首先創建Document對象實例,然后設置該對象的async屬性值為false(即不允許異步下載),并調用Document對象的Load方法加載指定的XML文檔,再調用Document對象的getElementsByTagName方法以及childNodes屬性讀取XML文檔中的數據。代碼如下:
例程5-17? 代碼位置:光盤"mr"5"5.4"5.4.1"index.asp
<%
?? Set xmlDoc=Server.CreateObject("Microsoft.XMLDOM")
?? Set xml_Record=Server.CreateObject("Microsoft.XMLDOM")
?? Set xml_child=Server.CreateObject("Microsoft.XMLDOM")
?? xmlDoc.async=False
?? xmlDoc.Load(Server.MapPath("payfor.xml"))
?? If xmlDoc.parseError.errorCode <> 0 Then
?? ? Response.Write("<tr><td colspan='6'>出現異常錯誤!</td></tr>")??? ?
?? Else
調用Document對象的getElementsByTagName方法返回指定名稱的元素集合,使用集合的length屬性獲取到元素的總數,再應用for…to循環語句讀取元素中各節點的內容。
?? ? Set xml_Record=xmlDoc.getElementsByTagName("Record")
?? ? record_num=xml_Record.length
?? ? For i=0 to (record_num-1)
?? ? Set xml_child=xml_Record.item(i)
? %>
<tr>
? <td height="22" align="center" valign="middle" bgcolor="#FFFFFF"><%=xml_child.childNodes(0).text%></td>
? <td height="22" align="center" valign="middle" bgcolor="#FFFFFF"><%=xml_child.childNodes(1).text%></td>
? <td height="22" align="center" valign="middle" bgcolor="#FFFFFF"><%=xml_child.childNodes(2).text%></td>
? <td height="22" align="center" valign="middle" bgcolor="#FFFFFF"><%=xml_child.childNodes(3).text%></td>
? <td height="22" align="center" valign="middle" bgcolor="#FFFFFF"><%=xml_child.childNodes(4).text%></td>
? <td align="center" valign="middle" bgcolor="#FFFFFF"><%=xml_child.childNodes(5).text%></td>
</tr>
<%Next
? End If
%>
將XML文檔中的數據信息顯示到ASP頁面后,就可以應用WebBrowse組件對頁面中的報表信息進行打印操作了。代碼如下:
例程5-18? 代碼位置:光盤"mr"5"5.4"5.4.1"index.asp
<style type="text/css">
@media print{
.Noprint{display:none /*應用該樣式的對象在實際打印時將不可見*/
}
</style>
<object id=WebBrowser classid=ClSID:8856F961-340A-11D0-A96B-00C04Fd705A2 width="0" height="0"></object>
<a href="#" οnclick="document.all.WebBrowser.Execwb(8,1)" class="Noprint">頁面屬性</a> <a href="#" οnclick="document.all.WebBrowser.Execwb(7,1)" class="Noprint">打印預覽</a> <a href="#" οnclick="document.all.WebBrowser.Execwb(6,1)" class="Noprint">打印</a>
?? 注意:在打印時,通過頁面設置可以設置打印時的邊距。
3.補充說明
在實際應用中,有時需要將數據庫中的數據導出到XML文檔中,再進行下一步的操作(如打印XML數據庫報表、查詢XML數據等)。
通過創建XML文檔對象,并設置對象的相關屬性和調用相關方法,可以實現將數據庫中的數據寫入到指定XML文檔的功能,代碼如下:
<%
If Not Isempty(Request("sure")) Then
'將數據庫中的數據寫入到XML文檔中
Set rs = Server.CreateObject("ADODB.RecordSet")
sqlstr = "SELECT * FROM tb_user"???
rs.Open sqlstr,conn,1,1
If rs.Eof Then
? Response.Write("<script language='javascript'>alert('數據庫中暫無記錄,請添加記錄后再嘗試運行本程序!');window.location.href='index.asp';</script>")
? Response.End()
Else???????
? Dim objXMLDOM, objRootNode, objNode
? Set objXMLDOM = Server.CreateObject("MSXML2.DOMDocument") '創建XML文檔對象
? Set objRootNode = objXMLDOM.createElement("xml") '創建根節點??
? objXMLDOM.documentElement = objRootNode
? Do While Not rs.Eof??????
?? ??? Set objRowNode = objXMLDOM.createElement("row") '創建父節點
?? ??? Set objNode = objXMLDOM.createElement("UserName") '創建子節點
?? ??? objNode.text = rs("UserName")
?? ??? objRowNode.appendChild(objNode)
?? ??? Set objNode = objXMLDOM.createElement("UserPassword") '創建子節點
?? ??? objNode.text = rs("Upwd")???????????
?? ??? objRowNode.appendChild(objNode)?????????????????
?? ??? Set objNode = objXMLDOM.createElement("UserTel")???? '創建子節點??????
?? ??? objNode.text = rs("Utel")???????????
?? ??? objRowNode.appendChild(objNode)?????????????????
?? ??? objRootNode.appendChild(objRowNode)???????
?? ??? rs.MoveNext
? loop????????????????
objXMLDOM.Save Server.MapPath("MyXMLDoc.xml")
Response.Write("<script language='javascript'>alert('將數據庫中的數據成功寫入到XML文檔中!');window.location.href='index.asp';</script>")
? Set objNode = Nothing????????????
? Set objRowNode = Nothing????????
? Set objRootNode = Nothing????
End If???
rs.Close???
Set rs = Nothing
End If
%>
5.4.2? 分頁報表打印
在一般情況下,顯示數據的頁面都會提供分頁程序,以方便用戶查看數據信息。在ASP應用程序中,可以使用JavaScript腳本語言來操作XML文檔中存儲的數據,并將信息進行分頁顯示。
1.方案分析
在使用XML文檔作為存儲數據的容器時,根據實際情況,對顯示的數據可以進行分頁控制。應用JavaScript腳本語言可以創建XML的Document對象,并使用Document對象的相關屬性和方法,讀取XML文檔中各節點包含的數據,同時還可以對數據進行分頁控制,然后在ASP頁面中通過CSS樣式來規范讀取到的XML數據的顯示格式,最后應用打印技術按照顯示的分頁效果打印XML數據報表。
分頁報表打印的流程圖,如圖5.30所示。
圖5.30? 分頁報表打印的流程圖
2.實施過程
? 實例位置:光盤"mr"5"5.4"5.4.2
使用JavaScript腳本語言可以操縱XML文檔中的數據,并可以將獲取到的數據進行分頁處理。在ASP頁面中,應用CSS樣式可以定義XML數據的顯示格式。下面以校園管理系統的檔案管理模塊為例,介紹應用JavaScript腳本語言將讀取到的XML數據進行分頁顯示,并對顯示在頁面中XML數據報表進行打印。運行效果如圖5.31所示。
圖5.31? 分頁報表打印
在運行本例程之前,需要建立有效的XML文檔,代碼如下:
例程5-19 代碼位置:光盤"mr"5"5.4"5.4.2"resume.xml
<?xml version="1.0" encoding="gb2312"?>
<Persons>
?? <Person>
?????? <Name>張三</Name>
?????? <Sex>男</Sex>
?????? <Grand>本科</Grand>
?????? <Tel>139565580</Tel>
?????? <Email>1@1.com</Email>
?????? <Like>計算機、英語</Like>
?? </Person>
?? <Person>
?????? <Name>李四</Name>
?????? <Sex>男</Sex>
?????? <Grand>本科</Grand>
?????? <Tel>133884580</Tel>
?????? <Email>2@1.com</Email>
?????? <Like>計算機、運動</Like>
?? </Person>
?? <Person>
?????? <Name>王元元</Name>
?????? <Sex>女</Sex>
?????? <Grand>專科</Grand>
?????? <Tel>135899680</Tel>
?????? <Email>3@1.com</Email>
?????? <Like>日語、英語</Like>
?? </Person>
?? <Person>
?????? <Name>趙明明</Name>
?????? <Sex>女</Sex>
?????? <Grand>本科</Grand>
?????? <Tel>139258880</Tel>
?????? <Email>4@1.com</Email>
?????? <Like>繪畫、英語</Like>
?? </Person>
</Persons>
在檔案信息列表查看頁面中,用戶可以通過單擊“前一頁”或“后一頁”超鏈接,進行分頁查看信息的操作,也可以通過選擇下拉列表框中的頁碼來分頁查看數據信息。在此頁面中,提供了“直接打印”、“頁面屬性”、“打印預覽”和“打印”4個關于打印技術的超鏈接,用戶可以根據實際需要進行相應的操作。
在程序處理頁面編寫的JavaScript腳本中,首先創建XML的Document對象實例,調用對象的load方法加載指定的XML文檔;然后獲取XML文檔中指定元素的個數,以及元素中包含節點的數目,根據所設置的初始值,計算顯示的頁碼總數;再定義執行翻頁操作的相關函數,并在定義的顯示XML文檔內容的函數中包含顯示分頁狀態的函數;最后調用顯示XML文檔內容的函數,實現分頁顯示XML數據報表的功能。代碼如下:
例程5-20 代碼位置:光盤"mr"5"5.4"5.4.2"index.asp
<script language="javascript">
var pagenum=2; //每頁顯示的記錄數
var page=0;?
var BodyHTML="";
var xmlDoc=new ActiveXObject("Microsoft.XMLDOM");
var mode="Person";
創建Document對象實例后,加載指定的XML文檔。
xmlDoc.async=false;
xmlDoc.load("resume.xml");
header="<table align='center' width='500' cellspaceing='1' cellpadding='2' border='1' bgcolor='#FFFFEE'><caption>職工檔案登記表</caption><tr align='center' class='title' bgcolor='#C1E6DB'><td>姓名</td><td>性別</td><td>學歷</td><td>電話</td><td>Email</td><td>愛好</td></tr>";
獲取XML文檔中的記錄條數,以及記錄包含的字段數,并計算顯示的總頁碼數。
recordNum=xmlDoc.getElementsByTagName(mode).length;
column=xmlDoc.getElementsByTagName(mode).item(0).childNodes;
colNum=column.length;
//計算總頁數
pagesNumber=Math.ceil(recordNum/pagenum)-1;
自定義顯示“前一頁”超鏈接的函數。
function Up_Page(page)
{
thePage="<font class='input'>前一頁</font>"
if(page+1 > 1) thePage="<a class='input' href='#' οnclick='JavaScript:return UpPageGo()'>前一頁</a>";
return thePage;
}
function UpPageGo()
{
if(page > 0) page--;
showContent();
BodyHTML="";
}
自定義顯示“后一頁”超鏈接的函數。
function Next_Page(page)
{
thePage="<font class='input'>后一頁</font>"
if(page < pagesNumber) thePage="<a class='input' href='#' οnclick='JavaScript:return NextPageGo()'>后一頁</a>";
return thePage;
}
function NextPageGo()
{
if(page < pagesNumber) page++;
showContent();
BodyTex="";
}
自定義顯示當前頁碼的函數。
function currentPage()//顯示當前頁碼
{
var str;
str="<font class='input'>當前是第"+(page+1)+"頁</font>";
return str;
}
自定義顯示總頁碼的函數。
function totalPage()//顯示總頁碼
{
var str;
str="<font class='input'>共有"+(pagesNumber+1)+"頁</font>";
return str;
}
自定義顯示“分頁狀態條”的函數。
function pageBar(page)//顯示分頁狀態條
{
var str;
str="<br><center class='Noprint'>"+Up_Page(page)+" "+Next_Page(page)+" "+currentPage()+" "+totalPage()+selectPage()+"</center>";
return str;
}
自定義自動轉換顯示頁的函數。
function changePage(tpage)
{
page=tpage;
if(page >= 0) page--;
if(page < pagesNumber) page++;
showContent();
BodyHTML="";
}
自定義具體顯示頁碼功能的下拉列表框函數。
function selectPage()
{
var sp;
sp="<select name='sel_page' onChange='javascript:changePage(this.options[this.selectedIndex].value)'>";
sp=sp+"<option value=''></option>";
for(t=0;t<=pagesNumber;t++)
{
? sp=sp+"<option value='"+t+"'>"+(t+1)+"</option>";
}
sp=sp+"</select>";
return sp;
}
自定義顯示XML文檔內容的函數。
function showContent()//將XML中的數據顯示到頁面中
{
if(!page) page=0;
n=page*pagenum;
endNum=(page+1)*pagenum;
if(endNum > recordNum) endNum=recordNum;
BodyHTML=header+BodyHTML;
for(;n<endNum;n++)
{
? kn=n+1;
? BodyHTML=BodyHTML+"<tr>";
? for(mNum=0;mNum<=colNum-1;mNum++)
? {
??? mName=column.item(mNum).tagName;
?? BodyHTML=BodyHTML+("<td>"+xmlDoc.getElementsByTagName(mName).item(n).text+"</td>");
? }
? BodyHTML=BodyHTML+"</tr>";
}
document.all.showXML.innerHTML=BodyHTML+"</table>"+pageBar(page);
BodyHTML="";
}
調用自定義的showContent()函數,將XML文檔中的數據信息顯示到頁面中指定的DIV標記中。
if(recordNum==0)
{
? document.Write("沒有可以顯示的數據!");
}
else
{
? showContent();
}
</script>
將XML文檔中的內容顯示到頁面后,可以調用WebBrowser組件對報表進行打印,代碼如下:
例程5-21 代碼位置:光盤"mr"5"5.4"5.4.2"index.asp
<div id="showXML"></div>
<p class="Noprint">
<object id=WebBrowser classid=ClSID:8856F961-340A-11D0-A96B-00C04Fd705A2 width="0" height="0"></object>
<a href="#" onClick="document.all.WebBrowser.Execwb(6,6)">直接打印</a> <a href="#" onClick="document.all.WebBrowser.Execwb(8,1)">頁面屬性</a> <a href="#" onClick="document.all.WebBrowser.Execwb(7,1)">打印預覽</a> <a href="#" onClick="document.all.WebBrowser.Execwb(6,1)">打印</a>
</p>
在頁面中應用的CSS樣式定義如下:
例程5-22 代碼位置:光盤"mr"5"5.4"5.4.2"Include"css.css
body,td{font-size:9pt}
A:link{color:#0000FF; text-decoration:none;}
A:visited{color:#0000FF; text-decoration:none;}
A:active{color:#3333ff; text-decoration:none;}
A:hover{color:#FF0000; text-decoration:none;}
td{font-size:9pt; line-height:150%}
.title{font-size:10.8pt; font-weight:bold}
.alert{font-size:9pt; color:#990000; font-weight:bold}
.input{font-size:9pt}
3.補充說明
除了使用JavaScript腳本語言對XML文檔中的數據進行分頁操作,在ASP中也可以將XML數據分頁顯示到網頁中。具體實現步驟如下:
(1)創建一個XML的FreeThreadedXMLDOM對象,并加載指定的XML文檔,然后選取相關節點,代碼如下:
<%
Set newXML=Server.CreateObject("Microsoft.FreeThreadedXMLDOM")
newXML.load(server. mappath("content.xml"))
Set newobj=newXML.documentElement.selectSingleNode("newxml")
%>
(2)通過以下代碼實現對XML數據進行分頁顯示,代碼如下:
<%
PageSize =5
'設置每頁顯示5條留言信息
newNum =newobj.childNodes.length-1
PageN=newNum"PageSize+1
'算出總頁數
PNo=request.querystring("PageNo")
if PNo="" then
'確定每一頁顯示最新的留言
PNo=PageN
end if
Ends=PNo*PageSize-1
'獲得起始節點
Strs=(PNo-1)*PageSize
'獲得結束節點
if Strs<0 then
Strs=0
end if
if Ends>newNum then
Strs=Strs-(Ends-newNum)
Ends=newNum
end if
if Strs<0 then
Strs=0
end if
while Strs<=Ends
'從結束節點到起始節點之間讀取節點數據
title=newobj.childNodes.item(Strs).childNodes.item(0).text
content = newobj.childNodes.item(Strs).childNodes.item(1).text
'取得留言內容
content = replace(content,chr(13),"<br>")
'應用replace函數替代回車符
content = replace(content,chr(32)," ")
'應用replace函數替代空格符
%>
<tr>
<td ><div align="center" class="STYLE2"><%=title%></div></td>
<td class="STYLE2"><div align="center"><%=content%></div></td>
</tr>
<%
Strs=Strs+1
wend
set newXML=nothing
%> ?
</table><br>共有<<%=PageN%>>頁
<%
'分頁
if cint(PNo)<>1 then
response.write "<a href='index.asp?PageNo="&(PNo-1)&"'>上一頁</a> "
end if
if cint(PNo)<>PageN then???????
response.write "<a href='index.asp?PageNo="&(PNo+1)&"'>下一頁</a>"
end if
%>
5.4.3? XSL瀏覽報表打印
XSL語言可以用于轉換XML文檔,也可以格式化XML文檔。應用XSL語言可以定義XML文檔的顯示格式,即將XML文檔轉換成能被瀏覽器識別的HTML文件;應用XSL語言還可以向輸出文件中添加新的元素、重新排列數據以及決定哪些元素顯示哪些元素不顯示等。
根據實際需要,可以通過XSL格式化XML文檔,并使數據信息以一定的格式顯示到ASP頁面中,然后對報表數據執行打印操作。
1.方案分析
使用XSL語言可以靈活、快速地定義出XML文檔的顯示格式,使格式化后的XML文檔數據以清晰的結構顯示在用戶面前。在ASP程序中,可以應用XSL瀏覽XML數據報表,并進行打印操作。
首先,用戶需要建立有效的.xml文件和.xsl文件,然后在ASP程序中創建XML的DOMDocument對象實例,應用該對象的相關方法加載建立好的兩個文件,并應用.xsl文件來格式化.xml文件,這樣XML文檔中的數據就能夠以.xsl文件規定的格式進行顯示了,再應用相關的打印技術打印顯示在ASP頁面中的數據報表。
XSL瀏覽報表打印的流程圖,如圖5.32所示。
圖5.32? XSL瀏覽報表打印流程圖
2.實施過程
? 實例位置:光盤"mr"5"5.4"5.4.3
在實際應用中,不僅可以通過CSS樣式來定義XML文檔的顯示格式,還可以應用XSL語言來轉換或格式化XML文檔,使瀏覽器可以識別XML文檔中的數據結構,從而使數據以指定的格式顯示在頁面中。下面以企業績效管理系統的員工考勤模塊為例,介紹如何使用XSL格式化XML文檔,并將XML文檔中的數據以分頁的形式顯示在頁面中,然后打印顯示的報表。運行效果如圖5.33所示。
圖5.33? XSL瀏覽報表打印
在運行本例程之前,需要建立有效的XML文檔,代碼如下:
例程5-23? 代碼位置:光盤"mr"5"5.4"5.4.3"emp_work.xml
<?xml version="1.0" encoding="gb2312"?>
<Persons>
?? <Person>
?? ??? <num>001</num>
?????? <date>2007年9月</date>
?????? <Name>張三</Name>
?????? <department>研發部</department>
?????? <count>10</count>
?????? <day>1</day>
?? </Person>
?? <Person>
?? ??? <num>002</num>
?????? <date>2007年9月</date>
?????? <Name>李四</Name>
?????? <department>銷售部</department>
?????? <count>2</count>
?????? <day>0</day>
?? </Person>
下面定義了兩個<Person2>的標記,作為分頁的標識。
?? <Person2>
?? ??? <num>003</num>
?????? <date>2007年9月</date>
?????? <Name>楊林林</Name>
?????? <department>企劃部</department>
?????? <count>0</count>
?????? <day>2</day>
?? </Person2>
?? <Person2>
?? ??? <num>004</num>
?????? <date>2007年9月</date>
?????? <Name>孫圓圓</Name>
?????? <department>廣告部</department>
?????? <count>1</count>
?????? <day>0</day>
?? </Person2>
</Persons>
建立了有效的XML文檔后,為此XML文檔建立.xsl文件,在.xsl文件中使用表格來規定數據的顯示格式。代碼如下:
例程5-24? 代碼位置:光盤"mr"5"5.4"5.4.3"emp_work.xsl
<?xml version="1.0" encoding="gb2312"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:template match="/Persons">
首先在<p>標記中建立表格,此表格的作用是使XML文檔中<Person>標記內的數據顯示在指定的單元格中。
<p><table align="center" width="500" cellpadding="2" cellspacing="1" border="0" bgcolor="#666600" class="table_style">
<caption align="center">員工考勤記錄表</caption>
? <tr align="center" class="title" bgcolor="#e5e5e5">
??? <td width="25"><xsl:text disable-output-escaping="yes"></xsl:text></td>
?? <td>序號</td>
?? <td>日期</td>
?? <td>姓名</td>
?? <td>所屬部門</td>
?? <td>早退遲到次數</td>
?? <td>缺席天數</td>
? </tr>
? <xsl:for-each select="Person">
? <tr bgcolor="#ffffff">
??? <td align="right"><xsl:value-of select="position()"/></td>
?? <td style="color:#990000" align="center"><xsl:value-of select="num"/></td>
?? <td style="color:#990000" align="center"><xsl:value-of select="date"/></td>
?? <td style="color:#990000" align="center"><xsl:value-of select="Name"/></td>
?? <td style="color:#990000" align="center"><xsl:value-of select="department"/></td>
?? <td style="color:#990000" align="center"><xsl:value-of select="count"/></td>
?? <td style="color:#990000" align="center"><xsl:value-of select="day"/></td>
? </tr>
? </xsl:for-each>
</table></p>
再次在<p>標記中建立表格,此表格的作用是使XML文檔中<Person2>標記內的數據顯示在指定的單元格中。
<p><table align="center" width="500" cellpadding="2" cellspacing="1" border="0" bgcolor="#666600" class="table_style">
? <tr align="center" class="title" bgcolor="#e5e5e5">
??? <td width="25"><xsl:text disable-output-escaping="yes"></xsl:text></td>
?? <td>序號</td>
?? <td>日期</td>
?? <td>姓名</td>
?? <td>所屬部門</td>
?? <td>早退遲到次數</td>
?? <td>缺席天數</td>
? </tr>
? <xsl:for-each select="Person2">
? <tr bgcolor="#ffffff">
??? <td align="right"><xsl:value-of select="position()"/></td>
?? <td style="color:#990000" align="center"><xsl:value-of select="num"/></td>
?? <td style="color:#990000" align="center"><xsl:value-of select="date"/></td>
?? <td style="color:#990000" align="center"><xsl:value-of select="Name"/></td>
?? <td style="color:#990000" align="center"><xsl:value-of select="department"/></td>
?? <td style="color:#990000" align="center"><xsl:value-of select="count"/></td>
?? <td style="color:#990000" align="center"><xsl:value-of select="day"/></td>
? </tr>
? </xsl:for-each>
</table></p>
</xsl:template>
</xsl:stylesheet>
建立了有效的.xml文件和.xsl文件后,自定義一個函數,此函數的作用是創建XML的DOMDocument對象實例,應用對象的load方法分別加載.xml文件和.xsl文件,然后調用DOMDocument對象的TransformNode方法使用.xsl文件格式化.xml文件。代碼如下:
例程5-25? 代碼位置:光盤"mr"5"5.4"5.4.3"Include"formatxml.asp
<%
Function FormatXML(XMLfile,XSLfile)
Dim objXML,objXSL
strXMLfile=Server.MapPath(XMLfile)
strXSLfile=Server.MapPath(XSLfile)
Set objXML=Server.CreateObject("MSXML2.DOMDocument")
Set objXSL=Server.CreateObject("MSXML2.DOMDocument")
objXML.async=false
If objXML.Load(strXMLfile) Then
? objXSL.async=false
? objXSL.ValidateonParse=false
? If objXSL.Load(strXSLfile) Then
??? On Error Resume Next
?? FormatXML=objXML.transformNode(objXSL)'很重要
?? If objXSL.parseError.errorCode <> 0 Then
?? ? Response.Write("<br><hr>")
?? ? Response.Write("Error Code: "&objXSL.parseError.errorCode)
?? ? Response.Write("<br>Error Reason: "&objXSL.parseError.reason)
?? ? Response.Write("<br>Error Line: "&objXSL.parseError.line)
?? ? FormatXML="<span class=""alert"">格式化XML文件錯誤!</span>"
?? End IF
? Else
?? ? Response.Write("<br><hr>")
?? ? Response.Write("Error Code: "&objXSL.parseError.errorCode)
?? ? Response.Write("<br>Error Reason: "&objXSL.parseError.reason)
?? ? Response.Write("<br>Error Line: "&objXSL.parseError.line)
?? ? FormatXML="<span class=""alert"">格式化XML文件錯誤!</span>"
? End If
Else
?? ? Response.Write("<br><hr>")
?? ? Response.Write("Error Code: "&objXSL.parseError.errorCode)
?? ? Response.Write("<br>Error Reason: "&objXSL.parseError.reason)
?? ? Response.Write("<br>Error Line: "&objXSL.parseError.line)
?? ? FormatXML="<span class=""alert"">格式化XML文件錯誤!</span>"
End If
Set objXML=Nothing
Set objXSL=Nothing
End Function
%>
做好前期準備之后,在首頁面中包含Include文件夾中的formatxml.asp文件,調用自定義的FormatXML(XMLfile,XSLfile)函數顯示XML文檔中的數據信息,并引用WebBrowser組件打印頁面中的XML數據報表。代碼如下:
例程5-26? 代碼位置:光盤"mr"5"5.4"5.4.3"index.asp
<style media="print">
.Noprint{display:none;}
</style>
<!--#include file="Include/formatxml.asp"-->
<%=FormatXML("emp_work.xml","emp_work.xsl")%>
<object id=WebBrowser classid=ClSID:8856F961-340A-11D0-A96B-00C04Fd705A2 width="0" height="0">
</object>
<p> <a href="#" οnclick="document.all.WebBrowser.Execwb(8,1)" class="Noprint">頁面屬性</a> <a href="#" οnclick="document.all.WebBrowser.Execwb(7,1)" class="Noprint">打印預覽</a> <a href="#" οnclick="document.all.WebBrowser.Execwb(6,1)" class="Noprint">打印</a> </div></p>
3.補充說明
除了調用XML對象的相關方法使用.xsl文件格式化.xml文件,還可以在XML文檔中直接鏈接指定的.xsl文件,從而實現轉換XML文檔格式的效果。代碼如下:
XSL樣式表文件xmlf.xsl。
<?xml version="1.0" encoding="gb2312"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/TR/WD-xsl">
<xsl:template match="/">
?? <html>
?? <body>
?? <center>
?? <table width="300" height="30" border="10" cellspacing="0" cellpadding="0">
?? ? <tr align="center">
?????? <td>書名</td>
?????? <td>頁碼</td>
?? ? </tr>
<xsl:for-each select="PUBLICATION/BOOK">
?? ? <tr align="center" height="30">
?????? <td><xsl:value-of select="TITLE"/></td>
?????? <td><xsl:value-of select="PAGES"/></td>
?? ? </tr>
</xsl:for-each>?????
?? </table>
?? </center>
?? </body>
?? </html>
</xsl:template>
</xsl:stylesheet>
XML文件index.xml。
<?xml version="1.0" encoding="gb2312"?>
<?xml-stylesheet type="text/xsl" href="xmlf.xsl"?>
<PUBLICATION>
?? <BOOK>
?????? <TITLE>ASP技術</TITLE>
?????? <PAGES>760</PAGES>
?? </BOOK>
?? <BOOK>
?????? <TITLE>SQL技術</TITLE>
?????? <PAGES>520</PAGES>
?? </BOOK>
</PUBLICATION>
在XML文檔中如果鏈接了多個XSL樣式表,瀏覽器將使用第一個XSL樣式表而忽略其他XSL樣式表;如果同時鏈接一個CSS樣式表文件和一個XSL樣式表,瀏覽器將只使用XSL樣式表。
5.5? 其他報表打印方案
除了以上介紹的Excel報表打印方案、XML技術報表打印方案和Crystal Report水晶報表打印方案,在ASP程序中還可以應用其他技術來實現報表打印的功能。本節將介紹Word報表打印、自定義ActiveX組件打印Access報表、圖形報表打印以及套打報表。
5.5.1? Word報表打印
Microsoft Word是微軟公司推出的Microsoft Office辦公軟件中的一個組件,它是一個功能強大的文字處理軟件,可以進行文字輸入、編輯、排版和打印操作等。在ASP程序中,可以創建Word的相關對象將網頁中的內容導入到Word中,也可以調用Word中的數據報表,然后進行報表打印。
1.方案分析
在Web服務器上安裝了Microsoft Word軟件后,ASP就可以創建Word的相關對象,從而應用該對象的屬性和方法對網頁中的數據或者Word文檔中的數據進行操作了。
網頁上顯示的數據一般都是從數據庫中讀取出來的,創建Word的Application對象可以將網頁中具有一定顯示格式的數據導入到Word文檔中,然后進行報表打印的操作。
在一些實際工作中,用戶可能會應用Word文檔來存儲一些數據報表(如:制作商務表格等),并進行排版工作等,為了方便用戶查看Word文檔中的內容,ASP可以編寫動態代碼打開指定的Word文檔,然后再執行打印命令。
Word報表打印的流程圖,如圖5.34所示。
圖5.34? Word報表打印的流程圖
2.實施過程
Microsoft Word在文字編輯、打印方面的應用很廣泛,ASP通過調用Word的相關對象可以訪問Word文檔中的數據內容。下面介紹兩種在ASP程序中通過Word進行報表打印的方法,分別是將網頁內容導入到Word和打印Word報表。
l????????? 方法一? 將網頁內容導入到Word
? 實例位置:光盤"mr"5"5.5"5.5.1"01
在本章的5.2節中介紹了Excel報表打印方案,在ASP中不僅可以將網頁中的內容保存到Excel中,還可以將網頁中指定的內容導入到Word中。下面以企業內部管理系統的庫存管理模塊為例,介紹將網頁中顯示的數據導入到Word,然后再進行打印操作的過程。運行結果如圖5.35所示。
圖5.35? 將網頁內容導入到Word
在庫存商品信息查看頁面中,可以瀏覽到從庫存商品信息表中讀取到的數據信息。代碼如下:
例程5-27? 代碼位置:光盤"mr"5"5.5"5.5.1"01"index.asp
<%
??? Set rs=Server.CreateObject("ADODB.Recordset")
?? sqlstr="select * from tb_store"
?? rs.open sqlstr,conn,1,1
?? do while not rs.eof
%>
<tr align="center">
? <td height="26"><%=rs("Gname")%></td>
? <td height="26"><%=rs("Gunit")%></td>
? <td width="93" height="26"><%=rs("Gstd")%></td>
? <td width="167" height="26"> <%=rs("Gprovide")%></td>
? <td width="85" height="26"> <%=rs("Gconect")%></td>
</tr>
<%
??? rs.movenext
?? loop
?? rs.close
?? Set rs=Nothing
%>
<div align="center"><a href="vbscript:" onClick="vbscript:SaveDoc()">Word報表打印</a></div>
單擊頁面中的“Word報表打印”超鏈接,就可以將表格中的數據寫入到Word文檔中,同時生成的臨時Word文檔會自動打開。運行效果如圖5.36所示。
圖5.36? 保存網頁內容的Word文檔
在程序處理頁面的客戶端VBScript腳本中,自定義一個子過程用于將網頁中的表格數據寫入到Word文檔中。具體的實現步驟如下:
(1)創建一個Word的Application對象實例,再調用Word的Documents集合的Add方法建立一個新的文檔,并將頁面中的表格數據存儲在一個數組中。
(2)將表格的標題寫入到Word中,并增添一個空行。
(3)在Word文檔中建立一個表格,并將數組中的內容填寫在該表格中。
(4)保存新建立的Word文檔。
代碼如下:
例程5-28? 代碼位置:光盤"mr"5"5.5"5.5.1"01"index.asp
<script language="vbscript">
Sub SaveDoc
Dim Table1
Set table1=document.all.data
row=Table1.rows.length
set wdapp=CreateObject("Word.Application")? //創建Word應用程序
wdapp.visible=true
set wddoc=wdapp.documents.add? //添加新的文檔
colnum =Table1.rows(1).cells.length
將頁面中表格的內容存放在數組中。
reDim theArray(colnum,row)
For i=0 to row-1
?? For j=0 to colnum-1
?????? thearray(j+1,i+1)=table1.rows(i).cells(j).innerHTML
?? next
next
intNumrows=row
將表格的標題信息寫入到Word文檔中,并設置其字體樣式。
wdapp.application.activedocument.paragraphs.add.range.insertbefore("庫存商品記錄表")
set rngpara=wdapp.application.activedocument.paragraphs.add.range
with rngpara
.paragraphformat.alignment=1
.font.name="arial"
.font.size=9
End with
Set rngPara=wdapp.Application.ActiveDocument.Paragraphs(1).Range
With rngPara
.Bold=True
.ParagraphFormat.Alignment=1
.Font.Name="Arial"
.Font.Size=12
End With
在文檔的指定段落的區域內,添加一表格,將數組中的數據寫入到表格中。
set rngcurrent=wdapp.application.activedocument.paragraphs(3).range
set tabCurent=wdapp.application.activedocument.tables.add(rngcurrent,intnumrows,colnum)
For i=1 To row
?? For j=1 to colnum??? ?????? wdapp.application.activeDocument.Tables(1).Rows(i).Cells(j).Range.InsertAfter theArray(j,i)? ?????? wdapp.application.activeDocument.Tables(1).Rows(i).Cells(j).Range.paragraphFormat.alignment=1
?? next
next
保存建立的Word文檔。
wdapp.application.activeDocument.SaveAs "NewDoc.doc",0,false,"",true,"",false,false,false,false,false
End sub
</script>
將網頁中的內容導入到Word文檔后,用戶可以根據實際需要再對數據報表進行編輯操作,然后打印報表。
l????????? 方法二? 打印Word報表
? 實例位置:光盤"mr"5"5.5"5.5.1"02
在ASP中不僅可以調用Word的相關對象將網頁中的內容導入到Word,還可以打開Word文檔直接進行打印操作。下面以企業營銷管理系統的銷售報表模塊為例,介紹如何打開指定的Word報表文件,并進行打印操作。運行效果如圖5.37所示。
圖5.37? 打印Word報表
在銷售報表查看和打印頁面中,首先選擇相關的Word文檔,然后單擊“Word報表打印”按鈕,這時選擇的Word文檔將自動打開,并處于打印的狀態中。
為了便于讀者理解,下面以列表的形式給出銷售報表查看頁面index.asp中所涉及到的表單及表單元素,如表5.8所示。
表5.8?????????? ??????銷售報表查看頁面index.asp中的表單及表單元素
| 名稱 | 元素類型 | 重要屬性 | 含義 |
| form | form | action="" method="post" enctype="multipart/form-data" | 選擇需要打印的Word文檔 |
| file1 | input | type="file" id="file1" size="20" | 確定Word文檔的路徑 |
| | input | type="submit" id="print" onClick="openWord(file1.value)" | Excel文件路徑 |
在頁面中單擊“Word報表打印”按鈕后的運行效果如圖5.38所示。
圖5.38? 打開指定的Word文檔
在程序處理頁面中的客戶端VBScript腳本中,自定義一個子過程用于打開并打印指定的Word文檔。在該子過程中,首先創建Word的Application對象實例,再調用Documents集合的Open方法打開Word文檔,最后調用Printout方法打印Word文檔。代碼如下:
例程5-29? 代碼位置:光盤"mr"5"5.5"5.5.1"02"index.asp
<script language="vbscript">
Sub openWord(filename)?
Set wrd=CreateObject("word.Application")
wrd.visible=true
wrd.Documents.Open(filename)
wrd.Application.Printout()
wrd=null
End Sub
</script>
3.補充說明
Microsoft Word是常用的文字編輯工具,使用Word可以進行記錄會議內容、起草協議等工作。為了用戶操作方便,在ASP中可以調用Word直接打印頁面中的數據信息,即將用戶在表單中輸入的信息直接封裝到Word中,然后再進行打印操作。如圖5.39所示。
圖5.39? 調用Word進行Web打印
自定義一個VBScript腳本子過程,在該子過程中,首先獲取頁面中表單的數據信息,然后在客戶端VBScript腳本中創建Word的Document對象,應用對象的相應方法將頁面內容裝入到Word文檔中,并直接進行打印操作。代碼如下:
<script language="vbscript">
Sub word_print
Set objWordDoc=CreateObject("Word.Document")
title=document.all.form1.txt_title.value&CHR(10)
nowtime=document.all.form1.txt_time.value&CHR(10)
table=title&nowtime&document.all.form1.txt_content.value
objWordDoc.Application.ActiveDocument.Paragraphs.Add.Range.InsertBefore(table)
objWordDoc.Application.ActiveDocument.Paragraphs.Add.Range.InsertBefore("")
Set rngPara=objworddoc.Application.ActiveDocument.Paragraphs(1).Range
objworddoc.Application.ActiveDocument.SaveAs "如何調用Word進行Web打印"
objWordDoc.application.printout()
End Sub
</script>
5.5.2? 打印Access報表
在Microsoft Access數據庫中,用戶可以根據數據表創建Access報表,從而快速、準確地掌握數據信息。在ASP應用程序中,通過調用Access的相關對象可以打印指定的Access報表。
1.方案分析
Microsoft Access數據庫不僅具有強大的數據存儲功能,還擁有完善的報表功能,它支持子報、表、多欄報表、圖形報表等多種復雜元素。在ASP中,調用Access的Application對象,可以開發直接打印Access報表的程序。
打印Access報表的流程圖,如圖5.40所示。
圖5.40? 打印Access報表流程圖
2.實施過程
? 實例位置:光盤"mr"5"5.5"5.5.2
在ASP應用程序中直接打印Access報表,可以方便用戶對數據庫的一些相關操作。下面以新聞網站為例,介紹ASP調用Access的Application對象實現打印Access數據庫中新聞報表的功能。運行效果如圖5.41所示。
圖5.41? 打印Access報表
在Microsoft Access數據庫中,可以使用向導創建報表。下面介紹具體創建報表的步驟:
(1)打開Access數據庫,單擊左側面板中的“報表”對象,在右側選擇“使用向導創建報表”的命令,打開“報表向導”窗口,在此窗口中選擇表及字段名稱,如圖5.42所示。
圖5.42? 選擇表及指定字段
(2)單擊“下一步”按鈕,可在打開的窗口中“確定是否添加分組類別”。再單擊“下一步”按鈕,在打開的窗口中可以確定記錄所用的排序次序,如圖5.43所示。
圖5.43? 確定記錄所用的排序次序
(3)單擊兩次“下一步”按鈕,分別確定報表的布局方式和所用樣式。然后在下一個窗口中為報表指定標題,這里輸入“打印新聞報表”,如圖5.44所示。最后,單擊“完成”按鈕成功創建Access報表。
圖5.44? 定義報表標題
創建Access報表后,在ASP頁面中建立表單。在表單中,用戶通過選擇所要操作的數據庫文件以及輸入Access數據庫中報表的名稱,來觸發打印Access報表的程序。下面給出表單中關鍵元素的代碼:
例程5-30? 代碼位置:光盤"mr"5"5.5"5.5.2"index.asp
<form action="" method="post" name="form1" onSubmit="PrintReport()">
Access數據庫路徑:<input name="txt_db" type="file" id="txt_db">
Access數據庫中報表名稱:<input name="txt_report" type="text" id="txt_report" title="Access數據庫中報表名稱">
<input type="submit" name="Submit" value="打印Access報表"? onClick="return Mycheck(this.form)">
<input type="reset" name="Submit2" value="重置表單內容"></td>
</form>
在ASP頁面中,自定義一個客戶端VBScript腳本的sub過程。在該過程中,首先創建Access的Application對象實例,然后調用對象的OpenCurrentDatabase方法連接所指定的Access數據庫,再調用OpenReport方法打印指定名稱的Access報表,最后給出打印成功的提示信息。代碼如下:
例程5-31? 代碼位置:光盤"mr"5"5.5"5.5.2"index.asp
<script language="vbscript">
sub PrintReport()
Set pr = CreateObject("Access.Application")
pr.OpenCurrentDatabase document.all.txt_db.value
pr.DoCmd.OpenReport document.all.txt_report.value
pr.CloseCurrentDatabase
Set pr = Nothing
Msgbox "恭喜您,打印Access報表成功!"
end sub
</script>
3.補充說明
編寫ASP應用程序所采用的VBScript語言是一種簡單的腳本語言,只能實現有限的功能。而使用一些開發工具編寫的組件,可以調用各種系統資源,實現較為復雜的功能。微軟公司的ASP具有良好的可擴展性,而擴展ASP最有效的途徑就是開發自定義的DLL組件,使用DLL組件的優勢如下:
(1)實現代碼封裝技術。在開發程序時,ASP代碼是嵌入在HTML語言中的,如果頁面設計有變動,設計人員很難對嵌有代碼的頁面做改動,如果將代碼封裝在組件中,既方便設計人員進行頁面布局,又增強程序的可讀性。
(2)起到保護頁面源碼的作用。ASP程序是無須編譯的,即它是以源碼的形式存儲在服務器上的,源程序很容易被他人獲取。而組件是經過編譯的,服務器端只有一個編譯的DLL文件,保證源代碼不被泄漏。
(3)編譯好的組件可以重復使用,節約開發時間。
(4)用戶將程序開發代碼封裝在組件中,可以申請知識產權保護其利益。
讀者可以嘗試使用Visual Basic軟件來自定義ActiveX組件,然后調用該組件來實現特定的功能模塊。
5.5.3? 圖形報表打印
圖形報表是一種非常直觀的數據表現形式,它是通過柱狀圖、餅型圖、折線圖等多種圖表格式來統計數據的報表形式。在ASP中,可以利用圖形報表來統計和處理數據,并進行打印操作等。
1.方案分析
在實際工作中,為了使用戶能夠以直觀的方式查看到數據報表的內在結構,并能夠明確報表所表達的含義,可以使用圖形報表作為報表的表現形式。在ASP應用程序中,可以調用Visual Basic軟件中內置的MSChart組件(MSChart組件是Microsoft提供的ActiveX組件之一,可以使用圖形方式顯示數據的圖表),將數據庫中的數據信息以圖形的方式展現在頁面中,從而實現圖形報表打印的功能。
圖形報表打印的流程圖,如圖5.45所示。
圖5.45? 圖形報表打印流程圖
2.實施過程
? 實例位置:光盤"mr"5"5.5"5.5.3
在ASP中可以引用外部組件,使用柱狀圖、折線圖等形式將統計數據展現在網頁中。下面以網站的銷售管理模塊為例,介紹在選擇查詢條件并對商品銷售情況進行統計核實時,利用圖形報表顯示查詢結果的過程。運行效果如圖5.46所示。
圖5.46? 圖形報表打印
在商品銷售統計頁面中,提供了按月、按年或者按照具體日期進行銷售統計的功能。在默認情況下,是針對所有商品進行銷售統計的,用戶也可以輸入具體的商品編號只針對一種商品進行銷售統計。
在程序處理頁面中,首先根據選擇的統計類型,確定對應的SQL查詢語句;然后使用<object>標記嵌入MSChart組件;再通過JavaScript腳本語言設定MSChart組件的各屬性值,使查詢到的結果以圖形方式顯示在頁面中。代碼如下:
例程5-32? 代碼位置:光盤"mr"5"5.5"5.5.3"index.asp
<%
If Not Isempty(Request("btt_sell")) Then
? txt_Gnum=Request.Form("txt_Gnum")
? txt_type=Request.Form("txt_type")
? txt_amount=Request.Form("txt_amount")
? txt_start=Request.Form("txt_start")
? txt_end=Request.Form("txt_end")
如果用戶在商品編號文本框中輸入內容,則判斷此商品編號是否存在。
? If txt_Gnum<>"" Then
??? Set rs=Server.CreateObject("ADODB.Recordset")
??? sqlstr="select Gnum from tb_sell where Gnum='"&txt_Gnum&"'"
??? rs.open sqlstr,conn,1,1
??? If rs.eof or rs.bof Then
????? Response.Write("<script language='javascript'>alert('此商品沒有銷售信息,請重新輸入!');history.back();</script>")??? ?
??? End If
?? rs.close
?? Set rs=Nothing
? End If
根據用戶選擇的統計類型,確定SQL查詢語句。獲取到的變量txt_type的值如果值為1,則按照商品的銷售月份進行分組查詢,并統計指定月份的銷售金額;如果值為2,則按照商品的銷售年份進行分組查詢,并統計指定年份的銷售金額。
? Select case txt_type
? case "1"
??? fig="個月"
??? If txt_Gnum<>"" Then
????? sqlstr="select * from (select top "&txt_amount&" sum(Smoney) as totals,Month(Sdate) as IssueDate from tb_sell where Gnum='"&txt_Gnum&"' group by Month(Sdate) order by Month(Sdate) desc) as a order by a.IssueDate"
??? Else
????? sqlstr="select * from (select top "&txt_amount&" sum(Smoney) as totals,Month(Sdate) as IssueDate from tb_sell group by Month(Sdate) order by Month(Sdate) desc) as a order by a.IssueDate"
??? End If
? case "2"
??? fig="年"
??? If txt_Gnum<>"" Then
????? sqlstr="select * from (select top "&txt_amount&" sum(Smoney) as totals,Year(Sdate) as IssueDate from tb_sell where Gnum='"&txt_Gnum&"' group by Year(Sdate) order by Year(Sdate) desc) as a order by a.IssueDate"
??? Else
????? sqlstr="select * from (select top "&txt_amount&" sum(Smoney) as totals,Year(Sdate) as IssueDate from tb_sell group by Year(Sdate) order by Year(Sdate) desc) as a order by a.IssueDate"
??? End If
? End Select
通過日期區間統計商品銷售情況。
? If txt_start<>"" and txt_end<>"" Then
??? If txt_Gnum<>"" Then
?? ? sqlstr="select * from (select sum(Smoney) as totals,Sdate as IssueDate from tb_sell where Gnum='"&txt_Gnum&"' and Sdate between #"&txt_start&"# and #"&txt_end&"# group by Sdate order by Sdate desc) as a order by a.IssueDate"
?? Else
????? sqlstr="select * from (select sum(Smoney) as totals,Sdate as IssueDate from tb_sell where Sdate between #"&txt_start&"# and #"&txt_end&"# group by Sdate order by Sdate desc) as a order by a.IssueDate"
?? End If
? End If
? Set rs=Server.CreateObject("ADODB.Recordset")
? rs.open sqlstr,conn,1,1
? counts=rs.recordcount
%>
使用<object>標記引用MSChart組件,并在JavaScript腳本中定義組件的各屬性值,從而將查詢到的結果以圖表的形式顯示在頁面表格中。
<table width="600" border="1" align="center" cellpadding="0" cellspacing="0"?? bordercolor="#FFFFFF" bordercolorlight="#9CA6C6" bordercolordark="#CCE3FF">
? <tr bgcolor="#FF9933">
??? <td height="10" colspan="6" class="word_white"> </td>
? </tr>
? <tr align="center" bgcolor="#C8E3FF">
??? <td height="14">
<%
if counts>0 then
sum=0
%>
<object classid="clsid:3A2B370C-BA0A-11D1-B137-0000F8753F5D" name="chart" width="100%" height="300">
?? <%'定義對象,該對象命名為chart%>
</object>
<% for i=1 to counts
? If txt_amount="" Then txt_amount=1
? If fig="" Then fig="企業"
%>
<script language="javascript">
chart.chartType=1;
chart.ColumnCount=1;???
chart.TitleText="最近 "+<%=txt_amount%>+"<%=fig%>"+" 商品銷售情況顯示圖表 : ";??
chart.rowcount=<%=counts%>;???????????
chart.row=<%=i%>;??????????????????????
chart.rowlabel="<%=rs("IssueDate")%>(月/年/日期)";
chart.Data=<%=rs("totals")%>;?????????
chart.Footnote="注:縱坐標為銷售金額";
</script>
<%sum=sum+rs("totals")
? rs.movenext?????
? next???????????
%>
</td>
? </tr>
? <tr>
??? <td height="30" colspan="6"> 最近<%Response.Write(txt_amount&fig)%>的銷售金額為 <%=sum%>元 </td>
? </tr>
</table>
<br>
引用WebBrowser組件,打印頁面中的圖形報表。
<object id=WebBrowser classid=ClSID:8856F961-340A-11D0-A96B-00C04Fd705A2 width="0" height="0"></object>
<div align="center"><a href="#" onClick="document.all.WebBrowser.Execwb(8,1)" class="Noprint">頁面屬性</a> <a href="#" onClick="document.all.WebBrowser.Execwb(7,1)" class="Noprint">打印預覽</a> <a href="#" onClick="document.all.WebBrowser.Execwb(6,1)" class="Noprint">打印</a></div>
<%End IF
End IF
%>
3.補充說明
在網絡應用程序中,經常會遇到由瀏覽者自己輸入日期的情況,如注冊頁面中的生日、商品銷售中售貨日期等,如果輸入的日期格式不正確,數據則不能正確保存。為了方便用戶操作及保證輸入日期格式的正確性,可以在需要輸入日期的位置加入Visual Basic的日期拾取組件(Microsoft Date and Time Picker),由用戶自己選擇日期。如圖5.47所示。
圖5.47? 調用Microsoft Date and Time Picker組件
DateTimePicker組件是Microsoft提供的ActiveX組件之一,可以返回格式化的日期字段,使得選擇日期很容易。在使用DateTimePicker組件之前,應注冊MSCOMCT2.OCX文件并安裝Visual Basic軟件。調用日歷組件及獲取選擇的日期的關鍵代碼如下:
<form name="myform" method="post" action="">
? <tr bgcolor="#FFFFFF">
??? <td width="107" height="22" align="right">您選擇的日期為:</td>
??? <td width="286" height="22"><input name="Date_time" type="text" id="Date_time" onMouseOver="myevent()" onFocus="myevent()"></td>
? </tr>?
</form>
? <tr bgcolor="#FFFFFF">
??? <td height="22" align="right">選擇日期:</td>
??? <td height="22">
<script language="javascript">
function myevent(){
var date=new Date(mydate.value) ;
year=date.getUTCFullYear();
month=date.getUTCMonth()+1;
day=date.getUTCDate();
myform.Date_time.value=year+"-"+month+"-"+day;
//myform.submit();
}
</script>
<object classid="clsid:20DD1B9E-87C4-11D1-8BE3-0000F8754DA1" name="mydate" width="110" height="20">
? <param name="format" value=1>
</object></td>
? </tr>
5.5.4? 套打報表
套打是現在應用較為廣范的一種打印方式,它是一種在印制有憑證、賬簿、報表格式、證書等紙張上進行打印的打印方式,以這種方式進行打印時,無須打印表格的表格線及其他固定的格式內容,有利于加快打印速度、節約打印耗材、延長打印機的使用壽命等。
1.方案分析
在一些工作領域中(例如通信、郵政、商務洽談、財務等),為了加快工作效率,并為用戶提供方便,工作人員通常會將一些常用的業務事項或流程、憑證等事先打印出來,再由用戶按照上面的提示進行填寫、核實等。
使用ASP開發動態網站時,可以在頁面中設計出所需要的格式,然后從數據庫中讀取所需要的數據,并將數據放置在頁面指定的位置,從而實現套打報表的功能。套打報表的流程圖,如圖5.48所示。
圖5.48? 套打報表流程圖
2.實施過程
? 實例位置:光盤"mr"5"5.5"5.5.4
在生活和工作過程中,當人們郵寄一些快件時,首先要在快遞單上填寫郵件的基本信息。在開發動態網站時,為了滿足用戶需求,可以提供實時打印快遞單的功能。下面以電子商務網站的訂單信息管理模塊為例,介紹套打快遞單的實現過程。運行效果如圖5.49所示。
圖5.49? 套打快遞單
在套打快遞單頁面中,用戶可以通過填寫寄件人或收件人的姓名來查詢快遞單的詳細信息。程序處理頁面根據獲取到的表單數據,確定查詢的SQL語句,然后將從數據庫中讀取到的數據添加到頁面中指定位置,并應用打印技術執行套打操作。代碼如下:
例程5-33? 代碼位置:光盤"mr"5"5.5"5.5.4"index.asp
<%
Dim SendTime,SendAddress,ReceiveAddress,SendTel,Sender,ReceiveTel,Receiver,ThingsName,PayMoney,ThingsNumber,ThingsWeight,ThingsPrice
sql_type=Trim(Request.Form("type"))
txt_name=Trim(Request.Form("txt_name"))
Set rs=Server.CreateObject("ADODB.Recordset")
sqlstr="select * from tb_info where 1=1"
根據用戶填寫的查詢條件,確定SQL查詢語句。
If txt_name<>"" then
?? select case sql_type
?? case "0"
?? sqlstr=sqlstr&" and sender='"&txt_name&"'"
?? case "1"
?? sqlstr=sqlstr&" and receiver='"&txt_name&"'"
?? end select
End If
rs.open sqlstr,conn,1,1
If rs.eof or rs.bof Then
? ? Response.Write("<p align=center>暫時不能提供任何信息!</p>")
?? Response.End
End if
對查詢到信息的進行分頁處理。
rs.pagesize=1? '定義每頁顯示的記錄數
pages=clng(Request("pages"))? '獲得當前頁數
If pages<1 Then pages=1
If pages>rs.recordcount Then pages=rs.recordcount
showpage rs,pages? '執行分頁子程序showpage?????
Sub showpage(rs,pages) ?'分頁子程序showpage(rs,pages)
rs.absolutepage=pages?? '指定指針所在的當前位置
For i=1 to rs.pagesize? '循環顯示記錄集中的記錄SendTime=Now()
SendAddress=rs("sendAddress")
ReceiveAddress=rs("ReceiveAddress")
SendTel=rs("SendTel")
Sender=rs("Sender")
ReceiveTel=rs("ReceiveTel")
Receiver=rs("Receiver")
ThingsName=rs("ThingsName")
PayMoney=rs("PayMoney")
ThingsNumber=rs("ThingsNumber")
ThingsWeight=rs("ThingsWeight")
ThingsPrice=rs("ThingsPrice")
SendTime=rs("sendTime")
%>
…略,表格信息
<%
? rs.movenext
? If rs.eof Then Exit For
? Next
? End Sub
%>
????? <br>
????? <table width="450" height="25"? border="0" align="center" cellpadding="-2" cellspacing="0" class="print">
??????? <tr valign="middle" bgcolor="#FFFFFF">
????????? <%If Not (rs.eof and rs.bof) Then%>
????????? <td width="280" height="28"><% if pages<>1 then %>
??????????? <a href=?pages=1>第一頁</a> <a href=?pages=<%=(pages-1)%>>上一頁</a>
??????????? <%end if
????????????? if pages<>rs.pagecount then %>
??????????? <a href=?pages=<%=(pages+1)%>>下一頁</a> <a href=?pages=<%=rs.pagecount%>>最后一頁</a>
??????????? <%end if%></td>
????????? <%If not(rs.Eof and rs.Bof) Then%>
????????? <td width="220" height="28" align="right" class="word_grey">[<%=pages%>/<%=rs.PageCount%>] 每頁<%=rs.PageSize%>條 共<%=rs.RecordCount%>條信息</td>
??? <%End If
?? ? rs.close
?? ? Set rs=Nothing
?? ?End If
?? %>
??????? </tr>
??????? <tr bgcolor="#000000">
????????? <td colspan="2" valign="bottom" height="1"></td>
??????? </tr>
????? </table>
????? <br>
應用WebBrowser組件進行套打報表的操作。
<object id=WebBrowser classid=ClSID:8856F961-340A-11D0-A96B-00C04Fd705A2 width="0" height="0"> </object>
????? <div align="center"><a href="#" onClick="document.all.WebBrowser.Execwb(8,1)" class="Noprint">頁面設置</a> <a href="#" onClick="document.all.WebBrowser.Execwb(7,1)" class="Noprint">打印預覽</a> <a href="#" onClick="document.all.WebBrowser.Execwb(6,1)" class="Noprint">打印</a></div>
3.補充說明
使用WebBrowser組件執行打印報表操作時,根據報表的實際結構,用戶可以通過“頁面設置”來定義打印選項,從而使打印能夠順利進行。例如,當紙張縱向打印不適合報表的寬度時,可以調整為“橫向”打印;可以設置“頁邊距”,使報表在指定的紙張位置處進行打印;可以設置打印頁面的頁眉頁腳等。
“頁面設置”所包含的選項,如圖5.50所示。
圖5.50? 頁面設置窗口
?
在網絡信息時代,人們對網絡信息系統的依賴正逐漸增加,保證網絡安全變得愈加重要。網絡安全的本質就是需要保證網絡上的信息安全,主要包括信息的保密性、完整性、可用性和準確性等。
網站屬于計算機網絡中的一部分,它用來向用戶提供服務及相關信息。因此網絡中的安全隱患都會映射到它的身上。如何更有效地保護重要的數據信息,提高網站的安全性已經成為Web程序開發中必須考慮和解決的一個重要問題。
本章將詳細介紹在網絡開發中的一些安全問題,及針對這些安全問題實施的各種策略和解決方案。讀者通過本章的學習,可采用這些技術加強網站的安全,使網站的運行得到可靠的保障。
6.3? 用戶權限方案
為了提高網站的安全性,經常會為網站中的用戶分配不同的權限,這樣不僅可以有效的管理用戶,而且可以在很大程度上提高網站的安全性。本節將對在開發和運營一個網站時,如何為不同級別的用戶分配不同的權限做了具體、全面的分析。
6.3.1? 默認用戶權限
在一些企業管理系統中,經常會有多位管理人員對系統中的內部資源進行管理。為了提高系統的安全性,大多數情況下,系統中只有一位具有全局權限的管理員,并且該管理員具有添加普通管理員的權限,在添加這些普通管理員時,可以為新的管理員進行權限的分配。
1.方案分析
? 實例位置:光盤"mr"6"6.3"6.3.1
進入用戶登錄頁面后,首先在登錄表單中添加用戶的登錄信息,然后提交表單,這樣該用戶的所有登錄信息將被提交的用戶登錄信息處理頁。在用戶信息處理頁中,首先判斷用戶的用戶名和密碼是否正確,如果錯誤則返回登錄頁面,否則繼續判斷該用戶所屬級別,并根據用戶級別為其分配不同的權限。例如,人力資源管理系統中的用戶可以分為系統用戶(或全局用戶)、讀寫用戶和只讀用戶,系統用戶具有全局管理的權限,讀寫用戶具有對常規數據進行修改、刪除等權限,而只讀用戶只具有最基本的瀏覽權限。默認用戶權限方案分析的示意圖,如圖6.16所示。
圖6.16? 默認用戶權限的示意圖
2.實施過程
? 實例位置:光盤"mr"6"6.3"6.3.1
運行網上企業辦公自動化系統的用戶信息修改頁面,如圖6.17所示,單擊該頁面中的用戶“權限”下拉列表框,可以發現該系統中用戶權限主要分為系統、讀寫和只讀3種。當對用戶權限進行修改時首先從用戶權限下拉列表中為用戶指定權限,然后單擊“修改”按鈕即可實現用戶權限的修改。
圖6.17? 用戶權限修改頁面
在網上企業辦公自動化系統管理頁面中單擊“人力資源”超鏈接,即可進入用戶信息管理頁面。在該頁面中可以添加新用戶信息、修改個人信息、修改其他用戶信息、刪除用戶信息等操作。用戶信息添加頁面主要用于向數據庫中添加新的用戶信息。運行結果如圖6.18所示。
圖6.18? 用戶信息添加頁面
制作添加用戶信息的表單頁面,該頁面主要用于系統用戶添加用戶信息。在添加用戶信息時,將應用JavaScript腳本驗證輸入信息是否合法。添加用戶信息表單頁面所涉及的重要表單元素如表6.1所示。
表6.1????????????? ????添加用戶信息頁面所涉及的重要表單元素
| 名稱 | 元素類型 | 含義 | 重要屬性 |
| form1 | form | 表單 | <form ACTION="personnel_add.asp" METHOD="POST" name="form1"> |
| username | text | 用戶名 | <input name="username" type="text" class="Sytle_text" id="username"> |
| branch | select | 部門 | <select name="branch" id="select4"> <option value="開發部" selected>開發部</option> <option value="人事部">人事部</option> <option value="銷售部">銷售部</option> </select> |
| name | text | 姓名 | <input name="name" type="text" class="Sytle_text" id="name"> |
| sex | select | 性別 | <select name="sex" id="sex"> <option value="男" selected>男</option><option value="女">女</option> </select> |
| purview | select | 權限 | <select name="purview" id="select"> <option value="系統" selected>系統</option> <option value="讀寫">讀寫</option><option value="只讀">只讀</option> </select> |
| Button | Button | “提交”按鈕 | <input name="Button" type="button" class="Style_button" value="提交" onClick="Mycheck()"> |
| Submit2 | reset | “重置”按鈕 | <input name="Submit2" type="reset" class="Style_button" value="重置"> |
| myclose | button | “關閉”按鈕 | <input name="myclose" type="button" class="Style_button" id="myclose" value="關閉" onClick="javascrip:window.close()"> |
在實現用戶信息添加時,首先判斷客戶端輸入的用戶信息是否合法,然后在將合法的用戶信息保存到用戶信息表中,通過以下代碼實現用戶信息的添加,代碼如下:
例程6-15? 代碼位置:光盤"mr"6"6.3"6.3.2"personnel_add.asp
<!--#include file="../Connections/conn.asp" -->
<%
if request.Form("username")<>""then
'檢測用戶名是否存在
?? Set rs= Server.CreateObject("ADODB.Recordset")
?? sql="SELECT UserName FROM dbo.Tab_User WHERE UserName='" &Request.Form("UserName")&"'"
?? rs.open sql,conn,1,3
?? if rs.eof then
'保存員工信息
?????? username=request.Form("username")
?????? cname=request.Form("name")
?????? branch=request.Form("branch")
?????? PWD=request.Form("PWD")
?????? job=request.Form("job")
?????? tel=request.Form("tel")
?????? purview=request.Form("purview")
?????? sex=request.Form("sex")
?????? email=request.Form("email")
?????? address=request.Form("address")
?????? Ins="Insert into dbo.Tab_User (username,name,branch,PWD,job,tel,purview,sex,"&_
?????? "email,address) values('"&username&"','"&cname&"','"&branch&"','"&PWD&"','"&_
?????? job&"','"&tel&"','"&purview&"','"&sex&"','"&email&"','"&address&"')"
?????? conn.execute(Ins)
%>
?????? <script language="javascript">
?????? alert("員工信息添加成功!");
?????? opener.parent.location.reload();
?????? window.close();
?????? </script>
?? <%
Else
%>
?????? <script language="javascript">
?????? alert("該員工信息已經存在!");
?????? </script>
?? <%
?? end if
end if
%>
<script language="javascript">
function Mycheck()
{
if (form1.username.value=="")
{ alert("請輸入員工姓名!");form1.username.focus();return;}
if (form1.PWD.value=="")
{ alert("請輸入密碼!");form1.PWD.focus();return;}
if (form1.tel.value=="")
{
alert("請輸入員工的聯系電話!");
form1.tel.focus();return;
}
if(form1.email.value!="" && (form1.email.value.indexOf('@',0)==-1|| form1.email.value.indexOf('.',0)==-1))
{alert("您輸入的E-mail地址不對!");form1.email.focus();return;}
if (form1.address.value=="")
{
alert("請輸入員工的住址!");
form1.address.focus();return;
}
form1.submit();}
</script>
用戶成功登錄后,首先判斷此用戶是否是系統用戶,如果該用戶是系統用戶,則可以通過“人力資源管理”模塊,進行“添加新用戶”、“修改個人信息”、“用戶信息修改”和“用戶信息刪除”操作(可以對所有用戶進行修改和刪除操作);否則只可以對用戶本身的密碼進行修改。用戶信息修改頁面的運行結果如圖6.19所示。
圖6.19? 用戶信息修改頁面
通過以下代碼實現用戶信息的修改,代碼如下:
例程6-16? 代碼位置:光盤"mr"6"6.3"6.3.2"personnel_modify.asp
<!--#include file="../Connections/conn.asp" -->
<%
'查詢員工信息
If Request.QueryString("ID")<>""then
session("ID")=Request.QueryString("ID")
end if
Set rs_personnel = Server.CreateObject("ADODB.Recordset")
sql_P="SELECT ID,UserName,name,PWD,purview,branch,job,sex,Email,Tel,Address"&_
" FROM dbo.Tab_User WHERE ID="&session("ID")&""
rs_personnel.open sql_p,conn,1,3
%>
<%
'修改員工信息
if request.Form("Name")<>"" then
?? cname=request.Form("name")
?? PWD=request.Form("PWD")
?? purview=request.Form("purview")
?? sex=request.Form("sex")
?? tel=request.Form("tel")
?? branch=request.Form("branch")
?? job=request.Form("job")
?? email=request.Form("email")
?? address=request.Form("address")
?? UP="Update dbo.Tab_User set name='"&cname&"',PWD='"&PWD&"',purview='"&_
?? purview&"',sex='"&sex&"',tel='"&tel&"',branch='"&branch&"',job='"&job&_
?? "',email='"&email&"',address='"&address&"' where ID='"&session("ID")&"'"
?? conn.execute(UP)
%>
?? <script language="javascript">
?? alert("數據修改成功!");
?? opener.parent.location.reload();
?? window.close();
?? </script>
<%
end if
%>
<script language="javascript">
function Mycheck()
{
if (form1.name.value=="")
{ alert("請輸入員工姓名!");form1.name.focus();return;}
if (form1.PWD.value=="")
{ alert("請輸入密碼!");form1.PWD.focus();return;}
if (form1.tel.value=="")
{
alert("請輸入員工的聯系電話!");
form1.tel.focus();return;
}
if(form1.email.value!="" && (form1.email.value.indexOf('@',0)==-1|| form1.email.value.indexOf('.',0)==-1))
{
alert("您輸入的E-mail地址不對!");
form1.email.focus();return;
}
if (form1.address.value=="")
{
alert("請輸入員工的住址!");
form1.address.focus();return;
}
form1.submit();}
</script>
通過以下代碼實現用戶信息的刪除,代碼如下:
例程6-17? 代碼位置:光盤"mr"6"6.3"6.3.2"personnel_del.asp
<!--#include file="../Connections/conn.asp" -->
<%
if request.Form("UserName")<>"" then
?? DEL="Delete From dbo.Tab_User where ID='"&session("ID")&"'"
?? conn.execute(Del)
%>
?? <script language="javascript">
?? alert("員工信息已經刪除!");
?? opener.location.reload();
?? window.close();
?? </script>
<%end if%>
<%
if Request.QueryString("ID")<>""then
?? session("ID")=Request.QueryString("ID")
end if
Set rs_personnel = Server.CreateObject("ADODB.Recordset")
sql_P="SELECT ID,UserName,Name,PWD,purview,branch,sex,Email,Tel,Address"&_
" FROM dbo.Tab_User WHERE ID="&session("ID")&""
rs_personnel.open sql_P,conn,1,3
%>
3.補充說明
為用戶分配默認的權限,即可在添加用戶信息時指定,也可以先注冊用戶信息,然后根據不同用戶的職能為其分配不同的權限。為了提高網站的安全性,在為用戶指定默認權限時,一定要根據用戶的職能權限進行的合理分配,否則一旦非法用戶登錄系統將會給整個系統造成極大的損失。
6.3.2? 簡單自定義用戶權限
簡單自定義權限是指在添加新管理員時,根據該管理員的管理職責而為其分配的權限。例如,在為系統添加數據錄入管理人員時,只需為其分配數據添加和數據刪除的權限即可,為了提高整個系統的安全性,不必為其過多的分配其他權限。下面將以辦公自化管理系統為例來講解簡單自定義用戶權限的具體實現過程。
1.方案分析
一個網站管理系統的后臺用戶主要分為兩種,一種是全局管理員,另一種是普通管理員。全局管理員具有整個后臺的全局管理權限,除了具有對后臺數據進行管理的所有權限外,還具有對普通管理員進行管理的權限;而普通管理員只具有對后臺數據進行添加、修改和刪除的權限以及對個人信息進行修改的權限。管理人員首先進入后臺登錄頁面,然后在登錄表單中輸入個人的登錄信息并提交表單,這樣該管理員的登錄信息將被提交到用戶信息驗證頁,如果用戶的個人信息填寫錯誤則返回到登錄頁,否則對用戶的級別進行判斷,并根據用戶的級別為其分配不同的權限。實現簡單自定義用戶權限的示意圖,如圖6.20所示。
圖6.20? 簡單自定義用戶權限的示意圖
2.實施過程
? 實例位置:光盤"mr"6"6.3"6.3.2
下面將以辦公自動化管理系統為例講解如何實現簡單自定義用戶權限。當超級用戶成功進入系統后,可以進行新用戶的添加,如圖6.21所示。首先在該頁面的用戶名和密碼的文本框中輸入合法的用戶名和密碼,然后從權限列表框中選擇要為該用戶分配的權限,最后單擊“提交”按鈕即可實現自定義權限的添加。
圖6.21? 添加超級用戶信息頁面
通過以下代碼實現數據庫的連接,代碼如下:
例程6-18? 代碼位置:光盤"mr"6"6.3"6.3.2"data"conn.asp
<%
set conn=server.CreateObject("Adodb.Connection")
Path="driver={SQL Server};server=.;uid=sa;pwd=;database=db_safe"
conn.open path
function HTMLcode(fString)
if not isnull(fString) then
??? fString = Replace(fString, CHR(13), "")
??? fString = Replace(fString, CHR(10) & CHR(10), "</P><P>")
??? fString = Replace(fString, CHR(10), "<BR>")
?? fString = Replace(fString, CHR(32), " ")
??? HTMLcode = fString
end if
end function
%>
在用戶管理模塊中單擊“用戶添加”超鏈接,即可進入到用戶添加頁面。用戶信息添加頁面主要用于向數據庫中添加新的用戶信息。其運行結果如圖6.22所示。
圖6.22? 用戶信息添加頁面的運行結果
制作添加用戶信息的表單頁面,該頁面主要用于收集超級用戶添加的用戶信息和驗證輸入信息是否合法。添加用戶信息表單頁面所涉及的重要表單元素如表6.2所示。
表6.2????????????????? 添加用戶信息頁面所涉及的重要表單元素
| 名稱 | 元素類型 | 含義 | 重要屬性 |
| form1 | form | 表單 | action="" method="post" name="form1" |
| username | text | 用戶名 | <input name="username" type="text" id="username" size="20"> |
| post | hidden | 隱藏域 | <input name="post" type="hidden" id="post" value="1"> |
| userpwd | password | 密碼 | <input name="userpwd" type="password" id="userpwd" size="20"> |
| menu1 | select | 文本域 | <select name="menu1" size="3" onChange="MM_jumpMenu('nei',this,0)"> <% set rs2=server.CreateObject("adodb.recordset") sql2="select * from renshi" rs2.open sql2,conn,1,1 if not rs2.eof then for i=1 to rs2.recordcount and not rs2.eof%>? <option value=nei.asp?id=<%=rs2("id")%>> <%=rs2("name")%></option> <% rs2.movenext if rs2.eof then exit for Next else response.Write("<option value='沒有用戶'>沒有用戶</option>")? end if????????? %></select> |
| Submit | Submit | “提交”按鈕 | <input type="submit" name="Submit" value="提交"> |
| Submit2 | reset | “重置”按鈕 | <input type="reset" name="Submit2" value="重置"> |
在實現用戶信息添加時,首先判斷客戶端輸入的用戶信息是否合法,然后在將合法的用戶信息保存到用戶信息表中,通過以下代碼實現用戶信息的添加,代碼如下:
例程6-19? 代碼位置:光盤"mr"6"6.3"6.3.2"adduser.asp
<!--#include file=data/conn.asp-->
<!--#include file=connfig.asp-->
<!--#include file=inc/yan.asp-->
<%
?? '驗證用戶身份
?? call case10
?? if request("post")=1 then
?? ? if request("username")="" or request("userpwd")="" then
?? response.Write("<script language=JavaScript>" & "alert('用戶名或者密碼不能為空!');" & "history.back()" & "</script>")
?? else
?? ?if request("user")=0 then
?????? ? call wr1
?????? else
?????? ?? call wr2
?????? end if
?? ? end if
?? end if
?? '添加普通用戶
?? function wr1
?? username=trim(replace(request("username"),"'",""))
?? userpwd=trim(replace(request("userpwd"),"'",""))
?? for i=1 to len(username)
?? ? user=mid(username,i,1)
?? ? if user="'" or user="%" or user="<" or user=">" or user="&" or user="|" then
?????? response.write "<script language=JavaScript>" & "alert('您的用戶名含有非法字符,請重新輸入!');" & "history.back()" & "</script>"
?????? response.end
?? ? end if
?? next
?? for i=1 to len(userpwd)
?? ? pass=mid(userpwd,i,1)
?? ? if pass="'" or pass="%" or pass="<" or pass=">" or pass="&" or pass="|" then
?????? ?response.write "<script language=JavaScript>" & "alert('您的密碼含有非法字符,請重新輸入!');" & "history.back()" & "</script>"
?????? ?response.end
?? ? end if
?? next
?? ???? '判斷用戶名是否已經存在
?????? ?set rs1=server.CreateObject("adodb.recordset")
?????? ?sql1 = "Select * From users Where username='"&request("username")&"'"
?????? ?rs1.open sql1,conn,1,1
?????? ?If not rs1.EOF Then
?????? ?response.Write("<script language=JavaScript>" & "alert('用戶名已經存在!');" & "window.location.href='adduser.asp';" & "</script>")
?????? ?response.End()
?????? ?end if
?????? ?rs1.close
?? '添加用戶權限
?? set rs=server.CreateObject("adodb.recordset")
?? sql="select * from users"
?? rs.open sql,conn,1,3
?? rs.addnew
?? rs("username")=request("username")
?? rs("userpwd")=request("userpwd")
?? rs("shenhe")=request("shenhe")
?? rs("huiyi")=request("huiyi")
?? rs("gonggong")=request("gonggong")
?? rs("geren")=request("geren")
?? rs("renshi")=request("renshi")
?? rs("name")=session("na")
?? rs("time")=now()
?? rs.update
?? rs.close
?? response.Write("<script language=JavaScript>" & "alert('添加成功!');" & "window.location.href='adduser.asp';" & "</script>")
?? response.End()
?? end function
?? ?'添加超級用戶
?? function wr2
?? username=trim(replace(request("username"),"'",""))
?? userpwd=trim(replace(request("userpwd"),"'",""))
?? for i=1 to len(username)
?? ? user=mid(username,i,1)
?? ? if user="'" or user="%" or user="<" or user=">" or user="&" or user="|" then
?????? response.write "<script language=JavaScript>" & "alert('您的用戶名含有非法字符,請重新輸入!');" & "history.back()" & "</script>"
?????? response.end
?? ? end if
?? next
?? for i=1 to len(userpwd)
?? ? pass=mid(userpwd,i,1)
?? ? if pass="'" or pass="%" or pass="<" or pass=">" or pass="&" or pass="|" then
?????? ?response.write "<script language=JavaScript>" & "alert('您的密碼含有非法字符,請重新輸入!');" & "history.back()" & "</script>"
?????? ?response.end
?? ? end if
?? next
?????? ?set rs1=server.CreateObject("adodb.recordset")
?????? ?sql1 = "Select * From users Where username='"&request("username")&"'"
?????? ?rs1.open sql1,conn,1,1
?????? ?If not rs1.EOF Then
?????? ?response.Write("<script language=JavaScript>" & "alert('用戶名已經存在!');" & "history.back()" & "</script>")
?????? ?end if
?????? ?rs1.close
?? set rs=server.CreateObject("adodb.recordset")
?? sql="select * from users"
?? rs.open sql,conn,1,3
?? rs.addnew
?? rs("username")=request("username")
?? rs("userpwd")=request("userpwd")
?? rs("name")=session("na")
?? rs("chaoji")=1
?? rs("time")=now()
?? rs.update
?? rs.close
?? response.Write("<script language=JavaScript>" & "alert('添加成功!');" & "history.back()" & "</script>")
?? end function
%>
在進行用戶登錄時,首先判斷此用戶是否是超級用戶,如果該用戶是超級用戶,則可以通過“用戶管理”模塊,進行“用戶添加”、“用戶修改”和“刪除”操作(可以對所有用戶進行修改和刪除操作);否則只可以對用戶本身的密碼進行修改。用戶信息修改頁面的運行結果如圖6.23所示。
圖6.23? 用戶信息修改頁面的運行結果
通過以下代碼實現用戶信息的修改,代碼如下:
例程6-20? 代碼位置:光盤"mr"6"6.3"6.3.2"adduser1.asp
<!--#include file=data/conn.asp-->
<!--#include file=connfig.asp-->
<!--#include file=inc/yan.asp-->
<%
call case10
?set rs2=server.CreateObject("adodb.recordset")
??? sql2="select * from users where id="&request("id")
??? rs2.open sql2,conn,1,1
if request("post")=1 then
? if request("username")="" or request("userpwd")="" then
response.Write("<script language=JavaScript>" & "alert('用戶名或者密碼不能為空!');" & "history.back()" & "</script>")
else
?if request("user")=0 then
????? call wr1
??? else
?????? call wr2
??? end if
? end if
end if
function wr1
if session("na")="" then
na=rs2("name")
else
na=session("na")
end if
username=trim(replace(request("username"),"'",""))
userpwd=trim(replace(request("userpwd"),"'",""))
for i=1 to len(username)
? user=mid(username,i,1)
? if user="'" or user="%" or user="<" or user=">" or user="&" or user="|" then
??? response.write "<script language=JavaScript>" & "alert('您的用戶名含有非法字符,請重新輸入!');" & "history.back()" & "</script>"
??? response.end
? end if
next
for i=1 to len(userpwd)
? pass=mid(userpwd,i,1)
? if pass="'" or pass="%" or pass="<" or pass=">" or pass="&" or pass="|" then
???? response.write "<script language=JavaScript>" & "alert('您的密碼含有非法字符,請重新輸入!');" & "history.back()" & "</script>"
???? response.end
? end if
next
set rs=server.CreateObject("adodb.recordset")
sql="select * from users where id="&session("id")
rs.open sql,conn,1,3
rs("username")=request("username")
rs("userpwd")=request("userpwd")
rs("shenhe")=request("shenhe")
rs("huiyi")=request("huiyi")
rs("gonggong")=request("gonggong")
rs("geren")=request("geren")
rs("renshi")=request("renshi")
rs("name")=na
rs("chaoji")=0
rs.update
rs.close
response.Write("<script language=JavaScript>" & "alert('修改成功!');" & "history.back()" & "</script>")
end function
?function wr2
?if session("na")="" then
na=rs2("name")
else
na=session("na")
end if
username=trim(replace(request("username"),"'",""))
userpwd=trim(replace(request("userpwd"),"'",""))
for i=1 to len(username)
? user=mid(username,i,1)
? if user="'" or user="%" or user="<" or user=">" or user="&" or user="|" then
??? response.write "<script language=JavaScript>" & "alert('您的用戶名含有非法字符,請重新輸入!');" & "history.back()" & "</script>"
??? response.end
? end if
next
for i=1 to len(userpwd)
? pass=mid(userpwd,i,1)
? if pass="'" or pass="%" or pass="<" or pass=">" or pass="&" or pass="|" then
???? response.write "<script language=JavaScript>" & "alert('您的密碼含有非法字符,請重新輸入!');" & "history.back()" & "</script>"
???? response.end
? end if
next
set rs=server.CreateObject("adodb.recordset")
sql="select * from users where id="&session("id")
rs.open sql,conn,1,3
rs("username")=request("username")
rs("userpwd")=request("userpwd")
rs("name")=na
rs("chaoji")=1
rs.update
rs.close
response.Write("<script language=JavaScript>" & "alert('修改成功!');" & "history.back()" & "</script>")
end function
%>
通過以下代碼實現用戶信息的刪除,代碼如下:
例程6-21? 代碼位置:光盤"mr"6"6.3"6.3.2"del.asp
<!--#include file=data/conn.asp-->
<!--#include file=connfig.asp-->
<!--#include file=inc/yan.asp-->
<%
?? '驗證用戶權限
?? call case10
?? if request("del")<>"" and ps("chaoji")=1 then
?? call del
?? end if
?? '刪除用戶
?? function del
?? sql2="delete from users where id="&request("del")
?? conn.Execute(sql2)
?? end function
%>
當登錄的用戶是普通用戶時,只可以對用戶本身的密碼進行修改。通過以下代碼實現普通用戶密碼的修改操作,代碼如下:
例程6-22? 代碼位置:光盤"mr"6"6.3"6.3.2"yonghugai.asp
<!--#include file=data/conn.asp-->
<!--#include file=connfig.asp-->
<%
if request("post")<>"" then
call write1
end if
function write1
if request("userpwd1")<>"" and request("userpwd2")<>"" then
if request("userpwd1")<>request("userpwd2") then
response.Write("<script language=javascript>alert('兩次輸入密碼不一致!!')</script>")
else
set rs=server.CreateObject("adodb.recordset")
sql="select * from users where username='"&session("admin_name")&"'"
rs.open sql,conn,1,3
rs("userpwd")=request("userpwd1")
rs.update
end if
else
response.Write("<script language=javascript>alert('密碼不能為空!')</script>")
end if
if request("qq")<>"" then
set rs1=server.CreateObject("adodb.recordset")
sql1="select * from renshi where name='"&rs("name")&"'"
rs1.open sql1,conn,1,3
rs1("tel")=request("tel")
rs1("age")=request("age")
rs1("email")=request("email")
rs1("address")=request("address")
rs1.update
rs1.close
end if
response.Redirect("chenggong.htm")
end function
set rs3=server.CreateObject("adodb.recordset")
sql3="select * from users where username='"&session("admin_name")&"'"
rs3.open sql3,conn,1,3
set rs4=server.CreateObject("adodb.recordset")
sql4="select * from renshi where name='"&rs3("name")&"'"
rs4.open sql4,conn,1,3
%>
3.補充說明
在實現簡單自定義用戶權限時,也可以將普通用戶權限和超級用戶權限的選項放在下拉列表中,并在Dreamweaver中插入兩個下拉列表框,同時將下拉列表的類型設置為“列表”類型,選擇“允許多選”前面的復選框,設置完成后將相關的權限信息輸入到下拉列表框中,此時可以按shift鍵進行用戶權限的多選操作,即實現與復選框同樣的功能。通過該方法同樣可以實現簡單自定義用戶權限的設置,運行結果如圖6.24所示。
圖6.24? 應用下拉列表實現簡單自定義用戶權限的設置
6.3.3? 復雜自定義用戶權限
在某些較大規模的管理系統中,為了有效合理的對系統信息進行管理,無論是全局管理員還是普通管理者的權限都是極其復雜的。那么如何在復雜的管理系統中定義及分配用戶的權限呢?下面將以企業進銷存管理系統為例來講解復雜自定義用戶權限的設計方案及具體實現過程。
1.方案分析
實現“復雜自定義用戶權限”與實現“簡單自定義用戶權限”的實現方案大體類似,區別是在為用戶指定權限時需要考慮更多的因素。管理人員首先進入后臺登錄頁面,然后在登錄表單中輸入個人的登錄信息并提交表單,這樣該管理員的登錄信息將被提交到用戶信息驗證頁,如果用戶的個人信息填寫錯誤則返回到登錄頁,否則可以對用戶的級別進行判斷,并根據用戶的級別為其分配不同的權限。實現復雜自定義用戶權限的示意圖,如圖6.25所示
圖6.25? 復雜自定義用戶權限的示意圖
2.實施過程
? 實例位置:光盤"mr"6"6.3"6.3.3
全局管理員成功登錄企業進銷存管理系統的后臺時,就可以進入該系統的“權限管理”模塊,如圖6.26所示。在“權限管理”模塊中列出了所有管理員的用戶名和該管理員的權限信息,如果預刪除某管理員,可以直接單擊該管理員所對應的“刪除”超鏈接即可。如果對某用戶的權限進行設置或重新分配時,可以單擊該管理員后的“權限設置”超鏈接進入權限設置頁面可以對該管理員的權限進行重新設定。
圖6.26? 復雜自定義用戶權限管理頁面
本系統后臺數據庫采用的是Access數據庫,系統數據庫名稱為db_database.mdb。數據庫db_database.mdb中包含兩張數據表:分別為tb_use(管理員信息表)和tb_purview(權限信息表)。下面將分別給出這兩個數據表的表結構。
(1)tb_use(管理員信息表)主要用于保存管理員的名稱及密碼信息,其表結構如表6.3所示。
表6.3?? ????????????????????????表tb_use的結構
| 字段名稱 | 數據類型 | 長度 | 默認值 | 描述 |
| id | 自動編號 | 管理員ID號 | ||
| use | 文本 | 50 | 管理員名稱 | |
| pwd | 文本 | 50 | 管理員密碼 |
(2)tb_purview(權限信息表)主要用于保存管理員的權限信息,其表結構如表6.4所示。
表6.4???????????????????????????? tb_purview表
| 字段名稱 | 數據類型 | 長度 | 默認值 | 描述 |
| id | 數字 | 長整型 | 0 | 管理員ID號 |
| purviewSet | 是/否 | 權限設置 | ||
| basicSet | 是/否 | 基本信息管理 | ||
| stockSet | 是/否 | 進貨管理 | ||
| sellSet | 是/否 | 銷售管理 | ||
| storageSet | 是/否 | 庫存管理 | ||
| querySet | 是/否 | 查詢統計 | ||
| reportSet | 是/否 | 報表管理 |
通過以下代碼實現數據庫的連接,代碼如下:
例程6-23? 代碼位置:光盤"mr"6"6.3"6.3.3"Conn"conn.asp
<%
Set conn=Server.CreateObject("ADODB.Connection")
sql="Provider=Microsoft.jet.oledb.4.0;data source="&Server.MapPath("database/db_database.mdb")
conn.open(sql)
%>
在權限管理的主頁中單擊“添加管理員信息”超鏈接,即可進入到添加管理員信息頁面。添加管理員信息頁面主要用于向數據庫中添加新的管理員。運行結果如圖6.27所示。
圖6.27? 添加管理員信息頁面的運行結果
制作添加管理員信息的表單頁面,該頁面主要用于收集管理員添加的管理員信息和驗證輸入信息是否合法。添加管理員信息表單頁面所涉及的重要表單元素如表6.5所示。
表6.5????????????????? 添加管理員信息頁面所涉及的重要表單元素
| 名稱 | 元素類型 | 含義 | 重要屬性 |
| form1 | form | 表單 | action="tjyg.asp" method="post" name="form1" |
| use | text | 管理員名稱 | <input name="use" type="text" id="use" size="19"> |
| pwd | password | 管理員密碼 | <input name="pwd" type="password" id="pwd" size="20"> |
| pwd1 | password | 確認密碼 | <input name="pwd1" type="password" id="pwd1" size="20"> |
| Img1 | Img | “保存”按鈕 | <img src="images/button2.gif" width="58" height="24" onClick="Mycheck1();"> |
| Img2 | img | “關閉”按鈕 | <img src="images/button3.gif" width="58" height="24" onClick="window.close();opener.location.reload();"> |
在實現管理員信息添加時,首先判斷客戶端輸入的管理員信息是否合法,然后在將合法的管理員信息保存到管理員信息表中,并同時級聯插入權限信息,級聯插入權限信息主要通過獲取Access數據庫中插入記錄的自動編號實現的。代碼如下:
例程6-24? 代碼位置:光盤"mr"6"6.3"6.3.3"tjyg.asp
<!--#include file="conn/conn.asp"-->
<%
function filter_Str(InString)
'***********************************
'功能:過濾輸入字符串中的危險符號
'調用方法:filter_Str("String")
'***********************************
?? NewStr=Replace(InString,"'","''")
?? NewStr=Replace(NewStr,"<","<")
?? NewStr=Replace(NewStr,">",">")
?? NewStr=Replace(NewStr,"chr(60)","<")
?? NewStr=Replace(NewStr,"chr(37)",">")
?? NewStr=Replace(NewStr,"""",""")
?? NewStr=Replace(NewStr,";",";;")
?? NewStr=Replace(NewStr,"--","-")
?? NewStr=Replace(NewStr,"/*"," ")
?? NewStr=Replace(NewStr,"%"," ")
?? filter_Str=NewStr
end function
if request.Form("use")<>"" then
?? use=filter_Str(request.Form("use"))
?? pwd=filter_Str(request.Form("pwd"))
?? '檢測輸入的管理員是否已存在
?? set rs=server.CreateObject("Adodb.recordset")
?? sql="select * from tb_use where use='"&use&"'"
?? rs.open sql,conn,1,3
?? if rs.eof and rs.bof then
?? '通過下面的程序代碼來保存用戶注冊信息
?? rs.addnew()
?? rs("use")=use
?? rs("pwd")=pwd
?? rs.update
?? '獲取Access數據庫中插入記錄的自動編號
?? temp=rs.bookmark
?? rs.bookmark=temp
?? id=rs("id")
?? ins1="insert into tb_purview(id,purviewSet,basicSet,stockSet,sellSet,storageSet,querySet,reportSet)values("&id&","&false&","&false&","&false&","&false&","&false&","&false&","&false&")"
?? conn.execute(ins1)
%>
?? <script language="javascript">
?? alert("管理員信息添加成功,繼續添加!");
?? window.location='tjyg.asp';
?? </script>
?? <%
Else
%>
?? <script language="javascript">
?? alert("該管理員信息已存在!");
?? window.location='tjyg.asp';
?? </script>
<%
end if
end if
%>
顯示管理員列表頁面即權限管理的主頁面,在該頁面中將顯示所有管理員信息,其中管理員的權限是以復選框的形式進行顯示,頁面運行結果如圖6.26所示,代碼如下:
例程6-25? 代碼位置:光盤"mr"6"6.3"6.3.3"main.asp
<%
Set rs=Server.CreateObject("Adodb.RecordSet")
sql="select * from tb_use u inner join tb_purview p on u.id=p.id order by u.id asc"
rs.open sql,conn,1,3
if rs.bof and rs.eof then
response.Write("暫無管理員信息!")
else
%>
<table width="696" height="67" border="1" align="center" cellpadding="0" cellspacing="0" bordercolor="#6598CD">
<tr>
<td height="25" bgcolor="#99CDFF">
<div align="center" class="STYLE6">管理員名稱</div>
</td>
<td bgcolor="#99CDFF"><div align="center" class="STYLE6">權限管理</div></td>
<td bgcolor="#99CDFF"><div align="center" class="STYLE6">基礎信息管理</div></td>
<td bgcolor="#99CDFF"><div align="center" class="STYLE6">進貨管理</div></td>
<td bgcolor="#99CDFF"><div align="center" class="STYLE6">銷售管理</div></td>
<td bgcolor="#99CDFF"><div align="center" class="STYLE6">庫存管理</div></td>
<td bgcolor="#99CDFF"><div align="center" class="STYLE6">查詢統計</div></td>
<td bgcolor="#99CDFF"><div align="center" class="STYLE6">報表管理</div></td>
<td bgcolor="#99CDFF"><div align="center" class="STYLE6">權限設置</div></td>
<td bgcolor="#99CDFF"><div align="center" class="STYLE6">操作</div></td>
</tr>
<%
for i=1 to rs.recordcount
%>
<tr>
<td height="20" bgcolor="#FFFFFF">
<div align="center" class="STYLE6"><%=rs("use")%></div>
</td>
<td bgcolor="#FFFFFF">
<div align="center" class="STYLE6">
<input name="checkbox" type="checkbox" class="noborder" value="checkbox" disabled="disabled"
<%if rs("purviewSet") then response.write("checked") end if%>>
</div>
</td>
<td bgcolor="#FFFFFF">
<div align="center" class="STYLE6">
<input name="checkbox" type="checkbox" class="noborder" value="checkbox" disabled="disabled" <%if rs("basicSet") then response.write("checked") end if%>>
</div>
</td>
<td bgcolor="#FFFFFF">
<div align="center" class="STYLE6">
<input name="checkbox" type="checkbox" class="noborder" value="checkbox" disabled="disabled" <%if rs("stockSet") then response.write("checked") end if%>>
</div>
</td>
<td bgcolor="#FFFFFF">
<div align="center" class="STYLE6">
<input name="checkbox" type="checkbox" class="noborder" value="checkbox" disabled="disabled" <%if rs("sellSet") then response.write("checked") end if%>>
</div>
</td>
<td bgcolor="#FFFFFF">
<div align="center" class="STYLE6">
<input name="checkbox" type="checkbox" class="noborder" value="checkbox" disabled="disabled" <%if rs("storageSet") then response.write("checked") end if%>>
</div>
</td>
<td bgcolor="#FFFFFF">
<div align="center" class="STYLE6">
<input name="checkbox" type="checkbox" class="noborder" value="checkbox" disabled="disabled" <%if rs("querySet") then response.write("checked") end if%>>
</div>
</td>
<td bgcolor="#FFFFFF">
<div align="center" class="STYLE6">
<input name="checkbox" type="checkbox" class="noborder" value="checkbox" disabled="disabled" <%if rs("reportSet") then response.write("checked") end if%>>
</div>
</td>
<td bgcolor="#FFFFFF"><div align="center"><span class="STYLE6">
<%
if rs1("purviewSet")=true and rs("use")<>"mr" then
%>
<a href="#" onClick="window.open('qx.asp?id=<%=rs("u.id")%>','','width=292,height=175')"><span class="STYLE9">權限設置</span></a>
<%else%>
<span class="STYLE9"> </span>
<%end if%>
</td>
<td bgcolor="#FFFFFF">
<div align="center">
<%if rs1("purviewSet")=true and rs("use")<>"mr" then%>?
<a href="del.asp?id=<%=rs("u.id")%>"><span class="STYLE9">刪除</span></a>
<%
Else
%>
<span class="STYLE9"> </span>
<%
end if
%>
</div>
</td>
</tr>
<%
rs.movenext
if rs.eof then exit for
next
%>
</table>
<%
end if
%>
管理員在進行登錄時,首先判斷此管理員是否擁有權限管理的功能,如果有權限管理功能,則可以通過單擊某條管理員信息右側的“權限設置”超鏈接即可進入到管理員權限修改頁面,在該頁面中將顯示該管理員的權限信息,設置相應的信息后,單擊“保存”按鈕即可將管理員的權限信息保存到數據表中;否則將不顯示“權限設置”超鏈接。管理員權限修改頁面的運行結果如圖6.28所示。
圖6.28? 管理員權限修改頁面的運行結果
通過以下代碼實現管理員權限的修改,代碼如下:
例程6-26? 代碼位置:光盤"mr"6"6.3"6.3.3"ok.asp
<!--#include file="conn/conn.asp"-->
<%
if request.Form("Button")="保存" then
?? purviewSet=request.Form("purviewSet")
?? if purviewSet="" then purviewSet=false
?? basicSet=request.Form("basicSet")
?? if basicSet="" then basicSet=false
?? stockSet=request.Form("stockSet")
?? if stockSet="" then stockSet=false
?? sellSet=request.Form("sellSet")
?? if sellSet="" then sellSet=false
?? storageSet=request.Form("storageSet")
?? if storageSet="" then storageSet=false
?? querySet=request.Form("querySet")
?? if querySet="" then querySet=false
?? reportSet=request.Form("reportSet")?
?? if reportSet="" then reportSet=false
?? UP="Update tb_purview set purviewSet="&purviewSet&",basicSet="&basicSet&",stockSet="&stockSet&",sellSet="&sellSet&",storageSet="&storageSet&",querySet="&querySet&",reportSet="&reportSet&" where ID="&session("ID")&""
?? conn.execute(UP)
end if
%>
通過以下代碼實現管理員信息的刪除,代碼如下:
例程6-27? 代碼位置:光盤"mr"6"6.3"6.3.3"del.asp
<!--#include file="conn/conn.asp"-->
<%
if request.QueryString("id")<>"" then
?? Del="Delete from tb_use where ID="&request.QueryString("id")&""
?? conn.execute(Del)
%>
<script language="javascript">
window.location.href='main.asp';
</script>
<%
end if
%>
3.補充說明
在本方案中實現管理員信息添加時,首先需要將管理員信息添加到管理員信息數據表中,然后需要在權限信息表中也同時級聯插入該管理員的權限信息,實現級聯插入管理員權限信息主要通過獲取Access數據庫中插入記錄的自動編號實現的。下面對該技術進行詳細介紹。
本方案主要通過Bookmark屬性使用戶對Recordset中的記錄進行標記,稍后再返回給它。使用Bookmark屬性可以保存當前記錄的位置并隨時返回該記錄。Bookmark屬性只能在支持書簽功能的Recordset對象中使用。
打開Recordset對象時,其每個記錄都有唯一的書簽。要保存當前記錄的書簽,請將Bookmark 屬性的值賦給一個變量。移動到其他記錄后要快速返回到該記錄時,請將該Recordset對象的 Bookmark屬性設置為該變量的值。
如果使用Clone方法創建Recordset對象的一個副本,則原始的和復制的Recordset對象Bookmark屬性設置相同并可以替換使用。但是無法替換使用不同Recordset對象的書簽,即使這些書簽是通過同一數據源或命令創建的。
在客戶端上使用Recordset對象時,Bookmark屬性始終有效。例如以下代碼:
temp=rs.bookmark
rs.bookmark=temp
為了使讀者能夠更好地理解和運用該技術,下面將給出一個具體的應用方案。在開發留言板程序時,應設置回復功能。本方案主要通過Recordset對象中的Bookmark屬性使用戶對Recordset 中的記錄進行標記,稍后再返回給它。當對留言信息進行回復時,回復的信息將直接與留言信息依依相對應,就無須在指定回復留言的ID號。運行結果如圖6.29所示。
圖6.29? 向Access數據庫中插入記錄
通過以下代碼實現數據庫的連接,代碼如下:
<%
set conn=server.CreateObject("adodb.connection")
sql="Driver={Microsoft Access Driver (*.mdb)};DBQ=" &server.MapPath("Database/db_database.mdb")
conn.open(sql)
%>
添加表單、文本框和文本域,并設置其相關的屬性值,代碼如下:
<form method="post" name="form1">
<input name="title" type="text" class="text" id="title" size="32">
<textarea name="content" cols="30" rows="8" class="text" id="content">
</textarea>
<input name="Submit" type="submit" class="button" value="提交">
<input name="Submit2" type="reset" class="button" value="重置">
</form>
通過以下代碼實現立即獲取插入記錄的自動編號,代碼如下:
<%
if request.form("title")<>"" then
title=request.form("title")
content=request.form("content")
Set rs=Server.CreateObject("ADODB.Recordset")
sql="select * from tb_sml"
rs.open sql,conn,1,3
rs.addnew()
rs("title")=title
rs("content")=content
rs.update()
temp=rs.bookmark
rs.bookmark=temp
topicID=rs("ID")
ins="insert into tb_back (title_ID) values ("&topicID&")"
conn.execute(ins)
end if
%>
6.5? ASP文件安全技術方案
使用瀏覽器的“查看源文件”功能只可以查看IIS服務器編譯后的HTML標簽和JavaScript等客戶端腳本,但使用迅雷等下載工具就可以將ASP源文件下載到本地,如果不對ASP文件加密,所有站點源文件將被竊取,這樣不僅不利于維護網站的版權,而且會給站點的安全帶來很大的隱患。本節將介紹如何對ASP文件進行加密。
6.5.1? 應用Script Encoder加密工具
Script Encoder是Microsoft推出的一個script加密工具,它是一個簡單的命令行工具,可以對html文件進行加密,只是對其中的VBscript部分進行加密處理,其他的文本部分均保持不變,加密后對script的功能并無影響,僅是其代碼變成密文,用源文件方式查看只是一些亂碼。該程序除了可對html文件加密外,也可以對asa、asp、cdx、js、sct、vbs文件進行加密。該程序很小只有64K,使用非常簡單,在DOS命令行下執行,也可在Windows下帶參數運行。
1.方案分析
應用Script Encoder對asp文件進行加密,首先依次單擊“開始”→“程序”→“附件”→“命令提示符”,在MS-DOS命令行中輸入以下命令,即可對某asp文件進行加密,加密格式如下:
SCRENC? [switches]? <要加密asp文件名>? <加密后的文件名>
在SRCENC命令中應用到了switches選項,該選項的常用參數如下所示,下面對常用的屬性進行詳細說明:
/s 可選。命令中帶了該參數,加密過程中屏幕上就不會有輸出。screnc /s lacl.sct ulacl.sct對當前目錄中的腳本小程序lacl.sct加密,加密過程中屏幕不顯示任何信息。
/f 可選。指定輸出文件是否覆蓋同名輸入文件。忽略,將不執行覆蓋。screnc /f lacl.asp對文件lacl.asp加密,并用編碼后的同名文件覆蓋原文件。
/xl 可選。是否在asp文件的頂部添加@Language指令。忽略,將添加。
/l defLanguage 可選。指定Script Encoder加密中選擇的缺省腳本語言。文件中不包含這種腳本語言特性的腳本將被Script Encoder 忽略。
對于HTML文件,JScript為內置缺省腳本語言;對于ASP文件,VBScript為缺省腳本語言;對于擴展名為.vbs或.js的文件,Script Encoder也有適應能力。screnc /l vbscript lacl.htm ulacl.htm對文件lacl.htm加密,并生成輸出文件ulacl.htm,確保沒有指定語言屬性的腳本使用VBScript。
/e defExtension 可選。指定待加密文件的文件擴展名。缺省狀態下,Script Encoder能識別asa、asp、cdx、htm、html、js、sct和vbs文件。screnc /e asp 11\*.* f:\labxw-jm對11目錄中的所有.ASP 文件進行加密,并把編碼后的輸出文件放在f:\labxw-jm目錄中。
2.實施過程
? 實例位置:光盤\mr\6\6.5\6.5.1
Script Encoder加密工具可以對asp、html、asa、cdx、sct和vbs等文件進行加密。下面將使用Script Encoder加密工具對index.asp進行加密,其中index.asp加密前的內容如圖6.40所示。
具體步驟如下:
(1)安裝Script Encoder加密工具到目錄c:\test下。
(2)把需要加密的ASP文件也拷到目錄c:\test下。
(2)依次選擇“開始”→“程序”→“附件”→“命令提示符”。
(3)在“命令提示符”對話框中,首先轉換到目錄c:\test(即輸入命令 cd c:\test)下,然后再C盤中建立test1文件夾,文件夾建立完成后并輸入以下代碼即可:
screnc *.asp c:\test1
最后應該得到如下代碼:
C:\test>screnc *.asp c:\test1
通過Script Encoder加密工具對index.asp文件進行加密后的結果如圖6.41所示。
圖6.40? 加密前的文件
圖6.41? 加密后的文件
3.補充說明
通過本方案的學習,讀者可以很輕松地對指定的ASP文件進行加密,還可以對html文件進行加密,但是不能對JavaScript腳本語言進行加密處理。
6.5.2? 將ASP文件轉換成HTML文件
對ASP文件進行加密,除了使用Script Encoder加密工具外,還可以將ASP文件轉換為HTML格式的文件。下面將對ASP文件轉換為HTML文件的具體實現過程進行分析和說明。
1.方案分析
首先通過Microsoft.XMLHTTP方法可以獲取到asp文件中信息內容的二進制數據,然后再通過ADO的Stream對象將二進制數據轉換為字符串,最后將獲取到的數據寫入到html文件中。
2.實施過程
? 實例位置:光盤\mr\6\6.5\6.5.2
在開發動態網站時,應考慮到隨著網站訪問量的不斷增多,服務器的承載壓力也會越來越大。如果將asp文件轉換成html文件,既可以減輕服務器的承載壓力和提高網站的瀏覽速度,又可以保證asp文件的源代碼不被泄漏,從而達到提高asp文件安全性的目的,如圖6.42所示。
圖6.42? 將ASP文件轉換成HTML文件的運行結果
運行本實例,如圖6.42所示,首先在圖中的文本框中輸入要轉換成html格式的asp文件的地址,然后單擊“提交”按鈕即可實現將asp格式文件轉換為html格式,實現該過程的關鍵代碼如下:
例程6-29? 代碼位置:光盤\mr\6\6.5\6.5.2\index.asp
<%
Function GetContent(url)?
'獲取文件內容
? Dim XMLObj
? Set XMLObj = CreateObject("Microsoft.XMLHTTP")
? With XMLObj
?? .Open "Get", url, False
?? .Send
?? GetContent=BytesToBstr(.ResponseBody)
? End With?
End Function
Function BytesToBstr(info)?
'將二進制轉換為字符串
?dim objstream
?set objstream = Server.CreateObject("adodb.stream")
?objstream.Type = 1
?objstream.Mode =3
?objstream.Open
?objstream.Write info
?objstream.Position = 0
?objstream.Type = 2
?objstream.Charset = "GB2312"
?BytesToBstr = objstream.ReadText
?objstream.Close
?set objstream = nothing
End Function
If Request.Form("url")<>"" Then
on error resume next
Url=Request.Form("url")?
'需要注意的是這里的URL指定為您要讀取的頁面地址
'開始獲取/更新頁面...
wstr = GetContent(Url)
'生成html文檔
Set FSO=Server.CreateObject("Scripting.FileSystemObject")
htmPath=server.MapPath("index.htm")
If (FSO.FileExists(htmPath)) Then
? FSO.DeleteFile(htmPath)
End If
Set TSobj=FSO.CreateTextFile(htmPath)
TSobj.Writeline(wstr)
set TSobj=nothing
set FSO=nothing
If err<>0 Then
? Response.Write("<script language='javascript'>alert('操作失敗,未能生成HTML文件!');window.location.href='index.asp';</script>")
? Response.End()
Else
? Response.Redirect("index.htm")
End If
End If
%>
3.補充說明
將asp格式的文件轉換為html格式,即可以有效地提高服務器端的速度,而且還可以在很大程度上提高站點的安全性。
轉載于:https://www.cnblogs.com/jiania1224/archive/2009/04/01/1426810.html
總結
以上是生活随笔為你收集整理的asp 与 database (3)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: vmware, failed to lo
- 下一篇: 匿名内部类 handler