Excel Interop Open/ Восстановление HResult исключение
Что я делаю: заполняю и форматирую файл Excel, используя смесь Interop и ClosedXML.
Сначала файл заполняется через Interop, затем сохраняется, закрывается, затем я форматирую RichText ячеек, используя ClosedXML.
К сожалению, это форматирование заставляет Excel рассматривать мой файл как "поврежденный" и нуждается в его восстановлении. Это соответствующая часть:
var workbook = new XLWorkbook(xlsPath);
var sheet = workbook.Worksheet("Error Log");
for (var rownum = 2; rownum <= 10000; rownum++)
{
var oldcell = sheet.Cell("C" + rownum);
var newcell = sheet.Cell("D" + rownum);
var oldtext = oldcell.GetFormattedString();
if(string.IsNullOrEmpty(oldtext.Trim()))
break;
XlHelper.ColorCellText(oldcell, "del", System.Drawing.Color.Red);
XlHelper.ColorCellText(newcell, "add", System.Drawing.Color.Green);
}
workbook.Save();
И метод окраски:
public static void ColorCellText(IXLCell cel, string tagName, System.Drawing.Color col)
{
var rex = new Regex("\\<g\\sid\\=[\\sa-z0-9\\.\\:\\=\\\"]+?\\>");
var txt = cel.GetFormattedString();
var mc = rex.Matches(txt);
var xlcol = XLColor.FromColor(col);
foreach (Match m in mc)
{
txt = txt.Replace(m.Value, "");
txt = txt.Replace("</g>", "");
}
var startTag = string.Format("[{0}]", tagName);
var endTag = string.Format("[/{0}]", tagName);
var crt = cel.RichText;
crt.ClearText();
while (txt.Contains(startTag) || txt.Contains(endTag))
{
var pos1 = txt.IndexOf(startTag);
if (pos1 == -1)
pos1 = 0;
var pos2 = txt.IndexOf(endTag);
if (pos2 == -1)
pos2 = txt.Length - 1;
var txtLen = pos2 - pos1 - 5;
crt.AddText(txt.Substring(0, pos1));
crt.AddText(txt.Substring(pos1 + 5, txtLen)).SetFontColor(xlcol);
txt = txt.Substring(pos2 + 6);
}
if (!string.IsNullOrEmpty(txt))
crt.AddText(txt);
}
Ошибка в файле myfile.xlsx
Были выполнены следующие ремонтные работы: _x000d__x000a__x000d__x000a_
Восстановленные записи:
строковые свойства /xl/sharedStrings.xml-Part (строки)
Я прошел через все xmls в поисках подсказок. На соответствующем листе, в сравнительном представлении Productivity Tool, некоторые блоки отображаются как вставленные в восстановленный файл и удаленные в поврежденном, хотя ничего существенного не изменилось, за исключением одного: атрибута стиля этой ячейки. Вот пример:
<x:c r="AA2" s="59">
<x:f>
(IFERROR(VLOOKUP(G2,Legende!$A$42:$B$45,2,FALSE),0))
</x:f>
</x:c>
Я проверил style.xml для стиля 59, но его нет. В восстановленном файле этот стиль был изменен на 14, который в моем файле styles.xml указан как числовой формат.
К сожалению, глобальный поиск / замена этих недопустимых индексов стилей не решил проблему. Видя, что здесь происходит с поврежденными индексами, переименованными xmls, недопустимыми именованными диапазонами и т. Д., Я выбрал другой путь: вообще не использовать взаимодействие, возможно, повреждение было вызвано Excel в первую очередь, а раскраска была только последней. солома.
Используя только ClosedXml:
Вот это да. Просто вау. Это делает это еще хуже. Я прокомментировал часть раскраски, поскольку без этого Interop создавал читаемый файл без ошибок, поэтому я ожидаю и от ClosedXml.
Вот как я открываю файл и обращаюсь к рабочему листу с помощью ClosedXml:
var wb= new XLWorkbook(xlsPath);
var errors = wb.Worksheet("Error Log");
Вот как я записываю значения в файл:
errors.Cell(zeile, 1).SetValue(fname);
Zeile - простой int counter
Затем я осмелюсь установить ширину столбца:
errors.Column(2).Width = 50;
errors.Column(3).Width = 50;
errors.Column(4).Width = 50;
А также установка некоторых значений на другом листе точно таким же образом перед сохранением с проверкой.
wb.Save(true);
wb.Dispose();
И вот: проверка выдает ошибки:
Атрибут "имя" должен иметь уникальное значение. Его текущее значение "Легенде дублирует с другими.
Атрибут 'sheetId' должен иметь уникальное значение. Его текущее значение "4" дублируется с другими.
Еще пара ошибок, таких как атрибут top с недопустимым значением '11.425781'.
Excel не может открыть файл напрямую, должен восстановить его. Мой лист "Legende" теперь пуст и первый лист вместо третьего, и я получаю дополнительный четвертый лист "Restored_Table1", который содержит мое оригинальное содержание "Legende".
Что, черт возьми, происходит с этим файлом?
Новая попытка: заново создать шаблон Excel с нуля - в LibreOffice.
Теперь я думаю, что проблема полностью вводит в заблуждение. Если я использую только что созданный файл из LibreOffice, проверка вызывает исключение System.OutOfMemory из-за слишком большого количества ошибок проверки. Открытие в Excel требует ремонта, дает дополнительный лист и пр.
Создание в LibreOffice, затем открытие в Excel, сохранение, а затем использование этого файла в качестве шаблона дает гораздо лучший результат, хотя еще и не идеальный. Так как я копировал детали из старого файла Excel в LO при создании нового файла, я предполагаю, что скопирован некоторый поврежденный остаток.
Я не могу избавиться от ощущения, что это все-таки сам файл и не имеет ничего общего с тем, как я его редактирую!
Выложу обнову завтра.
1 ответ
ХОРОШО. Наполните это. Я создал совершенно новый файл с помощью LibreOffice, стараясь не копировать что-либо из исходного файла, и отказался от Interop в пользу ClosedXml.
=> Это привело к повреждению файла, в котором мой первый лист был очищен, а его содержимое перемещено в "Restored_Table1".
После того, как я открыл свой новый шаблон в Excel через Open/Repair и сохранил его, полученный, неокрашенный файл НЕ был поврежден.
=> Раскраска производит "оригинальное" искажение, все листы не повреждены.
ClosedXml, кажется, немного медленнее, чем Interop, но на данный момент мне было все равно. Я предполагаю, что нам придется жить с "испорченным" сообщением и просто продолжать его.
Я ненавижу xlsx.