2011-03-09 78 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