Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/332.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何开发将模型对象转换为Excel工作表(.xls)和文本文件(.csv)的操作方法_C#_Asp.net Mvc_Asp.net Mvc 3_Razor_Entity Framework 4 - Fatal编程技术网

C# 如何开发将模型对象转换为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>

在我的asp.net mvc web应用程序中有以下视图:,它只是在表中显示模型数据,在表列标题处有三个复选框,用于选择应将哪些列提取到excel(.xls)或文本(.csv)文件。 意见是:-

@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"; }
    }
}