Wednesday, November 9, 2011

How to Export Repeater data to CSV


I was working recently on a web project. One of the requirements was to save the data from a repeater control (I decide to use repeater and not DataGrid because of speed) into a CSV file. Don't know if this is the best method or not, but this is the way I did it. Relevant code in ASPX page:
<table>
<asp:Repeater ID="test" runat="server" >
  <HeaderTemplate>
    <tr>
      <td>Item</td>
      <td>Count</td>
      <td>Price</td>
      <td>VAT</td>
      <td>Total</td>
    </tr>
  </HeaderTemplate>
  <ItemTemplate>
    <tr>
      <td><asp:label ID="Item" Text=<%#DataBinder.Eval(Container, "DataItem.Item")%> runat="server" /></td>
      <td><asp:label ID="Cnt" Text=<%#DataBinder.Eval(Container, "DataItem.Cnt")%> runat="server" /></td>
      <td><asp:label ID="Price" Text=<%#DataBinder.Eval(Container, "DataItem.Price")%> runat="server" /></td>
      <td><asp:label ID="VAT" Text=<%#DataBinder.Eval(Container, "DataItem.VAT")%> runat="server" /></td>
      <td><asp:label ID="Total" Text=<%#DataBinder.Eval(Container, "DataItem.Total")%> runat="server" /></td>
    </tr>
  </ItemTemplate>
</asp:Repeater>
</table>
<asp:Button id="Export" Text="Export" runat="server" />

We need the following class:

Imports System.Web.UI 
Imports System.Web.UI.WebControls
Imports System.IO
Imports System.Text

Public Class CCSVExport 
  Private _pPage As Page = Nothing
  Private _Title As String
  Private _ColumnList As ArrayList
  Private _FName As String

  Public Sub New(ByVal pPage As Page, ByVal tit As StringByVal fName As StringByVal colList As ArrayList)
    _pPage = pPage
    _Title = tit
    _FName = fName
    _ColumnList = colList
  End Sub

  Public Sub ExportRepeater(ByVal rpt As Repeater)
    Dim context As System.Web.HttpContext
    Dim byteArray() As Byte

    context = System.Web.HttpContext.Current
    context.Response.Clear()
    context.Response.Buffer = True
    context.Response.ContentType = "application/vnd.ms-excel"
    context.Response.Charset = ""
    _pPage.EnableViewState = False
    context.Response.AddHeader("Content-Disposition", "attachment;filename=" & _FName & ";")
    byteArray = System.Text.Encoding.ASCII.GetBytes(BuildData(rpt).ToString)
    context.Response.BinaryWrite(byteArray)
    context.Response.End()
  End Sub

  Private Function BuildData(ByVal rpt As Repeater) As StringBuilder

    Dim ri As RepeaterItem
    Dim currentLine As String
    Dim arrayIndex As Int16
    Dim sb As New StringBuilder

    sb.AppendLine(_Title)
    For Each ri In rpt.Items

      currentLine = ""
      If ri.ItemType = ListItemType.AlternatingItem Or ri.ItemType = ListItemType.Item Then
        For arrayIndex = 0 To _ColumnList.Count - 1
          currentLine &= CType(ri.FindControl(_ColumnList.Item(arrayIndex)), Label).Text.Trim & ","
        Next arrayIndex
        sb.AppendLine(currentLine)
      End If
    Next ri
    Return sb
  End Function
End Class

Code in page load, just binding the repeater to a datatable:

Protected Sub Page_Load(ByVal sender As ObjectByVal e As System.EventArgs) Handles Me.Load

  test.DataSource = dt
  test.DataBind()

End Sub

Finally, export the data:
Protected Sub Export_Click(ByVal sender As ObjectByVal e As System.EventArgs) Handles Export.Click

  Dim fileTitle As String
  Dim export As CCSVExport
  Dim arrFields As ArrayList

  fileTitle = "Test"
  arrFields = New ArrayList

  arrFields.Add("Item")
  arrFields.Add("Cnt")
  arrFields.Add("Price")
  arrFields.Add("VAT")
  arrFields.Add("Total")
  export = New CCSVExport(Page, fileTitle, "test.csv", arrFields)
  export.ExportRepeater(test)
End Sub