VBA 读取字符串中带分隔符的 CSV
VBA read CSV with delimiter in string
我正在尝试读取 .csv 以在 .accdb 中使用它
文件有;作为分隔符,“”作为字符串限定符。
年轻天真,我只是在分隔符处分割文件:
Set oFSO = New FileSystemObject
Set oStream = oFSO.OpenTextFile(sFilePath, ForReading)
Do Until oStream.AtEndOfStream
sLine = oStream.ReadLine
sArray = Split(sLine, ";")
....
现在我得到一行内容:
"String";"Str;ing";0;0;0;"String"
所以我在其中一个字符串中有分隔符,这使得上面的代码不起作用。有什么解决办法吗?
编辑:
我发现有人有类似的问题,只是用逗号作为分隔符。他们使用正则表达式解决了这个问题。
问题:我绝对不擅长正则表达式。在示例中使用了这个表达式和代码:
Function regLine(sLine As String) As String
Dim oRegEx As RegExp
Set oRegEx = New RegExp
oRegEx.IgnoreCase = True
oRegEx.Global = True
' Pattern: ",(?=([^"]*"[^"]*")*(?![^"]*"))"
oRegEx.Pattern = ",(?=([^" & Chr(34) & "]*" & Chr(34) & "[^" & Chr(34) & "]*" & Chr(34) & ")*(?![^" & Chr(34) & "]*" & Chr(34) & "))"
regLine = oRegEx.Replace(sLine, ";")
End Function
所以我不是很理解这个表达。我的第一个想法是用分号代替逗号,但没有用。
我的第一个问题是:有没有“;”在字符串值中是一个有效的字符串?如果是这样,除了手动验证数据外,我看不到任何其他方法。
如果不是,输入文件有多大?如果它不是太大(对于 "too" 的各种定义 :-) )那么只需手动扫描它以查找错误。
如果它非常大,我会简单地编写一个预处理程序来读取字符串值,然后删除任何“;”在它发生的地方。这样的程序只有十几行。然后运行将干净的文件导入Access。
Option Explicit
Dim line
line ="""String"";""Str;ing"";0;0;0;""String"""
WScript.Echo line
Dim aFields
With New RegExp
.Pattern = "(""[^""]*"")?;"
.Global = True
aFields = Split(.Replace(line, ""&Chr(0)),Chr(0))
End With
Dim field
For Each field In aFields
WScript.Echo field
Next
代码是 .vbs
,但展示了如何使用正则表达式将未包含在引号中的分号替换为空字符,并使用空字符将行拆分为其字段。
我现在通过编写一个循环解决了这个问题,如果它在字符串中则删除分隔符。
Function fixLine(sLine As String)
Dim i As Long
Dim bInString As Boolean
bInString = False
fixLine = ""
For i = 1 To Len(sLine)
If Mid(sLine, i, 1) = Chr(34) Then
If bInString Then
bInString = False
Else
bInString = True
End If
End If
If bInString And Mid(sLine, i, 1) = ";" Then
Else
fixLine = fixLine & Mid(sLine, i, 1)
End If
Next
End Function
感觉有点快和肮脏,我不确定性能但它有效。
编辑:
我还使用了我发现的上述示例。它取代了字符串外一行中的定界符。所以我用 Chr(0) 替换了分隔符,我知道它不会出现在一行中,然后在新的分隔符处拆分。
Function regLine(sLine As String) As String()
Dim oRegEx As RegExp
Dim sLine2() As String
Set oRegEx = New RegExp
oRegEx.Global = True
'Pattern: ";(?=([^"]*"[^"]*")*(?![^"]*"))"
oRegEx.Pattern = ";(?=([^" & Chr(34) & "]*" & Chr(34) & "[^" & Chr(34) & "]*" & Chr(34) & ")*(?![^" & Chr(34) & "]*" & Chr(34) & "))"
sLine2 = oRegEx.Replace(sLine, Chr(0))
regLine = Split(sLine2, Chr(0))
End Function
我正在尝试读取 .csv 以在 .accdb 中使用它
文件有;作为分隔符,“”作为字符串限定符。 年轻天真,我只是在分隔符处分割文件:
Set oFSO = New FileSystemObject
Set oStream = oFSO.OpenTextFile(sFilePath, ForReading)
Do Until oStream.AtEndOfStream
sLine = oStream.ReadLine
sArray = Split(sLine, ";")
....
现在我得到一行内容:
"String";"Str;ing";0;0;0;"String"
所以我在其中一个字符串中有分隔符,这使得上面的代码不起作用。有什么解决办法吗?
编辑:
我发现有人有类似的问题,只是用逗号作为分隔符。他们使用正则表达式解决了这个问题。 问题:我绝对不擅长正则表达式。在示例中使用了这个表达式和代码:
Function regLine(sLine As String) As String
Dim oRegEx As RegExp
Set oRegEx = New RegExp
oRegEx.IgnoreCase = True
oRegEx.Global = True
' Pattern: ",(?=([^"]*"[^"]*")*(?![^"]*"))"
oRegEx.Pattern = ",(?=([^" & Chr(34) & "]*" & Chr(34) & "[^" & Chr(34) & "]*" & Chr(34) & ")*(?![^" & Chr(34) & "]*" & Chr(34) & "))"
regLine = oRegEx.Replace(sLine, ";")
End Function
所以我不是很理解这个表达。我的第一个想法是用分号代替逗号,但没有用。
我的第一个问题是:有没有“;”在字符串值中是一个有效的字符串?如果是这样,除了手动验证数据外,我看不到任何其他方法。
如果不是,输入文件有多大?如果它不是太大(对于 "too" 的各种定义 :-) )那么只需手动扫描它以查找错误。
如果它非常大,我会简单地编写一个预处理程序来读取字符串值,然后删除任何“;”在它发生的地方。这样的程序只有十几行。然后运行将干净的文件导入Access。
Option Explicit
Dim line
line ="""String"";""Str;ing"";0;0;0;""String"""
WScript.Echo line
Dim aFields
With New RegExp
.Pattern = "(""[^""]*"")?;"
.Global = True
aFields = Split(.Replace(line, ""&Chr(0)),Chr(0))
End With
Dim field
For Each field In aFields
WScript.Echo field
Next
代码是 .vbs
,但展示了如何使用正则表达式将未包含在引号中的分号替换为空字符,并使用空字符将行拆分为其字段。
我现在通过编写一个循环解决了这个问题,如果它在字符串中则删除分隔符。
Function fixLine(sLine As String)
Dim i As Long
Dim bInString As Boolean
bInString = False
fixLine = ""
For i = 1 To Len(sLine)
If Mid(sLine, i, 1) = Chr(34) Then
If bInString Then
bInString = False
Else
bInString = True
End If
End If
If bInString And Mid(sLine, i, 1) = ";" Then
Else
fixLine = fixLine & Mid(sLine, i, 1)
End If
Next
End Function
感觉有点快和肮脏,我不确定性能但它有效。
编辑: 我还使用了我发现的上述示例。它取代了字符串外一行中的定界符。所以我用 Chr(0) 替换了分隔符,我知道它不会出现在一行中,然后在新的分隔符处拆分。
Function regLine(sLine As String) As String()
Dim oRegEx As RegExp
Dim sLine2() As String
Set oRegEx = New RegExp
oRegEx.Global = True
'Pattern: ";(?=([^"]*"[^"]*")*(?![^"]*"))"
oRegEx.Pattern = ";(?=([^" & Chr(34) & "]*" & Chr(34) & "[^" & Chr(34) & "]*" & Chr(34) & ")*(?![^" & Chr(34) & "]*" & Chr(34) & "))"
sLine2 = oRegEx.Replace(sLine, Chr(0))
regLine = Split(sLine2, Chr(0))
End Function