how to remove hyperlinks from paragraph marks?

J

Jason Eacott

Hi All, I am trying to find a way to remove Hyperlinks from paragraph marks.
It seems it's not so easy. I dont know how some users manage to apply
hyperlinks to so many paragraph marks, but I need to remove them without
deleting the hyperlink on the rest of the text prior to the mark, and
leaving the paragrah mark itself in tact.
Can anyone help?

thanks
Jason.
 
J

Jezebel

Could you explain this in more detail? Hyperlinks are fields embedded within
paragraph text. They are not applied to, or even related to, paragraph
marks.

If you press Alt-F9 you can see the hyperlink fields: { HYPERLINK ... }. You
can delete them manually by selecting and deleting, or through VBA by
reference to the Hyperlinks collection for the range you're concerned about.
 
J

Jason Eacott

Sorry, ok
you CAN it turns out get a hyperlink applied to an actual paragraph
mark.
if you choose to display marks they show up blue just like the rest of the
hyperlinked text before it. I only know of one way to do this but others
manage to do it all the time and its painful.
If you type a line and end it with a paragraph mark
then type a second line. select both lines and apply a hyperlink you will
notice that the first paragraph mark gets a hyperlink too. It turns out that
this really screws with other stuff I am trying to do but I cant figure out
how to remove it.
*Note in other example documents I have I dont think this is how they've
done it, because the links are different on each line, but the result is the
same, paragraphs with hyperlinks. also SHIFT-F9 looks identical for lines
with and without the hyperlink on the paragraph mark itself.

I hope you can help.
 
P

Peter Hewett

Hi Jason Eacott

It's the text displayed by the hypertext field you're talking about. You can use this
code to change it:

Public Sub StripParasFromHyperlinks()
Dim fldItem As Word.Field

' Enumerate the Main Text Stories Fields collection
For Each fldItem In ActiveDocument.Fields

' We're only interested in Hyperlink fields
If fldItem.Type = wdFieldHyperlink Then

' Remove the paragraph mark from the displayed text
fldItem.Result.Text = Replace(fldItem.Result, vbCr, vbNullString)
End If
Next
End Sub ' StripParasFromHyperlinks

It just strip out the paragraph mark, it adds no extra spaces or anything else. You may
need to adjust this to meet your specific requirements. If you need to change it replace
the vbNullString parameter of the Replace method with the text that you require.

HTH + Cheers - Peter
 
J

Jezebel

OK, now I understand the problem. It's not that the paragraph mark has a
hyperlink, but vice versa: the hyperlink's 'text to display' has one (or
more) paragraph marks. The paragraph mark doesn't "get" the hyperlink; it
merely happens to be included in the range to which the hyperlink is
applied.

Are you trying to remove these hyperlinks completely, or re-define the
displayed range so that it does not include the paragraph mark?

To change the displayed text, redefine the hyperlink's Range or
TextToDisplay properties. Removal is exactly as for any other hyperlink.
 
J

Jason Eacott

Ah, . thank you. your example code almost works.
it doesnt work for every case though, so now I have to figure out why it
wont
strip some paragraph marks.

Thank you. to ALL who helped.

Kindest Regards
Jason.
 
J

Jezebel

Don't know that it makes any difference here, but there was a thread in
VB.General a week or so ago arguing against using vbNullString in
expressions like this. The issue is that vbNullString is not strictly
equivalent to a zero length string (which is what's required here).
vbNullString is essentially a C construct, design for compatability with API
calls: it's a an empty pointer, as opposed to "" which is a pointer to
emptiness.
 
P

Peter Hewett

Hi Jezebel

For that reason vbNullString is actually more efficient than ""! When doing null string
comparisons in VB/VBA as you are aware, these three expression are effectively equal, but
are listed in order of least to most efficient:

If strTest = "" Then
If strTest = vbNullString
If LenB(strTest) = vbNullString

But when passing parameters or doing assignments I always use vbNullString. It always
works because strings are pointer types and you're just assigning a null reference.

But thanks for bringing it up in this thread.

Cheers - Peter


Don't know that it makes any difference here, but there was a thread in
VB.General a week or so ago arguing against using vbNullString in
expressions like this. The issue is that vbNullString is not strictly
equivalent to a zero length string (which is what's required here).
vbNullString is essentially a C construct, design for compatability with API
calls: it's a an empty pointer, as opposed to "" which is a pointer to
emptiness.

HTH + Cheers - Peter
 
G

Greg Maxey

Peter,

Your are the teacher, I am the student. What do you mean by "effectively
equal?" I ran this test:

Sub Test()
Dim strTest

strTest = ""

If strTest = "" Then
MsgBox "Check"
If strTest = vbNullString Then
MsgBox "Check"
If LenB(strTest) = vbNullString Then
MsgBox "Check"
Else: MsgBox "Houston Control we have a problem"
End If
End If
End If
End Sub

The third expression acts differently. The value is "0" rather than ""
 
J

Jezebel

This was one of the issues that prompted the original discussion; and
someone produced an example (unfortunately I can't now find it) of
vbNullString causing a program to crash, where using a zero-length string
does not. So although may be the appearance of efficiency, the wise folk of
the VB forum advised against using for any purpose other than that for which
it is intended -- API calls to C functions.
 
G

Greg Maxey

Well, I asked and you answered. Now I am off to find out what an API, call
and C function is.
 
J

Jezebel

API calls are calls to functions in non-VB DLLs. For example, to force a
form to appear above all other forms, you can use the SetWindowPos API call.
You have to declare the call, eg

Public Declare Function SetWindowPos _
Lib "user32" _
(ByVal hwnd As Long, ByVal hWndInsertAfter As Long, _
ByVal x As Long, ByVal y As Long, _
ByVal cx As Long, ByVal cy As Long, _
ByVal wFlags As Long) As Long

And you can then call it from within your VB/VBA code in the same way as
other functions. There are literally thousands of these API calls (do a
Google!) -- amongst other things they give you access to the low-level nuts
and bolts of Windows. You can even do things like switch your hard disks off
and on, check the CPU temperature, etc etc. These functions are mostly
written in C, and they are *very* fussy about the arguments you pass to
them. Some of them require null strings, which is a data type that does not
naturally occur in VB; hence the need for the vbNullString pseudo-constant.
 
G

Greg Maxey

Jezebel,

Thanks for the information. Its a crawl, walk, run thing. I'm not walking
yet :)
 
P

Peter Hewett

Hi Greg

It's a typo. It should of course have been:

If LenB(strTest) = 0 Then

When typing the worst to best list out I actually missed one out, here's the corrected
list:

If strTest = "" Then
If strTest = vbNullString Then
If Len(strTest) = 0 Then
If LenB(strTest) = 0 Then


The performance gain (try a million of so loops! ) comes from the fact that no string
comparison is actually performed! String are pointer types in VBA/VB, in other words what
you think of as your string variable (in our case strTest) is actually a pointer to part
of a BSTR structure. The BSTR structure contains the null terminated string (in unicode,
2 bytes per character including the null terminator) prefixed by a Long (4 bytes)
indicating the length of the string.

Using Len or better still LenB causes VBA only looks at the length part of strings BSTR
structure, rather than performing a string compare. The reason that vbNullString is
considered better than "", is that "" takes up 6 bytes of memory (4 bytes for the string
length and 2 for the null terminator character), whereas vbNullString is just a NULL
string-pointer. In other words there's no allocated string when using vbNullString.

I hope this makes some sense, even if it doesn't instead of writing:
If strTest = "" Then

use:
If LenB(strTest) = 0 Then

and don't bother with understanding why!

Cheers - Peter


Peter,

Your are the teacher, I am the student. What do you mean by "effectively
equal?" I ran this test:

Sub Test()
Dim strTest

strTest = ""

If strTest = "" Then
MsgBox "Check"
If strTest = vbNullString Then
MsgBox "Check"
If LenB(strTest) = vbNullString Then
MsgBox "Check"
Else: MsgBox "Houston Control we have a problem"
End If
End If
End If
End Sub

The third expression acts differently. The value is "0" rather than ""

HTH + Cheers - Peter
 
J

Jay Freedman

Hi Greg,

Karl Peterson has tons of VB example code using API calls on the
mvps.org site, and most of it runs unmodified or with minor changes in
VBA. Even better, he indexed it by the API calls that it illustrates.
Start at http://mvps.org/vb/apixref.htm and go from there -- have fun!
 
G

Greg Maxey

Jay,

Thanks for the pointer. I will have a look. I am still still stumbling
with See Dick run, and not sure that I am ready for the deep water yet :)
 
G

Greg Maxey

Peter,

Thanks for the explanation. I am becoming overloaded with tips, but I will
try to remember this one.
 
J

Jason Eacott

ok I've been playing with the suggestions for a while, and yes I can strip
out the paragraph mark ok (thank you), but I havent yet succeeded in
replacing it OUSTIDE of the hyperlink where it should be. If this isnt done
then I cant actually access the hyperlink address because the call to
...Hyperlink(x).address fails.
any thoughts?
 
B

Bob S

If LenB(strTest) Then
' non-zero length case
Else
'zero length case
End If

So is this (with reversed true and false cases) even faster because of
one less evaluation?

Clarity is not its strong point of course...

Bob S
 
P

Peter Hewett

Hi Bob S

Sorry the ammended code was (the earlier code I posted omitted the = 0):
If LenB(strTest) = 0 Then

It's fairly common in VB as opposed to VBA circles where the programmers are pushing the
envelope further. Once you've seen it you tend to remember what it means. It's an
optimisation that can be useful when needing to evaluate lots of strings. But if you're
knocking up a quick macro there's no real point .

Cheers - Peter


If LenB(strTest) Then
' non-zero length case
Else
'zero length case
End If

So is this (with reversed true and false cases) even faster because of
one less evaluation?

Clarity is not its strong point of course...

Bob S

HTH + Cheers - Peter
 

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