0

我所做的:使用 Interop 和 ClosedXML 的混合填充和格式化 Excel 文件。

首先,通过 Interop 填充文件,然后保存、关闭,然后我使用 ClosedXML 格式化单元格的 RichText。

不幸的是,这种格式会导致 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 寻找线索。在受影响的工作表中,在生产力工具的比较视图中,一些块显示为插入到修复的文件中并在损坏的文件中删除,尽管似乎没有任何重大变化 - 除了一件事:该单元格的样式属性。这里有一个例子:

   <x:c r="AA2" s="59">
    <x:f>
     (IFERROR(VLOOKUP(G2,Legende!$A$42:$B$45,2,FALSE),0))
    </x:f>
   </x:c>

我检查了styles.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 计数器。

然后我敢于设置列宽:

errors.Column(2).Width = 50;
errors.Column(3).Width = 50;
errors.Column(4).Width = 50;

以及在保存验证之前以完全相同的方式在另一张表中设置一些值。

wb.Save(true);
wb.Dispose();

瞧:验证抛出错误:

属性“名称”应具有唯一值。它的当前值 'Legende 与其他人重复。
属性“sheetId”应该具有唯一值。它的当前值“4”与其他值重复。

还有一些错误,例如属性“top”具有无效值“11.425781”。

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

这个文件到底是怎么回事??

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

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

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

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

明天会发布更新。

4

1 回答 1

1

好的。塞这个。我使用 LibreOffice 创建了一个全新的文件,确保不会从原始文件中复制任何内容,并且我放弃了 Interop,转而使用 ClosedXml。

=>这产生了一个损坏的文件,其中我的第一张工作表被清除,其内容移动到“Restored_Table1”。

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

=>着色它会产生“原始”损坏,所有纸张都完好无损。

ClosedXml 似乎比 Interop 稍慢,但在这一点上我不在乎。我想我们将不得不忍受“腐败”的信息并继续下去。

我讨厌 xlsx。

于 2016-12-13T11:57:49.383 回答