Consulting

Page 1 of 2 1 2 LastLast
Results 1 to 20 of 21

Thread: Solved: Position on page

  1. #1

    Solved: Position on page

    Greetings, all

    I'm seeking help in VBA for Word - I'm trying to write a bit of code which will break some kinds of paragraphs across pages differently than Word normally does. In order to do that, I need to determine the position of the insertion point relative to the page, in inches, lines, or something I can measure.

    Can anyone start me in the right direction?

    -WB

  2. #2
    VBAX Master TonyJollans's Avatar
    Joined
    May 2004
    Location
    Norfolk, England
    Posts
    2,291
    Location
    Hi WorkerBee,

    Welcome to VBAX!

    Personally I think this kind of activity is contrary to the nature of Word. You give Word a set of rules, and you give it the document content and it word processes the two together to make a complete document; it adjusts automatically for different paper sizes, different printers, etc. If you want to post-process the result you have a difficult time ahead of you. What effect are you looking to achieve? Is there not some way you could use Word's rules to achieve it?

    That said, the information you are asking for is available from:
    [VBA]
    Selection.information(wdHorizontalPositionRelativeToPage)
    Selection.information(wdVerticalPositionRelativeToPage)[/VBA]
    Enjoy,
    Tony

    ---------------------------------------------------------------
    Give a man a fish and he'll eat for a day.
    Teach him how to fish and he'll sit in a boat and drink beer all day.

    I'm (slowly) building my own site: www.WordArticles.com

  3. #3
    Tony, thanks for the information.

    As to the question of 'why,' it's just as you say. I'm trying to out-process the word processor.

    In fact, I'm creating a VB set for formatting film scripts, which utilize a complex set of rules. I created styles for each of the types of paragraphs used in a script, and some vb code which goes through the script after it's finished and conforms the document to the conventions of scripts.

    Relevant to this particular effort, each dialogue-style paragraph is preceeded by a paragraph style made for the character's name.

    i.e.
    TONY
    Personally I think this kind of activity is
    contrary to the nature of Word. You give
    Word a set of rules, and you give it the
    document content and it word processes
    the two together to make a complete
    document; it adjusts automatically for
    different paper sizes, different printers,
    etc. If you want to post-process the
    result you have a difficult time ahead of
    you. What effect are you looking to
    achieve? Is there not some way you
    could use Word's rules to achieve it?
    I have the character and dialogue paragraphs set to always keep together. Sometimes, when there is a very long speech near the end of a page, it leaves an unacceptably large white space at the bottom of the page so that it can keep the entire character and speech together.

    The common solution in scripts is to break the speech at the bottom of the page, adding the parenthetical "(MORE)" at the bottom of that page, and starting the next page with the character's name with an added (CONT'D). i.e.
    TONY
    Personally I think this kind of activity is
    contrary to the nature of Word.You give
    Word a set of rules, and you give it the
    document content and it word processes
    the two together to make a complete
    document; it adjusts automatically for
    different paper sizes, different printers,
    etc. If you want to post-process the
    (MORE)
    -----------------page break
    TONY (CONT'd)
    result you have a difficult time ahead of
    you. What effect are you looking to
    achieve? Is there not some way you
    could use Word's rules to achieve it?
    I want to use the power of the computer to free me from the drudgery of searching through each document manually and making these changes.

    And to make matters worse, I will make a corollary operation which will go through the document and REMOVE all of those "(MORE)" and "(CONT'D)" and extra character names in case I want to re-write some of the text and change the page breaks.

    If I had the money to do so at this time, I'd just buy one of the off-the-shelf one-trick-pony script-writing word processors. But I've got to sell a script to pay for it.

    In my defense, I am heavily using Word's templates, styles, pagination, headers, footers, and summary-tracking features.

    Again, I thank you for your help on this - I appreciate your sharing of your time and experience.

    -Curt

  4. #4
    VBAX Master TonyJollans's Avatar
    Joined
    May 2004
    Location
    Norfolk, England
    Posts
    2,291
    Location
    Interesting, Curt. I don't think there's any real way to do that in Word (bar coding it yourself) but it seems just like a word-processing type of thing which ought to be possible.

    I'm not entirely sure right now how I'd go about it but I would think you could determine where the page break was in a couple of ways without using physical position on the page like that.
    Enjoy,
    Tony

    ---------------------------------------------------------------
    Give a man a fish and he'll eat for a day.
    Teach him how to fish and he'll sit in a boat and drink beer all day.

    I'm (slowly) building my own site: www.WordArticles.com

  5. #5
    VBAX Wizard
    Joined
    May 2004
    Posts
    6,713
    Location
    This couild be done with VBA. Just curious, but how is this going?

  6. #6
    Administrator
    VP-Knowledge Base
    VBAX Guru MOS MASTER's Avatar
    Joined
    Apr 2005
    Location
    Breda, The Netherlands
    Posts
    3,281
    Location
    Quote Originally Posted by fumei
    This couild be done with VBA. Just curious, but how is this going?
    Hi,

    Sure but like Tony says it will be hard!

    Tony has posted some of the Information lines VBA uses to give coordinates but I would certainly also use:[VBA]
    MsgBox Selection.Information(wdFirstCharacterLineNumber)
    [/VBA]

    It returns the line you're at and will be very usefull if you're building your document dynamicly!

    But this sort of thing is so hard to to because Word has a dynamic body and things will be dependending on so much factors..to name some:
    * Page set-up
    * Font sizes
    * Paragraph settings

    This list could go on and on but I'm sure cursious just like you if the OP has made this work allready..

    Enjoy!
    _________
    Groetjes,

    Joost Verdaasdonk
    M.O.S. Master

    Mark your thread solved, when it has been, by hitting the Thread Tools dropdown at the top of the thread.
    (I don't answer questions asked through E-mail or PM's)

  7. #7
    VBAX Wizard
    Joined
    May 2004
    Posts
    6,713
    Location
    Well yes it would be a bit of work, but not HUGELY. Break it out logically.

    You have a Style. The rule is:

    IF the paragraph using the Style crosses over to another page THEN
    1. insert some space in the paragraph before the word processed page break
    2. add the "MORE" text
    3. add a forced page break
    4. add the "CONT" text.

    You can detect the page crossing with something like:

    [vba]Sub StyleParaAcrossPages()
    Dim mPara As Paragraph
    Selection.HomeKey unit:=wdStory
    For Each mPara In ActiveDocument.Paragraphs
    If mPara.Style = "NewStyle1" Then
    If mPara.Range.End > _
    ActiveDocument.Bookmarks("\page").Range.End Then
    ' ***********
    ' replace below with the routine to
    ' break the paragraph with "MORE" and
    ' page break

    MsgBox "Goes to next page"
    ' if DOES go to next page
    ' need to move Selection
    ' to keep using \page bookmark
    Selection.GoTo What:=wdGoToPage, Which:=wdGoToNext, Count:=1, Name:=""
    Else
    MsgBox "Nope."
    End If
    End If
    Next
    End Sub[/vba]

    I have not included the routine to make the actual text insertion and page break. Hey ya gotta work! Plus it would depend on whether you would use a special style for this temporary (possibly....likely) text. Whatever method, the actual logic would use the character count from the "\page" Range.End, back up the requirement length, insert the "MORE" and page break.....blah blah blah.

  8. #8
    Administrator
    VP-Knowledge Base
    VBAX Guru MOS MASTER's Avatar
    Joined
    Apr 2005
    Location
    Breda, The Netherlands
    Posts
    3,281
    Location
    Hi Gerry,

    This looks promissing but like you've said your not there yet.
    I will have to play with your code to see if its doing what I aspect from it.

    Do a postback later.
    Still wondering though if the OP still has interest in this subject..
    _________
    Groetjes,

    Joost Verdaasdonk
    M.O.S. Master

    Mark your thread solved, when it has been, by hitting the Thread Tools dropdown at the top of the thread.
    (I don't answer questions asked through E-mail or PM's)

  9. #9
    VBAX Wizard
    Joined
    May 2004
    Posts
    6,713
    Location
    That sounded vaguely challenging, but hey, what the heck.
    [vba]Sub StyleParaAcrossPages()
    Dim mPara As Paragraph
    Selection.HomeKey Unit:=wdStory
    For Each mPara In ActiveDocument.Paragraphs
    If mPara.Style = "NewStyle1" Then
    If mPara.Range.End > _
    ActiveDocument.Bookmarks("\page").Range.End Then
    Selection.SetRange _
    Start:=ActiveDocument.Bookmarks("\page").Range.End - 128, _
    End:=ActiveDocument.Bookmarks("\page").Range.End - 128
    Call FixMORE
    Else
    MsgBox "Nope."
    End If
    End If
    Next
    End Sub


    Sub FixMORE()
    With Selection
    .TypeParagraph
    .TypeParagraph
    .MoveLeft Unit:=wdCharacter, Count:=1
    NormalTemplate.AutoTextEntries("MORE").Insert _
    Where:=Selection.Range, _
    RichText:=True
    .Style = ActiveDocument.Styles("myMORE")
    .TypeParagraph
    ' next page stuff
    .TypeParagraph
    .TypeParagraph
    .MoveLeft Unit:=wdCharacter, Count:=1
    NormalTemplate.AutoTextEntries("CONT").Insert _
    Where:=Selection.Range, _
    RichText:=True
    .Style = ActiveDocument.Styles("myMORE")
    .TypeParagraph
    End With
    End Sub[/vba]

    I used a Style - myMore - for the (More) text. The VERY IMPORTANT thing to consider is that you will have to figure out, ahead of time, the character counts to deal with.

    The original text has the same font size as the next paragraph with "(MORE)", but obviously the character count will now be different. Less words, whole paragraphs.

    You need to make a paragraph that DOES go over, get the position number of the end of the page, then get the position number of the end of the line that you are going to break.

    If you are using Styles, then this will be the same every time. In my test case, this means 128 characters. This is hard coded in. IF you are using styles. So there will, in my case, always 128 characters between the end of the page and where I want to start the MORE (also a Style) stuff.

    Or....will it? NOPE. What if there are only two lines of this style, and 128 characters (my test doc had BIG paragraphs) actually brings you out of that paragraph? Ah, so sorry, but you then have to test this. It is fairly easy using a Range object.

    The question thoug is - what do you DO about it. This is a design element, so i can not answer. Is it acceptable to use this (MORE) format if there is only ONE line on page A, all the rest of the paragraph on page B? Or would you move a one-liner over to the next page?

    better specs - better code

    The rest of the code is self explanatory.

  10. #10
    Administrator
    VP-Knowledge Base
    VBAX Guru MOS MASTER's Avatar
    Joined
    Apr 2005
    Location
    Breda, The Netherlands
    Posts
    3,281
    Location
    Quote Originally Posted by fumei
    That sounded vaguely challenging, but hey, what the heck.
    Hahaha not really but I knew you'd pick up on it!

    I've copied everyting to a workbook and must have a go at it...but at the moment my mailbox is overflowing and this isn't a question to answer without testing first. (for me at least)

    Later...
    _________
    Groetjes,

    Joost Verdaasdonk
    M.O.S. Master

    Mark your thread solved, when it has been, by hitting the Thread Tools dropdown at the top of the thread.
    (I don't answer questions asked through E-mail or PM's)

  11. #11

    I've been away working.

    Greetings, all.

    I've been away from the forum, working on my real job, and I've put some time in this already.

    So far, here's how my code goes. I'm sure some will find some stylistic faults, but then I'm an amateur. I know there are too many literals, and I promise to clean that up when I get it all working.

    This subroutine is called when the first paragraph at the top of a page is formatted with the style "Character," and begins with the insertion point at the beginning of that line.

    Sometimes the name of the character already has the word "(CONT'D) following it because a person was talking, the dialogue was interrupted by narrative, then the dialogue continues. Additionally, the style requires that a sentence not be broken across a page. Even though this is creating a new paragraph in their speech, it's an accepted (and required) part of the format.

    The word "(More)" at the bottom of the page is formatted with the style "More Dialogue" and the inserted character name at the top of the page is formatted with the style "More Character" because I will write a corresponding macro to remove these formatted items so that the script can be re-edited and re-formatted.

    [VBA]
    Sub FixDialogBreak()
    Dim VertPos As Variant, NumLines As Integer, CharName As String

    'Move backwards one line
    Selection.MoveLeft unit:=wdCharacter, Count:=1

    'Check the current vertical position. If it's greater than 650, nothing should
    ' be done because there's not enough room. Move on

    VertPos = Selection.Information(wdVerticalPositionRelativeToPage)
    If VertPos > 668 Then
    Selection.MoveRight unit:=wdCharacter
    GoTo BreakDone
    End If

    'Calculate how many lines can be moved onto earlier page
    'VertPos is in points (72 points = 1 inch). Bottom of page is 719.1. Each line is 12 pts
    'Remove the page/section break that's just been put there
    NumLines = Int(((706 - VertPos) / 12) - 1)
    Selection.Delete unit:=wdCharacter, Count:=1

    'Move back down one line, capture the character name
    'Selection.MoveDown Unit:=wdLine, Count:=1
    Selection.EndKey unit:=wdLine, Extend:=wdExtend
    CharName = Selection.Text

    'Move forward x lines
    Selection.MoveDown unit:=wdLine, Count:=NumLines - 1
    Selection.EndKey unit:=wdLine

    'Move backwards, find the next preceding period, as we can't break in the middle of a
    ' sentence. If there are none prior to hitting the character name, we can't break the
    ' dialogue any earlier than it is, so give up.

    Do

    Selection.MoveLeft unit:=wdCharacter, Count:=2
    Selection.MoveRight unit:=wdCharacter, Extend:=wdExtend
    If Selection.Style <> "Dialogue" Then GoTo BreakDone 'Ran out of dialogue

    Loop Until Selection = "." Or Selection = "!" Or Selection = "?"

    Selection.MoveRight unit:=wdCharacter
    Do
    Selection.MoveRight unit:=wdCharacter
    Selection.MoveRight unit:=wdCharacter, Extend:=wdExtend
    Loop Until Selection <> " "

    If Selection = Chr(13) Then GoTo BreakDone

    Selection.MoveLeft unit:=wdCharacter
    'Add the (MORE) and insert page break here
    Selection.TypeText Text:=Chr(13) & "(MORE)" & Chr(13)
    Selection.MoveLeft unit:=wdCharacter
    Selection.Style = "More Dialogue"
    Selection.InsertBreak Type:=wdSectionBreakNextPage
    Selection.Delete unit:=wdCharacter, Count:=1

    'Paste in character name along with (CONT'D)
    Selection.TypeText Text:=CharName
    Selection.MoveLeft unit:=wdCharacter
    If Right$(CharName, 10) = "(CONT'D) " + Chr$(13) Then GoTo SKIPCONTD 'There's already a continued there
    Selection.TypeText Text:=" (CONT'D)"
    SKIPCONTD:
    Selection.Style = "More Character"
    Selection.HomeKey unit:=wdLine

    BreakDone:

    End Sub
    [/VBA]

    This is all working pretty well so far.

    I don't want there to be a strange short line of dialogue with only a couple of words left at the bottom of a page (in case of a short sentence), so I need to add some code to take that into account. However, in the depths of my ignorance, I don't know what the code is which will return to me the column position of the insertion point, that is, how many characters is the insertion point from the start of the line? Can someone help?

    -WB

  12. #12
    VBAX Wizard
    Joined
    May 2004
    Posts
    6,713
    Location
    Hi,

    First off, your code will run a bit better if you use With statements. As in:

    [vba]With Selection
    .MoveLeft unit:=wdCharacter
    'Add the (MORE) and insert page break here
    .TypeText Text:=Chr(13) & "(MORE)" & Chr(13)
    .MoveLeft unit:=wdCharacter
    .Style = "More Dialogue"
    .InsertBreak Type:=wdSectionBreakNextPage
    .Delete unit:=wdCharacter, Count:=1

    'Paste in character name along with (CONT'D)
    .TypeText Text:=CharName
    .MoveLeft unit:=wdCharacter
    If Right$(CharName, 10) = "(CONT'D) " + Chr$(13) Then Goto SKIPCONTD 'There's already a continued there
    .TypeText Text:=" (CONT'D)"
    End With[/vba]

    You asked how to find out the number of characters from the insertion point to the start of the line. Here is one way - there are others.
    [vba]Function ToStart() As Long
    Dim r As Range
    Set r = ActiveDocument.Range _
    (Start:=ActiveDocument.Bookmarks("\line").Range.Start, _
    End:=Selection.Range.Start)

    ToStart = r.ComputeStatistics(wdStatisticCharacters)
    Set r = Nothing
    End Function

    Sub GetCharacters()
    MsgBox ToStart
    End Sub[/vba]

    However, you had better make sure the insertion point (the Selection) is, in fact, where you want it to be. As this code needs to run (I assume) from the start of the document checking for these paragraph breaks, you must make sure you are moving the Selection along with it.

    I also notice you have added the requirement that you do NOT break the paragraph in the middle of a sentence, only at a period. In your original post on this:

    "etc. If you want to post-process the
    (MORE)

    -----------------page break
    TONY (CONT'd)

    result you have a difficult time ahead of "

    you did not have this requirement. Once again - better specs, better code. It also makes it more difficult, and complicated. You have done a gerat job so far!

  13. #13
    Thanks for the advice, Gerry. I'll make some of those modifications soon.

    I was hoping for an easier way to find the character column position (after all, it's displayed at the bottom of the Word window), but my wishin' hasn't always made things come true.

    You're correct that the design specs changed. It's my own fault for not paying close enough attention. It looked funny after completed, then I read deeper into the style book and found myself wrong.

    As for difficult or complicated: if it were easy, it wouldn't need doing. We have a saying in my business: "If a job's worth doing, it's worth doing over and over."

    -Curt

  14. #14
    VBAX Wizard
    Joined
    May 2004
    Posts
    6,713
    Location
    Yes it is displayed in Word, and guess what? Word make a range object and calculates the value every time the selection point is moved. It calculates it just like the code above. That IS the easy way.

    But again, be careful that the Selection point is, in fact, moved to where you want it to be. Consider doing your calculation using a range.

    As for, say, two lines being too small, and in which case you want to move the whiole thing to the next page, I suspect the faster way to get this done is determine the character count and hard code it.

    Do the break as "normal", then do a secondary calculation using a range object for the range of the last paragraph start, and the predefined bookmark "\page" End. If it is < 170 characters (approx. 2 lines) then dump the page break and move it to the beginning of the paragraph.

  15. #15
    Administrator
    VP-Knowledge Base
    VBAX Guru MOS MASTER's Avatar
    Joined
    Apr 2005
    Location
    Breda, The Netherlands
    Posts
    3,281
    Location
    Quote Originally Posted by WorkerBee
    I was hoping for an easier way to find the character column position (after all, it's displayed at the bottom of the Word window), but my wishin' hasn't always made things come true.-Curt
    Hi Curt,

    Many wise Words off Gery all of them true of course...

    But there is infact an easy way to retrieve that value of Col that you see in the statusbar (bottom window):[VBA]
    MsgBox Selection.Information(wdFirstCharacterColumnNumber)
    [/VBA]

    Enjoy!
    _________
    Groetjes,

    Joost Verdaasdonk
    M.O.S. Master

    Mark your thread solved, when it has been, by hitting the Thread Tools dropdown at the top of the thread.
    (I don't answer questions asked through E-mail or PM's)

  16. #16
    VBAX Wizard
    Joined
    May 2004
    Posts
    6,713
    Location
    Still need to make sure Selection is on the correct line.

    Would still need the paragraph range start to determine the number of characters to paragraph start - which may not be on the same line....

    But yes, you have a very valid point. I had also forgotten....sigh.... that Range.ComputeStatistics calculates very differently that Selection.Information.

    For example. the Selection is at the left most of a line.

    Selection.Information returns 1 - in fact can not return a 0
    Range.Calculate returns 0 - there are no characters

    Selection.Information includes punctuation and spaces.
    Range.CalculateStatistics does not.

    I to Joost

  17. #17
    Administrator
    VP-Knowledge Base
    VBAX Guru MOS MASTER's Avatar
    Joined
    Apr 2005
    Location
    Breda, The Netherlands
    Posts
    3,281
    Location
    Quote Originally Posted by fumei
    I to Joost
    Are we the new Laurel and Hardy?

    I to you as well!
    _________
    Groetjes,

    Joost Verdaasdonk
    M.O.S. Master

    Mark your thread solved, when it has been, by hitting the Thread Tools dropdown at the top of the thread.
    (I don't answer questions asked through E-mail or PM's)

  18. #18
    VBAX Wizard
    Joined
    May 2004
    Posts
    6,713
    Location
    Apparetly we are. Do you have a preference for which one?

  19. #19
    Administrator
    VP-Knowledge Base
    VBAX Guru MOS MASTER's Avatar
    Joined
    Apr 2005
    Location
    Breda, The Netherlands
    Posts
    3,281
    Location
    Nopes..let the audience decide!
    _________
    Groetjes,

    Joost Verdaasdonk
    M.O.S. Master

    Mark your thread solved, when it has been, by hitting the Thread Tools dropdown at the top of the thread.
    (I don't answer questions asked through E-mail or PM's)

  20. #20
    Thank you MOS Master (and you others, too). That was indeed what I was seeking. Now I can find true happiness.

    -Curt

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •