Is there a way, using vba, to determine if a footnote ends on the same page it begun on?
If the footnote flows over to the next page Selection.Range.Characters.First.Information(3) returns the number of the beginning page, not the current page.
Printable View
Is there a way, using vba, to determine if a footnote ends on the same page it begun on?
If the footnote flows over to the next page Selection.Range.Characters.First.Information(3) returns the number of the beginning page, not the current page.
There may be a more efficient way to do this, but this seems to work...
Code:Public Function fFootNoteIsSplit(Optional iFootnote As Integer = 1) As Boolean
Dim f As Footnote
Dim char As Range
Dim iNumFirstLines As Integer
If ActiveDocument.Footnotes.Count = 0 Then
fFootNoteIsSplit = False
End If
Set f = ActiveDocument.Footnotes(iFootnote)
For Each char In f.Range.Words
If char.Information(wdVerticalPositionRelativeToTextBoundary) = 0 Then
If iNumFirstLines > 0 Then
fFootNoteIsSplit = True
Exit For
End If
Else
iNumFirstLines = iNumFirstLines + 1
End If
Next
End Function
Actually, I'm sure there's a more efficient way than cycling through all of the characters in the footnote's range... just using .Words instead of .Characters (which I've already changed) would give less cycles to the loop, but the essential approach has to be something related to checking the vertical position (at least, I *think* it does).
But without using selection, you can't really move line by line, so .Words seems like it might be as good as it gets, because the footnote might be a single paragraph...
I'm curious if anyone comes up with something else... you always seem to have interesting little problems, MacroShadow :)
Thank you.
This question I asked on behalf of a co-worker. lol.Quote:
Originally Posted by Frosty
Actually how did you get a footnote to 'flow' to the next page?
As I add text to the footnote, the footnote line keeps climbing up the page, and the vertical size of the footnote gets bigger. (Word 2010)
A second footnote keeps climbing
I could probalby have a 1/2 page footnote section at that rate.
It would be nice if any footnote or footnotes that required more than a set space would continue on the next page in the footnote position
Paul
A footnote will fill up the entire page, as long as it starts on the same page as its reference. Try inserting your footnote closer to the bottom of the page to begin with.
thanks
I thought that at one time there was a setting as to how much footnote space there was at the bottom of the page, after margins and footers.
Guess not
Seems funny that it'd be sensitve to where the foot note is inserted
Paul
For a simple example, pages and rectangles seems to work:
Code:Sub ScratchMacro()
Dim oPage As Page
Dim oRect As Rectangle
Dim oRng As Word.Range
Dim oRngFN As Word.Range
Set oRngFN = ActiveDocument.Footnotes(1).Range
Set oPage = ActiveDocument.ActiveWindow.Panes(1).Pages(ActiveDocument.Footnotes(1).Range.Information(3))
Set oRect = oPage.Rectangles(3) '1 is main text, 2 is the separator 3 is the footnotes.
'not sure this would always be the case
Set oRng = oRect.Range
If oRngFN.InRange(oRng) Then
Debug.Print "FN is on same page"
Else
Debug.Print "FN spans multiple pages."
End If
End Sub
Frosty,
There is one problem with your function. If the footnote spans over multiple columns on the same page it still returns True.
Greg,
Is there a way to turn your macro into a function that will take the footnote number as a parameter (like Frosty's code)?
I tried but couldn't get it to work.
Code:Sub Test()
MsgBox ScratchMacro(1)
End Sub
Function ScratchMacro(lngIndex) As String
Dim oPage As Page
Dim oRect As Rectangle
Dim oRng As Word.Range
Dim oRngFN As Word.Range
Set oRngFN = ActiveDocument.Footnotes(lngIndex).Range
Set oPage = ActiveDocument.ActiveWindow.Panes(1).Pages(ActiveDocument.Footnotes(lngIndex).Range.Information(3))
Set oRect = oPage.Rectangles(3) '1 is main text, 2 is the separator 3 is the footnotes.
'not sure this would always be the case
Set oRng = oRect.Range
If oRngFN.InRange(oRng) Then
ScratchMacro = "Yes, the FN is on same page"
Else
ScratchMacro = "No, the FN spans multiple pages."
End If
End Function
That is basically what I tried.
If the footnote is not in the first column (in a multi column layout) it returns: No, the FN spans multiple pages even when the footnote doesn't flow over to the next page.
can you post a sample doc, MacroShadow? I don't even know how your set up is... this is back to your custom footnotes with linked textboxes, right?
I *suspect* you can use my function (at least) and simply check for a reset twice... but it would need to be modified somewhat to assume that the footnotes are always in two columns. Otherwise you need a separate function to test if this is a two-column footnote set up or a one-column footnote setup...
That is not a condition in your original post. It will help if you fully define the scope of what you are after.
This will probably work for 2 columns, but not for 1 or 3:
Code:Sub Test()
MsgBox ScratchMacro(1)
End Sub
Function ScratchMacro(lngIndex) As String
Dim oPage As Page
Dim oRect As Rectangle
Dim oRect2 As Rectangle
Dim oRng As Word.Range
Dim oRng2 As Word.Range
Dim oRngFN As Word.Range
Set oRngFN = ActiveDocument.Footnotes(lngIndex).Range
Set oPage = ActiveDocument.ActiveWindow.Panes(1).Pages(ActiveDocument.Footnotes(lngIndex).Range.Information(3))
Set oRect = oPage.Rectangles(4) '1 is main text column 1, 2 is main text column 2, 3 is the col 1separator
'4 is col1 footnotes, 5 is col2 separator, 6 is col 2 footnotes.
Set oRect2 = oPage.Rectangles(6)
'not sure this would always be the case
Set oRng = oRngFN.Duplicate
Set oRng2 = oRngFN.Duplicate
oRng.Collapse wdCollapseStart
oRng2.Collapse wdCollapseEnd
If oRng.InRange(oRect.Range) And oRng2.InRange(oRect2.Range) Then
ScratchMacro = "Yes, the FN is on same page"
Else
ScratchMacro = "No, the FN spans multiple pages."
End If
End Function
It will also help if you post what you've tried. This way people can spend their time trying to help you with what you've tried rather than spend it redoing what you, after the fact, inform us that you have already done.
Quote:
Originally Posted by MacroShadow
I agree with Greg: MacroShadow, you've been posting long enough here that you can give better information sooner, and post the kinds of things you've tried.
You're getting to the point that I got when I started programming. I kept asking my mentor "what about this, what about that" and he continued to patiently teach me. But then, at some point, his responses started becoming "Umm, I don't know-- figure it out. That's the job."
You won't get that response here, but there is a point where you're good enough to put in effort too.
That said... this is considerably more tricky, and this is what I've come up with. It seems to work regardless of the number of columns, or what column the initial footnote reference starts in.
Code:Public Function fFootNoteIsSplit(Optional iFootnote As Integer = 1, Optional oDoc As Document) As Boolean
Dim fn As Footnote
Dim rngWord As Range
Dim iNumFirstLinesInFootnote As Integer
Dim iNumColumnsInSection As Integer
Dim lLocation As Long
On Error GoTo l_err
'if no document passed, use the active document
If oDoc Is Nothing Then
Set oDoc = ActiveDocument
End If
'if no footnotes, then return false and exit
If oDoc.Footnotes.Count = 0 Then
fFootNoteIsSplit = False
MsgBox "No footnotes in this document.", vbInformation, "Footnote Checker"
GoTo l_exit
End If
'get the footnote
Set fn = oDoc.Footnotes(iFootnote)
'see how many columns in the footnote reference's section
iNumColumnsInSection = fn.Reference.Sections.First.PageSetup.TextColumns.Count
For Each rngWord In fn.Range.Words
'check to see if this word is the first word, or the beginning of a text column
If rngWord = fn.Range.Words.First _
Or rngWord.Information(wdVerticalPositionRelativeToTextBoundary) = 0 _
And rngWord.Information(wdHorizontalPositionRelativeToTextBoundary) = 0 Then
'check where it's horizontally located on the page, relative to any previous setting
If rngWord.Information(wdHorizontalPositionRelativeToPage) > lLocation Then
lLocation = rngWord.Information(wdHorizontalPositionRelativeToPage)
'also, increment our first line counter
iNumFirstLinesInFootnote = iNumFirstLinesInFootnote + 1
'if we've got a location that is closer to the left than a previous setting,
'we know we've hit a new page, so the range is split... we're done
Else
fFootNoteIsSplit = True
Exit For
End If
End If
'if we've gotten more first lines than columns, we know it's split
If iNumFirstLinesInFootnote > iNumColumnsInSection Then
fFootNoteIsSplit = True
Exit For
End If
Next
l_exit:
Exit Function
l_err:
MsgBox "Error in this function-- decide what you want to return"
Resume l_exit
End Function
Alright-- so I played around with the .Pages and .Rectangles collections a bit. Not to take the original post too off-topic, but I don't think making the assumption on the specific rectangle number can be a good approach to this problem, because you have to make too many assumptions about the layout of the document.
The .Page object is relatively simple to access (although you *have* to be in print layout view, which is a limiter)... but the number of rectangles on a page is too much of a variable.
On a single page, two columns of main story text with a single footnote that also spans two columns... you will have 6 rectangles (as Greg's comments articulate).
However, if the right column of the page is entirely taken up with the footnote (i.e., no main story text), you'll only have 5 rectangles.
Also, if you insert a text box on the page, you'll have a totally different rectangles count. And depending on the .WrapFormat of that text box (inline, top/bottom, tight, etc), the rectangles count will adjust as well. Because the .Rectangles collection seems to be an attempt to return valid "text" areas of that particular page (somewhat analogous to the way a powerpoint slide is laid out).
Granted, I don't know alot about this area of the object model, and Greg knows a lot more-- but it seems that the only way to use the rectangles collection is to iterate through all of them on the page, and then determine whether they are valid areas you're interested in... that's what I've done using the Rectangles approach that Greg started. This seems to work as well, although it has the limitation of requiring Print View/Page Layout to be turned on -- on the other hand, it's much much more readable code and structure.
Code:Public Function fFootNoteIsSplit_Alt1(Optional iFootnote As Integer = 1, _
Optional oDoc As Document) As Boolean
Dim r As Rectangle
Dim p As Page
Dim fn As Footnote
Dim rLastFootnoteOnPage As Range
If oDoc Is Nothing Then
Set oDoc = ActiveDocument
End If
If oDoc.ActiveWindow.ActivePane.View.Type <> wdPrintView Then
MsgBox "You must be in page layout view to use this function"
Exit Function
End If
Set fn = oDoc.Footnotes(iFootnote)
Set p = oDoc.ActiveWindow.ActivePane.Pages(1)
'cycle through the main footnote story rectangles
For Each r In p.Rectangles
If r.RectangleType = wdTextRectangle Then
If r.Range.StoryType = wdFootnotesStory Then
'get the range of the last footnote on the page
Set rLastFootnoteOnPage = r.Range.Duplicate
End If
End If
Next
'the range of whole footnote doesn't include the paragraph mark, so we add 1 to the .End test
If rLastFootnoteOnPage.End = fn.Range.End + 1 Then
fFootNoteIsSplit_Alt1 = False
Else
fFootNoteIsSplit_Alt1 = True
End If
End Function
Jason,
You very well may have crossed the Rubicon. You may now know alot more about panes, pages, rectangles, and lines than I do.
I know about them, and I know that sometimes there are some neat tricks that you can pull off using them.
Other than that, I pass the hat. You are now the resident expert ;-)
Ha. We'll see. I have no doubt you'll surprise me with something else. I just worry areas of the object model I don't understand like a dog worries a bone. So I played a bit. It's a pretty powerful area, in terms of identifying areas on a particular page. But the limitation of page layout view (and the general concept of pages in word) probably means it has to be use in pretty narrow circumstances.
MacroShadow-- because of all the layout work you're doing, you should really explore the rectangles collection... It might simplify some of your coding.
You know of the countless thousands of hours I've sat working with a Word document on screen, I'll bet that not five minutes of it was spent outside of print layout view.
For some people Normal (or Draft) is normal, but anything other that print layout just freaks me out.