我所做的:使用 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 中,因此我假设复制了一些损坏的残留物。
我无法摆脱这种感觉,毕竟这是文件本身,与我如何编辑它无关!
明天会发布更新。