MVC: Export contents of a grid on my View to Excel

2019-09-11 18:12发布

I am using GridMVC to load my model data values into a nice grid on my view, complete with Sort/Filter capabilities. The grid is coded like so on the View:

<div class="assetList">
    @try
    {
        @Html.Grid(Model).Columns(columns =>
        {
            columns.Add().Encoded(false).Sanitized(false).RenderValueAs(o => @<a href="/INV_Assets/Edit/@o.Id" class="btn btn-primary btn-sm noDecoration"><span class="glyphicon glyphicon-pencil"></span> @*Edit*@</a>).SetWidth(15);
            columns.Add().Encoded(false).Sanitized(false).RenderValueAs(o => @<a href="/INV_Assets/Delete/@o.Id" class="btn btn-danger btn-sm noDecoration"><span class="glyphicon glyphicon-remove-circle"></span> @*Delete*@</a>).SetWidth(15);
            columns.Add().Encoded(false).Sanitized(false).RenderValueAs(o => @<a href="#" class="btn btn-default btn-sm noDecoration verifyBtn" onclick="verifyAsset(@o.Id)"><span class="glyphicon glyphicon-ok"></span> @*View*@</a>).SetWidth(15);
            @*columns.Add().Encoded(false).Sanitized(false).RenderValueAs(o => @<a href="/INV_Assets/Details/@o.Id" class="btn btn-default btn-sm noDecoration"><span class="glyphicon glyphicon-eye-open"></span> @*View*</a>).SetWidth(15);*@
            columns.Add(o => o.Status.status_description).Titled("Status").RenderValueAs(o => o.Status.status_description).Sanitized(false).Encoded(false).Sortable(true).Filterable(true).SetWidth(20);
            columns.Add(o => o.Location.location_dept).Titled("Dept").RenderValueAs(o => o.Location.location_dept).SetWidth(20);
            columns.Add(o => o.Location.location_room).Titled("Room").RenderValueAs(o => o.Location.location_room).SetWidth(20);
            columns.Add(o => o.owner).Titled("Owner").RenderValueAs(o => o.owner).SetWidth(20);
            columns.Add(o => o.Type.type_description).Titled("Type").RenderValueAs(o => o.Type.type_description).SetWidth(20);
            columns.Add(o => o.Manufacturer.manufacturer_description).Titled("Manufacturer").RenderValueAs(o => o.Manufacturer.manufacturer_description).SetWidth(20);
            columns.Add(o => o.Model.model_description).Titled("Model").RenderValueAs(o => o.Model.model_description).SetWidth(20);
            columns.Add(o => o.Vendor.vendor_name).Titled("Vendor").RenderValueAs(o => o.Vendor.vendor_name).SetWidth(20);
            columns.Add(o => o.description).Titled("Desc").RenderValueAs(o => o.description).SetWidth(20);
            columns.Add(o => o.asset_tag_number).Titled("Asset Tag #").RenderValueAs(o => o.asset_tag_number).SetWidth(20);
            columns.Add(o => o.serial_number).Titled("Serial #").RenderValueAs(o => o.serial_number).SetWidth(20);
            columns.Add(o => o.ip_address).Titled("IP Addr").RenderValueAs(o => o.ip_address).SetWidth(20);
            columns.Add(o => o.mac_address).Titled("Mac Addr").RenderValueAs(o => o.mac_address).SetWidth(20);
            columns.Add(o => o.po_number).Titled("PO #").RenderValueAs(o => o.po_number).SetWidth(20);
            columns.Add(o => o.invoice_number).Titled("Inv. #").RenderValueAs(o => Convert.ToString(o.invoice_number)).SetWidth(20);
            columns.Add(o => o.cost).Titled("Cost").RenderValueAs(o => "$" + Convert.ToString(o.cost)).SetWidth(20);
            columns.Add(o => o.note).Titled("Note").RenderValueAs(o => o.note).SetWidth(20);
            columns.Add(o => o.acquired_date).Titled("Acq. Date").RenderValueAs(o => Convert.ToString(o.acquired_date)).SetWidth(20);
            columns.Add(o => o.disposed_date).Titled("Disp. Date").RenderValueAs(o => Convert.ToString(o.disposed_date)).SetWidth(20);
            columns.Add(o => o.verified_date).Titled("Ver. Date").RenderValueAs(o => Convert.ToString(o.verified_date)).SetWidth(20);
            columns.Add(o => o.created_date).Titled("Crtd. Date").RenderValueAs(o => Convert.ToString(o.created_date)).SetWidth(20);
            columns.Add(o => o.created_by).Titled("By").RenderValueAs(o => o.created_by).SetWidth(20);
            columns.Add(o => o.modified_date).Titled("Mod. Date").RenderValueAs(o => Convert.ToString(o.modified_date)).SetWidth(20);
            columns.Add(o => o.modified_by).Titled("By").RenderValueAs(o => o.modified_by).SetWidth(20);
        }).WithPaging(10).Sortable().Filterable().WithMultipleFilters();
    }
    catch (NullReferenceException ex)
    {
        return;
    }
</div>

With my current data, when I filter to show the only Asset with a [Status] of Available (1 record), the HTML rendered (for just the data row, not the Column Header/Filter function) is this:

    <tbody>
                        <tr class="grid-row ">
<td class="grid-cell" data-name=""><a href="/INV_Assets/Edit/5" class="btn btn-primary btn-sm noDecoration"><span class="glyphicon glyphicon-pencil"></span> </a></td>
<td class="grid-cell" data-name=""><a href="/INV_Assets/Delete/5" class="btn btn-danger btn-sm noDecoration"><span class="glyphicon glyphicon-remove-circle"></span> </a></td>
<td class="grid-cell" data-name=""><a href="#" class="btn btn-default btn-sm noDecoration verifyBtn" onclick="verifyAsset(5)"><span class="glyphicon glyphicon-ok"></span> </a></td>
<td class="grid-cell" data-name="Status.status_description">AVAILABLE</td>   
<td class="grid-cell" data-name="Location.location_dept">IT</td>
<td class="grid-cell" data-name="Location.location_room">Storage</td>
<td class="grid-cell" data-name="owner"></td>
<td class="grid-cell" data-name="Type.type_description">Desktop</td>
<td class="grid-cell" data-name="Manufacturer.manufacturer_description">Apple</td>
<td class="grid-cell" data-name="Model.model_description">A1396</td>
<td class="grid-cell" data-name="Vendor.vendor_name">Apple</td>
<td class="grid-cell" data-name="description">32GB iPad - 3rd Generation</td>
<td class="grid-cell" data-name="asset_tag_number">673158189254</td>
<td class="grid-cell" data-name="serial_number">HGT9823</td>
<td class="grid-cell" data-name="ip_address">10.10.159.73</td>
<td class="grid-cell" data-name="mac_address">10.10.92.48</td>
<td class="grid-cell" data-name="po_number">H423</td>
<td class="grid-cell" data-name="invoice_number">210</td>
<td class="grid-cell" data-name="cost">$22.50</td>
<td class="grid-cell" data-name="note"></td>
<td class="grid-cell" data-name="acquired_date">2/25/2015 8:37:08 AM</td>
<td class="grid-cell" data-name="disposed_date"></td>
<td class="grid-cell" data-name="verified_date">1/1/2015 12:00:00 PM</td>
<td class="grid-cell" data-name="created_date">2/25/2015 8:37:08 AM</td>
<td class="grid-cell" data-name="created_by">Admin</td>
<td class="grid-cell" data-name="modified_date"></td>
<td class="grid-cell" data-name="modified_by"></td>    
</tr></tbody>

What I am attempting to do is create an Export() functionality to export the contents of specified fields into an Excel File. For instance, my final grid may only contain 10 field columns, but the Model itself has say 27 fields. I want to include all the fields as checkboxes, and for each one that is selected export those particular fields that are currently in the grid out to an Excel file.

I pieced together the following Controller Action from a few examples:

    public ActionResult Export()
    {
        GridView gv = new GridView();
        gv.DataSource = _db.INV_Assets.ToList();
        gv.DataBind();
        Response.ClearContent();
        Response.Buffer = true;
        Response.AddHeader("content-disposition", "attachment; filename=InventoryAssets-" + DateTime.Now + ".xls");
        Response.ContentType = "application/ms-excel";
        Response.Charset = "";
        StringWriter sw = new StringWriter();
        HtmlTextWriter htw = new HtmlTextWriter(sw);
        gv.RenderControl(htw);
        Response.Output.Write(sw.ToString());
        Response.Flush();
        Response.End();

        return RedirectToAction("Index", "Home");
    }

This currently takes everything within my INV_Assets Model and exports it like so:

ExportToExcel

What I don't like is that this current method Exports the entire INV_Assets Table/Model, and exports the Model, Manufacturer, Type, Location, Vendor, and Status ID's instead of the Text value for each one. Also, the [asset_tag_number] which should be something like 293548195023 shows up in the file as 2.93548E+11, though I believe this is just a formatting issue.

Can anyone provide insight or suggestions for how to improve/or better implement the desired functionality here?


EDIT:

Using Dawood's suggestion, I'm attempting to use EPPlus. On my View I now have a ListBox populated with all of my Model Properties and a link to call my ExportUsingEPPlus() Controller Action:

@Html.ListBox("PropertyList", typeof(InventoryTracker.Models.INV_Assets).GetProperties().Select(p => new SelectListItem { Text = p.Name, Value = p.Name, Selected = false }), new { @Id = "exportListBox" })

<a href="/Export/ExportUsingEPPlus" class="btn btn-default btn-sm noDecoration"><span class="glyphicon glyphicon-export"> Export - EPPlus</span></a>

In my Controller, I've gotten a test Excel file to generate using some examples with EPPlus I pieced together:

    public ActionResult ExportUsingEPPlus()
    {

        //FileInfo newExcelFile = new FileInfo(output);
        ExcelPackage package = new ExcelPackage();
        var ws = package.Workbook.Worksheets.Add("TestExport");
        ws.Cells["A1"].Value = "Sample Export 1";


        var memoryStream = new MemoryStream();
        package.SaveAs(memoryStream);

        string fileName = "Exported-InventoryAssets-" + DateTime.Now + ".xlsx";
        string contentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";

        memoryStream.Position = 0;
        return File(memoryStream, contentType, fileName);

    }

What I need to now is pass in all selected values in my ListBox to my controller action and then create an Excel Export containing all data in the selected fields.

Can anyone offer advice for how to pass my ListBox selections to the controller action ExportUsingEPPlus()?

0条回答
登录 后发表回答