台灣最大程式設計社群網站
線上人數
509
 
會員總數:245463
討論主題:189220
歡迎您免費加入會員
討論區列表 >> 專欄文章 >> 建立 Web 基礎的行事曆
[]  
[我要回覆]
回應主題 加入我的關注話題 檢舉此篇討論 將提問者加入個人黑名單
建立 Web 基礎的行事曆
價值 : 0 QP  點閱數:3269 回應數:0

樓主

站務人員 站長
門外漢
0 1580
542 9
發送站內信

捐贈 VP 給 站務人員
簡介

在這片文章中,我會示範如何建立 Web 基礎的行事曆。這篇文章對於在資料驅動的網站中 Active Server Pages (ASP)、Structured Query Language (SQL) 與 and ActiveX Data Objects (ADO) 的開發新手,提供一個良好的導覽。對於有經驗的開發人員,我也提供一些調整性方面的實用建議。

圖 1 Web 基礎的行事曆

什麼是 Web 基礎的行事曆?

Web 基礎的行事曆近來十分的流行。起初,使用者將行事曆置於個人的資訊管理程式中,例如 Microsoft(R) Outlook(R)。這些行事曆的問題,簡單的說,是它們皆針對個人性而設計的,很難和其他人一起分享檢視或使用。現在我們需要的一種方式,讓其他人也可以看見您的個人行事曆,或是擁有一個許多人共用的小組行事曆。隨著網際網路的發展,隨時隨地使用 Web 基礎的行事曆也變得可行。

您能利用 Web 基礎的行事曆作什麼?

Web 基礎的行事曆使您能和其他人分享您的行事曆,或是讓一群人管理行事曆。如果您想要其他人存取您的行事曆,分享行事曆是很有用的。換句話說,小組行事曆對於顯示主要的行事項目是有幫助的,例如截止日期或重大事件,同時也可以顯示給正在休假中的人。

這裡現存的東西

在我的辦公室裡頭,我們有一個 intranet 網站,在那裡,我們合併所有與我們小組有關的資訊,包含休假行事曆、重大事件以及假期。這需要建立一個簡單的 Web 基礎的行事曆,讓任何人可以檢視、新增、以及/或是移除行事項目 (請參閱圖 1)。


在這篇文章中,我會說明如何在 Microsoft Internet Information 服務 (IIS) 與 Microsoft SQL Server 中,使用 ASP 網頁建立一個非常簡單 Web 基礎的行事曆。在這篇文章的結論中,我會討論當調整應用程式給更多使用者時,效能的牽連是必須考量的。對於剛進入 IIS 與 ASP 的人,這篇文章可以當成建立資料驅動網站的良好導覽。

SQL 後端

要儲存什麼資料?

第一個問題是,每個日期要儲存什麼類型資料?對我的行事曆而言,我只需要簡單的儲存標示行事性質的 100 字元長的文字字串。每個人都可以輕易的延伸資料模型,以包含更多的文字字串。


語法

Calendar.sql

SQL 程式碼包含下列的片段程式碼:

------- 資料表--------------

create table Schedule

(

idSchedule smallint identity primary key,

dtDate smalldatetime not null,

vcEvent varchar(100) not null

)

go



----------------- 預存程序--------------------------



create procedure GetSchedule (@nMonth tinyint, @nYear smallint)

as

select idSchedule, convert(varchar, datepart(dd, dtDate)) 'nDay', vcEvent

from Schedule

where datepart(yy, dtDate) = @nYear and datepart(mm, dtDate) = @nMonth

order by datepart(dd, dtDate)

go



create procedure AddEvent (@vcDate varchar(20), @vcEvent varchar(100))

as

insert Schedule

select @vcDate, @vcEvent

go



create procedure DeleteEvent (@idSchedule smallint)

as

delete Schedule where idSchedule = @idSchedule

go


對於我的排程表,我使用一個辨識鍵 (自動增加),作為主要鍵,所以我不需要自己建立一個唯一的鍵。 我選擇 smallint 給 idSchedule 使用,因為對於我的需求,我從來沒有期望擁有超過 32,000 個不同的行事項目。對於一個比較大規模的應用程式,你可能比較想要使用一個長整數來提供你 20 億筆的記錄。我將這個資料儲存為 smalldatetime,以節省空間,因為我不需要記錄到秒數位。一個正常 datetime 會記錄到萬分之一秒,比起正確率到分的 smalldatetime,其多佔了一倍的空間。規模較大的應用程式也許需要檢查其他方法,利用更少的空間來記錄日期 (例如,在經過特定的日期後,就出現整數顯示天數,例如 1970 年 1 月 1 日)。

對於我的資料,我使用一個不同長度的字元字串 (varchar),高達 100 個字元。 在 SQL Server 7.0 中,你可以使用一個 nvarchar,那可以使用 Unicode 字元,使你的應用程式可以全球性的使用。但是,這裡有為了國際使用者建立網路頁面的問題,這超過了我們現在這裡討論的範圍。


預存程序

一個有關 SQL 預存程序的摘記:在 ASP 程式碼上,預存程序比直接撰寫 SQL 還好,而原因有二。第一,將資料存取程式碼從敘述程式碼分出,確定資料的獨立性。這讓你可以改變資料的架構 (以及它伴隨的預存程序,並且不用改變 ASP 頁面。這是典型的 Microsoft Windows DNA n-tier 架構。第二個為什麼預存程序比較好的原因是,它們比文字參數執行得快,因為當它們被呼叫時,它們就會先被分析。因此,後來的呼叫就不用再次分析這個程序。


我需要三個預存程序來在這個表上存取和處理資料;GetSchedule、AddEvent 和 DeleteEvent。


對於 GetSchedule程序,我在月和年傳遞我想要回的資料。然後,我使用 Datepart() 功能來取得行事項目的日子數。然後,我將使用這個數字來和我建立的行事曆的日子配合。我們會在後面看到,每天排列結果是很重要的。


AddEvent 程序就是簡單的增加一個文字行事項目到一個給出的資料上。我並不擔心複製行事項目,因為所有的行事項目都用有一個獨特的排程 ID。


獨特的排程 ID 是從排程中移除一個行事項目唯一需要的。傳遞這個到 DeleteEvent 程序移除這個行事項目。


ASP 前端

基本的 UI

  圖 1 顯示主要的使用者介面 (UI)。 UI 的安裝像是一個桌面行事曆。我的一個星期從星期日開始並且包含 7 天。為了簡單,我必須避免執行吃重的格式,但是使用樣式表來製造這個行事曆,讓它看起來更專業就容易的多。從這個主要頁面,使用者可以看到哪一個行事項目已經在行事曆上。而且。它們可以在行事曆的月份上往前和往後移,只要使用在頁底的連結,或是選擇一個特定的月份和年份,只要使用在頁面左上角的下拉框。連結增加/移除行事項目的頁面是在行事曆的正下面。


ASP 程式碼基礎

header.asp

<%@ LANGUAGE="VBSCRIPT" 

ENABLESESSIONSTATE = False %>

<%

'**************************************

' 名稱: header.asp

'

' 目的:表頭包含啟動所有頁面的檔案

' 也包含總體函數

'

'********************************************************************



Option Explicit

Response.Buffer = True

Response.Expires = 0



sub Doheader(strTitle)

%>

<html>

<head>

<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=big5">

<title>Event Calendar - <%= strTitle %></title>

</head>



<body bgcolor="white" link="blue" alink="blue" vlink="blue">

<basefont face="Verdana, Arial">



<center><h1>Event Calendar</h1>

<h3><%= strTitle %></h3>

<%

end sub



sub DoFooter(strTitle)

%>

</center>

</body></html>

<%

end sub



function GetDataConnection()

dim oConn, strConn

Set oConn = Server.CreateObject("ADODB.Connection")

strConn = "Provider=SQLOLEDB; Data Source=adspm; Initial Catalog=TeamWeb; "

strConn = strConn & "User Id=TeamWeb; Password=x"

oConn.Open strConn

set GetDataConnection = oConn

end function

%>


當我使用 ASP 撰寫一個網站,我喜歡對整個網路使用一個單一表頭頁面。這讓我可以在每一頁上放相同的使用功能、樣式 ,Microsoft JScript 等等。對於這個網站,我必須安裝一個表頭頁面 (請參考處理碼的範例),在整個網站上安裝相同的 ASP 裝置,並且包含三個我在所有其他頁面上使用的功能:一個 HTML 表頭和表尾,以及我的資料連結程式碼。



我最先做的事是安裝語言到 Microsoft Visual Basic Scripting Edition (VBScript) 和停止階段作業狀態。安裝語言並不是絕對需要,但卻是一個好主意。並且,這個網站不用ASP 階段作業狀態,那就是我直接稱為的 IIS,因此,效能快速的進步。我其他撰寫習慣是用來設定 Option Explicit (意思是我必須在使用它們前 dim 變數),緩衝輸出 (IIS 將會保留輸出,然後一次放出,它增進的功能),並且立即設立這個頁面為過期的 (因此,使用者將永遠得到最新頁面)。



我使用 Doheader 功能處理所有我的 HTML 表頭程式碼。我傳遞頁面的名稱,同時顯示在 HTML 標題和 H3 標籤在頁面的最上面。這讓我有一個單一的地方來編譯HTML BODY 屬性、樣式等。相似於 Doheader 功能。我想要擁有一個表尾功能,萬一我需要增加一個普通的 (連結資訊等)。



ADO 讓我的 ASP 頁面很容易的連結 SQL 資料庫。首先,我建立一個連線到資料庫。為了獲得 recordset ,我呼叫 Execute 模式,在 Connection 物件傳遞我希望執行的文字字串命令。一旦我擁有了 recordset,我可以環繞它。header.asp 包含了獲得資料連線的功能。這表示我只需要在一個地方編譯連線資訊 (伺服器、使用者、密碼) 如果我的資料來源改變。注意,功能的最後,我必須使用 set 命令來傳遞出新的連線作為結果。



如何運作

Calendar.asp



<!--#includes file="header.asp"-->

<%

'********************************************************************

' 名稱:Calendar.asp

'

' 目的:用行事曆格式顯示行事項目的主要行事曆頁

'

'********************************************************************



dim dbConn, rs, nDex, nMonth, nYear, dtDate



' 取得現在的日期

dtDate = Now()



' 設定月份和年份

nMonth = Request.QueryString("nMonth")

nYear = Request.QueryString("nYear")

if nMonth = "" then nMonth = Month(dtDate)

if nYear = "" then nYear = Year(dtDate)



' 設定日期到現在第一個月份

dtDate = DateSerial(nYear, nMonth, 1)



Set dbConn = GetDataConnection

Set rs = dbConn.Execute ("GetSchedule " & nMonth & ", " & nYear)



Doheader(MonthName(Month(dtDate)) & "  " & nYear)

%>

<form method="get" name="DateSelect" action="Calendar.asp">



<table width=700>

<tr><td colspan=2><select name="nMonth" onChange="DateSelect.submit();"><%

for nDex = 1 to 12

Response.Write "<option value=""" & nDex & """"

if MonthName(nDex) = MonthName(nMonth) then

Response.Write " selected"

end if

Response.Write ">" & MonthName(nDex)

next %></select> 

<select name="nYear" onChange="DateSelect.submit();"><%

' Note: I have set the year to be between 1999 and 2000

for nDex = 1999 to 2002

Response.Write "<option value=""" & nDex & """"

if nDex = CInt(nYear) then Response.Write " selected"

Response.Write ">" & nDex

next %></select></td></tr>



<tr><td colspan=2>

<table border=1 bgcolor="gray" cellpadding=3>

<tr bgcolor="Blue"><td width=90><font color="white">Sunday</font></td>

<td width=90><font color="white">Monday</font></td>

<td width=90><font color="white">Tuesday</font></td>

<td width=90><font color="white">Wednesday</font></td>

<td width=90><font color="white">Thursday</font></td>

<td width=90><font color="white">Friday</font></td>

<td width=90><font color="white">Saturday</font></td></tr>

<tr bgcolor="#ffffc0">

<%

' 增加空白欄位,直到正確的天數

for nDex = 1 to Weekday(dtDate) - 1

Response.Write "<td bgcolor=""#c0c0c0""> </td>"

next



do

Response.Write "<td valign=""top"">" & Day(dtDate) & "<br> <br>"



if not rs.EOF then

do

if CInt(rs("nDay")) <> CInt(Day(dtDate)) then exit do



Response.Write "<font size=""-1"">" & rs("vcEvent")

Response.Write "
</font><br>"

rs.MoveNext



if rs.EOF then exit do

loop

end if



Response.Write "</td>"



if WeekDay(dtDate) = 7 then

Response.Write "</tr>" & vbCrLf & "<tr bgcolor=""#ffffc0"">"

end if

dtDate = DateAdd("d", 1, dtDate)

loop until (Month(dtDate) <> CInt(nMonth))



' 新增空白欄位來填滿其他需要的月份

if Weekday(dtDate) <> 1 then

for nDex = Weekday(dtDate) to 7

Response.Write "<td bgcolor=""#C0C0C0""> </td>"

next

end if

%>

</tr>

</table></td></tr>



<tr><td colspan=2 align="center"><a

href="Events.asp?nMonth=<%= nMonth %>&nYear=<%= nYear %>"

>Add/Remove Events</a></td></tr>



<tr><td><a href="Calendar.asp?nMonth=<%

if nMonth = 1 then

Response.Write "12&nYear=" & nYear - 1

else

Response.Write nMonth - 1 & "&nYear=" & nYear

end if %>"><b><- Previous Month
</a></td>

<td align=right><a href="Calendar.asp?nMonth=<%

if nMonth = 12 then

Response.Write "1&nYear=" & nYear + 1

else

Response.Write nMonth + 1 & "&nYear=" & nYear

end if %>">Next Month - ></a>

</td>

</tr>

</table>



</form>



<%

DoFooter("Home")

%>


這個專案最有挑戰的部分是建立一個正確的 HTML 行事曆。有很多需要決定的演算法,或是,例如,每一個月有多少天,今年是不是閏年等。與其從頭到尾的做,我使用在 Visual Basic 中的 date 物件,來建立我的行事曆。



為了設計某個月份的行事曆,首先我建立一個 date 物件,為了那個月份或年份的第一天。然後,我簡單的使用 DateAdd() 功能來增加一天。然後,我可以使用內建的方法來顯示這是星期幾,以及這個月結束的日期。我也可以知道這個月的天數,並且使用它在我排程的資訊上。這讓我可以建立一個顯示行事曆的表格。



行事曆頁面使用傳遞在查詢字串的日期和年份。如果沒有任何的日期或年份傳入,就會使用目前的日期和年份。



這使得建立可以在月份間移動的 UI 變的很容易。可以建立回到某個月份的連結,利用呼叫 Calendar.asp 和提供一個指定前一個月份的查詢字串 (並且減少一個年份,如果我們是在一月)。往前移一個月很簡單 (首先,先查看是不是在十二月)。移動到一個特定的月份和年份也比較簡單。我們只需要安裝一個 Calendar.asp 格式為一個目標,裝一些下拉框,用我們想要涵蓋的月份和年份,為了下拉表單,然後附加一個最頂端的事見到 onChange() 行事項目。這使得頁面可以自動的更新,當使用者選擇了一個新的月份或年份。注意到我如何使用 MonthName() 功能表來排列出月份。



顯示行事項目是很簡單的。首先,我用 ADO 來連結 SQL 資料庫,顯示出特定月份的行事項目。呼叫 GetSchedule 預存程序,並傳遞問號到月份和年份。這讓我使用一個包含了行事項目的表單 recordset,單獨隨著它們的發生日 (用日來儲存)。



現在,當我建立行事曆時,只要顯示行事項目發生的日期和內容即可。我可以這樣做是因為我知道行事項目以天來作為儲存單位。



圖 2 新增/移除行事項目頁



新增/移除行事項目頁允許使用者新增事件項目或移除現存的行事項目。要存取頁面,首先將行事曆移動到正確的月份頁,然後按新增/移除行事項目的連結。這個連結的建立包含查詢要新增/移除行事項目的月與年之字串。



使用與 Calendar.asp 相同的 GetSchedule 預存程序,會產生月份中目前的行事項目列表。現在,我們只需要循環資料錄集,就可顯示月份中所有的行事項目。



Events.asp



<!--#includes file="header.asp"-->

<%

'********************************************************************

' 名稱:Events.asp

'

' 目的:用來從行事項目資料庫中新增與移除行事項目。

'

'********************************************************************



dim dbConn, rs, nDex, nMonth, nYear, dtDate, dtTemp



' 取得現在的日期

dtDate = Now()



' 設定月份與年份

nMonth = Request("nMonth")

nYear = Request("nYear")

if nMonth = "" then nMonth = Month(dtDate)

if nYear = "" then nYear = Year(dtDate)



Set dbConn = GetDataConnection

Set rs = dbConn.Execute ("GetSchedule " & nMonth & ", " & nYear)



Doheader("Add/Remove Events")

%>



<form method="get" action="AddEvent.asp">



<br>Currently Scheduled Events for <%

Response.Write MonthName(nMonth) & "  " & nYear

%>
:<p>

<table bgcolor="gray" border=1 cellpadding=3>

<tr bgcolor="Blue"><td><font color="white">Day</font></td>

<td colspan=2><font color="white">Event</font></td></tr>



<% if rs.EOF then

Response.Write "<tr><td colspan=3 bgcolor=""#ffffc0"">No events listed</td></tr>"

end if



while not rs.EOF

Response.Write "<tr bgcolor=""#ffffc0""><td>" & rs("nDay") & "</td><td>"

Response.Write rs("vcEvent") & "</td><td><input type=""button"" value=""Remove"""

Response.Write " onClick=""window.location.href='RemoveEvent.asp?nMonth=" & nMonth

Response.Write "&nYear=" & nYear & "&idSchedule=" & rs("idSchedule") & "'""></td></tr>"

rs.MoveNext

wend

%></table>



<p><br>

<table bgcolor="gray" border=1 cellpadding=3>

<tr bgcolor="Blue"><td><font color="white">Add New Event:</font></td></tr>

<tr bgcolor="#ffffc0"><td>Event:

<input type="text" size=30 maxlength=100 name="Event"> Day: <select name="nDay"><%

' 設定日期到現在第一個月份

dtDate = DateSerial(nYear, nMonth, 1)



dtTemp = dtDate

do

Response.Write "<option value=""" & Day(dtTemp) & """>" & Day(dtTemp)

dtTemp = DateAdd("d", 1, dtTemp)

loop until (Month(dtTemp) <> CInt(nMonth)) %></select>

<input type="hidden" name="nMonth" value="<%= nMonth %>">

<input type="hidden" name="nYear" value="<%= nYear %>">

<input type="Submit" value="Add Event"></td></tr>

</table>

</form>



<p><a href="Calendar.asp?nMonth=<%= nMonth %>&nYear=<%= nYear %>">Back to Calendar</a>



<%

DoFooter("Home")

%>



要增加新行事項目,使用者簡單的輸入想要的行事項目類型到表單中,然後按 [確定] 按鈕。使用 maxlength 屬性,限制表單元素為 100 個字元,以配合排程表中的行事項目欄位。



要移除行事項目,使用者按下要移除行事項目旁邊的按鈕。這個按鈕會呼叫 RemoveEvent.asp,傳遞行事項目的 idSchedule 以及現在的月份與年份,所以可以建連結回到 Events.asp。



AddEvent.asp



<!--#includes file="header.asp"-->

<%

'********************************************************************

' 名稱:AddEvent.asp

'

' 目的:用來新增行事項目到行事項目資料庫。

'

'********************************************************************



dim dbConn, strSQL



Set dbConn = GetDataConnection

strSQL = "AddEvent '" & Request("nMonth") & "/" & Request("nDay")

strSQL = strSQL & "/" & Request("nYear") & "', '"

strSQL = strSQL & Replace(Request("Event"), "'", "''") & "'"



dbConn.Execute (strSQL)



Response.Redirect("Events.asp?nMonth=" & Request("nMonth") & "&nYear=" & Request("nYear"))

%>


AddEvent.asp 頁面取得傳遞表單的資訊,然後使用 AddEvent 預存程序,插入資料庫中。然後頁面重新導回新增/移除行事項目頁中,使用可以立即看到新的行事項目。請注意我如何使用 Replace() 功能來將單引號 (') 變更為雙引號 (''),SQL 會解析單引號。如果您沒有這樣做,當使用者嘗試輸入像是「All Saints Day」這樣的行事項目時,會得到錯誤。



RemoveEvent.asp



<!--#includes file="header.asp"-->

<%

'********************************************************************

' 名稱:RemoveEvent.asp

'

' 目的:用來從行事項目資料庫中移除行事項目。

'

'********************************************************************



dim dbConn



Set dbConn = GetDataConnection

dbConn.Execute ("DeleteEvent " & Request("idSchedule") )



Response.Redirect("Events.asp?nMonth=" & Request("nMonth") & "&nYear=" & Request("nYear"))

%>





RemoveEvent.asp 頁面使用 DeleteEvent 預存程序來移除給定的行事項目 ID,然後立即傳送給使用者,回到行事項目頁面中。



效能議題

調整性

  ASP 漂亮的地方是,它使得建立網頁更加的容易。然而,如果您想建立一個能容許多使用者的網站,則需要小心地撰寫程式。在這個章節中,我會討論不同的增加此 Web 基礎行事曆調整性的方法。雖然是以這個應用程式為例,我所敘述的方法可以在任何 ASP 網站中增加效能。



SQL 最佳化

  要增進網站的效能,簡單的方法是增加排程表中欄位的索引。這樣會加速 GetEvents 預存程式,因為它會在給定的資料中搜尋行事項目。



對於小型網站,SQL 可以安裝像是 IIS 的伺服器上。一旦網站開始成長,您會希望將 SQL 移往自己的伺服器中。當伺服持續的成長,您會希望增加數部 IS 伺服器,全部指向相同的 SQL 伺服器。如果 SQL 的流量極度的成長,您會將資料切割到不同的伺服器。您可能希望將單數的月份放到一部伺服器,而雙數的月份放到另一部。當然,您可以修改在 header.asp 中的 GetDataConnection,讓它根據月份給定正確的連線。



ASP 最佳化

  ASP 轉換的主要最佳化是快取頁面,讓它們不用每次都要轉換。要這樣做,最簡單的方法是透過 ASP Application 物件。您可以建單的儲存 HTML 到有月份與年份的應用程式變數中 (例如,Calendar07-2000)。然後,顯示行事曆頁面時。首先檢查行事曆是否已經儲存在應用程式變數中,如果有,簡單的擷取它。這樣會儲存路徑到 SQL 框格中,底下是一些虛擬程式碼,顯示它如何運作:



<<do header>>



ShowCalendar(nMonth, nYear)


<<do Footer>>

sub ShowCalendar(nMonth, nYear)



if Application(Calendar?& nMonth & ??& nYear) = ? then

<<Build Calendar>>

Application(Calendar?& nMonth & ??& nYear) = <<Calendar>>

End if



Response.Write Application(Calendar?& nMonth & ??& nYear)

End sub


當然,當 Events.asp 頁面變更月份行事項目時,您需要清空月份的應用程式變數,讓變更可以得到影響。


安全性

  有幾個方法來執行網站的安全性。對於 intranet 網站,Microsoft Windows NTR 根據授權,可以最簡單的設定,因為您的使用者最有可能已經登入網路。您可能要讓所有的使用者檢視行事曆頁面,但是只有管理員可以存取來新增/移除行事項目頁。


如果稽核是一個考量,您可以簡單的修改 AddEvent 與 DeleteEvent 程序,儲存它們的資訊到稽核表中。另外,您可以確認 IIS 登入每個頁面點擊的查詢字串與使用者中。然後,透過紀錄簡單的剖析,來決定誰在什麼時候做過什麼。


結論

  在這篇文章中,我已經示範了如何設定 Web 基礎的行事曆。我的 Web 基礎的行事曆非常簡單,但是可以輕易的延伸成為完整功能的網站。我已經小心的敘述建立 Web 基礎的行事曆之步驟,讓初學者可以參閱 ASP、SQL 與 ADO 的動作。最後,我也提供一些如何讓這個網站調整至所需範圍的實用建議。如果您有發現任何錯誤,或是有任何能改善這個程式碼的建議,請傳送電子郵件到 semyan@hotmail.com。

© 2000 Microsoft Corporation. All rights reserved.
本篇文章發表於2001-01-15 00:00
別忘捐VP感謝幫助你的人 新手會員瞧一瞧
目前尚無任何回覆
   

回覆
如要回應,請先登入.