Consulting

Results 1 to 6 of 6

Thread: Searching for a non-existent bookmark..

  1. #1

    Searching for a non-existent bookmark..

    Hi all!!

    Long time no write!

    I am VBA-Illiterate, but thanks to all of you, and thanks to keystroke macros, I have a nice little set of routines at my disposal!

    I am looking to modify one? I know what I want to do is pretty simple, so please bear with my ignorance!

    I have a small macro that looks for a bookmark called ?ReportStart?, and then, it wipes out all the pages prior to that bookmark.

    It?s part of a larger macro now, and works like a charm.

    However, here is what I am trying to achieve:

    If the user repeatedly presses this lovely ?Begin!? button (this is what we call the routine), it will keep chomping off more and more of the text since the ReportStart bookmark gets nuked!

    Actually, this is what happens:

    1 ? The first time the user presses the button, it works fine. It finds the bookmark, and deletes the pages of junk behind it.

    2 ? If the user presses it a second time by accident, it now DELETES the bookmark(!) and takes off some text.

    3 ? If the user presses it more times, it deletes more and more text.

    So, this whole diatribe is basically asking the following:

    ?How do I make sure this little macro doesn?t do more and more damage each time the user presses it??

    Any ideas are welcome!

    I think I need some kind of an IF statement that says to do this routine ONLY if the ReportStart bookmark Exists, and if so, it must not be in the first position of the document!


    Thanks as usual for your kind ideas!


    Here you can see it surrounded by two other parts of my lovely BEGIN! macro, the first part switching to Print View, and the third part setting the zoom to 100%. (Of course these two parts have nothing to do with the question, but hey, life is all about context, right?



    [VBA]
    ' Put it in a nice Print View
    If ActiveWindow.View.SplitSpecial = wdPaneNone Then
    ActiveWindow.ActivePane.View.Type = wdPrintView
    Else
    ActiveWindow.View.Type = wdPrintView
    End If

    ' Look for the ReportStart bookmark, and delete all all the pages before it
    On Error Resume Next
    Selection.GoTo What:=wdGoToBookmark, Name:="ReportStart"
    With ActiveDocument.Bookmarks
    .DefaultSorting = wdSortByName
    .ShowHidden = False
    End With
    Selection.HomeKey Unit:=wdStory, Extend:=wdExtend
    Selection.Delete Unit:=wdCharacter, Count:=1

    If err <> 0 Then err.Clear 'clear error if needed

    'Set the zoom to 100%
    ActiveWindow.ActivePane.View.Zoom.Percentage = 100

    [/VBA]

  2. #2
    Site Admin
    Jedi Master
    VBAX Guru Jacob Hilderbrand's Avatar
    Joined
    Jun 2004
    Location
    Roseville, CA
    Posts
    3,712
    Location
    This should get you started.
    [vba]
    Option Explicit

    Sub Macro1()

    Dim BMark As Bookmark
    Dim Page As Long
    Dim Line As Long

    On Error Resume Next
    Set BMark = ActiveDocument.Bookmarks("ReportStart")
    On Error GoTo 0

    If BMark Is Nothing Then
    MsgBox "No!!!", vbCritical
    GoTo Canceled:
    Else
    Selection.GoTo What:=wdGoToBookmark, Name:="ReportStart"
    Page = Selection.Range.Information(wdActiveEndPageNumber)
    Line = Selection.Range.Information(wdFirstCharacterLineNumber)
    If Page = 1 And Line = 1 Then
    MsgBox "No!!!", vbCritical
    GoTo Canceled:
    End If
    End If

    Canceled:

    Set BMark = Nothing

    End Sub
    [/vba]

    First we test if the bookmark even exists, then if it does we check the page and line number. You may wany to stop the macro if the page is 1 regardless of the line. But this shows how to get both values.

  3. #3
    VBAX Wizard
    Joined
    May 2004
    Posts
    6,713
    Location
    Here is what is happening (and why it is acting the way it is).

    You use Selection.GoTO with the bookmark. The Selection goes to the bookmark AND Selects it.

    You extend the selection to the beginning of the document. By default this moves Selection.Start. You can test this by making the original bookmark not a selection POINT, but a chunk of text. When you go:
    [vba]Selection.GoTo What:=wdGoToBookmark, Name:="ReportStart"
    ' if this was a chunk of text it would be highlighted
    With ActiveDocument.Bookmarks
    .DefaultSorting = wdSortByName
    .ShowHidden = False
    End With
    Selection.HomeKey Unit:=wdStory, Extend:=wdExtend
    ' the chunk is NO LONGER selected.[/vba]

    BTW: that With statement is not needed

    OK, so all text PRIOR to the bookmark is now deleted.

    Run a second time, the selection gets the bookmark and the instruction will delete it. The bookmark is gone. I find it hard to believe that it is taking off text over and over aghain. It will eat at some, if the bookmark contains text. But it will NOT if the bookmark does not exist.

    It is much better to use a Range. You can be very specific.

    A. You want to keep the bookmark.
    [vba]Dim oRange As Word.Range
    On Error Resume Next
    Set oRange = ActiveDocument.Range(Start:=0, _
    End:=ActiveDocument.Bookmarks("ReportStart").Range.Start - 1)
    oRange.Delete
    Set oRange = Nothing[/vba]
    Repeated execution will get an error as the bookmark.Start will end up being 0. So you get aSubscript out of range. 0 - 1. But you can run it a million times and the bookmark will never be deleted. Therefore you can put text before it again and again if you like.

    b. You WANT to remove the bookmark:
    [vba]Dim oRange As Word.Range
    On Error Resume Next
    Set oRange = ActiveDocument.Range(Start:=0, _
    End:=ActiveDocument.Bookmarks("ReportStart").Range.Start)
    oRange.Delete
    Set oRange = Nothing[/vba]
    In this case, yes the bookmark will eventually be deleted.

    Hard to say what is best, as you do not spec out what you want to happen exactly.

    Better specs...better code.

    In any case, using a Range is better than Selection. You certainly could do the numeric validation of the page and line numbers, but it really is not needed to do so.

  4. #4
    Hi guys!

    Thanks for the info...!

    I started off by using DRJ's code, and it works very well!

    I just did some minor tweaks, and it's fine. (I had it just look for the page number, not the line number, too. Good point!)

    I would like to ask a small question...

    The part where I define my ... (whatever they're called.. variables?)...

    Dim BMark As Bookmark
    Dim Page As Long
    Dim Line As Lon

    Should this be put on TOP of all the various macros in the list, or should they be put right before this particular macro?

    Also, what about the option explicit. Was never quite sure what that meant.

    Right now, amid the whole long page of 12 macros, I started off with:

    [VBA]
    Option Explicit
    Dim BMark As Bookmark
    Dim Page As Long
    Dim Line As Long
    [/VBA]

    and then I have my various macros/subroutines. Sub FrenchSpell(), Sub BeginReview(), Sub AdditUp(), etc. etc.

    Is this the proper way to do it?

    Option Explicit goes right on top followed by:

    [VBA]
    Option Explicit
    Dim BMark As Bookmark
    Dim Page As Long
    Dim Line As Long
    [/VBA]


    It DOES work...! I'll mark this baby as solved!... but I am just curous as to where this stuff goes..!

    Thank you!!!!

  5. #5
    VBAX Wizard
    Joined
    May 2004
    Posts
    6,713
    Location
    Option Explicit should always be at the very top of a code module - outside any Sub or Function.

    Your declaration of variables should be IN a Sub or Function - unless you want them to be global variables used in every Sub or Function in the code module. Look up Scope in Help.
    [vba]Option Explicit

    Sub Macro1()

    Dim BMark As Bookmark
    Dim Page As Long
    Dim Line As Long [/vba]
    You see that the variable declarations are INSIDE the Sub - that means the scope - the part that they cab be used, is only in the Sub. If they are outside the Sub, they are global. The difference is that if they are IN the Sub, once the Sub terminates, they terminate with it. If they are global they exist for as long as the code module has ANY procedure executing.

    Variables should match the scope of their purpose. Like objects, if you are not using them, destroy them.

    Glad DRJ's code works for you - as it should. I do want to reiterate that using Range rather than Selection is better code. And that, technically, unless you really need those page numbers (and frankly I do not see why you do), they are not needed.

  6. #6
    Hey Gerry,

    Thanks for the additional informaiton. I took out that whole WITH section, by the way.

    Also, I am glad to finally learn about the declaration of variables, and where I am able to put them, and where I should put them.

    I see what you are saying about the Range... it totally makes sense...

    Thank you for the help!!!

    Mike

Posting Permissions

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