2010-06-19 71 views
-1

我正在尋找將以下代碼轉換爲有效的VB.NET代碼。我需要將datagrid中的數據導出爲用戶可以保存的CSV格式,以下David提供的代碼可以很好地工作,但它是用C#編寫的。任何幫助,將不勝感激!這是針對我們正在開發的Silverlight 4網站。需要將C#代碼轉換爲VB.NET for Silverlight「導出爲CSV」

private void exportHistoryButton_Click(object sender, RoutedEventArgs e) 
{ 
    string data = ExportDataGrid(true, historyDataGrid); 
    SaveFileDialog sfd = new SaveFileDialog() 
    { 
     DefaultExt = "csv", 
     Filter = "CSV Files (*.csv)|*.csv|All files (*.*)|*.*", 
     FilterIndex = 1 
    }; 
    if (sfd.ShowDialog() == true) 
    { 
     using (Stream stream = sfd.OpenFile()) 
     { 
      using (StreamWriter writer = new StreamWriter(stream)) 
      { 
       writer.Write(data); 
       writer.Close(); 
      } 
      stream.Close(); 
     } 
    } 
} 

private string FormatCSVField(string data) 
{ 
    return String.Format(
      "\"{0}\"", 
      data.Replace("\"", "\"\"\"") 
      .Replace("\n", "") 
      .Replace("\r", "") 
     ); 
} 

public string ExportDataGrid(bool withHeaders, DataGrid grid) 
{ 
    string colPath; 
    System.Reflection.PropertyInfo propInfo; 
    System.Windows.Data.Binding binding; 
    System.Text.StringBuilder strBuilder = new System.Text.StringBuilder(); 
    System.Collections.IList source = (grid.ItemsSource as System.Collections.IList); 
    if (source == null) 
     return ""; 

    List<string> headers = new List<string>(); 
    grid.Columns.ToList().ForEach(col => 
    { 
     if (col is DataGridBoundColumn) 
     { 
      headers.Add(FormatCSVField(col.Header.ToString())); 
     } 
    }); 
    strBuilder 
    .Append(String.Join(",", headers.ToArray())) 
    .Append("\r\n"); 

    foreach (Object data in source) 
    { 
     List<string> csvRow = new List<string>(); 
     foreach (DataGridColumn col in grid.Columns) 
     { 
      if (col is DataGridBoundColumn) 
      { 
       binding = (col as DataGridBoundColumn).Binding; 
       colPath = binding.Path.Path; 
       propInfo = data.GetType().GetProperty(colPath); 
       if (propInfo != null) 
       { 
        csvRow.Add(FormatCSVField(propInfo.GetValue(data, null).ToString())); 
       } 
      } 
     } 
     strBuilder.Append(String.Join(",", csvRow.ToArray())).Append("\r\n"); 
    } 
    return strBuilder.ToString(); 
} 
+1

不是一個問題 – msarchet 2010-06-19 15:52:48

+1

「請將我的代碼轉換爲我」不是一個合適的問題 – 2010-06-19 20:49:38

回答

0

這不是一個問題,而是一個請求。不過,試試這個:

http://www.developerfusion.com/tools/convert/csharp-to-vb/

Private Sub exportHistoryButton_Click(sender As Object, e As RoutedEventArgs) 
    Dim data As String = ExportDataGrid(True, historyDataGrid) 
    Dim sfd As New SaveFileDialog() With { _ 
     .DefaultExt = "csv", _ 
     .Filter = "CSV Files (.csv)|.csv|All files (.)|.", _ 
     .FilterIndex = 1 _ 
    } 
    If sfd.ShowDialog() = True Then 
     Using stream As Stream = sfd.OpenFile() 
      Using writer As New StreamWriter(stream) 
       writer.Write(data) 
       writer.Close() 
      End Using 
      stream.Close() 
     End Using 
    End If 
End Sub 

Private Function FormatCSVField(data As String) As String 
    Return [String].Format("""{0}""", data.Replace("""", """""""").Replace(vbLf, "").Replace(vbCr, "")) 
End Function 

Public Function ExportDataGrid(withHeaders As Boolean, grid As DataGrid) As String 
    Dim colPath As String 
    Dim propInfo As System.Reflection.PropertyInfo 
    Dim binding As System.Windows.Data.Binding 
    Dim strBuilder As New System.Text.StringBuilder() 
    Dim source As System.Collections.IList = TryCast(grid.ItemsSource, System.Collections.IList) 
    If source Is Nothing Then 
     Return "" 
    End If 

    Dim headers As New List(Of String)() 
    grid.Columns.ToList().ForEach(Function(col) Do 
     If TypeOf col Is DataGridBoundColumn Then 
      headers.Add(FormatCSVField(col.Header.ToString())) 
     End If 
    End Function) 
    strBuilder.Append([String].Join(",", headers.ToArray())).Append(vbCr & vbLf) 

    For Each data As [Object] In source 
     Dim csvRow As New List(Of String)() 
     For Each col As DataGridColumn In grid.Columns 
      If TypeOf col Is DataGridBoundColumn Then 
       binding = TryCast(col, DataGridBoundColumn).Binding 
       colPath = binding.Path.Path 
       propInfo = data.[GetType]().GetProperty(colPath) 
       If propInfo IsNot Nothing Then 
        csvRow.Add(FormatCSVField(propInfo.GetValue(data, Nothing).ToString())) 
       End If 
      End If 
     Next 
     strBuilder.Append([String].Join(",", csvRow.ToArray())).Append(vbCr & vbLf) 
    Next 


    Return strBuilder.ToString() 
End Function 
+0

我確實嘗試過該網站,並且它創建的vb代碼無效。現在再看看它是否可以清理乾淨。 謝謝。 – 2010-06-19 14:32:58

1

這裏的大多是直接翻譯。我做了一些改進,但如果離原版很近,就應該認識到它。但是,我們可以做一個很多好,所以請繼續閱讀這個最初的嘗試後,更好的東西:

Private Sub exportHistoryButton_Click(ByVal sender As Object, ByVal e As RoutedEventArgs) 
    Dim sfd As New SaveFileDialog() 
    sfd.DefaultExt = "csv" 
    sfd.Filter = "CSV Files (*.csv)|*.csv|All files (*.*)|*.*" 
    sfd.FilterIndex = 1 

    If sfd.ShowDialog() Then 
     Using writer As New StreamWriter(sfd.OpenFile()) 
      writer.Write(ExportDataGrid(True, historyDataGrid)) 
     End Using 
    End If 

End Sub 

Private Function FormatCSVField(ByVal data As String) As String 
    Return String.Format("""{0}""", _ 
     data.Replace("""", """""").Replace(vbLf, "").Replace(vbCr, "")) 
End Function 

Public Function ExportDataGrid(ByVal withHeaders As Bool, ByVal grid As DataGrid) As String 
    Dim source As System.Collections.IList = TryCast(grid.ItemsSource, System.Collections.IList) 
    If source Is Nothing Then Return "" 

    Dim builder As New System.Text.StringBuilder() 

    If withHeaders Then 
     Dim headers As new List(Of String)() 
     For Each col As DataColumn In grid.Columns.Where(Function(c) TypeOf c is DataGridBoundColumn) 
      headers.Add(FormatCSVField(col.Header.ToString())) 
     Next col 
     builder.Append(String.Join(",", headers.ToArray())).Append(vbCrLf) 
    End If 

    For Each row in source 
     Dim csvRow As New List(Of String)() 
     For Each col As DataGridBoundColumn in grid.Columns.Where(Function(c) TypeOf col Is DataGridBoundColumn) 
      Dim propInfo As System.Reflection.PropertyInfo = _ 
        row.GetType().GetProperty(col.Binding.Path.Path) 
      If propInfo IsNot Nothing Then 
       csvRow.Add(FormatCSVField(propInfo.GetValue(row, Nothing).ToString())) 
      End If 
     Next col 

     builder.Append(String.Join(",", csvRow.ToArray())).Append(vbCrLf) 
    Next row 

    Return builder.ToString() 
End Function 

這段代碼的大問題是,當你把你的整個網格成一個字符串變量,您創建的對象很可能以大對象堆結束。這是一件「壞事」™。其中一件讓它變得糟糕的事情是,它在性能測試中往往看起來不好。直到生產纔會出現這種問題。但是當我說我們可以做得更好時相信我。

如果這仍然是C#我會重構它使用一個迭代器塊來返回一次一行的字符串,然後寫出來。由於它是VB,我們將重構它接受一個TextWriter並直接寫入到:

Private Sub exportHistoryButton_Click(ByVal sender As Object, ByVal e As RoutedEventArgs) 
    Dim sfd As New SaveFileDialog() 
    sfd.DefaultExt = "csv" 
    sfd.Filter = "CSV Files (*.csv)|*.csv|All files (*.*)|*.*" 
    sfd.FilterIndex = 1 

    If sfd.ShowDialog() Then 
     Using writer As New StreamWriter(sfd.OpenFile()) 
      ExportDataGrid(historyDataGrid, writer) ' Notice the change here 
     End Using 
    End If 

End Sub 

Private Function WriteCSVField(ByVal data As String, ByVal writer As TextWriter) As String 
    ' This would likely do a _lot_ better with a state machine to iterate over 
    ' each character rather than create 3 new strings for every field, 
    ' but we'll let it slide for now 
    writer.Write(""""c) 
    writer.Write(data.Replace("""", """""").Replace(vbLf, "").Replace(vbCr, "")) 
    writer.Write(""""c) 
End Function 

' Notice the new function signature 
Public Sub ExportDataGrid(ByVal grid As DataGrid, ByVal writer As TextWriter, Optional ByVal WithHeaders As Boolean = True) 
    Dim source As System.Collections.IList = TryCast(grid.ItemsSource, System.Collections.IList) 
    If source Is Nothing Then Return "" 

    Dim delimiter As String 
    If WithHeaders Then 
     delimiter = "" 
     For Each col As DataColumn In grid.Columns.Where(Function(c) TypeOf c is DataGridBoundColumn) 
      writer.Write(delimiter) 
      WriteCSVField(col.Header.ToString(), writer) 
      delimiter = "," 
     Next col 
     writer.Write(vbCrLf) 
    End If 

    For Each row In source 
     delimiter = "" 
     For Each col As DataGridBoundColumn in grid.Columns.Where(Function(c) TypeOf col Is DataGridBoundColumn) 
      writer.Write(delimiter) 
      delimiter = "," 

      ' I'm pretty sure this could be refactored to avoid the reflection, 
      ' But I also think there's a bug in your code here, so I'll 
      ' leave the direct translation for now 
      Dim propInfo As System.Reflection.PropertyInfo = _ 
        row.GetType().GetProperty(col.Binding.Path.Path) 
      If propInfo IsNot Nothing Then 
       WriteCSVField(propInfo.GetValue(row, Nothing).ToString(), writer) 
      End If 
     Next col 
     writer.Write(vbCrLf) 
    Next row 
End Sub 

當然,所有在這裏的最好的選擇是寫在所有沒有新的代碼,這已經是一個問題成千上萬的其他程序員解決了這個問題。你可以去找一個現成的庫,把這些亂七八糟的東西變成兩行或者調用這個API。