2011-03-09 61 views
0

我有一个xls文件,或一个没有引号的csv,并且使用vb.net需要把它变成一个csv,并在每个单元格周围加引号。如果我在MS Access中打开不带引号的xls/csv,请将每列设置为文本,然后将其导出为我需要的格式。有更容易的方法吗?如果不是,我该如何在vb.net中复制它?谢谢。vb.net xls与csv与报价?

+0

你可以给数据的例子吗? – Iain 2011-03-09 18:53:25

+0

“1”,“2”,“3”,“4”是我需要的,而不是1,2,3,4。 – Shawn 2011-03-09 19:33:26

回答

2

如果使用.Net OLE DB provider,您可以指定该.csv在您的数据文件居住在文件夹中schema.ini文件格式详细介绍了。 “不带引号的” .csv格式的规格 应该像

[noquotes.csv]  <-- file name 
ColNameHeader=True <-- or False 
CharacterSet=1252  <-- your encoding 
Format=Delimited(,) <-- 
TextDelimiter=  <-- important: no " in source file 
Col1=VendorID Integer <-- your columns, of course 
Col2=AccountNumber Char Width 15 

的“引用”的.csv,只是更改名称,并删除TextDelimiter =行(把周围的文本字段引号是默认值)。

然后连接到文字库并执行该语句

SELECT * INTO [quotes.csv] FROM [noquotes.csv] 

(因为这会产生quotes.csv,你可能希望每个实验运行之前删除的文件)

加入到应对“空字段必须引用”

这是一个VBScript演示,但作为重要的事情是参数.GetString(),你可以将它移植到容易VB:

Dim sDir : sDir  = resolvePath("§LibDir§testdata\txt") 
    Dim sSrc : sSrc  = "noquotes.csv" 
    Dim sSQL : sSQL  = "SELECT * FROM [" & sSrc & "]" 
    Dim oTxtDb : Set oTxtDb = New cADBC.openDb(Array("jettxt", sDir)) 
    WScript.Echo goFS.OpenTextFile(goFS.BuildPath(sDir, sSrc)).ReadAll() 
    Dim sAll : sAll = oTxtDb.GetSelectFRO(sSQL).GetString(_ 
          adClipString, , """,""", """" & vbCrlf & """", "" _ 
        ) 
    WScript.Echo """" & Left(sAll, Len(sAll) - 1) 

和输出:

VendorID;AccountNumber;SomethingElse 
    1;ABC 123 QQQ;1,2 
    2;IJK 654 ZZZ;2,3 
    3;;3,4 

    "1","ABC 123 QQQ","1,2" 
    "2","IJK 654 ZZZ","2,3" 
    "3","","3,4" 

(德语区域,因此字段分隔符;和小数点符号)

从这个VB.Net代码的输出结果相同:

Imports ADODB 
    ... 

     Sub useGetString() 
      Console.WriteLine("useGetString") 

      Const adClipString As Integer = 2 
      Dim cn As New ADODB.Connection 
      Dim rs As ADODB.Recordset 
      Dim sAll As String 

      cn.ConnectionString = _ 
       "Provider=Microsoft.Jet.OLEDB.4.0;" _ 
       & "Data Source=M:\lib\kurs0705\testdata\txt\;" _ 
       & "Extended Properties=""text;""" 

      cn.Open() 
      rs = cn.Execute("SELECT * FROM [noquotes.csv]") 
      sAll = rs.GetString(adClipString, , """,""", """" & vbCrLf & """", "") 
      cn.Close() 
      sAll = """" & Left(sAll, Len(sAll) - 1) 
      Console.WriteLine(sAll) 
     End Sub 
+0

这听起来很棒,我会试试这个。 – Shawn 2011-03-09 20:28:58

+0

是否可以在不指定每列的情况下执行此操作?我想使它更通用,因此它可以转换任何csv文件。 – Shawn 2011-03-10 13:38:18

+1

如果您不指定列,驱动程序会猜测您想要(不)引用的类型和可能(不)引用字段。如果这是一个问题,那么在执行“SELECT INTO”语句之前,可以以编程方式编辑schema.ini文件。 – 2011-03-10 14:05:23

1

查看方法this link。 你可以做些什么来确保引号绕过的是将引号添加到将列数据放入文件的循环中的每列数据的开始和结尾。

例如作出这样的循环:

For InnerCount = 0 To ColumnCount - 1 
    Str &= """" & DS.Tables(0).Rows(OuterCount).Item(InnerCount) & """," 
Next 
+0

这将工作。我想看看是否有任何其他解决方案,因为每次我必须通过vb.net在excel文件中工作时,它的速度非常缓慢。 – Shawn 2011-03-09 19:40:10

+0

+1。这是VB.NET的方式来做到这一点。 – 2011-03-09 20:08:48

+0

正如我提出了一个不同的解决方案,我可能有偏见。但是考虑这种方法的人应该思考3个问题:你是否想要(1)引用所有字段值而不管类型? (2)尾随,在每一行? (3)在具有不可变字符串的语言的2.级循环中使用字符串连接? – 2011-03-09 21:31:27

-1
Public Class clsTest 

Public Sub Test 
Dim s as string = "C:\!Data\Test1.csv" 

     Dim Contents As String = System.IO.File.ReadAllText(s) 


     Dim aryLines As String() = Contents.Split(New String() { Environment.Newline }, StringSplitOptions.None) 
     Dim aryParts() As String 
     Dim aryHeader() As String 
     Dim dt As System.Data.DataTable 
     For i As Integer = 0 To aryLines.Length - 1 
      aryParts = SplitCSVLine(aryLines(i)) 
      If dt Is Nothing And aryHeader Is Nothing Then 
       aryHeader = CType(aryParts.Clone, String()) 
      ElseIf dt Is Nothing And aryHeader IsNot Nothing Then 
       dt = DTFromStringArray(aryParts, 1000, "", aryHeader) 
      Else 
       DTAddStringArray(dt, aryParts) 
      End If 
     Next 
     dt.dump 
End Sub 

Public Shared Function SplitCSVLine(strCSVQuotedLine As String) As String() 
     Dim aryLines As String() = strCSVQuotedLine.Split(New String() {Environment.NewLine}, StringSplitOptions.None) 
     Dim aryParts As String() = Nothing 
     For i As Integer = 0 To aryLines.Length - 1 
      Dim regx As New Text.RegularExpressions.Regex(",(?=(?:[^\""]*\""[^\""]*\"")*(?![^\""]*\""))") 
      aryParts = regx.Split(aryLines(i)) 
      For p As Integer = 0 To aryParts.Length - 1 
       aryParts(p) = aryParts(p).Trim(" "c, """"c) 
      Next 
     Next 
     Return aryParts 
End Function 

Public Shared Function DTFromStringArray(ByVal aryValues() As String, Optional ByVal intDefaultColumnWidth As Integer = 255, Optional ByVal strTableName As String = "tblArray", Optional ByVal aryColumnNames() As String = Nothing) As DataTable 
     If String.IsNullOrWhiteSpace(strTableName) Then strTableName = "tblArray" 
     Dim dt As DataTable = New DataTable(strTableName) 
     Dim colNew(aryValues.GetUpperBound(0)) As DataColumn 
     If aryColumnNames Is Nothing Then 
      ReDim aryColumnNames(aryValues.Length) 
     Else 
      If aryColumnNames.GetUpperBound(0) < aryValues.GetUpperBound(0) Then 
       ReDim Preserve aryColumnNames(aryValues.Length) 
      End If 
     End If 
     For x As Integer = aryColumnNames.GetLowerBound(0) To aryColumnNames.GetUpperBound(0) 
      If String.IsNullOrWhiteSpace(aryColumnNames(x)) Then 
       aryColumnNames(x) = "Field" & x.ToString 
      Else 
       aryColumnNames(x) = aryColumnNames(x) 
      End If 
     Next 
     For i As Integer = 0 To aryValues.GetUpperBound(0) 
      colNew(i) = New DataColumn 
      With colNew(i) 
       .ColumnName = aryColumnNames(i) '"Value " & i 
       .DataType = GetType(String) 
       .AllowDBNull = False 
       .DefaultValue = "" 
       .MaxLength = intDefaultColumnWidth 
       .Unique = False 
      End With 
     Next 
     dt.Columns.AddRange(colNew) 
     Dim pRow As DataRow = dt.NewRow 
     For i As Integer = aryValues.GetLowerBound(0) To aryValues.GetUpperBound(0) 
      pRow.Item(i) = aryValues(i) 
     Next 
     dt.Rows.Add(pRow) 
     Return dt 
End Function 

Public Shared Sub DTAddStringArray(ByRef dt As DataTable, ByVal aryRowValues() As String) 
     Dim pRow As DataRow 
     pRow = dt.NewRow 
     For i As Integer = aryRowValues.GetLowerBound(0) To aryRowValues.GetUpperBound(0) 
      pRow.Item(i) = aryRowValues(i) 
     Next 
     dt.Rows.Add(pRow) 
End Sub 

End Class 
+0

考虑添加一个解释你在做什么以及它如何回答OP的问题。 – ApplePie 2013-09-10 23:51:18