简体   繁体   中英

Open DataTable in Excel VB

Ok, this is an interesting issue. I have been tasked with modifying an existing VB project. Currently the user selected from a series of dropdowns to select a sql query and then run that query. So the user selects and environment dropdown, the results of that dropdown populates the category dropdown. Once the category is selected, they get a dropdown of available queries. Once they select a query and hit the "Run" button, they get a gridview with the results of the query. Some of the query results are huge. The query I'm running as a test has 40 columns and 20,000 records. The query runs in less than 5 seconds but it takes over a minute to render the gridview. Once the gridview is done rendering, the user has the option to export the results to Excel. And by this, I mean the code opens an instance of Excel through gridview.RenderControl and displays the results in Excel. The user doesn't want to save the excel file and then navigate to the file, they want it to open right from the webform they are using which is what the code does currently.

However, the user doesn't care about the gridview. They don't care if they see it at all. They want to just open Excel. So instead of using gridview.RenderControl, I want to open Excel and populate it with the DataTable (or DataSet) in memory. Any thoughts on the best way to do that?

Here's how they are currently populating the gridview: Dim MyConnection As SqlConnection Dim MyCommand As SqlCommand Dim MyDataTable As DataTable Dim MyReader As SqlDataReader

        MyConnection = New SqlConnection()
        MyConnection.ConnectionString = ConfigurationManager.ConnectionStrings(Connection).ConnectionString

        MyCommand = New SqlCommand()
        MyCommand.CommandText = Sqlquery
        MyCommand.CommandType = CommandType.Text
        MyCommand.Connection = MyConnection

        MyCommand.Connection.Open()
        MyReader = MyCommand.ExecuteReader(CommandBehavior.CloseConnection)

        MyDataTable = New DataTable()
        MyDataTable.Load(MyReader)

        If (MyDataTable.Rows.Count > 0) Then
            QueryresultPanel.Visible = True
            gvLineItems.DataSource = MyDataTable
            gvLineItems.DataBind()
        End If

        MyDataTable.Dispose()
        MyCommand.Dispose()
        MyConnection.Dispose()

Here's how they're opening and populating the instance of Excel:

     Protected Sub btnExportToExcel_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnExportToExcel.Click
        Response.Clear()
        Response.Buffer = True
        '
        ' Set the content type to Excel.
        ' 
        Response.AddHeader("content-disposition", "attachment;filename=GridViewExport.xls")
        Response.Charset = ""
        Response.ContentType = "application/vnd.ms-excel"
        ' 
        ' Turn off the view state.
        ' 
        Me.EnableViewState = False
        Dim oStringWriter As New System.IO.StringWriter()
        Dim oHtmlTextWriter As New System.Web.UI.HtmlTextWriter(oStringWriter)
        ' 
        ' Get the HTML for the control.
        '
        gvLineItems.RenderControl(oHtmlTextWriter)
        ' 
        ' Write the HTML back to the browser.
        '
        Response.Write(oStringWriter.ToString())
        Response.[End]()
    End Sub

Obviously, there's no RenderControl for a DataTable or DataSet and can't figure out how to get this record set to render in an instance of Excel without saving it to a file first.

Alright, here's the solution I found (in case anyone is interested). It's pretty simple actually. I just looped through the datatable and used StringWriter.

    Protected Sub WriteToExcelFile(dt As DataTable)
    Dim sw As StringWriter

    For Each datacol As DataColumn In dt.Columns
        sw.Write(datacol.ColumnName + vbTab)
    Next

    Dim row As DataRow
    For Each row In dt.Rows
        sw.Write(vbNewLine)
        Dim column As DataColumn
        For Each column In dt.Columns
            If Not row(column.ColumnName) Is Nothing Then
                sw.Write(row(column).ToString() + vbTab)
            Else
                sw.Write(String.Empty + vbTab)
            End If
        Next column
    Next row

    Response.Clear()
    Response.ContentType = "application/vnd.ms-excel"
    Response.AddHeader("Content-Disposition", "attachment;filename=DataTable.xls")
    Response.Output.Write(sw.ToString())
    Response.Flush()
    System.Web.HttpContext.Current.Response.Flush()
    System.Web.HttpContext.Current.Response.SuppressContent = True
    System.Web.HttpContext.Current.ApplicationInstance.CompleteRequest()
End Sub

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM