Excel Open XML错误:创建简单示例时“找到不可读的内容”

时间:2011-05-16 18:20:05

标签: c# asp.net excel openxml openxml-sdk

当我尝试打开由以下代码创建的文档时,我收到了模糊的“excel发现不可读的内容”错误:

public void GenerateWorkbookFromDB()
{
    //Make a copy of the template file
    File.Copy(HttpContext.Current.Server.MapPath("ReportTemplate/test.xlsx"), HttpContext.Current.Server.MapPath("Reports/test.xlsx"), true);

    //Open up the copied template workbook
    using (SpreadsheetDocument myWorkbook = SpreadsheetDocument.Open(HttpContext.Current.Server.MapPath("Reports/test.xlsx"), true))
    {
        WorkbookPart workbookPart = myWorkbook.WorkbookPart;
        WorksheetPart worksheetPart = workbookPart.WorksheetParts.First();
        string origninalSheetId = workbookPart.GetIdOfPart(worksheetPart);

        WorksheetPart replacementPart = workbookPart.AddNewPart<WorksheetPart>();
        string replacementPartId = workbookPart.GetIdOfPart(replacementPart);

        OpenXmlReader reader = OpenXmlReader.Create(worksheetPart);
        OpenXmlWriter writer = OpenXmlWriter.Create(replacementPart);

        Row r = new Row();
        Cell c = new Cell();
        CellValue v = new CellValue();
        v.Text = "test";
        c.Append(v);

        while (reader.Read())
        {
            if (reader.ElementType == typeof(SheetData))
            {
                if (reader.IsEndElement)
                    continue;
                writer.WriteStartElement(new SheetData());

                for (int row = 0; row < 20; row++)
                {
                    writer.WriteStartElement(r);

                    for (int col = 0; col < 4; col++)
                    {
                        writer.WriteElement(c);
                    }

                    writer.WriteEndElement();
                }

                writer.WriteEndElement();
            }
            else
            {
                if (reader.IsStartElement)
                    writer.WriteStartElement(reader);
                else if (reader.IsEndElement)
                    writer.WriteEndElement();
            }
        }
        reader.Close();
        writer.Close();

        try
        {
            Sheet sheet = workbookPart.Workbook.Descendants<Sheet>().Where(s => s.Id.Value.Equals(origninalSheetId)).First();
            sheet.Id.Value = replacementPartId;
            workbookPart.DeletePart(worksheetPart);
        }
        catch (Exception ex) { }
    }
}

非常感谢任何帮助或建议! :d

7 个答案:

答案 0 :(得分:11)

我实际上找到了一种通过改变将文本输入单元格本身的方式来修复错误的方法。请注意下面的代码中我注释了2行以及我用它们替换它们的内容。

public void GenerateWorkbookFromDB()
{
    //Make a copy of the template file
    File.Copy(HttpContext.Current.Server.MapPath("ReportTemplate/test.xlsx"), HttpContext.Current.Server.MapPath("Reports/test.xlsx"), true);

    //Open up the copied template workbook
    using (SpreadsheetDocument myWorkbook = SpreadsheetDocument.Open(HttpContext.Current.Server.MapPath("Reports/test.xlsx"), true))
    {
        WorkbookPart workbookPart = myWorkbook.WorkbookPart;
        WorksheetPart worksheetPart = workbookPart.WorksheetParts.First();
        string origninalSheetId = workbookPart.GetIdOfPart(worksheetPart);

        WorksheetPart replacementPart = workbookPart.AddNewPart<WorksheetPart>();
        string replacementPartId = workbookPart.GetIdOfPart(replacementPart);

        OpenXmlReader reader = OpenXmlReader.Create(worksheetPart);
        OpenXmlWriter writer = OpenXmlWriter.Create(replacementPart);

        Row r = new Row();
        Cell c = new Cell();
        string txt = "test";
        c.CellValue = new CellValue(txt.ToString());
        c.DataType = new EnumValue<CellValues>(CellValues.String);
        //v.Text = "test";
        //c.Append(v);

        while (reader.Read())
        {
            if (reader.ElementType == typeof(SheetData))
            {
                if (reader.IsEndElement)
                    continue;
                writer.WriteStartElement(new SheetData());

                for (int row = 0; row < 20; row++)
                {
                    writer.WriteStartElement(r);

                    for (int col = 0; col < 4; col++)
                    {
                        writer.WriteElement(c);
                    }

                    writer.WriteEndElement();
                }

                writer.WriteEndElement();
            }
            else
            {
                if (reader.IsStartElement)
                    writer.WriteStartElement(reader);
                else if (reader.IsEndElement)
                    writer.WriteEndElement();
            }
        }
        reader.Close();
        writer.Close();

        try
        {
            Sheet sheet = workbookPart.Workbook.Descendants<Sheet>().Where(s => s.Id.Value.Equals(origninalSheetId)).First();
            sheet.Id.Value = replacementPartId;
            workbookPart.DeletePart(worksheetPart);
        }
        catch (Exception ex) { }
    }
}

我希望这可以帮助其他可能遇到同样问题的人。

感谢那些试图回答的人; - )

答案 1 :(得分:5)

我希望它对某些人有用。

我收到了相同的错误消息,在我的情况下,原因是工作表名称过长。

Excel将其截断为31个字符。因此,一旦我将代码中指定的工作表名称限制为31个字符,问题就解决了。

答案 2 :(得分:3)

我发现您需要确保在将Cell对象添加到行集合时,将它们按正确的顺序放置。它们必须按照它们在电子表格中显示的顺序显示。例如A2,B2,C2 ...... Z2,AA2,AB2。请注意,如果您尝试比较列的值以放置它们,它们将在A2和B2之间使用AA2进行排序,这将在您尝试打开工作表时导致错误。

答案 3 :(得分:1)

我通过在Cell上设置正确的类型来纠正它。例如,在我的例子中,我有两种类型的值:Numerics和Strings。

 public static void WriteValueOnCell(Cell cell, object value)
    {
        var sValue = value = x.ToString();
        var isValueNumeric = value.GetType().IsNumeric();
        cell.DataType = (isValueNumeric)? CellValues.Number : CellValues.String;
        cell.CellValue = new CellValue(sValue);
    }
    //This example uses this Helper. It informs if an object type is Numeric ;-)
    public static class TypeHelper
    {
        private static readonly HashSet<Type> NumericTypes = new HashSet<Type>
        {
            typeof(int),  typeof(double),  typeof(decimal),
            typeof(long), typeof(short),   typeof(sbyte),
            typeof(byte), typeof(ulong),   typeof(ushort),
            typeof(uint), typeof(float)
        };

        public static bool IsNumeric(this Type myType)
        {
            return NumericTypes.Contains(Nullable.GetUnderlyingType(myType) ?? myType);
        }
    }

答案 4 :(得分:0)

在工作簿中,是否有数据字段中保留的字符?例如'&lt;'还是'&gt;'?我已经看到过XML解析会发生这种情况,所以它可能是一个非法的角色。我不知道你的情况是否允许,但HTTPUtility.HTMLEncode会起作用吗?

答案 5 :(得分:0)

对我有用的是修改web.config文件。

我输入了maxRequestLength和executionTimeout,之后它运行良好!

在System.Web下,输入以下内容:

httpRuntime requestValidationMode="2.0" maxRequestLength="1048576" executionTimeout="600"

试一试,看看它是否有帮助。

答案 6 :(得分:0)

我遇到了这个问题,在使用SDK工具后,我发现实际上并不支持CellValues.Date。如果您尝试将单元格格式化为具有相应的DataType并且您收到此消息,请尝试将日期单元格保留为CellValues.String。