How can I duplicate a row in a Word table?

Gary McGill picture Gary McGill · Sep 12, 2013 · Viewed 16.4k times · Source

I am trying to duplicate a table row in Word, using VBA, without using the Selection object or the clipboard. That is, I want a new row that has the same content as an existing row.

To do this, I first create a new (empty) row, and loop through each cell in the source row and copy its contents into the corresponding cell in the target row.

To copy each cell, I get a Range object that references the entire content of the source cell, and an equivalent Range for the target cell, and then do this:

oToRange.FormattedText = oFromRange.FormattedText

This works well on Office 2003, and also works most of the time on Office 2010. However, I am having a real problem with one particular scenario. I have (greatly) simplified that scenario to demonstrate the core of the problem.

In the picture below, there are two cells in the outer (grey) 2R x 1C table. The second row is the row to be copied. The first row is the new row I created, and into which I want to copy the content of the second row.

enter image description here

You'll notice that the second row contains a nested table.

When I run the code below in Word 2003, it works perfectly, and I get the following result:

enter image description here

But, in Word 2010, the same code produces this result:

enter image description here

As you can see, the cell content has been inserted before (and outside) the target table cell.

It's worth mentioning that if I put something after the nested table, so that it's no longer the last thing in the source cell, then this problem does not occur.

Here's the full VBA code I'm using:

Dim oDoc As Word.Document
Set oDoc = ThisDocument

Dim oFromRange As Range
Set oFromRange = ThisDocument.Tables(1).Cell(2, 1).Range
oFromRange.End = oFromRange.End - 1

Dim oToRange As Range
Set oToRange = ThisDocument.Tables(1).Cell(1, 1).Range
oToRange.End = oToRange.End - 1

oToRange.FormattedText = oFromRange.FormattedText

NOTE: the adjustment to the end of the source and target ranges is necessary because Cell.Range includes the end-of-cell marker, and I don't want to copy that.

What can I do to persuade it to put the content inside the target cell (like Word 2003 does), rather than before it?

Answer

Siddharth Rout picture Siddharth Rout · Sep 12, 2013

Hope I have understood your query correctly... Isn't this what you are trying to do? This code will copy Row 1 of the table and create a copy of that row below it.

Sub Sample()
    Dim tbl As Table

    Set tbl = ActiveDocument.Tables(1)

    tbl.Rows(1).Range.Copy
    tbl.Rows(1).Select
    Selection.InsertRowsBelow
    tbl.Rows(2).Range.Paste
End Sub

Screenshot

enter image description here

FOLLOWUP (From Comments)

This code doesn't use the Selection object

Sub Sample()
    Dim tbl As Table
    Dim rowNew As Row

    Set tbl = ActiveDocument.Tables(1)
    Set rowNew = tbl.Rows.Add(BeforeRow:=tbl.Rows(1))
    tbl.Rows(2).Range.Copy
    tbl.Rows(1).Range.Paste
End Sub

MORE FOLLOWUP (From Comments)

Sub Sample()
    Dim tbl As Table
    Dim rowNew As Row

    Set tbl = ActiveDocument.Tables(1)
    Set rowNew = tbl.Rows.Add(BeforeRow:=tbl.Rows(1))
    tbl.Rows(1).Range.FormattedText = tbl.Rows(2).Range.FormattedText
    '~~~> This is required as the above code inserts a blank row in between
    tbl.Rows(2).Delete
End Sub