問題描述
VBscript 有模塊嗎?我需要處理 CSV (Does VBscript have modules? I need to handle CSV)
I have a need to read a CSV file, and the only language I can use is VBscript.
I'm currently just opening the file and splitting on commas, and it's working OK because there aren't any quoted commas in fields. But I'm aware this is an incredibly fragile solution.
So, is there such a thing as a VBscript module I can use? Somewhere to get a tried-and-tested regular expression that would only split on commas not in quotes?
Any suggestions gratefully received.
參考解法
方法 1:
VBScript does not have a module system comparable to Perl. However you can open CSV files with ADO and access them like a database table. The code would go something like this:
(The funny comments are solely to fix SO's broken VB syntax highlighting)
Dim conn ''// As ADODB.Connection
Dim rs ''// As ADODB.RecordSet
Dim connStr ''// As String
Dim dataDir ''// As String
dataDir = "C:\" '"
connStr = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & dataDir & ";Extended Properties=""text"""
Set conn = CreateObject("ADODB.Connection")
conn.Open(connStr)
Set rs = conn.Execute("SELECT * FROM [data.txt]")
''// do something with the recordset
WScript.Echo rs.Fields.Count & " columns found."
WScript.Echo "---"
WScript.Echo rs.Fields("Col1Name").Value
If Not rs.EOF Then
rs.MoveNext
WScript.Echo rs.Fields("Col3Name").Value
End If
''// explicitly closing stuff is somewhat optional
''// in this script, but consider it a good habit
rs.Close
conn.Close
Set rs = Nothing
Set conn = Nothing
Creating a schema.ini
file that exactly describes your input is optimal. If you don't, you force the text driver to guess, and all bets are off if it guesses the wrong thing. The schema.ini
must reside in the same directory where your data is.
Mine looked like this:
[data.txt]
Format=Delimited(;)
DecimalSymbol=.
ColNameHeader=True
MaxScanRows=0
Col1=Col1Name Long
Col2=Col2Name Long
Col3=Col3Name Text
Col4=Col4Name Text
and with this data.txt
:
a;b;c;d
1;2;"foo bar";"yadayada"
1;2;"sample data";"blah"
I get this output:
C:\>cscript -nologo data.vbs
4 columns found.
---
1
sample data
C:\>
Worth a read in this regard: Much ADO About Text Files off the MSDN.
方法 2:
You can try creating an Excel ODBC Data Source to CSV (Called DSN I think. Its in Control Panel -> Administrative Tools -> ODBC Data Sources. Then on, you can query it using SQL.
I am still unsure if you can get what you want. I mean inserting a string with commas in it as a value for a particular cell.
方法 3:
A regexp:
'Credits go to http://www.codeguru.com/cpp/cpp/algorithms/strings/article.php/c8153/
r.Pattern = ",(?=(?:[^""]*""[^""]*"")*(?![^""]*""))"
It will find all commas that are not inside quotes.
Alternatively, you can use this function which I just adapted for vbs.
call test
Function ParseCSV(StringToParse, Quotes)
Dim i, r(), QuotedItemStart, prevpos
ReDim r(0)
prevpos = 1
For i = 1 To Len(StringToParse)
If Mid(StringToParse, i, 1) = "," Then
If QuotedItemStart = 0 Then
r(UBound(r)) = Trim(Mid(StringToParse, prevpos, i - prevpos))
ReDim Preserve r(UBound(r) + 1)
prevpos = i + 1
End If
Else
If InStr(1, Quotes, Mid(StringToParse, i, 1)) Then
If QuotedItemStart Then
r(UBound(r)) = Trim(Mid(StringToParse, QuotedItemStart, i - QuotedItemStart))
ReDim Preserve r(UBound(r) + 1)
QuotedItemStart = 0
prevpos = i + 2
i = i + 1
Else
QuotedItemStart = i + 1
End If
End If
End If
Next
If prevpos < Len(StringToParse) Then r(UBound(r)) = Trim(Mid(StringToParse, prevpos))
ParseCSV = r
End Function
Sub Test()
Dim i, s
s = ParseCSV("""This is, some text!"",25,""Holy holes!"", 286", """")
For i = LBound(s) To UBound(s)
msgbox s(i)
Next
msgbox "Items: " & CStr(UBound(s) - LBound(s) + 1)
End Sub
方法 4:
To answer the other half of your question, I have a vague recollection that you can use Windows Script Host spread across several WSF files. I have never done it myself, link to MSDN. Not pure VBS, but it should work in 'just' windows, if that was the real constraint.
More links:
- Scripting Guys
- Wikipedia
- 'Tutorial'
(by AmbroseChapel、Tomalak、daanish.rumani、GSerg、Benjol)