PDA

View Full Version : Detecting last page VBA



Zack
04-29-2012, 04:15 AM
What is the VBA command for printing the last page of the S1 document? I've seen on the web examples explaining how to print S1P6 for example, but how to print the last page of the S1 without knowing the real number of pages?
Something that could be used for various documents with various number of pages.

MacroShadow
04-29-2012, 05:47 AM
See fumei's answer at http://www.vbaexpress.com/forum/showthread.php?t=5608

Zack
04-29-2012, 09:29 AM
I saw it, but I need it to print the last page of the S1 (section one) of the document.

So basically the last page before the section brake.

MacroShadow
04-29-2012, 10:48 AM
Are you talking about the last page before the section break on the last page of the document?

Zack
04-29-2012, 11:51 AM
Are you talking about the last page before the section break on the last page of the document?

Exactly. The document can have 3 or 4 sections, but I need a command to print the last page before the 1st section brake.

MacroShadow
04-29-2012, 02:05 PM
I've seen on the web examples explaining how to print S1P6 for example

Can you post it?

Zack
04-29-2012, 03:04 PM
Can you post it?

Sure

http://www.uwec.edu/help/word03/print.htm

fumei
04-29-2012, 04:33 PM
I really can not believe this.

Print 10 pages of a document "A", but the 10th page would be printed duplex

AND


I would need the last page to be always the front page of the C:\documents\document1.doc.No mention of Sections afterwards.

Now...

Question Originally Posted by: MacroShadow

Are you talking about the last page before the section break on the last page of the document?

Your answer
Exactly. The document can have 3 or 4 sections, but I need a command to print the last page before the 1st section brake.

Exactly?????????? You write "exactly"? THAT is NOT what was asked. The question asked if it was the Section break on last page of the document

YOUR answer states "the last page before the 1st section brake". In other words, it is NOT the last page of the document. There could be pages and pages and pages after where you want to print to.

In other worfds, if the document has 234 pages (with pages 1 to 17 in Section 1), you want to print 16 and 17.

Can you print the last page of a given Section. Sure. Yes.

You mention you found how to print S16. The REAL question you should have asked is:

How do I get the number of pages in a specific Section?

Just remember that for the task you originally asked for, you have a NEW Section. So you want to print the last page of Section 1, and the first page of Section 2.

It would be easier if there was not the extra Sections afterwards - which you did NOT mention before. Can it be done? Actually, fairly easily.

fumei
04-29-2012, 05:32 PM
Look, I am not trying to be rude. Really I am not. It is simply frustrating to deal with you.

macroshadow asked: "Are you talking about the last page before the section break on the last page of the document?"

Document.
Section 1 = 23 pages
Section 2 = 11 pages
Section 3 = 8 pages
Section 4 = 1 page

Total pages = 43. The answer to macroshadow's question is page 42 - "the last page before the section break on the last page of the document"

With the same example, YOUR answer is page 23 - "I need a command to print the last page before the 1st section brake."

How on earth can you call that "exactly". They are utterly different!

All the stuff various people posted on the other thread was dealing with the last page of the document. Now you say this inserted other document can be somewhere IN the document? Say inserted at page 31 of a 126 page document?

Do you not think this is relevant? We have been trying to help you, but you sure are not doing yourself any favours. You are not reading post very well at all. You respond "exactly" but what you write is not even close to what you say is "exactly".

Sheeesh.

MacroShadow
04-29-2012, 09:35 PM
Ok fumei, lets not be too harsh with Zack, as he stated elsewhere English is not his mother tongue...
Assuming that what he's REALLY after this time is to print the last page of the first section in the document, that can be accomplished be using the following procedure.

Sub PrintLastPageInSectionOne()

Dim rng As Range
Dim lngLastPage As Long
Set rng = ActiveDocument.Sections(1).Range.Duplicate
rng.Collapse wdCollapseEnd
lngLastPage = rng.Information(wdActiveEndAdjustedPageNumber)
ActiveDocument.PrintOut Pages:="p1" & "s" & CStr(lngLastPage)

End Sub

Zack
04-29-2012, 10:09 PM
Ok fumei, lets not be too harsh with Zack, as he stated elsewhere English is not his mother tongue...
Assuming that what he's REALLY after this time is to print the last page of the first section in the document, that can be accomplished be using the following procedure.

Sub PrintLastPageInSectionOne()

Dim rng As Range
Dim lngLastPage As Long
Set rng = ActiveDocument.Sections(1).Range.Duplicate
rng.Collapse wdCollapseEnd
lngLastPage = rng.Information(wdActiveEndAdjustedPageNumber)
ActiveDocument.PrintOut Pages:="p1" & "s" & CStr(lngLastPage)

End Sub

I tried it. It prints everything before and after the section break.
Btw, thank you for trying.

Zack
04-29-2012, 10:12 PM
We have been trying to help you,


And I am thankful for your help. After reading your posts here I am truly one step closer to solving the issue.

fumei
04-30-2012, 12:51 AM
It helps if you actually state what you want. As I stated, doing what you REALLY need was fairly easy (as you can see by macroshadow's code). I realize I sound harsh, but can you not see that all those other posts were a waste of time - as we were trying to help you do something you did NOT want (because you did not say what you wanted).

Look how fast you got something from macroshadow that moves you forward. That could have happened without the many posts by people (not just me) trying to help with incorrect information.

macroshadow: I am sympathetic to language issues, but I do not think this is strictly a language issue. It is a conceptual one.

But yes...I am not the gentlest person, and I can come across as harsh. I dislike wasting my time. Thank you for posting your gift to Zack.

Zack
04-30-2012, 07:48 AM
It helps if you actually state what you want. As I stated, doing what you REALLY need was fairly easy (as you can see by macroshadow's code). I realize I sound harsh, but can you not see that all those other posts were a waste of time - as we were trying to help you do something you did NOT want (because you did not say what you wanted).

Look how fast you got something from macroshadow that moves you forward. That could have happened without the many posts by people (not just me) trying to help with incorrect information.

macroshadow: I am sympathetic to language issues, but I do not think this is strictly a language issue. It is a conceptual one.

But yes...I am not the gentlest person, and I can come across as harsh. I dislike wasting my time. Thank you for posting your gift to Zack.

As I already explained to macroshadow, it prints everything before and after the section break. The idea was to print the last page of the first section in the document. The code unfortunately prints everything (the entire document).
Macroshadow is currently the only one posting some VBA so far. Even though it might not work as expected, I still appreciate the effort being put in coding it.
You said you want to help Fumei? I asked for your help again in the other thread and did I get that help? Of course not. Now there is someone here actually putting some VBA, trying to assist me and you come here to complain about how I described it all wrong, that I am giving ambivalent information regarding my needs etc. How did Macroshadow understand from first about what I need? He is not a VBA expert (at least by title in this forum) and still he understood. If you are looking for a job, you could PM me and tell me how much you would charge for solving this problem since you mentioned "hiring" couple of times. Would "hiring" resolve the conceptual issue? I noticed that you are a veteran here and tried to respect your dignity and your reputation, but you push just too far. The lack of respect for others is the lack of respect for yourself, remember that.
Naturally, others will support you because you are an old timer on this forum and probably have admin privileges (or know someone who does) etc., but since I am not going to get any constructive help from you, I couldn't care less.
On the other thread you said that "you would help me get my answer", after which I've asked for your help and I received none, again. You don't have to help me, but please have some common courtesy and don't prevent others from doing so. Thank you for your time.

Frosty
04-30-2012, 09:48 AM
Zack,

The concept of pages in Word is a difficult one. Not to harp on the same issue, but without getting into some of your points in this thread and the others, I can only repeat the thing I've said in the other thread:

The reason you are not getting a simple bit of VBA to solve your problem is because the answer is not simple. For example, the following items *may* help you...

ActiveDocument.Content.Information(wdActiveEndPageNumber)
ActiveDocument.ActiveWindow.ActivePane.Pages.Count

Both have values of "3" on a simple 3 page document.

However, in some scenarios one will give you "2" and one will give you "3" (for instance, if the page break separating Page 2 and Page 3 is formatted as hidden text and you are not showing paragraph marks).

In addition, the .Pages collection simply isn't available in some versions of Word (2002 and earlier), but there are other ways of potentially determining a "real" page count.

It also gets more complicated depending on a lot of other variables.

The more you understand about Word, the more you will understand that there is no simple answer to even this request. The simple concept of "pages" within Microsoft Word is not a simple concept, even though it seems like it should be.

This is why you aren't getting simple VBA code from the experts, but others (who don't know as much-- no offense, MacroShadow) are throwing something against the wall to see if it sticks.

Your design requirements seem simple, and are very clear:

Print out a document with the last page of the document automatically coming from another file (somehow) and the two last pages being printed out two-sided.

A lot of the elements of this design are simple:
1. Grab information from document X and insert (somewhere) into Document Y
2. Insert a section break near the end of the document, to allow duplex printing.
3. Print the document.

But you have to believe people when they tell you that this is actually very very difficult to do via code (for a couple of reasons).

You could have a 100 post thread, with every post containing different VBA code, and one portion may work and one portion may not... and you would be no closer to a "one-click solution."

The question you have to ask yourself is: do you want to learn all of the things you need to learn in order to make this work for yourself? If you do, then you have to forget the idea that there are 4 (or even 20) lines of code out there to solve this problem for your documents.

There might be-- the code is probably pretty simple. But only if a *lot* of things about the documents are exactly the same every time.

In short: look for threads about "Pages" in this forum, and you will see many posts about this concept.

This thread contains another way of determining pages by way of using a rectangles object...
http://www.vbaexpress.com/forum/showthread.php?t=41190&highlight=pages+rectangles

MacroShadow
04-30-2012, 10:51 AM
Zack,

Sorry, my bad replace the last line in the procedure with this one and let us know if it works.

ActiveDocument.PrintOut Pages:="p" & CStr(lngLastPage) & "s1"
On a side note:
The purpose of this forum is not to supply ready solutions and/or answers but rather to help newbies learn in the process of solving the issues there struggling with. If you're not willing to learn chances are the replies you're going to get from the experts will not help you very much, as Frosty said:
The question you have to ask yourself is: do you want to learn all of the things you need to learn in order to make this work for yourself? If you do, then you have to forget the idea that there are 4 (or even 20) lines of code out there to solve this problem for your documents.

MacroShadow
04-30-2012, 10:53 AM
If that doesn't work try this:

Sub PrintLastPageSectionOne()
Dim rng As Range
Dim strPages As String
Dim lngLastPage As Long
Set rng = ActiveDocument.Sections(1).Range.Duplicate
rng.Collapse wdCollapseEnd
lngLastPage = rng.Information(wdActiveEndAdjustedPageNumber)
strPages = "p" & CStr(lngLastPage) & "s1"
ActiveDocument.PrintOut Pages:=strPages
End Sub
If that doesn't work either just trust the experts.


The reason you are not getting a simple bit of VBA to solve your problem is because the answer is not simple.
This is why you aren't getting simple VBA code from the experts, but others (who don't know as much-- no offense, MacroShadow) are throwing something against the wall to see if it sticks.
No arguing with that!!!

Zack
04-30-2012, 12:08 PM
Your design requirements seem simple, and are very clear



Thank you.

Zack
04-30-2012, 12:18 PM
A lot of the elements of this design are simple:
1. Grab information from document X and insert (somewhere) into Document Y
2. Insert a section break near the end of the document, to allow duplex printing.
3. Print the document.



We don't have to worry about 1 and 2. They are already solved by using:With Selection
.EndKey Unit:=wdStory
.InsertBreak Type:=wdSectionBreakNextPage
.InsertFile FileName:="Other.doc", Range:=""


End With

The exact explanation of number 3 has already been posted numerous times. The thing I was asking for can be applied to every document really. Detecting and printing the last page before the first section break.

If you need a document, here it is. This should look familiar to you.

Tell me what other info do you need and I will give it to you.

This document doesn't have 2 section breaks, but the same thing is needed. Printing only the last page without prior knowledge about the total number of pages. You can add section break to test printing of only the last page of the 1st section. Normal printing. Nothing fancy.

Zack
04-30-2012, 12:21 PM
Zack,

Sorry, my bad replace the last line in the procedure with this one and let us know if it works.



Nah mate, doesn't work. I tried both of your codes and in both cases it prints all pages from the document. Doesn't matter.

Frosty
04-30-2012, 02:18 PM
Not sure why you posted that document. Seems like a lot of client specific data. Here are two ways to print the last page of a document.

1. Record a macro
2. Move your cursor to the last page of the document
3. Print the current page
4. Stop recording the macro.
5. Review the macro.

Another way...
1. See how many pages in a specific section... for example...
Try the following bit of code on a bunch of different documents. Try it when you are showing paragraphs, and when you are not. See how often it is right, and how often it is wrong.

Public Sub HowManyPages()
Dim sRet As String
Dim sInput As String
Dim x As Integer
Dim y As Integer

sInput = InputBox("Put the number of the section you wish to test." & vbCr & _
"NOTE: this document only has " & ActiveDocument.Sections.Count & _
" Section(s).", "Check Number of Pages", "1")

'if we got a number, we'll attempt to go on
If IsNumeric(sInput) Then
x = ActiveDocument.Sections(CLng(sInput)).Range.Information(wdActiveEndPageNumb er)
If sInput = 1 Then
sRet = "Number of pages: " & CStr(x)
Else
y = ActiveDocument.Sections(CLng(sInput) - 1).Range.Information(wdActiveEndPageNumber)
sRet = "Number of pages: " & CStr(x - y)
End If

MsgBox sRet
End If
End Sub

Zack
04-30-2012, 03:41 PM
Ok. I've tried this and it works. It basically tells me how many pages each section has. Works on several documents with and without showing paragraphs. 100% accuracy as far as I can tell.
Is there a way to pick a section and that it automatically prints the last detected page of it? So after it tells me that Section 1 has 10 pages the 10th would be printed.

Frosty
04-30-2012, 04:06 PM
The answer to your question is "yes."

Now do the following:
1. Create a document with 2 sections. Make the first section 10 pages long. Make the second section 5 pages long.
2. Record a macro.
3. Print the document using the custom range code "S1 P10"
4. Print the document using the Custom range code "s2 P5"
5. Stop recording.
6. Post your recorded macro here.

Zack
04-30-2012, 04:18 PM
The answer to your question is "yes."

Now do the following:
1. Create a document with 2 sections. Make the first section 10 pages long. Make the second section 5 pages long.
2. Record a macro.
3. Print the document using the custom range code "S1 P10"
4. Print the document using the Custom range code "s2 P5"
5. Stop recording.
6. Post your recorded macro here.

Done.

Application.PrintOut FileName:="", Range:=wdPrintRangeOfPages, Item:= _
wdPrintDocumentContent, Copies:=1, Pages:="P10S1", PageType:= _
wdPrintAllPages, ManualDuplexPrint:=False, Collate:=True, Background:= _
True, PrintToFile:=False, PrintZoomColumn:=0, PrintZoomRow:=0, _
PrintZoomPaperWidth:=0, PrintZoomPaperHeight:=0
Application.PrintOut FileName:="", Range:=wdPrintRangeOfPages, Item:= _
wdPrintDocumentContent, Copies:=1, Pages:="P5S2", PageType:= _
wdPrintAllPages, ManualDuplexPrint:=False, Collate:=True, Background:= _
True, PrintToFile:=False, PrintZoomColumn:=0, PrintZoomRow:=0, _
PrintZoomPaperWidth:=0, PrintZoomPaperHeight:=0
End Sub

Frosty
04-30-2012, 04:20 PM
And were the right pages printed out?

Zack
04-30-2012, 04:45 PM
And were the right pages printed out?

When entered manually yes, of course.

Frosty
04-30-2012, 04:47 PM
You see that the only difference between the two printed jobs you recorded are the "Pages" parameter... one is "P10S1" and one is "P5S2" yes?

Zack
04-30-2012, 04:52 PM
You see that the only difference between the two printed jobs you recorded are the "Pages" parameter... one is "P10S1" and one is "P5S2" yes?

I am not going socratic here but let me answer with this: Do you understand what I want to accomplish?

Frosty
04-30-2012, 05:00 PM
I don't mind the Socratic method at all. However, it is not terribly helpful when the student uses the Socratic method on the teacher. You don't know enough.

Can you answer the question? Do you see the difference?

If you do see the difference, then does the following (slightly modified from above) macro start to point you in the right direction?

Public Sub HowManyPages()
Dim sRet As String
Dim sInput As String
Dim x As Integer
Dim y As Integer
Dim sPrintCode As String


sInput = InputBox("Put the number of the section you wish to test." & vbCr & _
"NOTE: this document only has " & ActiveDocument.Sections.Count & _
" Section(s).", "Check Number of Pages", "1")

'if we got a number, we'll attempt to go on
If IsNumeric(sInput) Then
x = ActiveDocument.Sections(CLng(sInput)).Range.Information(wdActiveEndPageNumb er)
If sInput = 1 Then
sRet = "Number of pages: " & CStr(x)
sPrintCode = "P" & CStr(x) & "S" & sInput
Else
y = ActiveDocument.Sections(CLng(sInput) - 1).Range.Information(wdActiveEndPageNumber)
sRet = "Number of pages: " & CStr(x - y)
sPrintCode = "P" & CStr(x - y) & "S" & sInput
End If

MsgBox sRet & vbCr & "Pages Print code would be: " & sPrintCode
End If
End Sub

Zack
04-30-2012, 05:08 PM
Yes, it gives me the code for the last page of the selected section. If it has 10 pages for S1 it would be P10S1.

Frosty
04-30-2012, 05:14 PM
Then you have your solution.

If you wish to print the last page of a section other than 1 (which I've set as the default), you can uncomment out the InputBox line of code. If you want to test the result, you can uncomment out the MsgBox line of code.

Public Sub HowManyPages()
Dim sRet As String
Dim sInput As String
Dim x As Integer
Dim y As Integer
Dim sPrintCode As String

x = 1
sInput = CStr(x)
'sInput = InputBox("Put the number of the section you wish to test." & vbCr & _
"NOTE: this document only has " & ActiveDocument.Sections.Count & _
" Section(s).", "Check Number of Pages", sInput)

'if we got a number, we'll attempt to go on
If IsNumeric(sInput) Then
x = ActiveDocument.Sections(CLng(sInput)).Range.Information(wdActiveEndPageNumb er)
If sInput = 1 Then
sRet = "Number of pages: " & CStr(x)
sPrintCode = "P" & CStr(x) & "S" & sInput
Else
y = ActiveDocument.Sections(CLng(sInput) - 1).Range.Information(wdActiveEndPageNumber)
sRet = "Number of pages: " & CStr(x - y)
sPrintCode = "P" & CStr(x - y) & "S" & sInput
End If

'MsgBox sRet & vbCr & "Pages Print code would be: " & sPrintCode
End If
Application.PrintOut FileName:="", Range:=wdPrintRangeOfPages, Item:= _
wdPrintDocumentContent, Copies:=1, Pages:=sPrintCode, PageType:= _
wdPrintAllPages, ManualDuplexPrint:=False, Collate:=True, Background:= _
True, PrintToFile:=False, PrintZoomColumn:=0, PrintZoomRow:=0, _
PrintZoomPaperWidth:=0, PrintZoomPaperHeight:=0
End Sub

Zack
04-30-2012, 05:27 PM
Then you have your solution.



For my purpose a solution would be to automatically print the last page of the s1.

This code is great at determining how many pages each section has. I assume it can be arranged that the value given by the box can be used for printing. Such as: Print the value (example p10s1) given by the code.

I see that you really outdone yourself in writing this one, since even I can tell that it's not that simple and is fairly long. It should be probably posted somewhere for the future reference if someone comes asking for the similar thing.

But I wonder, if there is a way to determine the last page of each section, is there maybe a way to immediately print that page out by selecting a specific printer?
I guess I can manually enter the printer before

Application.PrintOut FileName:="", Range:=wdPrintRangeOfPages, Item:= _
wdPrintDocumentContent, Copies:=1, Pages:=sPrintCode, PageType:= _
wdPrintAllPages, ManualDuplexPrint:=False, Collate:=True, Background:= _
True, PrintToFile:=False, PrintZoomColumn:=0, PrintZoomRow:=0, _
PrintZoomPaperWidth:=0, PrintZoomPaperHeight:=0

but not sure if that would work.

As I said, code works well, but is there a way to avoid msgboxes? To assume that I want to check only for the S1?

Frosty
04-30-2012, 05:33 PM
But that is exactly what the latest code does.

Frosty
04-30-2012, 05:35 PM
Unless you mean code which prints out the last page of EVERY section (I.e., 4 section document with 50 pages would only print 4 pages)

fumei
04-30-2012, 05:39 PM
macroshadow, does it seem this is a language issue, rather than a conceptual one?


But I wonder, if there is a way to determine the last page of each section, is there maybe a way to immediately print that page out by selecting a specific printer?Yes, there is.

Zack
04-30-2012, 06:04 PM
But that is exactly what the latest code does.

I meant without poping the msgbox asking Check number of pages.

So it assumes that there is only section 1 and it auto prints its last page.

Regarding the printer, can I put it here?


'ActivePrinter="XX"
Application.PrintOut FileName:="", Range:=wdPrintRangeOfPages, Item:= _
wdPrintDocumentContent, Copies:=1, Pages:=sPrintCode, PageType:= _
wdPrintAllPages, ManualDuplexPrint:=False, Collate:=True, Background:= _
True, PrintToFile:=False, PrintZoomColumn:=0, PrintZoomRow:=0, _
PrintZoomPaperWidth:=0, PrintZoomPaperHeight:=0

What do you think?

Frosty
04-30-2012, 06:13 PM
There is no msgbox or input box in the latest code. I commented those lines out. You should get no prompts at all... it should simply print the last page of section 1.

Yes, I believe setting the ActivePrinter before you run the .Printout method would work. Again, that is the kind of thing you should try recording a macro to see if it works.

Since you've seen the code that can give you the text code ("S1P10") to print a specific page, then recording a macro which would...
1. Print pages 1-9 to a printer using simplex printing and then
2. switch to the duplex printer and print page 10

Would give you "most" of what you need... but you have to take the parts of the recorded macro which are useful, and delete the rest. And combine the stuff which is useful from another macro.

Once you can do that, you can say you're a beginning VBA programmer :)

Zack
04-30-2012, 06:24 PM
There is no msgbox or input box in the latest code. I commented those lines out. You should get no prompts at all... it should simply print the last page of section 1.

Yes, I believe setting the ActivePrinter before you run the .Printout method would work. Again, that is the kind of thing you should try recording a macro to see if it works.

Since you've seen the code that can give you the text code ("S1P10") to print a specific page, then recording a macro which would...
1. Print pages 1-9 to a printer using simplex printing and then
2. switch to the duplex printer and print page 10

Would give you "most" of what you need... but you have to take the parts of the recorded macro which are useful, and delete the rest. And combine the stuff which is useful from another macro.

Once you can do that, you can say you're a beginning VBA programmer :)

My fault. I've uncommented that line. It has no box at all. Works perfectly.
Regarding the bolded, that's exactly what I intend to do. I will combine it with the insertfile and insertbreak to create a macro that will do it all at once. This should be it.
I think this is solved.

Thank you for providing me with a solution. You've been most helpful.

Thanks again.

Frosty
04-30-2012, 06:46 PM
You bet. And then next step to learning is this:

Post the final code which is your solution (all the various pieces you've combined into a macro). That serves two purposes:
1) Someone who comes along and does a search will see the "fruits" of this threads "labor;" and
2) Others may be able to comment/improve your solution.

I'm fairly confident that the simple code I provided *will* break in some scenarios... you just haven't yet encountered (and may never) in the documents on which you've been testing.

For example... continuous section breaks will cause problems to the above methodology (since with continuous section breaks, you can have a 1 page document which contains multiple sections). And continuous section breaks happen more often than you think, especially if you paste text into Word from other sources.

But continuous section breaks can also be extremely useful, since you sometimes want the formatting only a section break can provide, without having to start a new page.

This is just the beginning of learning. It rapidly gets more complex. I'm sorry you had such a rough beginning with these two threads, but we often have to answer "what's wrong with the mouse software?" questions with "please click the mouse button" solutions, at least to start. All learning has to start simply, and go from there.

You happened to ask a question which combined some of the harder problems to solve:
1. the concept of "pages" (and pagination) in Word (always a tricky concept) with
2. A specific type of printing (often heavily dependent on the actual printer and printer driver).

If your first question on this forum was something like "how do I bold the first Word of every paragraph in the document?" the thread would have contained only a few posts. One of which would have been VBA code, and one of which would have showed you how to manually do it with an advanced Find/Replace, and one would have showed you how to combine the two.

Frosty
04-30-2012, 07:31 PM
One last thought on the code which is the current "solution" to this question:

This code is *not* reliable in all scenarios. I'm happy it's working for you, but without writing a dissertation on why this code is not reliable, I will hope that you take my word that this code is simply not reliable 100% of the time.

I have encountered specific problems in the legal industry (litigation can be very picky about specific pages, as can printing out a specific page of a 100 page Trust as an addendum, or for the purposes of making a minor substantive change which doesn't appear to have any effect on the overall pagination), and about the only thing that can be relied upon regarding pages is the following: you can always print out the current page to the current printer.

But there are certain scenarios where having your cursor at the EXACT same location in a document which is EXACTLY the same on two different computers, and running a macro on both computers which says "Print Current Page" can give you a different printed page. This cannot be over-stated.

Any time you are doing an operation about printing specific pages (especially in scenarios where you are only transferring the information electronically), you should always be in the habit of making a visual check that the output is exactly what you expect.

Because I guarantee the time the output is wrong will be the time when you most needed it to be correct and forgot to check because it had worked perfectly the other 50 times you used it.

Zack
04-30-2012, 11:27 PM
I've been trying to change X into 2.

It says x = ActiveDocument.Sections(CLng(sInput)).Range.Information(wdActiveEndPageNumb er)

Basically I wanted to create the same thing for the section 2.

But this line turns yellow y = ActiveDocument.Sections(CLng(sInput) - 1).Range.Information(wdActiveEndPageNumber)

I've been trying to change -1 into -2.

And I tried to change If sInput = 1 Then into If sInput = 2 Then

I would love to know how to make the same thing for the section 2 as well. Purely for upgrading my knowledge. Well, out of curiosity I admit. But then I thought, is there a way for this code to print the last pages of 2 sections at once (1st and 2nd)? In one print job that is. Since I usually will be having just 2 sections anyway..

Btw, I tried this code now on several documents already. Found no flaws so far. :beerchug:

Frosty
05-01-2012, 09:10 AM
Let me clean up that code and comment it a bit, I think that will help. I wrote it quickly, and so I didn't comment as much as I normally do.

In addition, I *think* you can print non-contiguous pages in a single print job. So you could put "1,5,7" in the Pages box of the print dialog. I did a little testing and it doesn't seem you can do anything more complex than that (i.e., no "S1P3, S2P5" kind of thing).

But finding out the absolute page numbers of the last page in the section using the same methodology would be easy as pie. You just have to create a loop.

First... here's a better commented (and slightly adjusted routine) to help you more easily go through it.

Couple additional pointers-- F5 will run the whole routine if your cursor is in it. But F8 will "step through" the routine... this allows you to go step by step, and combined with hovering your mouse over variables (or using the Locals Windows -- View > Locals Window), you can see the values of variables.

The major changes to this routine is that I renamed all the variables so that you can more easily tell what they are supposed to be, vs. what they might actually be doing. This is a good lesson: naming a variable properly often helps the troubleshooting. "X" is meaningless... but "iNumPages" tells you what it is supposed to be (at least). And if you find out it is incorrect, then you have something to go on.

Try working (and learning) the following routine.

Public Sub PrintSomePages()
Dim sInfo As String
Dim sSecNum As String
Dim iNumPages As Integer
Dim iNumPagesPrevSec As Integer
Dim sPrintCode As String
Dim bTestMode As Boolean

'set some defaults -- the section we want to use when running, and the default
'input for the input box when in test mode
sSecNum = "1"
'whether to do "test mode" or not
bTestMode = False

If bTestMode Then
sSecNum = InputBox("Put the number of the section you wish to test." & vbCr & _
"NOTE: this document only has " & _
ActiveDocument.Sections.Count & " Section(s).", _
"Check Number of Pages", sSecNum)
End If

'hitting cancel on an Input Box gives an empty string result, which would not be numeric
'so this is our test to see whether to do anything else
If IsNumeric(sSecNum) Then
'get the number of pages of the primary section
iNumPages = ActiveDocument.Sections(CLng(sSecNum)).Range.Information(wdActiveEndPageNum ber)

'if we're dealing with the first section, we don't need to subtract any pages
If sSecNum = 1 Then
sInfo = "Number of pages: " & CStr(iNumPages)
sPrintCode = "P" & CStr(iNumPages) & "S" & sSecNum

'otherwise, we need to get the number of pages of the current section
Else
'and the number of pages from the previous section
iNumPagesPrevSec = ActiveDocument.Sections(CLng(sSecNum) - 1).Range.Information(wdActiveEndPageNumber)

'and then subtract the difference to get the number of pages of our primary section
sInfo = "Number of pages: " & CStr(iNumPages - iNumPagesPrevSec)
sPrintCode = "P" & CStr(iNumPages - iNumPagesPrevSec) & "S" & sSecNum
End If

'if we're in test mode...
If bTestMode Then
'display the results of our test
MsgBox sInfo & vbCr & "Pages Print code would be: " & sPrintCode
Else
'print out the document, using the derived print code
Application.PrintOut FileName:="", _
Range:=wdPrintRangeOfPages, _
Item:=wdPrintDocumentContent, _
Copies:=1, _
Pages:=sPrintCode, _
PageType:=wdPrintAllPages, _
ManualDuplexPrint:=False, _
Collate:=True, _
Background:=True, _
PrintToFile:=False, _
PrintZoomColumn:=0, _
PrintZoomRow:=0, _
PrintZoomPaperWidth:=0, _
PrintZoomPaperHeight:=0
End If

Else
MsgBox "You cancelled the input box", vbInformation, "PrintSomePages Macro"
End If
End Sub
As for your question of how to do a single print job... all we need to do is put together the right "printcode" string.

So in a 2 section document, where the first section is 10 pages, and the second section is 5 pages... our print code would need to be "10,15" -- right?

So first step to solving that is to try it manually, and verify what you can or can't do... see if that first step makes sense. Then we'll talk about how functions work.

Frosty
05-01-2012, 09:31 AM
Here is a function which simply encapsulates getting the number of pages in a particular section. You call functions from other routines (or the immediate pane, CTRL+G in the VBA window). So you can place this function in your module,

'return the total number of page numbers of the passed section number
'NOTE: this methodology fails to give accurate page numbers in several scenarios:
'hidden text, continuous section breaks, a variety of print drivers on long documentsl, etc
Public Function fGetPageNumbers(iSecNum As Integer) As Integer
Dim iNumPages As Integer
Dim iNumPagesPrevSec As Integer
Dim iRet As Integer

'functions should generally have error trapping
On Error GoTo l_err

With ActiveDocument
'get the number of pages of the current section
iNumPages = .Sections(iSecNum).Range.Information(wdActiveEndPageNumber)
If iSecNum = 1 Then
iRet = iNumPages
Else
'and the number of pages from the previous section, if we're dealing with a section other than 1
iNumPagesPrevSec = .Sections(iSecNum - 1).Range.Information(wdActiveEndPageNumber)
iRet = iNumPages - iNumPagesPrevSec
End If
End With
l_exit:
fGetPageNumbers = iRet
Exit Function
l_err:
'black box-- any errors we return 0
iRet = 0
Resume l_exit
End Function

and then type
?fGetPageNumbers(1)
in the immediate window, and the result will be the number of page numbers in Section 1.
?fGetPageNumbers(2)
Will give the number of page numbers in Section 2, unless there is no section 2, in which case it will return 0.

You could also use this function in the original routine thusly...

Public Sub PrintSomePages()
Dim sInfo As String
Dim sSecNum As String
Dim iNumPages As Integer
Dim iNumPagesPrevSec As Integer
Dim sPrintCode As String
Dim bTestMode As Boolean

'set some defaults -- the section we want to use when running, and the default
'input for the input box when in test mode
sSecNum = "1"
'whether to do "test mode" or not
bTestMode = True

If bTestMode Then
sSecNum = InputBox("Put the number of the section you wish to test." & vbCr & _
"NOTE: this document only has " & _
ActiveDocument.Sections.Count & " Section(s).", _
"Check Number of Pages", sSecNum)
End If

'hitting cancel on an Input Box gives an empty string result, which would not be numeric
'so this is our test to see whether to do anything else
If IsNumeric(sSecNum) Then
'get the page num for current section
iNumPages = fGetPageNumbers(CLng(sSecNum))

'and the previous section
If CLng(sSecNum) > 1 Then
iNumPagesPrevSec = fGetPageNumbers(CLng(sSecNum) - 1)
End If

'and then subtract the difference to get the number of pages of our primary section
sInfo = "Number of pages: " & CStr(iNumPages - iNumPagesPrevSec)
sPrintCode = "P" & CStr(iNumPages - iNumPagesPrevSec) & "S" & sSecNum

'if we're in test mode...
If bTestMode Then
'display the results of our test
MsgBox sInfo & vbCr & "Pages Print code would be: " & sPrintCode
Else
'print out the document, using the derived print code
Application.PrintOut FileName:="", _
Range:=wdPrintRangeOfPages, _
Item:=wdPrintDocumentContent, _
Copies:=1, _
Pages:=sPrintCode, _
PageType:=wdPrintAllPages, _
ManualDuplexPrint:=False, _
Collate:=True, _
Background:=True, _
PrintToFile:=False, _
PrintZoomColumn:=0, _
PrintZoomRow:=0, _
PrintZoomPaperWidth:=0, _
PrintZoomPaperHeight:=0
End If

Else
MsgBox "You cancelled the input box", vbInformation, "PrintSomePages Macro"
End If
End Sub

Chew on those two routines for a bit...

Frosty
05-01-2012, 09:36 AM
And then you can see the result is actually easy, but also complex. And with all the caveats about this methodology not being 100% reliable, etc.

All you have to do to make the below routine work, is delete the line for the msgbox, and put in your line of code about printing.

Public Sub PrintLastPageOfEachSection()
Dim oSec As Section
Dim sPrintCode As String

'build our print code string
For Each oSec In ActiveDocument.Sections
sPrintCode = sPrintCode & oSec.Range.Information(wdActiveEndPageNumber) & ","
Next

'take off the last comma
sPrintCode = Left(sPrintCode, Len(sPrintCode) - 1)

'display info (replace with actual print code when ready)
MsgBox sPrintCode
End Sub

Zack
05-01-2012, 12:22 PM
So first step to solving that is to try it manually, and verify what you can or can't do... see if that first step makes sense. Then we'll talk about how functions work.

I need some time to comprehend this. I would have asked you yesterday about how to do the same thing, but for the section 2 as well. If I remember correctly you even asked me do I need a code which would print all last pages for all sections in the document at once. I overlooked that. My fault. In my own defense, it was 3am when we were having a conversation, since I live in CET zone.

Zack
05-01-2012, 12:28 PM
And then you can see the result is actually easy, but also complex. And with all the caveats about this methodology not being 100% reliable, etc.

All you have to do to make the below routine work, is delete the line for the msgbox, and put in your line of code about printing.

Public Sub PrintLastPageOfEachSection()
Dim oSec As Section
Dim sPrintCode As String

'build our print code string
For Each oSec In ActiveDocument.Sections
sPrintCode = sPrintCode & oSec.Range.Information(wdActiveEndPageNumber) & ","
Next

'take off the last comma
sPrintCode = Left(sPrintCode, Len(sPrintCode) - 1)

'display info (replace with actual print code when ready)
MsgBox sPrintCode
End Sub



Flawless, again..and I am not being polite here..

Frosty
05-01-2012, 03:11 PM
Thanks. But remember: it's only flawless because it is working on your documents. This is a *very* flawed approach as a general rule. If this were the perfect approach for all types of documents, this thread would be much shorter :)