├── Add_Ins ├── Add_Ins.esriaddin ├── Images │ ├── Database 1.png │ ├── LayoutIcon.png │ ├── LayoutToolbar.png │ ├── PDFexport.png │ ├── Textbox.png │ ├── Thumbs.db │ ├── button_grey_record.png │ ├── restoreLayout.png │ └── world.png ├── Install │ └── Add_Ins_addin.py ├── README.md ├── README.txt ├── config.xml └── makeaddin.py ├── Annotation ├── Annotation.esriaddin ├── Images │ ├── Thumbs.db │ ├── bw-annotate.png │ ├── glyphicons-100-vector-path-all.png │ └── letterA.png ├── Install │ └── Annotation_addin.py ├── README.txt ├── config.xml ├── makeaddin.py └── py │ ├── TiledAnno.py │ ├── dataFrameExtentPolygons.py │ └── dataFrameExtentPolygons_SinglePage.py ├── Annotation_Stand_Alone ├── Annotation_Cmd-SingleDF.py └── Annotation_Cmd.py ├── Cycle_Drives ├── Cycle_Drives.esriaddin ├── Images │ ├── cycle.png │ └── switch.png ├── Install │ └── Cycle_Drives_addin.py ├── README.txt ├── config.xml └── makeaddin.py ├── Dynamic_Elements ├── Dynamic_Elements.esriaddin ├── Images │ ├── Textbox.png │ └── eye-chart.png ├── Install │ ├── Dynamic_Elements_addin.py │ └── svaBoxSizing.py ├── README.txt ├── config.xml └── makeaddin.py ├── Functions ├── adjustElementsFunctions.py ├── clearAllQueries.py ├── clearSelectedLayerQuery.py ├── genericCmdPrompt.py ├── getSelectionSet.py └── querySelection.py ├── Layers ├── Images │ ├── 45.png │ ├── 45_1.png │ ├── Thumbs.db │ ├── computerscreen5.png │ ├── dropdown.gif │ └── maps-and-geolocation-layers-icon.png ├── Install │ ├── Layers_addin.py │ ├── __init__.py │ ├── autoPath.py │ └── createDefaultLyrs.py ├── Layers.esriaddin ├── README.txt ├── config.xml └── makeaddin.py ├── PDF_Export_Addin ├── Images │ ├── Thumbs.db │ ├── cmyk.png │ ├── cube-128.png │ ├── draftIcon.png │ ├── pdf-icon.png │ └── rgb.png ├── Install │ └── PDF_Export_Addin_addin.py ├── PDF_Export_Addin.esriaddin ├── README.txt ├── config.xml └── makeaddin.py ├── PDF_Export_Stand_Alone └── PDF_Export_Cmd.py ├── Page Layout Table ├── PageLayoutElements.cpg ├── PageLayoutElements.dbf.xml └── info │ └── arc.dir ├── Python ├── AnnoQuery.py ├── BrokenDataSources.py ├── ExtentBoxexRemovePts.py ├── RepairBrokenLayers.py ├── SDE_to_FGDB_BuiltInList.py ├── SelectCommunities.py ├── SelectPointsInTargetED.py ├── StripDataFromMXD.py ├── _template.py ├── batchRename.py ├── dataFrameExtentPolygons.py ├── dataFrameExtentPolygonsModified.py ├── dataframePolygon.cpg ├── dataframePolygon.dbf ├── dataframePolygon.sbn ├── dataframePolygon.sbx ├── dataframePolygon.shp ├── dataframePolygon.shp.xml ├── dataframePolygon.shx ├── dataframePolygonsY_sq.cpg ├── dataframePolygonsY_sq.dbf ├── dataframePolygonsY_sq.sbn ├── dataframePolygonsY_sq.sbx ├── dataframePolygonsY_sq.shp ├── dataframePolygonsY_sq.shp.xml ├── dataframePolygonsY_sq.shx ├── dfScaleMatch.py ├── nameElements.py ├── orginalGetSettings.py └── writeScaleRotation.py ├── QuerySelection ├── Images │ ├── ClearQueryCube.png │ ├── EDHighlight.png │ ├── Thumbs.db │ └── spatialQuery.png ├── Install │ ├── QuerySelection_addin.py │ ├── clearAllQueries.py │ ├── clearSelectedLayerQuery.py │ ├── getSelectionSet.py │ └── querySelected.py ├── QuerySelection.esriaddin ├── README.txt ├── config.xml └── makeaddin.py ├── README.md ├── SDE_Replication └── ReplicateSDE.py ├── SQL ├── PrelimReport87EDs_web.dbf ├── PrelimReport87EDs_web.prj ├── PrelimReport87EDs_web.shp ├── PrelimReport87EDs_web.shx ├── createViewSDE.sql └── tcn_road_type_QUERY.txt ├── XY └── shpToTxtCoords.py └── addin-wizard ├── .hgtags ├── AddinMaker.wxg ├── LICENSE ├── README.md ├── addin.py ├── addin_assistant.pyw ├── addin_ui.py ├── i18n.py ├── images ├── AddInDesktop.ico ├── AddInDesktop48.png ├── AddInDesktop64.png └── Thumbs.db ├── packaging ├── README.txt └── makeaddin.py ├── resources └── resource_strings.json └── setup.py /Add_Ins/Add_Ins.esriaddin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jstep/Arcpy/1cf1c68de1d598069d1e98ad4de68c8273fd9792/Add_Ins/Add_Ins.esriaddin -------------------------------------------------------------------------------- /Add_Ins/Images/Database 1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jstep/Arcpy/1cf1c68de1d598069d1e98ad4de68c8273fd9792/Add_Ins/Images/Database 1.png -------------------------------------------------------------------------------- /Add_Ins/Images/LayoutIcon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jstep/Arcpy/1cf1c68de1d598069d1e98ad4de68c8273fd9792/Add_Ins/Images/LayoutIcon.png -------------------------------------------------------------------------------- /Add_Ins/Images/LayoutToolbar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jstep/Arcpy/1cf1c68de1d598069d1e98ad4de68c8273fd9792/Add_Ins/Images/LayoutToolbar.png -------------------------------------------------------------------------------- /Add_Ins/Images/PDFexport.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jstep/Arcpy/1cf1c68de1d598069d1e98ad4de68c8273fd9792/Add_Ins/Images/PDFexport.png -------------------------------------------------------------------------------- /Add_Ins/Images/Textbox.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jstep/Arcpy/1cf1c68de1d598069d1e98ad4de68c8273fd9792/Add_Ins/Images/Textbox.png -------------------------------------------------------------------------------- /Add_Ins/Images/Thumbs.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jstep/Arcpy/1cf1c68de1d598069d1e98ad4de68c8273fd9792/Add_Ins/Images/Thumbs.db -------------------------------------------------------------------------------- /Add_Ins/Images/button_grey_record.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jstep/Arcpy/1cf1c68de1d598069d1e98ad4de68c8273fd9792/Add_Ins/Images/button_grey_record.png -------------------------------------------------------------------------------- /Add_Ins/Images/restoreLayout.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jstep/Arcpy/1cf1c68de1d598069d1e98ad4de68c8273fd9792/Add_Ins/Images/restoreLayout.png -------------------------------------------------------------------------------- /Add_Ins/Images/world.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jstep/Arcpy/1cf1c68de1d598069d1e98ad4de68c8273fd9792/Add_Ins/Images/world.png -------------------------------------------------------------------------------- /Add_Ins/README.md: -------------------------------------------------------------------------------- 1 | # Arcpy 2 | ESRI Arcpy scripts. 3 | -------------------------------------------------------------------------------- /Add_Ins/README.txt: -------------------------------------------------------------------------------- 1 | This is a stub project created by the ArcGIS Desktop Python AddIn Wizard. 2 | 3 | MANIFEST 4 | ======== 5 | 6 | README.txt : This file 7 | 8 | makeaddin.py : A script that will create a .esriaddin file out of this 9 | project, suitable for sharing or deployment 10 | 11 | config.xml : The AddIn configuration file 12 | 13 | Images/* : all UI images for the project (icons, images for buttons, 14 | etc) 15 | 16 | Install/* : The Python project used for the implementation of the 17 | AddIn. The specific python script to be used as the root 18 | module is specified in config.xml. 19 | -------------------------------------------------------------------------------- /Add_Ins/config.xml: -------------------------------------------------------------------------------- 1 | Content & Layout Helper{cbf16477-d233-4a5d-b9bc-b57c11874d8c}DDP layout helper tools1.0Images\LayoutIcon.pngJames StephaniukElections BC12/11/2015 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /Add_Ins/makeaddin.py: -------------------------------------------------------------------------------- 1 | import os 2 | import re 3 | import zipfile 4 | 5 | current_path = os.path.dirname(os.path.abspath(__file__)) 6 | 7 | out_zip_name = os.path.join(current_path, 8 | os.path.basename(current_path) + ".esriaddin") 9 | 10 | BACKUP_FILE_PATTERN = re.compile(".*_addin_[0-9]+[.]py$", re.IGNORECASE) 11 | 12 | def looks_like_a_backup(filename): 13 | return bool(BACKUP_FILE_PATTERN.match(filename)) 14 | 15 | with zipfile.ZipFile(out_zip_name, 'w', zipfile.ZIP_DEFLATED) as zip_file: 16 | for filename in ('config.xml', 'README.txt', 'makeaddin.py'): 17 | zip_file.write(os.path.join(current_path, filename), filename) 18 | dirs_to_add = ['Images', 'Install'] 19 | for directory in dirs_to_add: 20 | for (path, dirs, files) in os.walk(os.path.join(current_path, 21 | directory)): 22 | archive_path = os.path.relpath(path, current_path) 23 | found_file = False 24 | for file in (f for f in files if not looks_like_a_backup(f)): 25 | archive_file = os.path.join(archive_path, file) 26 | print archive_file 27 | zip_file.write(os.path.join(path, file), archive_file) 28 | found_file = True 29 | if not found_file: 30 | zip_file.writestr(os.path.join(archive_path, 31 | 'placeholder.txt'), 32 | "(Empty directory)") 33 | -------------------------------------------------------------------------------- /Annotation/Annotation.esriaddin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jstep/Arcpy/1cf1c68de1d598069d1e98ad4de68c8273fd9792/Annotation/Annotation.esriaddin -------------------------------------------------------------------------------- /Annotation/Images/Thumbs.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jstep/Arcpy/1cf1c68de1d598069d1e98ad4de68c8273fd9792/Annotation/Images/Thumbs.db -------------------------------------------------------------------------------- /Annotation/Images/bw-annotate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jstep/Arcpy/1cf1c68de1d598069d1e98ad4de68c8273fd9792/Annotation/Images/bw-annotate.png -------------------------------------------------------------------------------- /Annotation/Images/glyphicons-100-vector-path-all.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jstep/Arcpy/1cf1c68de1d598069d1e98ad4de68c8273fd9792/Annotation/Images/glyphicons-100-vector-path-all.png -------------------------------------------------------------------------------- /Annotation/Images/letterA.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jstep/Arcpy/1cf1c68de1d598069d1e98ad4de68c8273fd9792/Annotation/Images/letterA.png -------------------------------------------------------------------------------- /Annotation/Install/Annotation_addin.py: -------------------------------------------------------------------------------- 1 | import arcpy 2 | import os 3 | import pythonaddins 4 | 5 | class ExtentBoxes(object): 6 | """Implementation for Annotation_addin.extentBoxes (Button)""" 7 | def __init__(self): 8 | self.enabled = True 9 | self.checked = False 10 | def onClick(self): 11 | import arcpy 12 | import os 13 | import pythonaddins 14 | 15 | # Restore Page Layout (from PageLayoutElements table) before running this script. 16 | mxd = arcpy.mapping.MapDocument('CURRENT') 17 | ddp = mxd.dataDrivenPages 18 | pageName = str(ddp.pageRow.getValue(ddp.pageNameField.name)) 19 | df_lst = arcpy.mapping.ListDataFrames(mxd) 20 | onMapDFs = [] 21 | # List of data frames on the current page. 22 | for df in df_lst: 23 | if (df.elementPositionX > 0 and df.elementPositionX < mxd.pageSize[0] and df.elementPositionY > 0 and df.elementPositionY < mxd.pageSize[1]): 24 | onMapDFs.append(df) 25 | 26 | feature_info = [] 27 | for df in onMapDFs: 28 | # Only creates geometry for data frames on the page. Also creates FGDB. 29 | XMin = df.extent.XMin 30 | YMin = df.extent.YMin 31 | XMax = df.extent.XMax 32 | YMax = df.extent.YMax 33 | # A list of features and coordinate pairs 34 | df_info = [[XMin, YMin],[XMax, YMin],[XMax, YMax],[XMin, YMax]] 35 | feature_info.append(df_info) 36 | 37 | # A list that will hold each of the Polygon objects 38 | features = [] 39 | for feature in feature_info: 40 | # Create a Polygon object based on the array of points 41 | # Append to the list of Polygon objects 42 | features.append(arcpy.Polygon(arcpy.Array([arcpy.Point(*coords) for coords in feature]))) 43 | 44 | 45 | # Persist a copy of the Polygon objects using CopyFeatures 46 | poly_filename = "DF_Polygons_{}".format(pageName) 47 | parentDir = os.path.abspath(os.path.join(os.path.dirname(mxd.filePath), os.pardir)) 48 | edDir = os.path.join(parentDir, pageName) 49 | if not os.path.exists(edDir): 50 | os.makedirs(edDir) 51 | outDir = os.path.join(edDir, "anno_fgdb") 52 | if not os.path.exists(outDir): 53 | os.makedirs(outDir) 54 | workspace = arcpy.env.workspace = outDir 55 | 56 | arcpy.CopyFeatures_management(features, poly_filename) 57 | 58 | # Create FGDB(s). 59 | for df in onMapDFs: 60 | arcpy.CreateFileGDB_management(workspace, "{}_{}_{}_extentBoxes".format(pageName, df.name, str(int(round(df.scale)))), "CURRENT") 61 | 62 | del coords, feature_info, features, feature, poly_filename, outDir, mxd, df_lst, df_info, df, XMax, XMin, YMax, YMin, ddp, pageName 63 | 64 | class GenerateTiledAnno(object): 65 | """Implementation for Annotation_addin.tiledAnno (Button)""" 66 | def __init__(self): 67 | self.enabled = True 68 | self.checked = False 69 | def onClick(self): 70 | import arcpy 71 | import os 72 | 73 | mxd = arcpy.mapping.MapDocument("CURRENT") 74 | ddp = mxd.dataDrivenPages 75 | pageName = str(ddp.pageRow.getValue(ddp.pageNameField.name)) 76 | df_lst = arcpy.mapping.ListDataFrames(mxd) 77 | onMapDFs = [] 78 | # List of data frames on the current page. 79 | for df in df_lst: 80 | if (df.elementPositionX > 0 and df.elementPositionX < mxd.pageSize[0] and df.elementPositionY > 0 and df.elementPositionY < mxd.pageSize[1]): 81 | onMapDFs.append(df) 82 | 83 | GroupAnno = "GroupAnno" 84 | anno_suffix = "Anno" 85 | indexLyrName = "DF_Polygons_{}".format(pageName) 86 | tileIndexPoly = arcpy.mapping.ListLayers(mxd, indexLyrName)[0] 87 | 88 | parentDir = os.path.abspath(os.path.join(os.path.dirname(mxd.filePath), os.pardir)) 89 | workspace = arcpy.env.workspace = os.path.join(parentDir, pageName, "anno_fgdb") 90 | 91 | for df in onMapDFs: 92 | # arcpy.activeView = df.name 93 | try: 94 | fgdb = os.path.join(workspace, "{}_{}_{}_extentBoxes.gdb".format(pageName, str(df.name), int(round(df.scale)))) 95 | if os.path.exists(fgdb): 96 | arcpy.TiledLabelsToAnnotation_cartography( 97 | mxd.filePath, 98 | str(df.name), 99 | tileIndexPoly, 100 | fgdb, 101 | GroupAnno + str(df.name) + "_", 102 | anno_suffix, 103 | round(df.scale), 104 | feature_linked="STANDARD", 105 | generate_unplaced_annotation="GENERATE_UNPLACED_ANNOTATION") 106 | except Exception as e: 107 | print e 108 | 109 | # Turn off all labels. 110 | for lyr in arcpy.mapping.ListLayers(mxd): 111 | if lyr.supports("LABELCLASSES"): 112 | lyr.showLabels = False 113 | 114 | for df in df_lst: 115 | # Remove DF Polygons. 116 | for lyr in arcpy.mapping.ListLayers(mxd,"", df): 117 | if lyr.name.lower().startswith("df_polygons"): 118 | arcpy.mapping.RemoveLayer(df, lyr) 119 | 120 | # Remove empty annotation groups. 121 | groupLayers = [x for x in arcpy.mapping.ListLayers(mxd) if x.isGroupLayer and GroupAnno in x.name] 122 | for group in groupLayers: 123 | count = 0 124 | for item in group: 125 | count += 1 126 | if count == 0: 127 | arcpy.mapping.RemoveLayer(df, group) 128 | 129 | del anno_suffix, ddp, df, df_lst, fgdb, GroupAnno, indexLyrName, lyr, mxd, onMapDFs, pageName, parentDir, tileIndexPoly, groupLayers -------------------------------------------------------------------------------- /Annotation/README.txt: -------------------------------------------------------------------------------- 1 | This is a stub project created by the ArcGIS Desktop Python AddIn Wizard. 2 | 3 | MANIFEST 4 | ======== 5 | 6 | README.txt : This file 7 | 8 | makeaddin.py : A script that will create a .esriaddin file out of this 9 | project, suitable for sharing or deployment 10 | 11 | config.xml : The AddIn configuration file 12 | 13 | Images/* : all UI images for the project (icons, images for buttons, 14 | etc) 15 | 16 | Install/* : The Python project used for the implementation of the 17 | AddIn. The specific python script to be used as the root 18 | module is specified in config.xml. 19 | -------------------------------------------------------------------------------- /Annotation/config.xml: -------------------------------------------------------------------------------- 1 | Annotation{ce0c5f3a-82f6-4160-8eb9-ab41f45ec2ef}Generate tiled annotation for data driven pages and insets.1.0Images\letterA.pngJames StephaniukEBC12/11/2015 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /Annotation/makeaddin.py: -------------------------------------------------------------------------------- 1 | import os 2 | import re 3 | import zipfile 4 | 5 | current_path = os.path.dirname(os.path.abspath(__file__)) 6 | 7 | out_zip_name = os.path.join(current_path, 8 | os.path.basename(current_path) + ".esriaddin") 9 | 10 | BACKUP_FILE_PATTERN = re.compile(".*_addin_[0-9]+[.]py$", re.IGNORECASE) 11 | 12 | def looks_like_a_backup(filename): 13 | return bool(BACKUP_FILE_PATTERN.match(filename)) 14 | 15 | with zipfile.ZipFile(out_zip_name, 'w', zipfile.ZIP_DEFLATED) as zip_file: 16 | for filename in ('config.xml', 'README.txt', 'makeaddin.py'): 17 | zip_file.write(os.path.join(current_path, filename), filename) 18 | dirs_to_add = ['Images', 'Install'] 19 | for directory in dirs_to_add: 20 | for (path, dirs, files) in os.walk(os.path.join(current_path, 21 | directory)): 22 | archive_path = os.path.relpath(path, current_path) 23 | found_file = False 24 | for file in (f for f in files if not looks_like_a_backup(f)): 25 | archive_file = os.path.join(archive_path, file) 26 | print archive_file 27 | zip_file.write(os.path.join(path, file), archive_file) 28 | found_file = True 29 | if not found_file: 30 | zip_file.writestr(os.path.join(archive_path, 31 | 'placeholder.txt'), 32 | "(Empty directory)") 33 | -------------------------------------------------------------------------------- /Annotation/py/TiledAnno.py: -------------------------------------------------------------------------------- 1 | import arcpy 2 | import os 3 | 4 | mxd = arcpy.mapping.MapDocument("CURRENT") 5 | ddp = mxd.dataDrivenPages 6 | pageName = ddp.pageRow.getValue(ddp.pageNameField.name) 7 | df_lst = arcpy.mapping.ListDataFrames(mxd) 8 | onMapDFs = [] 9 | # List of data frames on the current page. 10 | for df in df_lst: 11 | if (df.elementPositionX > 0 and df.elementPositionX < mxd.pageSize[0] and df.elementPositionY > 0 and df.elementPositionY < mxd.pageSize[1]): 12 | onMapDFs.append(df) 13 | 14 | GroupAnno = "GroupAnno" 15 | anno_suffix = "Anno" 16 | indexLyrName = "DF_Polygons_{}".format(pageName) 17 | tileIndexPoly = arcpy.mapping.ListLayers(mxd, indexLyrName)[0] 18 | 19 | parentDir = os.path.abspath(os.path.join(os.path.dirname(mxd.filePath), os.pardir)) 20 | workspace = arcpy.env.workspace = os.path.join(parentDir, "anno_fgdb") 21 | 22 | for df in onMapDFs: 23 | # arcpy.activeView = df.name 24 | try: 25 | fgdb = os.path.join(workspace, "{}_{}_{}.gdb".format(pageName, str(df.name), int(round(df.scale)))) 26 | if os.path.exists(fgdb): 27 | arcpy.TiledLabelsToAnnotation_cartography(mxd.filePath, str(df.name), tileIndexPoly, fgdb, GroupAnno + str(df.name) + "_", anno_suffix, round(df.scale), "", "", "", "", "STANDARD", "GENERATE_UNPLACED_ANNOTATION") 28 | except Exception as e: 29 | print e 30 | 31 | # Turn off all labels. 32 | for lyr in arcpy.mapping.ListLayers(mxd): 33 | if lyr.supports("LABELCLASSES"): 34 | lyr.showLabels = False 35 | 36 | # Remove DF Polygons. 37 | for df in df_lst: 38 | for lyr in arcpy.mapping.ListLayers(mxd,"", df): 39 | if lyr.name.lower().startswith("df_polygons"): 40 | arcpy.mapping.RemoveLayer(df, lyr) 41 | 42 | del anno_suffix, ddp, df, df_lst, fgdb, GroupAnno, indexLyrName, lyr, mxd, onMapDFs, pageName, parentDir, tileIndexPoly -------------------------------------------------------------------------------- /Annotation/py/dataFrameExtentPolygons.py: -------------------------------------------------------------------------------- 1 | import arcpy, json, os, sys 2 | 3 | #Function that arranges data frames based on the field info within the PageLayoutElements table 4 | def arrangeDFs(row, dfName): 5 | rowInfo = json.loads(row.getValue(dfName)) 6 | try: 7 | df = arcpy.mapping.ListDataFrames(mxd, dfName)[0] 8 | df.elementPositionX = rowInfo[0] 9 | df.elementPositionY = rowInfo[1] 10 | df.elementWidth = rowInfo[2] 11 | df.elementHeight = rowInfo[3] 12 | newExtent = df.extent 13 | newExtent.XMin = rowInfo[4] 14 | newExtent.YMin = rowInfo[5] 15 | newExtent.XMax = rowInfo[6] 16 | newExtent.YMax = rowInfo[7] 17 | df.extent = newExtent 18 | df.scale = rowInfo[8] 19 | df.rotation = rowInfo[9] 20 | except IndexError: 21 | pass 22 | 23 | ################################################################################ 24 | 25 | mxd = arcpy.mapping.MapDocument('CURRENT') 26 | ddp = mxd.dataDrivenPages 27 | inset = "Inset" + "1" # Change value to '1', '2', '3', or '4' to control which inset polygons are made for. 28 | df_lst = arcpy.mapping.ListDataFrames(mxd, inset) 29 | 30 | feature_info = [] 31 | 32 | # Determine page orientation to append to output filename. Fallback to DDP count. 33 | if mxd.pageSize.width > mxd.pageSize.height: 34 | orient = "_L_" 35 | elif mxd.pageSize.width < mxd.pageSize.height: 36 | orient = "_P_" 37 | else: 38 | orient = "square" 39 | 40 | # Loop each DDP. 41 | for page in range(1, ddp.pageCount + 1): 42 | ddp.currentPageID = page 43 | # ArrangeDFs. 44 | pageName = ddp.pageRow.getValue(ddp.pageNameField.name) 45 | pageLayoutTable = arcpy.mapping.ListTableViews(mxd, "PageLayoutElements")[0] #Reference pageLayoutTable 46 | #Move all data frames off the layout and into their default positions 47 | pageLayoutCursor = arcpy.SearchCursor(pageLayoutTable.dataSource, "District = '" + pageName + "'") 48 | pageLayoutRow = pageLayoutCursor.next() 49 | 50 | for df in df_lst: 51 | arrangeDFs(pageLayoutRow, df.name) 52 | # Only creates geometry for data frames on the page. 53 | if (df.elementPositionX > 0 and df.elementPositionX < 11 and 54 | df.elementPositionY > 0 and df.elementPositionY < 8.5): 55 | XMin = df.extent.XMin 56 | YMin = df.extent.YMin 57 | XMax = df.extent.XMax 58 | YMax = df.extent.YMax 59 | # A list of features and coordinate pairs 60 | df_info = [[XMin, YMin],[XMax, YMin],[XMax, YMax],[XMin, YMax]] 61 | feature_info.append(df_info) 62 | 63 | # A list that will hold each of the Polygon objects 64 | features = [] 65 | 66 | for feature in feature_info: 67 | # Create a Polygon object based on the array of points 68 | # Append to the list of Polygon objects 69 | features.append( 70 | arcpy.Polygon( 71 | arcpy.Array([arcpy.Point(*coords) for coords in feature]))) 72 | 73 | # Persist a copy of the Polygon objects using CopyFeatures 74 | outDir = r"P:\15045 - ED Redistribution - Event Specific\R2015\21-Electoral_Boundaries_Commission_Support_Doc\WBS 8 - Geography\James\DataFrame_Polygon_Boxes" 75 | poly_filename = outDir + r"/dataframePolygons" + orient + inset + ".shp" 76 | if os.path.exists(poly_filename): 77 | os.remove(poly_filename) 78 | arcpy.CopyFeatures_management(features, poly_filename) 79 | 80 | del coords, feature_info, features, feature, poly_filename, outDir, mxd, df_lst, df_info, df, inset, XMax, XMin, YMax, YMin, page, orient, ddp, pageName, pageLayoutCursor, pageLayoutTable, pageLayoutRow -------------------------------------------------------------------------------- /Annotation/py/dataFrameExtentPolygons_SinglePage.py: -------------------------------------------------------------------------------- 1 | import arcpy 2 | import os 3 | import pythonaddins 4 | 5 | # Restore Page Layout (from PageLayoutElements table) before running this script. 6 | 7 | mxd = arcpy.mapping.MapDocument('CURRENT') 8 | ddp = mxd.dataDrivenPages 9 | pageName = ddp.pageRow.getValue(ddp.pageNameField.name) 10 | df_lst = arcpy.mapping.ListDataFrames(mxd) 11 | onMapDFs = [] 12 | # List of data frames on the current page. 13 | for df in df_lst: 14 | if (df.elementPositionX > 0 and df.elementPositionX < mxd.pageSize[0] and df.elementPositionY > 0 and df.elementPositionY < mxd.pageSize[1]): 15 | onMapDFs.append(df) 16 | 17 | feature_info = [] 18 | for df in onMapDFs: 19 | # Only creates geometry for data frames on the page. Also creates FGDB. 20 | XMin = df.extent.XMin 21 | YMin = df.extent.YMin 22 | XMax = df.extent.XMax 23 | YMax = df.extent.YMax 24 | # A list of features and coordinate pairs 25 | df_info = [[XMin, YMin],[XMax, YMin],[XMax, YMax],[XMin, YMax]] 26 | feature_info.append(df_info) 27 | 28 | # A list that will hold each of the Polygon objects 29 | features = [] 30 | for feature in feature_info: 31 | # Create a Polygon object based on the array of points 32 | # Append to the list of Polygon objects 33 | features.append(arcpy.Polygon(arcpy.Array([arcpy.Point(*coords) for coords in feature]))) 34 | 35 | 36 | # Persist a copy of the Polygon objects using CopyFeatures 37 | poly_filename = "DF_Polygons_{}".format(pageName) 38 | parentDir = os.path.abspath(os.path.join(os.path.dirname(mxd.filePath), os.pardir)) 39 | outDir = os.path.join(parentDir, "anno_fgdb") 40 | if not os.path.exists(outDir): 41 | os.makedirs(outDir) 42 | workspace = arcpy.env.workspace = outDir 43 | 44 | arcpy.CopyFeatures_management(features, poly_filename) 45 | 46 | # Create FGDB(s). 47 | for df in onMapDFs: 48 | arcpy.CreateFileGDB_management(workspace, "{}_{}_{}".format(pageName, df.name, str(int(round(df.scale)))), "CURRENT") 49 | 50 | del coords, feature_info, features, feature, poly_filename, outDir, mxd, df_lst, df_info, df, XMax, XMin, YMax, YMin, ddp, pageName 51 | 52 | -------------------------------------------------------------------------------- /Annotation_Stand_Alone/Annotation_Cmd-SingleDF.py: -------------------------------------------------------------------------------- 1 | ############################################################################# 2 | # The MIT License (MIT) 3 | # 4 | # Copyright (c) 2015 James Stephaniuk 5 | # 6 | # Permission is hereby granted, free of charge, to any person obtaining a copy 7 | # of this software and associated documentation files (the "Software"), to deal 8 | # in the Software without restriction, including without limitation the rights 9 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | # copies of the Software, and to permit persons to whom the Software is 11 | # furnished to do so, subject to the following conditions: 12 | # 13 | # The above copyright notice and this permission notice shall be included in 14 | # all copies or substantial portions of the Software. 15 | # 16 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | # SOFTWARE. 23 | # 24 | ############################################################################# 25 | # Usage: Run this script from the command line. 26 | # Navigate to this script's folder in the command line and type: 27 | # python [script name] "[mxd path]". 28 | # 29 | ############################################################################## 30 | 31 | import arcpy 32 | import datetime 33 | import getpass 34 | import glob 35 | import logging 36 | import logging.handlers 37 | import os 38 | import shutil 39 | import sys 40 | import time 41 | 42 | 43 | def query_yes_no(question, default="no"): 44 | """Ask a yes/no question via raw_input() and return their answer. 45 | 46 | "question" is a string that is presented to the user. 47 | "default" is the presumed answer if the user just hits . 48 | It must be "yes" (the default), "no" or None (meaning 49 | an answer is required of the user). 50 | 51 | The "answer" return value is one of "yes" or "no". 52 | """ 53 | valid = {"yes": "yes", "y": "yes", "ye": "yes", 54 | "no": "no", "n": "no"} 55 | if default is None: 56 | prompt = " [y/n] " 57 | elif default == "yes": 58 | prompt = " [Y/n] " 59 | elif default == "no": 60 | prompt = " [y/N] " 61 | else: 62 | raise ValueError("invalid default answer: '%s'" % default) 63 | 64 | while 1: 65 | sys.stdout.write(question + prompt) 66 | choice = raw_input().lower() 67 | if default is not None and choice == '': 68 | return default 69 | elif choice in valid.keys(): 70 | return valid[choice] 71 | else: 72 | sys.stdout.write("Please respond with 'yes' or 'no' " 73 | "(or 'y' or 'n').\n") 74 | 75 | 76 | def removeFGDBs(ws): 77 | """Remove existing FGDB(s) in workspace.""" 78 | for gdb in arcpy.ListFiles("*.gdb"): 79 | gdb_path = os.path.join(ws, gdb) 80 | shutil.rmtree(gdb_path) 81 | 82 | 83 | def createFGDBs(onMapDFs, workspace): 84 | """Create FGDB(s) to store annotation for each dataframe.""" 85 | for df in onMapDFs: 86 | fgdb = os.path.join(workspace, "{}_{}_{}.gdb".format(pageName, df.name, str(int(round(df.scale))))) 87 | if os.path.exists(fgdb): 88 | shutil.rmtree(fgdb) 89 | arcpy.CreateFileGDB_management(workspace, "{}_{}_{}".format(pageName, df.name, str(int(round(df.scale)))), "CURRENT") 90 | log.info("FGDB created: {}".format(fgdb)) 91 | 92 | 93 | def createExtentBoxes(mxdPath): 94 | try: 95 | # Restore Page Layout (from PageLayoutElements table) before running this script. 96 | mxd = arcpy.mapping.MapDocument(mxdPath) 97 | ddp = mxd.dataDrivenPages 98 | pageName = str(ddp.pageRow.getValue(ddp.pageNameField.name)) 99 | df_lst = arcpy.mapping.ListDataFrames(mxd) 100 | 101 | # Set the main dataframe variable. 102 | try: 103 | MDF = arcpy.mapping.ListDataFrames(mxd, "MDF")[0] 104 | except IndexError: 105 | MDF = arcpy.mapping.ListDataFrames(mxd)[0] 106 | 107 | log.info("MXD path: {}".format(mxd.filePath)) 108 | log.info("Page Name: {}".format(pageName)) 109 | 110 | onMapDFs = [] 111 | # List of data frames on the current page. 112 | for df in df_lst: 113 | if (df.elementPositionX > 0 and df.elementPositionX < mxd.pageSize[0] and df.elementPositionY > 0 and df.elementPositionY < mxd.pageSize[1]): 114 | onMapDFs.append(df) 115 | 116 | feature_info = [] 117 | 118 | XMin = MDF.extent.XMin 119 | YMin = MDF.extent.YMin 120 | XMax = MDF.extent.XMax 121 | YMax = MDF.extent.YMax 122 | # A list of features and coordinate pairs 123 | df_info = [[XMin, YMin], [XMax, YMin], [XMax, YMax], [XMin, YMax]] 124 | feature_info.append(df_info) 125 | 126 | # A list that will hold each of the Polygon objects 127 | features = [] 128 | for feature in feature_info: 129 | # Create a Polygon object based on the array of points 130 | # Append to the list of Polygon objects 131 | features.append(arcpy.Polygon(arcpy.Array([arcpy.Point(*coords) for coords in feature]))) 132 | 133 | # Persist a copy of the Polygon objects using CopyFeatures 134 | poly_filename = "DF_Polygons_{}".format(pageName) 135 | parentDir = os.path.abspath(os.path.join(os.path.dirname(mxd.filePath), os.pardir)) 136 | edDir = os.path.join(parentDir, pageName) 137 | outDir = os.path.join(edDir, "anno_fgdb") 138 | if not os.path.exists(outDir): 139 | os.makedirs(outDir) 140 | workspace = arcpy.env.workspace = outDir 141 | log.info("Output directory set to {}".format(outDir)) 142 | 143 | poly_shp = os.path.join(workspace, poly_filename) 144 | for filename in glob.glob(poly_shp + "*"): 145 | os.remove(filename) 146 | 147 | arcpy.CopyFeatures_management(features, poly_filename) 148 | 149 | removeFGDBs(workspace) 150 | createFGDBs(onMapDFs, workspace) 151 | 152 | del coords, feature_info, features, feature, poly_filename, outDir, mxd, df_info, XMax, XMin, YMax, YMin, ddp, pageName 153 | except Exception as e: 154 | log.info("An error occured: {}".format(e)) 155 | 156 | 157 | def generateTiledAnno(mxdPath): 158 | mxd = arcpy.mapping.MapDocument(mxdPath) 159 | ddp = mxd.dataDrivenPages 160 | pageName = str(ddp.pageRow.getValue(ddp.pageNameField.name)) 161 | df_lst = arcpy.mapping.ListDataFrames(mxd) 162 | 163 | # List of data frames on the current page. 164 | onMapDFs = [] 165 | for df in df_lst: 166 | if (df.elementPositionX > 0 and df.elementPositionX < mxd.pageSize[0] and df.elementPositionY > 0 and df.elementPositionY < mxd.pageSize[1]): 167 | onMapDFs.append(df) 168 | 169 | parentDir = os.path.abspath(os.path.join(os.path.dirname(mxd.filePath), os.pardir)) 170 | workspace = arcpy.env.workspace = os.path.join(parentDir, pageName, "anno_fgdb") 171 | 172 | indexFC = arcpy.ListFeatureClasses("DF_Polygons*")[0] 173 | tileIndexPoly = os.path.join(workspace, indexFC) 174 | GroupAnno = "GroupAnno" 175 | anno_suffix = "Anno" 176 | 177 | for df in onMapDFs: 178 | # arcpy.activeView = df.name 179 | try: 180 | fgdb = os.path.join(workspace, "{}_{}_{}.gdb".format(pageName, str(df.name), int(round(df.scale)))) 181 | if os.path.exists(fgdb): 182 | arcpy.TiledLabelsToAnnotation_cartography( 183 | mxd.filePath, 184 | str(df.name), 185 | str(tileIndexPoly), 186 | fgdb, 187 | GroupAnno + str(df.name) + "_", 188 | anno_suffix, 189 | round(df.scale), 190 | feature_linked="STANDARD", 191 | generate_unplaced_annotation="NOT_GENERATE_UNPLACED_ANNOTATION") 192 | log.info("Tiled Annotation Created at {}".format(fgdb)) 193 | else: 194 | log.info("{} DOES NOT EXIST".format(fgdb)) 195 | 196 | except Exception as e: 197 | log.info(e) 198 | 199 | 200 | def formatTime(x): 201 | minutes, seconds_rem = divmod(x, 60) 202 | if minutes >= 60: 203 | hours, minutes_rem = divmod(minutes, 60) 204 | return "%02d:%02d:%02d" % (hours, minutes_rem, seconds_rem) 205 | else: 206 | minutes, seconds_rem = divmod(x, 60) 207 | return "00:%02d:%02d" % (minutes, seconds_rem) 208 | 209 | 210 | def getPageName(mxdPath): 211 | mxd = arcpy.mapping.MapDocument(mxdPath) 212 | ddp = mxd.dataDrivenPages 213 | pageName = ddp.pageRow.getValue(ddp.pageNameField.name) 214 | return str(pageName) 215 | 216 | ############################################################################## 217 | 218 | if __name__ == "__main__": 219 | startTime = time.time() 220 | now = datetime.datetime.now() 221 | 222 | ############################ USER VARIABABLES ################################ 223 | mxd = sys.argv[1] 224 | 225 | pageName = getPageName(mxd) 226 | 227 | # Log files folder will be created in the ddp edabbr folder. 228 | curDirPath = os.path.dirname(mxd) 229 | parDirPath = os.path.abspath(os.path.join(curDirPath, os.pardir)) 230 | logPath = os.path.join(parDirPath, pageName, "Logfiles-Anno") 231 | if not os.path.exists(logPath): 232 | os.makedirs(logPath) 233 | 234 | # Make a global logging object. 235 | logName = os.path.join(logPath, (getpass.getuser() + now.strftime("_%Y-%m-%d_%H-%M.log"))) 236 | 237 | log = logging.getLogger("script_log") 238 | log.setLevel(logging.INFO) 239 | 240 | h1 = logging.FileHandler(logName) 241 | h2 = logging.StreamHandler() 242 | 243 | f = logging.Formatter("[%(levelname)s] [%(asctime)s] [%(lineno)d] - %(message)s", '%m/%d/%Y %I:%M:%S %p') 244 | 245 | h1.setFormatter(f) 246 | h2.setFormatter(f) 247 | 248 | h1.setLevel(logging.INFO) 249 | h2.setLevel(logging.INFO) 250 | 251 | log.addHandler(h1) 252 | log.addHandler(h2) 253 | 254 | log.info('----------------------------------------------------') 255 | log.info('Script: {0}'.format(os.path.basename(sys.argv[0]))) 256 | log.info('----------------------------------------------------') 257 | 258 | try: 259 | ########################### Function calls ########################### 260 | confirm = query_yes_no("Are you sure you want to create new annotation? Existing FGDB(s) will be overwritten.") 261 | 262 | if confirm.lower() in ("y", "ye", "yes"): 263 | createExtentBoxes(mxd) 264 | generateTiledAnno(mxd) 265 | 266 | except Exception as e: 267 | log.exception(e) 268 | 269 | totalTime = formatTime((time.time() - startTime)) 270 | log.info('----------------------------------------------------') 271 | log.info("Script Completed After: {0}".format(totalTime)) 272 | log.info('----------------------------------------------------') 273 | -------------------------------------------------------------------------------- /Annotation_Stand_Alone/Annotation_Cmd.py: -------------------------------------------------------------------------------- 1 | ############################################################################# 2 | # The MIT License (MIT) 3 | # 4 | # Copyright (c) 2015 James Stephaniuk 5 | # 6 | # Permission is hereby granted, free of charge, to any person obtaining a copy 7 | # of this software and associated documentation files (the "Software"), to deal 8 | # in the Software without restriction, including without limitation the rights 9 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | # copies of the Software, and to permit persons to whom the Software is 11 | # furnished to do so, subject to the following conditions: 12 | # 13 | # The above copyright notice and this permission notice shall be included in 14 | # all copies or substantial portions of the Software. 15 | # 16 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | # SOFTWARE. 23 | # 24 | ############################################################################# 25 | # Usage: Run this script from the command line. 26 | # Navigate to this script's folder in the command line and type: 27 | # python [script name] "[mxd path]". 28 | # 29 | ############################################################################## 30 | 31 | import arcpy 32 | import datetime 33 | import getpass 34 | import glob 35 | import logging 36 | import logging.handlers 37 | import os 38 | import shutil 39 | import sys 40 | import time 41 | 42 | 43 | def createExtentBoxes(mxdPath): 44 | try: 45 | # Restore Page Layout (from PageLayoutElements table) before running this script. 46 | mxd = arcpy.mapping.MapDocument(mxdPath) 47 | ddp = mxd.dataDrivenPages 48 | pageName = str(ddp.pageRow.getValue(ddp.pageNameField.name)) 49 | df_lst = arcpy.mapping.ListDataFrames(mxd) 50 | 51 | log.info("MXD path: {}".format(mxd.filePath)) 52 | log.info("Page Name: {}".format(pageName)) 53 | 54 | 55 | onMapDFs = [] 56 | # List of data frames on the current page. 57 | for df in df_lst: 58 | if (df.elementPositionX > 0 and df.elementPositionX < mxd.pageSize[0] and df.elementPositionY > 0 and df.elementPositionY < mxd.pageSize[1]): 59 | onMapDFs.append(df) 60 | 61 | feature_info = [] 62 | for df in onMapDFs: 63 | # Only creates geometry for data frames on the page. Also creates FGDB. 64 | XMin = df.extent.XMin 65 | YMin = df.extent.YMin 66 | XMax = df.extent.XMax 67 | YMax = df.extent.YMax 68 | # A list of features and coordinate pairs 69 | df_info = [[XMin, YMin],[XMax, YMin],[XMax, YMax],[XMin, YMax]] 70 | feature_info.append(df_info) 71 | 72 | # A list that will hold each of the Polygon objects 73 | features = [] 74 | for feature in feature_info: 75 | # Create a Polygon object based on the array of points 76 | # Append to the list of Polygon objects 77 | features.append(arcpy.Polygon(arcpy.Array([arcpy.Point(*coords) for coords in feature]))) 78 | 79 | 80 | # Persist a copy of the Polygon objects using CopyFeatures 81 | poly_filename = "DF_Polygons_{}".format(pageName) 82 | parentDir = os.path.abspath(os.path.join(os.path.dirname(mxd.filePath), os.pardir)) 83 | edDir = os.path.join(parentDir, pageName) 84 | outDir = os.path.join(edDir, "anno_fgdb") 85 | if not os.path.exists(outDir): 86 | os.makedirs(outDir) 87 | workspace = arcpy.env.workspace = outDir 88 | log.info("Output directory set to {}".format(outDir)) 89 | 90 | poly_shp = os.path.join(workspace, poly_filename) 91 | for filename in glob.glob(poly_shp + "*"): 92 | os.remove(filename) 93 | 94 | arcpy.CopyFeatures_management(features, poly_filename) 95 | log.info("'{}' saved to: {}".format(poly_filename, outDir)) 96 | 97 | # Remove existing FGDB(s). 98 | for gdb in arcpy.ListFiles("*.gdb"): 99 | gdb_path = os.path.join(workspace, gdb) 100 | shutil.rmtree(gdb_path) 101 | # Create FGDB(s). 102 | for df in onMapDFs: 103 | fgdb = os.path.join(workspace, "{}_{}_{}.gdb".format(pageName, df.name, str(int(round(df.scale))))) 104 | if os.path.exists(fgdb): 105 | shutil.rmtree(fgdb) 106 | arcpy.CreateFileGDB_management(workspace, "{}_{}_{}".format(pageName, df.name, str(int(round(df.scale)))), "CURRENT") 107 | log.info("FGDB created: {}".format(fgdb)) 108 | 109 | del coords, feature_info, features, feature, poly_filename, outDir, mxd, df_lst, df_info, df, XMax, XMin, YMax, YMin, ddp, pageName 110 | except Exception as e: 111 | log.info("An error occured: {}".format(e)) 112 | 113 | def generateTiledAnno(mxdPath): 114 | 115 | mxd = arcpy.mapping.MapDocument(mxdPath) 116 | ddp = mxd.dataDrivenPages 117 | pageName = str(ddp.pageRow.getValue(ddp.pageNameField.name)) 118 | df_lst = arcpy.mapping.ListDataFrames(mxd) 119 | 120 | # List of data frames on the current page. 121 | onMapDFs = [] 122 | for df in df_lst: 123 | if (df.elementPositionX > 0 and df.elementPositionX < mxd.pageSize[0] and df.elementPositionY > 0 and df.elementPositionY < mxd.pageSize[1]): 124 | onMapDFs.append(df) 125 | 126 | parentDir = os.path.abspath(os.path.join(os.path.dirname(mxd.filePath), os.pardir)) 127 | workspace = arcpy.env.workspace = os.path.join(parentDir, pageName, "anno_fgdb") 128 | 129 | indexFC = arcpy.ListFeatureClasses("DF_Polygons*")[0] 130 | tileIndexPoly = os.path.join(workspace, indexFC) 131 | GroupAnno = "GroupAnno" 132 | anno_suffix = "Anno" 133 | 134 | for df in onMapDFs: 135 | # arcpy.activeView = df.name 136 | try: 137 | fgdb = os.path.join(workspace, "{}_{}_{}.gdb".format(pageName, str(df.name), int(round(df.scale)))) 138 | if os.path.exists(fgdb): 139 | arcpy.TiledLabelsToAnnotation_cartography( 140 | mxd.filePath, 141 | str(df.name), 142 | # r"C:\Users\jastepha\Desktop\EDVA Maps\VMP\anno_fgdb\DF_Polygons_VMP.shp", 143 | str(tileIndexPoly), 144 | fgdb, 145 | GroupAnno + str(df.name) + "_", 146 | anno_suffix, 147 | round(df.scale), 148 | feature_linked="STANDARD", 149 | generate_unplaced_annotation="NOT_GENERATE_UNPLACED_ANNOTATION") 150 | log.info("Tiled Annotation Created at {}".format(fgdb)) 151 | else: 152 | log.info("{} DOES NOT EXIST".format(fgdb)) 153 | 154 | except Exception as e: 155 | log.info(e) 156 | 157 | # Turn off all labels. Uncomment mxd.save() below too. Turned off to improve script run time. 158 | # for lyr in arcpy.mapping.ListLayers(mxd): 159 | # if lyr.supports("LABELCLASSES"): 160 | # lyr.showLabels = False 161 | # log.info("All labels have been turned off.") 162 | 163 | # for df in df_lst: 164 | # # Remove DF Polygons. 165 | # for lyr in arcpy.mapping.ListLayers(mxd,"", df): 166 | # if lyr.name.lower().startswith("df_polygons"): 167 | # arcpy.mapping.RemoveLayer(df, lyr) 168 | 169 | # # Remove empty annotation groups. 170 | # groupLayers = [x for x in arcpy.mapping.ListLayers(mxd) if x.isGroupLayer and GroupAnno in x.name] 171 | # for group in groupLayers: 172 | # count = 0 173 | # for item in group: 174 | # count += 1 175 | # if count == 0: 176 | # arcpy.mapping.RemoveLayer(df, group) 177 | 178 | # mxd.save() 179 | 180 | # del anno_suffix, ddp, df, df_lst, fgdb, GroupAnno, mxd, onMapDFs, pageName, parentDir, tileIndexPoly 181 | 182 | def formatTime(x): 183 | minutes, seconds_rem = divmod(x, 60) 184 | if minutes >= 60: 185 | hours, minutes_rem = divmod(minutes, 60) 186 | return "%02d:%02d:%02d" % (hours, minutes_rem, seconds_rem) 187 | else: 188 | minutes, seconds_rem = divmod(x, 60) 189 | return "00:%02d:%02d" % (minutes, seconds_rem) 190 | 191 | def getPageName(mxdPath): 192 | mxd = arcpy.mapping.MapDocument(mxdPath) 193 | ddp = mxd.dataDrivenPages 194 | pageName = ddp.pageRow.getValue(ddp.pageNameField.name) 195 | return str(pageName) 196 | 197 | ############################################################################## 198 | 199 | if __name__ == "__main__": 200 | startTime = time.time() 201 | now = datetime.datetime.now() 202 | 203 | ############################ USER VARIABABLES ################################ 204 | mxd = sys.argv[1] 205 | 206 | pageName = getPageName(mxd) 207 | 208 | # Log files folder will be created in the ddp edabbr folder. 209 | curDirPath = os.path.dirname(mxd) 210 | parDirPath = os.path.abspath(os.path.join(curDirPath, os.pardir)) 211 | logPath = os.path.join(parDirPath, pageName, "Logfiles-Anno") 212 | if not os.path.exists(logPath): 213 | os.makedirs(logPath) 214 | 215 | # Make a global logging object. 216 | logName = os.path.join(logPath,(getpass.getuser() + now.strftime("_%Y-%m-%d_%H-%M.log")) ) 217 | 218 | log = logging.getLogger("script_log") 219 | log.setLevel(logging.INFO) 220 | 221 | h1 = logging.FileHandler(logName) 222 | h2 = logging.StreamHandler() 223 | 224 | f = logging.Formatter("[%(levelname)s] [%(asctime)s] [%(lineno)d] - %(message)s",'%m/%d/%Y %I:%M:%S %p') 225 | 226 | h1.setFormatter(f) 227 | h2.setFormatter(f) 228 | 229 | h1.setLevel(logging.INFO) 230 | h2.setLevel(logging.INFO) 231 | 232 | log.addHandler(h1) 233 | log.addHandler(h2) 234 | 235 | log.info('----------------------------------------------------') 236 | log.info('Script: {0}'.format(os.path.basename(sys.argv[0]))) 237 | log.info('----------------------------------------------------') 238 | 239 | try: 240 | ########################### Function calls ########################### 241 | createExtentBoxes(mxd) 242 | generateTiledAnno(mxd) 243 | 244 | except Exception as e: 245 | log.exception(e) 246 | 247 | totalTime = formatTime((time.time() - startTime)) 248 | log.info('----------------------------------------------------') 249 | log.info("Script Completed After: {0}".format(totalTime)) 250 | log.info('----------------------------------------------------') 251 | -------------------------------------------------------------------------------- /Cycle_Drives/Cycle_Drives.esriaddin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jstep/Arcpy/1cf1c68de1d598069d1e98ad4de68c8273fd9792/Cycle_Drives/Cycle_Drives.esriaddin -------------------------------------------------------------------------------- /Cycle_Drives/Images/cycle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jstep/Arcpy/1cf1c68de1d598069d1e98ad4de68c8273fd9792/Cycle_Drives/Images/cycle.png -------------------------------------------------------------------------------- /Cycle_Drives/Images/switch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jstep/Arcpy/1cf1c68de1d598069d1e98ad4de68c8273fd9792/Cycle_Drives/Images/switch.png -------------------------------------------------------------------------------- /Cycle_Drives/Install/Cycle_Drives_addin.py: -------------------------------------------------------------------------------- 1 | import arcpy 2 | import itertools 3 | import os 4 | import pythonaddins 5 | 6 | mxd = arcpy.mapping.MapDocument("CURRENT") 7 | # List of drives to cycle between. 8 | drives = [r"P:\15030_32_EBC_Digital_Mapping\Utilities\Scripts\Python\Replication\Replicated_P.gdb", \ 9 | r"C:\Users\jastepha\Desktop\testrep\Replicated_P.gdb"] 10 | # Function to cycle drive list. 11 | cycleDrives = itertools.cycle(drives).next 12 | 13 | class ToggleDataSource(object): 14 | """Implementation for Cycle_Drives_addin.toggleDataSource (Button)""" 15 | def __init__(self): 16 | self.enabled = True 17 | self.checked = False 18 | def onClick(self): 19 | path = cycleDrives() 20 | # Replace sources in MXD. Validate set to True: workspace will only be updated if the 'replace workspace path' value is valid. 21 | mxd.findAndReplaceWorkspacePaths("",path, True) 22 | 23 | print "Resourced to {}".format(path) 24 | 25 | # Testing. Prints out all layer data source paths. 26 | # for lyr in arcpy.mapping.ListLayers(mxd): 27 | # if lyr.supports("DATASOURCE"): 28 | # print lyr.dataSource -------------------------------------------------------------------------------- /Cycle_Drives/README.txt: -------------------------------------------------------------------------------- 1 | This is a stub project created by the ArcGIS Desktop Python AddIn Wizard. 2 | 3 | MANIFEST 4 | ======== 5 | 6 | README.txt : This file 7 | 8 | makeaddin.py : A script that will create a .esriaddin file out of this 9 | project, suitable for sharing or deployment 10 | 11 | config.xml : The AddIn configuration file 12 | 13 | Images/* : all UI images for the project (icons, images for buttons, 14 | etc) 15 | 16 | Install/* : The Python project used for the implementation of the 17 | AddIn. The specific python script to be used as the root 18 | module is specified in config.xml. 19 | -------------------------------------------------------------------------------- /Cycle_Drives/config.xml: -------------------------------------------------------------------------------- 1 | Cycle Drives{ba1aab9f-9911-4315-9592-b5da07445693}Cycle/toggle data source of layers of MXD to predefined paths.0.1Images\cycle.pngJames StephaniukEBC12/23/2015 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /Cycle_Drives/makeaddin.py: -------------------------------------------------------------------------------- 1 | import os 2 | import re 3 | import zipfile 4 | 5 | current_path = os.path.dirname(os.path.abspath(__file__)) 6 | 7 | out_zip_name = os.path.join(current_path, 8 | os.path.basename(current_path) + ".esriaddin") 9 | 10 | BACKUP_FILE_PATTERN = re.compile(".*_addin_[0-9]+[.]py$", re.IGNORECASE) 11 | 12 | def looks_like_a_backup(filename): 13 | return bool(BACKUP_FILE_PATTERN.match(filename)) 14 | 15 | with zipfile.ZipFile(out_zip_name, 'w', zipfile.ZIP_DEFLATED) as zip_file: 16 | for filename in ('config.xml', 'README.txt', 'makeaddin.py'): 17 | zip_file.write(os.path.join(current_path, filename), filename) 18 | dirs_to_add = ['Images', 'Install'] 19 | for directory in dirs_to_add: 20 | for (path, dirs, files) in os.walk(os.path.join(current_path, 21 | directory)): 22 | archive_path = os.path.relpath(path, current_path) 23 | found_file = False 24 | for file in (f for f in files if not looks_like_a_backup(f)): 25 | archive_file = os.path.join(archive_path, file) 26 | print archive_file 27 | zip_file.write(os.path.join(path, file), archive_file) 28 | found_file = True 29 | if not found_file: 30 | zip_file.writestr(os.path.join(archive_path, 31 | 'placeholder.txt'), 32 | "(Empty directory)") 33 | -------------------------------------------------------------------------------- /Dynamic_Elements/Dynamic_Elements.esriaddin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jstep/Arcpy/1cf1c68de1d598069d1e98ad4de68c8273fd9792/Dynamic_Elements/Dynamic_Elements.esriaddin -------------------------------------------------------------------------------- /Dynamic_Elements/Images/Textbox.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jstep/Arcpy/1cf1c68de1d598069d1e98ad4de68c8273fd9792/Dynamic_Elements/Images/Textbox.png -------------------------------------------------------------------------------- /Dynamic_Elements/Images/eye-chart.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jstep/Arcpy/1cf1c68de1d598069d1e98ad4de68c8273fd9792/Dynamic_Elements/Images/eye-chart.png -------------------------------------------------------------------------------- /Dynamic_Elements/Install/Dynamic_Elements_addin.py: -------------------------------------------------------------------------------- 1 | import arcpy 2 | import pythonaddins 3 | 4 | def svaBoxAdjust(): 5 | # Author: James Stephaniuk 6 | # October 19, 2015 7 | # 8 | # Populates and aligns a graphic box with data from an shapefile attribute table. 9 | 10 | mxd = arcpy.mapping.MapDocument("CURRENT") 11 | ddp = mxd.dataDrivenPages 12 | pageName = ddp.pageRow.getValue(ddp.pageNameField.name) # e.g. VMP 13 | pageNameField = ddp.pageNameField.name # edabbr 14 | 15 | # Feature class name. 16 | mapLyr = arcpy.mapping.ListLayers(mxd,"SVAs")[0] 17 | 18 | # SVA container (graphic box) name. Match this name to the SVA Box element name in ArcMap. 19 | svaBox = "svaBox" 20 | 21 | # Graphic box layout settings. 22 | padding = 0.2 # Distance (in inches) around edge of box to inner elements. 23 | spacer = 0.1 # Distance (in inches) between inner elements. 24 | 25 | # SVA source feature class field names. Add the field names from the layer that you want to populate the SVA Table. 26 | svaTxtField = "va" 27 | facilityName = "sectname" 28 | addrNo = "bldgstart" 29 | addrName = "stdaddr" 30 | city = "city_1" 31 | fieldLst = [svaTxtField, facilityName, addrNo, addrName, city] 32 | 33 | # SVA text element names. Match these names to the element names in ArcMap. 34 | SVATitleText = "SVATitle" 35 | svaTitleElem0 = "SVA_TitleElem0" 36 | svaTitleElem1 = "SVA_TitleElem1" 37 | svaTitleElem2 = "SVA_TitleElem2" 38 | svaTitleElem3 = "SVA_TitleElem3" 39 | svaTxtElem0 = "SVA_textElem0" 40 | svaTxtElem1 = "SVA_textElem1" 41 | svaTxtElem2 = "SVA_textElem2" 42 | svaTxtElem3 = "SVA_textElem3" 43 | 44 | mainTitle = arcpy.mapping.ListLayoutElements(mxd, "TEXT_ELEMENT", SVATitleText)[0] 45 | svaTitle = arcpy.mapping.ListLayoutElements(mxd, "TEXT_ELEMENT", svaTitleElem0)[0] 46 | facTitle = arcpy.mapping.ListLayoutElements(mxd, "TEXT_ELEMENT", svaTitleElem1)[0] 47 | addrTitle = arcpy.mapping.ListLayoutElements(mxd, "TEXT_ELEMENT", svaTitleElem2)[0] 48 | cityTitle = arcpy.mapping.ListLayoutElements(mxd, "TEXT_ELEMENT", svaTitleElem3)[0] 49 | svaTxtElem = arcpy.mapping.ListLayoutElements(mxd, "TEXT_ELEMENT", svaTxtElem0)[0] 50 | facTxtElem = arcpy.mapping.ListLayoutElements(mxd, "TEXT_ELEMENT", svaTxtElem1)[0] 51 | addrTxtElem = arcpy.mapping.ListLayoutElements(mxd, "TEXT_ELEMENT", svaTxtElem2)[0] 52 | cityTxtElem = arcpy.mapping.ListLayoutElements(mxd, "TEXT_ELEMENT", svaTxtElem3)[0] 53 | 54 | elemLst = [svaTxtElem, facTxtElem, addrTxtElem, cityTxtElem] 55 | 56 | # Captions cannot be empty therefore a single char. Set all font sizes to same. 57 | for elem in elemLst: 58 | elem.text = " " 59 | 60 | # Populate columns. 61 | whereClause = "ed = "+ "'" + pageName + "'" 62 | rows = sorted(arcpy.da.SearchCursor(mapLyr.dataSource, fieldLst, whereClause)) 63 | 64 | for row in rows: 65 | svaTxtElem.text += "{}\n".format(row[0]) 66 | facTxtElem.text += "{}\n".format(row[1]) 67 | addrTxtElem.text += "{} ".format(row[2]) 68 | addrTxtElem.text += "{}\n".format(row[3]) 69 | cityTxtElem.text += "{}\n".format(row[4]) 70 | 71 | # Slice off leading space char. 72 | for elem in elemLst: 73 | elem.text = elem.text[1:] 74 | elem.text = '\n'.join(' '.join(line.split()) for line in elem.text.split('\n')) # Removes two or more spaces. Splits text into lines. Then splits each line by whitespace and rejoins with single spaces. Then rejoins the lines. 75 | 76 | svaBox = arcpy.mapping.ListLayoutElements(mxd, "GRAPHIC_ELEMENT", svaBox)[0] 77 | 78 | # Position main title elem. 79 | mainTitle.elementPositionX = svaBox.elementPositionX + padding 80 | mainTitle.elementPositionY = svaBox.elementPositionY - padding 81 | 82 | # Position the titles and text elements relative to main title and each other. 83 | # Col 1 84 | widthCol1 = max(svaTitle.elementWidth, svaTxtElem.elementWidth) 85 | svaTitle.elementPositionX = svaTxtElem.elementPositionX = mainTitle.elementPositionX 86 | svaTitle.elementPositionY = mainTitle.elementPositionY - svaTitle.elementHeight - padding # Uses padding instead of spacer to give main title more room. 87 | svaTxtElem.elementPositionY = svaTitle.elementPositionY - svaTitle.elementHeight 88 | # Col 2 89 | widthCol2 = max(facTitle.elementWidth, facTxtElem.elementWidth) 90 | facTitle.elementPositionY = svaTitle.elementPositionY 91 | facTxtElem.elementPositionY = svaTxtElem.elementPositionY 92 | facTitle.elementPositionX = svaTitle.elementPositionX + widthCol1 + spacer 93 | facTxtElem.elementPositionX = svaTxtElem.elementPositionX + widthCol1 + spacer 94 | # Col 3 95 | widthCol3 = max(addrTitle.elementWidth, addrTxtElem.elementWidth) 96 | addrTitle.elementPositionY = facTitle.elementPositionY 97 | addrTxtElem.elementPositionY = facTxtElem.elementPositionY 98 | addrTitle.elementPositionX = facTitle.elementPositionX + widthCol2 + spacer 99 | addrTxtElem.elementPositionX = facTxtElem.elementPositionX + widthCol2 + spacer 100 | # Col 4 101 | widthCol4 = max(cityTitle.elementWidth, cityTxtElem.elementWidth) 102 | cityTitle.elementPositionY = addrTitle.elementPositionY 103 | cityTxtElem.elementPositionY = addrTxtElem.elementPositionY 104 | cityTitle.elementPositionX = addrTitle.elementPositionX + widthCol3 + spacer 105 | cityTxtElem.elementPositionX = addrTxtElem.elementPositionX + widthCol3 + spacer 106 | 107 | # Set the svaBox height and width derived from text elements heights and widths. 108 | tallestTxtElem = max(svaTxtElem.elementHeight, facTxtElem.elementHeight, addrTxtElem.elementHeight, cityTxtElem.elementHeight) 109 | tallestTitleElem = max(svaTitle.elementHeight, facTitle.elementHeight, addrTitle.elementHeight, cityTitle.elementHeight) 110 | colsWidths = widthCol1 + widthCol2 + widthCol3 + widthCol4 111 | textWidth = colsWidths + (spacer * 3) 112 | svaBox.elementHeight = tallestTxtElem + tallestTitleElem + mainTitle.elementHeight + (padding * 2) + spacer # Height of all elements, spacers, and padding. 113 | svaBox.elementWidth = max(textWidth, mainTitle.elementWidth) + (padding * 2) # Width of all elements, spacers, and padding. 114 | 115 | # Centre the main title. 116 | if mainTitle.elementWidth > textWidth: 117 | mainTitle.elementPositionX = svaTxtElem.elementPositionX 118 | else: 119 | mainTitle.elementPositionX = svaTxtElem.elementPositionX + (textWidth / 2) - (mainTitle.elementWidth / 2 ) 120 | 121 | # Contrived way to remove duplicates from SVA text column. If you have a better way I'd like to see it. 122 | splitLst = svaTxtElem.text.split() 123 | setSplititLst = list(set(svaTxtElem.text.split())) 124 | for i, item in enumerate(splitLst): 125 | if item in setSplititLst: 126 | setSplititLst.remove(item) 127 | else: 128 | splitLst[i] = splitLst[i].replace(splitLst[i], len(splitLst[i]) * " ") 129 | joinedText = "\n".join(splitLst) 130 | svaTxtElem.text = joinedText 131 | 132 | class SVA_BoxSizing_Btn(object): 133 | """Implementation for Dynamic_Elements_addin.svaButton (Button)""" 134 | def __init__(self): 135 | self.enabled = True 136 | self.checked = False 137 | def onClick(self): 138 | svaBoxAdjust() 139 | arcpy.RefreshActiveView() 140 | 141 | class SVA_Box_Sizing(object): 142 | """Implementation for Dynamic_Elements_addin.DynElem_Ext (Extension)""" 143 | def __init__(self): 144 | # For performance considerations, please remove all unused methods in this class. 145 | self.enabled = True 146 | def pageIndexExtentChanged(self, new_id): 147 | svaBoxAdjust() -------------------------------------------------------------------------------- /Dynamic_Elements/Install/svaBoxSizing.py: -------------------------------------------------------------------------------- 1 | import arcpy 2 | 3 | # Author: James Stephaniuk 4 | # October 19, 2015 5 | # 6 | # Populates and aligns a graphic box with data from an shapefile attribute table. 7 | 8 | mxd = arcpy.mapping.MapDocument("CURRENT") 9 | ddp = mxd.dataDrivenPages 10 | pageName = ddp.pageRow.getValue(ddp.pageNameField.name) # e.g. VMP 11 | pageNameField = ddp.pageNameField.name # edabbr 12 | 13 | # Feature class name. 14 | mapLyr = arcpy.mapping.ListLayers(mxd,"SVAs")[0] 15 | 16 | # SVA container (graphic box) name. Match this name to the SVA Box element name in ArcMap. 17 | svaBox = "svaBox" 18 | 19 | # Graphic box layout settings. 20 | padding = 0.2 # Distance (in inches) around edge of box to inner elements. 21 | spacer = 0.1 # Distance (in inches) between inner elements. 22 | 23 | # SVA source feature class field names. Add the field names from the layer that you want to populate the SVA Table. 24 | svaTxtField = "va" 25 | facilityName = "sectname" 26 | addrNo = "bldgstart" 27 | addrName = "stdaddr" 28 | city = "city_1" 29 | fieldLst = [svaTxtField, facilityName, addrNo, addrName, city] 30 | 31 | # SVA text element names. Match these names to the element names in ArcMap. 32 | SVATitleText = "SVATitle" 33 | svaTitleElem0 = "SVA_TitleElem0" 34 | svaTitleElem1 = "SVA_TitleElem1" 35 | svaTitleElem2 = "SVA_TitleElem2" 36 | svaTitleElem3 = "SVA_TitleElem3" 37 | svaTxtElem0 = "SVA_textElem0" 38 | svaTxtElem1 = "SVA_textElem1" 39 | svaTxtElem2 = "SVA_textElem2" 40 | svaTxtElem3 = "SVA_textElem3" 41 | 42 | mainTitle = arcpy.mapping.ListLayoutElements(mxd, "TEXT_ELEMENT", SVATitleText)[0] 43 | svaTitle = arcpy.mapping.ListLayoutElements(mxd, "TEXT_ELEMENT", svaTitleElem0)[0] 44 | facTitle = arcpy.mapping.ListLayoutElements(mxd, "TEXT_ELEMENT", svaTitleElem1)[0] 45 | addrTitle = arcpy.mapping.ListLayoutElements(mxd, "TEXT_ELEMENT", svaTitleElem2)[0] 46 | cityTitle = arcpy.mapping.ListLayoutElements(mxd, "TEXT_ELEMENT", svaTitleElem3)[0] 47 | svaTxtElem = arcpy.mapping.ListLayoutElements(mxd, "TEXT_ELEMENT", svaTxtElem0)[0] 48 | facTxtElem = arcpy.mapping.ListLayoutElements(mxd, "TEXT_ELEMENT", svaTxtElem1)[0] 49 | addrTxtElem = arcpy.mapping.ListLayoutElements(mxd, "TEXT_ELEMENT", svaTxtElem2)[0] 50 | cityTxtElem = arcpy.mapping.ListLayoutElements(mxd, "TEXT_ELEMENT", svaTxtElem3)[0] 51 | 52 | elemLst = [svaTxtElem, facTxtElem, addrTxtElem, cityTxtElem] 53 | 54 | # Captions cannot be empty therefore a single char. Set all font sizes to same. 55 | for elem in elemLst: 56 | elem.text = " " 57 | 58 | # Populate columns. 59 | whereClause = "ed = "+ "'" + pageName + "'" 60 | rows = sorted(arcpy.da.SearchCursor(mapLyr.dataSource, fieldLst, whereClause)) 61 | 62 | for row in rows: 63 | svaTxtElem.text += "{}\n".format(row[0]) 64 | facTxtElem.text += "{}\n".format(row[1]) 65 | addrTxtElem.text += "{} ".format(row[2]) 66 | addrTxtElem.text += "{}\n".format(row[3]) 67 | cityTxtElem.text += "{}\n".format(row[4]) 68 | 69 | # Slice off leading space char. 70 | for elem in elemLst: 71 | elem.text = elem.text[1:] 72 | elem.text = '\n'.join(' '.join(line.split()) for line in elem.text.split('\n')) # Removes two or more spaces. Splits text into lines. Then splits each line by whitespace and rejoins with single spaces. Then rejoins the lines. 73 | 74 | svaBox = arcpy.mapping.ListLayoutElements(mxd, "GRAPHIC_ELEMENT", svaBox)[0] 75 | 76 | # Position main title elem. 77 | mainTitle.elementPositionX = svaBox.elementPositionX + padding 78 | mainTitle.elementPositionY = svaBox.elementPositionY - padding 79 | 80 | # Position the titles and text elements relative to main title and each other. 81 | # Col 1 82 | widthCol1 = max(svaTitle.elementWidth, svaTxtElem.elementWidth) 83 | svaTitle.elementPositionX = svaTxtElem.elementPositionX = mainTitle.elementPositionX 84 | svaTitle.elementPositionY = mainTitle.elementPositionY - svaTitle.elementHeight - padding # Uses padding instead of spacer to give main title more room. 85 | svaTxtElem.elementPositionY = svaTitle.elementPositionY - svaTitle.elementHeight 86 | # Col 2 87 | widthCol2 = max(facTitle.elementWidth, facTxtElem.elementWidth) 88 | facTitle.elementPositionY = svaTitle.elementPositionY 89 | facTxtElem.elementPositionY = svaTxtElem.elementPositionY 90 | facTitle.elementPositionX = svaTitle.elementPositionX + widthCol1 + spacer 91 | facTxtElem.elementPositionX = svaTxtElem.elementPositionX + widthCol1 + spacer 92 | # Col 3 93 | widthCol3 = max(addrTitle.elementWidth, addrTxtElem.elementWidth) 94 | addrTitle.elementPositionY = facTitle.elementPositionY 95 | addrTxtElem.elementPositionY = facTxtElem.elementPositionY 96 | addrTitle.elementPositionX = facTitle.elementPositionX + widthCol2 + spacer 97 | addrTxtElem.elementPositionX = facTxtElem.elementPositionX + widthCol2 + spacer 98 | # Col 4 99 | widthCol4 = max(cityTitle.elementWidth, cityTxtElem.elementWidth) 100 | cityTitle.elementPositionY = addrTitle.elementPositionY 101 | cityTxtElem.elementPositionY = addrTxtElem.elementPositionY 102 | cityTitle.elementPositionX = addrTitle.elementPositionX + widthCol3 + spacer 103 | cityTxtElem.elementPositionX = addrTxtElem.elementPositionX + widthCol3 + spacer 104 | 105 | # Set the svaBox height and width derived from text elements heights and widths. 106 | tallestTxtElem = max(svaTxtElem.elementHeight, facTxtElem.elementHeight, addrTxtElem.elementHeight, cityTxtElem.elementHeight) 107 | tallestTitleElem = max(svaTitle.elementHeight, facTitle.elementHeight, addrTitle.elementHeight, cityTitle.elementHeight) 108 | colsWidths = widthCol1 + widthCol2 + widthCol3 + widthCol4 109 | textWidth = colsWidths + (spacer * 3) 110 | svaBox.elementHeight = tallestTxtElem + tallestTitleElem + mainTitle.elementHeight + (padding * 2) + spacer # Height of all elements, spacers, and padding. 111 | svaBox.elementWidth = max(textWidth, mainTitle.elementWidth) + (padding * 2) # Width of all elements, spacers, and padding. 112 | 113 | # Centre the main title. 114 | if mainTitle.elementWidth > textWidth: 115 | mainTitle.elementPositionX = svaTxtElem.elementPositionX 116 | else: 117 | mainTitle.elementPositionX = svaTxtElem.elementPositionX + (textWidth / 2) - (mainTitle.elementWidth / 2 ) 118 | 119 | # Contrived way to remove duplicates from SVA text column. If you have a better way I'd like to see it. 120 | splitLst = svaTxtElem.text.split() 121 | setSplititLst = list(set(svaTxtElem.text.split())) 122 | for i, item in enumerate(splitLst): 123 | if item in setSplititLst: 124 | setSplititLst.remove(item) 125 | else: 126 | splitLst[i] = splitLst[i].replace(splitLst[i], len(splitLst[i]) * " ") 127 | joinedText = "\n".join(splitLst) 128 | svaTxtElem.text = joinedText -------------------------------------------------------------------------------- /Dynamic_Elements/README.txt: -------------------------------------------------------------------------------- 1 | This is a stub project created by the ArcGIS Desktop Python AddIn Wizard. 2 | 3 | MANIFEST 4 | ======== 5 | 6 | README.txt : This file 7 | 8 | makeaddin.py : A script that will create a .esriaddin file out of this 9 | project, suitable for sharing or deployment 10 | 11 | config.xml : The AddIn configuration file 12 | 13 | Images/* : all UI images for the project (icons, images for buttons, 14 | etc) 15 | 16 | Install/* : The Python project used for the implementation of the 17 | AddIn. The specific python script to be used as the root 18 | module is specified in config.xml. 19 | -------------------------------------------------------------------------------- /Dynamic_Elements/config.xml: -------------------------------------------------------------------------------- 1 | Dynamic_Elements{e4528db6-a9cd-4b6f-a805-360334312963}Dynamically size and position map elements.1.0Images\eye-chart.pngJames StephaniukEBC11/09/2015 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /Layers/makeaddin.py: -------------------------------------------------------------------------------- 1 | import os 2 | import re 3 | import zipfile 4 | 5 | current_path = os.path.dirname(os.path.abspath(__file__)) 6 | 7 | out_zip_name = os.path.join(current_path, 8 | os.path.basename(current_path) + ".esriaddin") 9 | 10 | BACKUP_FILE_PATTERN = re.compile(".*_addin_[0-9]+[.]py$", re.IGNORECASE) 11 | 12 | def looks_like_a_backup(filename): 13 | return bool(BACKUP_FILE_PATTERN.match(filename)) 14 | 15 | with zipfile.ZipFile(out_zip_name, 'w', zipfile.ZIP_DEFLATED) as zip_file: 16 | for filename in ('config.xml', 'README.txt', 'makeaddin.py'): 17 | zip_file.write(os.path.join(current_path, filename), filename) 18 | dirs_to_add = ['Images', 'Install'] 19 | for directory in dirs_to_add: 20 | for (path, dirs, files) in os.walk(os.path.join(current_path, 21 | directory)): 22 | archive_path = os.path.relpath(path, current_path) 23 | found_file = False 24 | for file in (f for f in files if not looks_like_a_backup(f)): 25 | archive_file = os.path.join(archive_path, file) 26 | print archive_file 27 | zip_file.write(os.path.join(path, file), archive_file) 28 | found_file = True 29 | if not found_file: 30 | zip_file.writestr(os.path.join(archive_path, 31 | 'placeholder.txt'), 32 | "(Empty directory)") 33 | -------------------------------------------------------------------------------- /PDF_Export_Addin/Images/Thumbs.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jstep/Arcpy/1cf1c68de1d598069d1e98ad4de68c8273fd9792/PDF_Export_Addin/Images/Thumbs.db -------------------------------------------------------------------------------- /PDF_Export_Addin/Images/cmyk.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jstep/Arcpy/1cf1c68de1d598069d1e98ad4de68c8273fd9792/PDF_Export_Addin/Images/cmyk.png -------------------------------------------------------------------------------- /PDF_Export_Addin/Images/cube-128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jstep/Arcpy/1cf1c68de1d598069d1e98ad4de68c8273fd9792/PDF_Export_Addin/Images/cube-128.png -------------------------------------------------------------------------------- /PDF_Export_Addin/Images/draftIcon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jstep/Arcpy/1cf1c68de1d598069d1e98ad4de68c8273fd9792/PDF_Export_Addin/Images/draftIcon.png -------------------------------------------------------------------------------- /PDF_Export_Addin/Images/pdf-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jstep/Arcpy/1cf1c68de1d598069d1e98ad4de68c8273fd9792/PDF_Export_Addin/Images/pdf-icon.png -------------------------------------------------------------------------------- /PDF_Export_Addin/Images/rgb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jstep/Arcpy/1cf1c68de1d598069d1e98ad4de68c8273fd9792/PDF_Export_Addin/Images/rgb.png -------------------------------------------------------------------------------- /PDF_Export_Addin/Install/PDF_Export_Addin_addin.py: -------------------------------------------------------------------------------- 1 | import arcpy 2 | import os 3 | import pythonaddins 4 | 5 | def exporter(colorspace, dpi): 6 | try: 7 | mxd = arcpy.mapping.MapDocument('CURRENT') 8 | ddp = mxd.dataDrivenPages 9 | pageName = str(ddp.pageRow.getValue(ddp.pageNameField.name)) 10 | 11 | curDirPath = os.path.dirname(mxd.filePath) 12 | parDirPath = os.path.abspath(os.path.join(curDirPath, os.pardir)) 13 | outDir = os.path.join(parDirPath, pageName, "PDF_Draft_Exports") 14 | if not os.path.exists(outDir): 15 | os.makedirs(outDir) 16 | 17 | # Logic to determine orientation of page. 18 | if mxd.pageSize.width == 72.0 and mxd.pageSize.height == 72.0: 19 | orient = "4sheet" 20 | elif mxd.pageSize.width == 36.0 and mxd.pageSize.height == 36.0: 21 | orient = "1sheet" 22 | elif mxd.pageSize.width == 72.0 and mxd.pageSize.height == 36.0: 23 | orient = "2sheet_horizontal" 24 | elif mxd.pageSize.width == 36.0 and mxd.pageSize.height == 72.0: 25 | orient = "2sheet_vertical" 26 | else : 27 | orient = "{}x{}".format(str(mxd.pageSize[0]), str(mxd.pageSize[1])) 28 | 29 | # Join output directory with formatted file name. 30 | PathOut = os.path.join(outDir,"{}_{}_{}_{}".format(pageName,str(dpi),colorspace,orient)) 31 | 32 | # Export. 33 | arcpy.mapping.ExportToPDF(mxd, PathOut, resolution=dpi,image_quality="BEST",colorspace=colorspace, convert_markers=True) 34 | 35 | pythonaddins.MessageBox("Saved to \n{}\n as\n {}".format(outDir, os.path.split(PathOut)[1]),"Save Location") 36 | 37 | del mxd, ddp, pageName, outDir, orient, dpi, colorspace 38 | except Exception as e: 39 | pythonaddins.MessageBox(e, "Error Message") 40 | print e 41 | class CMYK(object): 42 | """Implementation for PDF_Export_Addin_addin.cmyk (Button)""" 43 | def __init__(self): 44 | self.enabled = True 45 | self.checked = False 46 | def onClick(self): 47 | # Call to exporter function. 48 | exporter("CMYK", 144) 49 | 50 | class RGB(object): 51 | """Implementation for PDF_Export_Addin_addin.rgb (Button)""" 52 | def __init__(self): 53 | self.enabled = True 54 | self.checked = False 55 | def onClick(self): 56 | # Call to exporter function. 57 | exporter("RGB", 144) -------------------------------------------------------------------------------- /PDF_Export_Addin/PDF_Export_Addin.esriaddin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jstep/Arcpy/1cf1c68de1d598069d1e98ad4de68c8273fd9792/PDF_Export_Addin/PDF_Export_Addin.esriaddin -------------------------------------------------------------------------------- /PDF_Export_Addin/README.txt: -------------------------------------------------------------------------------- 1 | MANIFEST 2 | ======== 3 | 4 | README.txt : This file 5 | 6 | makeaddin.py : A script that will create a .esriaddin file out of this 7 | project, suitable for sharing or deployment. Double-click 8 | this file to make the .esriaddin file. Then, double-click 9 | the .esriaddin file to install to ArcMap. 10 | 11 | config.xml : The AddIn configuration file 12 | 13 | Images/* : all UI images for the project (icons, images for buttons, 14 | etc) 15 | 16 | Install/* : The Python project used for the implementation of the 17 | AddIn. The specific python script to be used as the root 18 | module is specified in config.xml. 19 | -------------------------------------------------------------------------------- /PDF_Export_Addin/config.xml: -------------------------------------------------------------------------------- 1 | PDF Exporter{e1c9e822-9d68-447f-a1ce-e810cb6f8e31}Exports PDFs1.0Images\pdf-icon.pngJames StephaniukEBC12/11/2015 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /PDF_Export_Addin/makeaddin.py: -------------------------------------------------------------------------------- 1 | import os 2 | import re 3 | import zipfile 4 | 5 | current_path = os.path.dirname(os.path.abspath(__file__)) 6 | 7 | out_zip_name = os.path.join(current_path, 8 | os.path.basename(current_path) + ".esriaddin") 9 | 10 | BACKUP_FILE_PATTERN = re.compile(".*_addin_[0-9]+[.]py$", re.IGNORECASE) 11 | 12 | def looks_like_a_backup(filename): 13 | return bool(BACKUP_FILE_PATTERN.match(filename)) 14 | 15 | with zipfile.ZipFile(out_zip_name, 'w', zipfile.ZIP_DEFLATED) as zip_file: 16 | for filename in ('config.xml', 'README.txt', 'makeaddin.py'): 17 | zip_file.write(os.path.join(current_path, filename), filename) 18 | dirs_to_add = ['Images', 'Install'] 19 | for directory in dirs_to_add: 20 | for (path, dirs, files) in os.walk(os.path.join(current_path, 21 | directory)): 22 | archive_path = os.path.relpath(path, current_path) 23 | found_file = False 24 | for file in (f for f in files if not looks_like_a_backup(f)): 25 | archive_file = os.path.join(archive_path, file) 26 | print archive_file 27 | zip_file.write(os.path.join(path, file), archive_file) 28 | found_file = True 29 | if not found_file: 30 | zip_file.writestr(os.path.join(archive_path, 31 | 'placeholder.txt'), 32 | "(Empty directory)") 33 | -------------------------------------------------------------------------------- /PDF_Export_Stand_Alone/PDF_Export_Cmd.py: -------------------------------------------------------------------------------- 1 | ############################################################################# 2 | # The MIT License (MIT) 3 | # 4 | # Copyright (c) 2015 James Stephaniuk 5 | # 6 | # Permission is hereby granted, free of charge, to any person obtaining a copy 7 | # of this software and associated documentation files (the "Software"), to deal 8 | # in the Software without restriction, including without limitation the rights 9 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | # copies of the Software, and to permit persons to whom the Software is 11 | # furnished to do so, subject to the following conditions: 12 | # 13 | # The above copyright notice and this permission notice shall be included in 14 | # all copies or substantial portions of the Software. 15 | # 16 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | # SOFTWARE. 23 | # 24 | ############################################################################# 25 | # Usage: Run this script from the command line. 26 | # Navigate to this script's folder in the command line and type: 27 | # python [script name] "[mxd path]" [integer(for dpi)]. 28 | # 29 | ############################################################################## 30 | 31 | import arcpy 32 | import datetime 33 | import getpass 34 | import logging 35 | import logging.handlers 36 | import os 37 | import shutil 38 | import sys 39 | import time 40 | 41 | ########################### User defined functions ########################### 42 | 43 | def exporter(mxdPath, user_dpi): 44 | log = logging.getLogger("script_log") 45 | try: 46 | mxd = arcpy.mapping.MapDocument(mxdPath) 47 | dpi = user_dpi 48 | colorspace = "CMYK" 49 | ddp = mxd.dataDrivenPages 50 | pageName = str(ddp.pageRow.getValue(ddp.pageNameField.name)) 51 | 52 | log.info("MXD path: {}".format(mxd.filePath)) 53 | log.info("DPI: {}".format(str(dpi))) 54 | log.info("Colorspace: {}".format(colorspace)) 55 | log.info("Page Name: {}".format(pageName)) 56 | 57 | curDirPath = os.path.dirname(mxd.filePath) 58 | parDirPath = os.path.abspath(os.path.join(curDirPath, os.pardir)) 59 | outDir = os.path.join(parDirPath, pageName, "PDF_Draft_Exports") 60 | if not os.path.exists(outDir): 61 | os.makedirs(outDir) 62 | log.info("Output directory set to {}".format(outDir)) 63 | 64 | # Logic to determine orientation of page. 65 | if mxd.pageSize.width == 72.0 and mxd.pageSize.height == 72.0: 66 | orient = "4sheet" 67 | elif mxd.pageSize.width == 36.0 and mxd.pageSize.height == 36.0: 68 | orient = "1sheet" 69 | elif mxd.pageSize.width == 72.0 and mxd.pageSize.height == 36.0: 70 | orient = "2sheet_horizontal" 71 | elif mxd.pageSize.width == 36.0 and mxd.pageSize.height == 72.0: 72 | orient = "2sheet_vertical" 73 | else : 74 | orient = "{}x{}".format(str(mxd.pageSize[0]), str(mxd.pageSize[1])) 75 | 76 | log.info("MXD page size: {} x {}. Orient set to: {}".format(mxd.pageSize.width, mxd.pageSize.height, orient)) 77 | 78 | # Join output directory with formatted file name. 79 | PathOut = os.path.join(outDir,"{}_{}_{}_{}".format(pageName,str(dpi),colorspace,orient)) 80 | 81 | # Export 82 | log.info("") 83 | log.info("PDF being created...") 84 | arcpy.mapping.ExportToPDF(mxd, PathOut, resolution=dpi,image_quality="BEST",colorspace=colorspace, convert_markers=True) 85 | log.info("PDF saved to: {}".format(PathOut)) 86 | 87 | del mxd, ddp, pageName, outDir, orient, dpi, colorspace 88 | except Exception as e: 89 | log.info("An error occured: {}".format(e)) 90 | 91 | 92 | def formatTime(x): 93 | minutes, seconds_rem = divmod(x, 60) 94 | if minutes >= 60: 95 | hours, minutes_rem = divmod(minutes, 60) 96 | return "%02d:%02d:%02d" % (hours, minutes_rem, seconds_rem) 97 | else: 98 | minutes, seconds_rem = divmod(x, 60) 99 | return "00:%02d:%02d" % (minutes, seconds_rem) 100 | 101 | def getPageName(mxdPath): 102 | mxd = arcpy.mapping.MapDocument(mxdPath) 103 | ddp = mxd.dataDrivenPages 104 | pageName = ddp.pageRow.getValue(ddp.pageNameField.name) 105 | return str(pageName) 106 | 107 | ############################################################################## 108 | 109 | 110 | if __name__ == "__main__": 111 | startTime = time.time() 112 | now = datetime.datetime.now() 113 | 114 | ############################ USER VARIABABLES ################################ 115 | mxd = sys.argv[1] 116 | user_dpi = sys.argv[2] 117 | 118 | pageName = getPageName(mxd) 119 | 120 | # Log files folder will be created in the ddp edabbr folder. 121 | curDirPath = os.path.dirname(mxd) 122 | parDirPath = os.path.abspath(os.path.join(curDirPath, os.pardir)) 123 | logPath = os.path.join(parDirPath, pageName, "Logfiles-PDF_Export") 124 | if not os.path.exists(logPath): 125 | os.makedirs(logPath) 126 | 127 | # Make a global logging object. 128 | logName = os.path.join(logPath,(getpass.getuser() + now.strftime("_%Y-%m-%d_%H-%M.log")) ) 129 | 130 | log = logging.getLogger("script_log") 131 | log.setLevel(logging.INFO) 132 | 133 | h1 = logging.FileHandler(logName) 134 | h2 = logging.StreamHandler() 135 | 136 | f = logging.Formatter("[%(levelname)s] [%(asctime)s] [%(lineno)d] - %(message)s",'%m/%d/%Y %I:%M:%S %p') 137 | 138 | h1.setFormatter(f) 139 | h2.setFormatter(f) 140 | 141 | h1.setLevel(logging.INFO) 142 | h2.setLevel(logging.INFO) 143 | 144 | log.addHandler(h1) 145 | log.addHandler(h2) 146 | 147 | log.info('----------------------------------------------------') 148 | log.info('Script: {0}'.format(os.path.basename(sys.argv[0]))) 149 | log.info('----------------------------------------------------') 150 | 151 | try: 152 | ########################### Function calls ########################### 153 | exporter(mxd, user_dpi) 154 | 155 | except Exception as e: 156 | log.exception(e) 157 | 158 | totalTime = formatTime((time.time() - startTime)) 159 | log.info('----------------------------------------------------') 160 | log.info("Script Completed After: {0}".format(totalTime)) 161 | log.info('----------------------------------------------------') -------------------------------------------------------------------------------- /Page Layout Table/PageLayoutElements.cpg: -------------------------------------------------------------------------------- 1 | UTF-8 -------------------------------------------------------------------------------- /Page Layout Table/PageLayoutElements.dbf.xml: -------------------------------------------------------------------------------- 1 | 2 | 20140904161503001.0FALSEEDLI_Index0020.000file://\\cygnusa\PUBLIC\15030 - Electoral Geography\30 - Geography Data\Spatial Data Project Work\DDP_Multiplie_Insets\DDP_Index.gdbLocal Area NetworkProjectedGCS_North_American_1983Linear Unit: Meter (1.000000)Canada_Albers_Equal_Area_Conic<ProjectedCoordinateSystem xsi:type='typens:ProjectedCoordinateSystem' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns:xs='http://www.w3.org/2001/XMLSchema' xmlns:typens='http://www.esri.com/schemas/ArcGIS/10.1'><WKT>PROJCS[&quot;Canada_Albers_Equal_Area_Conic&quot;,GEOGCS[&quot;GCS_North_American_1983&quot;,DATUM[&quot;D_North_American_1983&quot;,SPHEROID[&quot;GRS_1980&quot;,6378137.0,298.257222101]],PRIMEM[&quot;Greenwich&quot;,0.0],UNIT[&quot;Degree&quot;,0.0174532925199433]],PROJECTION[&quot;Albers&quot;],PARAMETER[&quot;False_Easting&quot;,1000000.0],PARAMETER[&quot;False_Northing&quot;,0.0],PARAMETER[&quot;Central_Meridian&quot;,-126.0],PARAMETER[&quot;Standard_Parallel_1&quot;,58.5],PARAMETER[&quot;Standard_Parallel_2&quot;,50.0],PARAMETER[&quot;Latitude_Of_Origin&quot;,45.0],UNIT[&quot;Meter&quot;,1.0]]</WKT><XOrigin>-13239300</XOrigin><YOrigin>-8610100</YOrigin><XYScale>10000</XYScale><ZOrigin>-100000</ZOrigin><ZScale>10000</ZScale><MOrigin>-100000</MOrigin><MScale>10000</MScale><XYTolerance>0.001</XYTolerance><ZTolerance>0.001</ZTolerance><MTolerance>0.001</MTolerance><HighPrecision>true</HighPrecision></ProjectedCoordinateSystem>FeatureClassToFeatureClass GPL0 C:\Temp\DDP_InsetTest Scale_test.shp # "uniq_id "uniq_id" true true false 4 Long 0 10 ,First,#,GPL0,uniq_id,-1,-1;edname "edname" true true false 100 Text 0 0 ,First,#,GPL0,edname,-1,-1;edabbr "edabbr" true true false 3 Text 0 0 ,First,#,GPL0,edabbr,-1,-1;regcode "regcode" true true false 10 Text 0 0 ,First,#,GPL0,regcode,-1,-1;edeffctved "edeffctved" true true false 36 Date 0 0 ,First,#,GPL0,edeffctvedt,-1,-1;edexpirydt "edexpirydt" true true false 36 Date 0 0 ,First,#,GPL0,edexpirydt,-1,-1;ed_spare1 "ed_spare1" true true false 10 Text 0 0 ,First,#,GPL0,ed_spare1,-1,-1;ed_spare2 "ed_spare2" true true false 10 Text 0 0 ,First,#,GPL0,ed_spare2,-1,-1;SE_Area_bo "SE_Area_bo" false true true 0 Double 0 0 ,First,#,GPL0,SE_Area(boundary_linework),-1,-1;SE_Length_ "SE_Length_" false true true 0 Double 0 0 ,First,#,GPL0,SE_Length(boundary_linework),-1,-1" #AddField C:\Temp\DDP_InsetTest\Scale_test.shp scale FLOAT # # # # NULLABLE NON_REQUIRED #AddScale C:\Temp\DDP_InsetTest\EDLI_Template_DDP_Inset.mxd C:\Temp\DDP_InsetTest\Scale_test.shpCalculateField Scale_test Scale_1 [scale] VB #CalculateField Scale_test Rotation [Orient] VB #CalculateField PageLayoutElements Name [edname] VB #CalculateField PageLayoutElements Name [edabbr] VB #CalculateField PageLayoutElements MAINDF "" PYTHON_9.3 #CalculateField PageLayoutElements INSET1 "" PYTHON_9.3 #CalculateField PageLayoutElements INSET2 "" PYTHON_9.3 #CalculateField PageLayoutElements TITLE_NORT "" PYTHON_9.3 #CalculateField PageLayoutElements DISTRICT "" PYTHON_9.3 #DeleteRows PageLayoutElements20140904161318002014090416131800Microsoft Windows 7 Version 6.1 (Build 7601) Service Pack 1; Esri ArcGIS 10.2.1.3497EDLI_IndexFile Geodatabase Feature Class0.000dataset0SimpleFALSE0TRUEFALSEEDLI_IndexFeature Class0OBJECTIDOBJECTIDOID400Internal feature number.EsriSequential unique whole numbers that are automatically generated.ShapeShapeGeometry000Feature geometry.EsriCoordinates defining the features.ednameednameString10000edabbredabbrString300ed_spare1ed_spare1String1000ed_spare2ed_spare2String1000scalescaleSingle400RotationRotationDouble800OrientOrientString1000MainDFMainDFString10000Inset1Inset1String10000Inset2Inset2String10000Inset3Inset3String10000Inset4Inset4String10000Inset5Inset5String10000Inset6Inset6String10000Inset7Inset7String10000Inset8Inset8String10000NameNameString5000Title_NortTitle_NortString5000Shape_LengthShape_LengthDouble800Length of feature in internal units.EsriPositive real numbers that are automatically generated.Shape_AreaShape_AreaDouble800Area of feature in internal units squared.EsriPositive real numbers that are automatically generated.20140904 3 | -------------------------------------------------------------------------------- /Page Layout Table/info/arc.dir: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jstep/Arcpy/1cf1c68de1d598069d1e98ad4de68c8273fd9792/Page Layout Table/info/arc.dir -------------------------------------------------------------------------------- /Python/AnnoQuery.py: -------------------------------------------------------------------------------- 1 | 2 | def Anno(): 3 | """Turns on the annotation for only the current DDP.""" 4 | import arcpy 5 | import collections 6 | 7 | mxd = arcpy.mapping.MapDocument("current") #CURRENT. 8 | try: 9 | ddp = mxd.dataDrivenPages 10 | except: 11 | print "Data Driven Pages in not enabled on this map document" 12 | try: 13 | annoLyr = arcpy.mapping.ListLayers(mxd,"Annotation")[0] 14 | except: 15 | print "No layer named 'Annotation'" 16 | 17 | pageName = ddp.pageRow.getValue(ddp.pageNameField.name) 18 | 19 | for lyr in annoLyr: 20 | if lyr.supports("DATASOURCE"): 21 | tableCount = collections.Counter(row[0] for row in arcpy.da.SearchCursor(lyr, "TileID")) 22 | if tableCount: 23 | if str(arcpy.da.SearchCursor(lyr, "TileID").next()[0]) == str(pageName): 24 | lyr.visible = True 25 | else: 26 | lyr.visible = False 27 | else: 28 | lyr.visible = False 29 | arcpy.RefreshTOC() 30 | del lyr 31 | del annoLyr 32 | del tableCount 33 | del pageName 34 | del mxd 35 | del ddp 36 | 37 | # for lyr in annoLyr: 38 | # if lyr.supports("DATASOURCE"): 39 | # TileID = arcpy.da.SearchCursor(lyr,"TileID", "Name = '" + pageName + "'") 40 | # print pageName 41 | 42 | 43 | # #set pageName 44 | 45 | # # 1) Loop the Annotation Layer 46 | # # 2) if layer supports "DATASOURCE" (Or whatever) continue. Change this to check for NONE type. 47 | # # 3) if layer field of TileID= pageName 48 | # # 4) set visible to true. 49 | 50 | 51 | # mxd = arcpy.mapping.MapDocument("current") #CURRENT. 52 | # ddp = mxd.dataDrivenPages 53 | 54 | # annoLyr = arcpy.mapping.ListLayers(mxd,"Annotation")[0] 55 | # pageName = ddp.pageRow.getValue(ddp.pageNameField.name) 56 | # for lyr in annoLyr: #Loop each feature in Annotation. 57 | # if arcpy.management.GetCount(lyr)[0] == "0": 58 | # with arcpy.da.SearchCursor(lyr, "TileID") as cursor: 59 | # for row in cursor: 60 | # if str(row[0]) == str(pageName): 61 | # lyr.visible = True 62 | # else: 63 | # lyr.visible = False 64 | # arcpy.RefreshTOC() 65 | # _____________________________________________________________________________________________________________ 66 | 67 | # annoLyr = arcpy.mapping.ListLayers(mxd,"Annotation")[0] 68 | # pageName = ddp.pageRow.getValue(ddp.pageNameField.name) 69 | 70 | # for lyr in annoLyr: # Loop Annotation layers. 71 | # if lyr.supports("DATASOURCE"): # Check to avoid sub layer (usually called 'Default'). 72 | # # Check for empty table. 73 | # tileID = arcpy.da.SearchCursor(lyr,"TileID") 74 | # if str(tileID) == str(pageName): 75 | # lyr.visible = True 76 | # else: 77 | # lyr.visible = False 78 | # break 79 | 80 | # arcpy.RefreshTOC() 81 | 82 | 83 | # _____________________________________________________________________________________________________________ 84 | -------------------------------------------------------------------------------- /Python/BrokenDataSources.py: -------------------------------------------------------------------------------- 1 | import arcpy.mapping as mapping, os 2 | path = r"C:" 3 | f = open(r"C:\Users\jastepha\Desktop\BrokenDataList.txt",'w') 4 | for root,dirs,files in os.walk(path): 5 | for filename in files: 6 | basename, extension = os.path.splitext(filename) 7 | if extension == ".mxd": 8 | fullPath = os.path.join(path,filename) 9 | mxd = mapping.MapDocument(fullPath) 10 | f.write("MXD: " + filename + "\n") 11 | brknList = mapping.ListBrokenDataSources(mxd) 12 | for brknItem in brknList: 13 | f.write("\t" + brknItem.name + "\n") 14 | f.close() 15 | 16 | -------------------------------------------------------------------------------- /Python/ExtentBoxexRemovePts.py: -------------------------------------------------------------------------------- 1 | """"""""""""""""""""""""""""""""""""""""""""""""""""""""""" 2 | # ExtentBoxexRemovePts.py 3 | # Remove specific points from Inset Extent boxes. 4 | # 5 | # 6 | # Assumptions: 7 | # Main map (the one with the extent boxes) is first in TOC 8 | # 9 | 10 | """"""""""""""""""""""""""""""""""""""""""""""""""""""""""" 11 | import arcpy 12 | 13 | # Adds this script to system path. Used for separation of main script from other code packages. 14 | sys.path.append(os.path.dirname(__file__)) 15 | 16 | from poiDict import poiLyrDict 17 | import clearAllFuncs 18 | 19 | # Reference current mxd. 20 | mxd = arcpy.mapping.MapDocument("CURRENT") 21 | # Create list of all data frames (df's). 22 | dfLst = arcpy.mapping.ListDataFrames(mxd) 23 | # Reference main df. 24 | mainDF = dfLst[0] 25 | # Create list of inset df's. 26 | insetLst = dfLst[1:] 27 | 28 | 29 | # # Create list of Points of Interest layers. 30 | # poiLst = [] 31 | # lyrLst = arcpy.mapping.ListLayers(mxd, "*", mainDF) 32 | # for lyr in lyrLst: 33 | # if lyr.name in poiLyrDict: 34 | 35 | 36 | # # Skeleton code to access dict key/value pairs. 37 | # # for key in poiLyrDict: 38 | # # print key + " has the values of: " 39 | # # for item in poiLyrDict[key]: 40 | # # print item 41 | 42 | ######################################### 43 | ############### Extents ################# 44 | ######################################### 45 | 46 | # Create list of all data frames (df's). 47 | dfLst = arcpy.mapping.ListDataFrames(mxd) 48 | # Create list of inset df's. 49 | insetLst = dfLst[1:] 50 | # Create dictionary for extent(s) of box(es)/inset(s). Extent format: XMin, XMax, YMin, YMax (as tuple). 51 | insetExtentDict = {} 52 | for x in range(len(insetLst)): 53 | insetExtentDict["Inset{0}".format(x)] = insetLst[x].extent.XMin, insetLst[x].extent.XMax, insetLst[x].extent.YMin, insetLst[x].extent.YMax 54 | # insetExtentDict["Inset{0}".format(x)] = insetLst[x].extent # Dict populated with extent object instead of extent values. 55 | 56 | lyrLst = arcpy.mapping.ListLayers(mxd, "*", mainDF) 57 | for lyr in lyrLst: 58 | if lyr.name in poiLyrDict: 59 | # Select by location (extents) 60 | 61 | # Remove points in target extent box. 62 | # Select specific points in extent box (from extentDict) 63 | # if XMin < point.x < XMax and YMin < point.y < YMax: 64 | # Apply queries. -------------------------------------------------------------------------------- /Python/RepairBrokenLayers.py: -------------------------------------------------------------------------------- 1 | import arcpy 2 | import os 3 | 4 | mxd = arcpy.mapping.MapDocument('CURRENT') 5 | 6 | lyrLst = arcpy.mapping.ListLayers(mxd) 7 | 8 | # Change to location of your geodatabase. 9 | gdbPath = r"P:\15030_32_EBC_Digital_Mapping\MapData\2015 By Election Data\Replicate.gdb" 10 | 11 | for lyr in lyrLst: 12 | if lyr.isBroken: 13 | if lyr.supports("DATASETNAME"): 14 | mxd.findAndReplaceWorkspacePaths(lyr.workspacePath, gdbPath + lyr.datasetName, False) 15 | print "Layer {} repaired.".format(lyr.name) 16 | 17 | arcpy.RefreshTOC() -------------------------------------------------------------------------------- /Python/SDE_to_FGDB_BuiltInList.py: -------------------------------------------------------------------------------- 1 | """Module docstring. 2 | creat_FGDB_from_FCs.PY 3 | Long Usage: 4 | This scripts takes files from a SDE database and copies it to a local file geodatabase. 5 | 6 | change dir to the output directory location 7 | change input_source to the SDE connection file' 8 | change fc_list to point to a text file that contains feature names you want copied. 9 | change arcgis_version to the output FGDB output version 10 | """ 11 | 12 | import arcpy 13 | import os 14 | import shutil 15 | import sys 16 | 17 | #set output location for FGDB 18 | outDir = r"C:\Users\jastepha\Desktop\test" 19 | 20 | #set input location (sde connection file) 21 | #the pre-defined SDE connection file for input SOURCE 22 | input_source = r"C:\Users\jastepha\AppData\Roaming\ESRI\Desktop10.2\ArcCatalog\Connection to indeaprod2.sde" 23 | 24 | #set the list of FCs you want to copy to FGDB 25 | fc_list = ['indea:genmaint.idm_eds_std', 'indea:genmaint.cart_point_vas_std', 'indea:genmaint.idm_ebc_buildings'] 26 | 27 | arcgis_version = "10.0" 28 | 29 | # set the Source Feature Class you want to bring over in a txt file list for looping - this will create one FGDB for every FC 30 | #(list of SCHEMA.TABLENAMES) 31 | for input_fc in fc_list: 32 | print input_fc 33 | input_fc.split(".", 2) 34 | input_table = input_fc.split(".")[1] 35 | print input_table 36 | 37 | arcpy.env.workspace = outDir + "\\" + input_table + ".gdb" 38 | 39 | #set the output location 40 | outWorkspace = arcpy.env.workspace 41 | output = outWorkspace + "\\" + input_table 42 | 43 | # if FGDB exists then delete it.. (without prompt) 44 | if os.path.exists(outWorkspace): 45 | print "already exists so deleting FGDB first: " + outWorkspace 46 | shutil.rmtree(outWorkspace) 47 | 48 | input = input_source + "\\" + input_fc 49 | print "input: " + input 50 | 51 | # set some defaults 52 | arcpy.env.extent = arcpy.Extent(200000,200000,1900000,1900000) 53 | schemaType = "NO_TEST" 54 | fieldMappings = "" 55 | subtype = "" 56 | 57 | #set the projection to BC Albers. 58 | arcpy.env.outputCoordinateSystem = arcpy.SpatialReference(3005) 59 | 60 | # print the environment list 61 | environments = arcpy.ListEnvironments() 62 | 63 | for environment in environments: 64 | # Use Python's eval function to evaluate an environment's value 65 | envSetting = eval("arcpy.env." + environment) 66 | # Format and print each environment and its current setting 67 | print "%-30s: %s" % (environment, envSetting) 68 | 69 | 70 | #do it. 71 | try: 72 | print "creating FGDB" 73 | #create a FGDB in v10 based on table name (you could parameterized the diretory) 74 | arcpy.CreateFileGDB_management(outDir, input_table,arcgis_version) 75 | 76 | #set the output location 77 | output = outWorkspace + "\\" + input_table 78 | 79 | print "creating feature class using FCtoFC_conversion function: " + output 80 | print "input " + input 81 | print "output " + output 82 | 83 | arcpy.FeatureClassToFeatureClass_conversion(input, outWorkspace, input_table) 84 | 85 | except: 86 | # If an error occurred while running a tool print the messages 87 | print arcpy.GetMessages() 88 | 89 | 90 | 91 | -------------------------------------------------------------------------------- /Python/SelectCommunities.py: -------------------------------------------------------------------------------- 1 | import arcpy 2 | 3 | mxd = arcpy.mapping.MapDocument("CURRENT") 4 | ddp = mxd.dataDrivenPages 5 | pageName = ddp.pageRow.getValue(ddp.pageNameField.name) # ED NAME 6 | pageNameField = ddp.pageNameField.name # DIST_NAME 7 | 8 | EDLyr = ddp.indexLayer 9 | targetED = pageName 10 | communitiesLyr = arcpy.mapping.ListLayers(mxd, "indea_background_ebc_communities_active")[0] 11 | commLyr_fieldname = "featname" 12 | 13 | 14 | # Select target ED. 15 | arcpy.SelectLayerByAttribute_management(EDLyr, "NEW_SELECTION","{0} = '{1}'".format(pageNameField, targetED)) 16 | # Select points within target ED. 17 | arcpy.SelectLayerByLocation_management(communitiesLyr,"COMPLETELY_WITHIN", EDLyr, 0, "NEW_SELECTION") 18 | 19 | # Create list of selected points. 20 | commLst = [] 21 | for row in arcpy.da.SearchCursor(communitiesLyr, commLyr_fieldname): 22 | commLst.append(row[0]) 23 | 24 | # Build query from list. 25 | query = "{0} IN ({1})".format(commLyr_fieldname, ', '.join("'" + comm + "'" for comm in commLst)) 26 | 27 | # Apply definition query to communities layer. 28 | communitiesLyr.definitionQuery = query 29 | 30 | # Clear the selections. 31 | # arcpy.SelectLayerByAttribute_management(EDLyr, "CLEAR_SELECTION") 32 | # arcpy.SelectLayerByAttribute_management(communitiesLyr, "CLEAR_SELECTION") 33 | -------------------------------------------------------------------------------- /Python/SelectPointsInTargetED.py: -------------------------------------------------------------------------------- 1 | if __name__ == "__main__": 2 | import arcpy 3 | 4 | mxd = arcpy.mapping.MapDocument("CURRENT") 5 | ddp = mxd.dataDrivenPages 6 | pageName = ddp.pageRow.getValue(ddp.pageNameField.name) # ED NAME 7 | pageNameField = ddp.pageNameField.name # DIST_NAME 8 | 9 | EDLyr = ddp.indexLayer 10 | targetED = pageName 11 | 12 | # # Function to clear all queries. 13 | def clearAllQueries(): 14 | for lyr in arcpy.mapping.ListLayers(arcpy.mapping.MapDocument("CURRENT")): 15 | if lyr.supports("DEFINITIONQUERY"): 16 | lyr.definitionQuery = "" 17 | print "Query for {0} layer cleared.".format(lyr.name) 18 | arcpy.RefreshActiveView() 19 | 20 | def clearAllSelections(): 21 | for lyr in arcpy.mapping.ListLayers(arcpy.mapping.MapDocument("CURRENT")): 22 | arcpy.SelectLayerByAttribute_management(lyr, "CLEAR_SELECTION") 23 | 24 | clearAllQueries() 25 | clearAllSelections() 26 | 27 | 28 | # Dictionary of the point layers (keys) and their building use codes (values). 29 | # poiLyrDict = { 30 | # "Airports": [ 31 | # r'%Aero_Air%', 32 | # r'%Aero_Water%' 33 | # ], 34 | # "Fire Hall": [ 35 | # r'%Fire%' 36 | # ], 37 | # "Golf Course": [ 38 | # r'%Rec_Golf%' 39 | # ], 40 | # "Hall": [ 41 | # r'%Civ_CommHall%', 42 | # r'%Com_Church%', 43 | # r'%Com_Centre%' 44 | # ], 45 | # "Hospital": [ 46 | # r'%Hosp_Care%', 47 | # r'%Hosp_Ext%', 48 | # r'%Hosp_Hosp%' 49 | # ], 50 | # "School": [ 51 | # r'%PostSec_Acad%', 52 | # r'%PostSec_Coll%', 53 | # r'%PostSec_Inst%', 54 | # r'%PostSec_PSec%', 55 | # r'%PostSec_Univ%', 56 | # r'%Sch_Std%' 57 | # ] 58 | # } 59 | 60 | # Select target ED. 61 | arcpy.SelectLayerByAttribute_management(EDLyr, "NEW_SELECTION","{0} = '{1}'".format(pageNameField, targetED)) 62 | # Select points within target ED. 63 | for key in poiLyrDict: 64 | poiLyr = arcpy.mapping.ListLayers(mxd, key)[0] 65 | arcpy.SelectLayerByLocation_management(poiLyr, "COMPLETELY_WITHIN", EDLyr, 0, "ADD_TO_SELECTION") 66 | 67 | 68 | for key, values in poiLyrDict.iteritems(): 69 | oidLst = [] # Create list for selected points OIDs. 70 | poiLyr = arcpy.mapping.ListLayers(mxd, key)[0] 71 | bldgQuery = " OR ".join('"bldguses" LIKE %s' % "'" + value + "'" for value in values) 72 | for row in arcpy.da.SearchCursor(poiLyr, "OID@"): 73 | oidLst.append(row[0]) 74 | if oidLst: 75 | ptQuery = '\"{0}\" IN ({1})'.format("FID", ', '.join(str(oid) for oid in oidLst)) # Build query from list. May need to change FID. 76 | arcpy.mapping.ListLayers(mxd, key)[0].definitionQuery = ptQuery #+ " AND " + bldgQuery# Apply definition query to layer. 77 | else: 78 | ptQuery = '\"{0}\" IN (-1)'.format("FID") # Build query for empty set. May need to change FID. 79 | arcpy.mapping.ListLayers(mxd, key)[0].definitionQuery = ptQuery #+ " AND " + bldgQuery# Apply definition query to layer. 80 | 81 | 82 | arcpy.RefreshActiveView() 83 | 84 | # Clear the selections. 85 | arcpy.SelectLayerByAttribute_management(EDLyr, "CLEAR_SELECTION") 86 | 87 | # Delete variables. 88 | # del mxd, ddp, pageName, pageNameField, EDLyr, targetED, key, oidLst, poiLyr, row 89 | 90 | 91 | 92 | # "bldguses" LIKE '%Aero_Air%' OR bldguses LIKE '%Aero_Water%' 93 | -------------------------------------------------------------------------------- /Python/StripDataFromMXD.py: -------------------------------------------------------------------------------- 1 | import arcpy 2 | mxdPath = "C:\Users\jastepha\Desktop\EDVA Maps\MXD_templates\EDVA_Map_Template_4Sheet.mxd" 3 | mxd = arcpy.mapping.MapDocument(mxdPath) 4 | dfLst = arcpy.mapping.ListDataFrames(mxd) 5 | for df in dfLst: 6 | for lyr in arcpy.mapping.ListLayers(mxd, data_frame=df): 7 | if lyr.supports("DATASOURCE"): 8 | if not "Index" in lyr.dataSource: 9 | arcpy.mapping.RemoveLayer(df, lyr) 10 | 11 | mxdSave = mxdPath.split(".")[0] + "_No_Layers.mxd" 12 | mxd.saveACopy(mxdSave) -------------------------------------------------------------------------------- /Python/_template.py: -------------------------------------------------------------------------------- 1 | # Copyright: (c) company name 2 | # ArcGIS Version: 10 3 | # Python Version: 2.6 4 | #-------------------------------- 5 | import arcpy 6 | import os 7 | import sys 8 | 9 | def do_analysis(*argv): 10 | """TODO: Add documentation about this function here""" 11 | try: 12 | #TODO: Add analysis here 13 | pass 14 | except arcpy.ExecuteError: 15 | print arcpy.GetMessages(2) 16 | except Exception as e: 17 | print e.args[0] 18 | 19 | 20 | 21 | # This test allows the script to be used from the operating 22 | # system command prompt (stand-alone), in a Python IDE, 23 | # as a geoprocessing script tool, or as a module imported in 24 | # another script. 25 | if __name__ == '__main__': 26 | # Arguments are optional 27 | argv = tuple(arcpy.GetParameterAsText(i) 28 | for i in range(arcpy.GetArgumentCount())) 29 | do_analysis(*argv) -------------------------------------------------------------------------------- /Python/batchRename.py: -------------------------------------------------------------------------------- 1 | import arcpy 2 | from arcpy import env 3 | 4 | env.workspace = r"P:\15045 - ED Redistribution - Event Specific\R2015\21-Electoral_Boundaries_Commission_Support_Doc\WBS 8 - Geography\Mapping\local_shp\Anno GDBs\MDF Anno GDBs\D2_MDF_147250.gdb" # copy and paste directory between quotation marks. 5 | 6 | oldScale = "147250" # e.g. "119500" 7 | newScale = "666" # e.g. "_100000" 8 | 9 | for fc in arcpy.ListFeatureClasses(): 10 | arcpy.Rename_management(fc, fc.replace(oldScale, newScale)) 11 | -------------------------------------------------------------------------------- /Python/dataFrameExtentPolygons.py: -------------------------------------------------------------------------------- 1 | import arcpy, json, os, sys 2 | 3 | #Function that arranges data frames based on the field info within the PageLayoutElements table 4 | def arrangeDFs(row, dfName): 5 | rowInfo = json.loads(row.getValue(dfName)) 6 | try: 7 | df = arcpy.mapping.ListDataFrames(mxd, dfName)[0] 8 | df.elementPositionX = rowInfo[0] 9 | df.elementPositionY = rowInfo[1] 10 | df.elementWidth = rowInfo[2] 11 | df.elementHeight = rowInfo[3] 12 | newExtent = df.extent 13 | newExtent.XMin = rowInfo[4] 14 | newExtent.YMin = rowInfo[5] 15 | newExtent.XMax = rowInfo[6] 16 | newExtent.YMax = rowInfo[7] 17 | df.extent = newExtent 18 | df.scale = rowInfo[8] 19 | df.rotation = rowInfo[9] 20 | except IndexError: 21 | pass 22 | 23 | ################################################################################ 24 | 25 | mxd = arcpy.mapping.MapDocument('CURRENT') 26 | ddp = mxd.dataDrivenPages 27 | inset = "Inset" + "1" # Change value to '1', '2', '3', or '4' to control which inset polygons are made for. 28 | df_lst = arcpy.mapping.ListDataFrames(mxd, inset) 29 | 30 | feature_info = [] 31 | 32 | # Determine page orientation to append to output filename. Fallback to DDP count. 33 | if mxd.pageSize.width > mxd.pageSize.height: 34 | orient = "_L_" 35 | elif mxd.pageSize.width < mxd.pageSize.height: 36 | orient = "_P_" 37 | else: 38 | orient = "square" 39 | 40 | # Loop each DDP. 41 | for page in range(1, ddp.pageCount + 1): 42 | ddp.currentPageID = page 43 | # ArrangeDFs. 44 | pageName = ddp.pageRow.getValue(ddp.pageNameField.name) 45 | pageLayoutTable = arcpy.mapping.ListTableViews(mxd, "PageLayoutElements")[0] #Reference pageLayoutTable 46 | #Move all data frames off the layout and into their default positions 47 | pageLayoutCursor = arcpy.SearchCursor(pageLayoutTable.dataSource, "District = '" + pageName + "'") 48 | pageLayoutRow = pageLayoutCursor.next() 49 | 50 | for df in df_lst: 51 | arrangeDFs(pageLayoutRow, df.name) 52 | # Only creates geometry for data frames on the page. 53 | if (df.elementPositionX > 0 and df.elementPositionX < 11 and 54 | df.elementPositionY > 0 and df.elementPositionY < 8.5): 55 | XMin = df.extent.XMin 56 | YMin = df.extent.YMin 57 | XMax = df.extent.XMax 58 | YMax = df.extent.YMax 59 | # A list of features and coordinate pairs 60 | df_info = [[XMin, YMin],[XMax, YMin],[XMax, YMax],[XMin, YMax]] 61 | feature_info.append(df_info) 62 | 63 | # A list that will hold each of the Polygon objects 64 | features = [] 65 | 66 | for feature in feature_info: 67 | # Create a Polygon object based on the array of points 68 | # Append to the list of Polygon objects 69 | features.append( 70 | arcpy.Polygon( 71 | arcpy.Array([arcpy.Point(*coords) for coords in feature]))) 72 | 73 | # Persist a copy of the Polygon objects using CopyFeatures 74 | outDir = r"P:\15045 - ED Redistribution - Event Specific\R2015\21-Electoral_Boundaries_Commission_Support_Doc\WBS 8 - Geography\James\DataFrame_Polygon_Boxes" 75 | poly_filename = outDir + r"/dataframePolygons" + orient + inset + ".shp" 76 | if os.path.exists(poly_filename): 77 | os.remove(poly_filename) 78 | arcpy.CopyFeatures_management(features, poly_filename) 79 | 80 | del coords, feature_info, features, feature, poly_filename, outDir, mxd, df_lst, df_info, df, inset, XMax, XMin, YMax, YMin, page, orient, ddp, pageName, pageLayoutCursor, pageLayoutTable, pageLayoutRow -------------------------------------------------------------------------------- /Python/dataFrameExtentPolygonsModified.py: -------------------------------------------------------------------------------- 1 | import arcpy, os, sys 2 | 3 | mxd = arcpy.mapping.MapDocument('CURRENT') 4 | ddp = mxd.dataDrivenPages 5 | df_lst = arcpy.mapping.ListDataFrames(mxd) 6 | inset_lst = arcpy.mapping.ListDataFrames(mxd)[1:] 7 | 8 | feature_info = [] 9 | 10 | # A list that will hold each of the Polygon objects 11 | features = [] 12 | 13 | # Determine page orientation to append to output filename. Fallback to DDP count. 14 | if mxd.pageSize.width > mxd.pageSize.height: 15 | orient = "_L" 16 | elif mxd.pageSize.width < mxd.pageSize.height: 17 | orient = "_P" 18 | else: 19 | orient = "_sq" 20 | 21 | for df in inset_lst: 22 | # Only creates geometry for data frames on the page. 23 | if (df.elementPositionX > 0 and df.elementPositionX < mxd.pageSize[0] and 24 | df.elementPositionY > 0 and df.elementPositionY < mxd.pageSize[1]): 25 | XMin = df.extent.XMin 26 | YMin = df.extent.YMin 27 | XMax = df.extent.XMax 28 | YMax = df.extent.YMax 29 | # A list of features and coordinate pairs 30 | df_info = [[XMin, YMin],[XMax, YMin],[XMax, YMax],[XMin, YMax]] 31 | feature_info.append(df_info) 32 | 33 | 34 | 35 | for feature in feature_info: 36 | # Create a Polygon object based on the array of points 37 | # Append to the list of Polygon objects 38 | features.append( 39 | arcpy.Polygon( 40 | arcpy.Array([arcpy.Point(*coords) for coords in feature]))) 41 | 42 | # Persist a copy of the Polygon objects using CopyFeatures 43 | outDir = r"P:\15045 - ED Redistribution - Event Specific\R2015\21-Electoral_Boundaries_Commission_Support_Doc\WBS 8 - Geography\James\py" # TODO: Change out location. 44 | poly_filename = outDir + r"/dataframePolygon.shp" 45 | if os.path.exists(poly_filename): 46 | os.remove(poly_filename) 47 | arcpy.CopyFeatures_management(features, poly_filename) 48 | 49 | del coords, feature_info, features, feature, poly_filename, outDir, mxd, df_lst, df_info, df, XMax, XMin, YMax, YMin, orient, ddp -------------------------------------------------------------------------------- /Python/dataframePolygon.cpg: -------------------------------------------------------------------------------- 1 | UTF-8 -------------------------------------------------------------------------------- /Python/dataframePolygon.dbf: -------------------------------------------------------------------------------- 1 | sAIdN 0 -------------------------------------------------------------------------------- /Python/dataframePolygon.sbn: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jstep/Arcpy/1cf1c68de1d598069d1e98ad4de68c8273fd9792/Python/dataframePolygon.sbn -------------------------------------------------------------------------------- /Python/dataframePolygon.sbx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jstep/Arcpy/1cf1c68de1d598069d1e98ad4de68c8273fd9792/Python/dataframePolygon.sbx -------------------------------------------------------------------------------- /Python/dataframePolygon.shp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jstep/Arcpy/1cf1c68de1d598069d1e98ad4de68c8273fd9792/Python/dataframePolygon.shp -------------------------------------------------------------------------------- /Python/dataframePolygon.shp.xml: -------------------------------------------------------------------------------- 1 | 2 | 20150615145656001.0FALSEdataframePolygon0020.000file://\\cygnusa\PUBLIC\15045 - ED Redistribution - Event Specific\R2015\21-Electoral_Boundaries_Commission_Support_Doc\WBS 8 - Geography\James\py\dataframePolygon.shpLocal Area NetworkCopyFeatures in_memory\f67BF43B9_C5A6_47E5_BC7F_4B655E672577 "P:\15045 - ED Redistribution - Event Specific\R2015\21-Electoral_Boundaries_Commission_Support_Doc\WBS 8 - Geography\James\py\dataframePolygon.shp" # 0 0 020150615145656002015061514565600Microsoft Windows 7 Version 6.1 (Build 7601) Service Pack 1; Esri ArcGIS 10.2.1.3497dataframePolygonShapefile0.000dataset0SimpleFALSE0FALSEFALSEdataframePolygonFeature Class0FIDFIDOID400Internal feature number.EsriSequential unique whole numbers that are automatically generated.ShapeShapeGeometry000Feature geometry.EsriCoordinates defining the features.IdIdInteger66020150615 3 | -------------------------------------------------------------------------------- /Python/dataframePolygon.shx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jstep/Arcpy/1cf1c68de1d598069d1e98ad4de68c8273fd9792/Python/dataframePolygon.shx -------------------------------------------------------------------------------- /Python/dataframePolygonsY_sq.cpg: -------------------------------------------------------------------------------- 1 | UTF-8 -------------------------------------------------------------------------------- /Python/dataframePolygonsY_sq.dbf: -------------------------------------------------------------------------------- 1 | s AIdN 0 -------------------------------------------------------------------------------- /Python/dataframePolygonsY_sq.sbn: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jstep/Arcpy/1cf1c68de1d598069d1e98ad4de68c8273fd9792/Python/dataframePolygonsY_sq.sbn -------------------------------------------------------------------------------- /Python/dataframePolygonsY_sq.sbx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jstep/Arcpy/1cf1c68de1d598069d1e98ad4de68c8273fd9792/Python/dataframePolygonsY_sq.sbx -------------------------------------------------------------------------------- /Python/dataframePolygonsY_sq.shp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jstep/Arcpy/1cf1c68de1d598069d1e98ad4de68c8273fd9792/Python/dataframePolygonsY_sq.shp -------------------------------------------------------------------------------- /Python/dataframePolygonsY_sq.shp.xml: -------------------------------------------------------------------------------- 1 | 2 | 20150611152957001.0FALSEdataframePolygonsY_sq0020.000file://\\cygnusa\PUBLIC\15045 - ED Redistribution - Event Specific\R2015\21-Electoral_Boundaries_Commission_Support_Doc\WBS 8 - Geography\James\py\dataframePolygonsY_sq.shpLocal Area NetworkCopyFeatures in_memory\fAAAA2CBB_6FA6_4D33_88C2_AC28129D0F38 "P:\15045 - ED Redistribution - Event Specific\R2015\21-Electoral_Boundaries_Commission_Support_Doc\WBS 8 - Geography\James\py\dataframePolygonsY_sq.shp" # 0 0 020150611152957002015061115295700Microsoft Windows 7 Version 6.1 (Build 7601) Service Pack 1; Esri ArcGIS 10.2.1.3497dataframePolygonsY_sqShapefile0.000dataset0SimpleFALSE0FALSEFALSEdataframePolygonsY_sqFeature Class0FIDFIDOID400Internal feature number.EsriSequential unique whole numbers that are automatically generated.ShapeShapeGeometry000Feature geometry.EsriCoordinates defining the features.IdIdInteger66020150611 3 | -------------------------------------------------------------------------------- /Python/dataframePolygonsY_sq.shx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jstep/Arcpy/1cf1c68de1d598069d1e98ad4de68c8273fd9792/Python/dataframePolygonsY_sq.shx -------------------------------------------------------------------------------- /Python/dfScaleMatch.py: -------------------------------------------------------------------------------- 1 | import arcpy 2 | import collections 3 | import re 4 | 5 | mxd = arcpy.mapping.MapDocument("current") #CURRENT. 6 | ddp = mxd.dataDrivenPages 7 | df = arcpy.mapping.ListDataFrames(mxd, "MainDF")[0] 8 | dfScale = int(df.scale) 9 | annoLyr = arcpy.mapping.ListLayers(mxd,"Anno*")[0] 10 | 11 | for lyr in annoLyr: 12 | if lyr.supports("DATASOURCE"): # Weeds out 'default' sub-layer. 13 | lyrScale = int(re.match('.*?([0-9]+)$', str(lyr.name)).group(1)) # Matches digits at end of string. 14 | if lyrScale: 15 | if lyrScale == dfScale: 16 | lyr.visible = True 17 | else: 18 | lyr.visible = False 19 | else: 20 | lyr.visible = False 21 | arcpy.RefreshTOC() 22 | del lyr, annoLyr, mxd, ddp, df, dfScale, lyrScale -------------------------------------------------------------------------------- /Python/nameElements.py: -------------------------------------------------------------------------------- 1 | import arcpy 2 | 3 | mxd = arcpy.mapping.MapDocument("CURRENT") 4 | 5 | dfs_lst = arcpy.mapping.ListDataFrames(mxd) # List of all dataframes. MainDF and Insets. 6 | mainDF = arcpy.mapping.ListDataFrames(mxd)[0] # Assumes main data frame is first in TOC. 7 | insetDF_lst = arcpy.mapping.ListDataFrames(mxd, "*Inset*") 8 | mapElem_lst = arcpy.mapping.ListLayoutElements(mxd,"MAPSURROUND_ELEMENT", "*SCALE*") + arcpy.mapping.ListLayoutElements(mxd, "GRAPHIC_ELEMENT", "*NORTH*") 9 | 10 | def nameMapElements(elementList): 11 | """Append parent data frame name to map elements.""" 12 | for index, elem in enumerate(elementList): 13 | if type(elem) in ["MAPSURROUND_ELEMENT", "LEGEND_ELEMENT", "TEXT_ELEMENT"]: 14 | elem.name = elem.name + elem.parentDataFrameName 15 | 16 | nameMapElements(mapElem_lst) 17 | nameMapElements(insetDF_lst) # Won't do anything because they are of type "DATAFRAME_ELEMENT". 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /Python/orginalGetSettings.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | # Create an output location variable 4 | outputDirectory = r"C:\temp" 5 | 6 | # Open a text file to append info to 7 | insetTxt = outputDirectory + r"\insetInfo.txt" 8 | FILE = open(insetTxt, "a") 9 | 10 | try: 11 | mxd = arcpy.mapping.MapDocument("current") 12 | df = arcpy.mapping.ListDataFrames(mxd, "Inset*")[0] 13 | ddp = mxd.dataDrivenPages 14 | infoList = [] 15 | infoList.append("\n") 16 | # The following is information you would like to record 17 | # The text is written so it can be pasted directly into your script 18 | # This example assumes that 'pgIndex' is the variable for the current page id 19 | # and that 'dataFrame' is the variable for the data frame containing the inset map 20 | infoList.append("if (pgIndex == " + str(ddp.currentPageID) + "):\n") 21 | infoList.append("\tdataFrame.elementPositionX = " + str(df.elementPositionX) + "\n") 22 | infoList.append("\tdataFrame.elementPositionY = " + str(df.elementPositionY) + "\n") 23 | infoList.append("\tdataFrame.elementHeight = " + str(df.elementHeight) + "\n") 24 | infoList.append("\tdataFrame.elementWidth = " + str(df.elementWidth) + "\n") 25 | infoList.append("\tinsetExtent_" + str(ddp.currentPageID) + " = arcpy.Extent(" + 26 | str(df.extent.XMin) + ", " + str(df.extent.YMin) + ", " + 27 | str(df.extent.XMax) + ", " + str(df.extent.YMax) + ")" + "\n") 28 | infoList.append("\tdataFrame.extent = insetExtent_" + str(ddp.currentPageID) + "\n") 29 | 30 | FILE.writelines(infoList) 31 | except: 32 | print "Writing to file failed" 33 | 34 | # Close the text file 35 | FILE.close() -------------------------------------------------------------------------------- /Python/writeScaleRotation.py: -------------------------------------------------------------------------------- 1 | # Start of write scale/rotation to Index table feature. 2 | indexTable = arcpy.mapping.ListLayers(mxd,"Index Layer")[0] 3 | fieldNames = ["scale", "rotation"] 4 | sqlClause = "\"District\" = '" + pageName + "'" 5 | 6 | # Assign first (i.e. zeroth) dataframe to variable. Should be 'MainDF'. 7 | df = arcpy.mapping.ListDataFrames(mxd)[0] 8 | 9 | # Create an Update Cursor object on the DDP Index Layer for the current page row. 10 | scaleRotationUpdateCursor = arcpy.da.UpdateCursor(indexTable, fieldNames, sqlClause) 11 | scaleRotationUpdateRow = scaleRotationUpdateCursor.next() 12 | 13 | # Set Index Layer scale field equal to MainD 14 | scaleRotationUpdateRow[0] = df.scale 15 | scaleRotationUpdateRow[1] = df.rotation 16 | scaleRotationUpdateCursor.updateRow(scaleRotationUpdateRow) 17 | 18 | del scaleRotationUpdateRow, scaleRotationUpdateCursor # End of scale/rotation feature -------------------------------------------------------------------------------- /QuerySelection/Images/ClearQueryCube.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jstep/Arcpy/1cf1c68de1d598069d1e98ad4de68c8273fd9792/QuerySelection/Images/ClearQueryCube.png -------------------------------------------------------------------------------- /QuerySelection/Images/EDHighlight.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jstep/Arcpy/1cf1c68de1d598069d1e98ad4de68c8273fd9792/QuerySelection/Images/EDHighlight.png -------------------------------------------------------------------------------- /QuerySelection/Images/Thumbs.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jstep/Arcpy/1cf1c68de1d598069d1e98ad4de68c8273fd9792/QuerySelection/Images/Thumbs.db -------------------------------------------------------------------------------- /QuerySelection/Images/spatialQuery.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jstep/Arcpy/1cf1c68de1d598069d1e98ad4de68c8273fd9792/QuerySelection/Images/spatialQuery.png -------------------------------------------------------------------------------- /QuerySelection/Install/QuerySelection_addin.py: -------------------------------------------------------------------------------- 1 | import arcpy 2 | import pythonaddins 3 | import os 4 | import sys 5 | 6 | 7 | sys.path.append(os.path.dirname(__file__)) # Add this script to system path. Used to separate main script from other code packages. 8 | import clearSelectedLayerQuery 9 | import getSelectionSet 10 | import querySelected 11 | 12 | class ClearSelection(object): 13 | """Implementation for QuerySelection_addin.clearSelection (Button)""" 14 | def __init__(self): 15 | self.enabled = True 16 | self.checked = False 17 | def onClick(self): 18 | clearSelectedLayerQuery.clearSelectedLayerQuery() 19 | 20 | class QuerySelection(object): 21 | """Implementation for QuerySelection_addin.querySelection (Button)""" 22 | def __init__(self): 23 | self.enabled = True 24 | self.checked = False 25 | def onClick(self): 26 | querySelected.querySelected() -------------------------------------------------------------------------------- /QuerySelection/Install/clearAllQueries.py: -------------------------------------------------------------------------------- 1 | def clearAllQueries(): 2 | """Removes all definition queries from layers in T.O.C.""" 3 | for lyr in arcpy.mapping.ListLayers(arcpy.mapping.MapDocument("CURRENT")): 4 | if lyr.supports("DEFINITIONQUERY"): 5 | lyr.definitionQuery = "" 6 | print "Definition query for '{}'' layer cleared.".format(lyr.name) 7 | arcpy.RefreshActiveView() -------------------------------------------------------------------------------- /QuerySelection/Install/clearSelectedLayerQuery.py: -------------------------------------------------------------------------------- 1 | def clearSelectedLayerQuery(): 2 | """Clear definition query from the layer selected in the T.O.C.""" 3 | try: 4 | import arcpy, pythonaddins 5 | lyr = pythonaddins.GetSelectedTOCLayerOrDataFrame() 6 | lyr.definitionQuery = "" 7 | print "Definition query for '{}'' layer cleared.".format(lyr.name) 8 | arcpy.RefreshActiveView() 9 | except AttributeError as e: 10 | pythonaddins.MessageBox("Please select a layer in the T.O.C to clear it's query", "Error") 11 | print e -------------------------------------------------------------------------------- /QuerySelection/Install/getSelectionSet.py: -------------------------------------------------------------------------------- 1 | def getSelectionSet(): 2 | """Returns a layer's selection as a Python set of feature IDs the layer's name, the data frame object, and the OID field name. 3 | Provides an easy way to retrieve the layer's current selection. 4 | """ 5 | try: 6 | import arcpy 7 | mxd = arcpy.mapping.MapDocument("CURRENT") 8 | df = mxd.activeDataFrame 9 | lyrLst = arcpy.mapping.ListLayers(mxd, "*", df) # Only list first dataframe to avoid identically named layers, where all would get selected. 10 | fidLst = [] 11 | lyrName = "" 12 | for lyr in lyrLst: 13 | try: 14 | if not lyr.isGroupLayer: 15 | desc = arcpy.Describe(lyr) 16 | if hasattr(desc, 'FIDSet'): 17 | if desc.FIDSet: 18 | fidLst.append(desc.FIDSet) 19 | lyrName = desc.nameString.split("\\")[-1] # Handles case of layers nested in groups. Gets lyr name minus the group name(s). 20 | OIDFieldName = desc.OIDFieldName 21 | except RuntimeError, TypeError: 22 | pass 23 | 24 | # Check for multiple layers selected. 25 | if len(fidLst) > 1: 26 | raise TypeError("Please select features from a single layer.") 27 | 28 | # Convert list string items to integers. 29 | fidLst = fidLst[0].split(";") 30 | fidLst = map(int, fidLst) 31 | 32 | # Return list of selected feature IDs, the selected layer name, the data frame it is in, and the OID field name. 33 | return fidLst, lyrName, df, OIDFieldName 34 | except IndexError as ie: 35 | import pythonaddins 36 | pythonaddins.MessageBox("{}. Please make a selection.".format(str(ie).capitalize()), "Selection Error") 37 | except Exception as e: 38 | import pythonaddins 39 | pythonaddins.MessageBox(e, "Error") -------------------------------------------------------------------------------- /QuerySelection/Install/querySelected.py: -------------------------------------------------------------------------------- 1 | def querySelected(): 2 | """Builds a definition query to display only the currently 3 | selected features for that layer. 4 | """ 5 | import arcpy, os, sys 6 | sys.path.append(os.path.dirname(__file__)) # Add this script to system path. Used to separate main script from other code packages. 7 | import getSelectionSet 8 | mxd = arcpy.mapping.MapDocument("CURRENT") 9 | ids, name, df, oid = getSelectionSet.getSelectionSet() 10 | lyr = arcpy.mapping.ListLayers(mxd, name, df)[0] 11 | 12 | # Build SQL clause to use in definition query. 13 | whereClause = "{} in ({})".format(oid, ','.join(str(id) for id in ids)) 14 | 15 | # Apply the definition query. 16 | lyr.definitionQuery = whereClause 17 | 18 | arcpy.RefreshActiveView() -------------------------------------------------------------------------------- /QuerySelection/QuerySelection.esriaddin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jstep/Arcpy/1cf1c68de1d598069d1e98ad4de68c8273fd9792/QuerySelection/QuerySelection.esriaddin -------------------------------------------------------------------------------- /QuerySelection/README.txt: -------------------------------------------------------------------------------- 1 | This is a stub project created by the ArcGIS Desktop Python AddIn Wizard. 2 | 3 | MANIFEST 4 | ======== 5 | 6 | README.txt : This file 7 | 8 | makeaddin.py : A script that will create a .esriaddin file out of this 9 | project, suitable for sharing or deployment 10 | 11 | config.xml : The AddIn configuration file 12 | 13 | Images/* : all UI images for the project (icons, images for buttons, 14 | etc) 15 | 16 | Install/* : The Python project used for the implementation of the 17 | AddIn. The specific python script to be used as the root 18 | module is specified in config.xml. 19 | -------------------------------------------------------------------------------- /QuerySelection/config.xml: -------------------------------------------------------------------------------- 1 | Query Selection{da067a95-0738-424f-9e01-1186d722d31f}Query Selection Addin1.0Images\EDHighlight.pngJames StephaniukEBC12/11/2015 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /QuerySelection/makeaddin.py: -------------------------------------------------------------------------------- 1 | import os 2 | import re 3 | import zipfile 4 | 5 | current_path = os.path.dirname(os.path.abspath(__file__)) 6 | 7 | out_zip_name = os.path.join(current_path, 8 | os.path.basename(current_path) + ".esriaddin") 9 | 10 | BACKUP_FILE_PATTERN = re.compile(".*_addin_[0-9]+[.]py$", re.IGNORECASE) 11 | 12 | def looks_like_a_backup(filename): 13 | return bool(BACKUP_FILE_PATTERN.match(filename)) 14 | 15 | with zipfile.ZipFile(out_zip_name, 'w', zipfile.ZIP_DEFLATED) as zip_file: 16 | for filename in ('config.xml', 'README.txt', 'makeaddin.py'): 17 | zip_file.write(os.path.join(current_path, filename), filename) 18 | dirs_to_add = ['Images', 'Install'] 19 | for directory in dirs_to_add: 20 | for (path, dirs, files) in os.walk(os.path.join(current_path, 21 | directory)): 22 | archive_path = os.path.relpath(path, current_path) 23 | found_file = False 24 | for file in (f for f in files if not looks_like_a_backup(f)): 25 | archive_file = os.path.join(archive_path, file) 26 | print archive_file 27 | zip_file.write(os.path.join(path, file), archive_file) 28 | found_file = True 29 | if not found_file: 30 | zip_file.writestr(os.path.join(archive_path, 31 | 'placeholder.txt'), 32 | "(Empty directory)") 33 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Arcpy AddIns & Command Line Tools 2 | ESRI Arcpy scripts for ArcGIS. 3 | 4 | A collection of add-in and command line tools for map production and automation. 5 | 6 | Add_Ins 7 |
    8 |
  • Contains tools to record, restore, and reset layouts of data driven page (DDP) enabled mxds. 9 |
  • Records layout position, size, and extents of north arrows, scale bars/text, and data frames. 10 |
  • Saves data to a `.dbf` with specific name, which can be changed. 11 |
12 | 13 | Annotation & Annotation_Stand_Alone 14 |
    15 |
  • ExtentBoxes Tool to create bounding boxes (polygons) of ddp dataframe extents of on-map dfs. Used for index polygon for Tiled Annotation creation. 16 |
  • GenerateTiledAnno Automation of `TiledLabelsToAnnotation_cartography` tool that uses above generated boxes as index polygons. 17 |
  • Stand-alone script is the same tool as above but is run from the command line with syntax `python NAME_OF_SCRIPT.py`. Doesn't need ArcMap GUI and is therefore much fasterthan the above tools. 18 |
19 | 20 | Layers 21 |
    22 |
  • A method of programmatically saving and restoring layer symbology for a given ddp. 23 |
  • Saves layerfiles to a specific location named as `pageName_layerName_dataframeName.lyr`. 24 |
25 | 26 | PDF_Export_Addin & PDF_Export_Stand_Alone 27 |
    28 |
  • Buttons to automate pdf export with pre-defined parameters. Can be easily altered to allow different params. 29 |
  • Generates pdf name in the form `pageName_dpi_colorspace_orientation`. 30 |
  • Stand-alone script is the same tool as above but is run from the command line with syntax `python NAME_OF_SCRIPT.py DPI` where DPI is and integer representing the dots per inch of the exported pdf. Doesn't need ArcMap GUI and is therefore much faster than the above tools. 31 |
32 | 33 | QuerySelection 34 |
    35 |
  • On button press genterates definition query for layer of selected features. Simply select features you want to display for one layer, and press the button. 36 |
  • Select layer in table of contents and press clear selection button to clear the query for that layer. 37 |
38 | 39 | ReplicateSD (Command Line Tool) 40 |
    41 |
  • An automated way to replicate ArcSDE connected database to a local FGDB to improve performance. 42 |
  • Uses a list (`layerNameLst`) to control which files are copied. Can easily be altered to include all files on SDE. 43 |
  • Change databaseConnection variable to your .sde connection file. 44 |
  • Can be run by a task scheduler at regular intervals to keep data up-to-date. 45 |
46 | -------------------------------------------------------------------------------- /SDE_Replication/ReplicateSDE.py: -------------------------------------------------------------------------------- 1 | import arcpy 2 | import datetime 3 | import logging 4 | import logging.handlers 5 | import os 6 | import shutil 7 | import sys 8 | import time 9 | 10 | ########################### User defined functions ########################### 11 | 12 | def getDatabaseItemCount(workspace): 13 | log = logging.getLogger("script_log") 14 | """returns the item count in provided database""" 15 | arcpy.env.workspace = workspace 16 | feature_classes = [] 17 | log.info("Compiling a list of items in {0} and getting count.".format(workspace)) 18 | for dirpath, dirnames, filenames in arcpy.da.Walk(workspace,datatype="Any",type="Any"): 19 | for filename in filenames: 20 | feature_classes.append(os.path.join(dirpath, filename)) 21 | log.info("There are a total of {0} items in the database".format(len(feature_classes))) 22 | return feature_classes, len(feature_classes) 23 | 24 | def replicateDatabase(dbConnection, targetGDB): 25 | log = logging.getLogger("script_log") 26 | startTime = time.time() 27 | 28 | if arcpy.Exists(dbConnection): 29 | featSDE,cntSDE = getDatabaseItemCount(dbConnection) 30 | log.info("Geodatabase being copied: %s -- Feature Count: %s" %(dbConnection, cntSDE)) 31 | if arcpy.Exists(targetGDB): 32 | # Archive old geodatabase with timestamp. 33 | # shutil.copytree(targetGDB, os.path.join(os.path.dirname(__file__), str(now.strftime("%Y-%m-%d_%H-%M.gdb")))) # TODO: Release Locking 34 | featGDB,cntGDB = getDatabaseItemCount(targetGDB) 35 | log.info("Old Target Geodatabase: %s -- Feature Count: %s" %(targetGDB, cntGDB)) 36 | try: 37 | shutil.rmtree(targetGDB) 38 | log.info("Deleted Old %s" %(os.path.split(targetGDB)[-1])) 39 | except Exception as e: 40 | log.info(e) 41 | 42 | GDB_Path, GDB_Name = os.path.split(targetGDB) 43 | log.info("Now Creating New %s" %(GDB_Name)) 44 | arcpy.CreateFileGDB_management(GDB_Path, GDB_Name) 45 | 46 | arcpy.env.workspace = dbConnection 47 | 48 | # try: 49 | # datasetList = [arcpy.Describe(a).name for a in arcpy.ListDatasets()] 50 | # except Exception as e: 51 | # datasetList = [] 52 | # log.info(e) 53 | try: 54 | featureClasses = layerNameLst 55 | except Exception as e: 56 | featureClasses = [] 57 | log.info(e) 58 | # try: 59 | # tables = [arcpy.Describe(a).name for a in arcpy.ListTables()] 60 | # except Exception as e: 61 | # tables = [] 62 | # log.info(e) 63 | 64 | #Compiles a list of the previous three lists to iterate over 65 | allDbData = featureClasses # + datasetList + tables 66 | 67 | for sourcePath in allDbData: 68 | targetName = sourcePath.split('.')[-1] 69 | targetPath = os.path.join(targetGDB, targetName) 70 | if not arcpy.Exists(targetPath): 71 | try: 72 | log.info("Attempting to Copy %s to %s" %(targetName, targetPath)) 73 | arcpy.Copy_management(sourcePath, targetPath) 74 | log.info("Finished copying %s to %s" %(targetName, targetPath)) 75 | except Exception as e: 76 | log.info("Unable to copy %s to %s" %(targetName, targetPath)) 77 | log.info(e) 78 | else: 79 | log.info("%s already exists....skipping....." %(targetName)) 80 | 81 | featGDB,cntGDB = getDatabaseItemCount(targetGDB) 82 | log.info("Completed replication of %s -- Feature Count: %s" %(dbConnection, cntGDB)) 83 | 84 | else: 85 | log.info("{0} does not exist or is not supported! \ 86 | Please check the database path and try again.".format(dbConnection)) 87 | 88 | def formatTime(x): 89 | minutes, seconds_rem = divmod(x, 60) 90 | if minutes >= 60: 91 | hours, minutes_rem = divmod(minutes, 60) 92 | return "%02d:%02d:%02d" % (hours, minutes_rem, seconds_rem) 93 | else: 94 | minutes, seconds_rem = divmod(x, 60) 95 | return "00:%02d:%02d" % (minutes, seconds_rem) 96 | 97 | ################################# Layer List ################################# 98 | # Layer name list. Controls which features will be replicated. 99 | layerNameLst = [ 100 | 'indea:mdwilkie.indea_bs10_covlines_view_active', 101 | 'indea:mdwilkie.indea_background_ebc_greenspace_active', 102 | 'indea:mdwilkie.indea_background_ebc_usa_poly_active', 103 | 'indea:mdwilkie.indea_background_ebc_communities_active', 104 | 'indea:genmaint.idm_ebc_roads', 105 | 'indea:mdwilkie.indea_road_segments_active', 106 | 'indea:mdwilkie.indea_background_ebc_railways_active', 107 | 'indea:genmaint.idm_ebc_municipalities_ebc_indian_reserves', 108 | 'indea:mdwilkie.indea_background_ebc_canada_poly_active', 109 | 'indea:mdwilkie.indea_background_ebc_water_features_streams_active', 110 | 'indea:mdwilkie.indea_background_ebc_water_features_areal_active', 111 | 'indea:genmaint.cart_ebc_buildings', 112 | 'indea:mdwilkie.indea_background_ebc_ocean_active', 113 | 'indea:mdwilkie.indea_background_ebc_islands_active', 114 | 'indea:mdwilkie.indea_background_ebc_parks_active', 115 | 'indea:genmaint.cart_ebc_water_features_streams_tab', 116 | 'indea:genmaint.indea_background_ebc_external_transparency_active' 117 | ] 118 | 119 | if __name__ == "__main__": 120 | startTime = time.time() 121 | now = datetime.datetime.now() 122 | 123 | ############################# User variables ############################# 124 | # Change this variable to the target database location (SDE connection). 125 | databaseConnection = "PATH_TO_YOUR_SDE_CONNECTION" 126 | 127 | # Log files folder will be created at same directory level as script. 128 | logPath = os.path.join(os.path.dirname(os.path.realpath(__file__)), "replicateSDE_Logfiles") 129 | if not os.path.exists(logPath): 130 | os.makedirs(logPath) 131 | 132 | # Replicated FGDB will be created at same directory level as script. 133 | targetGDB = os.path.join(os.path.dirname(os.path.realpath(__file__)), "Replicated.gdb") 134 | 135 | ############################## Logging items ############################# 136 | 137 | # Make a global logging object. 138 | logName = os.path.join(logPath,(now.strftime("%Y-%m-%d_%H-%M.log"))) 139 | 140 | log = logging.getLogger("script_log") 141 | log.setLevel(logging.INFO) 142 | 143 | h1 = logging.FileHandler(logName) 144 | h2 = logging.StreamHandler() 145 | 146 | f = logging.Formatter("[%(levelname)s] [%(asctime)s] [%(lineno)d] - %(message)s",'%m/%d/%Y %I:%M:%S %p') 147 | 148 | h1.setFormatter(f) 149 | h2.setFormatter(f) 150 | 151 | h1.setLevel(logging.INFO) 152 | h2.setLevel(logging.INFO) 153 | 154 | log.addHandler(h1) 155 | log.addHandler(h2) 156 | 157 | log.info('----------------------------------------------------') 158 | log.info('Script: {0}'.format(os.path.basename(sys.argv[0]))) 159 | log.info('----------------------------------------------------') 160 | 161 | try: 162 | ########################### Function calls ########################### 163 | 164 | replicateDatabase(databaseConnection, targetGDB) 165 | 166 | ###################################################################### 167 | except Exception as e: 168 | log.exception(e) 169 | 170 | totalTime = formatTime((time.time() - startTime)) 171 | log.info('----------------------------------------------------') 172 | log.info("Script Completed After: {0}".format(totalTime)) 173 | log.info('----------------------------------------------------') -------------------------------------------------------------------------------- /SQL/PrelimReport87EDs_web.dbf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jstep/Arcpy/1cf1c68de1d598069d1e98ad4de68c8273fd9792/SQL/PrelimReport87EDs_web.dbf -------------------------------------------------------------------------------- /SQL/PrelimReport87EDs_web.prj: -------------------------------------------------------------------------------- 1 | PROJCS["Canada_Albers_Equal_Area_Conic",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Albers"],PARAMETER["False_Easting",1000000.0],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",-126.0],PARAMETER["Standard_Parallel_1",58.5],PARAMETER["Standard_Parallel_2",50.0],PARAMETER["Latitude_Of_Origin",45.0],UNIT["Meter",1.0]] -------------------------------------------------------------------------------- /SQL/PrelimReport87EDs_web.shp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jstep/Arcpy/1cf1c68de1d598069d1e98ad4de68c8273fd9792/SQL/PrelimReport87EDs_web.shp -------------------------------------------------------------------------------- /SQL/PrelimReport87EDs_web.shx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jstep/Arcpy/1cf1c68de1d598069d1e98ad4de68c8273fd9792/SQL/PrelimReport87EDs_web.shx -------------------------------------------------------------------------------- /SQL/createViewSDE.sql: -------------------------------------------------------------------------------- 1 | CREATE VIEW ed_bs10_view 2 | AS SELECT * 3 | FROM indea:mdwilkie.indea_edvas_active ed 4 | WHERE ed.emp_id = "10"; 5 | 6 | 7 | # Grant privileges 8 | GRANT SELECT 9 | ON ed_bs10_view 10 | TO USER dispatch_mgr WITH GRANT OPTION; 11 | 12 | 13 | -- http://resources.arcgis.com/en/help/main/10.2/index.html#//002m000000rs000000 14 | 15 | 16 | 17 | -- Table 18 | indea:mdwilkie.indea_edvas_active 19 | -- BS Field 20 | ebc_bdy_set_id 21 | -- View name 22 | edvas_active_bs10_v_ 23 | 24 | 25 | 26 | -- Arcpy 27 | INPUT_DATABASE = "C:\Users\jastepha\AppData\Roaming\ESRI\Desktop10.2\ArcCatalog\Connection to indeaprod2.sde" 28 | VIEW_DEFINITION = "SELECT * FROM indea:mdwilkie.indea_edvas_active WHERE ebc_bdy_set_id='10'" 29 | VIEW_NAME = "edvas_active_bs10_v_" 30 | arcpy.CreateDatabaseView_management(INPUT_DATABASE, VIEW_NAME, VIEW_DEFINITION) -------------------------------------------------------------------------------- /SQL/tcn_road_type_QUERY.txt: -------------------------------------------------------------------------------- 1 | -- Combination for mapping purposes. 2 | tcn_road_type IN ( 'arterial' , 'collector' , 'freeway' , 'highway' , 'Highway' ) AND road_generation = 'e' AND is_standard IN ('T','t') AND boundary_set_id = 8 3 | 4 | -- Minor Roads. 'boundary_set_id' removes NULL values, roads outside of BC (e.g. Yukon) 5 | tcn_road_type IN ( 'lane', 'local', 'recreation', 'resource', 'strata', 'service') AND is_standard IN ('T', 't') AND boundary_set_id = 8 6 | 7 | -- Major Roads 8 | tcn_road_type IN ( 'arterial', 'collector', 'ramp') AND is_standard IN ('T', 't') AND boundary_set_id = 8 9 | 10 | -- Highways 11 | tcn_road_type IN ( 'highway', 'freeway') AND is_standard IN ('T', 't') AND boundary_set_id = 8 12 | -------------------------------------------------------------------------------- /XY/shpToTxtCoords.py: -------------------------------------------------------------------------------- 1 | """****************************************************************** 2 | shpToTxtCoords.py 3 | Version: ArcGIS 10.2.1 4 | 5 | Description: Writes the X and Y coordinates of a polygon shapefile's 6 | verticies with a descriptive label to a text file. 7 | 8 | Author: James Stephaniuk 9 | 10 | Date: April 23, 2015 11 | ******************************************************************""" 12 | 13 | import arcpy 14 | 15 | # Map document - MXD. 16 | mxd = arcpy.mapping.MapDocument('CURRENT') 17 | # Polygon feature class. Target feature must be the first item in TOC. 18 | fc = arcpy.mapping.ListLayers(mxd)[0] 19 | 20 | # Create 'describe' object. 21 | desc = arcpy.Describe(fc) 22 | # Get shape field name and layer name of feature class. 23 | if hasattr(desc, "ShapeFieldName") and hasattr(desc, "baseName"): 24 | ShapeFieldName = desc.ShapeFieldName 25 | layerName = desc.baseName 26 | 27 | # Output save path for text file. 28 | outDir = r"P:\\15045 - ED Redistribution - Event Specific\\R2015\21-Electoral_Boundaries_Commission_Support_Doc\\WBS 8 - Geography\\James\\XY\\" 29 | 30 | # Column of shapefile for text file label. 31 | inField = "DIST_NAM_1" 32 | 33 | # Create update cursor on feature class. 34 | uCursor = arcpy.UpdateCursor(fc) 35 | 36 | # Open text file with overwrite permissions (w). Creates a text file if one does not exist already. 37 | # f = open(r"P:\\15045 - ED Redistribution - Event Specific\\R2015\21-Electoral_Boundaries_Commission_Support_Doc\\WBS 8 - Geography\\James\\XY\\Melnick_Final.txt", 'w') 38 | f = open("{}{}.txt".format(outDir, layerName), 'w') 39 | for shp in uCursor: 40 | polygon = shp.getValue(ShapeFieldName) 41 | for point in polygon: 42 | for p in point: 43 | # Convert x-y coordinates to strings for file writing. 44 | x = str(p.X) 45 | y = str(p.Y) 46 | # Write inField, x, y to text file. 47 | f.write(shp.getValue(inField) + ",") 48 | f.write(x + ",") 49 | f.write(y + "\n") 50 | # Close text file. 51 | f.close() 52 | -------------------------------------------------------------------------------- /addin-wizard/.hgtags: -------------------------------------------------------------------------------- 1 | d2c510239e37de29c20718cbbbfc53e94de59e0c 10.2-wizard 2 | -------------------------------------------------------------------------------- /addin-wizard/LICENSE: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jstep/Arcpy/1cf1c68de1d598069d1e98ad4de68c8273fd9792/addin-wizard/LICENSE -------------------------------------------------------------------------------- /addin-wizard/README.md: -------------------------------------------------------------------------------- 1 | # Python Add-In Wizard 2 | 3 | This is the application linked to in the help for creating Python Add-Ins in ArcGIS 10.1/10.2. It's a simple wxPython app bundled with py2exe, so it should act as a good example to learn from for doing that, too. 4 | 5 | This app does not require ArcGIS in any way to function, nor does it import or use arcpy/arcgisscripting in any way. It's just a UI to make boilerplate `.xml`/`.py` files. 6 | 7 | ## Licensing 8 | Copyright 2013 Esri 9 | 10 | Licensed under the Apache License, Version 2.0 (the "License"); 11 | you may not use this file except in compliance with the License. 12 | You may obtain a copy of the License at 13 | 14 | http://www.apache.org/licenses/LICENSE-2.0 15 | 16 | Unless required by applicable law or agreed to in writing, software 17 | distributed under the License is distributed on an "AS IS" BASIS, 18 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 19 | See the License for the specific language governing permissions and 20 | limitations under the License. 21 | 22 | A copy of the license is available in the repository's license.txt file. 23 | 24 | [](Esri: ArcGIS Python Add-In Wizard) 25 | [](Esri Language: Python) 26 | -------------------------------------------------------------------------------- /addin-wizard/addin_ui.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # generated by wxGlade 0.6.3 on Mon Sep 19 12:33:19 2011 4 | 5 | import wx 6 | 7 | # begin wxGlade: extracode 8 | _msize = wx.Size(700, 550) 9 | _msize = wx.Size(700, 550) 10 | # end wxGlade 11 | 12 | 13 | 14 | class AddinMakerWindow(wx.Frame): 15 | def __init__(self, *args, **kwds): 16 | # begin wxGlade: AddinMakerWindow.__init__ 17 | kwds["style"] = wx.DEFAULT_FRAME_STYLE 18 | wx.Frame.__init__(self, *args, **kwds) 19 | self.full_app_panel = wx.Panel(self, -1) 20 | self.bottom_buttons_pane = wx.Panel(self.full_app_panel, -1) 21 | self.propsheet_panel = wx.Panel(self.full_app_panel, -1) 22 | self.tabs_notebook = wx.Notebook(self.propsheet_panel, -1, style=0) 23 | self.project_items_pane = wx.Panel(self.tabs_notebook, -1) 24 | self.item_property_panel = wx.Panel(self.project_items_pane, -1) 25 | self.project_settings_pane = wx.Panel(self.tabs_notebook, -1) 26 | self.logo_panel = wx.Panel(self.propsheet_panel, -1) 27 | self.properties_rows_holder_staticbox = wx.StaticBox(self.project_settings_pane, -1, "Project Properties:") 28 | self.title_panel = wx.Panel(self.full_app_panel, -1) 29 | self.title_label = wx.StaticText(self.title_panel, -1, "Python Add-In Wizard", style=wx.ALIGN_RIGHT) 30 | self.title_divider_line = wx.StaticLine(self.full_app_panel, -1) 31 | self.logo_bitmap = wx.StaticBitmap(self.logo_panel, -1, wx.Bitmap("images\\AddInDesktop64.png", wx.BITMAP_TYPE_ANY)) 32 | self.folder_label = wx.StaticText(self.project_settings_pane, -1, "Working Folder:", style=wx.ALIGN_RIGHT) 33 | self.folder_button = wx.Button(self.project_settings_pane, -1, "Select Folder...") 34 | self.product_label = wx.StaticText(self.project_settings_pane, -1, "Select Product:", style=wx.ALIGN_RIGHT) 35 | self.product_combo_box = wx.ComboBox(self.project_settings_pane, -1, choices=["ArcMap", "ArcGlobe", "ArcScene", "ArcCatalog"], style=wx.CB_DROPDOWN|wx.CB_READONLY) 36 | self.static_line_1 = wx.StaticLine(self.project_settings_pane, -1) 37 | self.project_name_label = wx.StaticText(self.project_settings_pane, -1, "Name*:", style=wx.ALIGN_RIGHT) 38 | self.project_name = wx.TextCtrl(self.project_settings_pane, -1, "") 39 | self.project_version_label = wx.StaticText(self.project_settings_pane, -1, "Version*:", style=wx.ALIGN_RIGHT) 40 | self.project_version = wx.TextCtrl(self.project_settings_pane, -1, "") 41 | self.project_company_label = wx.StaticText(self.project_settings_pane, -1, "Company:", style=wx.ALIGN_RIGHT) 42 | self.project_company = wx.TextCtrl(self.project_settings_pane, -1, "") 43 | self.project_description_label = wx.StaticText(self.project_settings_pane, -1, "Description:", style=wx.ALIGN_RIGHT) 44 | self.project_description = wx.TextCtrl(self.project_settings_pane, -1, "") 45 | self.project_author_label = wx.StaticText(self.project_settings_pane, -1, "Author:", style=wx.ALIGN_RIGHT) 46 | self.project_author = wx.TextCtrl(self.project_settings_pane, -1, "") 47 | self.image_section_divider = wx.StaticLine(self.project_settings_pane, -1) 48 | self.project_image_label = wx.StaticText(self.project_settings_pane, -1, "Image:", style=wx.ALIGN_RIGHT) 49 | self.select_project_image = wx.Button(self.project_settings_pane, -1, "Select Image...") 50 | self.icon_bitmap = wx.StaticBitmap(self.project_settings_pane, -1, wx.Bitmap("images\\AddInDesktop48.png", wx.BITMAP_TYPE_ANY), style=wx.SIMPLE_BORDER) 51 | self.contents_tree = wx.TreeCtrl(self.project_items_pane, -1, style=wx.TR_HAS_BUTTONS|wx.TR_LINES_AT_ROOT|wx.TR_HIDE_ROOT|wx.TR_DEFAULT_STYLE|wx.RAISED_BORDER) 52 | self.bottom_buttons_spacer_panel = wx.Panel(self.bottom_buttons_pane, -1) 53 | self.open_folder = wx.Button(self.bottom_buttons_pane, -1, "Open Folder") 54 | self.save_button = wx.Button(self.bottom_buttons_pane, -1, "Save") 55 | 56 | self.__set_properties() 57 | self.__do_layout() 58 | 59 | self.Bind(wx.EVT_BUTTON, self.SelectFolder, self.folder_button) 60 | self.Bind(wx.EVT_COMBOBOX, self.ComboBox, self.product_combo_box) 61 | self.Bind(wx.EVT_TEXT_ENTER, self.ProjectNameText, self.project_name) 62 | self.Bind(wx.EVT_TEXT, self.ProjectNameText, self.project_name) 63 | self.Bind(wx.EVT_TEXT_ENTER, self.ProjectVersionText, self.project_version) 64 | self.Bind(wx.EVT_TEXT, self.ProjectVersionText, self.project_version) 65 | self.Bind(wx.EVT_TEXT_ENTER, self.ProjectCompanyText, self.project_company) 66 | self.Bind(wx.EVT_TEXT, self.ProjectCompanyText, self.project_company) 67 | self.Bind(wx.EVT_TEXT_ENTER, self.ProjectDescriptionText, self.project_description) 68 | self.Bind(wx.EVT_TEXT, self.ProjectDescriptionText, self.project_description) 69 | self.Bind(wx.EVT_TEXT_ENTER, self.ProjectAuthorText, self.project_author) 70 | self.Bind(wx.EVT_TEXT, self.ProjectAuthorText, self.project_author) 71 | self.Bind(wx.EVT_BUTTON, self.SelectProjectImage, self.select_project_image) 72 | self.Bind(wx.EVT_TREE_BEGIN_DRAG, self.BeginDrag, self.contents_tree) 73 | self.Bind(wx.EVT_TREE_END_DRAG, self.EndDrag, self.contents_tree) 74 | self.Bind(wx.EVT_TREE_DELETE_ITEM, self.DeleteItem, self.contents_tree) 75 | self.Bind(wx.EVT_TREE_SEL_CHANGED, self.SelChanged, self.contents_tree) 76 | self.Bind(wx.EVT_NOTEBOOK_PAGE_CHANGING, self.ChangeTab, self.tabs_notebook) 77 | self.Bind(wx.EVT_BUTTON, self.OpenFolder, self.open_folder) 78 | self.Bind(wx.EVT_BUTTON, self.SaveProject, self.save_button) 79 | # end wxGlade 80 | 81 | def __set_properties(self): 82 | # begin wxGlade: AddinMakerWindow.__set_properties 83 | self.SetTitle("ArcGIS Python Add-In Wizard") 84 | self.SetMinSize(_msize) 85 | self.title_label.SetFont(wx.Font(16, wx.DEFAULT, wx.NORMAL, wx.NORMAL, 0, "")) 86 | self.title_panel.SetBackgroundColour(wx.SystemSettings_GetColour(wx.SYS_COLOUR_3DHIGHLIGHT)) 87 | self.product_combo_box.SetSelection(0) 88 | self.project_name_label.SetMinSize((72, 16)) 89 | self.project_version_label.SetMinSize((72, 16)) 90 | self.project_company_label.SetMinSize((72, 16)) 91 | self.project_description_label.SetMinSize((72, 16)) 92 | self.project_author_label.SetMinSize((72, 16)) 93 | self.project_image_label.SetMinSize((72, 16)) 94 | self.contents_tree.SetMinSize((200, 484)) 95 | # end wxGlade 96 | 97 | def __do_layout(self): 98 | # begin wxGlade: AddinMakerWindow.__do_layout 99 | full_window_sizer = wx.BoxSizer(wx.HORIZONTAL) 100 | main_sizer = wx.BoxSizer(wx.VERTICAL) 101 | bottom_buttons_sizer = wx.BoxSizer(wx.HORIZONTAL) 102 | content_sizer = wx.BoxSizer(wx.HORIZONTAL) 103 | splitter_sizer = wx.BoxSizer(wx.HORIZONTAL) 104 | items_sizer = wx.BoxSizer(wx.HORIZONTAL) 105 | item_property_sizer = wx.BoxSizer(wx.VERTICAL) 106 | fields_sizer = wx.BoxSizer(wx.VERTICAL) 107 | properties_rows_holder = wx.StaticBoxSizer(self.properties_rows_holder_staticbox, wx.VERTICAL) 108 | project_bitmap_display_sizer = wx.BoxSizer(wx.HORIZONTAL) 109 | properties_rows = wx.BoxSizer(wx.VERTICAL) 110 | project_image_sizer = wx.BoxSizer(wx.HORIZONTAL) 111 | project_author_sizer = wx.BoxSizer(wx.HORIZONTAL) 112 | project_description_sizer = wx.BoxSizer(wx.HORIZONTAL) 113 | project_company_sizer = wx.BoxSizer(wx.HORIZONTAL) 114 | project_version_sizer = wx.BoxSizer(wx.HORIZONTAL) 115 | project_name_sizer = wx.BoxSizer(wx.HORIZONTAL) 116 | product_sizer = wx.BoxSizer(wx.HORIZONTAL) 117 | folder_sizer = wx.BoxSizer(wx.HORIZONTAL) 118 | logo_sizer = wx.BoxSizer(wx.HORIZONTAL) 119 | title_sizer = wx.BoxSizer(wx.HORIZONTAL) 120 | title_sizer.Add(self.title_label, 0, wx.ALL|wx.ALIGN_RIGHT|wx.ALIGN_CENTER_HORIZONTAL, 8) 121 | self.title_panel.SetSizer(title_sizer) 122 | main_sizer.Add(self.title_panel, 0, wx.EXPAND|wx.ALIGN_RIGHT, 0) 123 | main_sizer.Add(self.title_divider_line, 0, wx.EXPAND, 0) 124 | logo_sizer.Add(self.logo_bitmap, 0, wx.TOP, 8) 125 | self.logo_panel.SetSizer(logo_sizer) 126 | splitter_sizer.Add(self.logo_panel, 0, wx.EXPAND, 0) 127 | folder_sizer.Add(self.folder_label, 0, wx.ALIGN_CENTER_VERTICAL, 8) 128 | folder_sizer.Add(self.folder_button, 1, wx.EXPAND, 8) 129 | fields_sizer.Add(folder_sizer, 0, wx.ALL|wx.EXPAND, 4) 130 | product_sizer.Add(self.product_label, 0, wx.ALIGN_CENTER_VERTICAL, 3) 131 | product_sizer.Add(self.product_combo_box, 0, 0, 3) 132 | fields_sizer.Add(product_sizer, 0, wx.ALL|wx.EXPAND, 4) 133 | fields_sizer.Add(self.static_line_1, 0, wx.ALL|wx.EXPAND, 8) 134 | project_name_sizer.Add(self.project_name_label, 0, wx.ALL|wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL, 2) 135 | project_name_sizer.Add(self.project_name, 1, wx.EXPAND, 0) 136 | properties_rows.Add(project_name_sizer, 1, wx.EXPAND, 0) 137 | project_version_sizer.Add(self.project_version_label, 0, wx.ALL|wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL, 2) 138 | project_version_sizer.Add(self.project_version, 1, wx.EXPAND, 0) 139 | properties_rows.Add(project_version_sizer, 1, wx.EXPAND, 0) 140 | project_company_sizer.Add(self.project_company_label, 0, wx.ALL|wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL, 2) 141 | project_company_sizer.Add(self.project_company, 1, wx.EXPAND, 0) 142 | properties_rows.Add(project_company_sizer, 1, wx.EXPAND, 0) 143 | project_description_sizer.Add(self.project_description_label, 0, wx.ALL|wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL, 2) 144 | project_description_sizer.Add(self.project_description, 1, wx.EXPAND, 0) 145 | properties_rows.Add(project_description_sizer, 1, wx.EXPAND, 0) 146 | project_author_sizer.Add(self.project_author_label, 0, wx.ALL|wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL, 2) 147 | project_author_sizer.Add(self.project_author, 1, wx.EXPAND, 0) 148 | properties_rows.Add(project_author_sizer, 1, wx.EXPAND, 0) 149 | properties_rows.Add(self.image_section_divider, 0, wx.ALL|wx.EXPAND, 2) 150 | project_image_sizer.Add(self.project_image_label, 0, wx.ALL|wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL, 2) 151 | project_image_sizer.Add(self.select_project_image, 0, 0, 0) 152 | properties_rows.Add(project_image_sizer, 1, wx.EXPAND, 3) 153 | properties_rows_holder.Add(properties_rows, 0, wx.EXPAND, 0) 154 | project_bitmap_display_sizer.Add(self.icon_bitmap, 0, wx.TOP, 3) 155 | properties_rows_holder.Add(project_bitmap_display_sizer, 1, wx.LEFT|wx.EXPAND, 80) 156 | fields_sizer.Add(properties_rows_holder, 0, wx.EXPAND, 0) 157 | self.project_settings_pane.SetSizer(fields_sizer) 158 | items_sizer.Add(self.contents_tree, 0, wx.EXPAND, 0) 159 | self.item_property_panel.SetSizer(item_property_sizer) 160 | items_sizer.Add(self.item_property_panel, 1, wx.EXPAND, 0) 161 | self.project_items_pane.SetSizer(items_sizer) 162 | self.tabs_notebook.AddPage(self.project_settings_pane, "Project Settings") 163 | self.tabs_notebook.AddPage(self.project_items_pane, "Add-In Contents") 164 | splitter_sizer.Add(self.tabs_notebook, 1, wx.EXPAND, 4) 165 | content_sizer.Add(splitter_sizer, 1, wx.EXPAND, 4) 166 | self.propsheet_panel.SetSizer(content_sizer) 167 | main_sizer.Add(self.propsheet_panel, 1, wx.EXPAND, 0) 168 | bottom_buttons_sizer.Add(self.bottom_buttons_spacer_panel, 1, wx.EXPAND, 0) 169 | bottom_buttons_sizer.Add(self.open_folder, 0, wx.ALL, 2) 170 | bottom_buttons_sizer.Add(self.save_button, 0, wx.ALL, 2) 171 | self.bottom_buttons_pane.SetSizer(bottom_buttons_sizer) 172 | main_sizer.Add(self.bottom_buttons_pane, 0, wx.EXPAND, 4) 173 | self.full_app_panel.SetSizer(main_sizer) 174 | full_window_sizer.Add(self.full_app_panel, 1, wx.ALL|wx.EXPAND, 1) 175 | self.SetSizer(full_window_sizer) 176 | full_window_sizer.Fit(self) 177 | self.Layout() 178 | self.Centre() 179 | # end wxGlade 180 | 181 | def SelectFolder(self, event): # wxGlade: AddinMakerWindow. 182 | print "Event handler `SelectFolder' not implemented!" 183 | event.Skip() 184 | 185 | def ComboBox(self, event): # wxGlade: AddinMakerWindow. 186 | print "Event handler `ComboBox' not implemented!" 187 | event.Skip() 188 | 189 | def ProjectNameText(self, event): # wxGlade: AddinMakerWindow. 190 | print "Event handler `ProjectNameText' not implemented!" 191 | event.Skip() 192 | 193 | def ProjectVersionText(self, event): # wxGlade: AddinMakerWindow. 194 | print "Event handler `ProjectVersionText' not implemented!" 195 | event.Skip() 196 | 197 | def ProjectCompanyText(self, event): # wxGlade: AddinMakerWindow. 198 | print "Event handler `ProjectCompanyText' not implemented!" 199 | event.Skip() 200 | 201 | def ProjectDescriptionText(self, event): # wxGlade: AddinMakerWindow. 202 | print "Event handler `ProjectDescriptionText' not implemented!" 203 | event.Skip() 204 | 205 | def ProjectAuthorText(self, event): # wxGlade: AddinMakerWindow. 206 | print "Event handler `ProjectAuthorText' not implemented!" 207 | event.Skip() 208 | 209 | def SelectProjectImage(self, event): # wxGlade: AddinMakerWindow. 210 | print "Event handler `SelectProjectImage' not implemented!" 211 | event.Skip() 212 | 213 | def BeginDrag(self, event): # wxGlade: AddinMakerWindow. 214 | print "Event handler `BeginDrag' not implemented!" 215 | event.Skip() 216 | 217 | def EndDrag(self, event): # wxGlade: AddinMakerWindow. 218 | print "Event handler `EndDrag' not implemented!" 219 | event.Skip() 220 | 221 | def DeleteItem(self, event): # wxGlade: AddinMakerWindow. 222 | print "Event handler `DeleteItem' not implemented!" 223 | event.Skip() 224 | 225 | def SelChanged(self, event): # wxGlade: AddinMakerWindow. 226 | print "Event handler `SelChanged' not implemented!" 227 | event.Skip() 228 | 229 | def ChangeTab(self, event): # wxGlade: AddinMakerWindow. 230 | print "Event handler `ChangeTab' not implemented!" 231 | event.Skip() 232 | 233 | def OpenFolder(self, event): # wxGlade: AddinMakerWindow. 234 | print "Event handler `OpenFolder' not implemented!" 235 | event.Skip() 236 | 237 | def SaveProject(self, event): # wxGlade: AddinMakerWindow. 238 | print "Event handler `SaveProject' not implemented!" 239 | event.Skip() 240 | 241 | # end of class AddinMakerWindow 242 | 243 | 244 | if __name__ == "__main__": 245 | app = wx.PySimpleApp(0) 246 | wx.InitAllImageHandlers() 247 | addin_window = AddinMakerWindow(None, -1, "") 248 | app.SetTopWindow(addin_window) 249 | addin_window.Show() 250 | app.MainLoop() 251 | -------------------------------------------------------------------------------- /addin-wizard/i18n.py: -------------------------------------------------------------------------------- 1 | __all__ = ['_'] 2 | 3 | import json 4 | import os 5 | 6 | try: 7 | translations_dict = json.loads(open(os.path.join('resources', 'resource_strings.json'), 'rb').read().decode('utf-8')) 8 | except: 9 | print "Can't load translation strings file." 10 | 11 | def _(the_text): 12 | return translations_dict.get(the_text, the_text) 13 | -------------------------------------------------------------------------------- /addin-wizard/images/AddInDesktop.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jstep/Arcpy/1cf1c68de1d598069d1e98ad4de68c8273fd9792/addin-wizard/images/AddInDesktop.ico -------------------------------------------------------------------------------- /addin-wizard/images/AddInDesktop48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jstep/Arcpy/1cf1c68de1d598069d1e98ad4de68c8273fd9792/addin-wizard/images/AddInDesktop48.png -------------------------------------------------------------------------------- /addin-wizard/images/AddInDesktop64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jstep/Arcpy/1cf1c68de1d598069d1e98ad4de68c8273fd9792/addin-wizard/images/AddInDesktop64.png -------------------------------------------------------------------------------- /addin-wizard/images/Thumbs.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jstep/Arcpy/1cf1c68de1d598069d1e98ad4de68c8273fd9792/addin-wizard/images/Thumbs.db -------------------------------------------------------------------------------- /addin-wizard/packaging/README.txt: -------------------------------------------------------------------------------- 1 | This is a stub project created by the ArcGIS Desktop Python AddIn Wizard. 2 | 3 | MANIFEST 4 | ======== 5 | 6 | README.txt : This file 7 | 8 | makeaddin.py : A script that will create a .esriaddin file out of this 9 | project, suitable for sharing or deployment 10 | 11 | config.xml : The AddIn configuration file 12 | 13 | Images/* : all UI images for the project (icons, images for buttons, 14 | etc) 15 | 16 | Install/* : The Python project used for the implementation of the 17 | AddIn. The specific python script to be used as the root 18 | module is specified in config.xml. 19 | 20 | NOTE TO ADD-IN AUTHORS: Please edit this file to be relevant documentation 21 | for your project or delete it before distributing. 22 | -------------------------------------------------------------------------------- /addin-wizard/packaging/makeaddin.py: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | import os 3 | import re 4 | import zipfile 5 | 6 | current_path = os.path.dirname(os.path.abspath(__file__)) 7 | 8 | out_zip_name = os.path.join(current_path, 9 | os.path.basename(current_path) + ".esriaddin") 10 | 11 | BACKUP_FILE_PATTERN = re.compile(".*_addin_[0-9]+[.]py$", re.IGNORECASE) 12 | 13 | def looks_like_a_backup(filename): 14 | return bool(BACKUP_FILE_PATTERN.match(filename)) 15 | 16 | with zipfile.ZipFile(out_zip_name, 'w', zipfile.ZIP_DEFLATED) as zip_file: 17 | for filename in ('config.xml', 'README.txt', 'makeaddin.py'): 18 | full_filename = os.path.join(current_path, filename) 19 | if os.path.exists(full_filename): 20 | zip_file.write(full_filename, filename) 21 | dirs_to_add = ['Images', 'Install'] 22 | for directory in dirs_to_add: 23 | for (path, dirs, files) in os.walk(os.path.join(current_path, 24 | directory)): 25 | archive_path = os.path.relpath(path, current_path) 26 | found_file = False 27 | for file in (f for f in files if not looks_like_a_backup(f)): 28 | archive_file = os.path.join(archive_path, file) 29 | print archive_file 30 | zip_file.write(os.path.join(path, file), archive_file) 31 | found_file = True 32 | if not found_file: 33 | zip_file.writestr(os.path.join(archive_path, 34 | 'placeholder.txt'), 35 | "(Empty directory)") 36 | -------------------------------------------------------------------------------- /addin-wizard/resources/resource_strings.json: -------------------------------------------------------------------------------- 1 | { 2 | 3 | "**** THIS STRING RESOURCE FILE IS EXPECTED TO BE ENCODED IN UTF-8 ***": "(Do not translate this string)", 4 | "It is arranged into ORIGINAL: TRANSLATION pairs.": "(Do not translate this string)", 5 | 6 | "Add-In Contents": "Add-In Contents", 7 | "ArcGIS Python Add-In Wizard": "ArcGIS Python Add-In Wizard", 8 | "Author:": "Author:", 9 | "Button": "Button", 10 | "Caption": "Caption", 11 | "Choose a directory to use as an Add-In project root:": "Choose a directory to use as an Add-In project root:", 12 | "Class Name": "Class Name", 13 | "Column Count": "Column Count", 14 | "Company:": "Company:", 15 | "Description": "Description", 16 | "Description:": "Description:", 17 | "EXTENSIONS": "EXTENSIONS", 18 | "Extension": "Extension", 19 | "Extensions": "Extensions", 20 | "Has Separator": "Has Separator", 21 | "Help Content": "Help Content", 22 | "Help Heading": "Help Heading", 23 | "Hint Text": "Hint Text", 24 | "ID (Variable Name)": "ID (Variable Name)", 25 | "Image for Control": "Image for Control", 26 | "Image for control:": "Image for control:", 27 | "Image:": "Image:", 28 | "Is Shortcut Menu": "Is Shortcut Menu", 29 | "Load Automatically": "Load Automatically", 30 | "MENUS": "MENUS", 31 | "Menu": "Menu", 32 | "Menu Style": "Menu Style", 33 | "Message": "Message", 34 | "Methods to Implement": "Methods to Implement", 35 | "Name": "Name", 36 | "Name*:": "Name*:", 37 | "New Extension": "New Extension", 38 | "New Menu": "New Menu", 39 | "Open Folder": "Open Folder", 40 | "Project Properties:": "Project Properties:", 41 | "Project Settings": "Project Settings", 42 | "Python Add-In Wizard": "Python Add-In Wizard", 43 | "Save": "Save", 44 | "Save before exiting?": "Save before exiting?", 45 | "Save your changes before exiting?": "Save your changes before exiting?", 46 | "Select Folder...": "Select Folder...", 47 | "Select Image...": "Select Image...", 48 | "Select Product:": "Select Product:", 49 | "Show Initially": "Show Initially", 50 | "TOOLBARS": "TOOLBARS", 51 | "Toolbar": "Toolbar", 52 | "Toolbars": "Toolbars", 53 | "Tooltip": "Tooltip", 54 | "Toplevel Menus": "Toplevel Menus", 55 | "Version*:": "Version*:", 56 | "Working Folder:": "Working Folder:" 57 | } 58 | -------------------------------------------------------------------------------- /addin-wizard/setup.py: -------------------------------------------------------------------------------- 1 | from distutils.core import setup 2 | import py2exe 3 | import glob 4 | 5 | setup(windows=[ 6 | {'script': 'addin_assistant.pyw', 7 | 'icon_resources': [(1, "images\\AddInDesktop.ico")] 8 | } 9 | ], 10 | options={ "py2exe": { "dll_excludes": ["MSVCP90.dll"] }}, 11 | data_files=[('images', glob.glob("images\\*.png") + 12 | glob.glob("images\\*.ico")), 13 | ('packaging', glob.glob("packaging\\*.*")), 14 | ('resources', glob.glob("resources\\*.*"))] 15 | ) 16 | --------------------------------------------------------------------------------