Share via


Q&A: Determining location in Word table

Q: A customer asks...I'm using Microsoft Visual Studio 2005 Tools for the Microsoft Office System, and I have a Microsoft Office Word document that contains a table. Let's say the table has two columns. When the user clicks a cell in the first column, I want to trigger a user control in the actions pane. Likewise for the second column. I want each event handler to know which entry (which row) I'm on in the column. I don't want to give each cell a unique tag since the number of rows changes and I don't want the code to have to change. How would I do this?

 

A: One way to approach this is to select the table and add a Bookmark control so that the table is completely surrounded by the bookmark. You can then add code in the SelectionChange event handler of the bookmark to determine which cell is currently selected. You can get the index of the currently selected row using Application.Selection.Rows(1).Index, and get the index of the currently selected column using Application.Selection.Columns(1).Index. Note that the insertion point can be a selection, so text within the cell does not need to be selected. In this example, I create instances of Windows Forms controls to be added to the actions pane, but you could add custom user controls or actions pane controls instead.

 

' Visual Basic

' Create instances of Windows Forms controls to add to

' the actions pane.

Dim TextBox1 As New TextBox
Dim CheckBox1 As New CheckBox

Private Sub Bookmark1_Deselected(ByVal sender As _

    Object, ByVal e As Microsoft.Office.Tools.Word. _

    SelectionEventArgs) Handles Bookmark1.Deselected

    Me.ActionsPane.Controls.Remove(TextBox1)
Me.ActionsPane.Controls.Remove(CheckBox1)

End Sub

Private Sub Bookmark1_SelectionChange(ByVal sender As _

    System.Object, ByVal e As Microsoft.Office.Tools. _

    Word.SelectionEventArgs) Handles Bookmark1.SelectionChange

    ' Get the currently selected row and column index.

    Dim RowNumber As Integer = Application.Selection. _

        Rows(1).Index
Dim ColNumber As Integer = Application.Selection. _

        Columns(1).Index

    ' Each cell contains a paragraph mark and end of cell

    ' marker which will appear as square boxes when the

    ' cell's text is assigned to a control. Assign them to a

    ' variable so they can be removed by replacing them with

    ' an empty string.

    Dim CellMarker As String = Chr(13) & Chr(7)

    If ColNumber = 1 Then
Me.ActionsPane.Controls.Add(TextBox1)
TextBox1.Text = "Column " & ColNumber & ": " & _

            Bookmark1.Tables(1).Cell(RowNumber, ColNumber).

            Range.Text.Replace( CellMarker, "")

    Else

        Me.ActionsPane.Controls.Add(CheckBox1)

        CheckBox1.Text = "Column " & ColNumber & ": " & _

            Bookmark1.Tables(1).Cell(RowNumber, ColNumber).

            Range.Text.Replace(CellMarker, "")

    End If

End Sub

// C#

// Create instances of Windows Forms controls to add to

// the actions pane.

TextBox TextBox1 = new TextBox();

CheckBox CheckBox1 = new CheckBox();

private void ThisDocument_Startup(object sender,

  System.EventArgs e)

{

    Bookmark1.SelectionChange += new Microsoft.Office.

        Tools.Word.SelectionEventHandler( _ 

        Bookmark1_SelectionChange);

    Bookmark1.Deselected += new Microsoft.Office.Tools.

        Word.SelectionEventHandler(

        Bookmark1_Deselected);

}

void Bookmark1_Deselected(object sender, Microsoft.Office.Tools

    .Word.SelectionEventArgs e)

{

    this.ActionsPane.Controls.Remove(TextBox1);

    this.ActionsPane.Controls.Remove(CheckBox1);

}

void Bookmark1_SelectionChange(object sender, Microsoft.Office

    .Tools.Word.SelectionEventArgs e)

{

    // Get the currently selected row and column index.
int RowNumber = Application.Selection.Rows[1].Index;
int ColNumber = Application.Selection.Columns[1].Index;

    // Each cell contains a paragraph mark and end of cell

    // marker which will appear as square boxes when the cell's

    // text is assigned to a control. Assign them to a variable

    // so they can be removed by replacing them with an empty

    // string.

    string CellMarker = "\r\a";

    if (ColNumber == 1)

    {

        this.ActionsPane.Controls.Add(TextBox1);

        TextBox1.Text = "Column " + ColNumber + ": " +

            Bookmark1.Tables[1].Cell(RowNumber, ColNumber).

            Range.Text.Replace(CellMarker, "");

    }

  else

    {

        this.ActionsPane.Controls.Add(CheckBox1);

        CheckBox1.Text = "Column " + ColNumber + ": " +

            Bookmark1.Tables[1].Cell(RowNumber, ColNumber).

            Range.Text.Replace(CellMarker, "");

    }

}

Another approach is to use XML markup. You can mark up the cells and VSTO will generate XMLNodes controls for the collection of XMLNodes for the table cells. As rows are added to the table, the XML markup will automatically be copied to the new cells, and the XMLNodes collection will grow as well. It's then possible to write an event handler for the XMLNodes.ContextEnter and XMLNodes.ContextLeave events to add and remove controls from the actions pane. You can then write the code in the XMLNodes.Select event handler to update the information in the control with the text from the currently selected cell.

-- Kathleen McGrath

-----
This posting is provided "AS IS" with no warranties, and confers no rights.
Use of included script samples are subject to the terms specified at https://www.microsoft.com/info/cpyright.htm.