1

我需要读取一个 CSV 文件,而我唯一可以使用的语言是 VBscript。

我目前只是打开文件并用逗号分割,它工作正常,因为字段中没有任何带引号的逗号。但我知道这是一个非常脆弱的解决方案。

那么,有没有我可以使用的 VBscript 模块之类的东西?在某个地方可以获得一个经过验证的正则表达式,它只会在逗号而不是引号中分割?

任何建议都非常感激。

4

4 回答 4

7

VBScript 没有可与 Perl 相媲美的模块系统。但是,您可以使用ADO打开 CSV 文件并像访问数据库表一样访问它们。代码会是这样的:

(有趣的评论只是为了修复 SO 损坏的 VB 语法突出显示)

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

创建一个schema.ini准确描述您的输入的文件是最佳选择。如果你不这样做,你会强迫文本驱动程序猜测,如果它猜错了,所有的赌注都将被取消。schema.ini必须位于数据所在的同一目录中。

我的看起来像这样:

[data.txt]
Format=Delimited(;)
DecimalSymbol=.
ColNameHeader=True
MaxScanRows=0
Col1=Col1Name Long
Col2=Col2Name Long
Col3=Col3Name Text
Col4=Col4Name Text

有了这个data.txt

a;b;c;d
1;2;"foo bar";"yadayada"
1;2;"sample data";"blah"

我得到这个输出:

C:\>cscript -nologo data.vbs
4 columns found.
---
1
sample data

C:\>

在这方面值得一读:MSDN 上关于文本文件的很多 ADO 。

于 2009-03-27T10:27:13.783 回答
0

您可以尝试将 Excel ODBC 数据源创建为 CSV(我认为称为 DSN。它在Control Panel -> Administrative Tools -> ODBC Data Sources中。然后,您可以使用 SQL 查询它。

我仍然不确定你是否能得到你想要的。我的意思是插入一个带有逗号的字符串作为特定单元格的值。

于 2009-03-27T09:56:14.403 回答
0

一个正则表达式:

'Credits go to http://www.codeguru.com/cpp/cpp/algorithms/strings/article.php/c8153/
r.Pattern = ",(?=(?:[^""]*""[^""]*"")*(?![^""]*""))"

它将找到所有不在引号内的逗号。

或者,您可以使用我刚刚为 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
于 2009-03-27T10:23:33.900 回答
0

为了回答您问题的另一半,我模糊地记得您可以使用分布在多个 WSF 文件中的 Windows Script Host。我自己从来没有做过,链接到 MSDN。不是纯粹的 VBS,但它应该在“只是”窗口中工作,如果那是真正的限制的话。

更多链接:

于 2009-03-30T10:35:04.317 回答