我在mvc中有一个填充了xml的cshtml视图,例如:
@model myproject.net.Models.mymodel
@{
Layout = null;
Response.ContentType = "application/vnd.ms-excel";
Response.AddHeader("Content-Disposition", "attachment; " + "filename=" +
Model.myusername.ToString() + "(" +
Model.mydate.Date.ToShortDateString() + ").xls");
}
<?xml version="1.0" encoding="utf-8"?>
<ss:Workbook xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet">
<Styles>
<Style ss:ID="s25">
<Alignment ss:Horizontal="Center" ss:Vertical="Bottom"/>
<Borders>
<Border ss:Position="Bottom" ss:LineStyle="Continuous" ss:Weight="1"/>
</Borders>
<Interior ss:Color="#FFA500" ss:Pattern="Solid"/>
</Style>
</Styles>
<ss:Worksheet ss:Name="Sheet1">
<ss:Table>
@if (Model.someNumerableContent.Count > 0)
{
<!-- MyContent -->
<ss:Row>
<ss:Cell><ss:Data ss:Type="String">Content Header</ss:Data></ss:Cell>
</ss:Row>
<ss:Row>
<ss:Cell><ss:Data ss:Type="String">SubHeader 1</ss:Data></ss:Cell>
<ss:Cell><ss:Data ss:Type="String">SubHeader 2</ss:Data></ss:Cell>
<ss:Cell><ss:Data ss:Type="String">SubHeader 3</ss:Data></ss:Cell>
<ss:Cell><ss:Data ss:Type="String">SubHeader 4</ss:Data></ss:Cell>
<ss:Cell><ss:Data ss:Type="String">SubHeader 5</ss:Data></ss:Cell>
</ss:Row>
foreach (var subContent in Model.someNumerableContent)
{
<ss:Row>
<ss:Cell><ss:Data ss:Type="String">@subContent.mydate.Date.ToShortDateString()</ss:Data></ss:Cell>
<ss:Cell><ss:Data ss:Type="String">@subContent.number</ss:Data></ss:Cell>
<ss:Cell><ss:Data ss:Type="String">@subContent.name</ss:Data></ss:Cell>
<ss:Cell><ss:Data ss:Type="String">@subContent.surname</ss:Data></ss:Cell>
<ss:Cell><ss:Data ss:Type="String">@subContent.issue</ss:Data></ss:Cell>
</ss:Row>
}
<ss:Row> </ss:Row>
}
</ss:Table>
</ss:Worksheet>
</ss:Workbook>
我希望将其转换为.xls文件并附加到邮件而不保存在任何地方。 但无法弄清楚我怎么能做到这一点。我无法使用office.interop来获取服务器中的一些限制因此它不是我的选择。我只想通过Xml创建一个.xls文件并使用.net邮件发送它。到目前为止我已经这样做了:
// Memory stream for the xml file
using (MemoryStream memoryStream = new MemoryStream())
{
// Can i use something like this?
byte[] contentAsBytes = Encoding.Default.GetBytes( View("ExportToExcel").ToString() );
memoryStream.Write(contentAsBytes, 0, contentAsBytes.Length);
// Set the position to the beginning of the stream.
memoryStream.Seek(0, SeekOrigin.Begin);
// Create attachment
ContentType contentType = new ContentType();
contentType.MediaType = MediaTypeNames.Text.Xml;
contentType.Name = UserName + "(" + FileDate + ").xls";
// Attach
mail.Attachment = new Attachment(memoryStream, contentType);
}
所以我怎么能做到这一点呢?
答案 0 :(得分:2)
我无法成功实施剃刀视图,但在工作30个小时之后。我发现了另一种方法..
首先我创建了一个XmlString,如下所示:
public String XmlToImplement(int id)
{
// Add values from db to model
MyModel model = new MyModel();
model.contents = db.contents.Where(c => c.MyData.id == id).ToList();
// XmlString
String XmlString = @"<?xml version='1.0' encoding='utf-8'?>
<ss:Workbook xmlns='urn:schemas-microsoft-com:office:spreadsheet'
xmlns:o='urn:schemas-microsoft-com:office:office'
xmlns:x='urn:schemas-microsoft-com:office:excel'
xmlns:ss='urn:schemas-microsoft-com:office:spreadsheet'
xmlns:html='http://www.w3.org/TR/REC-html40'>
<Styles>
<Style ss:ID='s25'>
<Alignment ss:Horizontal='Center' ss:Vertical='Bottom'/>
<Borders>
<Border ss:Position='Bottom' ss:LineStyle='Continuous' ss:Weight='1'/>
</Borders>
<Interior ss:Color='#FFA500' ss:Pattern='Solid'/>
</Style>
</Styles>
<ss:Worksheet ss:Name='Sheet1'>
<ss:Table>";
if (model.contents.Count > 0)
{
XmlString = XmlString + @"<!-- MyModelData -->
<ss:Row>
<ss:Cell><ss:Data ss:Type='String'> MyModelData </ss:Data></ss:Cell>
</ss:Row>
<ss:Row>
<ss:Cell><ss:Data ss:Type='String'>Date</ss:Data></ss:Cell>
<ss:Cell><ss:Data ss:Type='String'>Number</ss:Data></ss:Cell>
<ss:Cell><ss:Data ss:Type='String'>Name/Surname</ss:Data></ss:Cell>
</ss:Row>";
foreach (var content in model.contents)
{
XmlString = XmlString + @"<ss:Row>";
XmlString = XmlString + @"<ss:Cell><ss:Data ss:Type='String'>" + content.thedate.Date.ToShortDateString() + "</ss:Data></ss:Cell>";
XmlString = XmlString + @"<ss:Cell><ss:Data ss:Type='String'>" + content.number + "</ss:Data></ss:Cell>";
XmlString = XmlString + @"<ss:Cell><ss:Data ss:Type='String'>" + content.namesurname+ "</ss:Data></ss:Cell>";
XmlString = XmlString + @"</ss:Row>";
}
// An empty row for next value set
XmlString = XmlString + "<ss:Row> </ss:Row>";
}
XmlString = XmlString + @"</ss:Table>
</ss:Worksheet>
</ss:Workbook>";
return XmlString;
}
然后我使用MemoryStream
编码将其保存到UTF8
// Create attachment
// Add XML to MemoryStream /* MyXmlString */
MemoryStream memoryStream = new MemoryStream(Encoding.UTF8.GetBytes(XmlToImplement(id)));
然后将ContentType
定义为Excel
// Content Type
ContentType contentType = new ContentType("application/vnd.ms-excel");
contentType.Name = UserName + "(" + FileDate + ").xls";
最后我将它附加到.net邮件
// Attach
mail.Attachment = new Attachment(memoryStream, contentType);
mail.Attachment.NameEncoding = UTF8Encoding.UTF8;
mail.Attachment.TransferEncoding = TransferEncoding.Base64;
mail.Attachment.ContentDisposition.DispositionType = DispositionTypeNames.Attachment;
它运作得很好。我可能无法将xml视图转换为邮件附件,但很容易我可以将xml字符串转换为邮件附件,我希望这有助于其他人解决这个问题。
答案 1 :(得分:1)
取决于excel的版本或您需要的功能。 Carlos Ag's Excel Writer可能就足够了。它有点陈旧,但适用于简单的excel工作簿。
如果您需要自己滚动模板,请查看Razor Generator Templates以将模型渲染为字符串。将字符串传递给Stream
并附加到电子邮件。
<强>更新强>
首先使用剃须刀模板,你需要一个视图
@* Generator: Template *@
@inherits The.NameSpace.RazorTemplateBase<dynamic>
@functions {
public object Model { get; set; }
}
<your typical markup goes here...>
然后你需要基类
public abstract class RazorTemplateBase<dynamic>
{
public static string RootAddress { get; set; }
public virtual RazorTemplateBase<dynamic> Layout { get; set; }
private readonly StringBuilder generatingEnvironment = new StringBuilder();
public abstract void Execute();
public void WriteLiteral(string textToAppend)
{
if (string.IsNullOrEmpty(textToAppend))
{
return;
}
generatingEnvironment.Append(textToAppend);
}
public void Write(object value)
{
if ((value == null))
{
return;
}
string stringValue;
var t = value.GetType();
var method = t.GetMethod("ToString", new [] { typeof(IFormatProvider) });
if ((method == null))
{
stringValue = value.ToString();
}
else
{
stringValue = ((string)(method.Invoke(value, new object[] { CultureInfo.InvariantCulture })));
}
WriteLiteral(stringValue);
}
string content;
public string RenderBody()
{
return content;
}
public string TransformText()
{
Execute();
if (Layout != null)
{
Layout.content = generatingEnvironment.ToString();
return Layout.TransformText();
}
else
{
return generatingEnvironment.ToString();
}
}
}
按照项目homepage上的说明设置custom tool
(查看属性窗口)RazorGenerator
。
那么你可以做点什么
string excelXml = new NameOfMyView { Model = theData }.TransformText();
//write string to memmory stream, attach to MailMessage