在OpenXML Word文档(C#)中更改字体颜色

14

我已经搜索了几个小时,但好像找不到确切的答案。我有一个包含内容控件的现有文档,需要使用外部数据编辑其中的文本。如果某个控件的数据不存在,则需要用适当的通知替换文本并更改字体颜色。

我的文字输入和所有工作都很好,唯一不能正常工作的部分是更改字体颜色。我目前的代码没有任何错误,并且正在通过该方法运行,但是当我查看完成的文档时,仍然是普通的黑色文本。

我的更改颜色的方法:(输入是具有相同标记的所有内容控件的列表)

public void SetBlueText(List<SdtElement> sdtElement)
{
    foreach (SdtElement element in sdtElement)
    {
        if (element != null)
        {
            RunProperties runProperties = element.Descendants<RunProperties>().FirstOrDefault();
            runProperties.Color = new DocumentFormat.OpenXml.Wordprocessing.Color() { Val = "0EBFE9" };
        }
    }
}

此外,将这两行代码简化为 / 也会产生相同的效果。

element.Descendants<RunProperties>().FirstOrDefault().Color = 
                        new DocumentFormat.OpenXml.Wordprocessing.Color() { Val = "0EBFE9" };
4个回答

20

我遇到了类似的问题,并发现将对象附加到RunProperties对象的顺序实际上会影响格式更新是否起作用(我注意到的模式是,如果在进行格式设置之前附加文本,则该文本的格式设置不会保留)。

例如,这个可以工作(文本变为粗体,Cambria标题字体,并且颜色设置为蓝色)

Run formattedRun = new Run();
RunProperties runPro = new RunProperties();
RunFonts runFont = new RunFonts() { Ascii = "Cambria(Headings)", HighAnsi = "Cambria(Headings)" };
Bold bold = new Bold();
Text text = new Text("TESTING");
Color color = new Color() { Val = "365F91", ThemeColor = ThemeColorValues.Accent1, ThemeShade = "BF" };
runPro.Append(runFont);
runPro.Append(bold);
runPro.Append(color);
runPro.Append(text);
formattedRun.Append(runPro);

但这不会改变文字颜色(虽然文本变为了Cambria标题和粗体,但颜色仍保持标准黑色)

Run formattedRun = new Run();
RunProperties runPro = new RunProperties();
RunFonts runFont = new RunFonts() { Ascii = "Cambria(Headings)", HighAnsi = "Cambria(Headings)" };
Text text = new Text("TESTING");
Bold bold = new Bold();
Color color = new Color() { Val = "365F91", ThemeColor = ThemeColorValues.Accent1, ThemeShade = "BF" };
runPro.Append(runFont);
runPro.Append(bold);
runPro.Append(text);
runPro.Append(color);
formattedRun.Append(runPro);

7

我有点用蛮力猜到了答案,但它起作用了。

List<RunProperties> runProps = element.Descendants<RunProperties>().ToList();
foreach (RunProperties rp in runProps)
{
    rp.Color = new DocumentFormat.OpenXml.Wordprocessing.Color() { Val = "0EBFE9" };
}

如果有更优雅的解决方案,请添加并我会点赞。

0

我曾有一个与 OP 非常相似的需求,我有一个 Word 文档模板中包含了大量的纯文本和其他控件,我需要在运行时进行填充。我创建了一个扩展方法来设置文本和其他格式化元素。希望这能帮助到像我一样有类似需求的人:

    public static void ReplaceText(this SdtElement element, string replacementText, bool? isBold = null, bool? isItalic = null, System.Drawing.Color? color = null, VerticalPositionValues? textVerticalType = null, int? fontSizeComplexScript = null)
    {

        // First try to get content blocks from the element
        IEnumerable<SdtContentBlock> childContentBlocks = element.ChildElements.OfType<SdtContentBlock>();

        //Function to generate the new run properties
        RunProperties SetupNewRunProperties(RunProperties oldRunProps) { 

            var props = new RunProperties();

            if (fontSizeComplexScript.HasValue && fontSizeComplexScript.HasValue)
                props.FontSizeComplexScript.Val = fontSizeComplexScript.ToString();
            else if (oldRunProps?.FontSizeComplexScript != null)
                props.FontSizeComplexScript = (FontSizeComplexScript)oldRunProps.FontSizeComplexScript.CloneNode(true);

            if (isBold.HasValue) 
                props.Bold.Val = OnOffValue.FromBoolean(isBold.Value);
            else if(oldRunProps?.Bold != null)
                props.Bold = (Bold)oldRunProps.Bold.CloneNode(true);

            if (isItalic.HasValue)
                props.Italic.Val = OnOffValue.FromBoolean(isItalic.Value);
            else if (oldRunProps?.Italic != null)
                props.Italic = (Italic)oldRunProps.Italic.CloneNode(true);

            if (textVerticalType.HasValue)
                props.VerticalTextAlignment.Val = textVerticalType.Value;
            else if (oldRunProps?.VerticalTextAlignment != null)
                props.VerticalTextAlignment = (VerticalTextAlignment)oldRunProps.VerticalTextAlignment.CloneNode(true);

            if (color.HasValue)
            {
                if (props.Color != null)
                    props.Color.Val = color.Value.ToHexString();
                else
                    props.Color = new Color() { Val = color.Value.ToHexString() };
            }
            else if (oldRunProps?.Color != null)
            {
                props.Color = (Color)oldRunProps?.Color.CloneNode(true);
            }

            return props;
        }

        if (childContentBlocks.Count() > 0)
        {
            SdtContentBlock contentBlock = childContentBlocks.First();
            Paragraph para = contentBlock.ChildElements.OfType<Paragraph>().First();
            if (para != null)
            {
                Run run = para.GetFirstChild<Run>();

                run.RunProperties = SetupNewRunProperties(run.RunProperties);

                Text text = run.GetFirstChild<Text>();
                text.Text = replacementText;
            }
        }
        else
        {
            // Instead, try to get content runs from the element
            IEnumerable<SdtContentRun> childContentRuns = element.ChildElements.OfType<SdtContentRun>();

            if (childContentRuns.Count() > 0)
            {
                Run run = childContentRuns.First().GetFirstChild<Run>();

                run.RunProperties = SetupNewRunProperties(run.RunProperties);

                Text text = run.GetFirstChild<Text>();
                text.Text = replacementText;
            }
        }

    }

-2

颜色值应该是8位数字。例如Color.Val="FFFF0000"将字符串显示为红色。


这不是问题的答案。颜色可以表示为6个十六进制数字。只有当alpha小于100%时,才需要8个数字。 - Little geek

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