Word VBA detect blank pages after odd/even section break - vba

I'm new here so be gentle... lol
I've made a document and have separated it into chapters (sections) and am numbering the pages of each section as follows
1-1 of 9
2-1 of 6
etc
I'm using odd page breaks to put the first page of my sections in my place of preference. Of course using odd/even page breaks will under the right circumstances result in a non-printing blank page at the end of the section which of course is exactly what is supposed to happen. The problem is that in those cases my page numbers end up as for example, 2-1 of 13 but 13 is a non printing blank page and so the last printing page is 2-12 of 13. I've tried .goto to that page but apparently it won't allow you to .goto that page. I pared down my code to just outputting the number of pages to a msgbox to prevent any ancillary nonsense from getting in the way of the point. Here it is:
Dim i, x
Dim FooterPages As Integer
Dim Sect As Integer
With ActiveDocument
For i = 1 To 10
'Footer page numbers
ActiveDocument.ActiveWindow.Selection.GoTo What:=wdGoToSection, Count:=i + 2
Sect = .ActiveWindow.Selection.Information(wdActiveEndSectionNumber)
FooterPages = .Sections(Sect).Range.Information(3) - .Sections(Sect - 1).Range.Information(3)
MsgBox FooterPages
Next i
End With
I would really appreciate some help with a bit of code to detect that last page so I can subtract it from the total page count of that section.
Thanks in advance

Related

Get table values from certain section in word VBA

I have a large word document that has several tables in several different sections. Something that looks like the following:
Section 1
Section 1.1 (has table)
Section 1.2
Section 1.2.1 (has table)
Section 2
Section 2.1 (has table)
Section 2.1.1 (has table)
Section 2.2
Section 3 (has table)
However, I only want the tables in one section. Is there a way to create a loop that can get the data from all the tables only in a certain section?
I was thinking about using something like ActiveDocument.TablesOfContents(1), but I think I'll need more than that. Is there a way to constantly check which section you're in? Maybe some pseudocode like...
'Starting at the top of the document
'This would not start until the document found Section 2, and would end once it found section 3
While [ActiveDocument.TablesOfContents("name")]
'Which would include 2.1, 2.1.1, and 2.2 because they are a part of 2
TableCount = ActiveDocument.Tables.Count 'But only header 2
For tableNum = 1 To TableCount
' do something/get data
Next tableNum
Wend
The first thing you need to do is find the Heading 1 styled paragraph that marks the start of the range you want to look in. You can then use the document’s GoTo method to go to the predefined bookmark that will give you the entire range of the heading level, starting at the Heading 1 para and extending to the next Heading 1 para.
You can then access the Tables collection of that Range
Don’t have access to a PC right now to give you the code, but there are numerous examples here on SO, for example Word VBA: How to delete sections of text from a template document using a heading (purely conicidental that it is one of mine!)

Microsoft Word Page Numbering Part-Section-Page

I have a long document with about 9 Parts and each part contains 2 - 5 sections. I want to have my page numbers read Part-Section-Page. For example, page 5 of section 4 in part 3 would have the page number 3-4-5.
Using this field code I can output this correct page number in my footer
{STYLEREF 1 \s}-{STYLEREF 2 \s}-{PAGE}
This works because the first field code outputs the current Part, signified by Header 1, the 2nd code outputs the section number signified by Header 2, and then last output is the page which I can control with section breaks.
BUT - This is no help with the Table of Contents! When the ToC is generated, Word only recognizes {PAGE} as the page number, and therefore I need to manually write the ToC.
Is there any way to make the page number actually be in the format x-y-x?
Any ideas or help would be appreciated!

Need help placing table at beginning of page

I am placing tables into a Word document. The number of rows in a table may vary but the row height is fixed so I know the maximum number of rows that can fit on a single page. When I reach that max number, I want to add a new page to the document and then insert a new table on it. Sounds simple but I'm running into all sorts of weird results.
Result #1: I have tried using both "Selection.InsertNewPage" and "Selection.InsertBreak(wdPageBreak)". When I do this, 2 pages are added instead of 1.
NumberOfPages = SectionObject.Range.Information(wdNumberOfPagesInDocument)
TableLocation = TableObject.Range 'get the range object of the current table
TableLocation.Collapse(WdCollapseDirection.wdCollapseEnd) 'go to end of table
TableLocation.Select()
WordDocument.Application.Selection.InsertBreak(WdBreakType.wdPageBreak) 'adds 2 pages instead of 1
NumberOfPagesNew = SectionObject.Range.Information(wdNumberOfPagesInDocument)
To try to make this work I wrote this code (it doesn't work)
If NumberOfPagesNew > NumberOfPages + 1 Then
TableLocation = WordDocument.Range.GoTo(wdGoToPage, wdGoToAbsolute, NumberOfPagesNew) 'go to last page of doc
TableLocation.Delete() 'delete that page
TableLocation = WordDocument.Range.GoTo(wdGoToPage, wdGoToAbsolute, NumberOfPagesNew - 1) 'go to new last page
TableLocation.Collapse(WdCollapseDirection.wdCollapseStart) 'move cursor to start of page
End If
'I add a new table using this code
TableObject = WordDocument.Tables.Add(TableLocation, NumberOfRowsNeeded - 1, 5)
But instead of placing my table on the last page, another page gets added and my table is placed on it. The end result is a page with a table, a blank page, and then another page with a table.
Result #2: Another thing I tried was moving my cursor to the end of the table, adding a line break and then placing my table after that. This got around my problem of adding 2 pages instead of 1. However, it adds 2 lines onto the new page instead of 1 which throws off my row counting code. Below is the code I used.
TableLocation = TableObject.Range 'get range object of current table
TableLocation.Collapse(wdCollapseEnd) 'go to end of table
TableLocation.Select()
WordDocument.Application.Selection.InsertBreak(wdLineBreak) 'should add 1 line
TableLocation = WordDocument.Application.Selection.GoToNext(wdGoToLine)
TableLocation.Collapse(WdCollapseDirection.wdCollapseStart)
'I add my next table using this code.
TableObject = WordDocument.Tables.Add(TableLocation, NumberOfRowsNeeded - 1, 5)
This code places my table one line lower than it should.
I don't do a lot of Word coding and I know very little about the intricacies of the selection object so I am sure that is where my problem lies. If someone could show me a good way of accomplishing what I want to do, I would appreciate it.
Thanks in advance,
Darren
Try the following code. Make sure that the number of rows of the table allows it to fit on one page. If this does not work, try with one fewer row in the table, Word might need some extra spaces before / after the table depending on the active format.
Selection.EndKey Unit:=wdStory
ActiveDocument.Tables.Add Selection.Range, 5, 5
Selection.EndKey Unit:=wdStory
Selection.InsertBreak WdBreakType.wdPageBreak
Selection.EndKey Unit:=wdStory
ActiveDocument.Tables.Add Selection.Range, 5, 5
' ...
Of course, this is just to show you an approach that will work and avoids the difficulties that you experienced. You need to adapt the code to your specific task.

Word VBA: How to get the current section number

I'm building a macro that loops through each word of a document and checks via a regex whether it matches a pattern and if so, writes the found word to an excel sheet. It goes like this:
For Each sentence In ActiveDocument.StoryRanges
For Each w In sentence.Words
myWord = w
If TestRegExp(myPattern, myWord) Then
WKS.Cells(myCount, 1).Value = myWord
myCount = myCount + 1
End If
Next
Next
This part works fine. Now I would also like to get the section per found word (aka "in what section did the found word appear"). I found the command "selection.Information" but no matter what I try, I only get "Section = 1". Even if I just check the whole document for sections ("ActiveDocument.Sections.Count") I only get 1. So there must be something off with the sections, but this document definitely has sections. Has anybody an idea what I do wrong?
Page and section numbers in Word are difficult since the document's logical structure may not match the displayed text. I can, for example, reset page numbering in the middle of a document.
Similarly, a "section" to word is the separation of parts of the document by virtue of the insertion of a section break, whether next page, continuous, next odd, next even, etc. However, the reader often thinks of the "section" as the number that appears before a "heading 1" style paragraph. Again, I can reset those numbers mid-document. So, a document that has 3 sections (logical) might have only two headings: none in section 1, one in section 2 that says "1. Introduction", and another in section 3 that says "Appendix A. Glossary". The (logical) sections are still 1, 2, 3......
w = ActiveDocument.Sentences(10).Words(1) ' given some word in the document
MsgBox w.Information(wdActiveEndPageNumber) ' logical page number
MsgBox w.Information(wdActiveEndAdjustedPageNumber) ' displayed page number
MsgBox w.Information(wdActiveEndSectionNumber) ' logical section number
As for the displayed section number, which is there by virtue of being "Heading 1" style and that style having been set to a multi-level numbered format... getting the displayed number of that list item appears to be very difficult, in the general case.
Solutions I've seen involve searching for the previous paragraph that matches a heading style then getting the .ListFormat.ListString from that.
MsgBox w.GoTo(What:=wdGoToHeading, Which:=wdGoToPrevious).ListFormat.ListString
but that gets the previous heading of any level, not just "Heading 1".
Sections are different from StoryRanges, and are part of the StoryRanges(wdMainTextStory) range. You can use For loop instead of For Each loop to get the WdStoryType number:
For i = 1 To ActiveDocument.StoryRanges.Count ' or 1 To 17
For Each w In ActiveDocument.StoryRanges(i).Words
If TestRegExp(myPattern, w) Then
WKS.Cells(myCount, 1).Value = myWord
myCount = myCount + 1
Debug.Print i, myCount, w ' i has the WdStoryType number
End If
Next
Next
Also, RegExp is probably not needed, as Word has wildcard Find and Replace https://superuser.com/questions/86397/wildcards-in-word, and VBA has the Like Operator

Print certain pages only

I have the following code which works fine:
Application.PrintOut FileName:="", Copies:=2
This prints my 10 page document twice.
I now want to use the pages option to specify only certain pages to print out:
Application.PrintOut FileName:="", Copies:=2, Pages:="2, 6-10"
I was expecting it to print out pages 2 and 6 to 10 twice, i.e. 2,6,7,8,9,10,2,6,7,8,9,10, but instead it just printed all 10 pages twice.
I am using VBA in Word 2010.
Any idea what I'm doing wrong?
RESOURCES:
From Microsoft Developer Network:
Pages - Optional - Variant - The page numbers and page ranges to be
printed, separated by commas. For example, "2, 6-10" prints page 2 and
pages 6 through 10
Range:=wdPrintRangeOfPages needs to be added along with Pages.
For example:
Application.PrintOut FileName:="", Copies:=2, Range:=wdPrintRangeOfPages, Pages:="2,6-10"
Alternative solution from the website
expression .PrintOut(Background, Append, Range, OutputFileName, From,
To, Item, Copies, Pages, PageType, PrintToFile, Collate, FileName,
ActivePrinterMacGX, ManualDuplexPrint, PrintZoomColumn, PrintZoomRow,
PrintZoomPaperWidth, PrintZoomPaperHeight
You can use From:="2", To:="5".