Нечитаемый контент в файле 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; }
}
Обратите внимание, что все сводные таблицы заполнены правильно, так почему это происходит?
Спасибо: -)
Ответы
Ответ 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());
}