I have blogged earlier about the possibility to submit calls to methods defined in classes stored within a .NET library either using
clr (with the help of
pythonnet) or using native
ctypes depending on how your libraries have been compiled. I have also shared some of the examples on how one can use
comtypes to access
COM-objects of ArcGIS Desktop to be able interact with ArcObjects via Python without writing any C#, Java, or C++ code.
This time, I need combine these approaches. I have to execute a tool on a toolbar in ArcMap (this can be a custom .NET add-in or a built-in tool such as
Full Extent) from Python code while working in an open ArcMap session. This is different from what I’ve done before because I have always worked with
comtypes in a stand-alone mode accessing existing map documents stored on the disk. This time, I have to use
comtypes within an ArcMap session hooking into the currently open map document.
Fortunately, this wasn’t as hard as I expected. I just had to use the standard interface to get into the application, and then into the map document, and then into the command bars available. The last thing you would need to do is to find the tool you need and then execute it. I’ve published a snippet that would get you started.
The first one is for calling the
Full Extent button on the Tools toolbar in ArcMap. The second one is for calling a button on a custom toolbar that is part of a custom .NET add-in in ArcMap. You can both of these samples as a part of a custom Python script tool or a Python add-in.
In ArcMap, in the
Editor toolbar, you can find a command
Copy Parallel which will create a copy of a selected line feature at an offset distance you specify. This command is unique to the
Editor toolbar and is not available as a geoprocessing tool. This makes it impossible to create parallel lines in batch (say, create lines to the both sides of the selected line feature starting with 10 meters up to 100 meters with the step of 20 meters).
A neat thing that exists in ArcMap is that you can assign a shortcut key to any command you can find in the
Customize menu > Commands tab window. So, your workflow could look like this: you start the editing session, select a feature, use your shortcut key (e.g., Ctrl-Alt-P) and enter the offset value in the
Copy Parallel window that appears. However, this implies that you would need to type an offset value for every copy to be created and you might also need to change other options in the window.
It’s important to understand that creating a parallel copy of a feature in the context of ArcGIS is not the same as creating a feature with a specified offset (because I thought it was). Compare the features produced using the
Copy Parallel command (to the left) and using Python code (that just moves each vertex of a feature using an offset value) (to the right):
As you can see, the length of line segments can change when using the
Copy Parallel command where as just moving vertices with offset preserves length of the segments.
You can call the
Copy Parallel command using ArcObjects (just like any other command) but you won’t be able to supply any input parameters such as the offset value. So, it’s no different from assigning a shortcut key. The only solution left is to implement an own version of
Copy Parallel that will mimic the built-in command. I have written an ArcGIS .NET add-in that can be called from a custom toolbar.
One can specify the intervals in a text box and then click the button.
This is the code for the combo box item and for the button item:
This is yet another post on how to use ArcObjects and Python comtypes package to call ArcObjects COM objects using Python. In this example, we have a map document with a couple of layout elements pre-created such as a scale bar, a north arrow, and a scale text. We would like to modify the scale bar label. Currently, it is ‘Miles’, but we have decided that we would like to change this label to be ‘Miles (1.6 km)’ for all our map documents we are going to export to pdf later on.
arcpy site-package doesn’t provide a way to either read or write this information when accessing a MapsurroundElement object. This means we have to use ArcObjects. Keep in mind that through ArcObjects, you can read/write many other properties of the scale bar such as divisions, symbols, text formatting and many others.
Here is the code that will update scale bar unit label:
When automating mapping production and exporting your map document layouts, you may need to manage map grids. They are grids or graticules which show the network of latitude and longitude lines in the layout.
For the very least, you would like to hide/show map grids in a map document’s data frame before exporting the map. The reason for this is that if your grid cell is of 1×1 km size, when exporting the map layout being in a small extent (for instance, 1: 1,000,000 you will get a pretty much no map except a black image because the grid will take all the place.
Being able to access map grids can also be handy when you have multiple grids with different grid cell sizes and you want to be able to control at what map scales each of the map grids should be visible.
Unfortunately, you cannot use arcpy to access grids defined for a data frame. However, the grids are exposed via an ArcGIS extension called Production Mapping which according to the Esri Help page
streamlines your GIS data and map production by providing tools that facilitate data creation, maintenance, and validation, as well as tools for producing high-quality cartographic products.
You might be surprised to learn this, but Production Mapping extension has its own arcpy-like site-package called arcpyproduction. Within this package, there is a class Grid class which provides access to grid properties for a grids and graticules layer. However, if you don’t have Production Mapping extension (it might be hard to justify buying this extension if you are not involved in heavy map production), as map grids are not exposed via arcpy, you have to use ArcObjects.
Since many would like to automate showing/hiding map grids when exporting map layouts, I’ve written a tiny function which can do that using Python. I have blogged earlier about how to start using ArcObjects from Python, so make sure to read this post first. Using this code, you will be able to choose which map grid you would like to use (if you have multiple grids with different cell size defined) when exporting a map layout.