I am working with a "map book" that has a large number of call outs (~3000). We have a request to change the line color and weight for the leaders. The annotation is in a SDE feature class. Is it possible to do this change in bulk?
ArcGIS 10.1
Thanks!
Just to check... this doesn't do it in bulk I suppose
Ya, looks like that has to do with setting up a "default" anno style before you place it.
I have also tried selecting a bunch of them (30 or so) and updating them with the Attribute panel; however, only one is updated. Furthermore, the far end of the leader is "reset" (i.e. the length of the leader is reduced to zero). So one must drag the leader back to the feature that the anno is referring to. I fear that even if I do find a way to mass update the annotation I would still need to drag all the leaders back by hand....
You certainly should be able to do this with ArcObjects. I did something kinda similar about 10 years ago using ArcObjects and VBA. I developed some internal tools to help automate and speed up mapping emergency road closures & one map product used balloon callouts that were symbolized either green (re-opened) or red (closed). Rather than drill down 12 levels in the symbol properties, I used VBA ArcObjects to quickly "flip" the color for the selected callout.
Screenshot:
And here's the VBA code:
Private Sub ToggleLabelColor_Click()
'==========================================================================
'This subroutine adds a one point white halo to the currently selected label
'==========================================================================
Dim pIMxDoc As IMxDocument
Dim pMap As IMap
Dim pActiveView As IActiveView
Dim pGraphSel As IGraphicsContainerSelect
Dim numSel As Integer
Dim pEnv As IEnvelope
Dim pDisplay As IDisplay
Dim pContainer As IGraphicsContainer
Dim pSymbol As ITextSymbol
Dim myColor As IRgbColor
Dim whiteFill As IRgbColor
Dim pTextElement As ITextElement
Dim pCallout As IBalloonCallout
Dim pFillSymbol As IFillSymbol
Dim pLineSymbol As ILineSymbol
Dim pTextBackground As ITextBackground
Dim pTextSymbol As IFormattedTextSymbolSet pIMxDoc = ThisDocument
Set pActiveView = pIMxDoc.FocusMap
Set pDisplay = pActiveView.ScreenDisplay
Set pMap = pIMxDoc.FocusMap
Set pContainer = pIMxDoc.FocusMap
Set pGraphSel = pContainer
'--------------------------------------------------------------------------
'Make sure only one label is selected. Adjust as desired..
'--------------------------------------------------------------------------
numSel = pGraphSel.ElementSelectionCount
Dim index As Integer
Dim pElement As IElement
Dim haloSize As Double
For index = 0 To numSel - 1
Set pElement = pGraphSel.SelectedElement(index)
If TypeOf pElement Is ITextElement Then
Set pTextElement = pGraphSel.SelectedElement(index)
Set pSymbol = pTextElement.Symbol
Set myColor = pSymbol.Color
If myColor.Red = 255 Then
'Road is changing from closed to OPEN
myColor.Red = 38
myColor.Green = 115
myColor.Blue = 0
'MsgBox "This road is closed!", vbInformation, "Results"
Else
'Road is changing from open to CLOSED
myColor.Red = 255
myColor.Green = 0
myColor.Blue = 0
'MsgBox "This road is open!", vbInformation, "Results"
End If
pSymbol.Color = myColor
Set whiteFill = New RgbColor
whiteFill.Red = 255
whiteFill.Green = 255
whiteFill.Blue = 255
Set pLineSymbol = New SimpleLineSymbol
Set pFillSymbol = New SimpleFillSymbol
pLineSymbol.Color = myColor
pLineSymbol.Width = 1
pFillSymbol.Color = whiteFill
pFillSymbol.Outline = pLineSymbol
pTextElement.Symbol = pSymbol
Set pElement = pTextElement
Set pTextSymbol = pTextElement.Symbol
Set pTextBackground = pTextSymbol.Background
Set pCallout = pTextBackground
Set pCallout.Symbol = pFillSymbol '.Outline.Color = myColor
Set pTextSymbol.Background = pCallout
pTextElement.Symbol = pTextSymbol
Set pElement = pTextElement
End If
Next indexpActiveView.PartialRefresh esriViewGraphics, Nothing, Nothing
'----------------------------------------------------------------------
'Release any memory allocated
'----------------------------------------------------------------------
Set pElement = Nothing
Set pTextElement = Nothing
End SubPrivate Function ToggleLabelColor_Message() As String
ToggleLabelColor_Message = "Toggles the Road Closure Balloon Callout Color Between Red (Closed) and Green (open)"
End FunctionPrivate Function ToggleLabelColor_ToolTip() As String
ToggleLabelColor_ToolTip = "Toggle Closure Callout Color"
End Function
In the example above, I'm working with graphic labels within an MXD but I think the principle is the same in terms of accessing the symbol properties for a callout.
Sorry I don't have a Dot Net version of this code since we moved away from producing the PDF map based updates during events.
Steve
Hah. Spoke too soon. Looks like I kind of have a Dot Net version of the VBA code. I frankly don't know if this works. I think it does but it's been years since I used it. Looks like this updated code only changes the color TO green in this example but you get the idea:
Imports ESRI.ArcGIS.ArcMapUI
Imports ESRI.ArcGIS.Carto
Imports ESRI.ArcGIS.DisplayPublic Class cmdMakeLabelGreen
Inherits ESRI.ArcGIS.Desktop.AddIns.ButtonPublic Sub New()
End Sub
Protected Overrides Sub OnClick()
Dim application As ESRI.ArcGIS.Framework.IApplication = Nothing
Dim pIMxDoc As IMxDocument
Dim pMap As IMap
Dim pActiveView As IActiveView
Dim pGraphSel As IGraphicsContainerSelect
Dim numSel As Integer
Dim pDisplay As IDisplay
Dim pContainer As IGraphicsContainer
Dim pSymbol As ITextSymbol
Dim myColor As IRgbColor
Dim whiteFill As IRgbColor
Dim pTextElement As ITextElementDim pCallout As IBalloonCallout
Dim pFillSymbol As IFillSymbol
Dim pLineSymbol As ILineSymbol
Dim pTextBackground As ITextBackground
Dim pTextSymbol As IFormattedTextSymbolTry
application = My.ArcMap.Application
Dim document As ESRI.ArcGIS.Framework.IDocument = application.Document
'pMxDoc = application.Document
pIMxDoc = CType(document, ESRI.ArcGIS.ArcMapUI.IMxDocument)
pActiveView = pIMxDoc.FocusMap
pDisplay = pActiveView.ScreenDisplay
pMap = pIMxDoc.FocusMappContainer = pIMxDoc.FocusMap
pGraphSel = pContainer
'--------------------------------------------------------------------------
'Make sure only one label is selected. Adjust as desired..
'--------------------------------------------------------------------------
numSel = pGraphSel.ElementSelectionCountSelect Case numSel
Case 0
MsgBox("You must select a label!", vbExclamation, "Error Encountered")
Exit Sub
Case 1
'Do Nothing
Case Else
MsgBox("You must have one label selected!", vbExclamation, "Error Encountered")
Exit Sub
End SelectDim index As Integer
Dim pElement As IElementFor index = 0 To numSel - 1
pElement = pGraphSel.SelectedElement(index)
If TypeOf pElement Is ITextElement Then
pTextElement = pGraphSel.SelectedElement(index)
pSymbol = pTextElement.SymbolmyColor = pSymbol.Color
'Road is changing from closed to OPEN
myColor.Red = 38
myColor.Green = 115
myColor.Blue = 0
pSymbol.Color = myColorwhiteFill = New RgbColor
whiteFill.Red = 255
whiteFill.Green = 255
whiteFill.Blue = 255pLineSymbol = New SimpleLineSymbol
pFillSymbol = New SimpleFillSymbol
pLineSymbol.Color = myColor
pLineSymbol.Width = 1pFillSymbol.Color = whiteFill
pFillSymbol.Outline = pLineSymbolpTextElement.Symbol = pSymbol
pElement = pTextElement
pTextSymbol = pTextElement.Symbol
pTextBackground = pTextSymbol.Background
pCallout = pTextBackgroundpCallout.Symbol = pFillSymbol '.Outline.Color = myColor
pTextSymbol.Background = pCallout
pTextElement.Symbol = pTextSymbolpElement = pTextElement
pContainer.UpdateElement(pElement)
End If
Next indexpActiveView.PartialRefresh(ESRI.ArcGIS.Carto.esriViewDrawPhase.esriViewGeography, Nothing, Nothing)
'----------------------------------------------------------------------
'Release any memory allocated
'----------------------------------------------------------------------
pElement = Nothing
pTextElement = Nothing
pLineSymbol = Nothing
pFillSymbol = Nothing
pTextSymbol = Nothing
pActiveView = Nothing
whiteFill = Nothing
pSymbol = Nothing
myColor = Nothing
pGraphSel = Nothing
pContainer = Nothing
pMap = Nothing
pDisplay = Nothing
pIMxDoc = Nothing
pTextBackground = Nothing
Catch ex As Exception
globalErrorHandler(ex)
End Try
End SubProtected Overrides Sub OnUpdate()
End Sub
End Class
This worked well in a test run: