Share via


嗨,Scripting Guy!

嗨,Scripting Guy!

歡迎使用 TechNet 專欄,Microsoft Scripting Guys 會在此為您解答有關系統管理指令碼的常見問題。您有關於系統管理指令碼方面的問題嗎?請將電子郵件傳送到 scripter@microsoft.com。我們無法保證能夠逐一回答每個問題,不過我們會盡力而為。

還有,別忘了瞧瞧全新經過改良的嗨,Scripting Guy!過往文件

今天的問題:如何使用 ADO 讀取以一行呈現所有資料的文字檔案?


如何使用 ADO 讀取以一行呈現所有資料的文字檔案?

嗨,Scripting Guy!我有一個固定寬度的文字檔案,裡頭包含名字 (6 個字元)、姓氏 (13 個字元) 和部門 (9 個字元),通通擠在一行。要怎麼使用 ADO 讀取資料呢?

-- DW

DW,您好。老實說,我們認為使用 ADO (ActiveX Data Objects) 沒辦法讀取像這樣的檔案。用 ADO 處理文字檔案是不錯的方法 (詳細資訊請參閱<Much ADO About Text Files>一文),但 ADO 其實有點大牌,沒準備好休想叫她表演 (哪像 Scripting Guy,就算準備好了也不想工作)。就資料庫技術而言,套一句 XML 的用詞,ADO 需要有格式正確 (well-formed) 的資料庫,所以根本沒法拿您的檔案製作出資料庫 (在本例中就是把黏成一團的一行資料分成幾筆記錄)。

沒關係,我們可以使用老牌又好用的 VBScript 來建立格式正確的資料庫。今天我們就來介紹怎麼簡單快速地把一長串連續資料切成一筆筆的記錄,再把個別的記錄 (例如文字檔案中的個別記錄) 回應至畫面中就可以了。您也可以把這些資料行寫入另一個文字檔,再使用 ADO 讀取第二個文字檔。反正今天的目的是領您開頭,剩下來的就讓各位讀者接手。

一開始先假設有一個文字檔,長得向下面一樣,其中欄為名稱和好幾筆記錄都黏成一行。

First Last         Dept     Ken   Meyer        Finance  Pilar Ackerman     HR

希望成果是這樣的:

First Last         Dept     
Ken   Meyer        Finance  
Pilar Ackerman     HR

有辦法嗎?當然沒問題:

Const ForReading = 1
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objFile = objFSO.OpenTextFile("C:\Scripts\Test.txt", ForReading)
strContents = objFile.ReadAll
objFile.Close
i = False
Do Until i = True 
    intLength = Len(strContents)
    If intLength < 28 Then
        Exit Do
    End If
    strLines = strLines & Left(strContents, 28) & vbCrLf
    strContents = Right(strContents, intLength - 28)
Loop
Wscript.Echo strLines

首先定義一個叫做 ForReading 的常數,然後把常數的值設為 1,再用它來開啟文字檔以便閱讀。

 

附註:還記得媽媽總是叮嚀衣服要穿暖,過馬路要看兩邊嗎?咱們 Scripting Guys 也總是提醒讀者,要開啟文字檔案,一定要指定用哪種方法開啟:是用讀取、寫入還是附加,要講清楚,而且一次只能用一種方式,不能同時用讀取和寫入的方法開啟文字檔,所以我們才要用 ForReading 這個常數。

對了,衣服要穿好,外頭的確很冷。


接著要建立 FileSystemObject 的執行個體,並使用 OpenTextFile 方法來開啟 C:\Scripts\Test.txt 檔案。然後使用 ReadAll 方法把文字檔中全部的內容讀取到變數 strContents 中,再使用 Close 方法關閉檔案。

接下來是這小段有趣的程式碼:

i = False

稍後要設定一個 Do 迴圈,每 28 個字元就讀取檔案內容 (再叮嚀一次,值是變數 strContents)。為什麼是 28 呢?這麼說好了,每筆記錄中都替名字保留了 6 個字元,姓氏是 13 個字元,部門則為 9 個字元。所以:

6 + 13 + 9 = 28

為了使迴圈能夠執行整個檔案,要將變數 i 設定為 False,接著告訴迴圈一直執行到 i 等於 True 為止。

Do Until i = True

結果 i 永遠都不會變成 True,別擔心,還是有辦法從迴圈中離開的,等會就讓您瞧瞧魔術師胡迪尼是怎麼脫身的。

先在迴圈使用 Len 函式,判斷字串 strContents 裡面有幾個字元 (範例檔案裡如果也計入標題行,那麼每筆記錄會有 28 個字元,乘以 3 比記錄就等於 84),結果就是這小段程式碼:

If intLength < 28 Then
    Exit Do
End If

這裡的目的是檢查字串長度否小於 28 個字元,如果是,就表示已經到達檔案末端,可以使用 Exit Do 命令離開迴圈。(這就是神奇的 Scripting Guy 從一圈圈無止無休的 Do 迴圈脫身的方法!)

假設長度是 28 個字元過更多,則執行這行指令碼:

strLines = strLines & Left(strContents, 28) & vbCrLf

這裡要建立一個新的字串 strLines,把文字檔案的內容分成數筆記錄。每筆記錄由 28 個字元和一個換行字元 (vbCrLf) 所組成。方法很簡單,只要把目前的 strLine 目前的內容和字串裡的第一組 28 個字元合在一起 (也就是 Left 函式的功能) 加上 VBScript 常數 vbCrLf 就可以了。第一次跑過迴圈後,strLines 的結果是:

First Last         Dept

看到它是怎麼運作的吧?

第一行 (第一筆記錄) 從變數 strLines 中取出後,需要把這些資訊從 strContents 中刪除。這個動作是由這段程式碼進行:

strContents = Right(strContents, intLength - 28)

然後使用 Right 函式反其道而行,從自串尾端取得數目為 x 的字串。所謂 x 個字元數到底是什麼意思呢?計算 x 的方法是這樣的,先取得 strContents 字串的長度 (84),扣掉每筆記錄的長度 28。84 – 28 的結果就等於 56,所以就從字串末端往前推算 56 個字元,第一次跑過迴圈後結果是:

Ken   Meyer        Finance  Pilar Ackerman     HR
附註:當然還有其他的方式,有些可以少寫一兩行指令碼,但我們認為這種方式最直接了當。


剛才只不過是移除了第一筆記錄。現在再跑一次迴圈,重複剛才的流程。當然這一次 strContents 的長度就是 56,因為剛才已經扣掉了 28 個字元。所以要取出這筆資料並添加至變數 strLines 內:

Ken   Meyer        Finance

我們持續這個步驟,直到把 strContents 變數內的字元跑完為止,最後回應 strLines 的值:

First Last         Dept     
Ken   Meyer        Finance  
Pilar Ackerman     HR

如果這樣還不算格式正確的資料庫,那我就沒話說了。

剛才提過,如果讀者有興趣,可以把資料存成文字檔再使用 ADO 讀取,或使用 VBScript 的字串處理函式把每一行分成個別的記錄。這就讓讀者自己琢磨吧。

喔,另外還有一件事:天氣冷,要穿暖一些喔。


如需詳細資訊

查看嗨,Scripting Guy!- 過往文件

 

回到頁首 回到頁首