2009-03-23 17 views
0
Dim re As New Regex("((?<field>[^"",\r\n]+)|""(?<field>([^""]|"""")+)"")((?<rowbreak>,\r\n|\r\n|\n|$)|,)") 


3700,Collin,Franc,,[email protected],Collins,Francine,,[email protected],"Enel North America, Inc.",One T Drive,Suite 220,MyCity,MA,77774,1,[email protected],,,,,3700, 
3701,Steur,Larry,,[email protected],Steur,Larry,,[email protected],"St. Petersburg Corp, Inc.",10490 Gady Blvd,,MyCity,FL,33772,1,[email protected],,,,,3701 
3705,Giger,Tina,CFO,[email protected],Giger,Tina,CFO,[email protected],Net Technologies,23 Calab Rd,Suite 202,Calabas,CA,77777,1,[email protected],,,,,3705, 

私が使用しているRegExは、空の列がある場合、次の列をその場所に「スライド」するという点では機能しません。次のように各行に5つの列を作成できるようにするにはどうすればよいですか?正規表現に空の値がありませんか?

<%@ Page Language="VB" MasterPageFile="~/_Common/MasterPage.master" %> 

<%@ Import Namespace="System.Data" %> 
<%@ Import Namespace="System.IO" %> 
<%@ Import Namespace="System.Text.RegularExpressions" %> 
<%@ Import Namespace="System.Xml" %> 

<script runat="server"> 

    Private Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) 
    
     ' call the parser 
     Dim dt As DataTable = ParseCSVFile(Server.MapPath("Documents/Test.csv")) 
    
     ' bind the resulting DataTable to a DataGrid Web Control 
     GridView1.DataSource = dt 
     GridView1.DataBind() 
    End Sub 

    Public Function ParseCSV(ByVal inputString As String) As DataTable 
    
     Dim dt As New DataTable() 
    
     ' declare the Regular Expression that will match versus the input string 
     Dim re As New Regex("((?<field>[^"",\r\n]+)|""(?<field>([^""]|"""")+)"")((?<rowbreak>,\r\n|\r\n|\n|$)|,)") 
    
     Dim colArray As New ArrayList() 
     Dim rowArray As New ArrayList() 
    
     Dim colCount As Integer = 0 
     Dim maxColCount As Integer = 0 
     Dim rowbreak As String = "" 
     Dim field As String = "" 
    
     Dim mc As MatchCollection = re.Matches(inputString) 
    
     For Each m As Match In mc 
        
      ' retrieve the field and replace two double-quotes with a single double-quote 
      field = m.Result("${field}").Replace("""""", """") 
        
      rowbreak = m.Result("${rowbreak}") 
        
      If field.Length > 0 Then 
       colArray.Add(field) 
       colCount += 1 
      End If 
        
      If rowbreak.Length > 0 Then 
            
       ' add the column array to the row Array List 
       rowArray.Add(colArray.ToArray()) 
            
       ' create a new Array List to hold the field values 
       colArray = New ArrayList() 
            
       If colCount > maxColCount Then 
        maxColCount = colCount 
       End If 
            
       colCount = 0 
      End If 
     Next 
    
     If rowbreak.Length = 0 Then 
      ' this is executed when the last line doesn't 
      ' end with a line break 
      rowArray.Add(colArray.ToArray()) 
      If colCount > maxColCount Then 
       maxColCount = colCount 
      End If 
     End If 
    
     ' create the columns for the table 
     For i As Integer = 0 To maxColCount - 1 
      dt.Columns.Add([String].Format("col{0:000}", i)) 
     Next 
    
     ' convert the row Array List into an Array object for easier access 
     Dim ra As Array = rowArray.ToArray() 
     For i As Integer = 0 To ra.Length - 1 
        
      ' create a new DataRow 
      Dim dr As DataRow = dt.NewRow() 
        
      ' convert the column Array List into an Array object for easier access 
      Dim ca As Array = DirectCast((ra.GetValue(i)), Array) 
        
      ' add each field into the new DataRow 
      For j As Integer = 0 To ca.Length - 1 
       dr(j) = ca.GetValue(j) 
      Next 
        
      ' add the new DataRow to the DataTable 
      dt.Rows.Add(dr) 
     Next 
    
     ' in case no data was parsed, create a single column 
     If dt.Columns.Count = 0 Then 
      dt.Columns.Add("NoData") 
     End If 
    
     Return dt 
    End Function 

    Public Function ParseCSVFile(ByVal path As String) As DataTable 
    
     Dim inputString As String = "" 
    
     ' check that the file exists before opening it 
     If File.Exists(path) Then 
        
      Dim sr As New StreamReader(path) 
      inputString = sr.ReadToEnd() 
      sr.Close() 
        
     End If 
    
     Return ParseCSV(inputString) 
    End Function 

</script> 


<asp:Content ID="Content1" ContentPlaceHolderID="head" Runat="Server"> 

</asp:Content> 

<asp:Content ID="Content2" ContentPlaceHolderID="ContentPlaceHolder1" Runat="Server"> 
    <asp:FileUpload ID="FileUpload1" runat="server" /> 
    <asp:Button ID="btnUpload" runat="server" Text="Upload" /> 
    <asp:GridView ID="GridView1" runat="server"> 
    </asp:GridView> 
</asp:Content> 

私は実際にLINQでこれをやって好むだろうが、私は中にカンマが含まれる値のために(値を引用したCSVファイルを使用していたすべての例を見つけることができませんでした:

1,2,3,4,5 
Test,,,Test, 
Test,,Test,, 

は、ここに私の完全なコードです値そのもの)。

** UPDATE **

私はこれに正規表現を変更し、それが近い私を取得しています:

Dim re As New Regex("(?<field>,)|((?<field>[^"",\r\n]+)|""(?<field>([^""]|"""")+)"")(,|(?<rowbreak>\r\n|\n|$))") 

今それが正しい列内のすべてのデータを置くが、中だけでコンマがあります空の列

+0

。車輪を改革しないでください...単に "LINQ to CSV"かそれに類似するものを検索してください – MarcinJuraszek

答えて

1

なぜ正規表現を使用するのですか?かなり簡単な構文解析ジョブがあります。引用符で囲まれていない限り、区切り記号としてカンマを使用します。したがって、各行の文字を文字ごとに繰り返したり、反対の引用符を押すとフラグを設定したり、終了引用符にヒットしたときにフラグを設定解除することができます。 「内側引用符」はカンマを無視します。 (私はこの使用して正規表現をしようとあきらめた)...これを試してみてください:

private DataTable GetDataTableFromCsv(string csvContent) 
    { 
     DataTable dt = new DataTable(); 
     string all = csvContent; 
     string[] lines = all.Split(new string[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries); 
     foreach (String s in lines) 
     { 
      bool isInsideQuote = false; 
      List<string> values = new List<string>(); 
      string accumulator = ""; 
      for (int j = 0; j < s.Length; j++)// (char c in s) 
      { 
       char c = s[j]; 
       if (c == '"') 
       { 
        if (!isInsideQuote) 
        { 
         isInsideQuote = true; 
        } 
        else 
        { 
         isInsideQuote = false; 
        } 
        accumulator += "\""; 
       } 
       else if (c == ',' && !isInsideQuote) 
       { 
        values.Add(accumulator); 
        accumulator = ""; //reset 
       } 
       else if (j == s.Length - 1) 
       { 
        accumulator += c; 
        values.Add(accumulator); 
        accumulator = ""; 
       } 
       else 
       { 
        accumulator += c; 
       } 
      } 
      //first time, create relevant columns 
      if (dt.Columns.Count == 0) 
      { 
       foreach (string colExample in values) 
       { 
        dt.Columns.Add(); 
       } 
       //list of strings now contains an example. 
      } 
      DataRow dr = dt.NewRow(); 
      for (int i = 0; i < values.Count; i++) 
      { 
       dr[i] = values[i]; 
      } 
      dt.Rows.Add(dr); 
     } 
     return dt; 
    } 
0

はこのような何かを試してみてください: CSVファイルを扱うの.NETライブラリの束だ"(?<field1>.*),(?<field2>.*),(?<field3>.*),(?<field4>.*),(?<field5>.*)"

関連する問題