none
Synchronize between Word and SQL Server trough content controls

    Question

  • I want to create a Word addin that allows our client to create documents such as invoices and contracts in Word 2007.

    There are three important constraints......

    • The documents must be centrally stored within a database.
    • The documents must be based on a templated that is generated on information in the same database.
    • It must be possible to (on-the-fly) add 'free text' content controls that are also stored in the database....

    For example....

    We have three database tables....a document table, a content table and a documentContent table that describes the structure of the document..

    <document Order>

        <contentControl OrderHeader>

       </contentControl>

      <contentControl OrderDetails>

             <contentControl OrderDetail1>

             </contentControl>

             <contentControl OrderDetail2>

             </contentControl>

       </contentControl>

        <contentControl FreeText1>

       </contentControl>

    </document>

    I think we need answers to the following two questions..........

    • Is it possible to generate content controls in Word trough VSTO (C#)?
    • Is it possible to synchronize these content controls with a database?

    I searched a lot on MSDN and the developer blogs but i can't find anything about the generation of content controls.

    I hope you can help me....Thanks a lot in advance!!

     

    .

     

    .

    Sunday, November 26, 2006 12:32 PM

Answers

  • Yes, it is possible to generate content controls in Word from your code. For example, to create content control from range myRange:

     

    ContentControl myCC = doc.ContentControls.Add(WdContentControlType.wdContentControlText, ref myRange);

     

    To later read CC content, look for Range.ContentControls.get_Item

     

    I think this document may be of interest to you:

     http://msdn2.microsoft.com/en-us/library/ms406053.aspx

    "Creating Word 2007 Templates Programmatically

     

     

    Sunday, November 26, 2006 6:25 PM
  • Dear Bojan, thanks a lot for your reaction....I tried to build some kind of prototype based on a addin template...I created a user control with some buttons and a calender control...

    I used your code on one of the buttons events...

    myRange = Globals.ThisAddIn.Application.ActiveDocument.Content;

    Word.ContentControl myCC = Globals.ThisAddIn.Application.ActiveDocument.ContentControls.Add(Word.WdContentControlType.wdContentControlRichText, ref myRange);

     This generated the following compile error...

    Error 1 The best overloaded method match for 'Microsoft.Office.Interop.Word.ContentControls.Add(Microsoft.Office.Interop.Word.WdContentControlType, ref object)' has some invalid arguments C:\Documents and Settings\Arthur.van.Adrichem\My Documents\Visual Studio 2005\Projects\Munch\Munch\CalendarControl.cs 53 39 Munch

    Error 2 Argument '2': cannot convert from 'ref Microsoft.Office.Interop.Word.Range' to 'ref object' C:\Documents and Settings\Arthur.van.Adrichem\My Documents\Visual Studio 2005\Projects\Munch\Munch\CalendarControl.cs 53 160 Munch

    Can you explain me the meaning of - and the idea behind - ref object? Have some ideas to get this thing to work?

    Monday, November 27, 2006 9:21 AM
  • Hi Artje

    This is something you'll run into a lot with Word. Read the parameter list very carefully as you enter parameters for methods and properties. If you see "ref object" that means you have to explicitly type what you're passing as an "object". So...

    Word.Range myRange = Globals.ThisAddIn.Application.ActiveDocument.Content:
    object oMyRange = (object) myRange

    Word.ContentControl myCC = Globals.ThisAddIn.Application.ActiveDocument.ContentControls.Add(Word.WdContentControlType.wdContentControlRichText, ref oMyRange);

    Monday, November 27, 2006 10:51 AM
    Moderator
  •  Artje wrote:

    Thanks for your help...I can now generate a singe content control...and view his/hers content through myCC.Range.Text.

    For dynamicaly accesing content controls i have to use the get_item function i guess?

    Yes :-) Don't forget it's "ref object index". Both the index number (position of the control in the document) and the control's ID property (read-only, generated when the control is created) are valid indexes for the property.

    Monday, November 27, 2006 2:25 PM
    Moderator

All replies

  • Yes, it is possible to generate content controls in Word from your code. For example, to create content control from range myRange:

     

    ContentControl myCC = doc.ContentControls.Add(WdContentControlType.wdContentControlText, ref myRange);

     

    To later read CC content, look for Range.ContentControls.get_Item

     

    I think this document may be of interest to you:

     http://msdn2.microsoft.com/en-us/library/ms406053.aspx

    "Creating Word 2007 Templates Programmatically

     

     

    Sunday, November 26, 2006 6:25 PM
  • Dear Bojan, thanks a lot for your reaction....I tried to build some kind of prototype based on a addin template...I created a user control with some buttons and a calender control...

    I used your code on one of the buttons events...

    myRange = Globals.ThisAddIn.Application.ActiveDocument.Content;

    Word.ContentControl myCC = Globals.ThisAddIn.Application.ActiveDocument.ContentControls.Add(Word.WdContentControlType.wdContentControlRichText, ref myRange);

     This generated the following compile error...

    Error 1 The best overloaded method match for 'Microsoft.Office.Interop.Word.ContentControls.Add(Microsoft.Office.Interop.Word.WdContentControlType, ref object)' has some invalid arguments C:\Documents and Settings\Arthur.van.Adrichem\My Documents\Visual Studio 2005\Projects\Munch\Munch\CalendarControl.cs 53 39 Munch

    Error 2 Argument '2': cannot convert from 'ref Microsoft.Office.Interop.Word.Range' to 'ref object' C:\Documents and Settings\Arthur.van.Adrichem\My Documents\Visual Studio 2005\Projects\Munch\Munch\CalendarControl.cs 53 160 Munch

    Can you explain me the meaning of - and the idea behind - ref object? Have some ideas to get this thing to work?

    Monday, November 27, 2006 9:21 AM
  • Hi Artje

    This is something you'll run into a lot with Word. Read the parameter list very carefully as you enter parameters for methods and properties. If you see "ref object" that means you have to explicitly type what you're passing as an "object". So...

    Word.Range myRange = Globals.ThisAddIn.Application.ActiveDocument.Content:
    object oMyRange = (object) myRange

    Word.ContentControl myCC = Globals.ThisAddIn.Application.ActiveDocument.ContentControls.Add(Word.WdContentControlType.wdContentControlRichText, ref oMyRange);

    Monday, November 27, 2006 10:51 AM
    Moderator
  • Thanks for your help...I can now generate a singe content control...and view his/hers content through myCC.Range.Text.

    For dynamically accessing content controls i have to use the get_item function i guess?

     

    Monday, November 27, 2006 12:15 PM
  •  Artje wrote:

    Thanks for your help...I can now generate a singe content control...and view his/hers content through myCC.Range.Text.

    For dynamicaly accesing content controls i have to use the get_item function i guess?

    Yes :-) Don't forget it's "ref object index". Both the index number (position of the control in the document) and the control's ID property (read-only, generated when the control is created) are valid indexes for the property.

    Monday, November 27, 2006 2:25 PM
    Moderator
  • Let me post some sample code... The code shows how to add a content control and sync it with a database

    public partial class ProjectsControl : UserControl

    {

    ProjectDataSet myProjects = new ProjectDataSet();

    ProjectDataSetTableAdapters.ProjectTableAdapter myProjectsTableAdapter = new ProjectDataSetTableAdapters.ProjectTableAdapter();

    ContentControlDataSet myContentControls = new ContentControlDataSet();

    ContentControlDataSetTableAdapters.ContentTableAdapter myContentControlsTableAdapter = new ContentControlDataSetTableAdapters.ContentTableAdapter();

    GuidConverter eenGuidConverter = new GuidConverter();

    private Word.Range myRange = null;

    public ProjectsControl()

    {

    InitializeComponent();

    }

    private void button1_Click(object sender, EventArgs e)

    {

    myRange = Globals.ThisAddIn.Application.Selection.Range;

    Object test = (object)myRange;

    //Add content control to selection and tag it with a GUID.

    try

    {

    Guid eenGuid = Guid.NewGuid();

    Word.ContentControl myCC = Globals.ThisAddIn.Application.ActiveDocument.ContentControls.Add(Word.WdContentControlType.wdContentControlRichText, ref test);

    myCC.Tag = eenGuidConverter.ConvertToString(eenGuid);

    Globals.ThisAddIn.Application.ActiveDocument.ContentControlOnExit += new Microsoft.Office.Interop.Word.DocumentEvents2_ContentControlOnExitEventHandler(ActiveDocument_ContentControlOnExit);

    }

    catch

    {

    MessageBox.Show("Content control could not be added to the document");

    }

    }

    private void ActiveDocument_ContentControlOnExit(Microsoft.Office.Interop.Word.ContentControl ContentControl, ref bool Cancel)

    {

    //Get the GUID...

    Guid deGuid = new Guid(ContentControl.Tag);

    //Search for GUID in existence in the database...

    myContentControlsTableAdapter.Fill(myContentControls.Content);

    ContentControlDataSet.ContentRow deContentControl = myContentControls.Content.FindByContentID(deGuid);

    //If not found insert, else update....

    if (deContentControl == null)

    {

    myContentControls.Content.AddContentRow(deGuid, ContentControl.Range.Text, int.Parse(comboBox1.SelectedValue.ToString()));

    }

    else

    {

    deContentControl.ContentText = ContentControl.Range.Text;

    }

    //Sync with database...

    myContentControlsTableAdapter.Update(myContentControls.Content);

    }

    private void button2_Click(object sender, EventArgs e)

    {

    }

    private void Projecten_Load(object sender, EventArgs e)

    {

    //Get the projects

    myProjectsTableAdapter.Fill(myProjects.Project);

    //Populate the combobox with the projects

    comboBox1.DataSource = myProjects.Project;

    }

    }

    If you have any ideas on how to improve the code...just shoot!

    Tuesday, November 28, 2006 1:56 PM