如何通过OpenXML C#SDK在文档中为现有文本添加上标(请参见下图)?我找到了一篇文章,但只添加了新的上标(不存在文字) This link
答案 0 :(得分:0)
以下Open XML标记代表您的行“出生日期:2019年10月15日”,其中“ th”的格式为上标:
<w:p>
<w:r>
<w:t>Date of birth: October 15</w:t>
</w:r>
<w:r>
<w:rPr>
<w:vertAlign w:val="superscript"/>
</w:rPr>
<w:t>th</w:t>
</w:r>
<w:r>
<w:t>, 2019</w:t>
</w:r>
</w:p>
请注意第二个w:r
元素(Run
类)及其子元素w:rPr
(RunProperties
类和孙子元素w:vertAlign
(VerticalTextAlignment
类) ),将“ th”的格式设置为上标。
使用Open XML SDK,您将如下创建上面的段落(注意缩进匹配,因此您可以看到对应关系):
var paragraph =
new Paragraph(
new Run(
new Text("Date of birth: October 15")),
new Run(
new RunProperties(
new VerticalTextAlignment { Val = VerticalPositionValues.Superscript }),
new Text("th")),
new Run(
new Text(", 2019")));
如果要格式化上面显示的现有文本,则必须标识并格式化满足“ st”,“ nd”,“ rd”和“ th”的序数。 Paragraph FormatSuperscript(string innerText)
方法可以做到这一点。它使用Text CreateText(string text)
方法为要渲染的任何文本(即,没有前导或尾随空格)生成具有正确w:text
属性的xml:space
元素。
// Matches ordinal number suffixes "st", "nd", "rd", and "th".
private static readonly Regex OrdinalNumberSuffixRegex =
new Regex("(?<=[0-9]+)(st|nd|rd|th)");
/// <summary>
/// Creates a new <see cref="Paragraph" /> with ordinal number suffixes
/// (i.e., "st", "nd", "rd", and "4th") formatted as a superscript.
/// </summary>
/// <param name="innerText">The paragraph's inner text.</param>
/// <returns>A new, formatted <see cref="Paragraph" />.</returns>
public static Paragraph FormatSuperscript(string innerText)
{
var destParagraph = new Paragraph();
var startIndex = 0;
foreach (Match match in OrdinalNumberSuffixRegex.Matches(innerText))
{
if (match.Index > startIndex)
{
string text = innerText[startIndex..match.Index];
destParagraph.AppendChild(new Run(CreateText(text)));
}
destParagraph.AppendChild(
new Run(
new RunProperties(
new VerticalTextAlignment
{
Val = VerticalPositionValues.Superscript
}),
CreateText(match.Value)));
startIndex = match.Index + match.Length;
}
if (startIndex < innerText.Length)
{
string text = innerText.Substring(startIndex);
destParagraph.AppendChild(new Run(CreateText(text)));
}
return destParagraph;
}
/// <summary>
/// Creates a new <see cref="Text" /> instance with the correct xml:space
/// attribute value.
/// </summary>
/// <param name="text">The text.</param>
/// <returns>A new <see cref="Text" /> instance.</returns>
public static Text CreateText(string text)
{
if (string.IsNullOrEmpty(text))
{
return new Text();
}
if (char.IsWhiteSpace(text[0]) || char.IsWhiteSpace(text[^1]))
{
return new Text(text) { Space = SpaceProcessingModeValues.Preserve };
}
return new Text(text);
}
以下单元测试显示了如何从上方使用FormatSuperscript()
方法:
[Fact]
public void FormatSuperscript_DateOfBirth_CorrectlyFormatted()
{
// Say we have a body or other container with a number of paragraphs, one
// of which is the paragraph that we want to format. In our case, we want
// the paragraph the inner text of which starts with "Date of birth:"
var body =
new Body(
new Paragraph(new Run(new Text("Full name: Phung Anh Tu"))),
new Paragraph(new Run(new Text("Date of birth: October 15th, 2019"))),
new Paragraph(new Run(new Text("Gender: male"))));
Paragraph sourceParagraph = body
.Descendants<Paragraph>()
.First(p => p.InnerText.StartsWith("Date of birth:"));
// In a first step, we'll create a new, formatted paragraph.
Paragraph destParagraph = FormatSuperscript(sourceParagraph.InnerText);
// Next, we format the existing paragraph by replacing it with the new,
// formatted one.
body.ReplaceChild(destParagraph, sourceParagraph);
// Finally, let's verify that we have a single "th" run that is:
// - preceded by one run with inner text "Date of birth: October 15",
// - followed by one run with inner text ", 2019", and
// - formatted as a superscript.
Assert.Single(body
.Descendants<Run>()
.Where(r => r.InnerText == "th" &&
r.PreviousSibling().InnerText == "Date of birth: October 15" &&
r.NextSibling().InnerText == ", 2019" &&
r.RunProperties.VerticalTextAlignment.Val == VerticalPositionValues.Superscript));
}
您将在我的CodeSnippets GitHub存储库中找到完整的源代码。寻找OrdinalNumberFormattingTests类。