使用EPPlus生成的Excel文件中的内容不可读

时间:2014-01-03 15:11:01

标签: c# .net excel xlsx epplus

当我使用EPPlus库从模板生成Excel文件时,我遇到了一些问题。该文件包含第一个电子表格,其中包含用于在以下表格中填充数据透视表的数据。

当我打开生成的文件时,收到以下错误消息: “Excel在'sampleFromTemplate.xlsx'中找到了不可读的内容。是否要恢复此工作簿的内容?我相信此工作簿的来源,请单击是。”

我显然单击是,然后获取对文件进行的修复的摘要,以及指向包含此内容的xml格式化日志文件的链接:

<?xml version="1.0" encoding="UTF-8" standalone="true"?>
<recoveryLog xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main">
    <logFileName>error095080_01.xml</logFileName>
    <summary>Errors were detected in file  'C:\TEMP\sampleFromTemplate.xlsx'</summary>
    <repairedRecords summary="Following is a list of repairs:">
        <repairedRecord>Repaired Records: Table from /xl/tables/table1.xml part (Table)</repairedRecord>
    </repairedRecords>
</recoveryLog>

这显然是由我在代码中定义的命名范围(“Table1”)引起的,用于指示要用于数据透视表的数据。模板中已经有一个名为“Table1”的“表名”,但我似乎无法通过ExcelPackage.Worksheet.Names集合访问它。作为EPPlus的新手,并没有非常熟悉Excel,我不明白我做错了什么。这是我生成文件的代码:

private string GenerateFromTemplate(string fileName, string templateName, DataTable tab)
{
    FileInfo newFile = new FileInfo(string.Format("C:\\MyPath\\{0}.xlsx", fileName));
    FileInfo templateFile = new FileInfo(string.Format("C:\\MyPath\\{0}.xlsx", templateName));

    try
    {
        using (ExcelPackage pkg = new ExcelPackage(newFile, templateFile))
        {
            ExcelWorksheet sheet = pkg.Workbook.Worksheets["MyDataSheet"];
            ExcelRange range = sheet.Cells[string.Format("A1:U{0}", dt.Rows.Count)];
            pkg.Workbook.Names.Add("Table1", range as ExcelRangeBase);

            int sheetRowIndex = 2;

            foreach (DataRow row in this.dt.Rows)
            {
                sheet.Cells[sheetRowIndex, 1].Value = row["Row1"];
                sheet.Cells[sheetRowIndex, 2].Value = row["Row2"];
                [...]
                sheet.Cells[sheetRowIndex, 21].Value = row["Row21"];

                sheetRowIndex++;
            }

            pkg.Save();
            return newFile.FullName;
        }
    }
    catch (IOException ex) { return ex.Message; }
}

请注意,无论如何都会正确填充数据透视表,为什么会发生这种情况呢?

谢谢: - )

7 个答案:

答案 0 :(得分:28)

我自己遇到了这个问题并修复了它,如果其他人碰到了我的解决方案:

这是使用asp.net,原因显而易见,它不适用。

我的问题不在于表格范围,Epplus生成的文件很好,而是服务器响应将页面响应附加到excel文件,显然使文件无效。在发送文件后立即结束服务器响应修复了我的问题,其中包括以下内容:

Response.BinaryWrite(pck.GetAsByteArray());  // send the file
Response.End();

答案 1 :(得分:8)

问题没有解决,但现在我知道原因。这个“Table1”的东西不是命名范围而是一个表,我可以通过工作表的“Tables”集合访问它。

现在,问题是EPPlus中的Tables集合和Table对象都是只读的,所以我不能从我的代码中定义表的维度,也不能删除它或添加新的以满足我的需要。 EPPlus的作者已经提到它可能有一天会被实现(herehere)总线,因为消息已经快3年了,我想没有希望看到这种情况发生......

无论如何,我希望这会帮助任何人遇到同样的问题。

[编辑]我终于想出了一种绕过问题的方法:ExcelTable对象有一个名为“TableXml”的可写属性,它包含表的xml定义 - 当然 - 它的范围。以下是我的案例内容:

<?xml version="1.0" encoding="UTF-8" standalone="true"?>
    <table dataCellStyle="Normal 2" headerRowCellStyle="Normal 2" headerRowDxfId="70" totalsRowShown="0" insertRow="1" ref="A1:U2" displayName="Table1" name="Table1" id="1" xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main">
        <autoFilter ref="A1:U2"/>
        <tableColumns count="21">
            <tableColumn dataCellStyle="Normal 2" name="Activity" id="1"/>
            <tableColumn dataCellStyle="Normal 2" name="Category" id="21"/>
            [...]
            <tableColumn dataCellStyle="Normal 2" name="Closed Year" id="20" dataDxfId="62"/>
        </tableColumns>
        <tableStyleInfo name="TableStyleMedium9" showColumnStripes="0" showRowStripes="1" showLastColumn="0" showFirstColumn="0"/>
</table>

我们感兴趣的是“table”和“autoFilter”节点中的“ref”属性,因为更改它们的值允许重新定义表格的范围。

我继续这样做:

XmlDocument tabXml = sheet.Tables(0).TableXml;
XmlNode tableNode = tabXml.ChildNodes[1];
tableNode.Attributes["ref"].Value = string.Format("A1:U{0}", dt.Rows.Count + 1);
XmlNode autoFilterNode = tableNode.ChildNodes[0];
autoFilterNode.Attributes["ref"].Value = string.Format("A1:U{0}", dt.Rows.Count + 1);

现在我的Excel文件正确生成,“Table1”符合我的数据的实际范围!

答案 2 :(得分:5)

我花了大约4个小时来解决这个问题,作为我的问题&amp;解决方案不在帖子中,我是为任何未来的访问者写的,

我的问题是由excel表中的重复列引起的。向一列添加空格后,问题就解决了。 有趣的是,当我通过MS excel生成数据透视表时,错误永远不会出现,只有当我使用epplus在excel文件中生成数据透视表时才出现。让bug更难找到

答案 3 :(得分:3)

当我遇到一个在每行后添加额外列分隔符的错误时,我遇到了这个问题:

head1{tab}head2{tab}
col11{tab}col21{tab}
col22{tab}col22{tab}

最后一列之后的额外标签以同样的方式破坏了生成的Excel电子表格,并删除它修复了问题。注意我正在使用LoadFromText从文本数据中一次加载整个工作表。这可能不是OP的问题,但未来的搜索者可能会发现这有用。

答案 4 :(得分:2)

在编辑工作簿时遇到此问题时,在其标题中使用具有特殊格式的表(Windings字体用于显示特殊符号)。不得不删除格式以修复邮件。

答案 5 :(得分:0)

不同的设置(返回流),但同样的问题(损坏的表记录)。就我而言,问题是对ExcelPackage.Save()的显式调用:

using (var excelPackage = new ExcelPackage())
{
    /* ... removed code for clarity */

    // caused the stream to contain the file 2 times, 
    // save is already called by GetAsByteArray()                
    //excelPackage.Save(); 

    return new MemoryStream(excelPackage.GetAsByteArray());
}

答案 6 :(得分:0)

当我使用C#和epplus从表中删除所有行时,我的问题解决了。