advanced labeling in arcmap with vbscript findlabel functions

1
Have you ever needed to do just a little bit or perhaps much more to label a featureclass in ArcMap than the standard ESRI or even Maplex labeling engine would allow? Me too. Lucky for us, with the release of ArcGIS 8.1, ESRI introduced "advanced" labeling to all licensing levels using the FindLabel function and your choice of two scripting languages: VBScript and JScript. Advanced labeling along with the FindLabel function provides a way to programmatically define the text that displays when labeling features. Through the use of code examples, we will focus on using VBScript and FindLabel functions to do advanced labeling of features by incorporating scripting functionality such as conditional logic, arrays, and regular expressions. With a little (or sometimes a lot) of code, users can either simplify or add complexity to their feature labels without having to modify the underlying data, create temporary datasets for the sole purpose of labeling, or convert labels to annotation and - oh, the horror - manually arrange labels by hand. Inspirations/other resources Hankley, Chip. Using VBScript to Build Complex Labels in ArcGIS. ArcUser. October-December 2004: 50-53. Online at http://www.esri.com/news/arcuser/1104/files/ vbscript_label.pdf Hoque, Mohammed A. Labeling Features Using Attributes from an External Database. ArcUser July-September 2005: 52-53. Online at http://www.esri.com/news/arcuser/0705/ files/externaldb.pdf exists This poster available as a pdf at: http://www.super-cooper.com/okscaug 1 Function FindLabel ([TOTNETAC], [NETNP], [NETPR], [NETHBP], [NETHBO], _ 2 [TOTNETFED], [NETFEDNP], [NETFEDPR], [NETFEDHBP], [NETFEDHBO]) 3 4 Dim iMaxValSz, h, i, j, k, space, intIndex, fedIntIndex, netArray, strLabel, strCarReturns, _ 5 strFedLabel, mathNP, mathHBP, mathPR 6 iMaxValSz = 0 ' set max value size initial value to zero 7 ' Set our field values into variables 8 totnetac = [TOTNETAC] 9 netnp = [NETNP] 10 netpr = [NETPR] 11 nethbp = [NETHBP] 12 nethbo = [NETHBO] 13 fednp = [NETFEDNP] 14 fedpr = [NETFEDPR] 15 fedhbp = [NETFEDHBP] 16 ' SECTIONS WITH FEDERAL LEASES 17 If FormatNumber([TOTNETFED]) > 0 Then 18 ' Do some math, compare fed to non‐fed NP/HBP/PR, if arent equal, get the difference 19 ' between the two, the non‐federal portion. If equal, set var to zero. Var goes into 20 ' array, if zero, ignore it, if non‐zero, display as non‐federal acreage 21 ' Compare NP/FNP 22 If [NETNP] = [NETFEDNP] Then 23 mathNP = "0" 24 Else 25 If ([NETNP] ‐ [NETFEDNP]) <= 0.5 Then 26 mathNP = FormatNumber(([NETNP] ‐ [NETFEDNP]),2) 27 ElseIf Right((FormatNumber(([NETNP] ‐ [NETFEDNP]),2)),2) = "00" Then 28 mathNP = FormatNumber(([NETNP] ‐ [NETFEDNP]),0) 29 ElseIf Right((FormatNumber(([NETNP] ‐ [NETFEDNP]),2)),2) <> "00" Then 30 mathNP = FormatNumber(([NETNP] ‐ [NETFEDNP]),2) 31 End If 32 End If 33 ' Compare HBP/FHBP 34 If [NETHBP] = [NETFEDHBP] Then 35 mathHBP = "0" 36 Else 37 If ([NETHBP] ‐ [NETFEDHBP]) <= 0.5 Then 38 mathHBP = FormatNumber(([NETHBP] ‐ [NETFEDHBP]),2) 39 ElseIf Right((FormatNumber(([NETHBP] ‐ [NETFEDHBP]),2)),2) = "00" Then 40 mathHBP = FormatNumber(([NETHBP] ‐ [NETFEDHBP]),0) 41 ElseIf Right((FormatNumber(([NETHBP] ‐ [NETFEDHBP]),2)),2) <> "00" Then 42 mathHBP = FormatNumber(([NETHBP] ‐ [NETFEDHBP]),2) 43 End If 44 End If 45 ' Compare PR/FPR 46 If [NETPR] = [NETFEDPR] Then 47 mathPR = "0" 48 Else 49 If ([NETPR] ‐ [NETFEDPR]) <= 0.5 Then 50 mathPR = FormatNumber(([NETPR] ‐ [NETFEDPR]),2) 51 ElseIf Right((FormatNumber(([NETPR] ‐ [NETFEDPR]),2)),2) = "00" Then 52 mathPR = FormatNumber(([NETPR] ‐ [NETFEDPR]),0) 53 ElseIf Right((FormatNumber(([NETPR] ‐ [NETFEDPR]),2)),2) <> "00" Then 54 mathPR = FormatNumber(([NETPR] ‐ [NETFEDPR]),2) 55 End If 56 End If 57 ' Build array for FED values, if mathNP/mathHBP/mathPR are zero, theyre ignored below when 58 ' tested, otherwise, they are included in the array explosion as non‐fed acreage 59 fedArray = Array(Array(totnetac, "<clr red='255'>", " CNT</clr>"), _ 60 Array(mathNP, "<clr red='0' green='0' blue='0'>", " NP</clr>"), _ 61 Array(mathHBP, "<clr red='0' green='0' blue='0'>", " HBP</clr>"), _ 62 Array(mathPR, "<clr red='0' green='0' blue='0'>", " PR</clr>"), _ 63 Array(fednp, "<clr red='132' green='0' blue='168'>", " FNP</clr>"), _ 64 Array(fedpr, "<clr red='132' green='0' blue='168'>", " FPR</clr>"), _ 65 Array(fedhbp, "<clr red='132' green='0' blue='168'>", " FHBP</clr>")) 66 ' Determine length of longest acreage string in array 67 ' Use it later to center longer strings in section 68 For i = 0 To UBound(fedArray) 69 j = fedArray(i) 70 If (Len(j(1)) > iMaxValSz) Then 71 iMaxValSz = Len(j(1)) 72 End If 73 Next 74 ' START MAKING LABEL 75 strFedLabel = "<bol>" 76 ' Explode array values, if they are > 0 77 k = fedArray(0) 78 fedIntIndex = 0 79 For h = 0 To UBound(fedArray) 80 k = fedArray(h) 81 82 If iMaxValSz > 2 Then ' push longer acreage strings over to 83 space = " " ' the left a little, center in section 84 Else 85 space = "" 86 End If 87 88 If k(0) > 0 Then 89 strFedLabel = strFedLabel & space & k(1) & k(0) & k(2) & vbNewLine 90 fedIntIndex = fedIntIndex + 1 ' count lines for non‐zero hits from array 91 End If 92 Next 93 ' Determine how many carriage returns are needed to top align 94 ' acreage list in the section polygon, based on line hits above 95 Select Case fedIntIndex 96 Case 2 97 strCarReturns = vbNewLine & vbNewLine 98 Case 3 99 strCarReturns = vbNewLine 100 Case Else 101 strCarReturns = "" 102 End Select 103 ' FINAL BUILD OF LABEL 104 FindLabel = strFedLabel & "</bol>" & strCarReturns 105 106 Else 107 ' SECTIONS WITHOUT FEDERAL LEASES 108 ' Build nested array of field values for non‐federal acreage 109 netArray = Array(Array(" CNT</clr>", totnetac, "<clr red='255'>"), _ 110 Array(" NP</clr>", netnp, "<clr red='0' green='0' blue='0'>"), _ 111 Array(" PR</clr>", netpr, "<clr red='0' green='0' blue='0'>"), _ 112 Array(" HBP</clr>", nethbp, "<clr red='0' green='0' blue='0'>"), _ 113 Array(" HBO</clr>", hbo, "<clr red='0' green='0' blue='0'>")) 114 ' Determine length of longest acreage string in array 115 ' Use it later to center longer strings in section 116 For i = 0 To UBound(netArray) 117 j = netArray(i) 118 If (Len(j(1)) > iMaxValSz) Then 119 iMaxValSz = Len(j(1)) 120 End If 121 Next 122 ' START BUILDING THE LABEL 123 strLabel = "<bol>" 124 ' Loop thru array, get our values, if not = 0 125 j = netArray(0) ' reset j to be first sub‐array in netArray 126 intIndex = 0 ' reset array counter 127 For i = 0 To UBound(netArray) 128 j = netArray(i) 129 130 If iMaxValSz > 2 Then ' push longer acreage strings over to 131 space = " " ' the left a little, center in section 132 Else 133 space = "" 134 End If 135 136 If j(1) > 0 Then ' test for zero values, skip em 137 strLabel = strLabel & space & j(2) & j(1) & j(0) & vbNewLine 138 intIndex = intIndex + 1 ' count how many returns we get 139 End If ' from our array, only non‐zero hits 140 Next 141 ' Determine how many carriage returns are needed to top align 142 ' acreage list in the section polygon, based on line hits above 143 Select Case intIndex 144 Case 2 145 strCarReturns = vbNewLine & vbNewLine 146 Case 3 147 strCarReturns = vbNewLine 148 Case Else 149 strCarReturns = "" 150 End Select 151 ' FINAL BUILD OF NON‐FEDERAL LABEL 152 FindLabel = strLabel & strFedLabel & "</bol>" & strCarReturns 153 End If 154 End Function The Problem You have a dataset with multiple attributes you want to label with, but when values are absent (zero or null), you want to skip that attribute. Also, it’s a polygon featureclass, so absolutely positioning the labels can be difficult. 1 Function FindLabel ([TOTNETAC],[NETPR],[NETNP],[NETHBP], [NETHBO],[NETFEDPR],[NETFEDNP],[NETFEDHBP]) 2 FindLabel = [TOTNETAC] & vbNewLine & [NETPR] & vbNewLine & _ 3 [NETNP] & vbNewLine & [NETHBP] & vbNewLine & _ 4 [NETHBO] & vbNewLine & [NETFEDPR] & vbNewLine & _ 5 [NETFEDNP] & vbNewLine & [NETFEDHBP] 6 End Function Better Solution Arrays to the rescue! Using a nested array, we can test values and only use valid ones in our label. We can also color the fonts of specific attributes, perform calculations using attribute values and place the results into our label array. By using a point featureclass (converted from the polygon featureclass) to label with, we have control over the absolute position of the labels around the points. Partial Solution Sure, we can stack the labels with a simple FindLabel function, but the results aren’t pretty at all. Values of zero get omitted from the array 1 Function FindLabel ( [Well_Name] ) 2 3 FindLabel = ParseWellName([Well_Name]) 4 5 End Function 6 7 Function ParseWellname(well_name) 8 9 Dim patt, reg_exp, repl 10 Set reg_exp = New RegExp 11 reg_exp.IgnoreCase = False 12 ' Regex to look for commingle, tubing, casing, inactive, 13 ' not active zones that we don't want labeled 14 patt = "(\s)" & _ 15 "(C*\s*T*\s*\(?CM\)?\s*(\(Inactive\)$|\(Not Active\))*$|" & _ 16 "C\s*(\(Inactive\)$|\(Not Active\))*$|" & _ 17 "T\s*(\(Inactive\)$|\(Not Active\))*$|" & _ 18 "UT \(Inactive\)$|" & _ 19 "LT \(Inactive\)$|" & _ 20 "(\(Inactive\)$|\(Not Active\))*$|" & _ 21 "C$|T$|UT$|LT$|" & _ 22 "(\(?CM\)?$|T|C)* \(?CM\)?$|" & _ 23 "[C|CM|T|LT|UT]*\s*STORAGE$)" 24 25 reg_exp.Pattern = patt 26 repl = "" 27 28 result = reg_exp.Replace(well_name, repl) 29 30 ParseWellname = result 31 32 End Function The Problem Here we have a point dataset (gas wells, to be more precise) where multiple points in the same location are stacked and each one has a different label. Each record for one well (some have only one point, some have 4+) represents a producing zone. The well names are almost identical except for codes that denote what zone the well is producing from. We need to get rid of the multiple labels, yet still show all of the points. The Solution Let’s put a regular expression to work for us. Regular expressions provide us with a way of identifying characters, words, or patterns of characters in strings of text. They are similar to wildcards, except much more powerful. For our label to work, you must have access to the Maplex labeling engine, since we are going to use the “Remove duplicate labels” function of the Maplex engine. Here’s how this works: a) Look at the attribute table for this dataset (upper right). Notice that well names are all based off of the lease name and have the zone information appended to that. If we can make the well names all the same, then the Maplex “Remove duplicates” function will remove all but one of those labels – with no modification of our underlying dataset! b) Our regular expression looks for the common combinations that occur in the zone names at the end of the well names (“CM”, “UT”, “Not Active”, etc.) and simply replaces those occurrences with “” - nothing. c) Now that our labels are all the same for any one well with multiple zones, Maplex drops the duplicates and leaves us just one – exactly what we wanted. For more information about using regular expressions with VBScript, see http://msdn.microsoft.com/en-us/library/ms974570.aspx or Google “regular expressions vbscript”. I also find the book VBScript in a Nutshell (published by O’Reilly, ISBN# 0596004885) to be an indispensable resource for writing FindLabel functions in VBScript. 2 Place it in the label expression 4 Set duplicate label search tolerance 1 Write the FindLabel function 3 Remove duplicate labels 1 Write the FindLabel function 2 Place it in the label expression 3 Absolutely position label around point BEFORE BEFORE AFTER AFTER DISCLAIMER: Not the most efficient or elegant regular expression, but it works

Upload: chad-cooper

Post on 19-Jun-2015

3.709 views

Category:

Technology


0 download

DESCRIPTION

Poster presented at the Oklahoma South Central Arc Users Group 2008 Annual Meeting. Norman, Oklahoma, September 2008

TRANSCRIPT

Page 1: Advanced Labeling In ArcMap With VBScript FindLabel Functions

Have you ever needed to do just a little bit or perhaps much

more to label a featureclass in ArcMap than the standard

ESRI or even Maplex labeling engine would allow? Me too.

Lucky for us, with the release of ArcGIS 8.1, ESRI

introduced "advanced" labeling to all licensing levels using

the FindLabel function and your choice of two scripting

languages: VBScript and JScript. Advanced labeling along

with the FindLabel function provides a way to

programmatically define the text that displays when labeling

features. Through the use of code examples, we will focus

on using VBScript and FindLabel functions to do advanced

labeling of features by incorporating scripting functionality

such as conditional logic, arrays, and regular expressions.

With a little (or sometimes a lot) of code, users can either

simplify or add complexity to their feature labels without

having to modify the underlying data, create temporary

datasets for the sole purpose of labeling, or convert labels

to annotation and - oh, the horror - manually arrange labels

by hand.

Inspirations/other resources

Hankley, Chip. Using VBScript to Build Complex Labels in

ArcGIS. ArcUser. October-December 2004: 50-53. Online

at http://www.esri.com/news/arcuser/1104/files/

vbscript_label.pdf

Hoque, Mohammed A. Labeling Features Using Attributes

from an External Database. ArcUser July-September 2005:

52-53. Online at http://www.esri.com/news/arcuser/0705/

files/externaldb.pdf

exists

This poster available as a pdf at: http://www.super-cooper.com/okscaug

1 Function FindLabel ([TOTNETAC], [NETNP], [NETPR], [NETHBP], [NETHBO], _

2 [TOTNETFED], [NETFEDNP], [NETFEDPR], [NETFEDHBP], [NETFEDHBO])

3

4 Dim iMaxValSz, h, i, j, k, space, intIndex, fedIntIndex, netArray, strLabel, strCarReturns, _

5 strFedLabel, mathNP, mathHBP, mathPR

6 iMaxValSz = 0 ' set max value size initial value to zero7 ' Set our field values into variables8 totnetac = [TOTNETAC]

9 netnp = [NETNP]

10 netpr = [NETPR]

11 nethbp = [NETHBP]

12 nethbo = [NETHBO]

13 fednp = [NETFEDNP]

14 fedpr = [NETFEDPR]

15 fedhbp = [NETFEDHBP]

16 ' SECTIONS WITH FEDERAL LEASES17 If FormatNumber([TOTNETFED]) > 0 Then

18 ' Do some math, compare fed to non‐fed NP/HBP/PR, if arent equal, get the difference 19 ' between the two, the non‐federal portion. If equal, set var to zero. Var goes into20 ' array, if zero, ignore it, if non‐zero, display as non‐federal acreage21 ' Compare NP/FNP22 If [NETNP] = [NETFEDNP] Then

23 mathNP = "0"24 Else

25 If ([NETNP] ‐ [NETFEDNP]) <= 0.5 Then

26 mathNP = FormatNumber(([NETNP] ‐ [NETFEDNP]),2)

27 ElseIf Right((FormatNumber(([NETNP] ‐ [NETFEDNP]),2)),2) = "00" Then

28 mathNP = FormatNumber(([NETNP] ‐ [NETFEDNP]),0)

29 ElseIf Right((FormatNumber(([NETNP] ‐ [NETFEDNP]),2)),2) <> "00" Then

30 mathNP = FormatNumber(([NETNP] ‐ [NETFEDNP]),2)

31 End If

32 End If

33 ' Compare HBP/FHBP34 If [NETHBP] = [NETFEDHBP] Then

35 mathHBP = "0"36 Else

37 If ([NETHBP] ‐ [NETFEDHBP]) <= 0.5 Then

38 mathHBP = FormatNumber(([NETHBP] ‐ [NETFEDHBP]),2)

39 ElseIf Right((FormatNumber(([NETHBP] ‐ [NETFEDHBP]),2)),2) = "00" Then

40 mathHBP = FormatNumber(([NETHBP] ‐ [NETFEDHBP]),0)

41 ElseIf Right((FormatNumber(([NETHBP] ‐ [NETFEDHBP]),2)),2) <> "00" Then

42 mathHBP = FormatNumber(([NETHBP] ‐ [NETFEDHBP]),2)

43 End If

44 End If

45 ' Compare PR/FPR46 If [NETPR] = [NETFEDPR] Then

47 mathPR = "0"48 Else

49 If ([NETPR] ‐ [NETFEDPR]) <= 0.5 Then

50 mathPR = FormatNumber(([NETPR] ‐ [NETFEDPR]),2)

51 ElseIf Right((FormatNumber(([NETPR] ‐ [NETFEDPR]),2)),2) = "00" Then

52 mathPR = FormatNumber(([NETPR] ‐ [NETFEDPR]),0)

53 ElseIf Right((FormatNumber(([NETPR] ‐ [NETFEDPR]),2)),2) <> "00" Then

54 mathPR = FormatNumber(([NETPR] ‐ [NETFEDPR]),2)

55 End If

56 End If

57 ' Build array for FED values, if mathNP/mathHBP/mathPR are zero, theyre ignored below when58 ' tested, otherwise, they are included in the array explosion as non‐fed acreage59 fedArray = Array(Array(totnetac, "<clr red='255'>", " CNT</clr>"), _60 Array(mathNP, "<clr red='0' green='0' blue='0'>", " NP</clr>"), _61 Array(mathHBP, "<clr red='0' green='0' blue='0'>", " HBP</clr>"), _62 Array(mathPR, "<clr red='0' green='0' blue='0'>", " PR</clr>"), _63 Array(fednp, "<clr red='132' green='0' blue='168'>", " FNP</clr>"), _64 Array(fedpr, "<clr red='132' green='0' blue='168'>", " FPR</clr>"), _65 Array(fedhbp, "<clr red='132' green='0' blue='168'>", " FHBP</clr>"))66 ' Determine length of longest acreage string in array67 ' Use it later to center longer strings in section68 For i = 0 To UBound(fedArray)

69 j = fedArray(i)

70 If (Len(j(1)) > iMaxValSz) Then

71 iMaxValSz = Len(j(1))

72 End If

73 Next

74 ' START MAKING LABEL75 strFedLabel = "<bol>"76 ' Explode array values, if they are > 077 k = fedArray(0)

78 fedIntIndex = 0

79 For h = 0 To UBound(fedArray)

80 k = fedArray(h)

81

82 If iMaxValSz > 2 Then ' push longer acreage strings over to 83 space = " " ' the left a little, center in section84 Else

85 space = ""86 End If

87

88 If k(0) > 0 Then

89 strFedLabel = strFedLabel & space & k(1) & k(0) & k(2) & vbNewLine

90 fedIntIndex = fedIntIndex + 1 ' count lines for non‐zero hits from array91 End If

92 Next

93 ' Determine how many carriage returns are needed to top align94 ' acreage list in the section polygon, based on line hits above95 Select Case fedIntIndex

96 Case 2

97 strCarReturns = vbNewLine & vbNewLine

98 Case 3

99 strCarReturns = vbNewLine

100 Case Else

101 strCarReturns = ""102 End Select

103 ' FINAL BUILD OF LABEL104 FindLabel = strFedLabel & "</bol>" & strCarReturns

105

106 Else

107 ' SECTIONS WITHOUT FEDERAL LEASES108 ' Build nested array of field values for non‐federal acreage109 netArray = Array(Array(" CNT</clr>", totnetac, "<clr red='255'>"), _110 Array(" NP</clr>", netnp, "<clr red='0' green='0' blue='0'>"), _111 Array(" PR</clr>", netpr, "<clr red='0' green='0' blue='0'>"), _112 Array(" HBP</clr>", nethbp, "<clr red='0' green='0' blue='0'>"), _113 Array(" HBO</clr>", hbo, "<clr red='0' green='0' blue='0'>"))114 ' Determine length of longest acreage string in array115 ' Use it later to center longer strings in section116 For i = 0 To UBound(netArray)

117 j = netArray(i)

118 If (Len(j(1)) > iMaxValSz) Then

119 iMaxValSz = Len(j(1))

120 End If

121 Next

122 ' START BUILDING THE LABEL123 strLabel = "<bol>"124 ' Loop thru array, get our values, if not = 0125 j = netArray(0) ' reset j to be first sub‐array in netArray126 intIndex = 0 ' reset array counter127 For i = 0 To UBound(netArray)

128 j = netArray(i)

129

130 If iMaxValSz > 2 Then ' push longer acreage strings over to 131 space = " " ' the left a little, center in section132 Else

133 space = ""134 End If

135

136 If j(1) > 0 Then ' test for zero values, skip em137 strLabel = strLabel & space & j(2) & j(1) & j(0) & vbNewLine

138 intIndex = intIndex + 1 ' count how many returns we get139 End If ' from our array, only non‐zero hits140 Next

141 ' Determine how many carriage returns are needed to top align142 ' acreage list in the section polygon, based on line hits above143 Select Case intIndex

144 Case 2

145 strCarReturns = vbNewLine & vbNewLine

146 Case 3

147 strCarReturns = vbNewLine

148 Case Else

149 strCarReturns = ""150 End Select

151 ' FINAL BUILD OF NON‐FEDERAL LABEL152 FindLabel = strLabel & strFedLabel & "</bol>" & strCarReturns

153 End If

154 End Function

The Problem

You have a dataset with multiple attributes

you want to label with, but when values are

absent (zero or null), you want to skip that

attribute. Also, it’s a polygon featureclass,

so absolutely positioning the labels can be

difficult.

1 Function FindLabel ([TOTNETAC],[NETPR],[NETNP],[NETHBP],

[NETHBO],[NETFEDPR],[NETFEDNP],[NETFEDHBP])

2 FindLabel = [TOTNETAC] & vbNewLine & [NETPR] & vbNewLine & _

3 [NETNP] & vbNewLine & [NETHBP] & vbNewLine & _

4 [NETHBO] & vbNewLine & [NETFEDPR] & vbNewLine & _

5 [NETFEDNP] & vbNewLine & [NETFEDHBP]

6 End Function

Better Solution

Arrays to the rescue! Using a nested array,

we can test values and only use valid ones in

our label. We can also color the fonts of

specific attributes, perform calculations using

attribute values and place the results into our

label array. By using a point featureclass

(converted from the polygon featureclass) to

label with, we have control over the absolute

position of the labels around the points.

Partial Solution

Sure, we can stack the labels with a simple

FindLabel function, but the results aren’t pretty at all.

Values of zero

get omitted

from the array

1 Function FindLabel ( [Well_Name] )

2

3 FindLabel = ParseWellName([Well_Name])

4

5 End Function

6

7 Function ParseWellname(well_name)

8

9 Dim patt, reg_exp, repl

10 Set reg_exp = New RegExp

11 reg_exp.IgnoreCase = False

12 ' Regex to look for commingle, tubing, casing, inactive,13 ' not active zones that we don't want labeled 14 patt = "(\s)" & _

15 "(C*\s*T*\s*\(?CM\)?\s*(\(Inactive\)$|\(Not Active\))*$|" & _

16 "C\s*(\(Inactive\)$|\(Not Active\))*$|" & _

17 "T\s*(\(Inactive\)$|\(Not Active\))*$|" & _

18 "UT \(Inactive\)$|" & _

19 "LT \(Inactive\)$|" & _

20 "(\(Inactive\)$|\(Not Active\))*$|" & _

21 "C$|T$|UT$|LT$|" & _

22 "(\(?CM\)?$|T|C)* \(?CM\)?$|" & _

23 "[C|CM|T|LT|UT]*\s*STORAGE$)"24

25 reg_exp.Pattern = patt

26 repl = ""27

28 result = reg_exp.Replace(well_name, repl)

29

30 ParseWellname = result

31

32 End Function

The Problem

Here we have a point dataset (gas wells, to be more precise) where multiple

points in the same location are stacked and each one has a different label. Each

record for one well (some have only one point, some have 4+) represents a

producing zone. The well names are almost identical except for codes that denote

what zone the well is producing from. We need to get rid of the multiple labels, yet

still show all of the points.

The Solution

Let’s put a regular expression to work for us. Regular expressions

provide us with a way of identifying characters, words, or patterns

of characters in strings of text. They are similar to wildcards,

except much more powerful. For our label to work, you must have

access to the Maplex labeling engine, since we are going to use

the “Remove duplicate labels” function of the Maplex engine.

Here’s how this works:

a) Look at the attribute table for this dataset (upper right). Notice

that well names are all based off of the lease name and have the

zone information appended to that. If we can make the well names

all the same, then the Maplex “Remove duplicates” function will

remove all but one of those labels – with no modification of our

underlying dataset!

b) Our regular expression looks for the common combinations that

occur in the zone names at the end of the well names (“CM”, “UT”,

“Not Active”, etc.) and simply replaces those occurrences with “” -

nothing.

c) Now that our labels are all the same for any one well with

multiple zones, Maplex drops the duplicates and leaves us just one

– exactly what we wanted.

For more information about using regular expressions with VBScript, see http://msdn.microsoft.com/en-us/library/ms974570.aspx or Google “regular expressions vbscript”.

I also find the book VBScript in a Nutshell (published by O’Reilly, ISBN# 0596004885) to be an indispensable resource for writing FindLabel functions in VBScript.

2 Place it in the

label expression

4 Set duplicate label

search tolerance

1 Write the FindLabel

function

3 Remove duplicate

labels

1 Write the FindLabel

function

2 Place it in the

label expression

3 Absolutely position

label around point

BEFOREBEFORE

AFTER

AFTER

DISCLAIMER: Not the

most efficient or elegant

regular expression, but

it works