views:

257

answers:

1

These routines (vb.net) allow you to dump a gridview to CSV, even if there are templated controls in the cells. It works, but I'm not thrilled with it.

What improvements should I make and why?

Private Shared Function CsvFormatted(ByVal t As String) As String
    If t.Contains(",") Then
        t = """" + t + """"
    End If
    Return t.Replace("\ ", "")

End Function

Private Shared Function GetCellText(ByVal cell As DataControlFieldCell) As String
    If cell.Controls.Count = 0 Then
        Return CsvFormatted(cell.Text)
    Else
        For Each current In cell.Controls
            If TypeOf current Is Label Then
                Return CsvFormatted(TryCast(current, Label).Text)
            ElseIf TypeOf current Is TextBox Then
                Return CsvFormatted(TryCast(current, TextBox).Text)
            ElseIf TypeOf current Is LinkButton Then
                Return CsvFormatted(TryCast(current, LinkButton).Text)
            ElseIf TypeOf current Is ImageButton Then
                Return CsvFormatted(TryCast(current, ImageButton).AlternateText)
            ElseIf TypeOf current Is HyperLink Then
                Return CsvFormatted(TryCast(current, HyperLink).Text)
            ElseIf TypeOf current Is DropDownList Then
                Return CsvFormatted(TryCast(current, DropDownList).SelectedItem.Text)
            ElseIf TypeOf current Is CheckBox Then
                Return CsvFormatted(If(TryCast(current, CheckBox).Checked, "True", "False"))
            End If
        Next
    End If
    Return ""
End Function

Public Shared Sub ExportGridViewToCSV(ByVal grid As GridView, ByVal fileName As String)
    HttpContext.Current.Response.Clear()
    HttpContext.Current.Response.Buffer = True
    HttpContext.Current.Response.AddHeader("content-disposition", "attachment;filename=" + fileName)
    HttpContext.Current.Response.Charset = ""
    HttpContext.Current.Response.ContentType = "application/text"
    Dim sb As New StringBuilder()
    For k As Integer = 0 To grid.Columns.Count - 1
        grid.Columns(k).Visible = True
        'add separator
        sb.Append(grid.Columns(k).HeaderText + ","c)
    Next
    'append new line
    sb.Append(vbCr & vbLf)
    For i As Integer = 0 To grid.Rows.Count - 1
        For k As Integer = 0 To grid.Columns.Count - 1
            grid.Columns(k).Visible = True
            'add separator
            sb.Append(GetCellText(grid.Rows(i).Cells(k)) + ","c)
        Next
        'append new line
        sb.Append(vbCr & vbLf)
    Next
    HttpContext.Current.Response.Output.Write(sb.ToString())
    HttpContext.Current.Response.Flush()
    HttpContext.Current.Response.End()
End Sub
+1  A: 
  • Should you be worrying about unescaping other HTML literals besides non-breaking space? You could use HttpUtility.HtmlDecode.
  • Your CsvFormatted routine could guard against null input strings - it costs almost nothing to be safe.
  • Do you need to pass the Turkey test? Some countries use a semicolon as the CSV delimiter. You might also need to account for dots or commas as decimal delimiter.
  • I might separate out building a CSV string into a separate function from issuing an HttpContext response.
  • I might use vbCrLf rather than vbCr & vbLf.

My main advice: create some good unit tests, make sure the code passes, then forget it, and move on to implement some more functionality. The code is fairly well encapsulated, so you can easily refactor in future if you ever decide it's necessary.

MarkJ
Great advice, thanks. The turkey test was very interesting...
BenB