Adding comments through VBA in Word includes page number field - vba

I have a procedure that adds a comment balloon into my Word document, but I have noticed that it also adds a page number field (evident by selecting the comment balloon and selecting update field from the context menu). This only happens when the comment is added through VBA, not when I create comments manually. Is there a way that I can inhibit the page number from being added to the comment?
Code extract below:
With Selection.Find
.Text = "Approvals"
.Forward = True
.Execute
If .Found = True Then
Selection.Comments.Add Range:=Selection.Range, Text:="My comment text"
End If
End With

Here's what I used to delete those page fields. After running the bulk of the code, just before End Sub I insert the following:
For Each f In ActiveDocument.StoryRanges(wdCommentsStory).Fields
If f.Type = wdFieldPage Then
f.Delete
End If
Next
It may not be pretty, but it does the job. Unfortunately, I don't think there's a way to filter based on, say, comment author.
For Each c In ActiveDocument.Comments
If c.Author = "Macro Name" Then 'Assuming you set it when you created the comment
Debug.Print c.Range.Fields.Count 'This prints a 0
End If
Next

In case you set field codes in comments, this is a bit more selective in what it deletes. This is designed to run just after you add a particular comment. However, you can combine something similar with the above to work on all comments.
If comment.range.fields.count > 0 Then
If comment.range.fields.Item(1).Type = wdFieldPage Then
comment.range.fields.Item(1).Delete
End If
End If

Related

Finding by style and selecting next table

I've been tasked with writing VBA code to automate Word. I have no idea about VBA.
What is needed:
There is a standard Word document based on a template, which has a section for writing issues. Each section has a heading, and below the heading there is a table with a couple of rows.
Sections view
The overall document layout with the different sections.
Issue view
A standard issue, with a Heading for the issue title, then a table to be filled, and then a description.
How do I write a macro that will:
Review ALL the issues in the document to see if the issue has a list of "Affected Hosts" in the table below the heading that contains more than 10 hosts
If this is not the case, ignore and move on to the next one.
If this is the case, that list should be replaced with some generic text such as "See Appendix G", and then add to that Appendix G the issue title and below it the list of all those hosts.
Where I am at:
I looked for examples of code snippets, looked at the documentation, etc. This is all I have:
Sub TidyAffectedSystems()
'
' TidyAffectedSystems Macro
'
'
' Loop over all issues by finding the appropriate style (IssueHeading)
With ActiveDocument.Range
With .Find
.ClearFormatting
.Forward = True
.Format = True
.Style = "Issue Heading" ' Heading style to find
.Wrap = wdFindStop
.Execute
End With
Do While .Find.Found
MsgBox .Text
' If it is the last one, then finish looping over
If .End = ActiveDocument.Range.End Then Exit Do
.Collapse wdCollapseEnd
.Find.Execute
Loop
End With
End Sub
This code tries to find the headings based on the style ("Issue Heading"), and then print that heading. I'm doing this to make sure that at least I am finding the right sections, but that's it.
I don't know how to for example select the table below the current found item to then see if that table has more than 10 hosts and all that, and of course no idea how to then replace, take it to an Appendix and repeat.

Mutually excluding checkboxes in Word table

I created a Word Document (Word 2016) that, by clicking a button, generates a Table with predefined text and formatting.
Column1
Column2
Column3
QUESTION (Y/N)
YES_Checkbox
No_Checkbox
Row number 8 (shown above) contains a YES/NO question; to manage that, I inserted two Checkboxes (one in Column2, the other in Column3) using the following syntax:
For ii = 2 To 3
Set rng = mytable.Cell(8, ii).Range
rng.Select
With Selection
.Collapse Direction:=wdCollapseStart
.Range.ContentControls.Add wdContentControlCheckBox
.MoveRight Unit:=wdCharacter, Count:=2
End With
Next ii
My idea is to have mutually exclusive checkboxes: that means, if User selects "YES" the "NO" is automatically deselected (and vice-versa). To do so, I created a Sub within the main button script. It checks for the checkbox value and then tries to 'tick it' (on un-tick it) using the following code (not yet completed):
Sub Check_YES_Not(tblNew)
Dim thisCell As Range
check1 = mytable.Cell(8, 2).Range.ContentControls(1).Checked
check2 = mytable.Cell(8, 3).Range.ContentControls(1).Checked
'If condition to be added
check1 = True 'This is how I am trying to modify the checkbox, but it is not working
'ElseIf add other conditions...
'Msgbox "to be completed..."
'End If
End Sub
Code runs and creates the table correctly, but the checkbox scripts is not behaving as I wish. Could someone please tell me what I am doing wrong and how I could make it work? Thank you very much.
UPDATE
This is how I solved it. There are still minor concerns (e.g. if I click "Yes", I need to select another cell before clicking "No", otherwise the control is not able to work correctly). Apart from this, many thanks to #macropod and Timothy for their kind support.
In order to allow the User to create additional table, I created a Public counter that is increased at each added table. It is not an elegant solution, but it works for now. The initial table has a different tag (I did not include it here).
Private Sub Document_ContentControlOnExit(ByVal oCC As ContentControl, Cancel As Boolean)
Dim collCCs As ContentControls
Dim oCCTarget As ContentControl
Dim ii As Integer
For ii = 1 To 500 'Additional tables
If Not IsEmpty(ActiveDocument.SelectContentControlsByTag("NO" + Str(ii))) Then
Select Case oCC.Tag
Case "YES" + Str(ii)
Set collCCs = ActiveDocument.SelectContentControlsByTag("NO" + Str(ii))
For Each oCCTarget In collCCs
If oCCTarget.Checked = True Then
oCCTarget.Checked = False
Exit For
End If
Next
Case "NO" + Str(ii)
Set collCCs = ActiveDocument.SelectContentControlsByTag("YES" + Str(ii))
For Each oCCTarget In collCCs
If oCCTarget.Checked = True Then
oCCTarget.Checked = False
Exit For
End If
Next
End Select
End If
Next ii
Your code isn't working as you are only setting the value of a variable, not the checked status of the checkbox. The simplest way of achieving your desired result is to set the checked status of one checkbox to the opposite of the other, like this:
mytable.Cell(8, 2).Range.ContentControls(1).Checked = Not mytable.Cell(8, 3).Range.ContentControls(1).Checked
Also your code to insert the content controls can be simplified to:
For ii = 2 To 3
mytable.Cell(8, ii).Range.ContentControls.Add wdContentControlCheckBox
Next ii
There is rarely any need to select anything when working with Word.
Finally, you appear not to be forcing variable declaration. This can lead to avoidable errors in your code. Just add Option Explicit at the top of every code module. This will prevent your code from compiling when you have undeclared variables. To add this automatically to new modules open the VBE and go to Tools | Options. In the Options dialog ensure that "Require Variable Declaration" is checked.

VBA - error handling for deleted checkboxes

I am working in MS Word 2013 and attempting to programatically delete rows in a table when Checkbox1 through CheckboxN is unchecked through use of a command button. The following abbreviated code works once (and can delete one or more rows) but breaks when run a second since the code still makes references to checkboxes that have been deleted. I have tried basic error handling but have been unsuccessful. Can anyone provide assistance so the code can be run multiple times and delete subsequent rows/checkboxes? If this is not the right forum to post this request, please let me know. Thank you!
Sub CommandButton1_Click()
If CheckBox1.Value = False Then
Selection.GoTo What:=wdGoToBookmark, Name:="Row6"
Selection.Rows.Delete
End If
If CheckBoxN.Value = False Then
Selection.GoTo What:=wdGoToBookmark, Name:="Row6"
Selection.Rows.Delete
End If
End sub
So, I'd probably take a different approach here. Rather than relying on named checkboxes, cycle backwards through all relevant checkboxes and determine the row to delete. I'm assuming that the checkboxes are in a cell within the row to be deleted. It's important to go backwards because, as you've noted, you'll be removing items as you go.
Sub checkChecks()
Dim objTable As Table
Dim objCC As ContentControl
Dim i As Long
Set objTable = ActiveDocument.Tables(1)
For i = objTable.Range.ContentControls.Count To 1 Step -1
Set objCC = objTable.Range.ContentControls(i)
If objCC.Type = wdContentControlCheckBox Then
If objCC.Checked = False Then objCC.Range.Rows(1).Delete
End If
Next i
End Sub
Obviously this only works if you can isolate the table in question, but that shouldn't be too hard.

Hide Text in between headers MS word 2007

I have a document that is roughly 200 pages and is essentially a list of test procedures for a specific software. Now this document has certain parts to it the pertain to different versions of the software and these parts are mixed in so their not nicely formatted in a specific order. What I would like to do is Be able to hide the parts of the document that are not needed when testing a different version. I know MS word has a font option to hide text but I would like to be able to setup up a button/hypertext link/macro that will easily hide the unneeded sections. Is this possible and how would I do it? I've started experimenting with VBA script to design my own macro but have only found a way to hide one part per shortcut hit. Is there a way to do this so all parts are effected simultaneously?
EDIT:
The document is organized like this
Version 1
Test Option button
/
Version 2
Test Option button
Check that Sample button is disabled
/
Version 1
Test Save button
/
Version 3
Test Save to USB button
/
So as you can see it's completely unorganized the code I currently have for one macro really doesn't work because instead of selecting between the two point I specify it selects the whole document.
Sub TextSelectTest()
'
' TextSelectTest Macro
' Base Test
'
With Selection.Find
.Text = "Version1"
.Forward = False
.MatchWildcards = False
.Wrap = wdFindStop
.Execute
End With
Selection.Extend
With Selection.Find
.Text = "/"
.Forward = True
.Execute
.Text = ""
End With
Selection.Extend
With Selection.Font
.Hidden = True
End With
End Sub
I don't think hiding font is most professional solution as the result is visible only for printing. But that could be the easiest in this situation especially you suggested it.
First step: set sections in your documents. It's quite easy and should be done ones in Word app. You will need to insert as many section separation marks as many parts of the document you need to manage. We will need to know which section should be/shouldn't be part of each Manual but I'll back to that later.
Second steps: Than you will need the following subroutine which will 'hide' all sections and than show appropriate ones:
Sub HideUnhide_Document_Section(secIndex As Variant)
Dim Doc As Document
Set Doc = ActiveDocument
Dim secDoc As Variant
'to hide all section first, by iteration
For Each secDoc In Doc.Sections
secDoc.Range.Font.Hidden = True
Next secDoc
'alternatively we could hide whole content without iteration:
'secDoc.Content.Font.Hidden = True
'to un-hide chosen sections
For Each secDoc In secIndex
Doc.Sections(secDoc).Range.Font.Hidden = False
Next secDoc
End Sub
And to manage your hiding process I would propose the following code:
Sub Call_Hide()
Dim arrVersion1 As Variant
'put all sections for appropriate version
arrVersion1 = Array(1, 3)
'to unhide
HideUnhide_Document_Section arrVersion1
End Sub
You could either prepare similar separate subroutine for each version or parametrize that one. It that second situation it will have to have separate arrays (arrVarsionX) for each Version of your manuals.

Word VBA Section break character in

How can you detect if the selection you have contains or is the section break character?
At the moment I select a page , collapse to the end , I want to know if the end of the page contains a section break or not.
I was going to use a method where I compare the section number at the end of the page , then move two characters forward , then check the section number. If they are different then the end of my page does have a section break - is there a better way to do it?
Perhaps something on these lines:
Function HasBreak() As Boolean
With Selection.Find
.Forward = True
.Execute FindText:="^b"
If .Found Then
HasBreak = True
End If
End With
End Function
Cheers that's a good suggestion.
The way I did it in the end was get the range of the page and section , check both "End" positions , if they were the same then the page contained the section break.