PDA

View Full Version : [SOLVED:] Number of pages in section



crowfan
05-17-2007, 11:53 AM
Hello,

I am new to VBA coding and even newer to these forums. :hi:

I have a Word document (Word 2003) with multiple sections. Each section is multiple pages.

What I would like to do is to write a macro that would do the following. I would like it to work when run from anywhere in that section.

1. move the cursor to the end of the section
2. count the number of pages in the section
3. If the number of pages is even, add a page; if it is odd, do not add a page.
4. add a section break (odd page)


Currently I have only step 4 working, and I have to manually place the cursor at the end of the section before I run it.

Bit I can't get 1-3 to work. My main problem is that I cannot find any function that will count the pages in the section. I feel like it is possible, because that information is displayed in the lower-left corner of the Word window. All I can find is a page count for the entire document.

What can I do?

Thanks!

mdmackillop
05-17-2007, 03:42 PM
Hi Crowfan,
Welcome to VBAX
This needs a bit more work, but no more time just now

Option Explicit
Sub Breaks()
Dim Sect As Long
Dim Pgs As Long
Dim Rng As Range
With ActiveDocument
'Get the number opf the current section
Sect = Selection.Information(wdActiveEndSectionNumber)
'Get pages from start to end of current and previous sections. Subtract for page count.
Pgs = .Sections(Sect).Range.Information(3) - .Sections(Sect - 1).Range.Information(3)
MsgBox Pgs
'If pages/2 0 then even number so do process
If Pgs Mod 2 = 0 Then
'With the section
Set Rng = .Sections(Sect).Range
'Go to the end of the section
Rng.Collapse (wdCollapseEnd)
'Insert selection point
Rng.Select
With Selection
' Go up one line
.MoveUp Unit:=wdLine, Count:=1
'Delete Pilcrow and Section Break
.Delete Unit:=wdCharacter, Count:=2
'Insert page break to make odd number of pages in the section
.InsertBreak Type:=wdPageBreak
'Insert OddPage section break
.InsertBreak Type:=wdSectionBreakOddPage
End With
End If
'For checking - next 3 lines can be deleted
Sect = Selection.Information(wdActiveEndSectionNumber)
Pgs = .Sections(Sect).Range.Information(3) - .Sections(Sect - 1).Range.Information(3)
MsgBox Pgs
End With
End Sub

crowfan
05-18-2007, 06:43 AM
Actually, that seems to work beautifully. Thank you!

I can't claim to fully understand what's happening in the macro, but it works. I'm off to research how it works and try to understand what is going on with it.

Thanks!

lucas
05-18-2007, 07:02 AM
I thought you gave up on Word Malcolm.....

mdmackillop
05-18-2007, 08:07 AM
I thought you gave up on Word Malcolm.....
I've never given up, but I've never quite got the hang of it in the same way as Excel. Probably because I find less coding is required at work. Once a document is set up, that's it! I'll keep trying with the interesting questions here that teach me something (along with the simple ones of course)

mdmackillop
05-18-2007, 08:14 AM
Hi Crowfan,
I've added some notes to my previous post.

lucas
05-18-2007, 08:15 AM
I'm still following your posts, learning something each time...learning from my own mistakes mostly...

I agree that word is a different animal...seems less intuitive than excel with a lot of Word specific nuances that are confusing. As you said, if we used Word more we would probably understand it better.

crowfan
05-18-2007, 08:51 AM
Hi Crowfan,
I've added some notes to my previous post.Thank you for adding those notes. They help.

I guess I am confused about a couple of things. I don't understand how the page number is calculated. It looks to me like the code is counting the number of pages in the whole document and then subtracting the number of pages in the previous section? I know this can't be right. What info exactly is Information(3) pulling?

Thanks for your help with this. I am still new at VBA. I've learned a lot recently and I am making strides, but some stuff still boggles my mind a little.

mdmackillop
05-18-2007, 09:42 AM
Information(3) uses the integer value of Information(wdActiveEndPageNumber); (which I copied from Help)
I'm not sure if you need the extra page breaks if BreakOddPage is used.
This code tidies up and removes the Selection procedures.

Option Explicit
Sub Breaks()
Dim Sect As Long
Dim Pgs As Long
Dim Rng As Range
With ActiveDocument
'Get the number opf the current section
Sect = Selection.Information(wdActiveEndSectionNumber)
'Get pages from start to end of current and previous sections. Subtract for page count.
Pgs = .Sections(Sect).Range.Information(wdActiveEndPageNumber) - _
.Sections(Sect - 1).Range.Information(wdActiveEndPageNumber)
'If pages/2 = 0 then even number, so do process
If Pgs Mod 2 = 0 Then
'Get the section
Set Rng = .Sections(Sect).Range
With Rng
'Go to the end of the section
.Collapse (wdCollapseEnd)
'Delete the existing section break
Rng.SetRange Start:=Rng.Start, End:=Rng.Start - 1
.Delete
'insert a page break
.InsertBreak Type:=wdPageBreak
'Add an OddPage break
.InsertBreak Type:=wdSectionBreakOddPage
End With
End If
End With
End Sub

crowfan
05-18-2007, 10:26 AM
Ah, OK, now that I understand what Information(3) is pulling, the macro makes much more sense to me now.

Thank you so much for your help and patience!

fumei
05-18-2007, 01:37 PM
Just because I like to bug Malcolm....an alternative.

Sub Breaks()
Dim Sect As Long
Dim Pgs As Long
Dim Rng As Range
With ActiveDocument
'Get the number of the current section
Sect = Selection.Range.Sections.Item(1).Index
' set Range
Set Rng = .Sections(Sect).Range
' resize to NOT include Section break
Rng.MoveEnd Unit:=wdCharacter, Count:=-1
' get number of pages
Pgs = Rng.ComputeStatistics(wdStatisticPages)
'If pages/2 = 0 then even number, so do process
If Pgs Mod 2 = 0 Then
With Rng
'Go to the end of the section
.Collapse (wdCollapseEnd)
'Delete the existing section break
.SetRange Start:=Rng.End, End:=Rng.End + 1
.Delete
'insert a page break
.InsertBreak Type:=wdPageBreak
'Add an OddPage break
.InsertBreak Type:=wdSectionBreakOddPage
End With
End If
End With
End Sub

fumei
05-18-2007, 01:48 PM
The important thing about using ComputeStatistics on a Range of a Section is that setting a Range includes the following Section break. Therefore, unless you back the End up, the number of pages will off by +1.

You could of course get the value and subtract 1...except if the Range made of the Section does NOT include a section break...then the value is, in fact, correct. This would occur for the last section of a document.

The main advantage of using the actual Range compute statistics, is of course, that you do not have calculate values from TWO sections (the current one, and the one previous).

I would further point out that if Malcolm's code is executed on Section 1, then:

Pgs = .Sections(Sect).Range.Information(wdActiveEndPageNumber) - _
.Sections(Sect - 1).Range.Information(wdActiveEndPageNumber)

will abort the procedure with a fatal error. The dreaded Error 5941: The requested member of the collection does not exist.

Sect = 1, so .Sections(Sect - 1) - Section(0) does not exist.

fumei
05-18-2007, 01:54 PM
Oh, FYI: the Range of a Section includes the following Section break (if there is one) because it is the trailing Section break that defines the Section.

It is the section break AFTER a Section that holds the values/information about that Section.

mdmackillop
05-18-2007, 02:23 PM
Thanks for that Gerry,
I'd not come across ComputeStatistics. You know, in Excel, there is a lot you can do from the Help file examples etc. In Word they leave a lot to be desired.
Keep on Bugging :bug:

fumei
05-20-2007, 12:59 PM
There is lot to be gained from the Help files in Word, but yes, I agree that they do leave a lot to be desired.

It may be worth your while to do some experimenting, comparing ComputeStatistics and Information. There can be differences.

Generally, ComputeStatistics is more accurate. I think it is because it forces Word to actually compute. I am not sure. Information may be a stored value.

In the example above, I think it is preferable for the reason I stated. It obtains a value from ONE object, rather than calculating TWO values from two.

The second reason is that it is a property of Range and Document. You can not use ComputeStatistics with Selection. And it has handy returnable values.

wdCharactersWithSpaces
wdCharacters
wdWords

Between these three you can deduce a lot of information about a string (set as a Range of course), and play with it.

Say you have a string, part of a paragraph, selected. True, you can use InStr, Mid, Left, Right etc. etc. on Selection.Text to get information. However, using some of those WITH ComputeStatistics can be very useful. I keep some ComputeStatistics values as Functions.

Public Function NumSpaces(r As Range) As Long
NumSpaces = r.ComputeStatistics(wdStatisticCharactersWithSpaces) - _
r.ComputeStatistics(wdStatisticCharacters)
End Function

Public Function NumWords(r As Range) As Long
NumWords = r.ComputeStatistics(wdStatisticWords)
End Function

As to values, check this out.

"This is some text." This is ended with a paragraph mark. FOUR words...or so you think.


Sub TestCrap()
Dim r As Range
Dim SelectionData As Long
Set r = Selection.Range
SelectionData = Selection.Range.Words.Count
MsgBox NumWords(r) & " " & SelectionData
End Sub

1. Select it the text, including the paragraph mark. Result: 4 6

ComputeStatistics is "correct".
Selection.Range.Words.Count is "wrong".

2. Select the text, without the paragraph mark. Result: 4 5

ComputeStatistics is "correct".
Selection.Range.Words.Count is "wrong".

Selection.Range.Words.Count includes in its count, the period at the end, AND the paragraph mark as "words". ComputeStatistics does not...except...

"." with a paragraph mark.

Select it, including the paragraph mark. Result: 1 2

Both ComputeStatistics, Range.Words.Count are "wrong"

Select just the period. Result: 1 1

In this case ComputeStatisics will count the period as a word. "Word" in ComputeStatistics is any character(s) with either leading or trailing space.

"This is some text [space] ." will count as 5 words, because the period has a leading space.

You know how you can sometimes get documents with extra spaces after a period? True, they do not show on printing. Yet, they bug me. Using the count of CharactersWithSpaces, Characters, and Words (with ComputeStatistcis) I can loop through and detect and remove those spaces.

There, if THAT does not show how fussy and crazed I am, nothing will.