Excel Interop打开/修复HResult异常

时间:2016-11-30 10:13:36

标签: c# excel openxml-sdk closedxml epplus-4

我的所作所为:填充&am​​p;使用Interop和ClosedXML混合格式化Excel文件。

首先,文件通过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(strings)的字符串属性

我已经通过所有的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>

我已经检查了样式59的styles.xml,但没有。在已修复的文件中,此样式已更改为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();

瞧瞧:验证会引发错误:

  

属性&#39; name&#39;应该有独特的价值。它目前的价值与其他人重复.Legende   属性&#39; sheetId&#39;应该有独特的价值。它的当前价值&#39; 4&#39;与他人重复。

还有一些错误,例如属性&#39; top&#39;具有无效值&#39; 11.425781&#39;。

Excel无法直接打开文件,必须修复它。我的表&#34; Legende&#34;现在是空的,第一张而不是第三张,我得到另外的第四张&#34; Restored_Table1&#34;其中包含我的原作&#34; Legende&#34;内容。

这个文件到底发生了什么?

新尝试:从头开始重新创建Excel模板 - 在LibreOffice中。

我现在认为这个问题完全是误导。如果我使用LibreOffice中新创建的文件,则由于验证错误太多,验证会导致System.OutOfMemory异常。在Excel中打开需要修复,提供额外的工作表等。

在LibreOffice中创建,然后在Excel中打开,使用该文件作为模板保存, 然后 会产生更好的结果,尽管还不完美。 由于我在创建新文件时将旧Excel文件中的部分复制到LO中,因此我假设已经复制了一些损坏的残余。

我无法摆脱这种文件本身的感觉,与我如何编辑它无关!

明天会发布更新。

1 个答案:

答案 0 :(得分:0)

行。这个东西。 我用LibreOffice创建了一个完全新鲜的文件,确保不要复制原始文件中的任何内容,我抛弃了Interop,转而支持ClosedXml。

=&gt; 这产生了一个损坏的文件,我的第一张纸被清除,其内容移至&#34; Restored_Table1&#34;。

用Excel通过打开/修复打开我的新模板并保存后,生成的无色文件没有损坏。

=&gt; 着色它会产生&#34;原作&#34;腐败,所有床单都完好无损。

ClosedXml似乎比Interop略慢,但此时我并不在乎。我想我们将不得不忍受&#34;腐败&#34;消息,然后继续使用它。

我讨厌xlsx。