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.

Другие вопросы по тегам