我在ASP.NET应用程序中使用OpenXML。以下是生成它的代码:
MemoryStream ms = new System.IO.MemoryStream();
SpreadsheetDocument spreadsheetDocument = SpreadsheetDocument.Create(ms, SpreadsheetDocumentType.Workbook);
WorkbookPart workbookPart = spreadsheetDocument.AddWorkbookPart();
workbookPart.Workbook = new Workbook();
WorksheetPart worksheetPart = workbookPart.AddNewPart<WorksheetPart>();
worksheetPart.Worksheet = new Worksheet();
UInt32Value rowIndex = 0;
SheetData sheetData = new SheetData();
Row r1 = new Row() { RowIndex = rowIndex };
Cell c1 = new Cell() { DataType = CellValues.String, CellValue=new CellValue("col1") };
Cell c2 = new Cell() { DataType = CellValues.String, CellValue = new CellValue("col2") };
Cell c3 = new Cell() { DataType = CellValues.String, CellValue = new CellValue("col3") };
Cell c4 = new Cell() { DataType = CellValues.String, CellValue = new CellValue("col4") };
r1.Append(new List<Cell>() { c1, c2, c3, c4 });
rowIndex++;
sheetData.Append(r1);
foreach (Rezultat rez in rezultati)
{
Row r2 = new Row() { RowIndex = rowIndex };
Cell c1 = new Cell() { DataType = CellValues.String, CellValue = new CellValue(rez.a) };
Cell c2 = new Cell() { DataType = CellValues.String, CellValue = new CellValue(rez.b) };
Cell c3 = new Cell() { DataType = CellValues.String, CellValue = new CellValue(rez.c) };
Cell prolaz = new Cell() { DataType = CellValues.String };
if (rez.d)
{
prolaz.CellValue = new CellValue("DA");
}
else
{
prolaz.CellValue = new CellValue("NE");
}
r2.Append(new List<Cell>() { c1,c2,c3,c4 });
rowIndex++;
sheetData.Append(r2);
}
worksheetPart.Worksheet.Append(sheetData);
Sheets sheets = new Sheets();
Sheet sheet = new Sheet();
sheet.Name = "first";
sheet.SheetId = 1;
sheet.Id = spreadsheetDocument.WorkbookPart.GetIdOfPart(worksheetPart);
sheets.Append(sheet);
spreadsheetDocument.WorkbookPart.Workbook.AppendChild<Sheets>(sheets);
spreadsheetDocument.WorkbookPart.Workbook.Save();
spreadsheetDocument.Close();
string fileName = "testOpenXml.xlsx";
Response.Clear();
Response.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
Response.AddHeader("content-disposition", string.Format("attachment; filename={0}", fileName));
ms.WriteTo(Response.OutputStream);
ms.Close();
Response.End();
当我下载它并尝试在excel中打开它时,我得到excel在excel中发现不可读的上下文的消息。我想我必须改变我如何生成excel的方式。我试了几个解决方案,有些给出了相同的错误,有些打开了excel,但没有数据。
答案 0 :(得分:1)
如果单元格没有按顺序出现在文件中,您将收到此错误。
如果您在“如何:在电子表格文档中将文本插入单元格(Open XML SDK)”中使用 Microsoft的示例代码,您将看到有一个名为InsertCellInWorksheet的函数。此功能中有缺陷线:
if(string.Compare(cell.CellReference.Value,cellReference,true)&gt; 0)
如果您有超过26列,这将导致它们按如下方式排序:
A1 AA1 AB1 B1 C1 D1 E1 ....
结果是您将看到A列和AA上的数据。列B到Z将丢失,您将看到可怕的“Excel发现不可读的内容”消息。
你需要替换这个字符串。比较一个将AA1置于Z1之后的函数,或者...如果你知道你正在创建所有内容,则将其更改为if(false)。
答案 1 :(得分:0)
您要创建的是InlineString类型的单元格而不是String。
以下是实现您需要的部分内容的片段。希望您可以根据自己的需要进行修改。
SpreadsheetDocument spreadsheetDocument = SpreadsheetDocument.Create(@"test.xlsx", SpreadsheetDocumentType.Workbook);
WorkbookPart workbookPart = spreadsheetDocument.AddWorkbookPart();
WorksheetPart worksheetPart = workbookPart.AddNewPart<WorksheetPart>();
Row row = new Row { RowIndex = 1 };
Cell cell1 = new Cell { DataType = CellValues.InlineString };
InlineString inlineString1 = new InlineString();
Text text = new Text { Text = "col1" };
inlineString1.Append(text);
cell1.Append(inlineString1);
Cell cell2 = new Cell { DataType = CellValues.InlineString };
InlineString inlineString2 = new InlineString();
Text text2 = new Text { Text = "col2" };
inlineString2.Append(text2);
cell2.Append(inlineString2);
row.Append(new List<Cell>() { cell1, cell2 });
SheetData sheetData = new SheetData();
sheetData.Append(row);
Worksheet worksheet = new Worksheet();
worksheet.Append(sheetData);
worksheetPart.Worksheet = worksheet;
worksheetPart.Worksheet.Save();
Sheets sheets = new Sheets();
string relId = workbookPart.GetIdOfPart(worksheetPart);
Sheet sheet = new Sheet { Name = "Sheet1", SheetId = 1, Id = relId };
sheets.Append(sheet);
Workbook workbook = new Workbook();
workbook.Append(sheets);
spreadsheetDocument.WorkbookPart.Workbook = workbook;
spreadsheetDocument.WorkbookPart.Workbook.Save();
spreadsheetDocument.Close();
答案 2 :(得分:0)
我知道这是一个老问题,但我遇到了这个问题并在 MSDN 论坛中找到了解决方案。 SDK 示例包含根本不适用于 Z 列(例如 AA)的代码。 正如这里提到的,问题是使用字母顺序,AA1 会在 B1 之前,依此类推。解决它的方法是使字母 base-26 数字。在同一个 MSDN 论坛中,给出了解决方案。
首先创建一个 base-26 转换器:
//Hexavigesimal (Excel Column Name to Number) - Bijective
private int fromBase26(string colName)
{
colName = colName.ToUpper();
int decimalValue = 0;
for (int i = 0; i < colName.Length; i++)
{
decimalValue *= 26;
decimalValue += (colName[i] - 64);
}
return decimalValue;
}
然后,在方法中更改这一行以在工作表中插入一个单元格:
if (string.Compare(cell.CellReference.Value, cellReference, true) > 0)
致:
if (fromBase26(Regex.Replace(cell.CellReference.Value, @"[\d-]", string.Empty)) > fromBase26(Regex.Replace(cellReference, @"[\d-]", string.Empty)))