2008年7月2日 星期三

資料驗證


「通用表示法」或「通用式」(Regular expressions)是在 UNIX 世界中發展出來的字串比對技巧,其基本概念是用一套格式簡單、但功能強大的符號來比對複雜的字串,並可對符合比對條件的字串進行修改或其他運算。事實上,UNIX 的許多軟體或指令都支援通用表示法,例如 grep、sed、awk、ed、vi、emacs 等。(但是這些東西大概只有像我這樣的 LKK 才會用吧。)

Hint
若按照字面來翻譯,Regular expressions 應該翻成「正規表示法」或「正規式」,但是我們使用「通用表示法」或「通用式」似乎更能適切地表達其功能。



Netscape 及 IE 在第四版後都支援 JavaScript/VBScript 的通用表示法,特別適用於表單資料的驗證與修改。事實上,JavaScript/VBScript 的通用表示法和 Perl 以及其他 UNIX 相關指令幾乎一模一樣,因此,在本章學到的通用表示法,也可以完全適用於 Perl 或 UNIX 相關指令。(一魚兩吃,真是太棒了!)


由於篇幅限制,我們僅介紹 JavaScript 的通用式;VBScript 的通用式在功能上完全相同,只不過命令格式有所不同,有興趣的讀者,可以參考網路相關資料。


JavaScript 的通用式是一個內建的物件,其建構函數(Construction functoin)為 RegExp,典型用法如下:


re = new RegExp("pattern", "flag")<br />

上述用法也可以簡寫成下列格式:
<br />re = /pattern/flag<br />

其中,pattern 是通用表示法的字串,flag 則是比對的方式。flag 的值可能有三種,分別解釋如下:

  • g:全域比對(Global match)
  • i:忽略大小寫(Ignore case)
  • gi:全域比對並忽略大小寫


舉例來說,我們的身份證字號的基本格式,是由一個英文字母加上九個數字組合而成,如果我們要求使用者輸入身份證字號,就可以使用 JavaScript 的通用表示法來驗證其格式的正確性。例如,我們可用下列表單來要求使用者輸入身份證字號:

Example(regExpID01.htm):



在上例中,我們只要按下「驗證」的按鈕,就會呼叫 checkID() 函數來對文字欄位中的身份證字號進行驗證。相關原始碼如下:

原始檔(regExpID01.htm):(灰色區域按兩下即可拷貝)
<html>
<head>
<meta HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=big5">
</head>

<body>
<h2 align=center>通用式:簡易身份證字號驗證</h2>
<hr>

<script>
function checkID(string) {
re = /^[A-Z]\d{9}$/;
if (re.test(string))
alert("成功!符合「" + re + "」的格式!");
else
alert("失敗!不符合「" + re + "」的格式!");
}
</script>
身份證字號(第一個英文字母需大寫):<input id=idNumber value=A12345678>
<input type=button value="驗證" onClick="checkID(idNumber.value)">

<hr>
</body>
</html>



在上述範例中,/^[A-Z]\d{9}$/ 就是一個通用式,說明如下:


  • 若要比對數個字元中的任一個字元,可用中括號,並可用「-」來代表字母或是數字的範圍,因此 [A-Z] 代表由 A 至 Z 的任一個英文字母。(若不嫌煩,當然也可以寫成 [ABCDEFGHIJKLMNOPQRSTUVWXYZ]。)
  • \d 代表由 0 至 9 的數目字,事實上也可以寫成 [0-9] 或 [0123456789]。
  • {9} 代表前一個字元的重複次數,因此 \d{9} 代表需要有九個數目字。
  • ^ 代表字串開始位置,$ 代表字串結束位置。(若沒有這兩個符號,那麼只要任一個字串中間含有身份證字號,也可以比對成功。)

由上述說明,可知 /^[A-Z]\d{9}$/ 就代表可以比對身份證字號的通用式。此外,idNumber.value 代表使用者輸入的字串,re.test(string) 則是通用式 re 的一個方法,會傳回 true 或 false,代表比對是否成功。若要不限定是大寫英文字母,只需將上述範例的通用式改成 /^[a-zA-Z]\d{9}$/ 就可以了!

Hint
注意:若不加入 ^ 和 $,那麼 /[A-Z]d{9}/ 就會比對到其他不合法的身份證字號,例如 AGF123456789 或是 F1234567890 等。因此,加入 ^ 和 $ 可保證比對正確的字串一定是由一個大寫英文字母加上九個數字所構成。



事實上,身份證字號本身就有內在的編碼規則,這些規則和使用者的性別有關,因此若要實現完整的表單驗證,就必須應用完整的身份證編碼規則,讀者可參考本章的最後一節。


另一個簡單的例子,是要求使用者輸入信用卡號碼,這是一組 16 個數字的號碼,例如:

Example(regExpCreditCardNumber01.htm):



當我們按下「驗證」按鈕時,JavaScript 會呼叫函數 checkCreditCard( ) 來對填入的資料進行驗證。相關原始碼如下:

原始檔(regExpCreditCardNumber01.htm):(灰色區域按兩下即可拷貝)
<html>
<head>
<meta HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=big5">
</head>

<body>
<h2 align=center>通用式:簡易信用卡卡號驗證</h2>
<hr>

<script>
function checkCreditCard(string) {
re = /^\d{4}-\d{4}-\d{4}-\d{4}$/;
// re = /^(\d{4}-){3}\d{4}$/; // 這種寫法也可以!
if (re.test(string))
alert("成功!符合「" + re + "」的格式!");
else
alert("失敗!不符合「" + re + "」的格式!");
}
</script>
信用卡號碼:<input id=creditCardNumber value=1234-5678-9012-3456>
<input type=button value="驗證" onClick="checkCreditCard(creditCardNumber.value)">

<hr>
</body>
</html>



在上例中,很顯然地,/^\d{4}-\d{4}-\d{4}-\d{4}$/ 就代表正確的信用卡格式。很明顯的,使用通用式會讓程式碼簡潔很多,而且會大大提高程式碼的正確性。(請和前面章節的類似範例 formValidation02.htm 比較看看。)但要注意的是,信用卡卡號本身就有內在的較複雜編碼規則,因此若要實現完整的表單驗證,就必須應用完整的信用卡卡號編碼規則,讀者可參考本章的最後一節。


如果重複的部分多於一個字母,我們就必須將需要重複的部分放在小括號內,再加上由大括號包夾的重複次數,例如,上述範例的通用式 /^\d{4}-\d{4}-\d{4}-\d{4}$/,也可以寫成 /^(\d{4}-){3}\d{4}$/,請試試看!


下一個例子,則是用通用表示法來驗證使用者的英文名字,例如:

Example(regExpEnglishName01.htm):



當我們按下「驗證」按鈕時,JavaScript 會呼叫函數 checkEnglishName( ) 來對填入的資料進行驗證。相關原始碼如下:

原始檔(regExpEnglishName01.htm):(灰色區域按兩下即可拷貝)
<html>
<head>
<meta HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=big5">
</head>

<body>
<h2 align=center>通用式:簡易英文名字驗證</h2>
<hr>

<script>
function checkEnglishName(string) {
re1 = /^[A-Za-z\-]+\s+[A-Za-z\-]+$/;
re2 = /^[A-Za-z\-]+\s+[A-Za-z\-]+\s+[A-Za-z\-]+$/;
if (re1.test(string) || re2.test(string))
alert("成功!符合「" + re1 + "」或「" + re2 + "」的格式!");
else
alert("失敗!不符合「" + re1 + "」或「" + re2 + "」的格式!");
}
</script>
你的英文全名(格式:First Last 或 First Middle Last):<input id=englishName value="Jyh-Shing Roger Jang">
<input type=button value="驗證" onClick="checkEnglishName(englishName.value)">

<hr>
</body>
</html>



對於上述範例程式,我們說明如下:


  • [A-Za-z\-] 代表一個英文字母(可以大寫或小寫),或是字元「-」。特別要注意的是,由於「-」在中括號內部已經有特殊意義,若要避掉此特殊意義,就必須在「-」之前加上反斜線(「\」)。
  • 加號代表重複前一個字元一次或多次,因此 [A-Za-z\-]+ 就代表由英文字母或是減號所形成的字串,且其長度至少是一。
  • \s 代表空白字元,可以是空格、定位鍵、換列字元等等。因此 \s+ 就表示由一個或多個空白字元所形成的字串。

因此 re1 = /^[A-Za-z\-]+\s+[A-Za-z\-]+$/ 可以比對由兩個字彙所形成的英文名字,例如 Michael Jordan;而 re2 = /^[A-Za-z\-]+\s+[A-Za-z\-]+\s+[A-Za-z\-]+$/ 則可以比對由三個字彙所形成的英文名字,例如,Jyh-Shing Roger Jang。


下一個例子,則是用通用表示法來驗證電子郵件,例如:

Example(regExpEmail01.htm):



相關原始碼如下:

原始檔(regExpEmail02.htm):(灰色區域按兩下即可拷貝)
<html>
<head>
<meta HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=big5">
</head>

<body>
<h2 align=center>通用式:電子郵件格式驗證(可以避開含有空白的電子郵件帳號)</h2>
<hr>

<script>
function checkEmail(string) {
re = /^[^\s]+@[^\s]+\.[^\s]{2,3}$/;
if (re.test(string))
alert("成功!符合「" + re + "」的格式!");
else
alert("失敗!不符合「" + re + "」的格式!");
}
</script>
電子郵件:<input id=email value="jang@cs.n thu.edu.tw">
<input type=button value="驗證" onClick="checkEmail(email.value)">

<hr>
</body>
</html>



對於此範例所用到的通用式 /^[^\s]+@[^\s]+\.[^\s]{2,3}$/,說明如下:


  • \s 代表所有可能的空白字元,包含空白、定位鍵、換列字元等。(但並不包含全形的空白,請特別注意!)
  • ^ 在中括弧內是代表「否定」,因此 [^\s]+ 代表「由一個或多個非空白字元」所形成的字串。

Hint
請注意:^ 在一般通用表示法的意義是「字串開始的位置」,但是一旦放在中括弧內,則是代表「否定」或「非」。




在以下的範例中,我們設計了一個表單,可以讓使用者輸入任意字串、通用式,以及比對選項,並在通用式比對後,列出比對到的字串,讀者們可以利用此範例,反覆演練,以增進對於通用式的瞭解:

Example(regExpTest01.htm):



上述範例的原始檔如下:

原始檔(regExpTest01.htm):(灰色區域按兩下即可拷貝)
<html>
<head>
<meta HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=big5">
</head>

<body>
<h2 align=center>通用式:完整測試頁</h2>
<hr>

<script>
function showMatched(form){
var regexp = new RegExp(form.pattern.value, form.flag.value);
var str = form.string.value;
var matched = str.match(regexp);
if (matched) {
var dispstr = matched.length + " 個比對到的字串:";
for (var i=0; i<matched.length; i++)
dispstr = dispstr + "\n" + matched[i];
alert(dispstr);
} else
alert("沒有比對到任何字串!");
}
</script>
<form>
<table align=center>
<tr><td align=right>字串:
<td><input type=text size=30 name=string value="There are 10 rookies coming at 3 o'clock!">
<tr><td align=right>通用式:
<td><input type=text size=30 name=pattern value=" \w+ "> (範例:\d{2,3}, T.*a, T.*?a)
<tr><td align=right>選項:
<td><input type=text size=30 name=flag value="g"> (g, i, or gi)
<tr><td align=right><br>
<td><input type="button" value="顯示比對到的字串" onClick="showMatched(this.form)"><input type="reset">
</table>
</form>

<hr>
</body>
</html>



在上述範例中,我們使用了字串的 match() 方法,來對通用式進行比對,因此 matched = str.match(regexp) 可將比對到的字串送到一個陣列,以便後續處理。


在進行表單資料驗證之前,我們應先進行表單資料修改,例如拿掉不必要的空格、英文字母大小寫轉換等,這些工作也可以由字串的 replace() 方法或通用式的 exec() 方法來達成,這是我們下一節的主題。

2008年6月29日 星期日

在指定的目錄下開啟 Command Prompt

在〔開始〕→〔執行〕→鍵入〔regedit〕→選〔HKEY_CLASSES_ROOT〕→〔Directory〕→〔shell〕→增加一個機碼〔CommandPrompt〕預設值為〔在 Command Prompt 打開〕再在〔CommandPrompt〕下增加一個機碼〔command〕預設值為〔cmd.exe cd %1〕完成後在檔案總管任何資料夾下右點鼠標便會出現〔在 Command Prompt 打開〕的選項

2008年6月17日 星期二

ASP.NET+javascript

RegisterStartupScript("","<SCRIPT>alert('更新比重成功');");

2008年6月5日 星期四

DataGrid轉Excel

Dim sw As New System.IO.StringWriter Dim hw As New System.Web.UI.HtmlTextWriter(sw)
DataGrid1.RenderControl(hw) Response.Clear() Response.AppendHeader("Content-Disposition", "attachment; filename=excel.xls") Response.ContentType = "application/vnd.ms-excel" Response.Write(sw.ToString()) Response.End()

2008年6月3日 星期二

網頁表單元素Input的高級用法11例

網頁表單元素Input的高級用法11例

http://big5.chinaz.com:88/www.chinaz.com/Design/Pages/0521YI2007.html


網頁表單元素Input的高級用法11例[ 來源:網頁教學網 作者: 時間:2007-05-21 09:13:51 收藏本文 ] 【大 中 小】

1.取消按鈕按下時的虛線框

在input裏添加屬性值 hideFocus 或者 HideFocus=true

2.只讀文本框內容

在input裏添加屬性值 readonly



3.防止退後清空的TEXT文檔(可把style內容做做為類引用)

<INPUT style=behavior:url(#default#savehistory); type=text id=oPersistInput>

4.ENTER鍵可以讓光標移到下一個輸入框



<input onkeydown="if(event.keyCode==13)event.keyCode=9" >

5.只能為中文(有閃動)


<input onkeyup="value=value.replace(/[ -~]/g,'')" onkeydown="if(event.keyCode==13)event.keyCode=9">


6.只能為數字(有閃動)



<input onkeyup="value=value.replace(/[^\d]/g,'') "onbeforepaste="clipboardData.setData('text',clipboardData.getData('text').replace(/[^\d]/g,''))">



7.只能為數字(無閃動)

<input style="ime-mode:disabled" onkeydown="if(event.keyCode==13)event.keyCode=9" onKeyPress="if ((event.keyCode<48 event.keyCode>57)) event.returnValue=false">




8.只能輸入英文和數字(有閃動)




<input onkeyup="value=value.replace(/[\W]/g,'')" onbeforepaste="clipboardData.setData('text',clipboardData.getData('text').replace(/[^\d]/g,''))">

9.屏蔽輸入法

<input type="text" name="url" style="ime-mode:disabled" onkeydown="if(event.keyCode==13)event.keyCode=9"> Www@Chinaz@com

10. 只能輸入 數字,小數點,減號(-) 字符(無閃動)

<input onKeyPress="if (event.keyCode!=46 && event.keyCode!=45 && (event.keyCode<48 event.keyCode>57)) event.returnValue=false">

11. 只能輸入兩位小數,三位小數(有閃動)

<input maxlength=9 onkeyup="if(value.match(/^\d{3}$/))value=value.replace(value,parseInt(value/10)) ;value=value.replace(/\.\d*\./g,'.')" onKeyPress="if((event.keyCode<48 event.keyCode>57) && event.keyCode!=46 && event.keyCode!=45 value.match(/^\d{3}$/) /\.\d{3}$/.test(value)) {event.returnValue=false}" id=text_kfxe name=text_kfxe>

2008年5月19日 星期一

.Net 2003 Excel2003

這份文件示範如何為 Visual Basic . NET 設定適當的專案參照至 Excel 型別程式庫並提供範例程式碼來自動化 Excel。
建立在 Microsoft Excel 的 Automation 用戶端
1. 啟動 Microsoft Visual Studio .NET。.
2. 在 [ 檔案 ] 功能表, 再按一下 [ New , 及 專案 。 從 Visual Basic 專案類型選取 [ Windows 應用程式 。 根據預設會建立 Form1。.
3. 將參考加入至 Microsoft Excel Object Library 。 如果要執行這項操作,請依照下列步驟執行。: a. 在 [ 專案 ] 功能表, 按一下 [ 加入參考 。
b. 在 [ COM ] 索引標籤, 找出 Microsoft Excel Object Library , 並按一下 選取 。

請注意 Microsoft Office 2003 包括 Primary Interop Assemblies (PIA)。 並未包含 Microsoft Office XP PIA, 但是他們可以下載。 如需有關 Office XP PIA 的詳細資訊,請按一下下面的文件編號,檢視「Microsoft 知識庫」中的文件::
328912 (http://support.microsoft.com/kb/328912/) Microsoft Office XP 主要 Interop 組件 (PIA) 可供下載
c. 按一下 [ 確定 ] 以接受您的選項在 [ 加入參考 ] 對話方塊。

4. 在 [ 檢視 ] 功能表, 選取 工具箱 ] 以顯示 [ 工具箱 ], 然後新增按鈕至 Form 1。
5. 連按兩下 Button 1 。 即會出現在表單的程式碼視窗。
6. 在程式碼視窗中,找出下列程式碼: Private Sub Button1_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Button1.Click

End Sub

以下列程式碼取代前一個程式碼: Private Sub Button1_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Button1.Click
Dim oXL As Excel.Application
Dim oWB As Excel.Workbook
Dim oSheet As Excel.Worksheet
Dim oRng As Excel.Range

' Start Excel and get Application object.
oXL = CreateObject("Excel.Application")
oXL.Visible = True

' Get a new workbook.
oWB = oXL.Workbooks.Add
oSheet = oWB.ActiveSheet

' Add table headers going cell by cell.
oSheet.Cells(1, 1).Value = "First Name"
oSheet.Cells(1, 2).Value = "Last Name"
oSheet.Cells(1, 3).Value = "Full Name"
oSheet.Cells(1, 4).Value = "Salary"

' Format A1:D1 as bold, vertical alignment = center.
With oSheet.Range("A1", "D1")
.Font.Bold = True
.VerticalAlignment = Excel.XlVAlign.xlVAlignCenter
End With

' Create an array to set multiple values at once.
Dim saNames(5, 2) As String
saNames(0, 0) = "John"
saNames(0, 1) = "Smith"
saNames(1, 0) = "Tom"
saNames(1, 1) = "Brown"
saNames(2, 0) = "Sue"
saNames(2, 1) = "Thomas"
saNames(3, 0) = "Jane"

saNames(3, 1) = "Jones"
saNames(4, 0) = "Adam"
saNames(4, 1) = "Johnson"

' Fill A2:B6 with an array of values (First and Last Names).
oSheet.Range("A2", "B6").Value = saNames

' Fill C2:C6 with a relative formula (=A2 & " " & B2).
oRng = oSheet.Range("C2", "C6")
oRng.Formula = "=A2 & "" "" & B2"

' Fill D2:D6 with a formula(=RAND()*100000) and apply format.
oRng = oSheet.Range("D2", "D6")
oRng.Formula = "=RAND()*100000"
oRng.NumberFormat = "$0.00"

' AutoFit columns A:D.
oRng = oSheet.Range("A1", "D1")
oRng.EntireColumn.AutoFit()

' Manipulate a variable number of columns for Quarterly Sales Data.
Call DisplayQuarterlySales(oSheet)

' Make sure Excel is visible and give the user control
' of Excel's lifetime.
oXL.Visible = True
oXL.UserControl = True

' Make sure that you release object references.
oRng = Nothing
oSheet = Nothing
oWB = Nothing
oXL.Quit()
oXL = Nothing

Exit Sub
Err_Handler:
MsgBox(Err.Description, vbCritical, "Error: " & Err.Number)
End Sub

Private Sub DisplayQuarterlySales(ByVal oWS As Excel.Worksheet)
Dim oResizeRange As Excel.Range
Dim oChart As Excel.Chart
Dim oSeries As Excel.Series
Dim iNumQtrs As Integer
Dim sMsg As String
Dim iRet As Integer


' Determine how many quarters to display data for.
For iNumQtrs = 4 To 2 Step -1
sMsg = "Enter sales data for" & Str(iNumQtrs) & " quarter(s)?"
iRet = MsgBox(sMsg, vbYesNo Or vbQuestion _
Or vbMsgBoxSetForeground, "Quarterly Sales")
If iRet = vbYes Then Exit For
Next iNumQtrs

' Starting at E1, fill headers for the number of columns selected.
oResizeRange = oWS.Range("E1", "E1").Resize(ColumnSize:=iNumQtrs)
oResizeRange.Formula = "=""Q"" & COLUMN()-4 & CHAR(10) & ""Sales"""

' Change the Orientation and WrapText properties for the headers.
oResizeRange.Orientation = 38
oResizeRange.WrapText = True

' Fill the interior color of the headers.
oResizeRange.Interior.ColorIndex = 36

' Fill the columns with a formula and apply a number format.
oResizeRange = oWS.Range("E2", "E6").Resize(ColumnSize:=iNumQtrs)
oResizeRange.Formula = "=RAND()*100"
oResizeRange.NumberFormat = "$0.00"

' Apply borders to the Sales data and headers.
oResizeRange = oWS.Range("E1", "E6").Resize(ColumnSize:=iNumQtrs)
oResizeRange.Borders.Weight = Excel.XlBorderWeight.xlThin

' Add a Totals formula for the sales data and apply a border.
oResizeRange = oWS.Range("E8", "E8").Resize(ColumnSize:=iNumQtrs)
oResizeRange.Formula = "=SUM(E2:E6)"
With oResizeRange.Borders(Excel.XlBordersIndex.xlEdgeBottom)
.LineStyle = Excel.XlLineStyle.xlDouble
.Weight = Excel.XlBorderWeight.xlThick
End With

' Add a Chart for the selected data.
oResizeRange = oWS.Range("E2:E6").Resize(ColumnSize:=iNumQtrs)
oChart = oWS.Parent.Charts.Add
With oChart
.ChartWizard(oResizeRange, Excel.XlChartType.xl3DColumn, , Excel.XlRowCol.xlColumns)
oSeries = .SeriesCollection(1)
oSeries.XValues = oWS.Range("A2", "A6")
For iRet = 1 To iNumQtrs
.SeriesCollection(iRet).Name = "=""Q" & Str(iRet) & """"
Next iRet
.Location(Excel.XlChartLocation.xlLocationAsObject, oWS.Name)
End With

' Move the chart so as not to cover your data.
With oWS.Shapes.Item("Chart 1")
.Top = oWS.Rows(10).Top
.Left = oWS.Columns(2).Left
End With

' Free any references.
oChart = Nothing
oResizeRange = Nothing
End Sub


7. 將下列程式碼新增至 Form1.vb 頂端::Imports Microsoft.Office.Core



測試自動化用戶端
1. 按下 F5 以建置並執行程式。.
2. 在表單, 按一下 Button 1 。 這個程式會啟動 Excel 並填入新的工作表上的資料。
3. 當出現提示要輸入每季的銷售資料, 請按一下 [ 是 ] 。 一個圖表為連結至每季的資料加入至工作表。

2008年5月1日 星期四

Word 開啟文件自動執行

Sub AutoOpen()