none
Looping over Content Control RRS feed

  • Question

  • I have created a content control in my document as shown below

     

    Now in my C# code I want to find this control tag and replace it with AltChunk

     

                using (WordprocessingDocument wpd = WordprocessingDocument.Open(@".\test.docx", true)) {
                    MainDocumentPart mpd = wpd.MainDocumentPart;
                    SdtElement titleContentControl = mpd.Document.Descendants<SdtElement>().Where(<br/>e => e.SdtProperties.GetFirstChild<Tag>() != null <br/>&& e.SdtProperties.GetFirstChild<Tag>().Val.Value.ToUpperInvariant() == "TITLE").FirstOrDefault();
                    string altChunkId = "AltChunkId12345";
                    AlternativeFormatImportPart chunk = mpd.AddAlternativeFormatImportPart(AlternativeFormatImportPartType.WordprocessingML, altChunkId);
                    chunk.FeedData(File.Open(@".\html.txt", FileMode.Open));
                    AltChunk altChunk = new AltChunk();
                    altChunk.Id = altChunkId;
                    //Replace content control with altChunk information                
                    OpenXmlElement parent = titleContentControl.Parent;
                    parent.InsertAfter(altChunk, titleContentControl);
                    titleContentControl.Remove();
                    wpd.Close();
                }
    

     

    However titleContentControl is always NULL.

     


    MSDNStudent Knows not much!
    Sunday, January 22, 2012 12:21 PM

Answers

  • Hi MSDN Student,

    Thank you for posting.

    You can try to find the control via the following code snippet which I have ever used:

                using (WordprocessingDocument document = WordprocessingDocument.Open(
              @"findcontentctl.docx"true))
                {
                    MainDocumentPart mainPart = document.MainDocumentPart;
                    Text text = null;
                    SdtContentBlock sdtContentBlock = null;
                    SdtBlock sdtBlock = mainPart.Document.Body.Descendants<SdtBlock>().
                        Where(r => r.SdtProperties.GetFirstChild<Tag>().Val == "mycontentctl").Single();
                    if (sdtBlock != null)
                    {
                        sdtContentBlock = sdtBlock.Descendants<SdtContentBlock>().FirstOrDefault();
                        text = sdtContentBlock.Descendants<Text>().FirstOrDefault();
     
                        // here you can set the current time
                        text.Text = DateTime.Now.ToString();
                        Console.WriteLine(text.Text);
                    }
                }

    Hope this can give you some hint and if the problem persists, it will be nice if you can upload your project to the skydirve: http://www.skydrive.com so that we can reproduce and analyze the problem more quickly.
    Best Regards,


    Bruce Song [MSFT]
    MSDN Community Support | Feedback to us
    • Marked as answer by Bruce Song Thursday, February 2, 2012 6:20 AM
    • Unmarked as answer by MSDN Student Saturday, February 4, 2012 8:34 AM
    • Marked as answer by MSDN Student Saturday, February 4, 2012 9:24 AM
    Tuesday, January 24, 2012 4:56 AM
  • Bruce,

    Your example works wonderfully if I have to insert plain text into the document.

    In my example, I am trying to insert HTML into the word document. this HTML should appear property formatted inside the work document (not like plain text with all the markup visible and all).

     

    Based on your code I modified my code as follows. But this code creates an invalid word document which cannot be opened in msword. Can you tell me how can I insert the html content without corrupting my document?

     

                    SdtContentBlock pizzaNameBlock = null;  
                    SdtContentBlock pizzaDescriptionBlock = null;  
                    //SdtContentBlock pizzaPictureBlock = null;  
    
                    SdtBlock s1 = mainPart.Document.Body.Descendants<SdtBlock>().Where(r => r.SdtProperties.GetFirstChild<Tag>().Val == "PizzaName").Single();
                    SdtBlock s2 = mainPart.Document.Body.Descendants<SdtBlock>().Where(r => r.SdtProperties.GetFirstChild<Tag>().Val == "PizzaDescription").Single();
                    //SdtBlock s3 = mainPart.Document.Body.Descendants<SdtBlock>().Where(r => r.SdtProperties.GetFirstChild<Tag>().Val == "PizzaPicture").Single();
    
                    if (s1 != null) {
                        pizzaNameBlock = s1.Descendants<SdtContentBlock>().FirstOrDefault();
                        text = pizzaNameBlock.Descendants<Text>().FirstOrDefault();
                        // here you can set the current time
                        text.Text = "Peperoni";
                        Console.WriteLine(text.Text);
                    }
    
    
                    if (s2 != null) {
                        pizzaDescriptionBlock = s2.Descendants<SdtContentBlock>().FirstOrDefault();
    
                        string altChunkId = "AltChunkId12345";
                        AlternativeFormatImportPart chunk = mainPart.AddAlternativeFormatImportPart(AlternativeFormatImportPartType.WordprocessingML, altChunkId);
                        chunk.FeedData(File.Open(@".\html.txt", FileMode.Open));
                        AltChunk altChunk = new AltChunk();
                        altChunk.Id = altChunkId;
                        ////Replace content control with altChunk information                
                        OpenXmlElement parent = pizzaDescriptionBlock.Parent;
                        parent.InsertAfter(altChunk, pizzaDescriptionBlock);
                        pizzaDescriptionBlock.Remove();
                    }
    
                    mainPart.Document.Save();
                    document.Close();
                }
    
    



    MSDNStudent Knows not much!
    • Marked as answer by MSDN Student Saturday, February 4, 2012 9:24 AM
    Saturday, February 4, 2012 8:38 AM
  • Got it to work in the above code change

    AlternativeFormatImportPart chunk = mainPart.AddAlternativeFormatImportPart(AlternativeFormatImportPartType.Xhtml, altChunkId);

    the other change is that the contents of html.txt should contain the FULL HTML

     

    <html><body><table>.....</table></body></html>

    Earlier I just had

     

     

    <table> </table>

     and word did not like that!

     


    MSDNStudent Knows not much!
    • Marked as answer by MSDN Student Saturday, February 4, 2012 9:24 AM
    Saturday, February 4, 2012 9:24 AM

All replies

  • Hi MSDN Student,

    Thank you for posting.

    You can try to find the control via the following code snippet which I have ever used:

                using (WordprocessingDocument document = WordprocessingDocument.Open(
              @"findcontentctl.docx"true))
                {
                    MainDocumentPart mainPart = document.MainDocumentPart;
                    Text text = null;
                    SdtContentBlock sdtContentBlock = null;
                    SdtBlock sdtBlock = mainPart.Document.Body.Descendants<SdtBlock>().
                        Where(r => r.SdtProperties.GetFirstChild<Tag>().Val == "mycontentctl").Single();
                    if (sdtBlock != null)
                    {
                        sdtContentBlock = sdtBlock.Descendants<SdtContentBlock>().FirstOrDefault();
                        text = sdtContentBlock.Descendants<Text>().FirstOrDefault();
     
                        // here you can set the current time
                        text.Text = DateTime.Now.ToString();
                        Console.WriteLine(text.Text);
                    }
                }

    Hope this can give you some hint and if the problem persists, it will be nice if you can upload your project to the skydirve: http://www.skydrive.com so that we can reproduce and analyze the problem more quickly.
    Best Regards,


    Bruce Song [MSFT]
    MSDN Community Support | Feedback to us
    • Marked as answer by Bruce Song Thursday, February 2, 2012 6:20 AM
    • Unmarked as answer by MSDN Student Saturday, February 4, 2012 8:34 AM
    • Marked as answer by MSDN Student Saturday, February 4, 2012 9:24 AM
    Tuesday, January 24, 2012 4:56 AM
  • Bruce,

    Your example works wonderfully if I have to insert plain text into the document.

    In my example, I am trying to insert HTML into the word document. this HTML should appear property formatted inside the work document (not like plain text with all the markup visible and all).

     

    Based on your code I modified my code as follows. But this code creates an invalid word document which cannot be opened in msword. Can you tell me how can I insert the html content without corrupting my document?

     

                    SdtContentBlock pizzaNameBlock = null;  
                    SdtContentBlock pizzaDescriptionBlock = null;  
                    //SdtContentBlock pizzaPictureBlock = null;  
    
                    SdtBlock s1 = mainPart.Document.Body.Descendants<SdtBlock>().Where(r => r.SdtProperties.GetFirstChild<Tag>().Val == "PizzaName").Single();
                    SdtBlock s2 = mainPart.Document.Body.Descendants<SdtBlock>().Where(r => r.SdtProperties.GetFirstChild<Tag>().Val == "PizzaDescription").Single();
                    //SdtBlock s3 = mainPart.Document.Body.Descendants<SdtBlock>().Where(r => r.SdtProperties.GetFirstChild<Tag>().Val == "PizzaPicture").Single();
    
                    if (s1 != null) {
                        pizzaNameBlock = s1.Descendants<SdtContentBlock>().FirstOrDefault();
                        text = pizzaNameBlock.Descendants<Text>().FirstOrDefault();
                        // here you can set the current time
                        text.Text = "Peperoni";
                        Console.WriteLine(text.Text);
                    }
    
    
                    if (s2 != null) {
                        pizzaDescriptionBlock = s2.Descendants<SdtContentBlock>().FirstOrDefault();
    
                        string altChunkId = "AltChunkId12345";
                        AlternativeFormatImportPart chunk = mainPart.AddAlternativeFormatImportPart(AlternativeFormatImportPartType.WordprocessingML, altChunkId);
                        chunk.FeedData(File.Open(@".\html.txt", FileMode.Open));
                        AltChunk altChunk = new AltChunk();
                        altChunk.Id = altChunkId;
                        ////Replace content control with altChunk information                
                        OpenXmlElement parent = pizzaDescriptionBlock.Parent;
                        parent.InsertAfter(altChunk, pizzaDescriptionBlock);
                        pizzaDescriptionBlock.Remove();
                    }
    
                    mainPart.Document.Save();
                    document.Close();
                }
    
    



    MSDNStudent Knows not much!
    • Marked as answer by MSDN Student Saturday, February 4, 2012 9:24 AM
    Saturday, February 4, 2012 8:38 AM
  • Got it to work in the above code change

    AlternativeFormatImportPart chunk = mainPart.AddAlternativeFormatImportPart(AlternativeFormatImportPartType.Xhtml, altChunkId);

    the other change is that the contents of html.txt should contain the FULL HTML

     

    <html><body><table>.....</table></body></html>

    Earlier I just had

     

     

    <table> </table>

     and word did not like that!

     


    MSDNStudent Knows not much!
    • Marked as answer by MSDN Student Saturday, February 4, 2012 9:24 AM
    Saturday, February 4, 2012 9:24 AM