【问题标题】:New Line in Rich Text Content Control of Word open xmlWord open xml的富文本内容控件中的新行
【发布时间】:2019-11-17 20:37:30
【问题描述】:

我有一个包含Rich text Content Control 的 Word 文档。

我想添加带有新行的文本。

using (WordprocessingDocument theDoc = WordprocessingDocument.Open(docName, true))
 {
   MainDocumentPart mainPart = theDoc.MainDocumentPart;
   foreach (SdtElement sdt in mainPart.Document.Descendants<SdtElement>())
     {
        SdtAlias alias = sdt.Descendants<SdtAlias>().FirstOrDefault();
        if (alias != null)
          {
            string sdtTitle = alias.Val.Value;
            var t = sdt.Descendants<Text>().FirstOrDefault();
             if (sdtTitle == "Body")
               {
                 t.Text = "Welcome to Yazd With its winding lanes, forest of badgirs,\r\n mud-brick houses and delightful places to stay, Yazd is a 'don't miss' destination. On a flat plain ringed by mountains, \r\nthe city is wedged between the northern Dasht-e Kavir and southern Dasht-e Lut and is every inch a city of the desert." }
         }
     }
}

我使用带有\r\n 的文本,但不添加新行。

【问题讨论】:

  • 但是文字加了? \r\n 是否被遗漏了?请注意,对于一个新行,仅使用 \r\n,而不是两者(应该给出两行)。你确定这是一个 RichText 内容控件而不是纯文本吗?如果您以用户身份在 Word 中打开文档,是否可以在其中键入新行?
  • 啊,model-view-controller和这个问题有什么关系?
  • @CindyMeister,“\r\n”(回车和换行)是 Windows 操作系统上的行分隔符。例如,在 Unix、Linux 和 macOS 上,行分隔符是“\n”(换行符)。
  • @ThomasBarnekow 此信息与使用 Open XML 文件格式添加到 Word 文档的内容无关。首先,Word 无法识别该组合,其次,它当然不应该用于在 Open XML 文档中生成新行。问题中的代码将按原样显示字符。如果需要换行,代码需要生成 Paragraphs 和 Runs。
  • @CindyMeister,我明白这一点。我是 Open XML SDK 和 PowerTools for Open XML 的贡献者,我在下面的回答也应该支持这一点。 Word 会将每个行分隔符呈现为单个空格字符(可以通过使用在文本中具有一个或多个行分隔符的 w:t 元素来验证)。我刚刚对您关于不使用“\r\n”作为行分隔符的评论做出了反应。与您的建议相反,“\r\n”不会产生两行,因为这两个控制字符的组合是 Windows 上的行分隔符。

标签: c# model-view-controller ms-word openxml openxml-sdk


【解决方案1】:

制表符、换行符等一些字符是用特殊的 XML 元素定义的。
对于您的情况,您需要 &lt;w:br/&gt; 元素,因此请尝试以下操作:

using (WordprocessingDocument theDoc = WordprocessingDocument.Open(docName, true))
{
    MainDocumentPart mainPart = theDoc.MainDocumentPart;
    foreach (SdtElement sdt in mainPart.Document.Descendants<SdtElement>())
    {
        SdtAlias alias = sdt.Descendants<SdtAlias>().FirstOrDefault();
        if (alias != null && alias.Val.Value == "Body")
        {
            var run = sdt.Descendants<Run>().FirstOrDefault();
            run.RemoveAllChildren<Text>();

            var text = "Welcome to Yazd With its winding lanes, forest of badgirs,\r\n mud-brick houses and delightful places to stay, Yazd is a 'don't miss' destination. On a flat plain ringed by mountains, \r\nthe city is wedged between the northern Dasht-e Kavir and southern Dasht-e Lut and is every inch a city of the desert.";
            var lines = text.Split(new string[] { "\r\n" }, StringSplitOptions.None);

            foreach (var line in lines)
            {
                run.AppendChild(new Text(line));
                run.AppendChild(new Break());
            }

            run.Elements<Break>().Last().Remove();
        }
    }
}

我希望这会有所帮助。

【讨论】:

    【解决方案2】:

    假设您确实希望将您的功能限制为富文本内容控件,即块级结构化文档标签,您将寻找SdtBlock 的实例。使用SdtElement,您还可以找到内联级(SdtRun)、行级(SdtRow)和单元级(SdtCell)结构化文档标签,因为SdtBlockSdtRun、@ 987654328@ 和SdtCellSdtElement 的子类。

    以下是一个简单的实现,假设富文本内容控件应该只包含多行文本。它会修剪线条,因为示例文本包含看似无关的空格。

    public void AddMultiLineTextToRichTextContentControlsUsingRuns()
    {
        // Produce the list of lines from the text separated by "\r\n"
        // in the question, trimming leading and trailing whitespace.
        const string text = "Welcome to Yazd With its winding lanes, forest of badgirs,\r\n mud-brick houses and delightful places to stay, Yazd is a 'don't miss' destination. On a flat plain ringed by mountains, \r\nthe city is wedged between the northern Dasht-e Kavir and southern Dasht-e Lut and is every inch a city of the desert.";
        string[] separator = { "\r\n" };
    
        List<string> lines = text
            .Split(separator, StringSplitOptions.None)
            .Select(line => line.Trim())
            .ToList();
    
        // Get the w:document element.
        const string path = @"path\to\your\document.docx";
        using WordprocessingDocument wordDocument = WordprocessingDocument.Open(path, true);
        Document document = wordDocument.MainDocumentPart.Document;
    
        // Get all Rich Text (i.e., block) w:sdt elements having a w:alias
        // descendant with w:val="Body".
        IEnumerable<SdtBlock> sdts = document
            .Descendants<SdtBlock>()
            .Where(sdt => sdt.Descendants<SdtAlias>().Any(alias => alias.Val == "Body"));
    
        foreach (SdtBlock sdt in sdts)
        {
            // Create one w:r element per line, prepending a w:br to the
            // second and following runs.
            IEnumerable<Run> runs = lines
                .Select((line, index) =>
                    index == 0
                        ? new Run(new Text(line))
                        : new Run(new Break(), new Text(line)));
    
            // Create or replace the w:sdtContent element with one that has
            // a single w:p with one or more w:r children.
            sdt.SdtContentBlock = new SdtContentBlock(new Paragraph(runs));
        }
    }
    
    

    【讨论】:

      猜你喜欢
      • 2014-07-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-06-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多