第十四章: 檔案
章節預覽 14.1 檔案類型 14.2 存取檔案 14.3 循序檔 14.4 記錄(Record) 14.5 隨機檔 14.1 檔案類型 14.2 存取檔案 14.3 循序檔 14.4 記錄(Record) 14.5 隨機檔 14.6 『磁碟機清單方塊』、『目錄清單方塊』、 『檔案清單方塊』控制項 14.7 通用型對話方塊 (Common Dialog) 14.8 例外處理 14.9 本章整合應用實例(簡易文書編輯器製作)
14.1:檔案類型 檔案有許多類型,但針對Visual Basic的檔案而言,則可以依 照功能區分為「程式檔」(Program file)與「資料檔」(Data file)兩大類。 「程式檔」是一群Visual Basic敘述與命令的集合,通常可以 用來來解決某個特定問題(該程式的設計目標)。 而「資料檔」存放的並不是Visual Basic的敘述與命令,而是 「資料」(Data),這些資料若尚未經由程式處理,則可能 雜亂無章,但是若必須經由程式的處理,將會變成有特定用 途的資訊。例如:我們可以將要排序的資料存放在資料檔內 ,經由排序程式的處理,形成有用的已排序資訊在回存到檔 案中,以便於下次搜尋資料時,可以使用比較快速的搜尋演 算法來搜尋資料。
14.1:檔案類型 程式檔 我們Visual Basic IDE下編寫的Visual Basic程式,在尚未編譯前 所儲存的檔案稱之為「原始程式檔」(Source Program File) 。一個Visual Basic的原始程式檔至少包含一個專案檔 (*.vbp)、 一個專案工作區檔 (*.vbw)、一個表單檔 (*.frm)或是一般模組 檔 (*.bas)。如果程式中有特殊需求(例如使用了映像或圖片控 制項載入一張圖片),則可能還會產生其他種類的檔案。 「原始程式檔」可以編譯成「可執行檔」(附檔名為.exe),就 不必進入IDE,而可以直接在Windows環境中執行程式了。 資料檔 資料通常是由數字、文字與特殊符號構成的,在未經程式處理 前,可能是不太有用的資料,但經過程式的處理後,將變成較 為有用的資訊,為了避免這些資訊的流失,通常我們會將程式 處例後的結果,以特定格式存入磁碟中。而不論存入磁碟的資 料是程式處理前的資料或是程式處理後的有用資訊,我們都將 這些存入磁碟的資料稱為「資料檔」。(對於程式而言,未經 處理的資料檔將會是程式的輸入、而程式處理後存放的資料檔 則為輸出。)
14.2:存取檔案 檔案格式 Visual Basic將檔案依照存取方式,分為「循序存取檔」、「 隨機存取檔」與「二進位檔」等3種。 循序存取檔 (Sequential Access File) 循序存取檔簡稱為「循序檔」,顧名思義,此類檔案的資料是 循序存放的。循序檔在寫入磁碟時,後面輸入的資料必須放在 剛剛才輸入的資料後面,並且按照資料的先後次序一個一個地 循序存放。而在讀取資料時,則必須由第一筆資料開始,慢慢 往後讀取資料。 由於新增的資料將會存放在舊資料的後面。因此,循序檔的每 一筆資料長度都可以不一樣,如此一來將比較節省空間,但在 搜尋資料時卻必須花費較多的時間。因為每次查詢資料時,都 必須從頭開始尋找,若資料放在很後面,就會花費很長的時間 。
14.2:存取檔案 隨機存取檔 (Random Access File) 隨機存取檔簡稱為「隨機檔」,隨機檔的每一筆資料長度所佔 用的磁碟空間都是相同的,並且資料存入磁碟的方式並沒有先 後次序限制。 由於隨機檔的每筆資料長度都是固定且相同的,因此在搜尋資 料時,只要知道要尋找的資料是第幾筆資料,就可以利用簡單 的公式計算出資料的實際位置,因此可以較快速地取得資料。 並且不論資料存放在檔案的哪一段位置,搜尋的時間也相差不 遠。 為了使得每筆資料都可以放入檔案中,因此隨機檔會以最長的 一筆資料長度做為資料長度的基準。因此,如果每一筆資料的 實際長度相差很大時,對於實際長度較小的資料而言,就浪費 了很多的磁碟空間。 二進位檔 (Binary File) 二進位檔的資料是由一連串的位元組(Byte)所組合,通常使 用在某些特殊用途(例如圖檔),暫時不深入討論此類型檔案 結構。
14.2:存取檔案 資料檔的操作 對於資料檔的操作,可以分為下列7種作業,透過這7種作業 ,程式就可以善用資料檔當做程式的輸入或輸出資料。 資料檔的操作 對於資料檔的操作,可以分為下列7種作業,透過這7種作業 ,程式就可以善用資料檔當做程式的輸入或輸出資料。 建檔作業:產生新的資料檔,並指定該檔案的存取模式。 新增作業:加入新的資料到指定的資料檔中。 修改作業:在指定的資料檔中,修改指定的資料內容。 刪除作業:在指定的資料檔中,刪除指定的資料。 查詢作業:在指定的檔案中,尋找滿足條件的資料。 列印作業:在指定的檔案中,尋找滿足條件的資料,並將之由 印表機列出。 分析作業:挑選滿足特定條件的資料,然後加以進行統計、分 析等工作,其結果將可做為決策的參考。
14.2:存取檔案 開啟與關閉檔案 要存取資料檔的資料,首先必須透過Open敘述將資料檔打開 ,資料檔才能被存取。當檔案使用完畢,則使用Close敘述來 關閉檔案。最好養成關閉檔案的動作,尤其是資料存取狀態 處於「寫入」狀態時,若忘了關檔,則暫存在緩衝區的資料 可能未遺失。建檔作業:產生新的資料檔,並指定該檔案的存取 模式。 開啟檔案 【語法說明】: 1. 檔名(FileName):字串或字串運算式,代表要開啟的檔案名稱。若檔 案與程式處於不同資料夾,則必須加上路徑。 2. 模式(Mode):指定要開啟那一種資料檔以及存取模式: 語法:Open檔名 [For模式] AS [#]檔案代碼 [Len =記錄長度] 功能:以指定的模式將檔案開啟。
14.2:存取檔案 檔案結構 模 式 說 明 循序存取檔 Output 說 明 循序存取檔 Output 將資料(主記憶體的資料)寫入磁碟檔案中。若已經存在該檔案,則 該檔案的原始內容將被全部刪除後再寫入新的資料。若不存在該檔案 ,則會建立一個新的檔案並寫入資料。 Append 由資料(主記憶體的資料)寫入磁碟檔案中。若已經存在該檔案,則 新的資料會加在檔案原始資料的後面(已存在的資料不會遺失)。若 不存在該檔案,則會建立一個新的檔案並寫入資料。 Input 由檔案中讀取資料並存入主記憶體中,由於是循序檔,因此會檔案開 頭開始讀取。若指定的檔案不存在,則發出錯誤訊息。 隨機存取檔 Random 在指定的磁碟檔案讀取或寫入資料。若省略模式參數,則預設值內定 為Random隨機檔。 二進位檔 Binary 以Byte為單位,讀寫檔案的任一位置。 3. 檔案代碼:每一個資料檔被開啟,就會被賦予一個檔案代碼,其值為 整數1~511。檔案一但被開啟後,往後有關該檔案的操作都是透過這個 代碼來代表該檔案。通常為了避免麻煩,我們會用FreeFile函數,自動 由系統分配可用的檔案代碼。 4. 記錄長度:在隨機檔模式下,此參數是用來設定隨機檔中每一筆記錄 的長度,單位為Byte,其值為整數1~32767。若輸入的某一筆資料長度 超過了設定的記錄長度時,資料將無法存入檔案中,此時會產生錯誤訊 息,在隨機檔中Len值通常設為最長一筆記錄的大小。省略此參數時, 循序檔與隨機檔的Len預設值為128,二進位檔的Len預設值則為1。
14.2:存取檔案 關閉檔案 語法:Close [[#] 檔案代碼1,[#] 檔案代碼 2,...] 功能:將檔案代碼所對應的資料檔關閉 【語法說明】: 1. 若省略檔案代碼,則會將目前已經開啟的所有資料檔通通關閉。 2. 若檔案不再被使用,最好將之關閉,避免佔用的過多的緩衝區。 3. 若使用Output或Append開啟檔案,當執行Close敘述時,會先將存放 在緩衝區的資料寫入檔案後,才將資料檔關閉。 語法:Close [[#] 檔案代碼1,[#] 檔案代碼 2,...] 功能:將檔案代碼所對應的資料檔關閉
14.2:存取檔案 與檔案有關的常用函數 FreeFile函數 【語法說明】: 執行FreeFile函數後,系統會在所有未使用的檔案代碼中挑選一個最小 的檔案代碼,回傳此檔案代碼。例如:#1、#2、#3、#6已經被其它檔案 使用,則執行FreeFile函數後會傳回檔案代碼#4。 LOF函數(Length Of File) 1. 回傳的檔案長度單位為「Byte」。 2. 本函數所指定的檔案,必須先透過Open敘述開啟。 【範例】:FileSize=LOF(3) '回傳檔案代碼為3的檔案長度。 語法:FreeFile 功能:自動由系統分配一個可用的檔案代碼。 語法:LOF(檔案代碼) 功能:回傳檔案代碼對應檔案的檔案長度。
14.2:存取檔案 FileLen函數(File Length) 語法:FileLen(檔名)。 功能:回傳指定檔名的檔案長度。 【語法說明】: 1. 回傳的檔案長度單位為「Byte」。傳回值的資料型態為長整數。 2. 檔名可包含路徑。若無路徑,則預設路徑為執行程式的相同資料夾。 3. 本函數所指定的檔案,必須尚未透過Open敘述開啟。 【範例】:FileSize=FileLen("TEST.txt") '回傳TEST.txt檔案的長度 EOF函數(End Of File) 1. 讀取檔案的資料時,可以使用EOF函數來判斷檔案指標是否已經指到檔 案結尾。若已指到檔案結尾,EOF函數將回傳True。否則回傳False 2. EOF函數若使用在循序檔時,可以用來判斷該循序檔是否已經讀取完畢 語法:FileLen(檔名)。 功能:回傳指定檔名的檔案長度。 語法:EOF(檔案代碼) 功能:測試檔案指標是否指到檔案結尾。回傳值為布林資料型態。
14.3:循序檔 循序檔 在「循序檔」中存取資料,一定要按照資料存入的先後順序依序處 理。所以在循序檔中寫入資料時,必須按照第一筆、第二筆、、的 順序一一寫入。而在循序檔中讀取資料時,也必須依序先讀過前面 資料,然後才能讀到後面的資料。以下是循序檔的特性與使用時機 循序檔的特性 每一筆記錄長度可以不同。 若每一筆資料長度有很大的差異 時,使用循序檔來存資料,將可 以節省磁碟空間。 新增一筆資料時,會加入到原有 資料最後一筆後面。 每次找尋資料時,必須從頭開始 找起,因此較為費時。 循序檔的使用時機 無法確定每筆記錄的長度時。 預估每筆記錄的長度差異很大 時。 資料不會經常做新增、修改和 刪除等作業時。 處理資料時可以按照順序連續 處理,不必跳來跳去時。 備份檔案時。(因為備份檔案 使用循序檔,可以有效利用儲 存體空間,並且由於備份之檔 案不需要常常做新增、修改和 刪除等作業)
14.3:循序檔 循序檔-寫入資料 在Visual Basic中,寫入資料到循序檔可以透過『Write #』與 『Print #』完成,兩者的功能相同但存檔格式略有不同。 『Write #』敘述(寫入資料) 【語法說明】: 檔案代碼與Open敘述開檔的檔案代碼相同。 在寫入檔案前,必須先使用Open … Output或Open …Append開 啟檔案。 運算式串列可以是數值或字串運算式,參數間以逗號『,』加以區 隔。 省略運算式串列時,『Write #』敘述會寫入一列空白列到檔案中 語法:Write #檔案代碼,運算式串列 [,] 功能:將運算式串列的運算結果寫入到檔案代碼對應的循序檔中
14.3:循序檔 語法:Print #檔案代碼,[運算式串列][{,或;}] 功能:將運算式串列的運算結果寫入到檔案代碼對應的循序檔中 【語法說明】: 1. 檔案代碼與Open敘述開檔的檔案代碼相同。 2. 在寫入檔案前,必須先使用Open … Output或Open …Append 開啟檔案。 3. 運算式串列可以是數值或字串運算式。多個資料可以使用逗號 『,』或分號『;』加以區隔,兩者之差別如同一般的Print敘述( 詳見第4章)。 語法:Print #檔案代碼,[運算式串列][{,或;}] 功能:將運算式串列的運算結果寫入到檔案代碼對應的循序檔中
14.3:循序檔 『Write #』與『Print #』的差別 『Write #』和『Print #』敘述都可以用來將資料寫入循序檔中, 但在資料的存放方式有一些不同: 使用『Write #』敘述,將字串資料寫入循序檔時,會自動在字串 前後加上雙引號。而且寫入多筆資料項目時,資料之間會出現逗 號『,』加以分開。 使用『Print #』敘述,將字串資料寫入循序檔時,若使用分號『; 』來區隔資料,則每筆資料會緊密相接。若要用逗號『.』來區隔 資料,則每一筆資料會佔用一定的區域長度,資料長度未達該區 域長度時,則會補上空白(與Print敘述相同)。 使用『Write #』敘述,寫入數值資料時,資料前後不會加空白。 使用『Print #』敘述,寫入數值資料時,和寫入字串沒有太大的 差別,唯一不同的是正數前面會保留一個空白(與Print敘述相同 )。
【實作範例14-1】 【實作範例14-1】:透過『Write #』敘述輸入資料並存入檔 案中。 上機實作 Step1:專案名稱為『p14_01』。 Step2:在表單上產生下列控制項並設定屬性。 Step3:編輯下頁程式碼。
【實作範例14-1】 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 Dim file_no Private Sub cmdAddNext_Click() '存入一筆資料,並清除文字方塊 Write #file_no, txtId, Val(txtComputer), Val(txtMath), Val(txtEng) txtId = "": txtComputer = "" txtMath = "": txtEng = "" End Sub Private Sub Form_Load() file_no = FreeFile '取得檔案代碼 Open "c:\vb6\ch14\14_01\Score.txt" For Output As #file_no '開檔 End Sub Private Sub Form_Unload(Cancel As Integer) '當最後一筆資料輸入完整則也要存入檔案中 If (txtId <> "") And (txtComputer <> "") _ And (txtMath <> "") And (txtEng <> "") Then Write #file_no, txtId, Val(txtComputer), Val(txtMath), Val(txtEng) End If Close #file_no '關檔 End '結束程式 End Sub
【實作範例14-1】 Step4:執行程式。輸入資料後。檔案內容如下。 "S9103501",89,84,75 "S9103502",77,69,87
14.3:循序檔 循序檔-讀取資料 在Visual Basic中,讀取循序檔的資料則可以透過『Input #』 敘述、『Line Input #』敘述及『Input』函數來完成。 『lnput #』敘述(讀取資料) 【語法說明】: 變數1、變數2、、可以為數值、字串或陣列變數。 變數的資料型態最好與檔案的資料型態相符,並且檔案的數值資 料可以讀入字串變數,但檔案的字串資料不可以讀入數值變數中 。 循序檔中若同時包含有文字與數值資料,在存檔時,最好不要使 用『Print #』敘述存檔,否則使用『Input #』敘述來讀取資料時 ,可能會發生錯誤。 語法:Input #檔案代碼,變數1[,變數2]… 功能:從檔案代碼對應的循序資料檔中依序讀出資料並存放到指定的變數中。
14.3:循序檔 『Line Input #』敘述(讀取整列資料) 字串變數:存放檔案整列的資料。由於一次讀一列資料,因此不論資 料是數值還是字元,都會被當成字串的一部份,因此不可使用數值變 數來存放讀取到的資料。 Line Input #』敘述將讀取整列的資料,直到碰上換列字元為止。不論 該列資料中出現任何的字元都被當成一個普通的字元而已,即使是逗 號字元與空白字元也是不具任何特殊意義的。而使用『Input #』讀取 資料拾,會將逗號與空白符號當做是資料與資料的區隔,而存入不同 的變數中。 【差異】: 『lnput #』與『Line Input #』讀取資料時有些不同,舉例來說,假設 檔案內容為"Good morning",使用Line Input # 讀取資料時,將讀到 一筆資料,內容為『Good morning』。若使用Input #讀取資料,將讀 到兩筆資料(因此必須使用兩個字串變數來讀取),資料內容依序為 『Good』、『morning』。 語法:Line Input #檔案代碼,字串變數 功能:從檔案代碼對應的循序資料檔中一次讀取一列資料並存放到指定的變數中
14.3:循序檔 語法:Input(n,[#]檔案代碼) 功能:由檔案中讀取n個Bytes資料。 Input函數(讀取資料) 【語法說明】:
【實作範例14-2】 【實作範例14-2】:從Score.txt檔案中,讀取資料並且計算 平均分數,每次讀取一列資料(4個項目),檔案內容如下。 "S9103501",89,84,75 "S9103502",77,69,87 "S9103503",65,68,77 上機實作 Step1:專案名稱為『p14_02』。 Step2:在表單上產生下列控制項並設定屬性。 Step3:編輯下頁程式碼。 Step4:執行程式。
4 6 7 8 9 10 12 13 14 15 16 17 18 19 20 21 22 23 24 26 27 28 29 31 32 33 34 36 37 38 39 Dim file_no Private Sub cmdFirst_Click() Close #file_no Call OpenFile cmdNext_Click End Sub Private Sub cmdNext_Click() If Not EOF(file_no) Then Input #file_no, stu_id, ScoreComputer, ScoreMath, ScoreEng txtId = stu_id txtComputer = Str(ScoreComputer) txtMath = Str(ScoreMath) txtEng = Str(ScoreEng) txtAvg = CInt((ScoreComputer + ScoreMath + ScoreEng) / 3) Else MsgBox "很抱歉,資料已經全部讀取完畢,將回到第一筆資料" cmdFirst_Click End If End Sub Private Sub Form_Load() Call OpenFile cmdNext_Click End Sub Private Sub Form_Unload(Cancel As Integer) Close #file_no End End Sub Private Sub OpenFile() file_no = FreeFile Open "c:\vb6\ch14\14_02\Score.txt" For Input As #file_no End Sub
14.4:記錄(Record) 為何需要記錄(Record)? 在上一個範例中,我們可以從檔案中讀取3筆資料,由於每次的資料都存 放在stu_id, ScoreComputer, ScoreMath, ScoreEng等變數中,因此無法一 次儲存所有的資料(如右圖示意)。 為了解決無法一起存放的問題,我們可以使用二維陣列來存放每一次讀取 的資料,只需要使用簡單的迴圈即可完成,但是請注意當資料型態不一致 時(例如:stu_id為字串,ScoreComputer為數值),我們必須要將陣列 的資料型態宣告為Variant (如右圖示意)。
14.4:記錄(Record) 為何需要記錄(Record)? 雖然使用陣列可以存放所有的 資料,但是如果我們想用之前 學習的排序程式針對『計概』 分數做排序,則陣列經由排序 後會變成右邊左圖之狀況。 在右邊左圖中,很明顯地如果 僅僅將資料Score(i,1)排序的 話,由於其他的資料不會跟著 移動,因此『65』分並不是 "S9103501"同學的計概成績, 真正希望的排序後之結果應該是 如右邊右圖的狀況。 當然我們可以在排序對調資料時,一併對調所有屬於同列的資料。但是這 將導致程式更加複雜。如果橫向的列可以一併移動移動該有多好,為了解 決這個問題,Visual Basic和其他的高階語言一樣,也提供了記錄( Record)資料型態,記錄的感覺類似資料庫中的紀錄,但此處所指的『 記錄』是一種由使用者自訂的資料型態,它可以組合多種資料型態的資料 構成一筆記錄,例如:我們可以將『學號』、『計概』、『數學』、『英 文』等成績合併為一個記錄,並且使用陣列來宣告記錄陣列(陣列元素為 記錄),則可以解決上述問題。
14.4:記錄(Record) 記錄(Record) 「記錄」是由一些邏輯相關的「欄位」(Field)所構成。例如:一位學 生的學號、計概成績、數學成績、英文成績就是一筆記錄,該記錄則擁有 「學號」欄、「計概」欄、「數學」欄、「英文」欄,而一群學生的記錄 集合將構成記錄陣列。(如下圖示意) 一個記錄資料型態包含許多「欄位」,每一個欄位都必須賦予一個欄位名 稱。由於記錄是使用者自訂的資料型態,因此記錄在使用之前必須要先經 過定義,然後在經過宣告後才可使用。
14.4:記錄(Record) 定義記錄型態的語法如下: 宣告記錄變數的語法如下: 【語法說明】: 1. 記錄型態必須在模組檔中定義。 語法: [Private|Public] Type 記錄型態名稱 欄位名稱[(索引)] As資料型態 [欄位名稱[(索引)] As資料型態] End Type 功能:定義一個記錄型態包含哪些欄位以及各欄位的資料型態。 語法:Dim記錄變數名稱As記錄型態名稱 功能:宣告記錄變數為已定義的記錄資料型態
14.4:記錄(Record) 2. 記錄型態名稱:由於記錄資料型態中的欄位包含許多基本資料型態( 如整數、長整數、單精確度等),因此記錄型態的命名規則與變數名稱 相同,記錄內欄位名稱的命名規則也與和變數名稱相同。 3. 欄位可以是陣列,若未使用上、下界設定索引值範圍,也未使用 Option Base敘述宣告陣列起始,則內定下界為0。 4. 欄位中資料型態,可以是各種資料型態或其他自行定義的記錄型態( 例如另一個記錄形態)。 5. 程式撰寫時,若要設定或讀取記錄的某個欄位值,只要在記錄名稱與 欄位名稱中間加上『.』即可,例如:Print Score_Record.stu_id。 6. 宣告記錄變數時,可使用Public、Private、Dim、ReDim或Static來 宣告。 7. 記錄變數可以宣告為陣列(形成記錄陣列),記錄陣列的每個陣列元 件都是記錄型態的資料,例如:Dim Score(10) As Score_Recoed就是宣 告Score含有11個元素,每個元素的資料型態都是Score_Record。
14.4:記錄(Record) 【範例】: 利用記錄型態來宣告一個成績的記錄。一個記錄包括四個欄位如下: 學生學號:固定字串(8個字元) 計概成績 :整數 數學成績 :整數 英文成績 :整數 其記錄型態定義格式如下: 上述定義代表有一個名稱為Score_Record記錄型態,當中包含有四個欄 位,分別為固定字串變數stu_id、整數變數S_Computer、整數變數 S_Math及、整數變數S_Eng。若要宣告含有五個記錄變數的記錄陣列 Score,則可如下宣告: Type Score_Record stu_id As String * 8 S_Computer As Integer S_Math As Integer S_Eng As Integer End Type Dim Score(1 To 5) As Score_Record
14.4:記錄(Record) 經過上述宣告後,將會在主記憶體配置五個記錄變數,每個記錄變數都 含有四個欄位,分別為Score(i).stu_id、Score(i).S_Computer、 Score(i).S_Math、Score(i).S_Eng,且1≦i≦5。 該記錄陣列在主記憶體中的配置如下圖示意:
14.4:記錄(Record) With敘述 With敘述是用來設定某一物件或記錄的屬性值或執行某些方 法之用,在With區塊內的所有敘述接可以省略物件或記錄的 名稱。With敘述其語法如下: 【範例】: 語法: With 物件或記錄 [With敘述區塊] End With 功能:在With敘述區塊內指定屬性或方法時,可省略物件名稱或記錄名稱,而這些省略名稱的敘述將會以With後面的物件或記錄做為物件名稱或記錄名稱。 With Label1 .FontSize=14 .Caption="您好嗎" End With Label1.FontSize=14 Label1.Caption="您好嗎" With Score(2) .stu_id="S9103502" .S_Math=69 End With Score(2).stu_id="S9103502" Score(2).S_Math=69
14.4:記錄(Record) 【範例14-3】:使用記錄陣列存放檔案資料,檔案內容如下 b14_03.bas "S9103501",89,84,75 "S9103502",77,69,87 "S9103503",65,68,77 "S9103504",79,64,65 "S9103505",72,79,63 "S9103506",61,98,92 1 2 3 4 5 6 7 8 9 Public Type Score_Record stu_id As String * 8 S_Computer As Integer S_Math As Integer S_Eng As Integer S_Avg As Integer End Type Public NotSortScore(1 To 6) As Score_Record Public SortScore(1 To 6) As Score_Record
14.4:記錄(Record) b14_03.bas 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 Public Sub BubbleSort(NotSortX() As Score_Record, SortX() As Score_Record) Dim Temp As Score_Record For i = LBound(NotSortX) To UBound(NotSortX) SortX(i) = NotSortX(i) Next i n = UBound(SortX) K = n Do While (K <> 0) Times = 0 For i = LBound(SortX) To K – 1 If SortX(i).S_Avg > SortX(i + 1).S_Avg Then '若要使用其他欄位做為排序準則,則修改此處的S_Avg欄位名稱即可 Temp = SortX(i) 'SortX(i)與SortX(i+1)互換 SortX(i) = SortX(i + 1) 'SortX(i)與SortX(i+1)互換 SortX(i + 1) = Temp 'SortX(i)與SortX(i+1)互換 Times = i End If Next i K = Times Loop End Sub
14.4:記錄(Record) f14_03.frm 4 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 27 28 29 30 Dim file_no Private Sub Form_Activate() Call OpenFile i = 1 Do While Not EOF(file_no) With NotSortScore(i) Input #file_no, .stu_id, .S_Computer, .S_Math, .S_Eng .S_Avg = CInt((.S_Computer + .S_Math + .S_Eng) / 3) i = i + 1 End With Loop Close #file_no FontSize = 12 Print " 學號", "計概", "數學", "英文", "平均" Print String(100, "-") Call BubbleSort(NotSortScore(), SortScore()) For j = 1 To i – 1 Print SortScore(j).stu_id, SortScore(j).S_Computer, _ SortScore(j).S_Math, SortScore(j).S_Eng, SortScore(j).S_Avg Next j End Sub Private Sub OpenFile() file_no = FreeFile Open "c:\vb6\ch14\14_03\Score.txt" For Input As #file_no End Sub
14.5:隨機檔 隨機檔 隨機檔中的資料能夠隨意存取,也就是存取時不必資料的先後順序 。一個隨機檔中的每一筆資料(亦可稱為記錄)在磁碟中使用的固 定長度來存放,並且隨機檔中的每一筆記錄都被賦予一個編號,存 取時則是先依照編號計算出實際的資料存放位置,再取出資料。 由於隨機檔的每一筆資料長度固定,因此當每筆資料的實際長度差 異很大時,會比較浪費磁碟空間。此外,由於「數值資料」在隨機 檔中將以二進位來存放(循序檔以ASCII碼存放),因此當數值資 料位數很長時,使用隨機檔會比較節省磁碟空間。 隨機檔的適用時機 常常需要做線上即時查詢的資料檔。(要求速度) 常常發生資料異動的資料檔。(要求速度) 當開檔後需要可讀可寫時應該使用隨機檔,因為循序資料檔在 開啟檔案時,只能設定為讀取或寫入單一模式。
14.5:隨機檔 【循序檔或隨機檔的原則】: 隨機檔的常用敘述與函數: 1. 磁碟存放空間:若每筆資料的記錄長度差異不大時,應使用隨 機檔。若每筆資料的記錄長度差異很大時,則可使用循序檔,以 節省磁碟空間。 2. 資料存取速度:若要求即時存取資料,則應該使用隨機檔。 隨機檔的常用敘述與函數: 保留字 型態 說 明 Open 敘述 開啟一個檔案。(參數為Random) Close 關閉檔案。 EOF 測試一個檔案是否結束。(檔案指標是否位於最後) LOF 回傳檔案長度(使用檔案代碼)。 FileLen 回傳檔案長度(使用檔名)。 Seek 函數 回傳目前檔案位置。 設定要存取的資料在檔案中位置。 Put 寫入一筆記錄到隨機檔中。 Get 從隨機檔中讀取一筆記錄。
14.5:隨機檔 開啟與關閉隨機檔 開檔 【語法說明】: 1. 使用Open敘述開啟隨機檔,可以透過Len參數指定記錄長度( 單位為Byte),若省略Len參數,則預設值為128 bytes。 2. 當開啟檔案後,若不知道記錄長度時,可以使用Len函數取得 記錄大小。例如:Length = Len (Score_Record) 3. 隨機檔開啟後,可讀取也可寫入。不必像循序檔分為『 Open…For Input』敘述和『Open…For Output』。 語法:Open "檔名" For Random As #檔案代碼[Len = 記錄長度] 功能:以隨機模式開啟檔案。
14.5:隨機檔 語法:Close[#file_num] 功能:關閉檔案 語法:Reset 功能:關閉檔案 關 檔 【語法說明】: 1. 關檔語法與關閉循序檔相同。 2. 執行Reset敘述,會先將緩衝區的資料寫入檔案,然後再關閉 所有檔案。 語法:Close[#file_num] 功能:關閉檔案 語法:Reset 功能:關閉檔案
14.5:隨機檔 存取隨機檔 為了能夠快速取出隨機檔的記錄,因此隨機檔的每一筆記錄都 有一個不同的記錄編號。要搜尋某一筆記錄時,必須在程式中 輸入該筆記錄的編號,由於隨機檔每筆資料長度都是相同的, 因此系統就可以很快地依照公式計算出該記錄編號在隨機檔中 的實際位置,然後將該筆記錄取出。因此隨機檔的資料是可以 隨意存取(不必按照順序),所以平均的存取速度比循序檔快 許多,適合用於時常更動檔案內容的應用。 Put敘述 語法:Put[#]檔案代碼,[記錄編號],變數 功能:寫入一筆資料到隨機檔中。
14.5:隨機檔 語法:Get[#]檔案代碼,[記錄編號],變數 功能:從隨機檔中讀取一資料 【語法說明】: 1. 記錄編號:整數,範圍是1~2,147,483,647。若省略記錄編號, 則會由上一次記錄編號的下一筆開始存取。 2. 變數的長度不能大於隨機檔的記錄長度。 3. 變數的資料型態必須與記錄中各對應欄位的資料型態一致,否 則將產生錯誤。 隨機檔與記錄資料型態 由於記錄資料型態可以將許多不同資料型態的變數聚集在一起 ,並以記錄變數來代表。而在隨機檔的存取語法中,若將變數 指定為記錄型態變數。則可以很容易地取出檔案中的記錄(詳 見範例14-4)。 語法:Get[#]檔案代碼,[記錄編號],變數 功能:從隨機檔中讀取一資料
【實作範例14-4】 【實作範例14-4】:配合記錄資料型態,存取隨機檔的資料 上機實作 Step1:專案名稱為『p14_04』。
【實作範例14-4】 b14_04.bas 1 2 3 4 5 6 7 8 9 10 Public file_no As Integer Public Record_Amount As Integer Public Type Score_Record stu_id As String * 8 S_Computer As Integer S_Math As Integer S_Eng As Integer S_Avg As Integer End Type Public Student As Score_RecordEnd Sub
【實作範例14-4】 f14_04_main.frm 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 Private Sub cmdInput_Click() file_no = FreeFile Open "c:\vb6\ch14\14_04\Score.dat" For Random As #file_no Len = Len(Student) Record_Amount = LOF(file_no) / Len(Student) f14_04_Input.Show 1 End Sub Private Sub cmdQuery_Click() file_no = FreeFile Open "c:\vb6\ch14\14_04\Score.dat" For Random As #file_no Len = Len(Student) Record_Amount = LOF(file_no) / Len(Student) f14_04_Query.Show 1 End Sub Private Sub Form_Unload(Cancel As Integer) Close #file_no End End Sub
【實作範例14-4】 f14_04_Input.frm 5 6 7 8 10 15 17 18 19 20 21 22 23 25 26 27 28 29 30 31 32 33 34 35 Private Sub cmdAddNext_Click() Call AddRecord Form_Load End Sub Private Sub Form_Load() txtId = "" : txtComputer = "" : txtMath = "" : txtEng = "" End Sub Private Sub Form_Unload(Cancel As Integer) If (txtId <> "") And (txtComputer <> "") _ And (txtMath <> "") And (txtEng <> "") Then Call AddRecord End If Close #file_no End Sub Private Sub AddRecord() Record_Amount = Record_Amount + 1 With Student .stu_id = txtId .S_Computer = Val(txtComputer) .S_Math = Val(txtMath) .S_Eng = Val(txtEng) .S_Avg = CInt((.S_Computer + .S_Math + .S_Eng) / 3) End With Put #file_no, Record_Amount, Student End Sub
【實作範例14-4】 f14_04_Query.frm 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 Private Sub cmdQuery_Click() If (Val(cboRecordNo.Text) <= 0) Or _ (Val(cboRecordNo.Text) > Record_Amount) Then MsgBox "請選擇正確的記錄編號" Exit Sub End If Get #file_no, Val(cboRecordNo.Text), Student With Student txtId = .stu_id txtComputer = .S_Computer txtMath = .S_Math txtEng = .S_Eng txtAvg = .S_Avg End With End Sub Private Sub Form_Load() cboRecordNo.Clear For i = 1 To Record_Amount cboRecordNo.AddItem (i) Next i End Sub Private Sub Form_Unload(Cancel As Integer) Close #file_no End Sub
14.6:『磁碟機清單方塊』、『目錄清單方塊』、『檔案清單方塊』控制項 當我們在操作許多軟體執行存檔與開檔的動作時,常常會出 現對話方塊讓我們選擇檔案的路徑與檔名,在Visual Basic中 ,我們可以透過「磁碟機清單方塊」、「目錄清單方塊」和 「檔案清單方塊」等三個控制項來完成下圖的檔案讀取操作 。 磁碟機清單方塊 目錄清單方塊 檔案清單方塊
14.6:『磁碟機清單方塊』、『目錄清單方塊』、『檔案清單方塊』控制項 磁碟機清單方塊(Drive List Box) 「磁碟機清單方塊」是一種下拉式清單方塊。在預設狀況下 ,它會顯示目前正使用的磁碟機。若按下 下拉鈕,則未列 出所有可用的磁碟機,使用者可以從中挑選一個磁碟機做為 目前的磁碟機。 建立『磁碟機清單方塊』控制項 2:在表單上拉出磁碟機 清單方塊控制項大小 1:選取磁碟機 清單方塊工具
14.6:『磁碟機清單方塊』、『目錄清單方塊』、『檔案清單方塊』控制項 磁碟機清單方塊的屬性 屬性 說明 Name 磁碟機清單方塊的名稱。 Drive Drive是磁碟機清單方塊非常重要的屬性,是用來 設定目前的工作磁碟。(只能在執行時被設定) Height 磁碟機清單方塊的高度。 Width 磁碟機清單方塊的寬度。
14.6:『磁碟機清單方塊』、『目錄清單方塊』、『檔案清單方塊』控制項 目錄清單方塊(Directory List Box) 「目錄清單方塊」代表目前作用磁碟目錄,使用者可以選取 清單中的任一個目錄做為路徑(選取時,按滑鼠兩下即可) 。 建立『目錄清單方塊』控制項 2:在表單上拉出目錄 清單方塊控制項大小 1:選取目錄 清單方塊工具
14.6:『磁碟機清單方塊』、『目錄清單方塊』、『檔案清單方塊』控制項 目錄清單方塊的屬性 屬性 說明 Name 目錄清單方塊的名稱。 Path Path是目錄機清單方塊非常重要的屬性,是用來設 定目前的工作目錄。(只能在執行時被設定) Height 目錄清單方塊的高度。 Width 目錄清單方塊的寬度。
14.6:『磁碟機清單方塊』、『目錄清單方塊』、『檔案清單方塊』控制項 檔案清單方塊(File List Box) 「檔案清單方塊」將會把目前工作目錄下的所有檔案列出, 使用者在其中挑選檔案。 建立『檔案清單方塊』控制項 2:在表單上拉出檔案 清單方塊控制項大小 1:選取檔案 清單方塊工具
14.6:『磁碟機清單方塊』、『目錄清單方塊』、『檔案清單方塊』控制項 檔案清單方塊的屬性 在Visual Basic IDE中拉出磁碟機、目錄、檔案清單方塊時, 其預設的磁碟、目錄、檔案為「Visual Basic的安裝位置」, 當您將程式存檔或編譯之後再執行,則磁碟、目錄、檔案會 變成執行檔的所在位置。 屬性 說明 FileName 設定或回傳被選取的檔案名稱,預設值為空字串。(只能在程 式執行中使用) Path 程式執行時,列出指定目錄下所包含的檔案。 Pattern 設定列出一組以上具有指定檔名或副檔名的檔案,預設值為『 "*.*"』。例如:『"*.vbp;*.frm"』。 Archive 列出所有「可備份」的檔案,預設值為True。 Hidden 列出所有「隱藏」的檔案,預設值為False。 Normal 列出所有非「系統」和非「隱藏」的檔案,預設值為True。 ReadOnly 列出所有「唯讀」的檔案,預設值為True。 System 列出所有「系統」檔案,預設值為False。
14.6:『磁碟機清單方塊』、『目錄清單方塊』、『檔案清單方塊』控制項 『磁碟機、目錄、檔案清單方塊』程式設計 「磁碟機」、「目錄」與「檔案」三種清單方塊控制項,通常會被 一起搭配使用,並且可以利用Change事件修改屬性值使得改變其中 一個控制項時,其它控制項也隨著改變。 舉例來說,當使用者在「磁碟機清單方塊」中選取某一個磁碟機時 ,「磁碟機清單方塊」的Drive屬性值會馬上變為選取的磁碟機,並 且觸發Change事件,此時,我們可以在Change事件中,將新的 Drive屬性值傳送給「目錄清單方塊」。同理,我們也可以將「目錄 清單方塊」的新Path屬性值,在Change事件中傳給「檔案清單方塊 」,然後列出該資料夾的檔案。下圖是事件與屬性的示意圖:
14.6:『磁碟機清單方塊』、『目錄清單方塊』、『檔案清單方塊』控制項 除了上述介紹的屬性之外,Visual Basic還提供了一些有關資料夾與 檔案維護的敘述如下: 【範例】: 【註】:當使用者在磁碟機清單方塊中選取了某一個新 的磁碟機,目前工作磁碟並自動隨著改變,我們必須透 過ChDrive敘述來設定新的磁碟機代碼。例如:ChDrive Drive1.Drive。 敘述 語法 功能 ChDrive ChDrive 磁碟機 設定目前工作的磁碟機代碼 ChDir ChDir 資料夾 設定目前工作的資料夾名稱 RmDir RmDir 資料夾 刪除指定的資料夾 Kill Kill 檔名 刪除指定的檔案 MkDir MkDir 資料夾 建立新的資料夾 Name Name 舊檔名 As 新檔名 修改檔案名稱或搬移檔案 ChDrive "C:" ChDrive Drive1.Drive ChDir "\vb6\ch14" ChDir Dir1.Path
14.6:『磁碟機清單方塊』、『目錄清單方塊』、『檔案清單方塊』控制項 【範例】: 【搬移檔案注意事項】:不同磁碟機的檔案則無法搬移 (舊檔名與新檔名必須在同一磁碟機),舊檔名之檔案 必須存在,新檔名之檔案不可以存在,否則會發生錯誤 。 MkDir "C:\TEST" '在C磁碟機中建立TEST資料夾 RmDir "C:\TEST" '刪除C磁碟機的TEST資料夾 Kill "Score.dat" '刪除目前目錄下的Score.dat Kill "C:\TEST1\*.bas" '刪掉C磁碟機TEST1資料夾中所有附檔名為『.bas』的檔案 Name "TEST1.dat" As "TEST2.txt" '將目前目錄下的TEST1.dat檔名改為TEST2.txt Name "C:\TEST1" As "C:\TEST2" '更改目錄名稱。 Name "C:\TEST1\TEST1.dat" As "C:\TEST2\TEST1.dat" '將檔案搬移到另一目錄下。 Name "C:\TEST1\TEST1.dat" As "C:\TEST2\TEST2.txt" '將檔案搬移並修改檔名。
【實作範例14-5】 【實作範例14-5】:使用磁碟機、目錄和檔案清單方塊設計 一個預覽圖片的程式。 上機實作 Step1:專案名稱為『p14_05』。 Step2:在表單上產生下列控制項並設定屬性。 Step3:編輯程式碼。 Step4:執行程式。
【實作範例14-5】 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 Private Sub dirView_Change() '設定目錄 ChDir dirView.Path filView.Path = dirView.Path End Sub Private Sub drvView_Change() '設定磁碟機 ChDrive drvView.Drive dirView.Path = drvView.Drive End Sub Private Sub filView_Click() '在檔案列選取檔名 lblFilename = "檔名:" & filView.FileName imgView.Picture = LoadPicture(filView.FileName) End Sub Private Sub Form_Load() drvView.Drive = App.Path dirView.Path = App.Path + "\Picture\" filView.Path = dirView.Path txtFilePattern = "*.Bmp;*.Jpg;*.Gif" filView.Pattern = txtFilePattern.Text lblFilename = "" End Sub Private Sub txtFilePattern_Change() filView.Pattern = txtFilePattern End Sub
14.7:通用型對話方塊 (Common Dialog) 『磁碟機』、『目錄』、『檔案清單』方塊雖可以製作指定 存取檔名的功能,但似乎和某些軟體的開檔、存檔對話方塊 有些不同,而且這三個物件的屬性值並不會自動互相更新而 必須透過程式來自行設定,如此顯得不是很方便。 其實Visual Basic含提供了另一種更好用的「通用型對話方塊 」控制項,該控制項的功能十分強大,可以用來製作開檔、 存檔、設定顏色、改變字型、列印、執行說明檔等六種對話 方塊。 由於「標準執行檔」的工具箱並未提供「通用型對話方塊」 工具。因此要使用「通用型對話方塊」工具,必須在建立新 專案時選取「Visual Basic普及版控制項」圖示,工具箱才會 出現「通用型對話方塊」工具以及其他標準執行檔所不提供 的工具。
1:選取「Visual Basic 普及版控制項」圖示 14.7:建立『通用型對話方塊』 建立『通用型對話方塊』 1:選取「Visual Basic 普及版控制項」圖示 2:按下 【開啟】鈕 3:按兩下 通用型對話方塊工具 4:在表單上出現了通用型對話方塊控制項
14.7:建立『通用型對話方塊』 Name屬性 CancelError屬性 1:按下 2:開啟『屬性頁』 對話方塊 『通用型對話方塊』的屬性 『屬性頁』對話方塊: 通用型對話方塊的屬性眾多,首先我們在屬性視窗中選取(自訂)後將出現 「屬性頁」對話方塊,預設標籤頁為『開啟/另存為』標籤頁,當中可以 設定許多關於開檔與存檔的屬性設定。 Name屬性 CancelError屬性 1:按下 2:開啟『屬性頁』 對話方塊
14.7:建立『通用型對話方塊』 各類對話方塊共同屬性: 「開啟/另存為」標籤頁 CancelError (取消) 說明 CancelError (取消) 當使用者按【取消】鈕時,是否產生錯誤值。True : 產生錯誤值。False(預設值):不產生錯誤值。 Name (名稱) 通用型對話方塊的名稱。 DialogTitle Flags FileName DefaultExt InitDir MaxFileSize Filter FilterIndex CancelError
14.7:建立『通用型對話方塊』 屬性 說明 DialogTitle (對話方塊標題) 設定對話方塊標題 DefaultExt (預設副檔名) 預設的副檔名。(例如:dlg1.DefaultExt=".txt") Filter (檔案類型) 設定在檔案清單方塊顯示的檔案類型。語法如下: 通用型對話方塊名稱.Filter=提示字串1|檔案類型1| 提示字串2|檔案類型2|… (例如:dlg1.Filter="Word檔(*.doc)|*.doc|純文字檔 (*.txt)|*.txt" FilterIndex (類型索引) 設定採用Filter屬性設定的第幾個檔案類型。 FileName (檔案名稱) 取得使用者選擇的檔案名稱(含路徑)(只能在程式 執行時使用)。 FileTitle (檔案標題) 取得使用者選擇的檔案名稱(不含路徑) (只能在程 式執行時使用)。 initDir (初始目錄) 設定起始目錄
14.7:建立『通用型對話方塊』 屬性 說明 MaxFileSize (檔案長度限制) 設定檔案的最大長度,其值為1~32K Bytes。 Flags (選項) 設定對話方塊要顯示的項目。 Flags = &H1&:「唯讀」核取方塊處於已設定狀態 Flags = &H2&:當選取的檔案已經存在資料夾中, 則會出現詢問是否覆蓋檔案的訊息方塊。 Flags = &H4&:隱藏「唯讀」核取方塊。 Flags = &H8&:當對話方塊開啟時,目前資料夾將 是實際所在資料夾。 Flags=&H2000&:開啟一個不存在的檔案時,發出 提示。
14.7:建立『通用型對話方塊』 【執行範例】:(使用ShowOpen方法) ShowOpen 標題
14.7:建立『通用型對話方塊』 【執行範例】:(使用ShowSave方法) ShowSave
14.7:建立『通用型對話方塊』 「色彩」標籤頁 Color Flags 屬性 說明 Color(顏色) 設定顏色值。(內定為0,也就是&H00000000&) Flags(選項) 設定色彩對話方塊要顯示的項目。 Flags = &H1&:顯示預設的色彩對話方塊。 Flags = &H2&:顯示完整的色彩對話方塊。 Flags = &H4&:設定【自選色彩】鈕為失效。 Flags = &H8&:顯示【輔助說明功能】鈕。 Flags值和MsgBox的參數類似,也是可以相加的,例如: Flages=&H6&代表同時具有『&H2&』和『&H4&』兩種功能
14.7:建立『通用型對話方塊』 【執行範例】:(使用ShowColor方法)
14.7:建立『通用型對話方塊』 「字型」標籤頁 Min Max FontName FontBold FontSize FontItalic Flags FontUnderLine FontStrikethru
14.7:建立『通用型對話方塊』 屬性 說明 FontName (字型名稱) 設定字型檔名稱欄。 FontSize (字型大小) 設定字型大小欄。 FontBold (粗體) 設定粗體字。 FontItalic (斜體) 設定斜體字。 FontStrikethru (刪除線) 設定加刪除線。 FontUnderLine (底線) 設定加底線。 Flags (選項) 設定要顯示字型的項目。常用的Flags值: Flags = &H1&:只顯示螢幕支援的字型。 Flags = &H2&:只顯示列表機支援的字型。 Flags = &H3&:顯示支援螢幕或列表機支援的字型。 Flags = &H4&:顯示【說明】按鈕。 Max (最大) 允許使用者可選擇最大字型的大小。 Min (最小) 允許使用者可選擇最小字型的大小。
14.7:建立『通用型對話方塊』 【執行範例】:(使用ShowFont方法)
14.7:建立『通用型對話方塊』 「列印」標籤頁 ToPage Flags Copies FromPage Min Max PrintDefault
PrinterDefault (印表機預設值) 14.7:建立『通用型對話方塊』 屬性 說明 Copies (列印份數) 設定列印的份數。 FromPage (從第幾頁開始) 設定從第幾頁開始列印。 ToPage (到第幾頁) 設定列印到第幾頁。 Max(最大) 設定列印範圍的最大頁數。 Min(最小) 設定列印範圍的最小頁數。 Flags (選項) 設定列印對話方塊要顯示的項目。常用的Flags值: Flags = &H0&:列印範圍預設為全部。 Flags = &H1&:列印範圍預設為選取範圍。 Flags = &H2&:列印範圍預設為頁數。 PrinterDefault (印表機預設值) 設定是否允許使用者更改系統列表機的設定。(預設 為True)
14.7:建立『通用型對話方塊』 【執行範例】:(使用ShowPrinter方法)
14.7:建立『通用型對話方塊』 通用型對話方塊的方法 「通用型對話方塊」控制項和「計時器」控制項一樣,當程 式執行時,並不會顯現出來,而要顯示不同種類的對話方塊 ,則必須透過程式指定執行不同的方法來完成,一共有6種不 同的方法如下。 舉例來說,假設 我們要希望程式 會跑出字型設定的對話方塊,則可以先在字型標籤頁中設定 相關屬性,然後在程式中執行ShowFont方法,如此一來,就 會出現字型對話方塊了。(在字型標籤頁中設定不同的屬性 值將導致字型方塊的內容也會有所不同) 方法 結果 ShowOpen 開啟開檔對話方塊 ShowSave 開啟存檔對話方塊 ShowColor 開啟色彩對話方塊 ShowFont 開啟字型對話方塊 ShowPrinter 開啟列印對話方塊 ShowHelp 開啟設定的說明檔
14.8:例外處理 例外處理 所謂例外處理,就是當程式執行發生錯誤時,就去自動執行另 外一段程式碼,這段程式碼將會處理這些錯誤。而程式正常運 作時,則不會執行這些程式碼。Visual Basic有關例外處理的 敘述有『On Error GoTo』與『Resume』敘述。 On Error GoTo敘述 【語法說明】: 1. 若行號為 0,則取消錯誤處理。 2. 錯誤處理次常式以行號或標記為起點,當作例外處理用的次常 式。 語法:On Error Goto {行號∣標記} 功能:當程式執行發生錯誤時,跳到指定的行號或標記去執行另外一段程式(錯誤處理次常式)。
14.8:例外處理 語法:Resume {0∣Next∣行號∣標記} 功能:執行錯誤處理次常式後,回到指定位置繼續執行程式。 【語法說明】: 依照Resume後面敘述的不同,改變程式的流程。一共有下列幾 種敘述: 語法:Resume {0∣Next∣行號∣標記} 功能:執行錯誤處理次常式後,回到指定位置繼續執行程式。 敘 述 繼續執行的位置 Resume [0]或Resume 跳到程式發生錯誤的位置繼續執行。 Resume Next 跳到程式發生錯誤的下一行繼續執行。 Resume行號 跳到指定的行號繼續執行。 Resume標記 跳到指定的標記繼續執行。
14.9:本章整合應用實例 (簡易文書編輯器製作) 14.9:本章整合應用實例 (簡易文書編輯器製作) 【實作範例14-6】:利用本章所學習的各項檔案函數與通用 型對話方塊,製作一個簡易型的文書編輯器。 上機實作 Step1:專案名稱為『p14_06』。 Step2:在表單上產生下列控制項並設定屬性。 Step3:編輯程式碼。 Step4:執行程式。
【實作範例14-6】 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 Dim Default_Directory, file_name As String Dim file_no As Integer Private Sub Form_Load() txtEditor.Width = f14_06.Width – 100 txtEditor.Height = f14_06.Height – 700 Default_Directory = "c:\VB6\ch14\14_06\" dlgEditor.CancelError = True dlgEditor.FontSize = 12 txtEditor = "" End Sub Private Sub Form_Resize() txtEditor.Width = f14_06.Width – 100 txtEditor.Height = f14_06.Height – 700 End Sub Private Sub Form_Unload(Cancel As Integer) Close #file_no End End Sub
【實作範例14-6】 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 Private Sub mnuExit_Click() Close #file_no End End Sub Private Sub mnuFontColor_Click() '色彩 On Error GoTo COLOR_ERROR dlgEditor.Flags = &H4& dlgEditor.ShowColor txtEditor.ForeColor = dlgEditor.Color Printer.ForeColor = dlgEditor.Color On Error GoTo 0 Exit Sub COLOR_ERROR: On Error GoTo 0 Exit Sub End Sub
【實作範例14-6】 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 Private Sub mnuFontStyle_Click() '字型 On Error GoTo FONT_ERROR dlgEditor.FontName = "細明體" dlgEditor.Flags = &H3& dlgEditor.ShowFont txtEditor.FontName = dlgEditor.FontName txtEditor.FontSize = dlgEditor.FontSize txtEditor.FontBold = dlgEditor.FontBold txtEditor.FontItalic = dlgEditor.FontItalic Printer.FontName = dlgEditor.FontName Printer.FontSize = dlgEditor.FontSize Printer.FontBold = dlgEditor.FontBold Printer.FontItalic = dlgEditor.FontItalic On Error GoTo 0 Exit Sub FONT_ERROR: On Error GoTo 0 Exit Sub End Sub Private Sub mnuNewFile_Click() '開新檔案 file_name = "" txtEditor = "" f14_06.Caption = "(簡易編輯器)" & "-未命名" End Sub
【實作範例14-6】 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 Private Sub mnuOpenFile_Click() '開啟舊檔 On Error GoTo OPENFILE_ERROR dlgEditor.InitDir = Default_Directory dlgEditor.Filter = "Word*.doc|*.doc|文書檔*.txt|*.txt" dlgEditor.FilterIndex = 2 dlgEditor.ShowOpen file_name = dlgEditor.FileName lblFileName = "檔名:" f14_06.Caption = "(簡易編輯器)" & "-" & dlgEditor.FileTitle file_no = FreeFile : txtEditor="" Open file_name For Input As #file_no Do While Not EOF(file_no) Line Input #file_no, Linestr txtEditor = txtEditor + Linestr + vbCrLf Loop Close #file_no On Error GoTo 0 Exit Sub OPENFILE_ERROR: On Error GoTo 0 Exit Sub End Sub
【實作範例14-6】 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 Private Sub mnuPrintFile_Click() '列印 On Error GoTo PRINTFILE_ERROR dlgEditor.Copies = 1 dlgEditor.Flags = &H0& dlgEditor.ShowPrinter For i = 1 To dlgEditor.Copies Printer.Print txtEditor Printer.NewPage Next i Printer.EndDoc On Error GoTo 0 Exit Sub PRINTFILE_ERROR: MsgBox "列印發生錯誤,請檢查印表機" On Error GoTo 0 Exit Sub End Sub
112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 Private Sub mnuSaveAsFile_Click() '另存新檔 On Error GoTo SAVEASFILE_ERROR dlgEditor.FilterIndex = 2 dlgEditor.InitDir = Default_Directory dlgEditor.Filter = "Word*.doc|*.doc|文書檔*.txt|*.txt" dlgEditor.ShowSave file_name = dlgEditor.FileName file_no = FreeFile Open file_name For Output As file_no Print #file_no, txtEditor Close #file_no f14_06.Caption = "(簡易編輯器)" & "-" & dlgEditor.FileTitle On Error GoTo 0 Exit Sub SAVEASFILE_ERROR: On Error GoTo 0 Exit Sub End Sub Private Sub mnuSaveFile_Click() '存檔 If file_name = "" Then mnuSaveAsFile_Click Exit Sub End If file_no = FreeFile Open file_name For Output As file_no Print #file_no, txtEditor Close #file_no End Sub
本章回顧 檔案類型 存取檔案 循序檔 記錄(Record) 隨機檔 『磁碟機清單方塊』、『目錄清單方塊』、『檔 案清單方塊』控制項 通用型對話方塊 (Common Dialog) 例外處理 簡易文書編輯器製作
本章習題