Scripting Guy 為您解答問題

Hey, Scripting Guy!

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

資源

如何將 .CSV 檔匯入 Access 資料庫?

Hey, Scripting Guy! Question

嗨,Scripting Guy!如何將 .CSV 檔匯入 Access 資料庫?

        -- CS

Hey, Scripting Guy! Answer

CS,您好。我們將馬上切入您的問題。不過,首先,我們想要分享一些對「第 41 屆超級杯足球聯賽」的想法:

撰寫本專欄的 Scripting Guy 認為比賽大致上而言還不錯,不過,這也讓他更堅信大學美式足球賽比職業美式足球賽更有娛樂性。畢竟,Colts 隊完全主導了比賽,雖然他們原本可能會輕易地輸球;原因大部分在於他們老是只想射門得分,而不是努力爭取達陣的機會。Colts 隊甚至一度從 36 碼線踢球。事實是,NFL 太過保守。撰寫本專欄的 Scripting Guy 預見未來某一天,「超級杯足球聯賽」將完全由兩個球隊來回踢球,直到有人接到反彈球而達陣或在球門區漏接球為止。

附註:當然,這也許是件好事:畢竟,當情勢變成最怕冒險的球隊保證會獲勝的時候,這樣我們自己的「西雅圖海鷹隊」最後將成為「超級杯足球聯賽」的冠軍。

再來呢?另外一點就是:撰寫本專欄的 Scripting Guy 一直不懂「超級杯足球聯賽」電視廣告的大肆宣傳手法,而且今年的這批廣告也不怎麼樣。有時候,他會看著廣告想:「為什麼這會想讓我買他們的產品?」至少有一次的情況是他看著廣告,想著:「他們到底是賣什麼產品?」而且,至少有一個廣告已經播放一兩年了。但是,我們假設您花費 $250 萬美元購買廣告時段後,大概就沒有錢來支付新的廣告費了。

有趣的是,有一則廣告對撰寫本專欄的 Scripting Guy 造成巨大影響,雖則說這不是原本預期造成的影響。在該則廣告中,有個機器人在汽車裝配線上掉了個螺絲釘,然後便立即被開除。他嘗試找其他工作,但是卻不太適合:雖然他會組裝汽車,不過無法在速食餐廳工作。最後,當他想要從橋上跳下時,還好他醒了過來,發現一切只是一場夢。

不可否認,這是一部很不錯的催淚廣告:您可能會情不自禁地同情這個小機器人。但是,一想到美國汽車公司近幾年陷入困境,這部廣告確實對美國汽車工業員工傳達了一則有趣的訊息:只要犯點小錯,就會被開除。而且,您知道嗎?如果您會組裝汽車,就表示將來無法在其他地方找到工作。您唯一可以做的事,就是從橋上跳下,然後結束一切。

這樣應該能激勵員工士氣吧?

最後要說的是,撰寫本專欄的 Scripting Guy 並沒有觀賞中場表演。但是,他看了一兩分鐘的賽前表演。不過,當他看到假裁判騎著假鴕鳥全場跑時,他就決定要去看看是不是有髒衣服要洗。如果沒有,他寧願在泥巴裡打滾,好一些髒衣服來洗。

附註:基於某些原因,在「第 41 屆超級杯足球聯賽」之前,當撰寫本專欄的 Scripting Guy 想到美式足球賽時,他從不會聯想到「太陽馬戲團」。

那麼,上述內容對於您將 .CSV (逗點分隔值) 檔匯入 Access 資料庫有任何幫助嗎?大概沒有,但是下列內容應該會有幫助:

Script Center
    Const adOpenStatic = 3
    Const adLockOptimistic = 3
    Const ForReading = 1
    
    Set objConnection = CreateObject("ADODB.Connection")
    Set objRecordSet = CreateObject("ADODB.Recordset")
    
    objConnection.Open _
        "Provider = Microsoft.Jet.OLEDB.4.0; " & _
            "Data Source = c:\scripts\test.mdb" 
    
    objRecordSet.Open "SELECT * FROM Employees", _
        objConnection, adOpenStatic, adLockOptimistic
    
    Set objFSO = CreateObject("Scripting.FileSystemObject")
    Set objFile = objFSO.OpenTextFile("C:\Scripts\Test.txt")
    
    Do Until objFile.AtEndOfStream
        strEmployee = objFile.ReadLine
        arrEmployee = Split(strEmployee, ",")
    
        objRecordSet.AddNew
        objRecordSet("EmployeeID") = arrEmployee(0)
        objRecordSet("EmployeeName") = arrEmployee(1)
        objRecordSet("Department") = arrEmployee(2)
        objRecordSet.Update
    
    Loop
    
    objRecordSet.Close
    objConnection.Close

老實說,我們也不知道任何可以直接將逗點分隔值檔案匯入 Access 資料庫的方法 (並不是沒有這種方法,只是我們不知道而已)。不過,使用指令碼來開啟 .CSV 檔,然後「手動」將新資料錄加入至資料庫卻相當簡單。這就是我們的做法。

CS,我們假設您已經建立了 Access 資料庫。針對範例指令碼,我們使用了名為 C:\Scripts\Test.mdb 的資料庫。在該資料庫內部,我們設有一個名為 Employees 的資料表。這個資料表包含三個欄位:

  • EmployeeID

  • EmployeeName

  • Department

您可能會猜想,文字檔 (C:\Scripts\Test.txt) 也包含三個欄位。所以:

1989,Ken Myer,Finance
1990,Pilar Ackerman,Research
1991,Jonathan Hass,Human Resources

在此情況下,我們有三個要加入至資料庫的新員工。進行這項作業的方法如下。

我們一開始先定義三個常數:adOpenStatic 和 adLockOptimistic (用於處理資料庫),以及 ForReading (用於處理文字檔)。然後,使用下列程式碼區塊來開啟 Test.mdb 並建立資料錄集 (其中包含 Employees 資料表中的所有項目):

Set objConnection = CreateObject("ADODB.Connection")
Set objRecordSet = CreateObject("ADODB.Recordset")

objConnection.Open _
    "Provider = Microsoft.Jet.OLEDB.4.0; " & _
        "Data Source = c:\scripts\test.mdb" 

objRecordSet.Open "SELECT * FROM Employees", _
    objConnection, adOpenStatic, adLockOptimistic

您可能會感到奇怪,上述所有程式碼幾乎都是可直接使用的現成程式碼。您唯一可能需要變更的就是資料庫檔案的路徑和資料表的名稱。

開啟資料庫之後,下一步就是要開啟文字檔。若要這樣做,我們要先建立 Scripting.FileSystemObject 的執行個體,然後使用 OpenTextFile 方法來開啟 Test.txt 檔,以便進行讀取:

Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objFile = objFSO.OpenTextFile("C:\Scripts\Test.txt")

接下來我們就要開始將資料錄加入至資料庫了。首先,我們要設定一個執行到文字檔結尾為止的 Do Until 迴圈 (也就是,直到 AtEndOfStream 屬性為 True 為止)。在該迴圈內部,我們要使用 ReadLine 方法,從文字檔的第一行開始讀取,然後將該值儲存在名為 strEmployee 的變數中:

strEmployee = objFile.ReadLine

這是什麼意思呢?這表示當時 strEmployee 等於:

1989,Ken Myer,Finance

這樣確實有效,但是卻幫助不大:我們需要從該字串剖析個別欄位值。所幸,我們可以使用 Split 函數並以逗點分隔字串來完成此作業:

arrEmployee = Split(strEmployee, ",")

這樣會有什麼結果?這樣會產生包含下列三個項目的陣列 (名為 arrEmployee):

  • 1989

  • Ken Myer

  • Finance

您猜會怎麼樣?這三個項目都剛好對應至資料庫中的三個欄位。

如此一來,這表示我們現在可以將 Ken Myer 加入至資料庫。若要這樣做,我們可以呼叫 AddNew 方法,將新資料錄加入至 Employees 資料表。然後,我們可以使用下列程式碼來指定欄位值:

objRecordSet("EmployeeID") = arrEmployee(0)
objRecordSet("EmployeeName") = arrEmployee(1)
objRecordSet("Department") = arrEmployee(2)

這裡沒有太複雜的內容。在第 1 行中,我們只是將 EmployeeID 欄位的值設定為陣列中項目 0 的值(請記住,在 VBScript 陣列中,第一個項目永遠具有索引編號 0)。在第 2 行中,我們將 EmployeeName 欄位的值設定為陣列中項目 1 的值 (第二個項目)。然後依此類推。

在指派所有欄位值之後,我們接著要呼叫 Update 方法,將新資料錄寫入資料庫。

objRecordSet.Update

接著我們再執行迴圈,對文字檔中的下一行重複此程序。然後依此類推。

等等,我們說到哪了?喔,對了,「超級杯足球聯賽」。事實上,對於撰寫本專欄的 Scripting Guy 而言,「超級杯足球聯賽」中最棒的一部分就是聆聽所有「專業」球評的評論。舉例來說,過去兩週以來,在「印第安納波利斯印地安人隊」的四分衛 Peyton Manning 贏得「超級杯足球聯賽」以前,沒有人認為他是優秀的四分衛(有趣的旁註:這些相同的評論員都認為「名人堂」的 Dan Marino 和 Warren Moon 才是優秀的四分衛。猜猜看這些優秀的四分衛贏過多少場「超級杯足球聯賽」)。當他最後贏得「超級杯足球聯賽」時,這些評論員對於 Peyton Manning 有何評語?「贏得一場『超級杯足球聯賽』雖然很棒,但是就一位真正優秀的四分衛而言,至少要贏得兩場『超級杯足球聯賽』」。

或許 Peyton Manning 應該從橋上跳下,然後讓一切結束。

有趣的旁註 2:這些相同的評論員都認為「綠灣包裝工」球隊的 Brett Favre 是優秀的四分衛 (可能也永遠是最好的四分衛)。當然,這表示 Brett Favre 至少贏過兩場「超級杯足球聯賽」,對吧?呃,大概有吧。這就讓讀者自己想想看...

編輯旁註:忘掉「超級杯足球聯賽」的廣告吧。過去幾年來,「Daytona 500 汽車大賽」廣告的鋒芒早就蓋過「超級杯足球聯賽」的廣告了。