[英]Exporting Grid.MVC data to Excel
我需要將Grid.MVC中的數據導出到Excel,我使用了這個鏈接中的方案。
http://www.codeproject.com/Articles/325103/MVC-Grid-to-Excel-file-download?msg=5161340#xx5161340xx
它正在工作,但我有 2 個問題。 首先它在 chrome 中工作,但在 IE 中不工作。 它在 IE 中給我一個錯誤(無法讀取文件)。 第二個問題是當我過濾網格時,Excel 中導出的數據仍然顯示所有數據而不是過濾后的數據。
如果這不是一個好的解決方案,請提供將 Grid.MVC 數據導出到 excel 的示例。
我有一個適合我的javascript / jquery解決方案。
當你使用grid.mvc時,它會向thead和tbody添加一些類,需要刪除這些類,以便在生成的excel文件上進行正確的導出/可視化。 我也在使用grid.mvc,這個代碼導出為excel,如果這對你有用,請告訴我。
<script> $("#btnExport").click(function (e) { $('.grid-wrap').find('table').removeAttr('class'); $('.grid-header').removeAttr('class'); $('.grid-row').removeAttr('class'); $('.grid-cell').removeAttr('data-name'); $('.grid-cell').removeAttr('class'); window.open('data:application/vnd.ms-excel,' + $('.grid-wrap').html()); //MakeAnyFunctionToReloadThePageToGetTheClassesAgain(); e.preventDefault(); }); </script>
@Html.Grid(Model).Columns(columns => { columns.Add(foo => foo.Date).Sortable(true).Filterable(true); columns.Add(foo => foo.User).Sortable(true).Filterable(true); columns.Add(foo => foo.Controller).Sortable(true).Filterable(true); columns.Add(foo => foo.Action).Sortable(true).Filterable(true); columns.Add(foo => foo.ActionType).Sortable(true).Filterable(true); columns.Add(foo => foo.JsonObject).Sortable(true).Filterable(true); }).WithMultipleFilters() <button type="button" class="btn btn-danger" id="btnExport">export csv</button>
你必須從url獲取參數。 然后在后端構建自己的服務,獲取參數並導出到excel
let params = new URLSearchParams(document.location.search);
let allParams = params.getAll('grid-filter');
這是服務器端解決方案
在這種情況下,客戶端組件並不重要。 您傳遞的任何數據用於導出,它將其導出到excel文件並下載。 當我想要導出數據時,我使用最新的過濾器並檢索顯示的相同數據。
我希望它對你有所幫助。
GridView
來顯示我的數據。 DataBase
或任何地方檢索數據。 DataView
只是幫助我過濾數據。 ClosedXML
添加到項目中。 使用此NuGet
命令: Install-Package ClosedXML
ASPX
<form id="form1" runat="server"> <div> <asp:TextBox ID="TextBox1" runat="server" placeholder="Name or Family" ></asp:TextBox> <asp:Button ID="ButtonFilter" runat="server" Text="Filter" OnClick="ButtonFilter_Click" /> <br /> <br /> <asp:GridView ID="GridView1" runat="server"> </asp:GridView> <br /> <br /> <asp:Button ID="ButtonExport" runat="server" Text="Export" OnClick="ButtonExport_Click" /> </div> </form>
C#代碼
private DataTable dt = new DataTable();
private DataView dv;
private void Page_Load(object sender, System.EventArgs e)
{
dt.Columns.Add("Id");
dt.Columns.Add("EmployeeName");
dt.Columns.Add("EmployeeFamily");
for (int i = 0; i < 10; i++)
{
var r1 = dt.NewRow();
r1["Id"] = i + 100;
r1["EmployeeName"] = "Name " + i.ToString();
r1["EmployeeFamily"] = "Family " + i.ToString();
dt.Rows.Add(r1);
}
dv = new DataView(dt);
GridView1.DataSource = dv;
GridView1.DataBind();
}
private MemoryStream GetStream(XLWorkbook excelWorkbook)
{
MemoryStream fs = new MemoryStream();
excelWorkbook.SaveAs(fs);
fs.Position = 0;
return fs;
}
protected void ButtonFilter_Click(object sender, EventArgs e)
{
dv.RowFilter = $"EmployeeName LIKE '%{TextBox1.Text}%' OR EmployeeFamily LIKE '%{TextBox1.Text}%'";
GridView1.DataSource = dv;
GridView1.DataBind();
}
protected void ButtonExport_Click(object sender, EventArgs e)
{
dv = new DataView(dt);
dv.RowFilter = $"EmployeeName LIKE '%{TextBox1.Text}%' OR EmployeeFamily LIKE '%{TextBox1.Text}%'";
using (XLWorkbook wb = new XLWorkbook())
{
wb.Worksheets.Add(dv.ToTable(), "Employees");
string myName = HttpContext.Current.Server.UrlEncode("Employees.xlsx");
MemoryStream stream = GetStream(wb);
HttpContext.Current.Response.Clear();
HttpContext.Current.Response.Buffer = true;
HttpContext.Current.Response.AddHeader("content-disposition", "attachment; filename=" + myName);
HttpContext.Current.Response.ContentType = "application/vnd.ms-excel";
HttpContext.Current.Response.BinaryWrite(stream.ToArray());
HttpContext.Current.Response.End();
}
}
更新: GridMvc
版本
在這個版本中,我使用了GridMvc
但我仍然在服務器端制作Excel文件
ASPX
@model IList<GridMvcExportToExcel.Controllers.EmployeeModel> @using GridMvc.Html @{ ViewBag.Title = "Home Page"; } <script type="text/javascript"> function exportToExcel() { debugger; var txtFilter = $('#txtFilter').val(); // get the textbox value var url = 'http://localhost:54312/Home/ExportToExcel?txtFilter=' + txtFilter; location.href = url; // redirect return false; // cancel default redirect }; </script> <div> @using (Html.BeginForm("Index", "Home")) { @Html.TextBox("txtFilter", "", new { id = "txtFilter" }) <button type="submit">Filter</button> } <br /> @Html.Grid(Model).Columns(c => { c.Add(x=>x.Id).Titled ("Employee Id"); c.Add(x=>x.Name).Titled ("First Name").Filterable(false); c.Add(x=>x.Family).Titled ("Last Name").Filterable(true); }).WithPaging(50) <input type="button" id="exportToExcel" value="Export to Excel" onclick="exportToExcel()" /> </div>
C#
public class EmployeeModel
{
public int Id { get; set; }
public string Name { get; set; }
public string Family { get; set; }
}
public class HomeController : Controller
{
private IList<EmployeeModel> employees = new List<EmployeeModel>();
public HomeController()
{
for (int i = 0; i < 20; i++)
{
employees.Add(new EmployeeModel()
{
Id = i + 1,
Name = "Name " + (i + 1).ToString(),
Family = "Family " + (i + 1).ToString(),
});
}
}
public ActionResult Index(string txtFilter)
{
txtFilter = txtFilter ?? "";
var result = employees.Where(x => x.Name.Contains(txtFilter) || x.Family.Contains(txtFilter) || x.Id.ToString() == txtFilter);
return View(result.ToList());
}
public void ExportToExcel(string txtFilter)
{
txtFilter = txtFilter ?? "";
var result = employees.Where(x => x.Name.Contains(txtFilter) || x.Family.Contains(txtFilter) || x.Id.ToString() == txtFilter).ToList();
DataTable table = new DataTable();
using (var reader = ObjectReader.Create(result))
{
table.Load(reader);
}
using (XLWorkbook wb = new XLWorkbook())
{
wb.Worksheets.Add(table, "Employees");
string myName = HttpContext.Server.UrlEncode("Employees.xlsx");
MemoryStream stream = GetStream(wb);
HttpContext.Response.Clear();
HttpContext.Response.Buffer = true;
HttpContext.Response.AddHeader("content-disposition", "attachment; filename=" + myName);
HttpContext.Response.ContentType = "application/vnd.ms-excel";
HttpContext.Response.BinaryWrite(stream.ToArray());
HttpContext.Response.End();
}
}
private MemoryStream GetStream(XLWorkbook excelWorkbook)
{
MemoryStream fs = new MemoryStream();
excelWorkbook.SaveAs(fs);
fs.Position = 0;
return fs;
}
}
在響應中設置以下標題,將以適當的類型下載
數據:應用程序/ vnd.ms-Excel中
我可能會遲到,但我找到了一個解決方案,可以使用GridMvc
插件的內置filtering
選項。 此解決方案不需要任何客戶端操作或自定義過濾器應用。 你這是怎么go一下的。
安裝插件時,它會生成一個名為: _Grid.cshtml
的partial
視圖,位於: ~/Views/Shared/_Grid.cshtml
位置。
現在我觀察到,每次您在網格上調用一個事件時,都會調用這個局部視圖,然后我調試到流程中,發現有問題的Model
具有不同的屬性,如RenderOptions
、 ItemsToDisplay
等。
所以我發現過濾后的數據也存儲了但沒有直接存儲在屬性中。 有一個名為: ItemsToDisplay
的屬性,但不幸的是,如果您在網格上應用paging
,那么它只會存儲前n
項目,其中n
是分頁限制。
最后我不得不求助於reflection
來獲取整個過濾列表,這會影響網格的性能但影響不大,但它會完成工作。
_網格.cshtml:
@using GridMvc.Columns
@using System.Reflection;
@model GridMvc.IGrid
@{
try
{
Type t = typeof(GridMvc.Html.GridHtmlOptions<MyModel>);
FieldInfo[] fi = t.GetFields(BindingFlags.Public | BindingFlags.Instance | BindingFlags.NonPublic);
foreach (FieldInfo info in fi)
{
if (info.Name == "_source")
{
object _source = info.GetValue(Model);
PropertyInfo gridItemsProperty = _source.GetType().GetProperty("GridItems");
object gridItemsData = gridItemsProperty.GetValue(_source);
//Set the filtered list here in Session
Session["CurrentFilteredGridForExcelExport"] = (IEnumerable<MyModel>)(gridItemsData);
}
}
}
catch
{
}
}
@if (Model.RenderOptions.RenderRowsOnly)
{
@RenderGridBody();
}
else
{
<div class="grid-mvc" data-lang="@Model.Language" data-gridname="@Model.RenderOptions.GridName" data-selectable="@Model.RenderOptions.Selectable.ToString().ToLower()" data-multiplefilters="@Model.RenderOptions.AllowMultipleFilters.ToString().ToLower()">
<div class="grid-wrap">
<table class="table table-striped grid-table">
@* Draw grid header *@
<thead>
@RenderGridHeader()
</thead>
<tbody>
@RenderGridBody()
@RenderGridFooter()
</tbody>
</table>
@RenderGridFooter()
</div>
</div>
}
@helper RenderGridBody()
{
if (!Model.ItemsToDisplay.Any())
{
<tr class="grid-empty-text">
<td colspan="@Model.Columns.Count()">
@Model.EmptyGridText
</td>
</tr>
}
else
{
foreach (object item in Model.ItemsToDisplay)
{
<tr class="grid-row @Model.GetRowCssClasses(item)">
@foreach (IGridColumn column in Model.Columns)
{
@column.CellRenderer.Render(column, column.GetCell(item))
}
</tr>
}
}
}
@helper RenderGridHeader()
{
if (Model.RenderOptions.ShowGridItemsCount)
{
<div class="grid-itemscount">
<span class="grid-itemscount-label">@Model.RenderOptions.GridCountDisplayName:</span>
<span class="grid-itemscount-caption">@Model.ItemsCount</span>
</div>
}
<tr>
@foreach (IGridColumn column in Model.Columns)
{
@column.HeaderRenderer.Render(column)
}
</tr>
}
@helper RenderGridFooter()
{
<div class="grid-footer">
@if (Model.EnablePaging && Model.Pager != null)
{
@Html.Partial(Model.Pager.TemplateName, Model.Pager)
}
</div>
}
最后,您可以像這樣在您的Controller
端導出這個過濾后的網格:
public void ExportToExcel()
{
List<MyModel> mymodel= new List<MyModel>();
if(Session["CurrentFilteredGridForExcelExport"] != null)
{
var datasetFromSession = (IEnumerable<MyModel>)(Session["CurrentFilteredGridForExcelExport"]);
mymodel = datasetFromSession.ToList();
}
//Use your export logic with this dataset
}
希望這對仍在使用此網格插件的人有所幫助。 干杯!
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.