Monday, 10 September 2018

How to trigger a Python script from an ArcGIS Desktop "save" operation?


Similar to the question Run a Python Script when opening an MXD, I'm looking for a way to run a Python script that is triggered when the "Save" command/button is pressed.


I've read the Creating a Python add-in application extension help for building a Python Add-In, but I don't see an interface in the Extension class that triggers upon Save, only close.


Is there something I might be overlooking? Otherwise, what are my alternative options other than ArcObjects, which is a road I am not willing to explore for this idea?



Answer



I found something in ArcObjects that will do the job. Thanks to This Post by Kirk Kuykendall as implemented on This Post by Rebecca Zeckoski. This is very counter-intuitive, the interface to find button clicks is ICustomizationFilter, which detects when a command is about to run (any command that implements ICommand I think).


Using Visual Studio I created an ArcMap addin and selected Extension and AutoLoad, then added a class alongside which implements ICustomizationFilter, using the LockCustomization method of the application the class is linked to the event then call the python script by (in this case) shell() other methods are discussed in this post; I'm not sure if you can make an ICommandItem from a python add-in but that would be how I would execute custom ArcObjects code.


Public Class Extension1 
Inherits ESRI.ArcGIS.Desktop.AddIns.Extension
'I am not using this event'

Public Sub New()
End Sub

Protected Overrides Sub OnStartup()
WireDocumentEvents() ' uncomment this, it is here by default'
End Sub

Protected Overrides Sub OnShutdown()
End Sub


Private Sub WireDocumentEvents()
AddHandler My.ArcMap.Events.NewDocument, AddressOf ArcMapNewDocument ' this is a default event'
AddHandler My.ArcMap.Events.OpenDocument, AddressOf ArcMapDocumentOpen ' add this event'
End Sub

Private Sub ArcMapNewDocument()
' Wire the event here in case the user starts with a blank'
' map and saves... this event does not survive a file::open'
Dim pCustFlt As ESRI.ArcGIS.Framework.ICustomizationFilter = New CustFlt
My.ArcMap.Application.LockCustomization("myLock", pCustFlt)

End Sub
Private Sub ArcMapDocumentOpen()
' When the document is opened wire the events to it'
' otherwise they dissapear after a new MXD is opened.'
Dim pCustFlt As ESRI.ArcGIS.Framework.ICustomizationFilter = New CustFlt
My.ArcMap.Application.LockCustomization("myLock", pCustFlt)
End Sub
End Class
Class CustFlt ' new class to implement the filter'
Implements ESRI.ArcGIS.Framework.ICustomizationFilter


Public Function OnCustomizationEvent(custEventType As ESRI.ArcGIS.Framework.esriCustomizationEvent, eventCtx As Object) As Boolean Implements ESRI.ArcGIS.Framework.ICustomizationFilter.OnCustomizationEvent
' modified from Rebecca Zeckoskis' post http://rzeckoskiengineering.blogspot.com.au/2012/06/capturing-button-clicks-in-arcobjects.html
' inspired by Kirk Kuykendalls' post https://gis.stackexchange.com/questions/8149/can-i-listen-to-the-icommandbar-or-icommand-onclick-event

If custEventType = ESRI.ArcGIS.Framework.esriCustomizationEvent.esriCEInvokeCommand Then
' if it is a call to invoke a command then find the command
' that is being invoked (executed)
Dim cmd As ESRI.ArcGIS.Framework.ICommandItem
cmd = TryCast(eventCtx, ESRI.ArcGIS.Framework.ICommandItem)


' find the name of the command, there's a whole bunch of them
' at http://resources.arcgis.com/en/help/arcobjects-net/conceptualhelp/index.html#//00010000029s000000
' search by tool caption to find others, you can use either the name or GUID/CLSID
If cmd.Name = "File_Save" Then
MsgBox("Customization Save") ' run your python here
' if you have a custom ArcObjects tool here you could make a new
' ICommandItem and execute, not sure if that works for python
' addins. You can call the shell with the path like this:
Shell("c:\path\to\your\script.py", AppWinStyle.Hide, False) ' returns an integer

' see https://stackoverflow.com/questions/13807860/execute-python-script-from-vb-net
End If
End If

Return False

End Function
End Class

No comments:

Post a Comment

arcpy - Changing output name when exporting data driven pages to JPG?

Is there a way to save the output JPG, changing the output file name to the page name, instead of page number? I mean changing the script fo...