ending multiple if/with statements

E

Elaine J.

I have what I know has to be a very basic programming question. But I always
have trouble with this and have not been able to locate an answer that has
made it clear to me.

When you have multiple if and with statements: what is the proper sequence
to end them.

for example

if
with
with
if

I need to end the two "with" statements and the last "if", but not the first
one just yet. what is the proper sequence to end them?

end with
end with
end if

OR

end if
end with
end with

If someone could explain how to know what the sequence should be, I would
greatly appreaciate it. Thanks.
 
J

Jonathan West

Elaine J. said:
I have what I know has to be a very basic programming question. But I
always
have trouble with this and have not been able to locate an answer that has
made it clear to me.

When you have multiple if and with statements: what is the proper
sequence
to end them.

for example

if
with
with
if

I need to end the two "with" statements and the last "if", but not the
first
one just yet. what is the proper sequence to end them?

end with
end with
end if

OR

end if
end with
end with

If someone could explain how to know what the sequence should be, I would
greatly appreaciate it. Thanks.

Such statement pairs should always be nested, not overlapping. It is easier
to keep track if you indent code within these structures, as follows

If A then
With B
With C
If D Then

End If 'from If D
End With 'from With C
End With 'from With B
End If 'from If A
 
S

SHewes

Jonathan West said:
Such statement pairs should always be nested, not overlapping. It is easier
to keep track if you indent code within these structures, as follows

If A then
With B
With C
If D Then

End If 'from If D
End With 'from With C
End With 'from With B
End If 'from If A

I have never done Imbeded WITH statements before with Word. Is it possible
to do so ??

For example you have

With Selection.Range
....
With Selection.Tables(1)
...
.Font.Color = wdDarkBlue
...
End With
End With

Whick of the two will have the .FONT.COLOR changed ???

In my experience, it would be something like this

With Selection.Range
...
End With

With Selection.Tables(1)
....
End With

You could put it in a IF statement

If condition = True then
With Selection
...
end with
else
with Selection
....
end with
endif

But never

If condition = True then
With Selection
...
else
....
end with
endif

The true fork will not find an END WITH statement and the false fork will
not find the WITH statement.
 
J

Jonathan West

SHewes said:
I have never done Imbeded WITH statements before with Word. Is it possible
to do so ??

Definitely! I use them often.
For example you have

With Selection.Range
...
With Selection.Tables(1)
...
.Font.Color = wdDarkBlue
...
End With
End With

Whick of the two will have the .FONT.COLOR changed ???

The innermost one
 
E

Elaine J.

Jonathan, thank you so much. It sometimes goes several months between times
when I need to write some code. It seems like every time, I get this mixed
up. Thank you for a clear answer. I can keep this with my samples.
 
N

NZ VBA Developer

Here's one example that I use regularly:

With ActiveDocument
If .Bookmarks.Exists("[Bookmark name]") Then
.Bookmarks("[Bookmark name]").Select
With Selection
.Text = "Some text..."
.Bookmarks.Add "[Bookmark name]", .Range
End With
End If
End With

Technically I suppose this is sloppy code because of the use of the
Selection object. However, I can't seem to find another reliable method for
preserving / retaining / reinstating a bookmark after inserting text...

That's not really important though. What matters is the nested With
statements, which reference completely different objects without ending one
before initiating the other. Very cool!

--
Cheers!
The Kiwi Koder

Please note: Uninvited email contact will be marked as SPAM and ignored -
unless you want to hire me. ;-)
 
J

Jonathan West

NZ VBA Developer said:
Here's one example that I use regularly:

With ActiveDocument
If .Bookmarks.Exists("[Bookmark name]") Then
.Bookmarks("[Bookmark name]").Select
With Selection
.Text = "Some text..."
.Bookmarks.Add "[Bookmark name]", .Range
End With
End If
End With

Technically I suppose this is sloppy code because of the use of the
Selection object. However, I can't seem to find another reliable method
for
preserving / retaining / reinstating a bookmark after inserting text...

You can avoid the Selection object by using a Range, like this

Dim myRange as Range
With ActiveDocument
If .Bookmarks.Exists("[Bookmark name]") Then
Set myRange = .Bookmarks("[Bookmark name]").Select
With myRange
.Text = "Some text..."
.Bookmarks.Add "[Bookmark name]", .Range
End With
End If
End With

This is generally quicker, and avoids moving the selection.
That's not really important though. What matters is the nested With
statements, which reference completely different objects without ending
one
before initiating the other. Very cool!

yes, that's a good example of the technique
 
D

Doug Robbins - Word MVP

Hi Jonathon,

I think that you meant

Set myRange = .Bookmarks("[Bookmark name]").Range

not

Set myRange = .Bookmarks("[Bookmark name]").Select

--
Hope this helps.

Please reply to the newsgroup unless you wish to avail yourself of my
services on a paid consulting basis.

Doug Robbins - Word MVP

Jonathan West said:
NZ VBA Developer said:
Here's one example that I use regularly:

With ActiveDocument
If .Bookmarks.Exists("[Bookmark name]") Then
.Bookmarks("[Bookmark name]").Select
With Selection
.Text = "Some text..."
.Bookmarks.Add "[Bookmark name]", .Range
End With
End If
End With

Technically I suppose this is sloppy code because of the use of the
Selection object. However, I can't seem to find another reliable method
for
preserving / retaining / reinstating a bookmark after inserting text...

You can avoid the Selection object by using a Range, like this

Dim myRange as Range
With ActiveDocument
If .Bookmarks.Exists("[Bookmark name]") Then
Set myRange = .Bookmarks("[Bookmark name]").Select
With myRange
.Text = "Some text..."
.Bookmarks.Add "[Bookmark name]", .Range
End With
End If
End With

This is generally quicker, and avoids moving the selection.
That's not really important though. What matters is the nested With
statements, which reference completely different objects without ending
one
before initiating the other. Very cool!

yes, that's a good example of the technique


--
Regards
Jonathan West - Word MVP
www.intelligentdocuments.co.uk
Please reply to the newsgroup
 
J

Jonathan West

Doug Robbins - Word MVP said:
Hi Jonathon,

I think that you meant

Set myRange = .Bookmarks("[Bookmark name]").Range

not

Set myRange = .Bookmarks("[Bookmark name]").Select

Correct!
 
N

NZ VBA Developer

Thanks Jonathan. I'll give this a try. If it works it should stop the screen
from jumping around while the document is building. (Does
Application.Screenupdating = False actually _do_ anything?) However, I'll
probably have to display a "Building document" dialog of some sort now so the
users will know to wait. Some of the documents are rather large and some of
the users' machine rather slooooow...

And thanks Doug for confirming the small error in the line
.Bookmarks("[Bookmark name]").Select
Had me scratching my head for a minute there. ;-D
--
Cheers!
The Kiwi Koder


Jonathan West said:
NZ VBA Developer said:
Here's one example that I use regularly:

With ActiveDocument
If .Bookmarks.Exists("[Bookmark name]") Then
.Bookmarks("[Bookmark name]").Select
With Selection
.Text = "Some text..."
.Bookmarks.Add "[Bookmark name]", .Range
End With
End If
End With

Technically I suppose this is sloppy code because of the use of the
Selection object. However, I can't seem to find another reliable method
for
preserving / retaining / reinstating a bookmark after inserting text...

You can avoid the Selection object by using a Range, like this

Dim myRange as Range
With ActiveDocument
If .Bookmarks.Exists("[Bookmark name]") Then
Set myRange = .Bookmarks("[Bookmark name]").Select
With myRange
.Text = "Some text..."
.Bookmarks.Add "[Bookmark name]", .Range
End With
End If
End With

This is generally quicker, and avoids moving the selection.
That's not really important though. What matters is the nested With
statements, which reference completely different objects without ending
one
before initiating the other. Very cool!

yes, that's a good example of the technique


--
Regards
Jonathan West - Word MVP
www.intelligentdocuments.co.uk
Please reply to the newsgroup
 
J

Jonathan West

NZ VBA Developer said:
Thanks Jonathan. I'll give this a try. If it works it should stop the
screen
from jumping around while the document is building. (Does
Application.Screenupdating = False actually _do_ anything?)

It reduces the amount of screen updating, but doesn't eliminate it
altogether. Since I use range objects almost exclusively in my longer macros
so the selection doesn't jump around, the advantage of setting
ScreenUpdating to true is minimal and I don't bother, especially as it can
occasionally result in unexpected behaviour such as seen here

Paragraph borders lost when printing from a VBA macro
http://www.word.mvps.org/FAQs/MacrosVBA/ParaBordersLost.htm
However, I'll
probably have to display a "Building document" dialog of some sort now so
the
users will know to wait. Some of the documents are rather large and some
of
the users' machine rather slooooow...

You could put a progress bar on the form.
 
N

NZ VBA Developer

Just to close the loop, my final code is as follows:

Private Sub InsertValues
Dim myRange as Range
With ActiveDocument
If .Bookmarks.Exists("[Bookmark name]") Then
Set myRange = .Bookmarks("[Bookmark name]").Range
With myRange
.Text = "Some text..."
.Bookmarks.Add "[Bookmark name]", myRange
End With
End If
End With
Set myRange = Nothing
'*** Repeat above as necessary for each additional bookmark ***
End Sub

Note a couple of small changes:

The range for the added bookmark is 'myRange', not '.Range'. This is
because, without the use of the Selection object and the related With
statement, there is no object whose Range attibute can be used to specify the
range for the bookmark - and it's not needed since I already have a range
object to work with.

Just to be tidy and ensure smooth execution of the code, I also set myRange
to 'Nothing' after each "insertion".

And now I have an even better example of nested 'With' statements!

(Hmm... I could probably pass arguments to this for the bookmark name and
text and really clean things up...)
 
J

Jonathan West

NZ VBA Developer said:
Just to close the loop, my final code is as follows:

Private Sub InsertValues
Dim myRange as Range
With ActiveDocument
If .Bookmarks.Exists("[Bookmark name]") Then
Set myRange = .Bookmarks("[Bookmark name]").Range
With myRange
.Text = "Some text..."
.Bookmarks.Add "[Bookmark name]", myRange
End With
End If
End With
Set myRange = Nothing
'*** Repeat above as necessary for each additional bookmark ***
End Sub

Note a couple of small changes:

The range for the added bookmark is 'myRange', not '.Range'. This is
because, without the use of the Selection object and the related With
statement, there is no object whose Range attibute can be used to specify
the
range for the bookmark - and it's not needed since I already have a range
object to work with.
Just to be tidy and ensure smooth execution of the code, I also set
myRange
to 'Nothing' after each "insertion".

No need. myRange automatically becomes Nothing when the variable goes out of
scope when you exit the routine.
And now I have an even better example of nested 'With' statements!

You don't really need the nested With statement here, because the .Bookmarks
line can be relative to Activedocument
(Hmm... I could probably pass arguments to this for the bookmark name and
text and really clean things up...)

Like this...

Private Sub InsertValues(sBookmarkname As String, sNewText as String)
Dim myRange as Range
With ActiveDocument
If .Bookmarks.Exists(sBookmarkname) Then
Set myRange = .Bookmarks(sBookmarkname).Range
myRange.Text = sNewText
.Bookmarks.Add sBookmarkname, myRange
End If
End With
End Sub
 
N

NZ VBA Developer

Actually, it ended up looking more like this:

Private Sub InsertValue(strBkmkName As String, strText As String, Optional
bBoldFirst As Boolean = False)
Dim myRange As Range
With myDoc
If .Bookmarks.Exists(strBkmkName) Then
Set myRange = .Bookmarks(strBkmkName).Range
With myRange
.Text = strText
If bBoldFirst Then
.Bold = False
.Characters(1).Bold = True
End If
End With
.Bookmarks.Add strBkmkName, myRange
End If
End With
End Sub

Which is very close to what you provided. However, I discovered that in some
instances I needed to make the first character of the text bold - thus the
reason for the optional Boolean argument. This also meant that I got to keep
my nested 'With'. :-D

And as for "unbolding" the range first, this is done to support rerunning
the macro. Otherwise any formatting applied to the first character gets
applied to the whole range when the new text is inserted.

I was aware that myRange would be set to nothing automatically when the
variable went out of scope at the end of the subroutine (and my code reflects
this), but in my previous version I was repeatedly resetting the value of
myRange within the sub and felt it best to set it to nothing in between -
just to be safe. Not necessary now though.

Cool fun! Thanks!
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top