none
Dynamically add content controls into my docx RRS feed

  • Question

  • I used this tutorial to merge several docx documents into one single document using Visual Studio. The tutorial is suggesting to add the content control manually. I'm at a point where I want to be able to add a content control and replace it by a word document shortly after that.

    Step 2 shows how to find content controls with specific names, but I can't figure out how to add one earlier myself and replace it later on. Thanks for your help

    Wednesday, August 4, 2010 11:36 AM

Answers

  • Hi Andreas,

    Here is a code snippet which I tried to add three SdtBlocks in a blank document, and it worked for me.

    static void Main(string[] args)
    {
    	WordprocessingDocument doc = WordprocessingDocument.Create(@"d:\myOpenXmlTest.docx", DocumentFormat.OpenXml.WordprocessingDocumentType.Document);
    
    	MainDocumentPart mainDocPart = doc.AddMainDocumentPart();
    	
    	mainDocPart.Document = new Document();
    	mainDocPart.Document.Body = new Body();
    
    	Paragraph tPara = new Paragraph();
    	Run tRun = new Run();
    
    	Text tText = new Text() { Space = SpaceProcessingModeValues.Preserve};
    	tText.Text = "This is a test document";
    
    	tRun.Append(tText);
    	tPara.Append(tRun);
    
    	mainDocPart.Document.Body.Append(tPara);
    
    	// Add three SdtBlocks
    	for (int i = 0; i < 3; ++i)
    	{
    
    		SdtBlock tBlock = new SdtBlock();
    		SdtProperties tBlockProps = new SdtProperties();
    		
    		SdtId tId = new SdtId();
    		tId.Val = 100 + i + 1;		// a unique ID for this document
    		tBlockProps.Append(tId);
    
    		SdtPlaceholder tPlaceholder = new SdtPlaceholder();
    		
    		DocPartReference tDocPartRef = new DocPartReference();
    		tDocPartRef.Val = "DocPartRef1";
    		tPlaceholder.Append(tDocPartRef);
    
    		tBlockProps.Append(tPlaceholder);
    
    		SdtContentBlock tContentBlock = new SdtContentBlock();
    		Paragraph tContentPara = new Paragraph();
    		Run tContentRun = new Run();
    		
    		Text tContentText = new Text() { Space = SpaceProcessingModeValues.Preserve };
    		tContentText.Text = string.Format("This is content block : {0}", i + 1);
    		
    		tContentRun.Append(tContentText);
    		tContentPara.Append(tContentRun);
    		tContentBlock.Append(tContentPara);
    
    		tBlock.Append(tBlockProps);
    		tBlock.Append(tContentBlock);
    
    		mainDocPart.Document.Body.Append(tBlock);
    
    		// Add another paragraph for differentiating
    
    		tPara = new Paragraph();
    		tRun = new Run();
    
    		tText = new Text() { Space = SpaceProcessingModeValues.Preserve };
    		tText.Text = "This is a new Paragraph";
    
    		tRun.Append(tText);
    		tPara.Append(tRun);
    
    		mainDocPart.Document.Body.Append(tPara);
    	}
    
    	doc.Close();
    
    }
    
    

     

    Please try this in your scenario, and let me know how it goes.

    HTH,

    Manvir Singh
    http://www.manvirsingh.net/

    Thursday, August 12, 2010 10:36 PM

All replies

  • Hi Andreas,

    I think you are looking for a way to add an SdtBlock programmatically in your Open XML Document. If not, please let me know.

    You can generate the required code yourself by using the Open XML SDK 2.0 Productivity Tool, as below:

    1. Create a test document that has a content control in it.
    2. Open the document in Open XML Productivity tool, and navigate to w:sdt tag and click on Reflect Code.

    Use the same logic in your program before Step 2 of you document.

    In addition to using Content Controls, you can also use Bookmarks as the placeholder for you external content.

    Hope this helps,

    Manvir Singh
    http://www.manvirsingh.net/

     

    Wednesday, August 4, 2010 4:20 PM
  • Hello Manvir,

    you're right about what I was looking for and your suggestion helps me a lot. The generated code helps to create one specific SdtBlock what but I need is a more general approach so my goal is to create a method which returns a new SdtBlock.

    I'm struggeling with the following properties of a SdtBlock to create a new one via a method:

    • SdtId : Can I use a random int to set this id?
    • DocPartReference: What impact does this value have? Can I use a random value here myself for all SdtBlocks in my document?
    • Paragraph: This includes some values like ParagraphId and TextId and I'm not sure how to set those values. How does the paragraph influences my SdtBlock?
    Copying all the code from the Productivity Tool seems to be a little bit too much overhead, so I focused on my key problems.
    Thursday, August 5, 2010 9:41 AM
  • Is there anybody else out there who might be able to help me with this? I'm looking for a method with some parameters which adds a new content control to my docx document. Any help very much appreciated.
    Monday, August 9, 2010 7:13 AM
  • Hi Andreas,

    I noticed your last post on this forum and the comment on my blog post :)

    I will have a look into this, and will get back to you.

    Regards,

    Manvir Singh
    http://www.manvirsingh.net/

     

    Monday, August 9, 2010 5:05 PM
  • Hi Andreas,

    Here is a code snippet which I tried to add three SdtBlocks in a blank document, and it worked for me.

    static void Main(string[] args)
    {
    	WordprocessingDocument doc = WordprocessingDocument.Create(@"d:\myOpenXmlTest.docx", DocumentFormat.OpenXml.WordprocessingDocumentType.Document);
    
    	MainDocumentPart mainDocPart = doc.AddMainDocumentPart();
    	
    	mainDocPart.Document = new Document();
    	mainDocPart.Document.Body = new Body();
    
    	Paragraph tPara = new Paragraph();
    	Run tRun = new Run();
    
    	Text tText = new Text() { Space = SpaceProcessingModeValues.Preserve};
    	tText.Text = "This is a test document";
    
    	tRun.Append(tText);
    	tPara.Append(tRun);
    
    	mainDocPart.Document.Body.Append(tPara);
    
    	// Add three SdtBlocks
    	for (int i = 0; i < 3; ++i)
    	{
    
    		SdtBlock tBlock = new SdtBlock();
    		SdtProperties tBlockProps = new SdtProperties();
    		
    		SdtId tId = new SdtId();
    		tId.Val = 100 + i + 1;		// a unique ID for this document
    		tBlockProps.Append(tId);
    
    		SdtPlaceholder tPlaceholder = new SdtPlaceholder();
    		
    		DocPartReference tDocPartRef = new DocPartReference();
    		tDocPartRef.Val = "DocPartRef1";
    		tPlaceholder.Append(tDocPartRef);
    
    		tBlockProps.Append(tPlaceholder);
    
    		SdtContentBlock tContentBlock = new SdtContentBlock();
    		Paragraph tContentPara = new Paragraph();
    		Run tContentRun = new Run();
    		
    		Text tContentText = new Text() { Space = SpaceProcessingModeValues.Preserve };
    		tContentText.Text = string.Format("This is content block : {0}", i + 1);
    		
    		tContentRun.Append(tContentText);
    		tContentPara.Append(tContentRun);
    		tContentBlock.Append(tContentPara);
    
    		tBlock.Append(tBlockProps);
    		tBlock.Append(tContentBlock);
    
    		mainDocPart.Document.Body.Append(tBlock);
    
    		// Add another paragraph for differentiating
    
    		tPara = new Paragraph();
    		tRun = new Run();
    
    		tText = new Text() { Space = SpaceProcessingModeValues.Preserve };
    		tText.Text = "This is a new Paragraph";
    
    		tRun.Append(tText);
    		tPara.Append(tRun);
    
    		mainDocPart.Document.Body.Append(tPara);
    	}
    
    	doc.Close();
    
    }
    
    

     

    Please try this in your scenario, and let me know how it goes.

    HTH,

    Manvir Singh
    http://www.manvirsingh.net/

    Thursday, August 12, 2010 10:36 PM
  • Hey Manvir,

    amazing work, thank you very much as my scales now waaaaaaay better than before without using dirty code and adding 200 content blocks into my template without knowing how many of them I'll need in the end. Thanks to you I can add as many content blocks as I need while editing the docx file.

    Friday, August 13, 2010 7:58 AM