PDA

View Full Version : Cycling through headings to find correct place in document



GenuineGin
05-24-2017, 03:40 AM
Hello!

I am working on some code to allow users to restructure a long, complex template document without having to go through and delete/insert each section by hand. I don't want to use bookmarks as in my experience these get removed by users all the time and completely break the whole document.

I've already got the code to cycle through the headings, find those that have not been selected for inclusion and remove these (and their content).

Now I'm trying to come up with code to do the following and simplify it as much as possible. I've provided an example to explain what I mean.

Document Structure
Section A
Section B
Section C
Section D

Code I want to create:
If Checkbox C value = true then
Cycle through headings to see if Section C heading exists
If it does - do nothing

If it doesn't - cycle through headings to see if Section B heading exists

If it does - insert autotext entry for Section C after
If it doesn't - cycle through headings to see if Section A heading exists

If it does - insert autotext entry for Section C after
If it doesn't - insert autotext entry for Section C at start

However, there are much more than four headings and any one of them could be added or removed, so the above approach is going to result in some very complicated code!

I was thinking I might be able to call some sort of function that would do the above for me and replace the red text in the code below with strings that could be defined based on the checkboxes which are selected? But this is way beyond my current skill set!

I'd be very grateful for any advice!

This is what I have so far:

Private Sub cmdStructure_Click()
'*********RESTRUCTURE REPORT************************
If chkNVCUndertaken.Value = False Then
Dim headStyle As Style
With ActiveDocument.Range
With Selection.Find
.ClearFormatting
.Replacement.ClearFormatting
.Format = True
.Forward = True
.Wrap = wdFindContinue
.MatchWholeWord = True
.Text = "National Vegetation Classification Survey"
.Style = "Heading 2"
.Replacement.Text = ""
.Execute

'do something with the heading
If ActiveDocument.Styles(Selection.Paragraphs(1).Style).ParagraphFormat.Outlin eLevel < wdOutlineLevelBodyText Then
Set headStyle = Selection.Paragraphs(Selection.Paragraphs.count).Style
Selection.Expand wdParagraph
Else: Exit Sub
End If
' Turns off screen updating so the the screen does not flicker.
Application.ScreenUpdating = False
' Loops through the paragraphs following your selection, and incorporates them into the selection as long as they have a higher outline level than the selected heading (which corresponds to a lower position in the document hierarchy). Exits the loop if there are no more paragraphs in the document.
Do While ActiveDocument.Styles(Selection.Paragraphs(Selection.Paragraphs.count).Next .Style).ParagraphFormat.OutlineLevel > headStyle.ParagraphFormat.OutlineLevel
Selection.MoveEnd wdParagraph
If Selection.Paragraphs(Selection.Paragraphs.count).Next Is Nothing Then Exit Do
Loop
Selection.Delete
' Turns screen updating back on.
Application.ScreenUpdating = True
End With
End With
ElseIf chkNVCUndertaken.Value = True Then
' Check if text already exists and if not then add
With ActiveDocument.Range
With Selection.Find
.ClearFormatting
.Replacement.ClearFormatting
.Format = True
.Forward = True
.Wrap = wdFindContinue
.MatchWholeWord = True
.Text = "National Vegetation Classification Survey"
.Style = "Heading 2"
.Replacement.Text = ""
.Execute
If Selection.Find.Execute Then
'Do nothing
Else
'Find correct place in document
With Selection.Find
.ClearFormatting
.Replacement.ClearFormatting
.Format = True
.Forward = True
.Wrap = wdFindContinue
.MatchWholeWord = True
.Text = "Field Survey"
.Style = "Heading 2"
.Replacement.Text = ""
.Execute
If Selection.Find.Execute Then
' Turns off screen updating so the the screen does not flicker.
Application.ScreenUpdating = False
' Loops through the paragraphs following your selection, and incorporates them into the selection as long as they have a higher outline level than the selected heading (which corresponds to a lower position in the document hierarchy). Exits the loop if there are no more paragraphs in the document.
Do While ActiveDocument.Styles(Selection.Paragraphs(Selection.Paragraphs.count).Next .Style).ParagraphFormat.OutlineLevel > headStyle.ParagraphFormat.OutlineLevel
Selection.MoveEnd wdParagraph
If Selection.Paragraphs(Selection.Paragraphs.count).Next Is Nothing Then Exit Do
Loop
Selection.Delete
' Turns screen updating back on.
Application.ScreenUpdating = True
End With
'Insert standard text
ActiveDocument.AttachedTemplate.AutoTextEntries("StandardMethodTextVegetation").Insert Where:=Selection.Range, RichText:=True
Else
'FIND NEXT SECTION HEADING UP

End If
End If
End Sub

gmayor
05-24-2017, 04:45 AM
If the various sections are already saved as autotext entries, wouldn't it make more sense to provide a userform for the user to select the structure of the document either by picking from a multiselect list box or perhaps check boxes and then build the required document from those selections?

GenuineGin
05-24-2017, 07:01 AM
That is how I envisage it, but it needs to be more dynamic than that, so the report can be restructured at any point during drafting and sections can be added and removed at any time. That's the aim anyway. I used to do this by bookmarking all the sections and adding/removing as necessary but people kept deleting the bookmarks so I'm trying to steer clear of them. Entering text at the cursor will also be quite fiddly and time consuming for the user, so I was hoping to position text using code.

GenuineGin
05-24-2017, 07:17 AM
This is my current userform:

19273

The code above applies to the checkboxes on the right hand side and is run when the OK button in that section is clicked.

I don't know if this helps at all...

gmayor
05-24-2017, 08:47 PM
If you use the following code to fill the bookmarks (or change the values in the bookmarks) the users will not delete the bookmarks, because there would be no need to edit the document directly.


Public Sub FillBM(strBMName As String, strValue As String)
'Graham Mayor - http://www.gmayor.com
Dim oRng As Range
With ActiveDocument
On Error GoTo lbl_Exit
Set oRng = .Bookmarks(strBMName).Range
oRng.Text = strValue
oRng.Bookmarks.Add strBMName
End With
lbl_Exit:
Set oRng = Nothing
Exit Sub
End Sub

For re-editing, recall the form, loop through the bookmark values from the document bookmarks and when an appropriate bookmark contains a value, check the check box on the form. Thus whenever the form is called it will reflect the current status of the document. All you then have to do is encourage the users to use the userform to edit the document which could be achieved by protecting the document as read only and unlocking the document to write to the bookmarls e.g.


Sub Macro1()
If Not ActiveDocument.ProtectionType = wdNoProtection Then
ActiveDocument.Unprotect
End If
FillBM "bm1", "Write this text to the bookmark bm1"
ActiveDocument.Protect wdAllowOnlyReading
End Sub