Export GridView image to Excel

David Chase 681 Reputation points
2021-07-12T18:05:23.02+00:00

We have an asp.net web application that we want to export a GridView that includes an image column to Excel. Our code works fine but now we added an image control and we want the actual picture to export. Below is our GridView and code that is working but I am not sure how to code for the ImageButton control (we are open to using just an Image control if that would work better but I think the concept is the same. If I export the URL for the image it works fine but does not export the actual image.

    <asp:GridView ID="GridView1" runat="server" DataSourceID="SqlPartInventory" AutoGenerateColumns="False" DataKeyNames="InventoryID" Visible="True">
        <Columns>
            <asp:BoundField DataField="InventoryID" HeaderText="InventoryID" InsertVisible="False" ReadOnly="True" SortExpression="InventoryID" />
            <asp:BoundField DataField="PartNumber" HeaderText="PartNumber" SortExpression="PartNumber" />
            <asp:BoundField DataField="PartDescription" HeaderText="PartDescription" SortExpression="PartDescription" />
            <asp:BoundField DataField="VehicleYear" HeaderText="VehicleYear" SortExpression="VehicleYear" />
            <asp:BoundField DataField="VehicleMake" HeaderText="VehicleMake" SortExpression="VehicleMake" />
            <asp:BoundField DataField="VehicleModel" HeaderText="VehicleModel" SortExpression="VehicleModel" />
            <asp:BoundField DataField="Qty" HeaderText="Qty" SortExpression="Qty" />
            <asp:BoundField DataField="SellingPrice" HeaderText="SellingPrice" SortExpression="SellingPrice" />
            <asp:BoundField DataField="PartCost" HeaderText="PartCost" SortExpression="PartCost" />
            <asp:BoundField DataField="PartQuality" HeaderText="PartQuality" SortExpression="PartQuality" />
            <asp:BoundField DataField="QualityText" HeaderText="QualityText" ReadOnly="True" SortExpression="QualityText" />
            <asp:BoundField DataField="Location" HeaderText="Location" SortExpression="Location" />
            <asp:BoundField DataField="RepairOrderID" HeaderText="RepairOrderID" SortExpression="RepairOrderID" />
            <asp:CheckBoxField DataField="Available" HeaderText="Available" SortExpression="Available" />
            <asp:BoundField DataField="PartNotes" HeaderText="PartNotes" SortExpression="PartNotes" />
            <asp:TemplateField>
                <ItemTemplate>
                    <asp:ImageButton ID="IBtnPhoto" runat="server" />
                </ItemTemplate>
            </asp:TemplateField>
        </Columns>
    </asp:GridView>

    Private Sub GridView1_RowDataBound(sender As Object, e As GridViewRowEventArgs) Handles GridView1.RowDataBound
        If e.Row.RowType = DataControlRowType.DataRow Then
            Dim img As ImageButton = e.Row.FindControl("IBtnPhoto")
            Dim strurl As String = ConfigurationManager.AppSettings("appurl")
            Dim strurlPhy As String = Server.MapPath("~/Photos/_Parts/") & DataBinder.Eval(e.Row.DataItem, "InventoryID") & ".jpg"

            If File.Exists(strurlPhy) = False Then
                img.CssClass = "hide"
            Else
                img.ImageUrl = "../Photos/_Parts/" & DataBinder.Eval(e.Row.DataItem, "InventoryID") & ".jpg"
            End If
            img.AlternateText = DataBinder.Eval(e.Row.DataItem, "InventoryID")

        End If
    End Sub

    Private Sub LBtnExport_Click(sender As Object, e As EventArgs) Handles LBtnExport.Click
        GridView1.Visible = True
        GridView1.DataBind()
        UtilClass.Export("MABParts.xls", GridView1, "Internal Parts Inventory")
    End Sub


    Public Shared Sub Export(ByVal fileName As String, ByVal gv As GridView, ByVal strTitle As String)
        If gv.AllowPaging = True Then
            gv.AllowPaging = False
        End If

        HttpContext.Current.Response.Clear()
        HttpContext.Current.Response.AddHeader("content-disposition", String.Format("attachment; filename={0}", fileName))
        'HttpContext.Current.Response.ContentType = "application/ms-excel"
        HttpContext.Current.Response.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"

        Dim sw As StringWriter = New StringWriter
        Dim htw As HtmlTextWriter = New HtmlTextWriter(sw)
        '  Create a form to contain the grid
        Dim table As Table = New Table
        table.GridLines = gv.GridLines
        If strTitle <> "" Then
            strTitle = "<p><b>" & strTitle & "</b></p>"
            sw.Write(strTitle)
        End If

        '  add the header row to the table
        If (Not (gv.HeaderRow) Is Nothing) Then
            UtilClass.PrepareControlForExport(gv.HeaderRow)
            table.Rows.Add(gv.HeaderRow)
        End If
        '  add each of the data rows to the table
        For Each row As GridViewRow In gv.Rows
            UtilClass.PrepareControlForExport(row)
            table.Rows.Add(row)
        Next
        '  add the footer row to the table
        If (Not (gv.FooterRow) Is Nothing) Then
            UtilClass.PrepareControlForExport(gv.FooterRow)
            table.Rows.Add(gv.FooterRow)
        End If
        '  render the table into the htmlwriter
        table.RenderControl(htw)

        '  render the htmlwriter into the response
        HttpContext.Current.Response.Write(sw.ToString)

        HttpContext.Current.Response.End()
    End Sub

    Private Shared Sub PrepareControlForExport(ByVal control As Control)
        Dim i As Integer = 0
        Do While (i < control.Controls.Count)
            Dim current As Control = control.Controls(i)
            If current.Visible Then
                If (TypeOf current Is LinkButton) Then
                    control.Controls.Remove(current)
                    control.Controls.AddAt(i, New LiteralControl(CType(current, LinkButton).Text))
                ElseIf (TypeOf current Is ImageButton) Then
                    control.Controls.Remove(current)
                    control.Controls.AddAt(i, New LiteralControl(CType(current, ImageButton).AlternateText))
                ElseIf (TypeOf current Is HyperLink) Then
                    control.Controls.Remove(current)
                    control.Controls.AddAt(i, New LiteralControl(CType(current, HyperLink).Text))
                ElseIf (TypeOf current Is DropDownList) Then
                    control.Controls.Remove(current)
                    control.Controls.AddAt(i, New LiteralControl(CType(current, DropDownList).SelectedItem.Text))
                ElseIf (TypeOf current Is CheckBox) Then
                    control.Controls.Remove(current)
                    control.Controls.AddAt(i, New LiteralControl(CType(current, CheckBox).Checked))
                    'TODO: Warning!!!, inline IF is not supported ?
                End If
                If current.HasControls Then
                    UtilClass.PrepareControlForExport(current)
                End If
            End If
            i = (i + 1)
        Loop
    End Sub
ASP.NET
ASP.NET
A set of technologies in the .NET Framework for building web applications and XML web services.
3,254 questions
0 comments No comments
{count} votes

1 answer

Sort by: Most helpful
  1. Yijing Sun-MSFT 7,066 Reputation points
    2021-07-13T05:54:11.577+00:00

    Hi @David Chase ,
    As far as I think,your export and add imagebutton events are right. But as far as I know,there are two problems of your codes:
    1.You have to specify full path instead of relative path.
    2.If Your image route format is right.
    You could learn more about export images.

      Protected Sub ExportExcel(ByVal sender As Object, ByVal e As EventArgs)  
                Image1.ImageUrl = Me.GetAbsoluteUrl(Image1.ImageUrl)  
    
            Using sw As StringWriter = New StringWriter()  
    
                Using hw As HtmlTextWriter = New HtmlTextWriter(sw)  
                    Dim table As Table = New Table()  
                    Dim row As TableRow = New TableRow()  
                    row.Cells.Add(New TableCell())  
                    row.Cells(0).Controls.Add(Image1)  
                    table.Rows.Add(row)  
                    table.RenderControl(hw)  
                    Response.Clear()  
                    Response.Buffer = True  
                    Response.AddHeader("content-disposition", "attachment;filename=Images.xls")  
                    Response.Charset = ""  
                    Response.ContentType = "application/vnd.ms-excel"  
                    Response.Write(sw.ToString())  
                    Response.Flush()  
                    Response.[End]()  
                End Using  
            End Using  
        End Sub  
    
        Public Overrides Sub VerifyRenderingInServerForm(ByVal control As Control)  
        End Sub  
    
        Private Function GetAbsoluteUrl(ByVal relativeUrl As String) As String  
            relativeUrl = relativeUrl.Replace("~/", String.Empty)  
            Dim splits As String() = Request.Url.AbsoluteUri.Split("/"c)  
    
            If splits.Length >= 2 Then  
                Dim url As String = splits(0) & "//"  
    
                For i As Integer = 2 To splits.Length - 1 - 1  
                    url += splits(i)  
                    url += "/"  
                Next  
    
                Return url & relativeUrl  
            End If  
    
            Return relativeUrl  
        End Function  
    

    Best regards,
    Yijing Sun


    If the answer is helpful, please click "Accept Answer" and upvote it.

    Note: Please follow the steps in our  documentation  to enable e-mail notifications if you want to receive the related email notification for this thread.