C# 如何开发将模型对象转换为Excel工作表(.xls)和文本文件(.csv)的操作方法
在我的asp.net mvc web应用程序中有以下视图:,它只是在表中显示模型数据,在表列标题处有三个复选框,用于选择应将哪些列提取到excel(.xls)或文本(.csv)文件。 意见是:-C# 如何开发将模型对象转换为Excel工作表(.xls)和文本文件(.csv)的操作方法,c#,asp.net-mvc,asp.net-mvc-3,razor,entity-framework-4,C#,Asp.net Mvc,Asp.net Mvc 3,Razor,Entity Framework 4,在我的asp.net mvc web应用程序中有以下视图:,它只是在表中显示模型数据,在表列标题处有三个复选框,用于选择应将哪些列提取到excel(.xls)或文本(.csv)文件。 意见是:- @model MvcApplication4.Models.SelectedCustomers @{ ViewBag.Title = "CustomerDetials"; } <h3>Select Customers Detials</h3> <table>
@model MvcApplication4.Models.SelectedCustomers
@{
ViewBag.Title = "CustomerDetials";
}
<h3>Select Customers Detials</h3>
<table>
<tr>
<th>
NAME @Html.CheckBox("Name",true)
</th>
<th>
Description @Html.CheckBox("Description",true)
</th>
<th>
Address @Html.CheckBox("Address",true)
</th>
</tr>
@foreach (var item in Model.Info) {
<tr>
<td>
@Html.DisplayFor(modelItem => item.Name)
</td>
<td>
@Html.DisplayFor(modelItem => item.description)
</td>
<td>
@Html.DisplayFor(modelItem => item.address)
</td>
</tr>
}
</table>
<p>
@Html.ActionLink("Back","customer","Home") |
<a href="">extract to excel</a> |
<a href="">extract to text file</a>
</p>
以及以下模型类:-
public abstract class ExportAccountsResult : ActionResult
{
protected ExportAccountsResult(IEnumerable<Account> accounts, ExportViewModel exportOptions)
{
this.Accounts = accounts;
this.ExportOptions = exportOptions;
}
protected IEnumerable<Account> Accounts { get; private set; }
protected ExportViewModel ExportOptions { get; private set; }
protected abstract string ContentType { get; }
protected abstract string Filename { get; }
public override void ExecuteResult(ControllerContext context)
{
var response = context.HttpContext.Response;
response.ContentType = ContentType;
var cd = new ContentDisposition
{
FileName = this.Filename,
Inline = false
};
response.AddHeader("Content-Disposition", cd.ToString());
// TODO: Use a real CSV parser here such as https://github.com/JoshClose/CsvHelper/wiki/Basics
// and never roll your own parser as shown in this oversimplified
// example. Here's why: http://secretgeek.net/csv_trouble.asp
using (var writer = new StreamWriter(response.OutputStream))
{
foreach (var account in this.Accounts)
{
var values = new List<object>();
if (this.ExportOptions.IncludeName)
{
values.Add(account.Name);
}
if (this.ExportOptions.IncludeDescription)
{
values.Add(account.Description);
}
if (this.ExportOptions.IncludeAddress)
{
values.Add(account.Address);
}
writer.WriteLine(string.Join(", ", values));
}
}
}
}
}
namespace MvcApplication4.Models
{
public class ExportViewModel
{
public string Format { get; set; }
public bool IncludeName { get; set; }
public bool IncludeDescription { get; set; }
public bool IncludeAddress { get; set; }
}
}
namespace MvcApplication4.Models
{
public class CsvResult : ExportAccountsResult
{
public CsvResult(IEnumerable<Account> accounts, ExportViewModel exportOptions)
: base(accounts, exportOptions)
{
}
protected override string ContentType
{
get { return "text/csv"; }
}
protected override string Filename
{
get { return "accounts.csv"; }
}
}
}
namespace MvcApplication4.Models
{
public class XlsResult : ExportAccountsResult
{
public XlsResult(IEnumerable<Account> accounts, ExportViewModel exportOptions)
: base(accounts, exportOptions)
{
}
protected override string ContentType
{
get { return "application/vnd.ms-excel"; }
}
protected override string Filename
{
get { return "accounts.csv"; }
}
}
}
namespace MvcApplication4.Models
{
public class SelectedCustomers
{
public IEnumerable<Account> Info { get; set; }
}
public static class ActionResultextensions
{
public static ActionResult AsCsvResult(this IEnumerable<Account> accounts, ExportViewModel exportOptions)
{
return new CsvResult(accounts, exportOptions);
}
public static ActionResult AsXlsResult(this IEnumerable<Account> accounts, ExportViewModel exportOptions)
{
return new XlsResult(accounts, exportOptions);
}
}
}
那么,可能出了什么问题?
BR您可以将记录放入一个表单中,并使用两个链接提交按钮。让我们举个例子。我们将对文本文件和Excel文件格式使用CSV,因为Excel理解CSV。如果需要为Excel导出应用某些特殊格式,可以使用第三方库,例如 让我们从定义视图模型开始:
public class SelectedCustomers
{
public IEnumerable<Account> Info { get; set; }
}
public class Account
{
public string Name { get; set; }
public string Description { get; set; }
public string Address { get; set; }
}
public class ExportViewModel
{
public string Format { get; set; }
public bool IncludeName { get; set; }
public bool IncludeDescription { get; set; }
public bool IncludeAddress { get; set; }
}
然后我们可以有两种实现:
public class CsvResult : ExportAccountsResult
{
public CsvResult(IEnumerable<Account> accounts, ExportViewModel exportOptions)
: base(accounts, exportOptions)
{
}
protected override string ContentType
{
get { return "text/csv"; }
}
protected override string Filename
{
get { return "accounts.csv"; }
}
}
public class XlsResult : ExportAccountsResult
{
public XlsResult(IEnumerable<Account> accounts, ExportViewModel exportOptions)
: base(accounts, exportOptions)
{
}
protected override string ContentType
{
get { return "application/vnd.ms-excel"; }
}
protected override string Filename
{
get { return "accounts.csv"; }
}
}
public类CsvResult:ExportAccountsResult
{
公共CsvResult(IEnumerable帐户、ExportViewModel导出选项)
:base(帐户、导出选项)
{
}
受保护的重写字符串ContentType
{
获取{return“text/csv”;}
}
受保护的重写字符串文件名
{
获取{return“accounts.csv”;}
}
}
公共类XlsResult:ExportAccountsResult
{
公共XlsResult(IEnumerable帐户、ExportViewModel导出选项)
:base(帐户、导出选项)
{
}
受保护的重写字符串ContentType
{
获取{return“application/vnd.ms excel”;}
}
受保护的重写字符串文件名
{
获取{return“accounts.csv”;}
}
}
我对代码感到厌倦,但它出现了一些错误,但我认为在[HttpPost]公共操作结果导出(ExportViewModel exportOptions)上{我应该传递视图中的SelectedCustomer对象,而不是使用GetAccounts方法获取帐户。请给出建议。不,您不应该将SelectedCustomer
传递到Export
操作。您应该传递ExportViewModel
,如我的回答所示。至于错误你知道我不能给你任何建议,除非你先告诉我你犯了什么错误,对吗?我看不懂你的心思。我已经在我的电脑上测试了代码,它工作得很好。如果它在你的电脑上不工作,这可能意味着你做错了什么。谢谢,我已经用更新的代码和我得到的错误更新了我的原始帖子。Thnaksy你有在GET操作中从某处获取了它们,对吗?您应该在导出操作中从相同的位置获取它们。如果数据在内存中,那么就更容易了,您所要做的就是检索它们。您可以轻松地添加标题。只需修改我的示例中的ExecuteSult方法,并在生成的CSV containi中添加一行额外的内容正在删除列名。您需要再次检查是否使用视图模型中相应的布尔值选择了列。
System.NullReferenceException was unhandled by user code
HResult=-2147467261
Message=Object reference not set to an instance of an object.
Source=MvcApplication4
StackTrace:
at MvcApplication4.Models.ExportAccountsResult.ExecuteResult(ControllerContext context) in c:\Users\Administrator\Documents\Visual Studio 2012\Projects\MvcApplication4\MvcApplication4\Models\ExportAccountResult.cs:line 43
at System.Web.Mvc.ControllerActionInvoker.InvokeActionResult(ControllerContext controllerContext, ActionResult actionResult)
at System.Web.Mvc.ControllerActionInvoker.<>c__DisplayClass1c.<InvokeActionResultWithFilters>b__19()
at System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilter(IResultFilter filter, ResultExecutingContext preContext, Func`1 continuation)
InnerException:
foreach (var account in this.Accounts)
public class SelectedCustomers
{
public IEnumerable<Account> Info { get; set; }
}
public class Account
{
public string Name { get; set; }
public string Description { get; set; }
public string Address { get; set; }
}
public class ExportViewModel
{
public string Format { get; set; }
public bool IncludeName { get; set; }
public bool IncludeDescription { get; set; }
public bool IncludeAddress { get; set; }
}
public class HomeController : Controller
{
public ActionResult Index()
{
var model = new SelectedCustomers
{
Info = GetAccounts()
};
return View(model);
}
[HttpPost]
public ActionResult Export(ExportViewModel exportOptions)
{
var accounts = GetAccounts();
if (exportOptions.Format == "csv")
{
return accounts.AsCsvResult(exportOptions);
}
else if (exportOptions.Format == "xls")
{
return accounts.AsXlsResult(exportOptions);
}
throw new NotSupportedException(
string.Format("Unsupported format: {0}", exportOptions.Format)
);
}
private static IEnumerable<Account> GetAccounts()
{
// TODO: those records will probably come from a database or something
// I have hardcoded them here to make my answer more clear
// and not dependent on some data stores
return Enumerable.Range(1, 5).Select(x => new Account
{
Name = "name " + x,
Description = "description " + x,
Address = "address " + x
});
}
}
@model SelectedCustomers
<h3>Select Customers Detials</h3>
@using (Html.BeginForm("Export", null))
{
<table>
<tr>
<th>
NAME @Html.CheckBox("IncludeName", true)
</th>
<th>
Description @Html.CheckBox("IncludeDescription", true)
</th>
<th>
Address @Html.CheckBox("IncludeAddress", true)
</th>
</tr>
@foreach (var item in Model.Info) {
<tr>
<td>
@Html.DisplayFor(modelItem => item.Name)
</td>
<td>
@Html.DisplayFor(modelItem => item.Description)
</td>
<td>
@Html.DisplayFor(modelItem => item.Address)
</td>
</tr>
}
</table>
<p>
@Html.ActionLink("Back","customer","Home") |
<button type="submit" name="format" value="xls">extract to excel</button> |
<button type="submit" name="format" value="csv">extract to text file</button>
</p>
}
public static class ActionResultextensions
{
public static ActionResult AsCsvResult(this IEnumerable<Account> accounts, ExportViewModel exportOptions)
{
return new CsvResult(accounts, exportOptions);
}
public static ActionResult AsXlsResult(this IEnumerable<Account> accounts, ExportViewModel exportOptions)
{
return new XlsResult(accounts, exportOptions);
}
}
public abstract class ExportAccountsResult : ActionResult
{
protected ExportAccountsResult(IEnumerable<Account> accounts, ExportViewModel exportOptions)
{
this.Accounts = accounts;
this.ExportOptions = exportOptions;
}
protected IEnumerable<Account> Accounts { get; private set; }
protected ExportViewModel ExportOptions { get; private set; }
protected abstract string ContentType { get; }
protected abstract string Filename { get; }
public override void ExecuteResult(ControllerContext context)
{
var response = context.HttpContext.Response;
response.ContentType = ContentType;
var cd = new ContentDisposition
{
FileName = this.Filename,
Inline = false
};
response.AddHeader("Content-Disposition", cd.ToString());
// TODO: Use a real CSV parser here such as https://github.com/JoshClose/CsvHelper/wiki/Basics
// and never roll your own parser as shown in this oversimplified
// example. Here's why: http://secretgeek.net/csv_trouble.asp
using (var writer = new StreamWriter(response.OutputStream))
{
foreach (var account in this.Accounts)
{
var values = new List<object>();
if (this.ExportOptions.IncludeName)
{
values.Add(account.Name);
}
if (this.ExportOptions.IncludeDescription)
{
values.Add(account.Description);
}
if (this.ExportOptions.IncludeAddress)
{
values.Add(account.Address);
}
writer.WriteLine(string.Join(", ", values));
}
}
}
}
public class CsvResult : ExportAccountsResult
{
public CsvResult(IEnumerable<Account> accounts, ExportViewModel exportOptions)
: base(accounts, exportOptions)
{
}
protected override string ContentType
{
get { return "text/csv"; }
}
protected override string Filename
{
get { return "accounts.csv"; }
}
}
public class XlsResult : ExportAccountsResult
{
public XlsResult(IEnumerable<Account> accounts, ExportViewModel exportOptions)
: base(accounts, exportOptions)
{
}
protected override string ContentType
{
get { return "application/vnd.ms-excel"; }
}
protected override string Filename
{
get { return "accounts.csv"; }
}
}