• 沒有找到結果。

第六章資料處理類別介紹

N/A
N/A
Protected

Academic year: 2021

Share "第六章資料處理類別介紹"

Copied!
48
0
0

加載中.... (立即查看全文)

全文

(1)

第六章資料處理類別介紹

6.1 VB200X序列資料庫物件關聯圖 2

6.2 引入資料處理類別 4

6.3 建立連線 4

6.3.1 屬性說明 5

6.3.2 選項參數說明 5

6.3.3 相關語法 6

6.4 資料處理 6

6.4.1 執行SQL指令 6

6.4.2 讀取資料表紀錄 7

6.4.3 使用ADODB類別與方法讀取紀錄 7

6.4.4 表列紀錄 9

6.4.5 DataGridView常用屬性 11

6.4.6 動態設定DataGridView表格及加入資料 12 6.4.7 取出 DataGridView表格資料 13

6.4.8 排序 14

6.4.9 過濾紀錄 14

6.4.10 關聯查詢 14

6.4.11 逐筆處理資料 14

6.4.12 動態產生記憶體資料表 18

6.4.13 BLOB 檔案處理 19

6.5 匯出檔案 22

6.5.1 資料表定義匯出為SQL指令 22

6.5.2 資料表紀錄匯出為SQL指令 23

6.5.3 資料表紀錄匯出為XML格式 25

6.6 交易機制處理指令 25

6.6.1 交易機制處理指令一 25

6.6.2 交易機制處理指令二 27

6.6.3 交易機制處理指令三 27

6.6.4 資料表上鎖 27

6.6.5 批次方式執行轉檔交易 28

6.7 動態表單 29

6.7.1 前置作業 29

6.7.2 程式設計 31

6.7.3 應用範例 37

6.8 報表設計技巧 37

6.8.1 前置作業 37

(2)

6.8.2 程式設計 38

6.9 條碼製作技巧 43

6.9.1 加入條碼控制項 44

6.9.2 條碼列印 46

回目錄

(3)

第六章資料處理類別介紹

本章介紹以 VB 程式語言來開發資料庫應用系統之技巧,此外也將詳細解說 各種資料處理物件之相關屬性和方法。

6.1 VB200X 序列資料庫物件關聯圖

Database

Connection

Command DataReader

Windows 控制項 TextBox

SQL Command

DataAdapter

DataSet DataTable

DataView

Windows 控制項 TextBox BindingSource BindingNavigator CommandBuilder DataGridView ADODB

ODBC Driver Database

Database

Connection

Command DataReader

Windows 控制項 TextBox

SQL Command

DataAdapter

DataSet DataTable

DataView

Windows 控制項 TextBox BindingSource BindingNavigator CommandBuilder DataGridView ADODB

ODBC Driver

圖 6.1 資料庫物件關聯圖

上圖說明 MySQL 資料庫使用到的類別及相關物件之關係,引用物件時,須 按照上圖連線之箭頭方向依序引用。

類別:System.Data.Odbc 物件:

OdbcConnection:資料庫連接器,用途為與伺服端資料庫之連線。

OdbcCommand:SQL 指令處理器,將主控端 SQL 指令送往伺服端處理。

OdbcDataReader:前導型資料讀取器,逐筆讀取開啟之資料表紀錄。

OdbcDataAdapter:資料表橋接器,透過開啟之連線,建立資料表在伺服端與 主控端之橋接機制,並將取得的資料表加入記憶體資料 庫。

OdbcCommandBuilder:資料表更新處理器,建立橋接資料表資料更新機制,

諸如新增、修改及刪除等作業。

ADODB:使用 ADO 類別與方法處理紀錄集。

通用型資料處理物件:

DataSet:記憶體資料庫,用於存放以橋接器連接之資料表。

DataTable:記憶體資料表,將記憶體資料表轉成可前後移動紀錄指標之資料 表,此資料表可用於新增、修改及刪除等用途。

DataView:視界型資料表,將DataTable轉成視界,視界型資料表可排 ↑H

(4)

序及設定過濾條件,並與 DataGridView 控制項結合,使得資料瀏 覽更加方便。

BindingSource:資料來源,將記憶體資料庫轉成可與其它控制項結合之資料 來源。

BindingNavigator:紀錄導覽器,建立來源資料之紀錄導覽按鈕。

ODBC Driver:作為應用系統在 Windows 平台與 MySQL 間之溝通驅動程式。

6.2 引入資料處理類別

在表單程序區前端加入下述指令,引入資料處理類別後,才可以在表單程序 內叫用相關物件及方法。

Imports System.Data.Odbc Imports System

Imports Microsoft.VisualBasic 6.3 建立連線

可在模組區建立公用連線方法,開啟表單時,可叫用此方法來開啟連線。本 書將其命名為openCon,程式內容如下:

Public Sub openCon(ByVal dbStr As String) Try

Dim opValue As Long Dim str As String

opValue = 1 + 2 + 8 + 32 + 16384,說明:通用型選項參數值

str = "DRIVER={MySQL ODBC " & DRV & " Driver};SERVER=" & HST & ";

DATABASE=" & dbStr & ";UID=" & USR & ";PASSWORD=" & PSW &

";Option= " & opValue

myCon = New OdbcConnection(str)

If Not myCon.State = ConnectionState.Open Then myCon.Open() 說明:若須處理中文資料,則須加入下列程式。

If myCon.State = ConnectionState.Open Then str = "Set character_set_client = big5;"

說明:MySQL指令

myCmd = New OdbcCommand(str, myCon) myCmd.ExecuteNonQuery()

str = "Set character_set_results= big5;"

說明:MySQL指令

myCmd = New OdbcCommand(str, myCon) myCmd.ExecuteNonQuery()

str = "Set character_set_connection = big5;" ↑H

(5)

說明:MySQL指令

myCmd = New OdbcCommand(str, myCon) myCmd.ExecuteNonQuery()

End If

Catch ex As Exception MsgBox(ex.Message) End Try

End Sub 6.3.1 屬性說明

粗斜體字部份必須由讀者自己輸入,通常可透過登錄表單來給值,相關變數 用途說明如下。可在完成登錄資料輸入後,叫用 openCon 來開啟連線。

DRV:驅動程式版本序號。

HST:主機 IP。

dbStr:資料庫名稱。

USR:帳號。

PSW:密碼。

opValue:資料處理方法設定值,詳細內容請參閱下節說明。

6.3.2 選項參數說明

有關連線參數 Option 之各種設定值,代表意義請參看表 6.1 之說明。

MySQL 推薦之預設值,請參照表 6.2 說明。其中數值 3,對照表 6.1 內並 沒有 3 這個參數選項,其實它是”1+2”之組合值,代表數值 1 和 2 之選項 組合。

表 6.1 Option參數對照表 ↑H 數值 說 明

1 欄寬不做最佳化處理 2 傳回匹配紀錄值

4 紀錄驅動程式動作在 c:\myodbc.log 檔 8 允許大型資料表

16 連線時不提示 32 允許動態游標

64 忽略 db_name.tbl_name.col_name 格式 128 使用驅動程式管理員游標

256 不允許結果存在近端 512 字元欄位完整呈現

1024 以 SQLDescribeCol()型式傳回資料表名

(6)

2048 使用壓縮協定

4096 忽略函數括弧前後之空白字元 8192 NT 系統以 named pipes 連線 16384 長整數型轉型為整數型

32768 以帳號取代 Table_qualifier 和 Table_owner 65536 從 my.cnf 讀取 [client] 和 [odbc] 群組設定值 131072 安全檢查 (最好不設定,除非發生問題)

262144 不允許交易機制

524288 允許查詢記錄在 c:\myodbc.sql (只允許在 debug 模 式)

1048576 查詢結果不做快取(只允許 Forward-only 游標) 2097152 強制使用 Forward-only 游標

表 6.2 MySQL 推薦參數

系 統 規 劃 Option

Access 3

Visual Basic 3

大型資料表包含大量紀錄 2049

追蹤紀錄(除錯模式) 4

記錄查詢結果 (除錯模式) 524288

追蹤紀錄及查詢結果(除錯模式) 524292

大型資料表無快取 3145731

6.3.3 相關語法

建立連線物件:New OdbcConnection(str),str為連線參數。

開啟連線:連線物件.Open() 處理中文資料(SQL指令):

上傳資料:Set character_set_client = big5;

回傳結果:Set character_set_results= big5;

連線過程信息:Set character_set_connection = big5;

6.4 資料處理

6.4.1 執行 SQL 指令

使用OdbcCommand物件來執行SQL指令,此物件可與伺服端紀錄集連線,

但是不取出結果。

myCmd = New OdbcCommand(strSQL, myCon) ↑H

(7)

myCmd.ExecuteNonQuery() 相關語法

建立處理物件:New OdbcCommand(strSQL, myCon) 引數一:SQL指令,範例: Select * From myTable;

引數二:連線物件

執行SQL指令:SQL指令物件.ExecuteNonQuery() 6.4.2 讀取資料表紀錄

使用OdbcDataReader物件來讀取紀錄。

建立OdbcDataReader物件

Dim tblReader As OdbcDataReader 建立SQL指令物件

strSQL = "Select * From myTable;"

myCmd = New OdbcCommand(strSQL, myCon) 建立紀錄讀取物件

tblReader = myCmd.ExecuteReader() 逐筆讀取紀錄

While tblReader.Read

For i = 0 To tblReader.FieldCount -1

vl = tblReader.Item(i).ToString,說明:取出第 i 欄資料 Nest i

End While 關閉物件

tblReader.Close()

說明:OdbcDataReade.Read 方法只能往前讀取紀錄。

取出之 vl 可轉存至其它控制項或與記憶體變數進行運算,例如:

txtName.text = tblReader.Item(1).ToString

OdbcDataReader 可使用 HasRows 屬性來判斷取得的資料表有無紀錄,若 包含紀錄則傳回 True。

6.4.3 使用 ADODB 類別與方法讀取紀錄

ADODB類別與方法可使用程式碼來處理資料表之新增、修改、刪除及轉檔 工作。下述程式示範連線、開啟紀錄集,以及逐筆處理紀錄。

宣告連線物件 ↑H

(8)

Dim con As New ADODB.Connection 宣告紀錄集物件

Dim rs As New ADODB.Recordset 定義連線屬性

Dim MysqlSTR As String

MysqlSTR = "DRIVER={MySQL ODBC 3.51 Driver}; SERVER=localhost;

DATABASE=mysal; USER=UserAccount; PASSWORD=XXXX; OPTION=3"

設定連線屬性

con.ConnectionString = MysqlSTR 開啟連線

con.Open() 設定SQL指令

Dim strSQL As String

strSQL = "Select * from Bkicbl"

開啟紀錄集

rs.Open(strSQL, con, 2, 4) 逐筆讀取全部紀錄

Do While Not rs.EOF

vl = rs(0).Value ,說明:取出欄位資料 rs.MoveNext()

Loop rs.Close 說明:

ADODB類別事前須先引入專案才可使用,引入步驟如下:

z 啟動表單在設計模式

z 下拉專案功能表,然後點擊【加入參考】功能,當開啟【加入參考】對 話表單後,點選【COM】及捲動清單至【MicroSoft Active Data Objects 2.8 Library】,按下【確定】,即可加入此類別。

RecordSet相關方法與屬性使用說明:

Open 方法傳入引數說明 引數一:SQL 指令,

引數二:開啟之 ODBC 連線,

引數三:紀錄集開啟模式,代表值如下:,

0: adOpenForwardOnly, ↑H

(9)

1: adOpenKeySet, 2: adOpenDynamic, 3: adOpenStatic

引數四:紀錄集鎖定模式,代表值如下:,

1: adLockReadOnly, 2: adLockPessimistic, 3: adLockOptimistic, 4: adLockBatchOptimistic EOF:判斷是否已至檔案末端,

BOF:判斷是否已至檔案頂端,

Close:關閉紀錄集,

AddNew:新增一筆空紀錄,

Delete:刪除紀錄,

Update:更新紀錄,使用時機為修改紀錄或新增紀錄後;Delete方法不須搭 配Update方法。

取值:可使用下列方法:

傳入欄位註標(從0開始起算):rs(i).Value 傳入欄位名稱: rs(“欄名”).Value。

給值:可使用下列方法 rs(i).Value = 值

rs(“欄名”).Value = 值。

移動紀錄指標:

首筆:rs.MoveFirst 次筆:rs.MoveNext 前筆:rs.MovePrevious 次筆:rs.MoveLast

過濾紀錄:rs.Filter =“欄名 = 欄值 [And | Or ….]”。

釋放過濾條件:rs.Filter = “”。

6.4.4 表列紀錄

下述範例是以視界形式顯示紀錄,可搭配DaGridView來展示多筆紀錄。

Dim ds As New DataSet

Dim da As New OdbcDataAdapter(SQL, myCon) Dim daView As DataView

Dim tbl As DataTable

da.Fill(ds, "qryTable") ↑H

(10)

說明:將連線資料表加入記憶體資料庫,並將資廖表取明為qryTable。

tbl = ds.Tables("qryTable")

說明:將記憶體資料表轉為DataTable物件。

daView = tbl.DefaultView

說明:將 DataTable 物件轉為視界型資料表。

DataGridView1.DataSource = daView1 說明:將視界型資料表連結至表格物件。

語法說明

OdbcDataAdapter(資料表橋接器)引數說明:

引數一:SQL指令 引數二:連線物件

OdbcDataAdapter須使用Fill方法將所取得的伺服端資料表加入記憶體資料庫,語 法如下:

da.Fill(ds, "qryTable")

記憶體資料庫可使用下述指令轉成記憶體資料表:

tbl = ds.Tables("qryTable")

記憶體資料表可使用下述指令取得相關資料:

取得紀錄筆數: rn = tbl.Rows.Count 取得欄位個數: fln = tbl.Columns.Count

取得欄位名稱: na = tbl.Columns(i).ColumnName 取得第 i 筆第 j 欄值:vl = tbl.Rows(i).Item(j)

若使用 ADODB 之 RecordSet 取得來源資料,可使用下述指令加入記憶體資料庫。

da.Fill(ds, myRs, "qryTable"),說明:myRs為ADODB之RecordSet 6.4.4.1 取出資料錄

下述程式示範如何取出資料表紀錄。

Dim dRow As DataRow dRow = tbl.Rows(n)

說明:n表第幾筆紀錄,從0起算

Me.BK_BLNO.Text = dRow("BK_BLNO")

說明:取值並存入文字方塊,dRow引數可使用註標變數或使用欄名。

vl = dRow.Item(0).ToString()

說明:取出欄值並存入記憶體變數,0表第一欄 6.4.4.2 取出視界資料表紀錄

視界資料表可使用下述指令取得相關資料: ↑H

(11)

daView(n).Item(j) .ToString

說明:傳入欄位註標,n為紀錄序,j為欄序。

daView(n).Item(“欄名”) .ToString 說明:傳入欄位名稱。

6.4.4.3 取得欄位資料型態

下述程式示範如何取出資料表欄位型態,以SQL指令新增或修改資料時,必 須依欄位型態來組合SQL。

daType = tbl.Rows(0).Item(i).GetType.ToString 傳回結果:

System.Char/ System.String:字元型 System.Boolean:布林型

System.Byte/ System.SByte:位元組型 System.DateTime:日期時間

System.Decimal/ System.Double/ System.Single:實數型 System.Int16/ System.Int32/ System.Int64:整數型

System.Uint16/ System.Uint32/ System.Uint64:無號整數型

組合SQL時,日期及字元型欄位必須在取得的控制項資料前後加上引號,製 作過濾條件時亦同。

範例:strFilter = "BK_BLNO =’" & txtNo.Text & "’"

6.4.5 DataGridView常用屬性

下述程式示範DataGridView控制項之用法。

DataGridView1.DataSource = Nothing,說明:釋放原資料來源 DataGridView1.Refresh()

DataGridView1.DataSource = daView,說明:設定連結資料來源 6.4.5.1 語法說明

ColumnIndex:取得目前游標位置欄註標

curCI = DataGridView1.CurrentCell.ColumnIndex CurrentRow.Index:取得目前游標位置列註標

curRI = DataGridView1.CurrentRow.Index Cells(ci).Value:取得目前游標位置欄值

VL =DataGridView1.CurrentRow.Cells(ci).Value Name:取得目前游標位置之欄名

NA = DataGridView1.Columns(ci).Name ↑H

(12)

Frozen:凍結欄位

DataGridView1.Columns(1).Frozen = True DefaultCellStyle.Format:格式化資料

DataGridView1.Columns(i).DefaultCellStyle.Format = "yyyy/M/d H:mm:ss"

HeaderText:設定欄位抬頭

DataGridView1.Columns(i).HeaderText = “欄位抬頭”

ValueType.:取得欄位型態

ftp = DataGridView1.Columns(i).ValueType.ToString DefaultCellStyle.Alignment:設定欄位對齊方式

DataGridView1.Columns(i).DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleRight

6.4.5.2 應用範例

DataGridView控制項應用範例如下圖。

圖 6.2 DataGridView 控制項應用範例 6.4.6 動態設定 DataGridView 表格及加入資料

下述程式示範以動態方式(在執行階段)將資料加入 DataGridView 控制項,

請預先在表單內加入 DataGridView 控制項並取名為 dataGridView1。

Private Sub CreateDataGridView()

dataGridView1.ColumnCount = 4 ,說明:設定欄數

dataGridView1.ColumnHeadersVisible = True ,說明:設為可見 設定欄位抬頭樣式.

Dim columnHeaderStyle As New DataGridViewCellStyle() columnHeaderStyle.BackColor = Color.Beige

columnHeaderStyle.Font = New Font("Verdana", 10, FontStyle.Bold) dataGridView1.ColumnHeadersDefaultCellStyle = columnHeaderStyle 設定欄名.

dataGridView1.Columns(0).Name = "Recipe ↑H

(13)

dataGridView1.Columns(1).Name = "Category"

dataGridView1.Columns(2).Name = "Main Ingredients"

dataGridView1.Columns(3).Name = "Rating"

加入紀錄.

Dim row1() As String = {"Meatloaf", "Main Dish", "ground beef", "**"}

Dim row2() As String = _

{"Key Lime Pie", "Dessert", "lime juice, evaporated milk", "****"}

Dim row3() As String = {"Orange-Salsa Pork Chops", "Main Dish", _ "pork chops, salsa, orange juice", "****"}

Dim row4() As String = {"Black Bean and Rice Salad", "Salad", _ "black beans, brown rice", "****"}

Dim rows() As Object = {row1, row2, row3, row4 } Dim rowArray As String()

For Each rowArray In rows

dataGridView1.Rows.Add(rowArray) Next rowArray

End Sub

6.4.7 取出 DataGridView表格資料

以下程式為點擊DataGridView1控制項時,取出當筆紀錄內含鍵值欄資料。

Private Sub DataGridView1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles DataGridView1.Click

Try

Dim fi As Integer

If DataGridView1.CurrentRow.Index >= rn Then Exit Sub 說明:rn, 事先取得之紀錄總數

curCI = DataGridView1.CurrentCell.ColumnIndex curRI = Me.DataGridView1.CurrentRow.Index If curCI = 0 Then

For fi = 0 To UBound(tbl.Columns.Count-1) If tbl.Columns(fi).Name = keyField1 Then 說明:取出第一鍵值

KVL1 = Me.DataGridView1.CurrentRow.Cells(fi).Value End If

If tbl.Columns(fi).Name = keyField2 Then 說明:取出第二鍵值(若有兩個主鍵時)

KVL2 = Me.DataGridView1.CurrentRow.Cells(fi).Value ↑H

(14)

End If Next End If

Catch ex As Exception MsgBox(ex.Message) End Try

End Sub

此範例程式可應用於全螢幕編修紀錄,修改紀錄前,先點擊DataGridView鍵 值欄控制項來取得鍵值。修改紀錄後,再搭配下列方法來組合SQL指令,然後執 行該指令以修改紀錄。

strSQL = "Update 資料表名 Set "

For fi = 0 To UBound(tbl.Columns.Count-1)

strSQL= strSQL & tbl.Columns(fi).Name & "= " &

DataGridView1.CurrentRow.Cells(fi).Value & ","

Next

strSQL = Mid(strSQL, 1, Len(strSQL)-1) & " Where 過濾條件; "

myCmd = New OdbcCommand(strSQL, myCon) myCmd.ExecuteNonQuery()

6.4.8. 排序

可搭配視界資料表將紀錄排序。

daView1.Sort = "欄名 ASC | DESC [, 第二排序欄位] "。

6.4.9 過濾紀錄

可搭配視界資料表來過濾紀錄。

daView.RowFilter = "欄名 = 欄值 [And | Or ….] "。

6.4.10 關聯查詢

進階應用-以關聯方式查詢兩個資料表,當主資料表紀錄變更時,可同步顯 示子資料表之關聯紀錄。處理方法如下:

¾ 主表以逐筆方式顯示,當紀錄指標移動時,同步取出鍵值並置入表單對應之 文字方塊內。

¾ 設定文字方塊資料變更事件程序 (TextChanged 事件),當資料變更時,將子 資料表之 DataView 重設為 daView.RowFilter = "過濾字串"。

¾ 將連結子資料表之 DataGridView.DataSource 重新設為 daView。

6.4.11 逐筆處理資料 ↑H

(15)

6.4.11.1 搭配紀錄導覽器及控制項

下述程式示範以紀錄導覽器來移動紀錄指標,須在表單內加入紀錄導覽器控 制項,並取名為BindingNavigator1。

宣告物件

Dim bindSRC As BindingSource Dim bindADP As OdbcDataAdapter Dim bindTBL As DataTable

Dim ds As DataSet

Dim builder As OdbcCommandBuilder Dim daView1 As DataView

Dim tbl As DataTable, mKey(0) as DataColumn ds = New DataSet("ds")

定義SQL

strSQL =以 Select 前導之SQL 指令 mKey(0) = 主鍵

建立資料物件

bindADP = New OdbcDataAdapter(strSQL, myCon) 說明:建立資料庫橋接器

bindSRC = New BindingSource 說明:建立表單連結資料來源物件 bindADP.Fill(ds, “給定資料表名”)

說明:資料表填入資料庫橋接器 bindTBL = ds.Tables(“給定資料表名”)

說明:建立連結資料表物件 bindSRC.DataSource = ds

說明:建立資料來源物件

bindSRC.DataMember = “給定資料表名”

說明:設定表單連結資料來源 bindTBL.PrimaryKey = mKey

說明:設定連結資料表主鍵

BindingNavigator1.BindingSource = bindSRC 說明:設定紀錄導覽器資料來源

tbl = ds.Tables(“給定資料表名”) fln = tbl.Columns.Count

說明:取得連結資料表之欄位數 定義輸入法

Dim ime1, ime2, ime3 As ImeMode ↑H

(16)

ime1 = Windows.Forms.ImeMode.Alpha 說明:英數

ime2 = Windows.Forms.ImeMode.Off 說明:關閉輸入法

ime3 = Windows.Forms.ImeMode.On 說明:中文半形

設定控制項屬性並連結資料來源 控制項.ImeMode = ime1

說明:設定控制項輸入法 控制項.Name = 連結資料表欄名

說明:設定控制項名稱

控制項名.DataBindings.Add(New Binding("Text", bindSRC, 欄名, True)

說明:連結控制項來源資料,若為日期型欄位,引數"Text"須改為"Value"。

紀錄導覽器及控制項應用範例 應用範例如下圖。

紀錄導覽器

文字方塊

DataGridView:關聯查詢 紀錄導覽器

文字方塊

DataGridView:關聯查詢 紀錄導覽器

文字方塊

DataGridView:關聯查

圖 6.3 紀錄導覽器控制項 6.4.11.2 搭配 DataTable

下述程式示範以DataTable物件來增修紀錄。

宣告及建立物件

ds = New DataSet("ds")

strSQL : Select 前導之SQL 指令

bindADP = New OdbcDataAdapter(strSQL, myCon) 說明:建立資料庫連接器

bindADP.Fill(ds, “給定資料表名”) 說明:資料表填入資料庫連接器 bindTBL = ds.Tables(“給定資料表名”)

說明:建立連結資料表物件 ↑H

(17)

rn = bindTBL.Rows.Count 說明:取得紀錄筆數 fn = bindTBL.Columns.Count 逐筆處理紀錄

For i =0 To rn -1 說明:逐筆

For j = 0 To fn -1 說明:逐欄

vl = bindTBL.Rows(i).Item(j).ToString 說明:取得欄位資料‘

Next j Next i

6.4.11.3 新增、修改及刪除紀錄

以DataTable物件來增修紀錄時,須搭配OdbcCommandBuilder物件。

builder1 = New OdbcCommandBuilder(da1) bindSRC.DataSource = dsT

bindSRC.DataMember = wkTBL tbl = dsT.Tables(wkTBL)

daView = New DataView(tbl) 過濾紀錄

daView.RowFilter = ""

說明:釋放過濾條件 daView.RowFilter = keyVL

說明:過濾紀錄 刪除紀錄指令

daView.Delete

說明:刪除紀錄前,須使用 RowFilter 過濾指定鍵值之紀錄。

新增紀錄指令

Dim row As DataRowView = daView.AddNew 說明:新增紀錄

row.BeginEdit()

說明:開啟編輯功能 For j = 0 To fn -1 row(j) = 資料

Next j ↑H

(18)

row.EndEdit()

說明:結束編輯功能 修改紀錄指令

Dim row As DataRowView For Each row In daView

row.BeginEdit()

說明:開啟編輯功能 vl = row(fi)

說明:取值,fi表欄位序號 row(fi) = vl

說明:給值 row.EndEdit()

說明:結束編輯功能 Next

將修改紀錄存回資料庫 Me.Validate()

bindSRC.EndEdit() bindADP.Update(tbl)

6.4.11.4 設定控制項連結資料來源欄位

設定控制項連結資料來源欄位之語法如下:

控制項.DataBindings.Add(New Binding("Text", bindSRC, 欄名, True)) 6.4.11.5 批次更新連結資料表紀錄

開啟表單時, 須先建立紀錄更新物件 OdbcCommandBuilder,指令如下:

builder = New OdbcCommandBuilder(bindADP)

然後使用指令按鈕來執行下述指令,也可以將下述指令放在 FormClosed 事 件內。

Me.Validate() bindSRC.EndEdit()

bindADP.Update(bindTBL) 6.4.12 動態產生記憶體資料表

下述程式示範以動態方式產生記憶體資料表、加入資料及顯示。

Dim staTbl As DataTable = New DataTable("StaTable")

Dim daview As DataView ↑H

(19)

Dim column As DataColumn Dim row As DataRow 定義欄位屬性

column = New DataColumn()

column.DataType = System.Type.GetType("System.String") 'System.Single column.ColumnName = "Item"

將欄位加入資料表

staTbl.Columns.Add(column) column = New DataColumn()

column.DataType = System.Type.GetType("System.Single") column.ColumnName = "Value"

staTbl.Columns.Add(column) 新增紀錄

row = staTbl.NewRow() row(0) = "筆數"

row(1) = st.RecNo 紀錄加入資料表

staTbl.Rows.Add(row) 定義第二筆紀錄

row = staTbl.NewRow() row(0) = "合計"

row(1) = st.Sum 紀錄加入資料表

staTbl.Rows.Add(row) 連結資料表至 DataGridView

daView = staTbl.DefaultView

DataGridView1.DataSource = daView 6.4.13 BLOB 檔案處理

6.4.13.1 上傳檔案

下述程式可將主控端二進制檔案上傳至伺服端,必須在表單程序前引入 System.IO類別,以及在表單程序宣告下列物件變數。

Dim boCON As New ADODB.Connection

Dim boRS As New ADODB.Recordset ↑H

(20)

建立檔案物件

Dim stream As FileStream 說明:宣告檔案物件 Dim reader As BinaryReader

說明:宣告位元資料讀取物件

stream = New FileStream(fna, FileMode.Open, FileAccess.Read) 說明: fna表Client 端 BLOB含路徑檔名

reader = New BinaryReader(stream)

Dim photo() As Byte = reader.ReadBytes(stream.Length) reader.Close()

stream.Close() 開啟連線

opValue = 3

str = "DRIVER={MySQL ODBC " & DRV & " Driver};SERVER=" & boHost & ";

DATABASE=" & dbStr & ";UID=" & USR & ";PASSWORD=" & PSW &

";Option= " & opValue boCON.ConnectionString = str boCON.Open()

開啟紀錄集

strSQL= "Select * From TempTable"

說明:TempTable,內含 BLOB 欄位之範例資料表

boRS.CursorLocation = ADODB.CursorLocationEnum.adUseClient boRS.Open(strSQL, boCON, ADODB.CursorTypeEnum.adOpenDynamic,

ADODB.LockTypeEnum.adLockOptimistic) 將檔案物件存入伺服端資料表

boRS.Fields(0).Value = cna

boRS.Fields(1).AppendChunk(photo) 說明:此欄型態必需是 BLOB。

boRS.Update() boRS.Close()

將資料表二進制欄資料轉存至伺服端指名檔案

cmd = "Select ObjectFile Into Dumpfile '" & cna & "' From TempTable"

說明:cna 表 Server 端 BLOB含路徑檔名, 路徑符號必須使用 / ObjectFile : BLOB欄位

boCON.Execute(cmd)

6.4.13.2 下載BLOB檔案 ↑H

(21)

下述程式可將伺服端二進制檔案下載至主控端,必須在表單程序前引入 System.IO類別,以及在表單程序宣告下列物件變數。

Dim dnCON As New ADODB.Connection Dim dnRS As New ADODB.Recordset 開啟連線

opValue = 3145731

說明: 下載時必須使用此值。

str = "DRIVER={MySQL ODBC " & DRV & " Driver};SERVER=" & HST & ";

DATABASE=" & dbStr & ";UID=" & US遠項R & ";PASSWORD=" & PSW &

";Option= " & opValue dnCON.ConnectionString = str dnCON.Open()

載入二進制檔至暫存表

cmd = "Update TempTable Set ObjectName='" & fna & "', ObjectFile=

Load_File('" & fna & "');"

dnCON.Execute(cmd)

說明:Load_File()為MySQL函數,可用於載入伺服端檔案至資料表指名欄位 開啟紀錄集

strSQL= "Select * From TempTable Where ObjectName='" & fna & "'"

dnRS.Open(strSQL, dnCON, 2, 4) lngImageSize = dnRS("ObjectFile").ActualSize If My.Computer.FileSystem.FileExists(fna) Then

My.Computer.FileSystem.DeleteFile(fna) End If

設定資料處理區塊大小

Dim lngImageSize As Long = 0 Dim lngOffset As Long = 0 Dim bytChunk() As Byte Const conChunkSize = 128 建立檔案物件

Dim stream As FileStream Dim writer As BinaryWriter

stream = New FileStream(cna, FileMode.OpenOrCreate, FileAccess.Write) writer = New BinaryWriter(stream)

將連線紀錄集資料逐段轉入主控端檔案物件

Do While lngOffset < lngImageSize ↑H

(22)

bytChunk = dnRS("ObjectFile").GetChunk(conChunkSize) writer.Write(bytChunk)

writer.Flush()

lngOffset = lngOffset + conChunkSize Loop

關閉物件 writer.Close() stream.Close() dnRS.Close()

註 1:大型 Text 檔案,諸如 Word 檔案、PowerPoint 檔都可使用此方法來上傳 和下載。

註 2:主控端連線環境變數 Max_allowed_Packet 須設為 16777216,可在 my.ini 檔指定下列敘述:

Max_allowed_Packet = 16777216 6.5 匯出檔案

6.5.1 資料表定義匯出為 SQL 指令

下述程式用於匯出資料表定義為 SQL 指令 宣告及建立物件

Dim daReader As OdbcDataReader

Dim cmd As String, fstr() As String, str As String

cmd = "Show Create Table 資料表名" ,說明:MySQL指令 myCmd = New OdbcCommand(cmd, myCon)

daReader = myCmd.ExecuteReader() 讀取SQL定義

Do While daReader.Read()

cmd = daReader.Item(1).ToString Exit Do

Loop

daReader.Close() 轉換換行符號

fstr = Split(cmd, vbLf) For i = 0 To UBound(fstr) - 1 str = str & fstr(i) & vbCrLf

Next ↑H

(23)

將讀取結果存檔

My.Computer.FileSystem.WriteAllText(存檔檔名, str, False, System.Text.Encoding.Default)

6.5.2 資料表紀錄匯出為 SQL 指令

下述程式用於匯出資料表紀錄為 SQL 指令。

宣告及建立物件

Dim cmd As String, fstr() As String

Dim str As String = "", tstr As String, dstr As String Dim dRow As DataRow, i As Integer

Dim ds As New DataSet, daTable As DataTable Dim vl

Dim rn As Long, fln As Integer, key As String = ""

Dim da As New OdbcDataAdapter(strSQL, myCon) da.Fill(ds, 資料表名)

daTable = ds.Tables(資料表名) rn = daTable.Rows.Count

fln = daTable.Columns.Count - 1 組合對應SQL指令

i = 0

str = "Use資料庫名;" & vbCrLf

說明:加入切換MySQL資料庫指令

str = str & "DROP TABLE IF EXISTS " & wkTBL & ";" & vbCrLf 說明:加入MySQL刪除資料表指令

str = str & fstr(UBound(fstr)) & ";" & vbCrLf & vbCrLf

str = str & "LOCK TABLES " & wkTBL & " WRITE;" & vbCrLf 說明:加入MySQL資料表上鎖指令

str = str & "INSERT INTO " & wkTBL & " Values" & vbCrLf 說明:加入MySQL資料表新增紀錄指令,wkTBL表資料表名 Dim ri As Long = 0, ftp As String = ""

For Each dRow In daTable.Rows dstr = "("

For i = 0 To fln

ftp = 取出第 i欄型態

以下程序用於轉換欄位資料格式 Select Case ftp

Case "Numeric" ↑H

(24)

dstr = dstr & " " & dRow.Item(i).ToString Case "Boolean"

dstr = dstr & " " & dRow.Item(i).ToString Case "Date", "DateTime", "Stamp"

vl = dRow.Item(i).ToString If Not IsDBNull(vl) Then vl = Now

vl = Replace(vl, "上午", "") vl = Replace(vl, "下午", "") vl = Replace(vl, " ", " ") End If

dstr = dstr & "'" & vl & "'"

Case "Binary", "BLOB"

dstr = dstr & "Null"

Case "String", "Enum"

dstr = dstr & "'" & dRow.Item(i).ToString & "'"

Case "Text"

vl = dRow.Item(i).ToString vl = Replace(vl, vbCrLf, "") vl = Replace(vl, vbLf, "") dstr = dstr & "'" & vl & "'"

Case Else

vl = dRow.Item(i).ToString dstr = dstr & vl

End Select If i < fln Then dstr = dstr & ","

Else

dstr = dstr & "),"

End If Next

ri += 1 ↑H

(25)

以下程序將讀取紀錄加入在SQL指令集內 If ri < rn Then

str = str & dstr & vbCrLf dstr = "("

Else

dstr = Mid(dstr, 1, Len(dstr) - 1) & ";"

str = str & dstr & vbCrLf dstr = ""

End If Next

str = str & "UNLOCK TABLES;" & vbCrLf 說明:加入MySQL解鎖指令

da.Dispose() ds.Clear() 將讀取結果存檔

My.Computer.FileSystem.WriteAllText(存檔檔名, str, False, & _ System.Text.Encoding.Default)

6.5.3 資料表紀錄匯出為 XML 格式

下述程式用於匯出資料表紀錄為 XML 格式。

宣告及建立物件

Dim ds As New DataSet, daTable As DataTable da = New OdbcDataAdapter(strSQL, myCon) da.Fill(ds, 資料表名)

daTable = ds.Tables(資料表名 L)

Dim mode As XmlWriteMode = XmlWriteMode.WriteSchema ds = daTable.DataSet

匯出紀錄

If fld = False Then '//不寫入欄位結構 ds.WriteXml(存檔檔名)

Else

ds.WriteXml(存檔檔名, mode) '//寫入欄位結構 End If

6.6 交易機制處理指令

6.6.1 交易機制處理指令一 ↑H

(26)

下列範例會建立 OdbcConnection 和 OdbcTransaction,它也示範如何使用 BeginTransaction、Commit 和 Rollback 方法。

Public Sub ExecuteTransaction(ByVal connectionString As String) Using connection As New OdbcConnection(connectionString)

說明:Using 宣告之物件, 當程序結束時物件即被釋放,不須使用 Close 方 法,connectionString:連線參數

Dim command As New OdbcCommand() Dim transaction As OdbcTransaction 說明:設定連線參數和物件 command.Connection = connection 說明:開啟連線並啟動交易機制.

Try

connection.Open()

說明:啟動區域型交易機制.

transaction = connection.BeginTransaction() 說明: 指派交易機制.

command.Connection = connection command.Transaction = transaction

說明:執行相關 SQL 指令(Insert 型或 Update 型).

command.CommandText = _

"Insert into 資料表 (….) VALUES (…')"

command.ExecuteNonQuery() command.CommandText = _

"Insert into 資料表 (….) VALUES (…')"

command.ExecuteNonQuery() transaction.Commit() '//確認交易 MsgBox("紀錄已回存至資料庫.") Catch ex As Exception

Console.WriteLine(ex.Message) 說明:發生錯誤時倒捲交易資料 Try

transaction.Rollback() Catch

End Try End Try End Using End Sub

↑H

(27)

6.6.2 交易機制處理指令二

Using updateTransaction As New Transactions.TransactionScope 執行 SQL 指令 1

執行 SQL 指令 2 ………..

updateTransaction.Complete() ,說明:確認交易 End Using

6.6.3 交易機制處理指令三

使用 MySQL 交易指令來處理交易,下列指令為 MySQL 指令,須搭配 OdbcCommand 物件方可執行。

START TRANSACTION;

SELECT @A:=SUM(salary) FROM table1 WHERE type=1;

UPDATE table2 SET summary=@A WHERE type=1;

COMMIT;

說明:確認 6.6.4 資料表上鎖

執行交易機制前資料表必須先鎖表,執行 Lock Tables 指令時,同一執行緒 被上鎖之資料表將自動被解鎖。

鎖表指令

單一資料表 : Lock Table TblName Read | Write;

多個資料表 : Locak Tables TblName1 Read | Write, TblName2 Read | Write...;

若一道 SQL 須開啟某個資料表多次, 則需要替該表另取別名,否則無法上鎖。

範例:

Lock Tables bkiclog Write, bkiclog As tmpbkiclog Write;

str = "LOCK TABLE " & wkTBL2 & " Write, " & wkTBL2 & " AS objTable Write, " & wkTBL & " Write;"

說明:objTable 為別名

myCmd = New OdbcCommand(str, srcCon) myCmd.ExecuteNonQuery()

trnSQL = "Insert Into " & wkTBL2 & "(" & cFLD & ") Select " & mFLD & "

From " & wkTBL & " Where (" & mFLD & ")"

trnSQL = trnSQL & " Not In (Select " & cFLD & " From " & wkTBL2 & " As objTable)" ↑H

(28)

myCmd = New OdbcCommand(trnSQL, objCon) myCmd.ExecuteNonQuery()

6.6.5 批次方式執行轉檔交易

執行轉檔交易時, 可使用批次方式以加快執行速度。

Step 1 首先定義當鍵值不存在時新增鍵值之 SQL 指令

trnSQL = "Insert Into " & wkTBL2 & "(" & cFLD & ") Select " & mFLD & "

From " & wkTBL & " Where (" & mFLD & ")"

trnSQL = trnSQL & " Not In (Select " & cFLD & " From " & wkTBL2 & " As objTable)"

myCmd = New OdbcCommand(trnSQL, objCon) myCmd.ExecuteNonQuery()

說明:cFLD 表子鍵,mFLD 表主鍵。

Step2 接著定義資料小計 SQL 指令 trnSQL = "Select " & mFLD For vi = skipN To endN mtp = wkType(vi - skipN) If mtp <> "取代" Then

trnSQL = trnSQL & ", Sum(" & fld(vi) & ") As " & fld(vi) Else

trnSQL = trnSQL & ", " & fld(vi) End If

Next

trnSQL = trnSQL & " From " & wkTBL & " Group By " & mFLD 說明:轉檔處理可區分為取代、累加和累減。

Step3 建立暫存表 - 依小計 SQL 指令

trnSQL = "Create Temporary Table updTable " & trnSQL myCmd = New OdbcCommand(trnSQL, objCon)

myCmd.ExecuteNonQuery() Step4 定義交易 SQL 指令

trnSQL = "Update " & wkTBL2 & ", updTable Set "

For vi = skipN To endN mtp = wkType(vi - skipN) If mtp = "累加" Then

trnSQL = trnSQL & wkTBL2 & "." & Trim(fld(vi)) & "=" & wkTBL2 & "."

& Trim(fld(vi)) & " + updTable." & Trim(tblStruct(vi).fldName) ↑H

(29)

ElseIf mtp = "累減" Then

trnSQL = trnSQL & wkTBL2 & "." & Trim(fld(vi)) & "=" & wkTBL2 & "."

& Trim(fld(vi)) & " - updTable." & Trim(tblStruct(vi).fldName) ElseIf mtp = "取代" Then

trnSQL = trnSQL & wkTBL2 & "." & Trim(fld(vi)) & "= updTable." &

Trim(tblStruct(vi).fldName) End If

If vi < endN Then trnSQL = trnSQL & ", "

Next

strJoin = wkTBL2 & "." & Trim(CKfld1) & "=" & "updTable." & Trim(Kfld1) If Kfld2 <> "" Then

strJoin = strJoin & " And " & wkTBL2 & "." & Trim(CKfld2) & " = updTable." & Trim(Kfld2)

End If

trnSQL = trnSQL & " Where " & strJoin

說明:不能使用 Inner Join 關聯指令,而必須改用 Where 形式來建立關 聯。

Step5 執行轉檔作業

myCmd = New OdbcCommand(trnSQL, objCon) myCmd.ExecuteNonQuery()

Step6 刪除暫存表

trnSQL = "Drop Temporary Table updTable"

myCmd = New OdbcCommand(trnSQL, objCon) myCmd.ExecuteNonQuery()

6.7 動態表單

本節示範動態表單之設計技巧。所謂動態表單,是指表單介面在設計階段未 將處理資料所需之控制項加入,而在啟動表單時,才依傳入之資料表或 SQL 指 令集內含之欄位加入合適的控制項,以及設定相關的屬性資料、事件程序和連結 資料來源。使用動態表單之優點,主要在於只要一個資料輸入介面即可滿足眾多 的資料表資料輸入作業需求,除了可縮減軟體所需空間,也可降低系統維護之困 難度。

6.7.1 前置作業 ↑H

(30)

6.7.1.1 上層表單

動態表單之產生乃依據傳入之來源資料表或 SQL 指令,因此需要一個能設 定來源資料之上層表單,以及一個能開啟動態表單之指令按鈕。本書使用下列公 用變數來傳遞相關來源資料。

wkTBL:主資料表

wkSQL:主 SQL(與 wkTBL 為二選一)

wkTBL2:子資料表(若需要以關聯方式輸入資料時)

wkSQL2:子 SQL(與 wkTBL2 為二選一)

6.7.1.2 動態表單

為了示範資料表之新增、修改、刪除及查詢功能,請在動態表單上加入相關 的控制項,如下列圖示:

¾ 紀錄導覽器(BindingNavigator)

¾ 指令按鈕-主資料表

圖 6.4 紀錄導覽器用圖說明

首筆 前筆 紀錄址器 次筆 末筆 新增 刪除 搜尋鍵值

紀錄導覽器 下拉方塊

首筆 前筆 紀錄址器 次筆 末筆 新增 刪除 搜尋鍵值

紀錄導覽器 下拉方塊

首筆 前筆 紀錄址器 次筆 末筆 新增 刪除 搜尋鍵值 首筆 前筆 紀錄址器 次筆 末筆 新增 刪除 搜尋鍵值

紀錄導覽器 下拉方塊

圖 6.5 主表指令按鈕 各按鈕之用途說明如下:

更新:將新增或編修紀錄存入資料表 取值:將表單上之資料存入記憶體 清空:將輸入方塊資料清除

填入:將記憶體資料置入對應輸入方塊 預設值:將預設值置入對應輸入方塊 查閱:查閱其它資料表紀錄

傳送:將表單資料以郵件傳送

¾ 表格控制項(DataGridView)

用途:處理子資料表

¾ 指令按鈕-子資料表

↑H

(31)

圖 6.6 子表指令按鈕 各按鈕之用途說明如下:

新增:新增紀錄 編輯:修改紀錄 刪除:刪除紀錄

顯示子表:開啟子表以單筆形式查閱紀錄

¾ 文字方塊(取名為 KeyText)

用途:當紀錄改變時,將主鍵值填入此控制項,再透過 TextChanged 事件來過濾 子表。

6.7.2 程式設計 6.7.2.1 變數宣告

在表單程序區宣告下列公用變數:

ds:DataSet

bindSRC:BindingSource bindADP:OdbcDataAdapter bindTBL:DataTable

bindADP2:OdbcDataAdapter bindTBL2:DataTable

daView2:DataView

builder:OdbcCommandBuilder builder2:OdbcCommandBuilder DataView

lbl():標籤控制項物件,用於提示欄位抬頭

obj():標籤控制項物件,用於設定欄位資料控制項 vl():控制項資料暫存變數

fln:主表欄數 fln2:子表欄數

tblStruct():主表欄位結構 tblStruct2():子表欄位結構 keyField1:主表主鍵 keyField2:主表第二主鍵 ckeyField1:子表主鍵 ckeyField2:子表第二主鍵

Dim ime1, ime2, ime3 As ImeMode ↑H

(32)

ime1 = Windows.Forms.ImeMode.Alpha '英數 ime2 = Windows.Forms.ImeMode.Off

ime3 = Windows.Forms.ImeMode.On '中文半形 6.7.2.2 加入控制項

在表單之 Load 事件程序內加入下列敘述:

¾ 開啟資料來源 ds = New DataSet("ds")

bindADP = New OdbcDataAdapter(strSQL, myCon) bindADP.Fill(ds, wkTBL)

bindTBL = ds.Tables(wkTBL) bindSRC.DataSource = ds

bindSRC.DataMember = wkTBL bindTBL.PrimaryKey = 主表主鍵 tbl = ds.Tables(wkTBL)

BindingNavigator1.BindingSource = bindSRC

¾ 設定資料表欄位結構及介面資料

在此段加入資料表欄位結構及介面資料設定程式碼 ReDim tblStruct(fln)

If wkSQL = "" Then

Call getTableStructure(wkTBL, 1) 說明:請自行設計副程式 Else

Call getSqlStructure(wkSQL, 1) End If

¾ 計算資料表欄數

fln = tbl.Columns.Count - 1 ReDim lbl(fln)

說明:重新宣告相關變數陣列大小 ReDim obj(fln)

ReDim vl(fln)

¾ 填入主表鍵值-搜尋鍵值下拉方塊 If keyField1 <> "" Then

keyValue = getKeyValue(wkTBL, keyField1)

kvl = Split(keyValue, ",") ↑H

(33)

keyCBO.Items.Clear() 說明:搜尋鍵值下拉方塊 keyCBO.Items.Add("")

說明:空字串可用於取消Filter For i = 0 To UBound(kvl)

keyCBO.Items.Add(kvl(i)) Next

End If

¾ 加入控制項-依主表欄數 stX1 = 1,說明:標籤X座標 stY1 = 60,說明:標籤Y座標

stX2 = 95,說明:資料控制項X座標 stY2 = 60,說明:資料控制項 Y 座標 For i = 0 To fln

‹ 加入欄位抬頭(Label)控制項 lbl(i).Text = tblStruct(i).fldTitle lbl(i).font = 自訂字型

loc.X = stX1 loc.Y = stY1

lbl(i).Location = loc sz.Height = 18

sz.Width = 94 lbl(i).Size = sz

Me.Controls.Add(lbl(i))

‹ 加入資料輸入控制項

obj(i) = New TextBox 或是 ComboBox loc.X = stX2

loc.Y = stY2

obj(i).Location = loc obj(i).font = 自訂字型

sz.Height = font.GetHeight + 5 obj(i).Size = sz

obj(i).Name = tbl.Columns(i).ColumnName Me.Controls.Add(obj(i))

stY2 = stY2 + setY 說明:遞增Y座標

stY1 = stY2, ↑H

(34)

‹ 設定滑鼠事件

AddHandler CType(obj(i), TextBox).MouseDown, AddressOf On_MouseDown 說明:On_MouseDown 事件程序必須自行定義,它將用來回應用戶按下滑鼠

時,需要處理之作業。

‹ 設定輸入法

If tblStruct(i).fldImeMode = "Aa" Or tblStruct(i).fldImeMode = "" Then obj(i).imemode = ime1

ElseIf tblStruct(i).fldImeMode = "Of" Then obj(i).imemode = ime2

ElseIf tblStruct(i).fldImeMode = "On" Then obj(i).imemode = ime3

End If Next

¾ 設定 KeyText 連結資料來源 此控制項用於存取鍵值。

KeyText.DataBindings.Clear()

KeyText.DataBindings.Add(New Binding("Text", bindSRC, keyField1, True))

¾ 開啟子表資料來源 Dim ds2 As New DataSet

If wkTBL2 <> "" Or wkSQL2 <> "" Then If wkSQL2 = "" Then

strSQL2 = "Select * From " & wkTBL2 & " Order By " & ckeyField1 Else

strSQL2 = wkSQL2 End If

bindADP2 = New OdbcDataAdapter(strSQL2, myCon) bindADP2.Fill(ds2, wkTBL2)

bindTBL2 = ds2.Tables(wkTBL2) daView2 = New DataView(bindTBL2)

fln2 = bindTBL2.Columns.Count – 1 說明:以下程式用於設定子表關聯條件 If tblStruct2(0).fldType = "Numeric" Then

daView2.RowFilter = ckeyField1 & "=" & KeyText.Text Else

daView2.RowFilter = ckeyField1 & "='" & KeyText.Text & "'" ↑H

(35)

End If

DataGridView1.DataSource = daView2

‹ 設定資料表欄位結構及介面資料

在此段加入子表資料表欄位結構及介面資料設定程式碼 ReDim tblStruct2(fln2)

If wkSQL = "" Then

Call getTableStructure(wkTBL2, 2),說明:請自行設計副程式 Else

Call getSqlStructure(wkSQL2, 2) End If

End If

¾ 定義 On_MouseDown 事件程序

Private Sub On_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs)

Dim na As String '取得傳入事件之控制項名稱 na = sender.name

在此處加入自訂敘述

說明:加入自訂敘述,可依 na 個別設定對應程序,當處理人員在控制項上按 下滑鼠時,就會啟動此段程序。

End Sub

¾ 定義 KeyCBO_TextChanged 事件程序

用途:下拉選取鍵值,當鍵值改變時,觸發主表過濾機制

Private Sub keyCBO_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles keyCBO.SelectedIndexChanged

Try

bindSRC.Filter = Nothing

If keyCBO.Text = "" Then Exit Sub 說明:以下程式用於設定主表過濾條件

If tblStruct(0).fldType = "String" Or tblStruct(0).fldType = "Stamp" Then bindSRC.Filter = keyField1 & "='" & keyCBO.Text & "'"

Else

If tblStruct(0).fldType = "Date" Then

bindSRC.Filter = keyField1 & "='" & keyCBO.Text & "'"

Else

bindSRC.Filter = keyField1 & "=" & keyCBO.Text

End If ↑H

(36)

End If

Catch ex As Exception MsgBox(ex.Message) End Try

End Sub

¾ 定義 KeyText_TextChanged 事件程序

Private Sub KeyText_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles KeyText.TextChanged

Dim i As Integer Dim vl

說明:以下程式用於設定子表關聯條件 If wkTBL2 <> "" Or wkSQL2 <> "" Then If tblStruct2(0).fldType = "Numeric" Then

daView2.RowFilter = ckeyField1 & "=" & KeyText.Text Else

daView2.RowFilter = ckeyField1 & "='" & KeyText.Text & "'"

End If End If End Sub

¾ 定義主表資料更新事件程序

事件程序應包含下列敘述(子表更新程序與主表類似):

‹ 擷取控制項資料並存放於資料表結構體變數內 語法:

For i = 0 To UBound(tblStruct) vl = obj(i).text

vl = 依欄位型態將 vl 轉型 tblStruct(i).fldValue = vl Next

‹ 修改資料時

upOK = UpdateNewRecord(1, kv1, kv2) If upOK = True Then

lblStatus.Text = "更新成功..."

Else

lblStatus.Text = "更新失敗..."

End If ↑H

(37)

‹ 新增資料時

upOK = InsertNewRecord(1, kv1, kv2) If upOK = True Then

lblStatus.Text = "新增成功..."

BindingNavigatorAddNewItem.Visible = True Else

lblStatus.Text = "新增失敗..."

End If

¾ 定義主表資料刪除事件程序

事件程序應包含下列敘述(子表刪除程序與主表類似):

Dim srtKey As String srtKey = 組合過濾鍵值 If newDrow = False Then

If DeleteKeyValue(wkTBL, srtKey) = True Then lblStatus.Text = "紀錄已刪除.."

End If End If

6.7.3 應用範例

下圖示範以動態表單新增和查詢關聯資料表記錄。

6.8 報表設計技巧

圖 6.7 動態表單範例

資料輸出介面除了使用表單形式並提示在螢幕外,也經常使用報表形式輸出 至印表機。本節介紹以印表機列印報表之技巧。

6.8.1 前置作業 ↑H

(38)

在設計報表前,須準備下列物件、設定來源資料及設定報表格式。

功能表單:開啟一個一般形式之表單,在表單上加入下拉功能表或指令按鈕,可 以用來執行版面設定、預覽列印及列印功能。此外,在表單上加入下 列控制項:

PageSetupDialog:版面設定控制項,

PrintPreviewDialog:預覽列印控制項,

PrintDialog:列印控制項,

PrintDocument:文件製作控制項。

來源資料:可以是資料表或 SQL 指令。

報表格式:設定如下圖所示之報表格式,下圖中之控制項須分別設定其座標位 置。特別提醒讀者,報表之座標是以 1/100 英吋為單位。

報表表頭 列印日期

欄位抬頭

逐筆分開列印之資料錄 設定是否加印分隔線

設定是否須按鍵值列印小計值

. . .

按分頁方式分頁

頁碼

報表表頭 列印日期

欄位抬頭

逐筆分開列印之資料錄 設定是否加印分隔線

設定是否須按鍵值列印小計值

. . .

按分頁方式分頁

頁碼

圖 6.8 報表格式說明 事前須決定下列屬性:

列印字型,

列與列之間之行距,行距大小取決於字型點數,

列與列之間是否加印分隔線,

是否須按鍵值小計,

分頁方式:依鍵值分頁或依可列印行數自動分頁。

6.8.2 程式設計

6.8.2.1 設定資料來源及報表格式

請在功能表表單 Load 事件程序內加入下列敘述:

¾ 開啟資料來源 ↑H

(39)

¾ 取出預先設定之報表格式 6.8.2.2 啟動版面設定對話方塊

請在對應按鈕或下拉功能表之 Click 事件內加入列程式:

PageSetupDialog1.Document = PrintDocument1 說明:將列印版面指向預設之PrintDocument物件

PageSetupDialog1.PageSettings = New System.Drawing.Printing.PageSettings PageSetupDialog1.PrinterSettings = New System.Drawing.Printing.PrinterSettings PageSetupDialog1.ShowNetwork = False

PageSetupDialog1.PageSettings.Margins.Left = mrgLeft 說明:設為預設之左邊

PageSetupDialog1.PageSettings.Margins.Right = mrgRight 說明:設為預設之右邊界

PageSetupDialog1.PageSettings.Margins.Top = mrgTop 說明:設為預設之上邊界

PageSetupDialog1.PageSettings.Margins.Bottom = mrgBottom 說明:設為預設之下邊界

Dim result As DialogResult

result = PageSetupDialog1.ShowDialog() 說明:開啟對話方塊

If result = Windows.Forms.DialogResult.OK Then

mrgLeft = PageSetupDialog1.PageSettings.Margins.Left mrgRight = PageSetupDialog1.PageSettings.Margins.Right mrgTop = PageSetupDialog1.PageSettings.Margins.Top

mrgBottom = PageSetupDialog1.PageSettings.Margins.Bottom

PrintDocument1.DefaultPageSettings = PageSetupDialog1.PageSettings End If

6.8.2.3 啟動預覽列印對話方塊

請在對應按鈕或下拉功能表之 Click 事件內加入列程式:

PrintPreviewDialog1.Document = Me.PrintDocument1 說明:將列印版面指向預設之PrintDocument物件 PrintPreviewDialog1.ShowDialog()

6.8.2.4 啟動列印對話方塊

請在對應按鈕或下拉功能表之 Click 事件內加入列程式:

PrintDialog1.Document = Me.PrintDocument1

說明:將列印版面指向預設之PrintDocument物件 ↑H

(40)

If PrintDialog1.ShowDialog = Windows.Forms.DialogResult.OK Then PrintDocument1.Print()

End If

6.8.2.4 設計 PrintDocument1_PrintPage 事件程序

請在此事件內加入下列程式碼,當設定 PrintPreviewDialog1.Document 或 PrintDialog1.Document 時,此事件程序就會被啟動來製作報表文件

¾ 設定工作變數

Dim x As Single, y As Single, txtW As Single Dim txt

Dim dRow As DataRow

Dim fnd As Integer, str As String, i As Integer Dim gi As Integer, grpString As String

Dim prnX As Single, prnU As Single, maxPOS As Single = recWidth Dim pen As New Pen(Color.Black)

說明:建立畫筆

pgHight = e.MarginBounds.Height

說明:e 代表列印事件,讀取列印版面高度 pgWidth = e.MarginBounds.Width

說明:取出列印版面寬度 Dim docFont As Font

docFont = New Font(titleFontName, titleFontSize) 說明:設定字型

Dim docSize As New Size(e.MarginBounds.Width, e.MarginBounds.Height - docFont.GetHeight(e.Graphics))

說明:設定列印文件方塊大小 Dim lineRA As Single = 1 + spcLine

說明:設定每列文件佔用高度,spcLine表行距。

Dim docFormat As New StringFormat

docFormat.Trimming = StringTrimming.Word 說明:設定文字輸出格式,中文字不截斷 If recWidth < pgWidth Then

prnU = recWidth / lineLength Else

prnU = pgWidth / lineLength End If

x = e.MarginBounds.Left

說明:設定起始左邊界 ↑H

(41)

y = e.MarginBounds.Top 說明:設定起始出上邊界

¾ 列印報表抬頭

Dim rect As New Rectangle(x, y, pgWidth, docFont.GetHeight(e.Graphics)) e.Graphics.DrawString(rptTitle, docFont, Brushes.Black, rect, docFormat) y = y + docFont.GetHeight(e.Graphics) * lineRA

¾ 列印報表表頭

Call PrintHead(x, y, sender, e) 說明:請自行設計所需表頭

y = y + docFont.GetHeight(e.Graphics) * lineRA

¾ 列印欄位抬頭

Call PrintColHead(x, y, sender, e) 說明:請自行設計所需欄位抬頭

y = y + docFont.GetHeight(e.Graphics) * 2.2

¾ 列印報表本文-輸出所需紀錄

Do While True,說明:依序輸出來源資料之每筆紀錄

‹ 列印紀錄指標所在紀錄 For i = 0 To fln

txt = Trim(dRow.Item(i).ToString)

txtW = StrWidth(txt, dataFontName, dataFontSize) + 5 說明:StrWidth為自訂函數,用來量測文件寬度 If sumField(i) = True Then,說明:需要小計時 sumValue(i) = sumValue(i) + Val(txt) ttlValue(i) = ttlValue(i) + Val(txt) End If

If sumReport = False Then ‘非摘要式報表 If tblStruct(i).fldType = "Numeric" Then If i < fln Then

prnX = x + (colLOC(i + 1) - 2) * prnU - txtW Else

prnX = x + lineLength * prnU - txtW End If

rect = New Rectangle(prnX, y, txtW, docFont.GetHeight(e.Graphics)) e.Graphics.DrawString(txt, docFont, Brushes.Black, rect, docFormat)

Else ↑H

(42)

If tblStruct(i).fldType = "Date" Or tblStruct(i).fldType = "Stamp" Then txt = Trim(dRow.Item(i).ToString)

If daFMT = "Short" Then txt = Format(txt, "Short Date")

ElseIf tblStruct(i).fldType <> "Binary" And tblStruct(i).fldType <> "BLOB"

Then

txt = Trim(dRow.Item(i).ToString) Else

txt = "Byte_data"

說明:預設BLOB欄不印,並以Byte_data提示 End If

txtW = StrWidth(txt, dataFontName, dataFontSize) prnX = x + colLOC(i) * prnU

說明:colLOC(i)表預設欄位之X座標

rect = New Rectangle(prnX, y, txtW, docFont.GetHeight(e.Graphics)) e.Graphics.DrawString(txt, docFont, Brushes.Black, rect, docFormat) End If

Next

‹ 列印分隔線

If grdLine = True Then,說明:需要分隔線 y = y + docFont.GetHeight(e.Graphics) * lineRA e.Graphics.DrawLine(pen, gx(0), y, gx(fln + 1), y) Else

y = y + docFont.GetHeight(e.Graphics) * lineRA End If

‹ 移動紀錄指標

加入判斷次筆紀錄鍵值是否改變或已至檔尾 CurrentREC = CurrentREC + 1

dRow = rptTable.Rows(CurrentREC)

‹ 列印小計

If sumFLD = True Then,說明:需要小計 txt = "小計"

txtW = StrWidth(txt, dataFontName, dataFontSize) + 5 prnX = x + (colLOC(1) - 2) * prnU - txtW

rect = New Rectangle(prnX, y, txtW, docFont.GetHeight(e.Graphics)) e.Graphics.DrawString(txt, docFont, Brushes.Black, rect, docFormat) y = y + docFont.GetHeight(e.Graphics) * lineRA

For i = 1 To fln ↑H

(43)

If sumField(i) = True Then txt = Trim(CStr(sumValue(i)))

txtW = StrWidth(txt, dataFontName, dataFontSize) + 5 If i < fln Then

prnX = x + (colLOC(i + 1) - 2) * prnU - txtW Else

prnX = x + lineLength * prnU - txtW End If

rect = New Rectangle(prnX, y, txtW, docFont.GetHeight(e.Graphics)) e.Graphics.DrawString(txt, docFont, Brushes.Black, rect, docFormat) End If

Next End If

‹ 檔案尾端處理

Call PrintTail(x, y, sender, e) 說明:請自行加入報表表尾程式 e.HasMorePages = False

說明:已無資料 Exit Do

說明:跳出迴圈

‹ 文件區已滿且尚有資料錄

If y >= (e.MarginBounds.Bottom - docFont.GetHeight(e.Graphics) * 1.5) Then

Call PrintTail(x, y, sender, e) 說明:請自行加入報表表尾程式 curPage = curPage + 1

說明:頁碼加1 e.HasMorePages = True

說明:仍有資料 Exit Do

End If Loop

¾ 特殊指令說明

列印資料:e.Graphics.DrawString 畫線:e.Graphics.DrawLine 列印影像:e.Graphics.DrawImage

文件區已無資料:e.HasMorePages = False ↑H

(44)

文件區尚有資料:e.HasMorePages = True

中文字不截斷:docFormat.Trimming = StringTrimming.Word 6.9 條碼製作技巧

條碼常搭配表單或報表一起使用,可讓取得來源資料人員快速擷取內含鍵 值,從而取得原始內容。製作條碼時,必須先引用條碼控制項,引用方法如下:

¾ 開啟工具箱,

¾ 在工具箱上按下滑鼠右鍵以開啟快顯功能表,

¾ 點取【選擇項目】,開啟【工具箱選擇項目】對話控制項,

¾ 點取【COM元件】,捲動選項清單至【MicroSoft條碼控制項 9.0】,如圖 6.9,

¾ 點取【確定】,將條碼控制項加入工具箱。

圖 6.9 引入條碼控制項 6.9.1 加入條碼控制項

條碼必須搭配表單方能正常顯示,因此需要在表單內加入條碼控制項,接下 來可依所需條碼規格設定條碼屬性,工作畫面如圖 6.10。

↑H 圖 6.10 條碼屬性對話控制項

(45)

條碼屬性說明如下:

【樣式】-Style:可選用下列樣式:

0 - UPC-A 1 - UPC-B 2 - JAN-13 3 - JAN-8 4 - Case Code 5 - NW7 6 - Code-39 7 - Code-128 8 - U.S. Post net 9 - U.S. Postal FIM 10 - JP Post

【副樣式】-SubStyle:選擇樣式後,若有副樣式屬性,可依規格來設定,選項 內容如下:

0-UPC-A、1-UPC-A、2-JAN-13 及 3-JAN-8 有下列副樣式:

0-標準 1-2 位補充碼 2-5 位補充碼 3-POS Case Code

4-Case Code 有下列副樣式:

0-標準版 1-擴充版 2-附加版

8-U.S. Post net 有下列副樣式:

0-傳遞點 1-ZIP Code + 4 2-5 Digit ZIP Code

9-U.S. Post FIM 有下列副樣式:

0-FIM-A Symbol 1-FIM-B Symbol 2-FIM-C Symbol

【線條粗細】-LineWeight:可設定 1-5 之線條樣式。

【列印方向】-Direction:可設為下列形式:

0 - 0 度 1 - 90 度

2 - 180 度 ↑H

(46)

3 - 270 度

【標籤寬度】-Width:以 Pixel 為單位,可自行調整控制項。

【標籤高度】-Height:以 Pixel 為單位,可自行調整控制項。

可以使用程式來設定條碼屬性,語法如下:

barCD.Width = W barCD.Height = H barCD.Style =N barCD.SubStyle =M barCD.LineWeight = L barCD.Direction = D

barCD.Value =來源資料欄位

其中 barCD 為自定條碼控制項名稱。

6.9.2 條碼列印

因為條碼控制項無法直接列印在報表上,若要在報表上列印條碼,必須先將 條碼顯示在表單上,然後將表單條碼複製在記憶體,最後再將記憶體影像貼在列 印物件上。

複製影像時,必須在表單公用程序區引入 BitBlt 函數,語法如下:

<DllImport("gdi32.dll", CharSet:=CharSet.Auto, SetLastError:=True,

ExactSpelling:=True)> Public Shared Function BitBlt(ByVal hDC As IntPtr, ByVal x As Integer, ByVal y As Integer, ByVal nWidth As Integer, ByVal nHeight As Integer, ByVal hSrcDC As IntPtr, ByVal xSrc As Integer, ByVal ySrc As Integer, ByVal dwRop As Integer) As Boolean

End Function 複製條碼

處理程式如下:

Private Sub SaveBarBMP(ByVal i As Integer) Try

Dim barGD As Graphics Dim mmoGD As Graphics Dim dc1 As IntPtr, dc2 As IntPtr barGD = barCD.CreateGraphics()

說明:建立條碼圖像物件

barBMP = New Bitmap(baStru(i).Width, baStru(i).Height, barGD) 說明:將條碼圖像物件轉成BitMap圖像

mmoGD = Graphics.FromImage(barBMP) ↑H

(47)

說明:將BitMap圖像轉存記憶體 dc1 = barGD.GetHdc()

說明:取得條碼圖像物件參考指標 dc2 = mmoGD.GetHdc()

說明:取得記憶體圖像物件參考指標

BitBlt(dc2, 0, 0, baStru(i).Width, baStru(i).Height, dc1, 0, 0, 13369376) 說明:複製圖像

barGD.ReleaseHdc(dc1) 說明:釋放記憶體 mmoGD.ReleaseHdc(dc2)

說明:釋放記憶體 Catch ex As Exception End Try

End Sub 列印條碼

在 PrintDocument.PrintPage 事件區列印條碼,語法如下:

e.Graphics.DrawImage(barBMP, x, y)

↑H

參考文獻

相關文件

Sometimes called integer linear programming (ILP), in which the objective function and the constraints (other than the integer constraints) are linear.. Note that integer programming

Contudo, excluem-se as reuniões com menos de 10 participantes, as cerimónias de lançamento de produtos, as sessões de esclarecimento, as conferências de imprensa e as exposições

• Students annotate a text using an annotation tool that identifies their authorship. • Advantage: student annotations may

How would this task help students see how to adjust their learning practices in order to improve?..

Strands (or learning dimensions) are categories of mathematical knowledge and concepts for organizing the curriculum. Their main function is to organize mathematical

The non-normalizable (zero) modes picked up by the AdS/CFT description localized on the AdS boundary, which corresponds to dual CFT operators and should be topological sector of

Schematic phase diagram of high-Tc superconductors showing hole doping right side and electron doping left side.. The common Features in

又要加上節制。有了節制、又要加上忍耐。有了忍