PDA

View Full Version : Searching for a non-existent bookmark..



Michael 514
12-10-2005, 11:30 PM
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? :yes




' 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

Jacob Hilderbrand
12-11-2005, 12:28 AM
This should get you started.

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


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.

fumei
12-11-2005, 08:05 AM
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:
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.

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.
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
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:
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
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.

Michael 514
12-11-2005, 12:18 PM
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:


Option Explicit
Dim BMark As Bookmark
Dim Page As Long
Dim Line As Long


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:


Option Explicit
Dim BMark As Bookmark
Dim Page As Long
Dim Line As Long



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

Thank you!!!!

fumei
12-11-2005, 12:32 PM
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.
Option Explicit

Sub Macro1()

Dim BMark As Bookmark
Dim Page As Long
Dim Line As Long
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.

Michael 514
12-11-2005, 03:00 PM
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