Подтвердить что ты не робот

Нечитаемый контент в файле Excel, созданный с помощью EPPlus

У меня возникла небольшая проблема, когда я создаю файл Excel из шаблона, используя библиотеку EPPlus. Файл имеет первую электронную таблицу, которая содержит данные, которые используются для заполнения сводных таблиц в следующих листах.

Когда я открываю сгенерированный файл, появляется следующее сообщение об ошибке: "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>

Это, по-видимому, вызвано именованным диапазоном ( "Таблица1" ), который я определяю в своем коде, чтобы указать данные, которые будут использоваться для сводных таблиц. В шаблоне под названием "Таблица1" уже есть "Имя таблицы", но я не могу получить доступ к нему через коллекцию 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; }
}

Обратите внимание, что все сводные таблицы заполнены правильно, так почему это происходит?

Спасибо: -)

4b9b3361

Ответ 1

Проблема не решена, но теперь я точно знаю, почему. Эта вещь "Table1" не была именованным диапазоном, кроме таблицы, которую я могу получить через коллекцию "Таблицы" рабочего листа.

Теперь проблема заключается в том, что как объекты таблиц, так и таблицы в EPPlus доступны только для чтения, поэтому я не могу определить размер таблицы из своего кода, и я не могу удалить его или добавить новый, чтобы он соответствовал моим потребностям. Автор EPPlus уже упоминал, что он может когда-нибудь быть реализован (здесь и здесь), поскольку сообщениям почти 3 года, я думаю, что мало надежд увидеть, что это произойдет...

В любом случае, я надеюсь, что это поможет любому, кто сталкивается с той же проблемой.

[EDIT] Я, наконец, придумал способ обойти проблему: объект ExcelTable имеет свойство writeable, называемое "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>

Здесь нас интересуют атрибуты "ref" в узлах "table" и "autoFilter", так как изменение их значений позволяет переопределить диапазон нашей таблицы.

Я продолжал:

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

Я просто сам столкнулся с этой проблемой и исправил ее, поставив свое решение здесь, если кто-то еще столкнется с ней:

Это использовало asp.net, по очевидным причинам это не применимо в противном случае.

Моя проблема была не в диапазоне таблиц, Epplus сгенерировал файл просто отлично, а скорее, что ответ сервера добавлял ответ страницы в файл excel, что явно делает файл недействительным. Завершение ответа сервера сразу после отправки файла исправил мою проблему, что-то вроде:

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

Ответ 3

Я потратил около 4 часов на решение этой проблемы. Поскольку мои проблемы и решения не входят в сообщение, я пишу это для любого будущего посетителя,

Моя проблема была вызвана дублирующимися столбцами на листе excel. После добавления места в один столбец проблема решена. Интересная часть: Ошибка никогда не возникала, когда я генерировал сводную таблицу через MS excel, она появилась только тогда, когда я использовал epplus для создания сводной таблицы в файле excel. Сделать ошибку сложнее найти

Ответ 4

Я столкнулся с этим, когда у меня была ошибка, которая добавила дополнительный разделитель столбцов после каждой строки:

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

Эта дополнительная вкладка после последнего столбца разбила полученную таблицу Excel таким же образом, и устранение этой проблемы устранило проблему. Примечание. Я использую LoadFromText для загрузки всего листа за один раз из текстовых данных. Возможно, это не проблема OP, но, возможно, будущие поисковики найдут это полезным.

Ответ 5

Если это проблема при редактировании книг с таблицами, которые имели специальное форматирование (шрифт Windings использовался для отображения специального символа) в своих заголовках. Удалил форматирование, чтобы исправить сообщение.

Ответ 6

Другая настройка (возвращающая поток), но та же проблема (поврежденная запись таблицы). В моем случае проблема заключалась в явном вызове 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());
}