Word Copying, Pasting and Deleting Columns with VBA - vba

I have a word document with tables throughout.
I have a macro that I use to copy values from cells in certain columns and paste them into other columns. Then the macro deletes several columns from the table.
Generally I use bookmarks for the copying and pasting.
The Bookmarks are all cells in a specific column, except the header.
So for example "Objectives" bookmark would span from row2 of column 2 of table5, until the end of column2. So if the user adds a row, that would also be included in the bookmark.
Here is an example below:
If ActiveDocument.Bookmarks.Exists("ProposedOverallObj") = True Then
ActiveDocument.Bookmarks.Item("ProposedOverallObj").Select
Selection.Cut
Selection.GoTo What:=wdGoToBookmark, Name:="Objectives"
With ActiveDocument.Bookmarks
.DefaultSorting = wdSortByName
.ShowHidden = False
End With
Selection.PasteAndFormat (wdPasteDefault)
End If
Dim Table1 As Table
Set Table1 = ThisDocument.Tables(5)
If Table1.Columns.Count >= 5 Then
With Table1
.Columns(5).Delete
.Columns(4).Delete
.Columns(3).Delete
End With
Else
MsgBox "Not enough columns!"
End If
and it goes on like this for about 13 tables. The first few tables work fine, then i start running into a weird error where randomly the line of text above my table gets copied into the table header and then my "delete columns" code breaks and tells me that one of the columns has already been deleted. (it hasn't).
Is there a better way to do this? Might this be happening because I am using .Select? I know it can be sketchy. Would it be better to assign IDs to my column ranges rather than using bookmarks and select? if so, could you provide me with a small example code for using Dim on a range in a table (my range will always start on row2 and go to the end of the column)?

Related

How to insert table in Word after another one with VBA?

I am trying to insert a table after another one with VBA in Word. I have a button, clicking on which should cause insertion of some new table (with borders, filled with words) five table rows under the button. I've tried some examples, like
Selection.MoveDown Unit:=wdLine, Count:=5
With ThisDocument
Set table1 = .Tables.Add(.Range(Start:=myInt, End:=myInt), 2, 7)
End With
table1.Rows(1).Cells(1).Range = "text"
table1.Borders.OutsideLineStyle = wdLineStyleSingle
table1.Borders.InsideLineStyle = wdLineStyleSingle
It makes table with borders, but it is being inserted at the beginning of the document and I need it five rows below the selected cell. I can't get how to specify myInt to place the table 5 rows below.
Maybe there is another way to do this.
Thank you!
Try
Set table1 = .Tables.Add(Selection.Range, 2, 7)
But you would be much better served by avoiding the use of Selection if you can.

VBA Word Changing table row and column size in

nested table in WordI have a template which is essentially a 4-row column in Work. Each cell marked with a bookmark. I've copied a table from Excel to Word into one of these bookmarks (inside on of the cells). Now I'm trying to format this 'nested table' to make it fit according to my desired column widths (for certain columns) but I'm really struggling with the syntax. Additionally, in the table, the first row contains some merged cells (Some are merged to the cell in the adjacent column and some in the row below).
The code I was trying:
With wd.Tables(2)
.Columns(2).Width = 20
End With
But I keep getting "Run-time error '5941': The requested member of the collection does not exist." Does this mean I am not indexing it properly?
Tabels(2) is meant to refer to the 'nested table' within the larger single column of 4 rows cells.
How do index it properly/find its index?
And how would I change the widths when I have merged cells?
Would I need to:
divide them first>adjust width>re-merge?
Also, I'm doing this in VBA Word, if I reference 'Microsoft Word xx.0 Object Library' in excel VBA can I do this in excel?
I have recreated a nested table like the one in the screen shot; i.e. 1 column with 4 rows, then a nested 14 column/10 row table in row 3.
The following code works just fine for me:
Sub AccessNestedTable()
Dim tbl As Table, tbl2 As Table
Dim wd As Document
Set wd = ActiveDocument
Set tbl = wd.Tables(1)
Set tbl2 = tbl.Tables(1)
With tbl2
.Columns.Width = 20
End With
End Sub

VBA code to merge two cells together

My scenario is a document with one two-column table. I am reading from a database and populating each row/column, but for some records, I want to merge the two columns into one cell and populate that as a row, then after that, continue the two column scenario. I want to issue a VBA statement to merge the two cells together to make one cell across the entire row. This is impossible to "record" as a new macro. I don't know what the row number is at run time, I only know the column numbers. My search string is: '"Word 2013" VBA table merge cells' but I get a lot of site that show you how to do it manually, not with VBA code.
My current code:
With ActiveDocument.Tables(1)
.Cell(Row:=1, Column:=1).merge _
MergeTo:=.Cell(Row:=1, Column:=2)
.Borders.Enable = True
End With
In the document, I have a small table of one row and two columns. But I should be able to have a table of three rows with any mixture of columns, right? I just want to pick any two columns and merge them together to make one space, but at run-time I do not know what row number to provide.
I finally got this worked out, and I want to again thank you for your help. Here is my current code. The entire document is one two-column table, skinny, and includes hyperlinks so that it can be read and navigated on an iPhone. When a Unit value changes in the data, I want to 1) insert a new row below and merge it into one column, add a 'Go Home' link, then continue adding two-column rows.
The document is finally converted to a .PDF and accessed by iOS users.
'Add a row for a 'back to home' link
If (intUnitOrder > intCurrentUnit) Then
Selection.InsertRowsBelow (1)
rowno = Selection.Information(wdEndOfRangeRowNumber) - 1
With ActiveDocument.Tables(1)
.Cell(Row:=rowno, Column:=1).Merge MergeTo:=.Cell(Row:=rowno, _
Column:=2)
End With
Selection.Tables(1).Rows(rowno).Range.ParagraphFormat. _
Alignment = wdAlignParagraphRight
Selection.Shading.BackgroundPatternColor = RGB(230, 230, 230)
Selection.Font.ColorIndex = wdBlue
Selection.Font.Italic = True
ActiveDocument.Hyperlinks.Add Anchor:=Selection.Range, _
Address:="#Home", SubAddress:="", _
ScreenTip:="Go back to the top", _
TextToDisplay:="back to Home"
Selection.MoveDown wdLine, 1
intCurrentUnit = intUnitOrder
End If

Removing a row in a table if it doesn't contain keyword

Right now I have a really long table in a Word doc which I populated from an Excel worksheet. It has 6 columns and I'm trying to code something in Word VBA that will go through all the rows in the table and delete the entire row if the cell in the first column DOES NOT start with an equal sign ("=").
For example, I'm only trying to keep the rows that has texts like,
"=1+S -03F7", "=1+M -06M1", etc. etc.
How would I code this? I can't give the code anything specific to look for since the parts after the equal sign will be different for every row.
So this wouldn't work, right?:
If Not ActiveDocument.Tables(83).Columns(1).Range.Text = "=" Then
EntireRow.Select
Selection.Delete
I guess I should reference to cells in column 1, not the column itself... Also, it doesn't work because it's only looking for things with just the equal sign... And I don't know how I can get it to select the row if it find the cell without the equal sign. I don't know how to match by case in the cell of the first column.
You can loop through the rows in the table using the Rows property. You can then find the first cell in that Row using the Cells property. You can then check just the first character of the Range:
Sub DeleteUnwantedRows()
Dim t As Table
Dim r As Row
Set t = ActiveDocument.Tables(1)
For Each r In t.Rows
If r.Cells(1).Range.Characters(1) <> "=" Then r.Delete
Next r
End Sub

Deleting columns from a table with merged cells

I'm trying to delete columns from a table which has horizontally merged cells
Selection.MoveEnd Unit:=WdUnits.wdCell, Count:=3
Selection.Columns.Delete
Eventhough columns are getting deleted, merged cells are removed in the process leaving a broken table.
Almost similar approach to delete rows works fine as explained in this answer
Workaround
I'm doing something like this as work around
Selection.MoveEnd Unit:=WdUnits.wdCell, Count:=3
Selection.MoveDown Unit:=WdUnits.wdLine, Count:=2, Extend:=wdExtend
Selection.Cells.Delete
Then setting width of Cell at index 1,2 to rest of the table rows. This way you can avoid merged cell getting deleted.
Word tables are not always intuitive. If a cell spans a column that is to be deleted, then the ENTIRE spanned cell will always be deleted, as you have shown.
When I'm NOT using VBA, I always unmerge cells before deleting rows or columns; otherwise Word's behavior is hard to predict.
Using VBA I would suggest the following:
'splits the header row of the current table into 7 cells
Selection.tables(1).cell(1,2).split numrows:=1, numcolumns:=7
'your code to delete columns
Selection.MoveEnd Unit:=WdUnits.wdCell, Count:=3
Selection.Columns.Delete
'merge the header row back into one span
ActiveDocument.Range( _
start:= Selection.tables(1).cell(1,2).range.start, _
end := Selection.tables(1).cell(1,5).range.end _
).cells.Merge
or for a more general approach, to delete n columns:
width = Selection.tables(1).columns.count - 1
Selection.tables(1).cell(1,2).split numrows:=1, _
numcolumns:= width - 1
Selection.MoveEnd Unit:=WdUnits.wdCell, Count:= n
Selection.Columns.Delete
ActiveDocument.Range( _
start:= Selection.tables(1).cell(1,2).range.start, _
end := Selection.tables(1).cell(1,width-n-1).range.end _
).cells.Merge
This should do it
Sub DeleteCols()
Dim Col2Delete As Range
Set Col2Delete = Selection.EntireColumn
Col2Delete.Delete
End Sub
First of all, we must look at the table not as rows/columns, but as indexed cells. (fig.1)
Now, we should select a range that starts from second cell and end to the last cell.
Finally, delete selection columns
Set Rng = Tbl.Range.Cells(2).Range
Rng.End = Tbl.Range.Cells(Tbl.Range.Cells.Count).Range.End
Rng.Select
Selection.Columns.Delete