简体   繁体   English

OpenXML:excel 在 .xsls 中发现不可读的内容

[英]OpenXML: excel found unreadable content in .xsls

I'm using OpenXML in my ASP.NET application.我在我的 ASP.NET 应用程序中使用 OpenXML。 Here is the code for generating it:这是生成它的代码:

        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();

When I download it, and try to open it in excel, I got message that excel found unreadable context in excel.I suppose I have to change the way how I geenrate excel.当我下载它并尝试在 excel 中打开它时,我收到消息说 excel 在 excel 中发现了不可读的上下文。我想我必须改变我生成 excel 的方式。 I tried couple of solutions, some gave same error and some open excel, but with no data in it.我尝试了几种解决方案,一些给出了相同的错误,一些打开了 excel,但没有数据。

You will get this error if the cells do not appear in order in the file.如果单元格未按顺序出现在文件中,您将收到此错误。

If you are using Microsoft's Sample Code in "How to: Insert text into a cell in a spreadsheet document (Open XML SDK)" in DevCenter you will see there is a function called InsertCellInWorksheet.如果您在 DevCenter 的“如何:将文本插入电子表格文档 (Open XML SDK) 中的单元格”中使用Microsoft 的示例代码,您将看到有一个名为 InsertCellInWorksheet 的函数。 This function has the defective line in it:此函数中有缺陷行:

if (string.Compare(cell.CellReference.Value, cellReference, true) > 0) if (string.Compare(cell.CellReference.Value, cellReference, true) > 0)

If you have more than 26 columns, this will cause them to be sorted like this:如果您有超过 26 列,这将导致它们按如下方式排序:

A1 AA1 AB1 B1 C1 D1 E1 .... A1 AA1 AB1 B1 C1 D1 E1 ....

The result is you will see the data in column A and from AA on.结果是您将在 A 列中看到从 AA 开始的数据。 Columns B through Z will be missing and you will get the dreaded "Excel found unreadable content" message. B 到 Z 列将丢失,您将收到可怕的“Excel 发现无法读取的内容”消息。

You need to replace this string.Compare with a function that will put AA1 after Z1, or... if you know you are creating everything in order change it to if (false).您需要将此字符串替换为一个将 AA1 放在 Z1 之后的函数,或者...如果您知道您正在创建所有内容以便将其更改为 if (false)。

What you want to create are cells of type InlineString instead of String.您要创建的是 InlineString 类型而不是 String 类型的单元格。

Below is a snippet to achieve part of what you need.以下是实现您需要的部分内容的片段。 Hopefully, you can modify it to your needs.希望您可以根据需要对其进行修改。

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();

I know this is an old question, but I ran into this problem and found the solution in a MSDN forum.我知道这是一个老问题,但我遇到了这个问题并在 MSDN 论坛中找到了解决方案。 The SDK samples contain code that simply does not work with columns beyong Z (like AA for example). SDK 示例包含的代码根本不适用于 Z 以外的列(例如 AA)。 As mentioned here, the problem is that using alphabetial order, AA1 will come before B1 and so on.正如这里提到的,问题是使用字母顺序,AA1 会在 B1 之前,依此类推。 The way to resolve it is to make the letters base-26 numbers.解决它的方法是使字母 base-26 数字。 In the very same MSDN forum, the solution was given.在同一个 MSDN 论坛中,给出了解决方案。

First create a base-26 converter:首先创建一个 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;
}

Then, change this line in the method to insert a cell in the worsheet from:然后,更改方法中的这一行以在工作表中插入一个单元格:

if (string.Compare(cell.CellReference.Value, cellReference, true) > 0)

To:到:

if (fromBase26(Regex.Replace(cell.CellReference.Value, @"[\d-]", string.Empty)) > fromBase26(Regex.Replace(cellReference, @"[\d-]", string.Empty)))

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM