我有高达150000的对象列表,我想在运行时绑定到razor视图,因为它导出为EXCEL但在绑定时我遇到了内存异常,是否有任何解决方法可以克服此限制?
导出方法:
public void ExportToExcel()
{
string viewPath = "~/Modules/Reports/Views/" + TempData["reportName"] + ".cshtml";
string viewPathCopy = "~/Modules/Reports/Views/" + TempData["reportName"] + "2.cshtml";
string serverViewPath = Server.MapPath(viewPath);
string serverViewPathCopy = Server.MapPath(viewPathCopy);
if (System.IO.File.Exists(serverViewPathCopy))
{
System.IO.File.Delete(serverViewPathCopy);
}
System.IO.File.Copy(serverViewPath, serverViewPathCopy);
string viewContents = System.IO.File.ReadAllText(serverViewPathCopy).Replace("thead", "tr");
viewContents += "<style>body{font-size:8px !important;}table {padding:0 !important,margin:0 !important}</style>";
System.IO.File.WriteAllText(serverViewPathCopy, viewContents);
System.IO.File.WriteAllText(viewPathCopy, TemplateFromFile(viewPathCopy, TempData["reportData"]));
FileInfo file = new FileInfo(viewPathCopy);
if (file.Exists)
{
Response.Clear();
Response.AddHeader("Content-Disposition", "attachment; filename=" + file.Name + ".xls");
Response.AddHeader("Content-Length", file.Length.ToString());
Response.ContentType = "application/octet-stream";
Response.WriteFile(file.FullName);
Response.End();
}
else
{
Response.Write("This file does not exist.");
}
}
要查看的绑定模型:
public string TemplateFromFile(string file, dynamic model)
{
string template = "";
TextReader textReader = new StreamReader(HelperMethods.GetFullFilePath(file));
try
{
template = textReader.ReadToEnd();
}
finally
{
textReader.Close();
}
return Razor.Parse(template, model);
}
答案 0 :(得分:0)
如果要导出大量数据,我的goto工具为DoddleReport,这样可以创建有效的xlsx导出。使用doddle,您甚至可以创建多选项卡Excel工作表(请参阅Github上的示例)。
一些代码
IEnumerable的扩展程序
public static ExportBuilder<TModel> Export<TModel>(this IEnumerable<TModel> models) where TModel : class
{
return ExportBuilder<TModel>.Create(models);
}
导出构建器
public class ExportBuilder<TModel> where TModel : class
{
private readonly IEnumerable<TModel> _models;
private readonly ICollection<IExportColumn<TModel>> _columns;
/// <summary>
/// Initializes a new instance of the <see cref="T:System.Object"/> class.
/// </summary>
private ExportBuilder(IEnumerable<TModel> models)
{
_models = models;
_columns = new List<IExportColumn<TModel>>();
}
public static ExportBuilder<TModel> Create(IEnumerable<TModel> models)
{
return new ExportBuilder<TModel>(models);
}
public ExportBuilder<TModel> Column<TProperty>(Expression<Func<TModel, TProperty>> display)
{
if (!(display.Body is MemberExpression))
throw new ArgumentException(display + " is not a property!");
var memberInfo = ((MemberExpression)display.Body).Member;
if (!memberInfo.HasAttribute<DisplayNameAttribute>())
throw new ArgumentException(display + " does not have a [Display] attribute");
var displayAttribute = ExtensionsForMemberInfo.GetAttribute<DisplayNameAttribute>(memberInfo);
_columns.Add(new ExportColumn<TModel, TProperty>(displayAttribute.DisplayName, display));
return this;
}
public ExportBuilder<TModel> Column<TProperty>(string header, Expression<Func<TModel, TProperty>> property)
{
_columns.Add(new ExportColumn<TModel, TProperty>(header, property));
return this;
}
public IReportSource ToReportSource()
{
if (_models.Any())
{
return DoddleExporter.ToReportSource(_models.Select(model => _columns.ToDictionary(c => c.Header, c => c.Display(model))));
}
var result = _columns
.ToDictionary(a => a.Header, a => string.Empty);
return DoddleExporter.ToReportSource(new[] { result });
}
public Report ToReport([CanBeNull] IEnumerable<KeyValuePair<string, string>> headers, [CanBeNull] IReportWriter writer = null)
{
headers = headers ?? Enumerable.Empty<KeyValuePair<string, string>>();
var report = new Report(ToReportSource(), writer);
//report.TextFields.Footer = string.Format(@"Aangemaakt op: {0}", DateTime.Now.ToString(DataFormatStrings.Date));
var headersArray = headers as KeyValuePair<string, string>[] ?? headers.ToArray();
if (headersArray.Any())
{
report.TextFields.Header = headersArray.Aggregate(string.Empty,
(currentHeaders, header) => string.Format("{0}{3}{1} : {2}", currentHeaders, header.Key, header.Value, Environment.NewLine));
}
return report;
}
public ReportResult ToExcelReportResult([CanBeNull] IEnumerable<KeyValuePair<string, string>> headers)
{
return new ReportResult(ToReport(headers), new ExcelReportWriter(), "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
}
}
出口商
public static class DoddleExporter
{
/// <summary>
/// Converts an enumerable of dictionaries to a report source
/// </summary>
/// <typeparam name="TValue">
/// The type of values in the dictionaries
/// </typeparam>
/// <param name="elements">
/// An enumerable of elements
/// </param>
/// <returns>The report source that was created from the elements</returns>
public static IReportSource ToReportSource<TValue>(IEnumerable<IDictionary<string, TValue>> elements)
{
var elementsArray = elements.ToArray();
if (!elementsArray.Any())
throw new ArgumentException("Can't export empty list of elements");
return ToReportSource(elementsArray, elementsArray.First().Keys.ToArray(),
(element, key) => element.ContainsKey(key) ? element[key] : default(TValue));
}
/// <summary>
/// Converts an enumerable of XElement to a report source
/// </summary>
/// <param name="rootElements">
/// The xml root elements that contain the values
/// </param>
/// <param name="keys">
/// They keys that can be used to fetch values from each root element
/// </param>
/// <returns>The report source that was created from the elements</returns>
public static IReportSource ToReportSource(IEnumerable<XElement> rootElements, string[] keys)
{
return ToReportSource(rootElements, keys, delegate(XElement element, string key)
{
var value = element.Element(XmlConvert.EncodeLocalName(key));
return value != null ? value.Value : null;
});
}
/// <summary>
/// Converts a list of elements to a report source
/// </summary>
/// <param name="elements">
/// An enumerable of elements
/// </param>
/// <param name="keys">
/// They keys with which the values can be fetched from one element
/// </param>
/// <param name="valueSelector">
/// The function with which one value can be fetched given one key and one element
/// </param>
/// <returns>The report source that was created from the elements</returns>
public static IReportSource ToReportSource<T>(IEnumerable<T> elements, string[] keys,
Func<T, string, object> valueSelector)
{
var expandos = new List<ExpandoObject>();
foreach (var element in elements)
{
var expando = new ExpandoObject();
var expandoDictionary = (IDictionary<string, object>) expando;
foreach (var key in keys)
{
var value = valueSelector(element, key);
expandoDictionary[key] = value;
}
expandos.Add(expando);
}
return expandos.ToReportSource();
}
}
帮助程序类
public interface IExportColumn<TModel> where TModel : class
{
string Header { get; }
Func<TModel, Object> Display { get; }
}
public class ExportColumn<TModel, TProperty> : IExportColumn<TModel> where TModel : class
{
private readonly string _header;
private readonly Expression<Func<TModel, TProperty>> _display;
public string Header { get { return _header; } }
public Func<TModel, Object> Display { get { return model => _display.Compile().Invoke(model); } }
/// <summary>
/// Initializes a new instance of the <see cref="T:System.Object"/> class.
/// </summary>
public ExportColumn(string header, Expression<Func<TModel, TProperty>> display)
{
_header = header;
_display = display; ;
}
/// <summary>
/// Returns a string that represents the current object.
/// </summary>
/// <returns>
/// A string that represents the current object.
/// </returns>
public override string ToString()
{
return string.Format("Header: {0}, Display: {1}", _header, _display);
}
}
<强>用法强>
var report = probing.Measurements.Export()
.Column(MeasurementResource.Depth, m => m.Depth)
.Column(MeasurementResource.DepthBelowWater, m => m.DepthBelowWater)
.Column(MeasurementResource.ResistancePoint, m => m.ResistancePoint)
.Column(MeasurementResource.FrictionLateral, m => m.FrictionLateral)
.Column(MeasurementResource.FrictionLocal, m => m.FrictionLocal)
.Column(MeasurementResource.FrictionTotal, m => m.FrictionTotal)
.Column(MeasurementResource.Inclination, m => m.Inclination)
.Column(MeasurementResource.PoreWaterPressure, m => m.PoreWaterPressure)
.Column(MeasurementResource.Speed, m => m.Speed)
.Column(MeasurementResource.CalcAlpha, m => m.CalcAlpha)
.Column(MeasurementResource.CalcGammaDry, m => m.CalcGammaDry)
.Column(MeasurementResource.CalcGammaWet, m => m.CalcGammaWet)
.Column(MeasurementResource.GrainTension, m => m.GrainTension)
.Column(MeasurementResource.CompressionCoefficient, m => m.CompressionCoefficient)
.ToReport(null, new ExcelReportWriter());
var stream = new MemoryStream();
writer.WriteReport(report, stream);
stream.Seek(0, SeekOrigin.Begin);
return File(stream, "application/vnd.ms-excel", string.Format(@"{0}-{1}.xlsx", probing.Project.ProjectNumber, probing.ProbingNumber));