在Excel中标记超过255个字符的文本部分的颜色

3
我已经为第三方软件编写了一个插件,可以将修订后的文本提取到Excel工作表中,并对Excel中发生更改的部分进行着色。 只要每个文本段(=单元格内容)不超过255个字符,就能正常运行。但是,这种情况偶尔会发生。
为了在Excel中标识更改的部分,我用、resp和标签包围它们来表示删除和添加的文本。然后,我会像这样对这些部分进行着色(并删除周围的标记):
while (((string)cell1.Text).Contains("<del>"))
{
    try
    {
        var pos = ((string) cell1.Text).IndexOf("<del>") + 1;
        var pos2 = ((string) cell1.Text).IndexOf("</del>") + 1;
        var txt = cell1.Characters[pos, (pos2-pos) + 9].Text;

        txt = txt.Replace("<del>", "").Replace("</del>", "");
        cell1.Characters[pos, (pos2-pos) + 9].Text = txt;
        cell1.Characters[pos, txt.Length-3].Font.Color = -16776961;
    }
    catch
    {
            break;
    }
}

我使用Interop是因为我发现它更容易使用,而且我找不到任何关于如何使用OpenXML的好例子。然而,我知道Excel在处理单元格文本时有其限制,所以我愿意听取建议。
是否有一种方法可以使用Interop对包含>255个字符的单元格中的单个单词进行着色?
如果所有方法都失败了,我可能需要创建一个带有表格的Word文档,在那里进行格式设置,然后将其复制/粘贴到Excel中(恶心)。请帮助我避免这种丑陋的情况。
附注:是的,修订摘要需要基于Excel。

尝试使用cell.Value而不是cell.Text。至少在EPPlus中,Text是显示给用户的值,而Value是单元格的内容。因此,如果列宽小于内容,则Text属性包含的值与Value属性不同。 - Magnetron
不行。字符没有Value属性。 - LocEngineer
@Magnetron 抱歉,我有点迟钝。当然我可以使用 cell.Value。但是这并没有什么区别。对于大于255的单元格仍然没有结果。 - LocEngineer
1个回答

0

好的,我现在用OpenXML解决了它。 如果一个单元格包含要着色的文本,我会创建一个到该位置的文本运行,第二个着色的运行包含受影响的文本,第三个回到默认值的运行包含其余部分。

var xlsx = SpreadsheetDocument.Open(xlsPath, true);
var contents = xlsx.WorkbookPart.GetPartsOfType<SharedStringTablePart>().First();
foreach (SharedStringItem si in contents.SharedStringTable.Elements<SharedStringItem>())
{
    if (si.Text != null)
    {
        XlHelper.ColorCellText(si, "del", new DocumentFormat.OpenXml.Spreadsheet.Color { Rgb = "FFFF0000" });
        XlHelper.ColorCellText(si, "add", new DocumentFormat.OpenXml.Spreadsheet.Color { Rgb = "0000BF00" });
    }
}

我的XlHelper.ColorCellText方法:

public static void ColorCellText(SharedStringItem si, string TagName, DocumentFormat.OpenXml.Spreadsheet.Color col)
{
    var newText = si.InnerText;
    var startTag = string.Format("<{0}>", TagName);
    var endTag = string.Format("</{0}>", TagName);
    if (newText.Contains(startTag))
    {
        si.Text.Remove();
        var lastpos = 0;
        while (newText.Contains(startTag))
        {
            try
            {
                var pos1 = newText.IndexOf(startTag);
                var pos2 = newText.IndexOf(endTag);
                var txtLen = pos2 - pos1 - 5;
                var it = string.Concat(newText.Substring(0, pos1), newText.Substring(pos1 + 5, txtLen),
                    newText.Substring(pos2 + 6));

                var run = new Run();
                var txt = new Text
                {
                    Text = it.Substring(0, pos1),
                    Space = SpaceProcessingModeValues.Preserve
                };
                run.Append(txt);
                si.Append(run);

                run = new Run();
                txt = new Text
                {
                    Text = it.Substring(pos1, txtLen),
                    Space = SpaceProcessingModeValues.Preserve
                };

                var rp = new RunProperties();

                rp.Append(col.CloneNode(true));
                run.RunProperties = rp;
                run.Append(txt.CloneNode(true));
                si.Append(run.CloneNode(true));

                newText = newText.Substring(pos2 + 6);
            }
            catch(Exception ex)
            {
                using (var sw = new StreamWriter(logFile, true))
                {
                    sw.WriteLine("Error: {0}\r\n{1}", ex.Message, newText);
                }
                break;
            }
        }
        if (newText.Length>=0)
        {
            var lastrun = new Run();
            var lasttxt = new Text
            {
                Text = newText,
                Space = SpaceProcessingModeValues.Preserve
            };
            lastrun.Append(lasttxt);
            si.Append(lastrun);
        }
    }
}

Space = SpaceProcessingModeValues.Preserve 这一部分非常关键,否则它会将所有三个部分粘在一起并忽略它们之间的空格。

我想我会研究一下EPPlus,因为它的“In-cell Richtext”功能听起来相当有前途。


OpenXML文档并不差,它是低级别的,你真的需要了解Excel的模型——单元格有样式。就像在使用Excel时可以应用样式一样,使用SDK也可以应用样式。你不需要实际修改文本。像EPPlus这样的高级库使这个过程变得更容易,并包含样式示例。 - Panagiotis Kanavos

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接