- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在使用jqgrid(标准)和 EF 4 + MVC3。我想实现Excel导出。您会建议我哪种方法?
要生成 Excel,我想使用 this library由 Stephen Walther 博士编写,它具有三种类型的输出,并且也允许定义 header 。如果您认为它对我的目的有效,请告诉我。
我问这个问题是因为我仍在尝试实现Excel导出并且我发现了几种技术。有些人建议进行 csv 导出,其他人则表明它应该返回 JSON 输出,我不清楚 jqgrid 的免费版本中是否存在此功能。无论如何,我想将数据传递给 Walther 的对象。
关于jqgrid代码,我找到了this interesting answer作者:Oleg,但我不知道是否可以满足我的需求。
不幸的是,到目前为止我只找到了部分使用 EF MVC 导出 Excel 的解决方案,但没有解决方案或完整的示例...
关于MVC逻辑,我要实现和开发this code正如@Tommy 的善意建议。
如果问题可能很愚蠢,请抱歉,我只是一个(爱好者)初学者。
感谢您的宝贵帮助!致以诚挚的问候
最佳答案
正如我之前所写(例如,参见 here 和 here),将网格数据导出到 XML 的最佳方法是使用 Open XML SDK 2.0 .
post Stephen Walther 博士的演示了如何创建可由 Excel 读取的 HTML 文件。它不是 Excel 文件,仍必须转换为 Excel 格式。 CSV 的使用还有更多问题。根据源表中的内容,自动转换为 Excel 数据类型可能是绝对错误的。在我为客户开发的一个项目中,网格包含有关软件产品的信息:产品名称、版本等。软件版本有时看起来像日期(例如 1.3.1963),并且此类单元格将被错误转换(在德语中,使用“.”作为日期中的分隔符)。结果,人们遇到了非常棘手的问题。使用内部含有逗号的文本的 CSV 也经常会被错误导入。即使引用带有逗号 (,
) 的单元格并转义具有配额的文本,导入仍然是错误的,尤其是在第一列中。我不想在这里解释所有尝试和错误的全部历史,但毕竟我决定放弃使用 CSV 和 HTML,并开始使用 Open XML SDK 2.0,它允许创建真正的 Excel 文件 扩展名为 XLSX。我觉得这种方式很完美,因为不需要任何办公室组件安装在服务器上,无需额外许可证。
唯一的限制是应该能够使用DocumentFormat.OpenXml.dll
,因此您的服务器程序应该在任何Windows 操作系统上运行。众所周知,XLSX 文件是 ZIP 文件,其中包含一些 XML 文件。如果您仍然不知道,我建议您将 XLSX 文件重命名为 ZIP 文件并解压。 Open XML SDK 2.0 是一个可以像处理 XML 文件一样处理 XLSX 文件的库。因此不需要额外的 Office 组件。
可以找到很多有关如何使用 Open XML SDK 2.0 的信息(请参阅 here 、 here 和 here )。人们可以直接在 MSDN 上找到许多有用的代码示例(请参阅 here )。然而,Open XML SDK 2.0 的实际使用并不那么容易,至少在第一次时是这样。因此,我根据自己使用的部分代码创建了一个演示。
您可以从 here 下载演示项目。该演示是 the answer 中演示的扩展。和 this one .
为了导出数据,我使用 DataForExcel
帮助程序类。它具有以下形式的构造函数
DataForExcel(string[] headers, DataType[] colunmTypes, List<string[]> data,
string sheetName)
或者以稍微简化的形式
DataForExcel(string[] headers, List<string[]> data, string sheetName)
也是唯一的公共(public)方法
CreateXlsxAndFillData(Stream stream)
该类创建Excel文件的用法如下
var excelData = new DataForExcel (
// column Header
new[]{"Col1", "Col2", "Col3"},
new[]{DataForExcel.DataType.String, DataForExcel.DataType.Integer,
DataForExcel.DataType.String},
new List<string[]> {
new[] {"a", "1", "c1"},
new[] {"a", "2", "c2"}
},
"Test Grid");
Stream stream = new FileStream ("Test.xlsx", FileMode.Create);
excelData.CreateXlsxAndFillData (stream);
stream.Close();
ASP.NET MVC 演示中的用法如下
static readonly string[] HeadersQuestions = {
"Id", "Votes", "Title"
};
static readonly DataForExcel.DataType[] ColunmTypesQuestions = {
DataForExcel.DataType.Integer,
DataForExcel.DataType.Integer,
DataForExcel.DataType.String
};
public ActionResult ExportAllQuestionsToExcel () {
var context = new HaackOverflowEntities ();
var questions = context.Questions;
questions.MergeOption = MergeOption.NoTracking; // we don't want to update the data
// to be able to use ToString() below which is NOT exist in the LINQ to Entity
// we should include in query only the properies which we will use below
var query = questions.ToList ();
if (query.Count == 0)
return new EmptyResult ();
var data = new List<string[]> (query.Count);
data.AddRange (query.Select (item => new[] {
item.Id.ToString(CultureInfo.InvariantCulture),
item.Votes.ToString(CultureInfo.InvariantCulture),
item.Title
}));
return new ExcelResult (HeadersQuestions, ColunmTypesQuestions, data,
"Questions.xlsx", "Questions");
}
其中 ExcelResult
定义为
public class ExcelResult : ActionResult {
private readonly DataForExcel _data;
private readonly string _fileName;
public ExcelResult (string[] headers, List<string[]> data, string fileName, string sheetName) {
_data = new DataForExcel (headers, data, sheetName);
_fileName = fileName;
}
public ExcelResult (string[] headers, DataForExcel.DataType[] colunmTypes, List<string[]> data, string fileName, string sheetName) {
_data = new DataForExcel (headers, colunmTypes, data, sheetName);
_fileName = fileName;
}
public override void ExecuteResult (ControllerContext context) {
var response = context.HttpContext.Response;
response.ClearContent();
response.ClearHeaders();
response.Cache.SetMaxAge (new TimeSpan (0));
using (var stream = new MemoryStream()) {
_data.CreateXlsxAndFillData (stream);
//Return it to the client - strFile has been updated, so return it.
response.AddHeader ("content-disposition", "attachment; filename=" + _fileName);
// see http://filext.com/faq/office_mime_types.php
response.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
response.ContentEncoding = Encoding.UTF8;
stream.WriteTo (response.OutputStream);
}
response.Flush();
response.Close();
}
}
为了使代码完整,我必须包含类 DataForExcel
的代码:
public class DataForExcel {
public enum DataType {
String,
Integer
}
private readonly string[] _headers;
private readonly DataType[] _colunmTypes;
private readonly List<string[]> _data;
private readonly string _sheetName = "Grid1";
private readonly SortedSet<string> _os = new SortedSet<string> ();
private string[] _sharedStrings;
private static string ConvertIntToColumnHeader(int index) {
var sb = new StringBuilder ();
while (index > 0) {
if (index <= 'Z' - 'A') // index=0 -> 'A', 25 -> 'Z'
break;
sb.Append (ConvertIntToColumnHeader (index / ('Z' - 'A' + 1) - 1));
index = index % ('Z' - 'A' + 1);
}
sb.Append ((char)('A' + index));
return sb.ToString ();
}
private static Row CreateRow(UInt32 index, IList<string> data) {
var r = new Row { RowIndex = index };
for (var i = 0; i < data.Count; i++)
r.Append (new OpenXmlElement[] { CreateTextCell (ConvertIntToColumnHeader (i), index, data[i]) });
return r;
}
private Row CreateRowWithSharedStrings(UInt32 index, IList<string> data) {
var r = new Row { RowIndex = index };
for (var i = 0; i < data.Count; i++)
r.Append (new OpenXmlElement[] { CreateSharedTextCell (ConvertIntToColumnHeader (i), index, data[i]) });
return r;
}
private Row CreateRowWithSharedStrings(UInt32 index, IList<string> data, IList<DataType> colunmTypes) {
var r = new Row { RowIndex = index };
for (var i = 0; i < data.Count; i++)
if (colunmTypes != null && i < colunmTypes.Count && colunmTypes[i] == DataType.Integer)
r.Append (new OpenXmlElement[] { CreateNumberCell (ConvertIntToColumnHeader (i), index, data[i]) });
else
r.Append (new OpenXmlElement[] { CreateSharedTextCell (ConvertIntToColumnHeader (i), index, data[i]) });
return r;
}
private static Cell CreateTextCell(string header, UInt32 index, string text) {
// create Cell with InlineString as a child, which has Text as a child
return new Cell (new InlineString (new Text { Text = text })) {
// Cell properties
DataType = CellValues.InlineString,
CellReference = header + index
};
}
private Cell CreateSharedTextCell(string header, UInt32 index, string text) {
for (var i=0; i<_sharedStrings.Length; i++) {
if (String.Compare (_sharedStrings[i], text, StringComparison.Ordinal) == 0) {
return new Cell (new CellValue { Text = i.ToString (CultureInfo.InvariantCulture) }) {
// Cell properties
DataType = CellValues.SharedString,
CellReference = header + index
};
}
}
// create Cell with InlineString as a child, which has Text as a child
throw new InstanceNotFoundException();
}
private static Cell CreateNumberCell(string header, UInt32 index, string numberAsString) {
// create Cell with CellValue as a child, which has Text as a child
return new Cell (new CellValue { Text = numberAsString }) {
// Cell properties
CellReference = header + index
};
}
private void FillSharedStringTable(IEnumerable<string> data) {
foreach (var item in data)
_os.Add (item);
}
private void FillSharedStringTable(IList<string> data, IList<DataType> colunmTypes) {
for (var i = 0; i < data.Count; i++)
if (colunmTypes == null || i >= colunmTypes.Count || colunmTypes[i] == DataType.String)
_os.Add (data[i]);
}
public DataForExcel(string[] headers, List<string[]> data, string sheetName) {
_headers = headers;
_data = data;
_sheetName = sheetName;
}
public DataForExcel(string[] headers, DataType[] colunmTypes, List<string[]> data, string sheetName) {
_headers = headers;
_colunmTypes = colunmTypes;
_data = data;
_sheetName = sheetName;
}
private void FillSpreadsheetDocument(SpreadsheetDocument spreadsheetDocument) {
// create and fill SheetData
var sheetData = new SheetData ();
// first row is the header
sheetData.AppendChild (CreateRow (1, _headers));
//const UInt32 iAutoFilter = 2;
// skip next row (number 2) for the AutoFilter
//var i = iAutoFilter + 1;
UInt32 i = 2;
// first of all collect all different strings in OrderedSet<string> _os
foreach (var dataRow in _data)
if (_colunmTypes != null)
FillSharedStringTable (dataRow, _colunmTypes);
else
FillSharedStringTable (dataRow);
_sharedStrings = _os.ToArray ();
foreach (var dataRow in _data)
sheetData.AppendChild (_colunmTypes != null
? CreateRowWithSharedStrings (i++, dataRow, _colunmTypes)
: CreateRowWithSharedStrings (i++, dataRow));
var sst = new SharedStringTable ();
foreach (var text in _os)
sst.AppendChild (new SharedStringItem (new Text (text)));
// add empty workbook and worksheet to the SpreadsheetDocument
var workbookPart = spreadsheetDocument.AddWorkbookPart ();
var worksheetPart = workbookPart.AddNewPart<WorksheetPart> ();
var shareStringPart = workbookPart.AddNewPart<SharedStringTablePart> ();
shareStringPart.SharedStringTable = sst;
shareStringPart.SharedStringTable.Save ();
// add sheet data to Worksheet
worksheetPart.Worksheet = new Worksheet (sheetData);
worksheetPart.Worksheet.Save ();
// fill workbook with the Worksheet
spreadsheetDocument.WorkbookPart.Workbook = new Workbook (
new FileVersion { ApplicationName = "Microsoft Office Excel" },
new Sheets (
new Sheet {
Name = _sheetName,
SheetId = (UInt32Value)1U,
// generate the id for sheet
Id = workbookPart.GetIdOfPart (worksheetPart)
}
)
);
spreadsheetDocument.WorkbookPart.Workbook.Save ();
spreadsheetDocument.Close ();
}
public void CreateXlsxAndFillData(Stream stream) {
// Create workbook document
using (var spreadsheetDocument = SpreadsheetDocument.Create (stream, SpreadsheetDocumentType.Workbook)) {
FillSpreadsheetDocument (spreadsheetDocument);
}
}
}
以上代码直接创建新的XLSX文件。您可以扩展代码以支持更多数据类型,例如我在代码中使用的 String
和 Integer
。
在更专业的应用程序版本中,您可以创建一些 XLSX 模板来导出不同的表。在代码中,您可以将数据放置在单元格中,因此修改电子表格而不是创建。这样您就可以创建完美格式的 XLSX 文件。 MSDN 中的示例(请参阅 here )将帮助您在需要时实现该方法。
更新:The answer包含更新的代码,允许生成具有更多单元格格式的 Excel 文档。
关于asp.net-mvc - jqgrid + EF + MVC : How to export in excel? 你建议哪种方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9339792/
我是一名优秀的程序员,十分优秀!