├── .gitattributes ├── .gitignore ├── .vs ├── ProjectSettings.json ├── VSWorkspaceState.json ├── slnx.sqlite └── utility-network-properties-extractor │ └── v16 │ └── .suo ├── CSV ├── 20210507_090906_ElectricUtilityNetwork_DomainNetworks.csv ├── 20210507_090909_ElectricUtilityNetwork_NetworkRules.csv ├── 20210507_090913_ElectricUtilityNetwork_NetworkCategories.csv └── 20210507_090920_ElectricUtilityNetwork_Fields.csv ├── README.md ├── Screenshots ├── Toolbar.PNG ├── Toolbar2024.PNG └── UN Addin toolbar.PNG ├── UtilityNetworkPropertiesExtractor ├── .vs │ └── UtilityNetworkPropertiesExtractor │ │ └── v16 │ │ └── .suo ├── AssetGroupsButton.cs ├── AttributeRulesButton.cs ├── Common.cs ├── Config.daml ├── ContingentValuesButton.cs ├── DarkImages │ ├── AddInDesktop16.png │ └── AddInDesktop32.png ├── DisplayFieldExpressionButton.cs ├── DisplayFilterButton.cs ├── DomainAssignmentsButton.cs ├── DomainNetworksButton.cs ├── DomainOrphansButton.cs ├── DomainValuesButton.cs ├── ExportSubnetworkResultFieldsButton.cs ├── ExtractAllButton.cs ├── ExtractLocationButton.cs ├── FieldSettingsInMapButton.cs ├── FieldSettingsInMapImportButton.cs ├── FieldsExtractButton.cs ├── GdbObjectNamesButton.cs ├── Helpers │ ├── DataSourcesInMapHelper.cs │ ├── GeoprocessingPrepHelper.cs │ └── LayerPopupInfoHelper.cs ├── Images │ ├── AddInDesktop16.png │ └── AddInDesktop32.png ├── JSON Mappings │ ├── ArcRestError.cs │ ├── FeatureServiceJSONMapping.cs │ ├── NetworkDiagramTemplateJSONMapping.cs │ └── TraceConfigurationJSONMapping.cs ├── LayerCountsButton.cs ├── LayerInfoButton.cs ├── LayerScalesButton.cs ├── MachineInfoButton.cs ├── Module1.cs ├── NetworkAttributesButton.cs ├── NetworkCategoriesButton.cs ├── NetworkDiagramsButton.cs ├── NetworkRulesButton.cs ├── NoNetworkRulesButton.cs ├── PopupFieldsButton.cs ├── PopupFieldsImportButton.cs ├── ProjectItemsButton.cs ├── Properties │ ├── AssemblyInfo.cs │ └── launchSettings.json ├── RelationshipClassButton.cs ├── SymbolScalesButton.cs ├── TerminalConfigurationButton.cs ├── TraceConfigurationButton.cs ├── UNFeatureServiceInfoButton.cs ├── UtilityNetworkPropertiesExtractor.csproj ├── UtilityNetworkPropertiesExtractor.csproj.bak ├── UtilityNetworkPropertiesExtractor.sln ├── VersionInfoButton.cs ├── obj │ └── Debug │ │ ├── .NETFramework,Version=v4.8.AssemblyAttributes.cs │ │ └── DesignTimeResolveAssemblyReferencesInput.cache └── packages.config ├── contributing.md └── license.txt /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | ## 4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore 5 | 6 | # User-specific files 7 | *.rsuser 8 | *.suo 9 | *.user 10 | *.userosscache 11 | *.sln.docstates 12 | 13 | # User-specific files (MonoDevelop/Xamarin Studio) 14 | *.userprefs 15 | 16 | # Build results 17 | [Dd]ebug/ 18 | [Dd]ebugPublic/ 19 | [Rr]elease/ 20 | [Rr]eleases/ 21 | x64/ 22 | x86/ 23 | [Aa][Rr][Mm]/ 24 | [Aa][Rr][Mm]64/ 25 | bld/ 26 | [Bb]in/ 27 | [Oo]bj/ 28 | [Ll]og/ 29 | 30 | # Visual Studio 2015/2017 cache/options directory 31 | .vs/ 32 | # Uncomment if you have tasks that create the project's static files in wwwroot 33 | #wwwroot/ 34 | 35 | # Visual Studio 2017 auto generated files 36 | Generated\ Files/ 37 | 38 | # MSTest test Results 39 | [Tt]est[Rr]esult*/ 40 | [Bb]uild[Ll]og.* 41 | 42 | # NUNIT 43 | *.VisualState.xml 44 | TestResult.xml 45 | 46 | # Build Results of an ATL Project 47 | [Dd]ebugPS/ 48 | [Rr]eleasePS/ 49 | dlldata.c 50 | 51 | # Benchmark Results 52 | BenchmarkDotNet.Artifacts/ 53 | 54 | # .NET Core 55 | project.lock.json 56 | project.fragment.lock.json 57 | artifacts/ 58 | 59 | # StyleCop 60 | StyleCopReport.xml 61 | 62 | # Files built by Visual Studio 63 | *_i.c 64 | *_p.c 65 | *_h.h 66 | *.ilk 67 | *.meta 68 | *.obj 69 | *.iobj 70 | *.pch 71 | *.pdb 72 | *.ipdb 73 | *.pgc 74 | *.pgd 75 | *.rsp 76 | *.sbr 77 | *.tlb 78 | *.tli 79 | *.tlh 80 | *.tmp 81 | *.tmp_proj 82 | *_wpftmp.csproj 83 | *.log 84 | *.vspscc 85 | *.vssscc 86 | .builds 87 | *.pidb 88 | *.svclog 89 | *.scc 90 | 91 | # Chutzpah Test files 92 | _Chutzpah* 93 | 94 | # Visual C++ cache files 95 | ipch/ 96 | *.aps 97 | *.ncb 98 | *.opendb 99 | *.opensdf 100 | *.sdf 101 | *.cachefile 102 | *.VC.db 103 | *.VC.VC.opendb 104 | 105 | # Visual Studio profiler 106 | *.psess 107 | *.vsp 108 | *.vspx 109 | *.sap 110 | 111 | # Visual Studio Trace Files 112 | *.e2e 113 | 114 | # TFS 2012 Local Workspace 115 | $tf/ 116 | 117 | # Guidance Automation Toolkit 118 | *.gpState 119 | 120 | # ReSharper is a .NET coding add-in 121 | _ReSharper*/ 122 | *.[Rr]e[Ss]harper 123 | *.DotSettings.user 124 | 125 | # JustCode is a .NET coding add-in 126 | .JustCode 127 | 128 | # TeamCity is a build add-in 129 | _TeamCity* 130 | 131 | # DotCover is a Code Coverage Tool 132 | *.dotCover 133 | 134 | # AxoCover is a Code Coverage Tool 135 | .axoCover/* 136 | !.axoCover/settings.json 137 | 138 | # Visual Studio code coverage results 139 | *.coverage 140 | *.coveragexml 141 | 142 | # NCrunch 143 | _NCrunch_* 144 | .*crunch*.local.xml 145 | nCrunchTemp_* 146 | 147 | # MightyMoose 148 | *.mm.* 149 | AutoTest.Net/ 150 | 151 | # Web workbench (sass) 152 | .sass-cache/ 153 | 154 | # Installshield output folder 155 | [Ee]xpress/ 156 | 157 | # DocProject is a documentation generator add-in 158 | DocProject/buildhelp/ 159 | DocProject/Help/*.HxT 160 | DocProject/Help/*.HxC 161 | DocProject/Help/*.hhc 162 | DocProject/Help/*.hhk 163 | DocProject/Help/*.hhp 164 | DocProject/Help/Html2 165 | DocProject/Help/html 166 | 167 | # Click-Once directory 168 | publish/ 169 | 170 | # Publish Web Output 171 | *.[Pp]ublish.xml 172 | *.azurePubxml 173 | # Note: Comment the next line if you want to checkin your web deploy settings, 174 | # but database connection strings (with potential passwords) will be unencrypted 175 | *.pubxml 176 | *.publishproj 177 | 178 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 179 | # checkin your Azure Web App publish settings, but sensitive information contained 180 | # in these scripts will be unencrypted 181 | PublishScripts/ 182 | 183 | # NuGet Packages 184 | *.nupkg 185 | # The packages folder can be ignored because of Package Restore 186 | **/[Pp]ackages/* 187 | # except build/, which is used as an MSBuild target. 188 | !**/[Pp]ackages/build/ 189 | # Uncomment if necessary however generally it will be regenerated when needed 190 | #!**/[Pp]ackages/repositories.config 191 | # NuGet v3's project.json files produces more ignorable files 192 | *.nuget.props 193 | *.nuget.targets 194 | 195 | # Microsoft Azure Build Output 196 | csx/ 197 | *.build.csdef 198 | 199 | # Microsoft Azure Emulator 200 | ecf/ 201 | rcf/ 202 | 203 | # Windows Store app package directories and files 204 | AppPackages/ 205 | BundleArtifacts/ 206 | Package.StoreAssociation.xml 207 | _pkginfo.txt 208 | *.appx 209 | 210 | # Visual Studio cache files 211 | # files ending in .cache can be ignored 212 | *.[Cc]ache 213 | # but keep track of directories ending in .cache 214 | !?*.[Cc]ache/ 215 | 216 | # Others 217 | ClientBin/ 218 | ~$* 219 | *~ 220 | *.dbmdl 221 | *.dbproj.schemaview 222 | *.jfm 223 | *.pfx 224 | *.publishsettings 225 | orleans.codegen.cs 226 | 227 | # Including strong name files can present a security risk 228 | # (https://github.com/github/gitignore/pull/2483#issue-259490424) 229 | #*.snk 230 | 231 | # Since there are multiple workflows, uncomment next line to ignore bower_components 232 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 233 | #bower_components/ 234 | 235 | # RIA/Silverlight projects 236 | Generated_Code/ 237 | 238 | # Backup & report files from converting an old project file 239 | # to a newer Visual Studio version. Backup files are not needed, 240 | # because we have git ;-) 241 | _UpgradeReport_Files/ 242 | Backup*/ 243 | UpgradeLog*.XML 244 | UpgradeLog*.htm 245 | ServiceFabricBackup/ 246 | *.rptproj.bak 247 | 248 | # SQL Server files 249 | *.mdf 250 | *.ldf 251 | *.ndf 252 | 253 | # Business Intelligence projects 254 | *.rdl.data 255 | *.bim.layout 256 | *.bim_*.settings 257 | *.rptproj.rsuser 258 | *- Backup*.rdl 259 | 260 | # Microsoft Fakes 261 | FakesAssemblies/ 262 | 263 | # GhostDoc plugin setting file 264 | *.GhostDoc.xml 265 | 266 | # Node.js Tools for Visual Studio 267 | .ntvs_analysis.dat 268 | node_modules/ 269 | 270 | # Visual Studio 6 build log 271 | *.plg 272 | 273 | # Visual Studio 6 workspace options file 274 | *.opt 275 | 276 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 277 | *.vbw 278 | 279 | # Visual Studio LightSwitch build output 280 | **/*.HTMLClient/GeneratedArtifacts 281 | **/*.DesktopClient/GeneratedArtifacts 282 | **/*.DesktopClient/ModelManifest.xml 283 | **/*.Server/GeneratedArtifacts 284 | **/*.Server/ModelManifest.xml 285 | _Pvt_Extensions 286 | 287 | # Paket dependency manager 288 | .paket/paket.exe 289 | paket-files/ 290 | 291 | # FAKE - F# Make 292 | .fake/ 293 | 294 | # JetBrains Rider 295 | .idea/ 296 | *.sln.iml 297 | 298 | # CodeRush personal settings 299 | .cr/personal 300 | 301 | # Python Tools for Visual Studio (PTVS) 302 | __pycache__/ 303 | *.pyc 304 | 305 | # Cake - Uncomment if you are using it 306 | # tools/** 307 | # !tools/packages.config 308 | 309 | # Tabs Studio 310 | *.tss 311 | 312 | # Telerik's JustMock configuration file 313 | *.jmconfig 314 | 315 | # BizTalk build output 316 | *.btp.cs 317 | *.btm.cs 318 | *.odx.cs 319 | *.xsd.cs 320 | 321 | # OpenCover UI analysis results 322 | OpenCover/ 323 | 324 | # Azure Stream Analytics local run output 325 | ASALocalRun/ 326 | 327 | # MSBuild Binary and Structured Log 328 | *.binlog 329 | 330 | # NVidia Nsight GPU debugger configuration file 331 | *.nvuser 332 | 333 | # MFractors (Xamarin productivity tool) working folder 334 | .mfractor/ 335 | 336 | # Local History for Visual Studio 337 | .localhistory/ 338 | 339 | # BeatPulse healthcheck temp database 340 | healthchecksdb -------------------------------------------------------------------------------- /.vs/ProjectSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "CurrentProjectSetting": null 3 | } -------------------------------------------------------------------------------- /.vs/VSWorkspaceState.json: -------------------------------------------------------------------------------- 1 | { 2 | "ExpandedNodes": [ 3 | "" 4 | ], 5 | "SelectedNode": "\\UtilityNetworkPropertiesExtractor.sln", 6 | "PreviewInSolutionExplorer": false 7 | } -------------------------------------------------------------------------------- /.vs/slnx.sqlite: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Esri/utility-network-properties-extractor/5f5b769bc5e4dba64e782683b3aea8da27f6c04b/.vs/slnx.sqlite -------------------------------------------------------------------------------- /.vs/utility-network-properties-extractor/v16/.suo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Esri/utility-network-properties-extractor/5f5b769bc5e4dba64e782683b3aea8da27f6c04b/.vs/utility-network-properties-extractor/v16/.suo -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # utility-network-properties-extractor 2 | 3 | For use with ArcGIS Pro 3.3 4 | 5 | This repository contains the source code for the 'Utility Network Property Extractor' ArcGIS Pro Add-in. Single click buttons will create CSV files for the ArcGIS Utility Network, Geodatabase and Map properties. There are also 6 efficiency tools to help set up your map and get your machine info. 6 | 7 | The Add-in works against layers from feature services, database connections and file geodatabases. Buttons are enabled/disabled based on the layers in the map. 8 | 9 | The Add-in is domain network agnostic. It doesn’t matter if the industry is Electric, Gas, Communications, District Heating & Cooling, Water, Sewer, or others. 10 | 11 | 12 | ``` 13 | Language: C# 14 | Subject: Utility Network 15 | Author: Mike Hirschheimer 16 | Organization: Esri, http://www.esri.com 17 | Date: 2/23/2023 18 | ArcGIS Pro: 3.3 19 | Visual Studio: 2022 20 | .NET Target Framework: .NET 8 21 | ``` 22 | 23 | 24 | ## ArcGIS Pro Add-In 25 | ![Screenshot](Screenshots/Toolbar2024.PNG) 26 | 27 | ### 1. Single click buttons that extract Utility Network, Geodatabase and Map properties to CSV files 28 | * **Utility Network**: UN FeatureService, Asset Groups, Domain Networks, Network Rules, Network Attributes, Network Categories, Network Diagram Info, Terminal Configuration, Trace Configuration, No Network Rules 29 | * **Geodatabase**: Domain Values, Domain Assignments, Orphan Domains, Fields, Relationship Classes, Versioning Info, Attribute Rules, Contingent Values, GDB Object Names 30 | * **Map**: Layer Info, Layer Scales, Layer Counts, Symbol Scales, Map Field Settings, Pop-up Fields 31 | 32 | * **CSV file(s)** are written to folder c:\temp\ProSDK_CSV\Pro Project Name\ 33 | 34 | ### 2. Efficiency tools to help with map configuration. 35 | 36 | #### Set Display Field Expressions 37 | - For Utility Network layers, sets the primary display field to the following: 38 | - Domain/Structure layers: Asset Type and Objectid 39 | - Subnetline layer: Subnetwork Name 40 | - Dirty Areas layer: Objectid 41 | 42 | #### Set Containment Display Filters 43 | * Creates a new Display Filter used by containment for Utility Network layers with an assocationstatus field 44 | * Name: DisplayContent 45 | * Sql: associationstatus not in (4,5,6,12,13,14,36,37,38,44,45,46) 46 | 47 | #### Import Map Field Settings 48 | * Using a CSV from a “Map Field Settings” extraction, field settings can be modified and applied to the active map. 49 | * Map Field Settings that can be changed: Visibility, Read-Only, Highlighted and Field Alias 50 | 51 | _Directions_ 52 | 1. Open any map 53 | 2. Generate a CSV by clicking the Map Field Settings button 54 | 3. Open the CSV in Excel and edit the necessary Field Order, Visibility, Read-Only, Highlighted and Field Alias settings 55 | 4. Once done, make sure to save the file in CSV format and then close the file 56 | 5. In Pro, click on the 'Import Map Field Settings' button 57 | 6. Choose the CSV file to import 58 | 7. Once prompted that the import is complete, review the changes in either the 'Fields' pane or selecting features and viewing in the 'Attributes' pane 59 | 8. You MUST save the Pro project for settings to persist 60 | 61 | #### Import Popup Field Settings 62 | * Using a CSV from a “Pop-up Fields” extraction, the Pop-up field visibility and order can be modified and applied to the active map 63 | 64 | _Directions_ 65 | 1. Open any map 66 | 2. Generate a CSV by clicking the Pop-up Fields button 67 | 3. Open the CSV in Excel and edit the necessary Pop-up Order and/or Visibility settings 68 | 4. Once done, make sure to save the file in CSV format and then close the file 69 | 5. In Pro, click on the 'Import Pop-up Field Settings' button 70 | 6. Choose the CSV file to import 71 | 7. Once prompted that the import is complete, review the changes in either the 'Configure Pop-ups' pane or identify a feature to open the Pop-up 72 | 8. You MUST save the Pro project for settings to persist 73 | 74 | ## Third party assemblies 75 | 1. Newtonsoft.JSON v13.0.3 76 | 2. Microsoft.Windows.Compatibility v8.0.7 77 | 78 | ## Compilation Directions 79 | 1. Download the source code 80 | 2. In Visual studio .NET compile the solution 81 | 3. **The source code was written against ArcGIS Pro SDK 3.1 and it won't compile cleanly against a 2.x version. Please switch to the 2.9 branch to get the latest code for that release. 82 | 4. Start up ArcGIS Pro 83 | 5. Open a project and confirm that the "Utility Network Add-in" toolbar is present 84 | 85 | ## ArcGIS Pro SDK Resources 86 | * [ArcGIS Pro SDK for Microsoft .NET](https://pro.arcgis.com/en/pro-app/latest/sdk/) 87 | 88 | * [ProConcepts Migrating to ArcGIS Pro](https://github.com/esri/arcgis-pro-sdk/wiki/ProConcepts-Migrating-to-ArcGIS-Pro) 89 | 90 | * [ProConcepts Utility Network](https://github.com/esri/arcgis-pro-sdk/wiki/ProConcepts-Utility-Network) 91 | 92 | * [Pro SDK Community Samples](https://github.com/esri/arcgis-pro-sdk-community-samples) 93 | 94 | ## Issues 95 | Find a bug or want to request a new feature? Please let us know by submitting an issue. 96 | 97 | ## Contributing 98 | Esri welcomes contributions from anyone and everyone. Please see our [guidelines for contributing](https://github.com/esri/contributing). 99 | 100 | ## Licensing 101 | Copyright 2021 Esri 102 | 103 | Licensed under the Apache License, Version 2.0 (the "License"); 104 | you may not use this file except in compliance with the License. 105 | You may obtain a copy of the License at 106 | 107 | http://www.apache.org/licenses/LICENSE-2.0 108 | 109 | Unless required by applicable law or agreed to in writing, software 110 | distributed under the License is distributed on an "AS IS" BASIS, 111 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 112 | See the License for the specific language governing permissions and 113 | limitations under the License. 114 | 115 | A copy of the license is available in the repository's [license.txt]( https://raw.github.com/Esri/quickstart-map-js/master/license.txt) file. 116 | -------------------------------------------------------------------------------- /Screenshots/Toolbar.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Esri/utility-network-properties-extractor/5f5b769bc5e4dba64e782683b3aea8da27f6c04b/Screenshots/Toolbar.PNG -------------------------------------------------------------------------------- /Screenshots/Toolbar2024.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Esri/utility-network-properties-extractor/5f5b769bc5e4dba64e782683b3aea8da27f6c04b/Screenshots/Toolbar2024.PNG -------------------------------------------------------------------------------- /Screenshots/UN Addin toolbar.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Esri/utility-network-properties-extractor/5f5b769bc5e4dba64e782683b3aea8da27f6c04b/Screenshots/UN Addin toolbar.PNG -------------------------------------------------------------------------------- /UtilityNetworkPropertiesExtractor/.vs/UtilityNetworkPropertiesExtractor/v16/.suo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Esri/utility-network-properties-extractor/5f5b769bc5e4dba64e782683b3aea8da27f6c04b/UtilityNetworkPropertiesExtractor/.vs/UtilityNetworkPropertiesExtractor/v16/.suo -------------------------------------------------------------------------------- /UtilityNetworkPropertiesExtractor/AttributeRulesButton.cs: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021 Esri 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | http://www.apache.org/licenses/LICENSE-2.0 7 | Unless required by applicable law or agreed to in writing, software 8 | distributed under the License is distributed on an "AS IS" BASIS, 9 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10 | See the License for the specific language governing permissions and 11 | limitations under the License. 12 | */ 13 | using ArcGIS.Desktop.Core.Geoprocessing; 14 | using ArcGIS.Desktop.Framework.Contracts; 15 | using ArcGIS.Desktop.Framework.Threading.Tasks; 16 | using System; 17 | using System.Collections.Generic; 18 | using System.Threading.Tasks; 19 | using MessageBox = System.Windows.MessageBox; 20 | 21 | namespace UtilityNetworkPropertiesExtractor 22 | { 23 | internal class AttributeRulesButton : Button 24 | { 25 | protected async override void OnClick() 26 | { 27 | Common.CreateOutputDirectory(); 28 | ProgressDialog progDlg = new ProgressDialog("Extracting Attribute Rule CSV(s) to:\n" + Common.ExtractFilePath); ; 29 | 30 | try 31 | { 32 | progDlg.Show(); 33 | await ExtractAttributeRulesAsync(); 34 | } 35 | catch (Exception ex) 36 | { 37 | MessageBox.Show(ex.Message, "Extract Attribute Rules"); 38 | } 39 | finally 40 | { 41 | progDlg.Dispose(); 42 | } 43 | } 44 | 45 | public static async Task ExtractAttributeRulesAsync() 46 | { 47 | await QueuedTask.Run(async () => 48 | { 49 | //If Subtype Group layers are in the map, will have multiple layers pointing to same source featureclass 50 | //Populate Dictionary of distinct featureclasses and tables 51 | Dictionary tablesDict = GeoprocessingPrepHelper.BuildDictionaryOfDistinctObjectsInMap(); 52 | 53 | //Execute GP for each table in the dictionary 54 | foreach (KeyValuePair pair in tablesDict) 55 | { 56 | TableAndDataSource tableAndDataSource = pair.Value; 57 | 58 | //Get gdb path to specific object 59 | string pathToObject = GeoprocessingPrepHelper.BuildPathForObject(tableAndDataSource); 60 | 61 | //Strip off database name and owner (if exists) 62 | string objectName = Common.StripDatabaseOwnerAndSchema(pair.Key); 63 | 64 | //build output CSV file name 65 | string attrRuleOutputFile = Common.BuildCsvName($"AttributeRules_{objectName}", tableAndDataSource.DataSourceName); 66 | 67 | //arcpy.management.ExportAttributeRules("DHC Line", r"C:\temp\DHCLine_AR_rules.CSV") 68 | IReadOnlyList attrRuleArgs = Geoprocessing.MakeValueArray(pathToObject, attrRuleOutputFile); 69 | var result = await Geoprocessing.ExecuteToolAsync("management.ExportAttributeRules", attrRuleArgs); 70 | } 71 | 72 | //Now delete any files that were generated but didn't have any Attribute Rules assigned 73 | GeoprocessingPrepHelper.DeleteEmptyFiles("_AttributeRules"); 74 | }); 75 | } 76 | } 77 | } -------------------------------------------------------------------------------- /UtilityNetworkPropertiesExtractor/ContingentValuesButton.cs: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021 Esri 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | http://www.apache.org/licenses/LICENSE-2.0 7 | Unless required by applicable law or agreed to in writing, software 8 | distributed under the License is distributed on an "AS IS" BASIS, 9 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10 | See the License for the specific language governing permissions and 11 | limitations under the License. 12 | */ 13 | using ArcGIS.Desktop.Core.Geoprocessing; 14 | using ArcGIS.Desktop.Framework.Contracts; 15 | using ArcGIS.Desktop.Framework.Threading.Tasks; 16 | using System; 17 | using System.Collections.Generic; 18 | using System.Threading.Tasks; 19 | using MessageBox = System.Windows.MessageBox; 20 | 21 | namespace UtilityNetworkPropertiesExtractor 22 | { 23 | internal class ContingentValuesButton : Button 24 | { 25 | protected async override void OnClick() 26 | { 27 | Common.CreateOutputDirectory(); 28 | ProgressDialog progDlg = new ProgressDialog("Extracting Contingent Value CSV(s) to:\n" + Common.ExtractFilePath); 29 | 30 | try 31 | { 32 | progDlg.Show(); 33 | await ExtractContingentValuesAsync(); 34 | } 35 | catch (Exception ex) 36 | { 37 | MessageBox.Show(ex.Message, "Extract Contingent Values"); 38 | } 39 | finally 40 | { 41 | progDlg.Dispose(); 42 | } 43 | } 44 | 45 | public static async Task ExtractContingentValuesAsync() 46 | { 47 | await QueuedTask.Run(async () => 48 | { 49 | //If Subtype Group layers are in the map, will have multiple layers pointing to same source featureclass 50 | //Populate Dictionary of distinct featureclasses and tables 51 | Dictionary tablesDict = GeoprocessingPrepHelper.BuildDictionaryOfDistinctObjectsInMap(); 52 | 53 | //Execute GP for each table in the dictionary 54 | foreach (KeyValuePair pair in tablesDict) 55 | { 56 | TableAndDataSource tableAndDataSource = pair.Value; 57 | 58 | //Get gdb path to specific object 59 | string pathToObject = GeoprocessingPrepHelper.BuildPathForObject(tableAndDataSource); 60 | 61 | //Strip off database name and owner (if exists) 62 | string objectName = Common.StripDatabaseOwnerAndSchema(pair.Key); 63 | 64 | //build output CSV file name 65 | string cvGroupOutputFile = Common.BuildCsvName($"ContingentValuesGroups_{objectName}", tableAndDataSource.DataSourceName); 66 | string cvOutputFile = Common.BuildCsvName($"ContingentValues_{objectName}", tableAndDataSource.DataSourceName); 67 | 68 | ////arcpy.management.ExportContingentValues("DHC Line", r"C:\temp\ProSdk_CSV\DHC_Line_CV_groups.CSV", r"C:\temp\ProSdk_CSV\DHC_Line_CV.CSV") 69 | IReadOnlyList cvArgs = Geoprocessing.MakeValueArray(pathToObject, cvGroupOutputFile, cvOutputFile); 70 | var result = await Geoprocessing.ExecuteToolAsync("management.ExportContingentValues", cvArgs); 71 | } 72 | 73 | //Now delete any files that were generated but didn't have any Contingent Values assigned 74 | GeoprocessingPrepHelper.DeleteEmptyFiles("_ContingentValues"); 75 | }); 76 | } 77 | } 78 | } -------------------------------------------------------------------------------- /UtilityNetworkPropertiesExtractor/DarkImages/AddInDesktop16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Esri/utility-network-properties-extractor/5f5b769bc5e4dba64e782683b3aea8da27f6c04b/UtilityNetworkPropertiesExtractor/DarkImages/AddInDesktop16.png -------------------------------------------------------------------------------- /UtilityNetworkPropertiesExtractor/DarkImages/AddInDesktop32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Esri/utility-network-properties-extractor/5f5b769bc5e4dba64e782683b3aea8da27f6c04b/UtilityNetworkPropertiesExtractor/DarkImages/AddInDesktop32.png -------------------------------------------------------------------------------- /UtilityNetworkPropertiesExtractor/DisplayFieldExpressionButton.cs: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021 Esri 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | http://www.apache.org/licenses/LICENSE-2.0 7 | Unless required by applicable law or agreed to in writing, software 8 | distributed under the License is distributed on an "AS IS" BASIS, 9 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10 | See the License for the specific language governing permissions and 11 | limitations under the License. 12 | */ 13 | using ArcGIS.Core.CIM; 14 | using ArcGIS.Core.Data.UtilityNetwork; 15 | using ArcGIS.Desktop.Framework.Threading.Tasks; 16 | using ArcGIS.Desktop.Mapping; 17 | using System; 18 | using System.Collections.Generic; 19 | using System.Linq; 20 | using System.Threading.Tasks; 21 | using System.Windows.Forms; 22 | using Button = ArcGIS.Desktop.Framework.Contracts.Button; 23 | using MessageBox = System.Windows.Forms.MessageBox; 24 | 25 | namespace UtilityNetworkPropertiesExtractor 26 | { 27 | internal class DisplayFieldExpressionButton : Button 28 | { 29 | protected override void OnClick() 30 | { 31 | try 32 | { 33 | SetDisplayFieldExpressionAsync(); 34 | } 35 | catch (Exception ex) 36 | { 37 | MessageBox.Show(ex.Message, "Set Display Field Expression"); 38 | } 39 | } 40 | 41 | private Task SetDisplayFieldExpressionAsync() 42 | { 43 | return QueuedTask.Run(() => 44 | { 45 | UtilityNetwork utilityNetwork = Common.GetUtilityNetwork(out FeatureLayer featureLayerInUn); 46 | if (utilityNetwork == null) 47 | { 48 | MessageBox.Show("Utility Network not found in the active map", "Set Display Field Expression", MessageBoxButtons.OK, MessageBoxIcon.Error); 49 | return; 50 | } 51 | 52 | //Confirm with user before proceeding 53 | DialogResult dialogResult = MessageBox.Show("Modify display field expression to be Utility Network meaningful?", "Confirmation", MessageBoxButtons.YesNo, MessageBoxIcon.Question); 54 | if (dialogResult == DialogResult.No) 55 | return; 56 | 57 | //Pause drawing 58 | MapView.Active.DrawingPaused = true; 59 | 60 | //Get list of all featurelayers in the map 61 | List featureLayerList = MapView.Active.Map.GetLayersAsFlattenedList().OfType().ToList(); 62 | 63 | //Standalone Tables in the map 64 | IReadOnlyList standaloneTableList = MapView.Active.Map.StandaloneTables; 65 | 66 | int total = featureLayerList.Count + standaloneTableList.Count; 67 | 68 | using (ProgressDialog progress = new ProgressDialog("Processing", "Canceled", (uint)total, false)) 69 | { 70 | string progressMessage = string.Empty; 71 | CancelableProgressorSource cps = new CancelableProgressorSource(progress) 72 | { 73 | Max = (uint)featureLayerList.Count + (uint)standaloneTableList.Count 74 | }; 75 | 76 | QueuedTask.Run(() => 77 | { 78 | foreach (FeatureLayer featureLayer in featureLayerList) 79 | { 80 | //if user clicks the cancel button, stop processing. 81 | if (cps.Progressor.CancellationToken.IsCancellationRequested) 82 | return; 83 | 84 | progressMessage = "Processing layer, " + featureLayer.Name + " (" + featureLayer.GetFeatureClass().GetName() + ") --> " + cps.Progressor.Value + " of " + total; 85 | cps.Progressor.Value += 1; 86 | cps.Progressor.Status = (cps.Progressor.Value * 100 / cps.Progressor.Max) + @"% Completed"; 87 | cps.Progressor.Message = progressMessage; 88 | 89 | //Based on fields in featureclass, determine the display field expression. 90 | List fieldDescList = featureLayer.GetFieldDescriptions(); 91 | FieldDescription assetTypeRec = fieldDescList.Where(x => x.Name.ToUpper() == "ASSETTYPE").FirstOrDefault(); 92 | FieldDescription dirtyAreaRec = fieldDescList.Where(x => x.Name.ToUpper() == "DIRTYAREA").FirstOrDefault(); 93 | FieldDescription subnetLineRec = fieldDescList.Where(x => x.Name.ToUpper() == "LASTACKEXPORTSUBNETWORK").FirstOrDefault(); 94 | 95 | if (assetTypeRec != null || dirtyAreaRec != null || subnetLineRec != null) 96 | { 97 | CIMBasicFeatureLayer cimBasicFeatureLayer = featureLayer.GetDefinition() as CIMBasicFeatureLayer; 98 | CIMFeatureTable cimFeatureTable = cimBasicFeatureLayer.FeatureTable; 99 | CIMExpressionInfo cimExpressionInfo = cimFeatureTable.DisplayExpressionInfo; 100 | 101 | if (cimExpressionInfo is null) 102 | cimExpressionInfo = new CIMExpressionInfo(); 103 | 104 | if (assetTypeRec != null) 105 | { 106 | if (featureLayer.IsSubtypeLayer) 107 | { 108 | cimExpressionInfo.Title = "Asset Type and Objectid"; 109 | cimExpressionInfo.Expression = "return DomainName($feature, 'ASSETTYPE', $feature.ASSETTYPE, $feature.ASSETGROUP) + ' ' + $feature.OBJECTID"; 110 | } 111 | else 112 | { 113 | cimExpressionInfo.Title = "Asset Group, Asset Type and Objectid"; 114 | cimExpressionInfo.Expression = "return DomainName($feature, 'ASSETGROUP', $feature.ASSETGROUP, $feature.ASSETGROUP) + ', ' + DomainName($feature, 'ASSETTYPE', $feature.ASSETTYPE, $feature.ASSETGROUP) + ' ' + $feature.OBJECTID"; 115 | } 116 | } 117 | else if (subnetLineRec != null) 118 | { 119 | cimExpressionInfo.Title = "Subnetworkname"; 120 | cimExpressionInfo.Expression = "$feature.SUBNETWORKNAME"; 121 | } 122 | else if (dirtyAreaRec != null) 123 | { 124 | cimExpressionInfo.Title = "Objectid"; 125 | cimExpressionInfo.Expression = "$feature.OBJECTID"; 126 | } 127 | 128 | cimFeatureTable.DisplayExpressionInfo = cimExpressionInfo; 129 | featureLayer.SetDefinition(cimBasicFeatureLayer); 130 | } 131 | } 132 | 133 | foreach (StandaloneTable standaloneTable in standaloneTableList) 134 | { 135 | //if user clicks the cancel button, stop processing. 136 | if (cps.Progressor.CancellationToken.IsCancellationRequested) 137 | return; 138 | 139 | progressMessage = "Processing table, " + standaloneTable.Name + " --> " + cps.Progressor.Value + " of " + total; 140 | cps.Progressor.Value += 1; 141 | cps.Progressor.Status = (cps.Progressor.Value * 100 / cps.Progressor.Max) + @"% Completed"; 142 | cps.Progressor.Message = progressMessage; 143 | 144 | List fieldDescList = standaloneTable.GetFieldDescriptions(); 145 | FieldDescription assetTypeRec = fieldDescList.Where(x => x.Name.ToUpper() == "ASSETTYPE").FirstOrDefault(); 146 | 147 | if (assetTypeRec != null) 148 | { 149 | CIMStandaloneTable cimStandaloneTable = standaloneTable.GetDefinition(); 150 | CIMExpressionInfo cimExpressionInfo = cimStandaloneTable.DisplayExpressionInfo; 151 | 152 | if (cimExpressionInfo is null) 153 | cimExpressionInfo = new CIMExpressionInfo(); 154 | 155 | cimExpressionInfo.Title = "Asset Group, Asset Type and Objectid"; 156 | cimExpressionInfo.Expression = "return DomainName($feature, 'ASSETGROUP', $feature.ASSETGROUP, $feature.ASSETGROUP) + ', ' + DomainName($feature, 'ASSETTYPE', $feature.ASSETTYPE, $feature.ASSETGROUP) + ' ' + $feature.OBJECTID"; ; 157 | 158 | cimStandaloneTable.DisplayExpressionInfo = cimExpressionInfo; 159 | standaloneTable.SetDefinition(cimStandaloneTable); 160 | } 161 | } 162 | }, cps.Progressor); 163 | } 164 | MapView.Active.DrawingPaused = false; 165 | }); 166 | } 167 | } 168 | } 169 | -------------------------------------------------------------------------------- /UtilityNetworkPropertiesExtractor/DisplayFilterButton.cs: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021 Esri 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | http://www.apache.org/licenses/LICENSE-2.0 7 | Unless required by applicable law or agreed to in writing, software 8 | distributed under the License is distributed on an "AS IS" BASIS, 9 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10 | See the License for the specific language governing permissions and 11 | limitations under the License. 12 | */ 13 | using ArcGIS.Core.CIM; 14 | using ArcGIS.Core.Data.UtilityNetwork; 15 | using ArcGIS.Desktop.Framework.Threading.Tasks; 16 | using ArcGIS.Desktop.Mapping; 17 | using System.Collections.Generic; 18 | using System.Linq; 19 | using System.Threading.Tasks; 20 | using System.Windows.Forms; 21 | using Button = ArcGIS.Desktop.Framework.Contracts.Button; 22 | using MessageBox = System.Windows.Forms.MessageBox; 23 | 24 | namespace UtilityNetworkPropertiesExtractor 25 | { 26 | internal class DisplayFilterButton : Button 27 | { 28 | private const string _ContainmentFilterName = "DisplayContent"; 29 | private const string _AssocationStatusFieldName = "ASSOCIATIONSTATUS"; 30 | 31 | protected override void OnClick() 32 | { 33 | SetDisplayFilterChoiceAsync(); 34 | } 35 | 36 | private Task SetDisplayFilterChoiceAsync() 37 | { 38 | return QueuedTask.Run(() => 39 | { 40 | UtilityNetwork utilityNetwork = Common.GetUtilityNetwork(out FeatureLayer featureLayerInUn); 41 | if (utilityNetwork == null) 42 | { 43 | MessageBox.Show("Utility Network not found in the active map", "Set Display Filters", MessageBoxButtons.OK, MessageBoxIcon.Error); 44 | return; 45 | } 46 | 47 | //Confirm with user before proceeding 48 | DialogResult dialogResult = MessageBox.Show("Create Containment Display Filters on Utility Network layers?", "Confirmation", MessageBoxButtons.YesNo, MessageBoxIcon.Question); 49 | if (dialogResult == DialogResult.No) 50 | return; 51 | 52 | //pause drawing 53 | MapView.Active.DrawingPaused = true; 54 | 55 | bool createFilter = true; 56 | 57 | //Get all layers in the map 58 | List layerList = MapView.Active.Map.GetLayersAsFlattenedList().OfType().ToList(); 59 | 60 | using (ProgressDialog progress = new ProgressDialog("Processing", "Canceled", (uint)layerList.Count, false)) 61 | { 62 | string progressMessage = string.Empty; 63 | CancelableProgressorSource cps = new CancelableProgressorSource(progress) 64 | { 65 | Max = (uint)layerList.Count 66 | }; 67 | 68 | QueuedTask.Run(() => 69 | { 70 | foreach (Layer layer in layerList) 71 | { 72 | //if user clicks the cancel button, stop processing. 73 | if (cps.Progressor.CancellationToken.IsCancellationRequested) 74 | return; 75 | 76 | progressMessage = "Processing layer, " + layer.Name + " --> " + cps.Progressor.Value + " of " + layerList.Count; 77 | cps.Progressor.Value += 1; 78 | cps.Progressor.Status = (cps.Progressor.Value * 100 / cps.Progressor.Max) + @"% Completed"; 79 | cps.Progressor.Message = progressMessage; 80 | 81 | if (layer is SubtypeGroupLayer subtypeGroupLayer) 82 | { 83 | CompositeLayer compositeLayer = layer as CompositeLayer; 84 | FeatureLayer featureLayer = compositeLayer.Layers.First() as FeatureLayer; 85 | FieldDescription associationStatusFieldDesc = FieldDescriptionOfAssociationstatus(featureLayer); 86 | if (associationStatusFieldDesc != null) 87 | { 88 | CIMSubtypeGroupLayer cimSubtypeGroupLayerDefinition = subtypeGroupLayer.GetDefinition() as CIMSubtypeGroupLayer; 89 | 90 | //Get list of existing Display Filter choices 91 | List existingDisplayFilterChoicesList = cimSubtypeGroupLayerDefinition.DisplayFilterChoices?.ToList(); 92 | if (existingDisplayFilterChoicesList == null) 93 | existingDisplayFilterChoicesList = new List(); 94 | else 95 | createFilter = CreateContainmentFilter(existingDisplayFilterChoicesList); 96 | 97 | if (createFilter) //Add new display filter for containment 98 | { 99 | cimSubtypeGroupLayerDefinition.EnableDisplayFilters = true; 100 | cimSubtypeGroupLayerDefinition.DisplayFiltersType = DisplayFilterType.ByChoice; 101 | 102 | existingDisplayFilterChoicesList.Add(BuildDisplayFilterForContainment()); 103 | cimSubtypeGroupLayerDefinition.DisplayFilterChoices = existingDisplayFilterChoicesList.ToArray(); 104 | layer.SetDefinition(cimSubtypeGroupLayerDefinition); 105 | } 106 | } 107 | } 108 | else if (layer is FeatureLayer featureLayer) 109 | { 110 | if (featureLayer.IsSubtypeLayer) 111 | continue; // if subtype layer, then the display filter is assigned to the SubtypeGroupLayer. 112 | else 113 | { 114 | FieldDescription associationStatusFieldDesc = FieldDescriptionOfAssociationstatus(featureLayer); 115 | if (associationStatusFieldDesc != null) 116 | { 117 | CIMFeatureLayer cimFeatureLayerDefinition = layer.GetDefinition() as CIMFeatureLayer; 118 | 119 | //Get list of existing Display Filter choices 120 | List existingDisplayFilterChoicesList = cimFeatureLayerDefinition.DisplayFilterChoices?.ToList(); 121 | if (existingDisplayFilterChoicesList == null) 122 | existingDisplayFilterChoicesList = new List(); 123 | else 124 | createFilter = CreateContainmentFilter(existingDisplayFilterChoicesList); 125 | 126 | if (createFilter) 127 | { 128 | //Add new display filter for containment 129 | cimFeatureLayerDefinition.EnableDisplayFilters = true; 130 | cimFeatureLayerDefinition.DisplayFiltersType = DisplayFilterType.ByChoice; 131 | existingDisplayFilterChoicesList.Add(BuildDisplayFilterForContainment()); 132 | 133 | cimFeatureLayerDefinition.DisplayFilterChoices = existingDisplayFilterChoicesList.ToArray(); 134 | layer.SetDefinition(cimFeatureLayerDefinition); 135 | } 136 | } 137 | } 138 | } 139 | createFilter = true; 140 | } 141 | }, cps.Progressor); 142 | } 143 | MapView.Active.DrawingPaused = false; 144 | }); 145 | } 146 | 147 | private static FieldDescription FieldDescriptionOfAssociationstatus(FeatureLayer featureLayer) 148 | { 149 | List fieldDescList = featureLayer.GetFieldDescriptions(); 150 | FieldDescription associationStatus = fieldDescList.Where(x => x.Name.ToUpper() == _AssocationStatusFieldName).FirstOrDefault(); 151 | return associationStatus; 152 | } 153 | 154 | private static bool CreateContainmentFilter(List existingDisplayFilterChoicesList) 155 | { 156 | //check if Containment filter already exists 157 | bool retVal = true; 158 | foreach (CIMDisplayFilter displayFilter in existingDisplayFilterChoicesList) 159 | { 160 | if (displayFilter.Name == _ContainmentFilterName) 161 | { 162 | retVal = false; 163 | continue; 164 | } 165 | } 166 | 167 | return retVal; 168 | } 169 | 170 | private static CIMDisplayFilter BuildDisplayFilterForContainment() 171 | { 172 | return new CIMDisplayFilter 173 | { 174 | Name = _ContainmentFilterName, 175 | WhereClause = string.Format("{0} not in (4,5,6,12,13,14,36,37,38,44,45,46)", _AssocationStatusFieldName) 176 | }; 177 | } 178 | } 179 | } 180 | -------------------------------------------------------------------------------- /UtilityNetworkPropertiesExtractor/DomainAssignmentsButton.cs: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021 Esri 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | http://www.apache.org/licenses/LICENSE-2.0 7 | Unless required by applicable law or agreed to in writing, software 8 | distributed under the License is distributed on an "AS IS" BASIS, 9 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10 | See the License for the specific language governing permissions and 11 | limitations under the License. 12 | */ 13 | using ArcGIS.Core.CIM; 14 | using ArcGIS.Core.Data; 15 | using ArcGIS.Desktop.Framework.Contracts; 16 | using ArcGIS.Desktop.Framework.Threading.Tasks; 17 | using System; 18 | using System.Collections.Generic; 19 | using System.IO; 20 | using System.Linq; 21 | using System.Reflection; 22 | using System.Threading.Tasks; 23 | using MessageBox = System.Windows.MessageBox; 24 | 25 | namespace UtilityNetworkPropertiesExtractor 26 | { 27 | internal class DomainAssignmentsButton : Button 28 | { 29 | protected async override void OnClick() 30 | { 31 | Common.CreateOutputDirectory(); 32 | ProgressDialog progDlg = new ProgressDialog("Extracting Domain Assignments to: \n" + Common.ExtractFilePath); 33 | 34 | try 35 | { 36 | progDlg.Show(); 37 | await ExtractDomainAssignmentsAsync(); 38 | } 39 | catch (Exception ex) 40 | { 41 | MessageBox.Show(ex.Message, "Extract Domain Assignments"); 42 | } 43 | finally 44 | { 45 | progDlg.Dispose(); 46 | } 47 | } 48 | 49 | public static Task ExtractDomainAssignmentsAsync() 50 | { 51 | return QueuedTask.Run(() => 52 | { 53 | List dataSourceInMapList = DataSourcesInMapHelper.GetDataSourcesInMap(); 54 | foreach (DataSourceInMap dataSourceInMap in dataSourceInMapList) 55 | { 56 | if (dataSourceInMap.WorkspaceFactory != WorkspaceFactory.Shapefile.ToString()) 57 | { 58 | using (Geodatabase geodatabase = dataSourceInMap.Geodatabase) 59 | { 60 | string outputFile = Common.BuildCsvName("DomainAssignments", dataSourceInMap.Name); 61 | using (StreamWriter sw = new StreamWriter(outputFile)) 62 | { 63 | //Header information 64 | Common.WriteHeaderInfoForGeodatabase(sw, dataSourceInMap, "Domain Assignments"); 65 | 66 | //Get all properties defined in the class. This will be used to generate the CSV file 67 | CSVLayout emptyRec = new CSVLayout(); 68 | PropertyInfo[] properties = Common.GetPropertiesOfClass(emptyRec); 69 | 70 | //Write column headers based on properties in the class 71 | string columnHeader = Common.ExtractClassPropertyNamesToString(properties); 72 | sw.WriteLine(columnHeader); 73 | 74 | List csvLayoutList = new List(); 75 | 76 | IReadOnlyList featureClassDefinitions = geodatabase.GetDefinitions(); 77 | foreach (FeatureClassDefinition fcDefinition in featureClassDefinitions) 78 | { 79 | try 80 | { 81 | IReadOnlyList listOfFields = fcDefinition.GetFields(); 82 | IReadOnlyList subtypes = fcDefinition.GetSubtypes(); 83 | 84 | if (subtypes.Count != 0) 85 | { 86 | foreach (Subtype subtype in subtypes) 87 | BuildDomainAssignments(fcDefinition, subtype, listOfFields, ref csvLayoutList); 88 | } 89 | else 90 | BuildDomainAssignments(fcDefinition, null, listOfFields, ref csvLayoutList); 91 | } 92 | catch (Exception ex) 93 | { 94 | if (ex.HResult != -2146233088) // No database permissions to perform the operation. 95 | MessageBox.Show(ex.Message); 96 | } 97 | } 98 | 99 | IReadOnlyList tableDefinitions = geodatabase.GetDefinitions(); 100 | foreach (TableDefinition tableDefinition in tableDefinitions) 101 | { 102 | try 103 | { 104 | IReadOnlyList listOfFields = tableDefinition.GetFields(); 105 | IReadOnlyList subtypes = tableDefinition.GetSubtypes(); 106 | 107 | if (subtypes.Count != 0) 108 | { 109 | foreach (Subtype subtype in subtypes) 110 | BuildDomainAssignments(tableDefinition, subtype, listOfFields, ref csvLayoutList); 111 | } 112 | else 113 | BuildDomainAssignments(tableDefinition, null, listOfFields, ref csvLayoutList); 114 | } 115 | catch (Exception ex) 116 | { 117 | if (ex.HResult != -2146233088) // No database permissions to perform the operation. 118 | MessageBox.Show(ex.Message); 119 | } 120 | } 121 | 122 | //Write body of CSV 123 | foreach (CSVLayout row in csvLayoutList.OrderBy(x => x.Domain)) 124 | { 125 | string output = Common.ExtractClassValuesToString(row, properties); 126 | sw.WriteLine(output); 127 | } 128 | 129 | sw.Flush(); 130 | sw.Close(); 131 | } 132 | } 133 | } 134 | } 135 | }); 136 | } 137 | 138 | private static void BuildDomainAssignments(TableDefinition tableDefinition, Subtype subtype, IReadOnlyList listOfFields, ref List domainAssignmentsCSVList) 139 | { 140 | string defaultCode = string.Empty; 141 | string defaultValue = string.Empty; 142 | 143 | foreach (Field field in listOfFields) 144 | { 145 | Domain domain = field.GetDomain(subtype); 146 | if (domain != null) 147 | { 148 | if (domain is CodedValueDomain) 149 | { 150 | CodedValueDomain cvd = domain as CodedValueDomain; 151 | if (field.GetDefaultValue(subtype) != null) //check first if Subtype has default value 152 | { 153 | defaultCode = field.GetDefaultValue(subtype).ToString(); 154 | defaultValue = cvd.GetName(field.GetDefaultValue(subtype)); 155 | } 156 | else if (field.HasDefaultValue) 157 | { 158 | defaultCode = field.GetDefaultValue().ToString(); 159 | defaultValue = cvd.GetName(field.GetDefaultValue()); 160 | } 161 | } 162 | 163 | CSVLayout rec = new CSVLayout() 164 | { 165 | ClassName = tableDefinition.GetName(), 166 | FieldName = field.Name, 167 | FieldType = field.FieldType.ToString(), 168 | Domain = domain.GetName(), 169 | DefaultCode = defaultCode, 170 | DefaultValue = Common.EncloseStringInDoubleQuotes(defaultValue) 171 | }; 172 | 173 | if (subtype != null) 174 | { 175 | rec.SubtypeCode = subtype.GetCode().ToString(); 176 | rec.Subtype = subtype.GetName(); 177 | } 178 | domainAssignmentsCSVList.Add(rec); 179 | 180 | defaultCode = string.Empty; 181 | defaultValue = string.Empty; 182 | } 183 | } 184 | } 185 | 186 | private class CSVLayout 187 | { 188 | public string Domain { get; set; } 189 | public string ClassName { get; set; } 190 | public string SubtypeCode { get; set; } 191 | public string Subtype { get; set; } 192 | public string FieldName { get; set; } 193 | public string FieldType { get; set; } 194 | public string DefaultCode { get; set; } 195 | public string DefaultValue { get; set; } 196 | } 197 | } 198 | } 199 | -------------------------------------------------------------------------------- /UtilityNetworkPropertiesExtractor/DomainOrphansButton.cs: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021 Esri 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | http://www.apache.org/licenses/LICENSE-2.0 7 | Unless required by applicable law or agreed to in writing, software 8 | distributed under the License is distributed on an "AS IS" BASIS, 9 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10 | See the License for the specific language governing permissions and 11 | limitations under the License. 12 | */ 13 | using ArcGIS.Core.CIM; 14 | using ArcGIS.Core.Data; 15 | using ArcGIS.Desktop.Framework.Contracts; 16 | using ArcGIS.Desktop.Framework.Threading.Tasks; 17 | using System; 18 | using System.Collections.Generic; 19 | using System.IO; 20 | using System.Linq; 21 | using System.Threading.Tasks; 22 | using MessageBox = System.Windows.MessageBox; 23 | 24 | namespace UtilityNetworkPropertiesExtractor 25 | { 26 | internal class DomainOrphansButton : Button 27 | { 28 | protected async override void OnClick() 29 | { 30 | Common.CreateOutputDirectory(); 31 | ProgressDialog progDlg = new ProgressDialog("Extracting Orphan Domains to: \n" + Common.ExtractFilePath); 32 | 33 | try 34 | { 35 | progDlg.Show(); 36 | await ExtractOrphanDomainsAsync(); 37 | } 38 | catch (Exception ex) 39 | { 40 | MessageBox.Show(ex.Message, "Extract Domain Values"); 41 | } 42 | finally 43 | { 44 | progDlg.Dispose(); 45 | } 46 | } 47 | 48 | public static Task ExtractOrphanDomainsAsync() 49 | { 50 | return QueuedTask.Run(() => 51 | { 52 | List dataSourceInMapList = DataSourcesInMapHelper.GetDataSourcesInMap(); 53 | foreach (DataSourceInMap dataSourceInMap in dataSourceInMapList) 54 | { 55 | if (dataSourceInMap.WorkspaceFactory != WorkspaceFactory.Shapefile.ToString()) 56 | { 57 | using (Geodatabase geodatabase = dataSourceInMap.Geodatabase) 58 | { 59 | string outputFile = Common.BuildCsvName("OrphanDomains", dataSourceInMap.Name); 60 | using (StreamWriter sw = new StreamWriter(outputFile)) 61 | { 62 | //Header information 63 | Common.WriteHeaderInfoForGeodatabase(sw, dataSourceInMap, "Orphan Domains"); 64 | 65 | HashSet assignedDomainsList = new HashSet(); 66 | 67 | //Get Domains assigned to a featureclass 68 | IReadOnlyList featureClassDefinitions = geodatabase.GetDefinitions(); 69 | foreach (FeatureClassDefinition fcDefinition in featureClassDefinitions) 70 | { 71 | try 72 | { 73 | IReadOnlyList listOfFields = fcDefinition.GetFields(); 74 | IReadOnlyList subtypes = fcDefinition.GetSubtypes(); 75 | 76 | if (subtypes.Count != 0) 77 | { 78 | foreach (Subtype subtype in subtypes) 79 | PopulateAssignedDomainList(assignedDomainsList, listOfFields, subtype); 80 | } 81 | else 82 | PopulateAssignedDomainList(assignedDomainsList, listOfFields, null); 83 | } 84 | catch (Exception ex) 85 | { 86 | if (ex.HResult != -2146233088) // No database permissions to perform the operation. 87 | MessageBox.Show(ex.Message); 88 | } 89 | } 90 | 91 | //Get Domains assigned to a table 92 | IReadOnlyList tableDefinitions = geodatabase.GetDefinitions(); 93 | foreach (TableDefinition tableDefinition in tableDefinitions) 94 | { 95 | try 96 | { 97 | IReadOnlyList listOfFields = tableDefinition.GetFields(); 98 | IReadOnlyList subtypes = tableDefinition.GetSubtypes(); 99 | 100 | if (subtypes.Count != 0) 101 | { 102 | foreach (Subtype subtype in subtypes) 103 | PopulateAssignedDomainList(assignedDomainsList, listOfFields, subtype); 104 | } 105 | else 106 | PopulateAssignedDomainList(assignedDomainsList, listOfFields, null); 107 | } 108 | catch (Exception ex) 109 | { 110 | if (ex.HResult != -2146233088) // No database permissions to perform the operation. 111 | MessageBox.Show(ex.Message); 112 | } 113 | } 114 | 115 | //Now loop through each domain in the geodatabase and see if it's in the assigned list 116 | sw.WriteLine("Domain Name"); 117 | IEnumerable domainsList = geodatabase.GetDomains().OrderBy(x => x.GetName()); 118 | foreach (Domain domain in domainsList) 119 | { 120 | if (!assignedDomainsList.Contains(domain.GetName())) 121 | sw.WriteLine(domain.GetName()); 122 | } 123 | 124 | sw.Flush(); 125 | sw.Close(); 126 | assignedDomainsList.Clear(); 127 | } 128 | } 129 | } 130 | } 131 | }); 132 | } 133 | 134 | private static void PopulateAssignedDomainList(HashSet assignedDomainsList, IReadOnlyList listOfFields, Subtype subtype) 135 | { 136 | foreach (Field field in listOfFields) 137 | { 138 | Domain domain = field.GetDomain(subtype); 139 | if (domain != null) 140 | { 141 | if (!assignedDomainsList.Contains(domain.GetName())) 142 | assignedDomainsList.Add(domain.GetName()); 143 | } 144 | } 145 | } 146 | } 147 | } -------------------------------------------------------------------------------- /UtilityNetworkPropertiesExtractor/DomainValuesButton.cs: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021 Esri 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | http://www.apache.org/licenses/LICENSE-2.0 7 | Unless required by applicable law or agreed to in writing, software 8 | distributed under the License is distributed on an "AS IS" BASIS, 9 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10 | See the License for the specific language governing permissions and 11 | limitations under the License. 12 | */ 13 | using ArcGIS.Core.CIM; 14 | using ArcGIS.Core.Data; 15 | using ArcGIS.Desktop.Framework.Contracts; 16 | using ArcGIS.Desktop.Framework.Threading.Tasks; 17 | using System; 18 | using System.Collections.Generic; 19 | using System.IO; 20 | using System.Linq; 21 | using System.Reflection; 22 | using System.Threading.Tasks; 23 | using MessageBox = System.Windows.MessageBox; 24 | 25 | namespace UtilityNetworkPropertiesExtractor 26 | { 27 | internal class DomainValuesButton : Button 28 | { 29 | protected async override void OnClick() 30 | { 31 | Common.CreateOutputDirectory(); 32 | ProgressDialog progDlg = new ProgressDialog("Extracting Domain Values to: \n" + Common.ExtractFilePath); 33 | 34 | try 35 | { 36 | progDlg.Show(); 37 | await ExtractDomainValuesAsync(); 38 | } 39 | catch (Exception ex) 40 | { 41 | MessageBox.Show(ex.Message, "Extract Domain Values"); 42 | } 43 | finally 44 | { 45 | progDlg.Dispose(); 46 | } 47 | } 48 | 49 | public static Task ExtractDomainValuesAsync() 50 | { 51 | return QueuedTask.Run(() => 52 | { 53 | List dataSourceInMapList = DataSourcesInMapHelper.GetDataSourcesInMap(); 54 | foreach (DataSourceInMap dataSourceInMap in dataSourceInMapList) 55 | { 56 | if (dataSourceInMap.WorkspaceFactory != WorkspaceFactory.Shapefile.ToString()) 57 | { 58 | using (Geodatabase geodatabase = dataSourceInMap.Geodatabase) 59 | { 60 | int i = 0; 61 | 62 | string outputFile = Common.BuildCsvName("DomainValues", dataSourceInMap.Name); 63 | using (StreamWriter sw = new StreamWriter(outputFile)) 64 | { 65 | //Header information 66 | Common.WriteHeaderInfoForGeodatabase(sw, dataSourceInMap, "Domains"); 67 | sw.WriteLine("Number of Domains," + geodatabase.GetDomains().Count); 68 | sw.WriteLine(); 69 | 70 | //Get all properties defined in the class. This will be used to generate the CSV file 71 | CSVLayout emptyRec = new CSVLayout(); 72 | PropertyInfo[] properties = Common.GetPropertiesOfClass(emptyRec); 73 | 74 | //Write column headers based on properties in the class 75 | string columnHeader = Common.ExtractClassPropertyNamesToString(properties); 76 | sw.WriteLine(columnHeader); 77 | 78 | List csvLayoutList = new List(); 79 | 80 | IEnumerable domainsList = geodatabase.GetDomains().OrderBy(x => x.GetName()); 81 | foreach (Domain domain in domainsList) 82 | { 83 | i += 1; 84 | CSVLayout rec = new CSVLayout() 85 | { 86 | ID = i.ToString(), 87 | DomainName = domain.GetName(), 88 | FieldType = domain.GetFieldType().ToString(), 89 | Description = Common.EncloseStringInDoubleQuotes(domain.GetDescription()), 90 | SplitPolicy = domain.SplitPolicy.ToString(), 91 | MergePolicy = domain.MergePolicy.ToString() 92 | }; 93 | 94 | if (domain is RangeDomain rangeDomain) 95 | { 96 | //Excel was formatting range of "3 - 15" as a date. Added double dash so that it would appear in Excel as a string 97 | rec.Range = Common.EncloseStringInDoubleQuotes(rangeDomain.GetMinValue().ToString() + " -- " + rangeDomain.GetMaxValue().ToString()); 98 | } 99 | 100 | csvLayoutList.Add(rec); 101 | 102 | //Write domain values on individual lines 103 | if (domain is CodedValueDomain codedValueDomain) 104 | { 105 | SortedList codedValuePairs = codedValueDomain.GetCodedValuePairs(); 106 | foreach (var pair in codedValuePairs) 107 | { 108 | rec = new CSVLayout() 109 | { 110 | DomainName = domain.GetName(), 111 | Code = pair.Key.ToString(), 112 | // Value = Common.EncloseStringInDoubleQuotes(pair.Value) 113 | Value = Common.EncloseStringInDoubleQuotes(pair.Value.Replace("\"", "\"\"")) 114 | }; 115 | csvLayoutList.Add(rec); 116 | } 117 | } 118 | } 119 | 120 | //Write body of CSV 121 | foreach (CSVLayout row in csvLayoutList) 122 | { 123 | string output = Common.ExtractClassValuesToString(row, properties); 124 | sw.WriteLine(output); 125 | } 126 | 127 | sw.Flush(); 128 | sw.Close(); 129 | } 130 | } 131 | } 132 | } 133 | }); 134 | } 135 | 136 | private class CSVLayout 137 | { 138 | public string ID { get; set; } 139 | public string DomainName { get; set; } 140 | public string FieldType { get; set; } 141 | public string Code { get; set; } 142 | public string Value { get; set; } 143 | public string Range { get; set; } 144 | public string SplitPolicy { get; set; } 145 | public string MergePolicy { get; set; } 146 | public string Description { get; set; } 147 | } 148 | } 149 | } -------------------------------------------------------------------------------- /UtilityNetworkPropertiesExtractor/ExportSubnetworkResultFieldsButton.cs: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021 Esri 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | http://www.apache.org/licenses/LICENSE-2.0 7 | Unless required by applicable law or agreed to in writing, software 8 | distributed under the License is distributed on an "AS IS" BASIS, 9 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10 | See the License for the specific language governing permissions and 11 | limitations under the License. 12 | */ 13 | using ArcGIS.Core.CIM; 14 | using ArcGIS.Core.Data; 15 | using ArcGIS.Core.Data.UtilityNetwork; 16 | using ArcGIS.Desktop.Framework.Contracts; 17 | using ArcGIS.Desktop.Framework.Threading.Tasks; 18 | using System; 19 | using System.Collections.Generic; 20 | using System.IO; 21 | using System.Linq; 22 | using System.Threading.Tasks; 23 | using MessageBox = System.Windows.MessageBox; 24 | 25 | namespace UtilityNetworkPropertiesExtractor 26 | { 27 | // 11/10/22 28 | // https://pro.arcgis.com/en/pro-app/2.9/tool-reference/utility-networks/export-subnetwork.htm 29 | // Geoprocessing Tool, Export Subnetwork, has a parameter for "result_fields" which identifies all the fields to be written to a JSON file. 30 | // Using ArcGIS Pro's GUI to manually select thoses fields in the GP Tool is not efficient. 31 | // This Pro SDK button will extract all Attribute fields to a text file in the format that the GP tool is expecting it. 32 | // If you don't want all fields on every class, either manually remove specific fields or modify method, BuildResultsString() 33 | // Note: Export Subnetwork is not supported in client-server mode. So this button will raise an error when exectued against a map using database connections. 34 | internal class ExportSubnetworkResultFieldsButton : Button 35 | { 36 | protected async override void OnClick() 37 | { 38 | Common.CreateOutputDirectory(); 39 | ProgressDialog progDlg = new ProgressDialog("Extracting Asset Groups to: \n" + Common.ExtractFilePath); 40 | 41 | try 42 | { 43 | progDlg.Show(); 44 | await BuildResultFieldsAsync(); 45 | } 46 | catch (Exception ex) 47 | { 48 | MessageBox.Show(ex.Message, "Build Export Subnetwork Result Fields"); 49 | } 50 | finally 51 | { 52 | progDlg.Dispose(); 53 | } 54 | } 55 | 56 | public static Task BuildResultFieldsAsync() 57 | { 58 | return QueuedTask.Run(() => 59 | { 60 | List utilityNetworkDataSourceInMapList = DataSourcesInMapHelper.GetUtilityNetworkDataSourcesInMap(); 61 | if (utilityNetworkDataSourceInMapList.Count == 0) 62 | return; 63 | 64 | string resultFields = string.Empty; 65 | foreach (UtilityNetworkDataSourceInMap utilityNetworkDataSourceInMap in utilityNetworkDataSourceInMapList) 66 | { 67 | using (Geodatabase geodatabase = utilityNetworkDataSourceInMap.Geodatabase) 68 | { 69 | string outputFile = Common.BuildTextFileName("ExportSubnetworkResultFields", utilityNetworkDataSourceInMap.Name); 70 | using (StreamWriter sw = new StreamWriter(outputFile)) 71 | { 72 | IReadOnlyList fcDefinitionList = geodatabase.GetDefinitions(); 73 | IReadOnlyList tableDefinitionList = geodatabase.GetDefinitions(); 74 | 75 | //Get all Network Sources 76 | UtilityNetworkDefinition utilityNetworkDefinition = utilityNetworkDataSourceInMap.UtilityNetwork.GetDefinition(); 77 | IOrderedEnumerable networkSourceList = utilityNetworkDefinition.GetNetworkSources().OrderBy(x => x.ID); 78 | foreach (NetworkSource networkSource in networkSourceList) 79 | { 80 | // don't include these UN classes when builidng the ResultFields 81 | if (networkSource.UsageType == SourceUsageType.SubnetLine || networkSource.UsageType == SourceUsageType.Association || networkSource.UsageType == SourceUsageType.SystemJunction) 82 | continue; 83 | 84 | // Utility Network FeatureClasses's UsageType values are between 0 and 7 85 | if ((int)networkSource.UsageType <= 7) 86 | { 87 | //search for featureclass 88 | foreach (FeatureClassDefinition fcDefinition in fcDefinitionList) 89 | { 90 | string fcName = fcDefinition.GetName(); 91 | 92 | if (utilityNetworkDataSourceInMap.WorkspaceFactory == WorkspaceFactory.FeatureService.ToString()) 93 | fcName = ReformatClassNameFromService(fcName); 94 | 95 | if (fcName == networkSource.Name) 96 | { 97 | IReadOnlyList fieldsList = fcDefinition.GetFields(); 98 | BuildResultsString(fcName, fieldsList, ref resultFields); 99 | break; 100 | } 101 | } 102 | } 103 | else // Utility Network Tables 104 | { 105 | foreach (TableDefinition tableDefinition in tableDefinitionList) 106 | { 107 | string tableName = tableDefinition.GetName(); 108 | 109 | if (utilityNetworkDataSourceInMap.WorkspaceFactory == WorkspaceFactory.FeatureService.ToString()) 110 | tableName = ReformatClassNameFromService(tableName); 111 | 112 | if (tableName == networkSource.Name) 113 | { 114 | IReadOnlyList fieldsList = tableDefinition.GetFields(); 115 | BuildResultsString(tableName, fieldsList, ref resultFields); 116 | break; 117 | } 118 | } 119 | } 120 | } 121 | 122 | sw.WriteLine(Common.EncloseStringInDoubleQuotes(resultFields)); 123 | sw.Flush(); 124 | } 125 | } 126 | } 127 | }); 128 | } 129 | 130 | private static string ReformatClassNameFromService(string fcName) 131 | { 132 | //strip out the leading number from the table name "L0Electric_Device". 133 | //Also need to replace the underscore with a blank space 134 | int index = fcName.LastIndexOfAny("0123456789".ToCharArray()); 135 | return fcName.Substring(index + 1).Replace("_", " "); 136 | } 137 | 138 | private static string StripOffDbOwner(string fcName) 139 | { 140 | //When exporting from a Mobile GDB, need to strip off db owner ("main.ElectricDevice") from the class name 141 | //When data source is an database connection, need to strip off database name and owner ("prod.gis.ElectricDevice") from the class name. 142 | int index = fcName.LastIndexOf("."); 143 | if (index == -1) 144 | return fcName; 145 | else 146 | return fcName.Substring(index + 1); 147 | } 148 | 149 | private static void BuildResultsString(string fcName, IReadOnlyList fieldsList, ref string resultFields) 150 | { 151 | fcName = StripOffDbOwner(fcName); 152 | 153 | foreach (Field field in fieldsList) 154 | { 155 | if (field.FieldType == FieldType.Geometry || field.FieldType == FieldType.Blob || field.FieldType == FieldType.Raster || field.Name.Contains('(')) 156 | continue; 157 | else 158 | resultFields += string.Format("'{0}' {1};", fcName, field.Name); 159 | } 160 | } 161 | } 162 | } -------------------------------------------------------------------------------- /UtilityNetworkPropertiesExtractor/ExtractAllButton.cs: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021 Esri 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | http://www.apache.org/licenses/LICENSE-2.0 7 | Unless required by applicable law or agreed to in writing, software 8 | distributed under the License is distributed on an "AS IS" BASIS, 9 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10 | See the License for the specific language governing permissions and 11 | limitations under the License. 12 | */ 13 | using ArcGIS.Desktop.Framework.Contracts; 14 | using ArcGIS.Desktop.Framework.Threading.Tasks; 15 | using System; 16 | using MessageBox = System.Windows.MessageBox; 17 | 18 | namespace UtilityNetworkPropertiesExtractor 19 | { 20 | internal class ExtractAllButton : Button 21 | { 22 | protected async override void OnClick() 23 | { 24 | ProgressDialog progDlg = new ProgressDialog("Extracting to:\n" + Common.GetExtractFilePath()); 25 | try 26 | { 27 | progDlg.Show(); 28 | 29 | DateTime startTime = DateTime.Now; 30 | Common.CreateOutputDirectory(); 31 | 32 | //Start with reports that are written to the root output directory 33 | await LayerInfoButton.ExtractLayerInfoAsync(); 34 | await LayerScalesButton.ExtractLayerScalesAsync(); 35 | await SymbolScalesButton.ExtractSymbolScalesAsync(); 36 | await PopupFieldsButton.ExtractPopupFieldsAsync(); 37 | await FieldSettingsInMapButton.ExtractFieldSettingsInMapAsync(); 38 | 39 | //Utility Network specific reports 40 | await UNFeatureServiceInfoButton.ExtractUNFeatureServiceInfo(false); 41 | await AssetGroupsButton.ExtractAssetGroupsAsync(false); 42 | await NetworkAttributesButton.ExtractNetworkAttributesAsync(false); 43 | await NetworkCategoriesButton.ExtractNetworkCategoriesAsync(false); 44 | await NetworkRulesButton.ExtractNetworkRulesAsync(false); 45 | await NoNetworkRulesButton.ExtractNoNetworkRulesAsync(false); 46 | await DomainNetworksButton.ExtractDomainNetworksAsync(false); 47 | await TerminalConfigurationButton.ExtractTerminalConfigurationAsync(false); 48 | await TraceConfigurationButton.ExtractTraceConfigurationAsync(false); 49 | await NetworkDiagramsButton.ExtractNetworkDiagramsAsync(false); 50 | 51 | //Database specific reports 52 | await FieldsExtractButton.ExtractFieldsAsync(); 53 | await DomainValuesButton.ExtractDomainValuesAsync(); 54 | await DomainAssignmentsButton.ExtractDomainAssignmentsAsync(); 55 | await DomainOrphansButton.ExtractOrphanDomainsAsync(); 56 | await GdbObjectNamesButton.ExtractGdbObjectNamesAsync(); 57 | await RelationshipClassButton.ExtractRelationshipClassesAsync(); 58 | await AttributeRulesButton.ExtractAttributeRulesAsync(); 59 | await ContingentValuesButton.ExtractContingentValuesAsync(); 60 | 61 | //Longer duration reports (if dataset is large) 62 | await LayerCountsButton.ExtractLayerCountAsync(); 63 | await VersionInfoButton.ExtractVersionInfoAsync(); 64 | 65 | //Some report had to go last 66 | ProjectItemsButton.ExtractProjectItem(); 67 | 68 | DateTime endTime = DateTime.Now; 69 | string timeDifference = Common.DetermineTimeDifference(startTime, endTime); 70 | 71 | MessageBox.Show("Directory: " + Common.ExtractFilePath + Environment.NewLine + "Duration: " + timeDifference, "CSV files were generated", System.Windows.MessageBoxButton.OK); 72 | } 73 | catch (Exception ex) 74 | { 75 | MessageBox.Show(ex.Message, "Extract All"); 76 | } 77 | finally 78 | { 79 | progDlg.Dispose(); 80 | } 81 | } 82 | } 83 | } -------------------------------------------------------------------------------- /UtilityNetworkPropertiesExtractor/ExtractLocationButton.cs: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021 Esri 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | http://www.apache.org/licenses/LICENSE-2.0 7 | Unless required by applicable law or agreed to in writing, software 8 | distributed under the License is distributed on an "AS IS" BASIS, 9 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10 | See the License for the specific language governing permissions and 11 | limitations under the License. 12 | */ 13 | using ArcGIS.Desktop.Framework.Contracts; 14 | using System.Windows; 15 | 16 | namespace UtilityNetworkPropertiesExtractor 17 | { 18 | internal class ExtractLocationButton : Button 19 | { 20 | protected override void OnClick() 21 | { 22 | Common.CreateOutputDirectory(); 23 | string mesg = "Extract Loction for this map is: \n\n" + Common.ExtractFilePath; 24 | Clipboard.SetText(Common.ExtractFilePath); 25 | MessageBox.Show(mesg + "\n\nThe path to the folder has been copied to the clipboard", "Extract Location"); 26 | } 27 | } 28 | } -------------------------------------------------------------------------------- /UtilityNetworkPropertiesExtractor/FieldSettingsInMapButton.cs: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021 Esri 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | http://www.apache.org/licenses/LICENSE-2.0 7 | Unless required by applicable law or agreed to in writing, software 8 | distributed under the License is distributed on an "AS IS" BASIS, 9 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10 | See the License for the specific language governing permissions and 11 | limitations under the License. 12 | */ 13 | using ArcGIS.Core.Data; 14 | using ArcGIS.Desktop.Framework.Contracts; 15 | using ArcGIS.Desktop.Framework.Dialogs; 16 | using ArcGIS.Desktop.Framework.Threading.Tasks; 17 | using ArcGIS.Desktop.Mapping; 18 | using System; 19 | using System.Collections.Generic; 20 | using System.IO; 21 | using System.Linq; 22 | using System.Threading.Tasks; 23 | 24 | namespace UtilityNetworkPropertiesExtractor 25 | { 26 | internal class FieldSettingsInMapButton : Button 27 | { 28 | protected async override void OnClick() 29 | { 30 | Common.CreateOutputDirectory(); 31 | ProgressDialog progDlg = new ProgressDialog("Extracting Field Settings in Map to: \n" + Common.ExtractFilePath); 32 | 33 | try 34 | { 35 | progDlg.Show(); 36 | await ExtractFieldSettingsInMapAsync(); 37 | } 38 | catch (Exception ex) 39 | { 40 | MessageBox.Show(ex.Message, "Extract Field Settings in Map"); 41 | } 42 | finally 43 | { 44 | progDlg.Dispose(); 45 | } 46 | } 47 | 48 | public static Task ExtractFieldSettingsInMapAsync() 49 | { 50 | return QueuedTask.Run(() => 51 | { 52 | string outputFile = Common.BuildCsvNameContainingMapName("FieldSettingsInMap"); 53 | using (StreamWriter sw = new StreamWriter(outputFile)) 54 | { 55 | //Header information 56 | Common.WriteHeaderInfoForMap(sw, "Field Settings in Map"); 57 | 58 | IReadOnlyList basicFeatureLayerList = MapView.Active.Map.GetLayersAsFlattenedList().OfType().ToList(); 59 | IReadOnlyList standaloneTableList = MapView.Active.Map.GetStandaloneTablesAsFlattenedList(); 60 | 61 | sw.WriteLine("Layers," + basicFeatureLayerList.Count); 62 | sw.WriteLine("Standalone Tables," + standaloneTableList.Count); 63 | sw.WriteLine(""); 64 | sw.WriteLine("Note,Column headers with an * are the editable field settings"); 65 | sw.WriteLine(); 66 | sw.WriteLine(Common.FieldSettingsClassNameHeader + ",Layer Name,Subtype Value,Field Name,Field Order*,Visible*,Read-Only*,Highlight*,Field Alias*"); 67 | 68 | //Basic Feature Layers in the map 69 | string subtypeValue = string.Empty; 70 | foreach (BasicFeatureLayer basicFeatureLayer in basicFeatureLayerList) 71 | { 72 | using (Table table = basicFeatureLayer.GetTable()) 73 | { 74 | if (table == null) // broken datasource. Don't add to the csv 75 | continue; 76 | 77 | subtypeValue = string.Empty; 78 | if (basicFeatureLayer is FeatureLayer fLayer) 79 | { 80 | if (fLayer.IsSubtypeLayer) 81 | subtypeValue = fLayer.SubtypeValue.ToString(); 82 | } 83 | List fieldDescList = basicFeatureLayer.GetFieldDescriptions(); 84 | WriteFieldSettings(sw, basicFeatureLayer.Name, table.GetName(), subtypeValue, fieldDescList); 85 | } 86 | } 87 | 88 | //Standalone Tables in the map 89 | foreach (StandaloneTable standaloneTable in standaloneTableList) 90 | { 91 | if (standaloneTable is not SubtypeGroupTable) // exclude the SubtypeGroupTable from the report 92 | { 93 | using (Table table = standaloneTable.GetTable()) 94 | { 95 | if (table == null) // broken datasource. Don't add to the csv 96 | continue; 97 | 98 | if (standaloneTable.IsSubtypeTable) 99 | subtypeValue = standaloneTable.SubtypeValue.ToString(); 100 | 101 | List fieldDescList = standaloneTable.GetFieldDescriptions(); 102 | WriteFieldSettings(sw, standaloneTable.Name, table.GetName(), subtypeValue, fieldDescList); 103 | } 104 | } 105 | } 106 | 107 | sw.Flush(); 108 | sw.Close(); 109 | } 110 | }); 111 | } 112 | 113 | private static void WriteFieldSettings(StreamWriter sw, string tocName, string className, string subtype, List fieldDescList) 114 | { 115 | int fieldOrder = 0; 116 | foreach (FieldDescription fieldDesc in fieldDescList) 117 | { 118 | fieldOrder += 1; 119 | sw.WriteLine(className + "," + Common.EncloseStringInDoubleQuotes(tocName) + "," + subtype + "," + fieldDesc.Name + "," + fieldOrder + "," + fieldDesc.IsVisible + "," + fieldDesc.IsReadOnly + "," + fieldDesc.IsHighlighted + "," + Common.EncloseStringInDoubleQuotes(fieldDesc.Alias)); 120 | } 121 | } 122 | } 123 | } -------------------------------------------------------------------------------- /UtilityNetworkPropertiesExtractor/GdbObjectNamesButton.cs: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021 Esri 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | http://www.apache.org/licenses/LICENSE-2.0 7 | Unless required by applicable law or agreed to in writing, software 8 | distributed under the License is distributed on an "AS IS" BASIS, 9 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10 | See the License for the specific language governing permissions and 11 | limitations under the License. 12 | */ 13 | using ArcGIS.Core.CIM; 14 | using ArcGIS.Core.Data; 15 | using ArcGIS.Core.Data.UtilityNetwork; 16 | using ArcGIS.Desktop.Framework.Contracts; 17 | using ArcGIS.Desktop.Framework.Threading.Tasks; 18 | using System; 19 | using System.Collections.Generic; 20 | using System.IO; 21 | using System.Linq; 22 | using System.Reflection; 23 | using System.Threading.Tasks; 24 | using MessageBox = System.Windows.MessageBox; 25 | 26 | namespace UtilityNetworkPropertiesExtractor 27 | { 28 | internal class GdbObjectNamesButton : Button 29 | { 30 | protected async override void OnClick() 31 | { 32 | Common.CreateOutputDirectory(); 33 | ProgressDialog progDlg = new ProgressDialog("Extracting GDB Object Info to:\n" + Common.ExtractFilePath); 34 | 35 | try 36 | { 37 | progDlg.Show(); 38 | await ExtractGdbObjectNamesAsync(); 39 | } 40 | catch (Exception ex) 41 | { 42 | MessageBox.Show(ex.Message, "Extract GDB Object Info Info"); 43 | } 44 | finally 45 | { 46 | progDlg.Dispose(); 47 | } 48 | } 49 | 50 | public static Task ExtractGdbObjectNamesAsync() 51 | { 52 | return QueuedTask.Run(() => 53 | { 54 | List dataSourceInMapList = DataSourcesInMapHelper.GetDataSourcesInMap(); 55 | foreach (DataSourceInMap dataSourceInMap in dataSourceInMapList) 56 | { 57 | //Skip over shapefiles 58 | if (dataSourceInMap.WorkspaceFactory == WorkspaceFactory.Shapefile.ToString() ) 59 | continue; 60 | 61 | using (Geodatabase geodatabase = dataSourceInMap.Geodatabase) 62 | { 63 | string outputFile = Common.BuildCsvName("GdbObjectNames", dataSourceInMap.Name); 64 | using (StreamWriter sw = new StreamWriter(outputFile)) 65 | { 66 | //Header information 67 | Common.WriteHeaderInfoForGeodatabase(sw, dataSourceInMap, "GDB Object Names"); 68 | 69 | //Get all properties defined in the class. This will be used to generate the CSV file 70 | CSVLayout emptyRec = new CSVLayout(); 71 | PropertyInfo[] properties = Common.GetPropertiesOfClass(emptyRec); 72 | 73 | //Write column headers based on properties in the class 74 | string columnHeader = Common.ExtractClassPropertyNamesToString(properties); 75 | sw.WriteLine(columnHeader); 76 | 77 | List csvLayoutList = new List(); 78 | 79 | List datasetTypeList = new List 80 | {DatasetType.UtilityNetwork, 81 | DatasetType.FeatureDataset, 82 | DatasetType.FeatureClass, 83 | DatasetType.Table, 84 | DatasetType.RelationshipClass, 85 | DatasetType.AttributedRelationshipClass}; 86 | 87 | if (dataSourceInMap.WorkspaceFactory == WorkspaceFactory.FeatureService.ToString()) 88 | datasetTypeList.Remove(DatasetType.FeatureDataset); // Exception raised with this dataset type on a featureservice 89 | 90 | foreach (DatasetType datasetType in datasetTypeList) 91 | { 92 | IReadOnlyList definitionList = null; 93 | switch (datasetType) 94 | { 95 | case DatasetType.UtilityNetwork: 96 | definitionList = geodatabase.GetDefinitions(); 97 | break; 98 | 99 | case DatasetType.FeatureDataset: 100 | definitionList = geodatabase.GetDefinitions(); 101 | break; 102 | 103 | case DatasetType.FeatureClass: 104 | definitionList = geodatabase.GetDefinitions(); 105 | break; 106 | 107 | case DatasetType.Table: 108 | definitionList = geodatabase.GetDefinitions(); 109 | break; 110 | 111 | case DatasetType.RelationshipClass: 112 | definitionList = geodatabase.GetDefinitions(); 113 | break; 114 | 115 | case DatasetType.AttributedRelationshipClass: 116 | definitionList = geodatabase.GetDefinitions(); 117 | break; 118 | } 119 | 120 | try 121 | { 122 | 123 | //Loop through each object in the definitionList and determine it's FeatureDataset before writing it to the CSV file 124 | foreach (Definition definition in definitionList) 125 | { 126 | string featureDatasetName = string.Empty; 127 | 128 | //Determine the feature dataset name (if applicable) for the featureclass 129 | if (datasetType == DatasetType.FeatureClass) 130 | { 131 | using (FeatureClass featureClass = geodatabase.OpenDataset(definition.GetName())) 132 | { 133 | FeatureDataset featureDataset = featureClass.GetFeatureDataset(); 134 | if (featureDataset != null) 135 | featureDatasetName = featureDataset.GetName(); 136 | } 137 | } 138 | 139 | //Determine the feature dataset name (if applicable) for the RelationshipClass 140 | else if (datasetType == DatasetType.RelationshipClass) 141 | { 142 | using (RelationshipClass relationshipClass = geodatabase.OpenDataset(definition.GetName())) 143 | { 144 | FeatureDataset featureDataset = relationshipClass.GetFeatureDataset(); 145 | if (featureDataset != null) 146 | featureDatasetName = featureDataset.GetName(); 147 | } 148 | } 149 | 150 | //Determine the feature dataset name for the Utility Network object 151 | else if (datasetType == DatasetType.UtilityNetwork) 152 | { 153 | using (UtilityNetwork un = geodatabase.OpenDataset(definition.GetName())) 154 | { 155 | NetworkSource assemblyNetworkSource = un.GetDefinition().GetNetworkSources().Where(x => x.UsageType == SourceUsageType.Assembly).First(); 156 | FeatureClass assemblyFeatureClass = un.GetTable(assemblyNetworkSource) as FeatureClass; 157 | featureDatasetName = assemblyFeatureClass.GetFeatureDataset()?.GetName(); 158 | } 159 | } 160 | 161 | CSVLayout rec = new CSVLayout() 162 | { 163 | ObjectType = definition.DatasetType.ToString(), 164 | ObjectName = definition.GetName(), 165 | FeatureDataset = featureDatasetName 166 | }; 167 | csvLayoutList.Add(rec); 168 | } 169 | } 170 | catch (Exception ex) // suppress error message 171 | { 172 | if (ex.HResult != -2146233088) // No database permissions to perform the operation. 173 | MessageBox.Show(ex.Message); 174 | } 175 | } 176 | 177 | //Write body of CSV 178 | foreach (CSVLayout row in csvLayoutList.OrderBy(x => x.ObjectType).ThenBy(x => x.ObjectName)) 179 | { 180 | string output = Common.ExtractClassValuesToString(row, properties); 181 | sw.WriteLine(output); 182 | } 183 | 184 | sw.Flush(); 185 | sw.Close(); 186 | } 187 | } 188 | } 189 | }); 190 | } 191 | 192 | private class CSVLayout 193 | { 194 | public string ObjectType { get; set; } 195 | public string ObjectName { get; set; } 196 | public string FeatureDataset { get; set; } 197 | } 198 | } 199 | } -------------------------------------------------------------------------------- /UtilityNetworkPropertiesExtractor/Helpers/GeoprocessingPrepHelper.cs: -------------------------------------------------------------------------------- 1 | using ArcGIS.Core.Data; 2 | using ArcGIS.Desktop.Mapping; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.IO; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | 10 | namespace UtilityNetworkPropertiesExtractor 11 | { 12 | internal class GeoprocessingPrepHelper 13 | { 14 | public static Dictionary BuildDictionaryOfDistinctObjectsInMap() 15 | { 16 | Dictionary tablesDict = new Dictionary(); 17 | 18 | //If Subtype Group layers are in the map, will have multiple layers pointing to same source featureclass 19 | //Populate Dictionary of distinct featureclasses 20 | IReadOnlyList featureLayerList = MapView.Active.Map.GetLayersAsFlattenedList().OfType().ToList(); 21 | foreach (FeatureLayer featureLayer in featureLayerList) 22 | { 23 | Table table = featureLayer.GetTable(); 24 | if (!tablesDict.ContainsKey(table.GetName())) 25 | { 26 | DataSourceInMap dataSourcesInMap = DataSourcesInMapHelper.GetDataSourceOfLayerForDatabaseGPToolUsage(featureLayer); 27 | if (dataSourcesInMap != null) 28 | { 29 | TableAndDataSource tableAndDataSource = new TableAndDataSource() 30 | { 31 | DataSourceName = dataSourcesInMap.Name, 32 | Table = table 33 | }; 34 | 35 | tablesDict.Add(table.GetName(), tableAndDataSource); 36 | } 37 | } 38 | } 39 | 40 | //Standalone Tables 41 | IReadOnlyList standaloneTableList = MapView.Active.Map.StandaloneTables; 42 | foreach (StandaloneTable standaloneTable in standaloneTableList) 43 | { 44 | Table table = standaloneTable.GetTable(); 45 | if (!tablesDict.ContainsKey(table.GetName())) 46 | { 47 | DataSourceInMap dataSourcesInMap = DataSourcesInMapHelper.GetDataSourceOfLayerForDatabaseGPToolUsage(standaloneTable); 48 | if (dataSourcesInMap != null) 49 | { 50 | TableAndDataSource tableAndDataSource = new TableAndDataSource() 51 | { 52 | DataSourceName = dataSourcesInMap.Name, 53 | Table = table 54 | }; 55 | 56 | tablesDict.Add(table.GetName(), tableAndDataSource); 57 | } 58 | } 59 | } 60 | 61 | return tablesDict; 62 | } 63 | 64 | public static string BuildPathForObject(TableAndDataSource tableAndDataSource) 65 | { 66 | using (Datastore datastore = tableAndDataSource.Table.GetDatastore()) 67 | { 68 | string pathToObject = string.Empty; 69 | 70 | if (datastore is UnknownDatastore) 71 | return string.Empty; 72 | 73 | //Using the absolute path for local files results in escape characters for things like spaces, which the GP tool can't handle for input/output of local files. 74 | Uri uri = datastore.GetPath(); 75 | string datastorePath = uri.LocalPath; 76 | 77 | FeatureClass featureclass = tableAndDataSource.Table as FeatureClass; 78 | FeatureDataset featureDataset = null; 79 | 80 | if (featureclass != null) 81 | featureDataset = featureclass.GetFeatureDataset(); 82 | 83 | if (featureDataset == null) 84 | { 85 | //.sde/meh.unadmin.featureclass 86 | pathToObject = string.Format("{0}\\{1}", datastorePath, tableAndDataSource.Table.GetName()); 87 | } 88 | else 89 | { 90 | //.sde/meh.unadmin.Electric\meh.unadmin.ElectricDevice 91 | string featureDatasetName = featureclass.GetFeatureDataset().GetName(); 92 | pathToObject = string.Format("{0}\\{1}\\{2}", datastorePath, featureDatasetName, tableAndDataSource.Table.GetName()); 93 | } 94 | 95 | pathToObject = pathToObject.Replace("\\", "/"); 96 | return pathToObject; 97 | } 98 | } 99 | 100 | public static void DeleteEmptyFiles(string searchString) 101 | { 102 | //Loop through directories and delete "_ContingentValues" files that are empty 103 | string[] directories = Directory.GetDirectories(Common.ExtractFilePath); 104 | foreach (string directory in directories) 105 | { 106 | //Delete files that only have 1 line (header) which means 0 Contingent Values are assigned 107 | DirectoryInfo directoryInfo = new DirectoryInfo(directory); 108 | List blankFiles = directoryInfo.GetFiles().Where(f => f.Extension == ".csv" && f.Name.Contains(searchString)).ToList(); 109 | foreach (FileInfo bf in blankFiles) 110 | { 111 | string[] lines = File.ReadAllLines(bf.FullName); 112 | int cnt = lines.Count(); 113 | 114 | if (cnt == 1) 115 | bf.Delete(); 116 | } 117 | 118 | //Delete the .xml files that are genereated by the GP tool 119 | List deleteableFiles = directoryInfo.GetFiles().Where(f => f.Extension == ".xml" && f.Name.Contains(searchString)).ToList(); 120 | foreach (FileInfo file in deleteableFiles) 121 | file.Delete(); 122 | 123 | FileInfo[] schemaIniFile = directoryInfo.GetFiles("schema.ini"); 124 | foreach (FileInfo schemaIni in schemaIniFile) 125 | schemaIni.Delete(); 126 | } 127 | } 128 | } 129 | 130 | public class TableAndDataSource 131 | { 132 | public Table Table { get; set; } 133 | public string DataSourceName { get; set; } 134 | } 135 | } -------------------------------------------------------------------------------- /UtilityNetworkPropertiesExtractor/Images/AddInDesktop16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Esri/utility-network-properties-extractor/5f5b769bc5e4dba64e782683b3aea8da27f6c04b/UtilityNetworkPropertiesExtractor/Images/AddInDesktop16.png -------------------------------------------------------------------------------- /UtilityNetworkPropertiesExtractor/Images/AddInDesktop32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Esri/utility-network-properties-extractor/5f5b769bc5e4dba64e782683b3aea8da27f6c04b/UtilityNetworkPropertiesExtractor/Images/AddInDesktop32.png -------------------------------------------------------------------------------- /UtilityNetworkPropertiesExtractor/JSON Mappings/ArcRestError.cs: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021 Esri 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | http://www.apache.org/licenses/LICENSE-2.0 7 | Unless required by applicable law or agreed to in writing, software 8 | distributed under the License is distributed on an "AS IS" BASIS, 9 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10 | See the License for the specific language governing permissions and 11 | limitations under the License. 12 | */ 13 | 14 | // Esri Community blog on creating C# classes needed to deserialize the JSON. 15 | // https://community.esri.com/t5/arcgis-pro-sdk-questions/extracting-coordinates-from-json-results/td-p/1014686 16 | //1. Copy your [valid] JSON string to the Clipboard 17 | //2. In Visual Studio: 18 | //3. Create a new cs class file in your project 19 | //4. Delete the create class stub in the new class file and use Edit -> Paste Special -> Paste as JSON Classes 20 | //5. This will create the classes you need to deserialize the JSON. 21 | //6. You need to add the Newton.JSON nuget to your project (VS will suggest that to you once you add the code below) 22 | //7. Now you can use this code to deserialize the JSON string 23 | 24 | 25 | namespace UtilityNetworkPropertiesExtractor.JSONMappings 26 | { 27 | public class ArcRestError 28 | { 29 | public Error error { get; set; } 30 | } 31 | 32 | public class Error 33 | { 34 | public int code { get; set; } 35 | public string message { get; set; } 36 | public object[] details { get; set; } 37 | } 38 | } -------------------------------------------------------------------------------- /UtilityNetworkPropertiesExtractor/JSON Mappings/FeatureServiceJSONMapping.cs: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021 Esri 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | http://www.apache.org/licenses/LICENSE-2.0 7 | Unless required by applicable law or agreed to in writing, software 8 | distributed under the License is distributed on an "AS IS" BASIS, 9 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10 | See the License for the specific language governing permissions and 11 | limitations under the License. 12 | */ 13 | namespace UtilityNetworkPropertiesExtractor.JSONMappings 14 | { 15 | public class FeatureServiceJSONMapping 16 | { 17 | public float currentVersion { get; set; } 18 | public string cimVersion { get; set; } 19 | public string serviceDescription { get; set; } 20 | public bool hasVersionedData { get; set; } 21 | public bool hasArchivedData { get; set; } 22 | public bool hasBranchVersionedData { get; set; } 23 | public bool supportsDisconnectedEditing { get; set; } 24 | public bool supportsDatumTransformation { get; set; } 25 | public bool supportsReturnServiceEditsOption { get; set; } 26 | public bool returnServiceEditsHaveSR { get; set; } 27 | public bool supportsQueryDataElements { get; set; } 28 | public bool supportsRelationshipsResource { get; set; } 29 | public bool syncEnabled { get; set; } 30 | 31 | public Synccapabilities syncCapabilities { get; set; } 32 | public Extractchangescapabilities extractChangesCapabilities { get; set; } 33 | public string supportedQueryFormats { get; set; } 34 | public int maxRecordCount { get; set; } 35 | public int maxRecordCountFactor { get; set; } 36 | public string capabilities { get; set; } 37 | public string description { get; set; } 38 | public string copyrightText { get; set; } 39 | public Advancededitingcapabilities advancedEditingCapabilities { get; set; } 40 | public Spatialreference spatialReference { get; set; } 41 | public Initialextent initialExtent { get; set; } 42 | public Fullextent fullExtent { get; set; } 43 | public bool allowGeometryUpdates { get; set; } 44 | public bool allowTrueCurvesUpdates { get; set; } 45 | public bool onlyAllowTrueCurveUpdatesByTrueCurveClients { get; set; } 46 | public bool supportsApplyEditsWithGlobalIds { get; set; } 47 | public bool supportsOidReservation { get; set; } 48 | public bool supportsTrueCurve { get; set; } 49 | public string units { get; set; } 50 | public Documentinfo documentInfo { get; set; } 51 | public bool supportsQueryDomains { get; set; } 52 | public bool supportsQueryContingentValues { get; set; } 53 | public Layer[] layers { get; set; } 54 | public Table[] tables { get; set; } 55 | public Relationship[] relationships { get; set; } 56 | public Controllerdatasetlayers controllerDatasetLayers { get; set; } 57 | public bool supportsDynamicLayers { get; set; } 58 | public bool enableZDefaults { get; set; } 59 | public int zDefault { get; set; } 60 | public bool allowUpdateWithoutMValues { get; set; } 61 | public Heightmodelinfo heightModelInfo { get; set; } 62 | public bool supportsVCSProjection { get; set; } 63 | public Datumtransformation[] datumTransformations { get; set; } 64 | public int referenceScale { get; set; } 65 | public string serviceItemId { get; set; } 66 | } 67 | 68 | public class Synccapabilities 69 | { 70 | public bool supportsRegisteringExistingData { get; set; } 71 | public bool supportsSyncDirectionControl { get; set; } 72 | public bool supportsPerLayerSync { get; set; } 73 | public bool supportsPerReplicaSync { get; set; } 74 | public bool supportsRollbackOnFailure { get; set; } 75 | public bool supportsAsync { get; set; } 76 | public bool supportsAttachmentsSyncDirection { get; set; } 77 | public bool supportsSyncModelNone { get; set; } 78 | public string versionCreationRule { get; set; } 79 | public int supportedSyncDataOptions { get; set; } 80 | public bool supportsBiDirectionalSyncForServer { get; set; } 81 | public Advancedreplicasresourcecapabilities advancedReplicasResourceCapabilities { get; set; } 82 | } 83 | 84 | public class Advancedreplicasresourcecapabilities 85 | { 86 | public bool supportsVersion { get; set; } 87 | public bool supportsReturnVersion { get; set; } 88 | public bool supportsReturnLastSyncDate { get; set; } 89 | } 90 | public class Extractchangescapabilities 91 | { 92 | public bool supportsReturnIdsOnly { get; set; } 93 | public bool supportsReturnExtentOnly { get; set; } 94 | public bool supportsReturnAttachments { get; set; } 95 | public bool supportsLayerQueries { get; set; } 96 | public bool supportsGeometry { get; set; } 97 | public bool supportsFeatureReturn { get; set; } 98 | } 99 | 100 | public class Advancededitingcapabilities 101 | { 102 | public bool supportsSplit { get; set; } 103 | public bool supportsReturnServiceEditsInSourceSR { get; set; } 104 | } 105 | 106 | public class Spatialreference 107 | { 108 | public int wkid { get; set; } 109 | public int latestWkid { get; set; } 110 | public int vcsWkid { get; set; } 111 | public int latestVcsWkid { get; set; } 112 | public float xyTolerance { get; set; } 113 | public float zTolerance { get; set; } 114 | public float mTolerance { get; set; } 115 | public int falseX { get; set; } 116 | public int falseY { get; set; } 117 | public float xyUnits { get; set; } 118 | public int falseZ { get; set; } 119 | public float zUnits { get; set; } 120 | public int falseM { get; set; } 121 | public int mUnits { get; set; } 122 | } 123 | 124 | public class Initialextent 125 | { 126 | public float xmin { get; set; } 127 | public float ymin { get; set; } 128 | public float xmax { get; set; } 129 | public float ymax { get; set; } 130 | public Spatialreference1 spatialReference { get; set; } 131 | } 132 | 133 | public class Spatialreference1 134 | { 135 | public int wkid { get; set; } 136 | public int latestWkid { get; set; } 137 | public int vcsWkid { get; set; } 138 | public int latestVcsWkid { get; set; } 139 | public float xyTolerance { get; set; } 140 | public float zTolerance { get; set; } 141 | public float mTolerance { get; set; } 142 | public int falseX { get; set; } 143 | public int falseY { get; set; } 144 | public float xyUnits { get; set; } 145 | public int falseZ { get; set; } 146 | public float zUnits { get; set; } 147 | public int falseM { get; set; } 148 | public int mUnits { get; set; } 149 | } 150 | 151 | public class Fullextent 152 | { 153 | public float xmin { get; set; } 154 | public float ymin { get; set; } 155 | public float xmax { get; set; } 156 | public float ymax { get; set; } 157 | public Spatialreference2 spatialReference { get; set; } 158 | } 159 | 160 | public class Spatialreference2 161 | { 162 | public int wkid { get; set; } 163 | public int latestWkid { get; set; } 164 | public int vcsWkid { get; set; } 165 | public int latestVcsWkid { get; set; } 166 | public float xyTolerance { get; set; } 167 | public float zTolerance { get; set; } 168 | public float mTolerance { get; set; } 169 | public int falseX { get; set; } 170 | public int falseY { get; set; } 171 | public float xyUnits { get; set; } 172 | public int falseZ { get; set; } 173 | public float zUnits { get; set; } 174 | public int falseM { get; set; } 175 | public int mUnits { get; set; } 176 | } 177 | 178 | public class Documentinfo 179 | { 180 | public string Title { get; set; } 181 | public string Author { get; set; } 182 | public string Comments { get; set; } 183 | public string Subject { get; set; } 184 | public string Category { get; set; } 185 | public string Keywords { get; set; } 186 | } 187 | 188 | public class Controllerdatasetlayers 189 | { 190 | public int utilityNetworkLayerId { get; set; } 191 | } 192 | 193 | public class Heightmodelinfo 194 | { 195 | public string heightModel { get; set; } 196 | public string vertCRS { get; set; } 197 | public string heightUnit { get; set; } 198 | } 199 | 200 | public class Layer 201 | { 202 | public int id { get; set; } 203 | public string name { get; set; } 204 | public int parentLayerId { get; set; } 205 | public bool defaultVisibility { get; set; } 206 | public int[] subLayerIds { get; set; } 207 | public int minScale { get; set; } 208 | public int maxScale { get; set; } 209 | public string type { get; set; } 210 | public string geometryType { get; set; } 211 | } 212 | 213 | public class Table 214 | { 215 | public int id { get; set; } 216 | public string name { get; set; } 217 | } 218 | 219 | public class Relationship 220 | { 221 | public int id { get; set; } 222 | public string name { get; set; } 223 | } 224 | 225 | public class Datumtransformation 226 | { 227 | public Geotransform[] geoTransforms { get; set; } 228 | } 229 | 230 | public class Geotransform 231 | { 232 | public int wkid { get; set; } 233 | public int latestWkid { get; set; } 234 | public bool transformForward { get; set; } 235 | public string name { get; set; } 236 | } 237 | } -------------------------------------------------------------------------------- /UtilityNetworkPropertiesExtractor/JSON Mappings/NetworkDiagramTemplateJSONMapping.cs: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021 Esri 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | http://www.apache.org/licenses/LICENSE-2.0 7 | Unless required by applicable law or agreed to in writing, software 8 | distributed under the License is distributed on an "AS IS" BASIS, 9 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10 | See the License for the specific language governing permissions and 11 | limitations under the License. 12 | */ 13 | namespace UtilityNetworkPropertiesExtractor.JSONMappings 14 | { 15 | public class NetworkDiagramTemplateJSONMapping 16 | { 17 | public Diagramtemplateinfo[] diagramTemplateInfos { get; set; } 18 | } 19 | 20 | public class Diagramtemplateinfo 21 | { 22 | public string name { get; set; } 23 | public string description { get; set; } 24 | public long creationDate { get; set; } 25 | public long lastUpdateDate { get; set; } 26 | public bool usedByATier { get; set; } 27 | public bool enableDiagramExtend { get; set; } 28 | public bool enableDiagramStorage { get; set; } 29 | } 30 | } -------------------------------------------------------------------------------- /UtilityNetworkPropertiesExtractor/JSON Mappings/TraceConfigurationJSONMapping.cs: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021 Esri 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | http://www.apache.org/licenses/LICENSE-2.0 7 | Unless required by applicable law or agreed to in writing, software 8 | distributed under the License is distributed on an "AS IS" BASIS, 9 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10 | See the License for the specific language governing permissions and 11 | limitations under the License. 12 | */ 13 | namespace UtilityNetworkPropertiesExtractor.JSONMappings 14 | { 15 | public class TraceConfigurationJSONMapping 16 | { 17 | public Traceconfiguration[] traceConfigurations { get; set; } 18 | public bool success { get; set; } 19 | } 20 | 21 | public class Traceconfiguration 22 | { 23 | public string name { get; set; } 24 | public string description { get; set; } 25 | public string traceType { get; set; } 26 | public Traceconfiguration1 traceConfiguration { get; set; } 27 | public object[] resultTypes { get; set; } 28 | public string minNumStartingPoints { get; set; } 29 | public long creationDate { get; set; } 30 | public string[] tags { get; set; } 31 | public string creator { get; set; } 32 | public string globalId { get; set; } 33 | } 34 | 35 | public class Traceconfiguration1 36 | { 37 | public bool includeContainers { get; set; } 38 | public bool includeContent { get; set; } 39 | public bool includeStructures { get; set; } 40 | public bool includeBarriers { get; set; } 41 | public bool validateConsistency { get; set; } 42 | public bool validateLocatability { get; set; } 43 | public bool includeIsolated { get; set; } 44 | public bool ignoreBarriersAtStartingPoints { get; set; } 45 | public bool includeUpToFirstSpatialContainer { get; set; } 46 | public bool allowIndeterminateFlow { get; set; } 47 | public string domainNetworkName { get; set; } 48 | public string tierName { get; set; } 49 | public string targetTierName { get; set; } 50 | public string subnetworkName { get; set; } 51 | public string diagramTemplateName { get; set; } 52 | public string shortestPathNetworkAttributeName { get; set; } 53 | public string filterBitsetNetworkAttributeName { get; set; } 54 | public string traversabilityScope { get; set; } 55 | public Conditionbarrier[] conditionBarriers { get; set; } 56 | public object[] functionBarriers { get; set; } 57 | public string arcadeExpressionBarrier { get; set; } 58 | public Filterbarrier[] filterBarriers { get; set; } 59 | public object[] filterFunctionBarriers { get; set; } 60 | public string filterScope { get; set; } 61 | public object[] functions { get; set; } 62 | public Nearestneighbor nearestNeighbor { get; set; } 63 | public Outputfilter[] outputFilters { get; set; } 64 | public Outputcondition[] outputConditions { get; set; } 65 | public object[] propagators { get; set; } 66 | } 67 | 68 | public class Nearestneighbor 69 | { 70 | public int count { get; set; } 71 | public string costNetworkAttributeName { get; set; } 72 | public object[] nearestCategories { get; set; } 73 | public object[] nearestAssets { get; set; } 74 | } 75 | 76 | public class Conditionbarrier 77 | { 78 | public string name { get; set; } 79 | public string type { get; set; } 80 | public string _operator { get; set; } 81 | public object value { get; set; } 82 | public bool combineUsingOr { get; set; } 83 | public bool isSpecificValue { get; set; } 84 | } 85 | 86 | public class Filterbarrier 87 | { 88 | public string name { get; set; } 89 | public string type { get; set; } 90 | public string _operator { get; set; } 91 | public string value { get; set; } 92 | public bool combineUsingOr { get; set; } 93 | public bool isSpecificValue { get; set; } 94 | } 95 | 96 | public class Outputfilter 97 | { 98 | public int networkSourceId { get; set; } 99 | public int assetGroupCode { get; set; } 100 | public int assetTypeCode { get; set; } 101 | } 102 | 103 | public class Outputcondition 104 | { 105 | public string name { get; set; } 106 | public string type { get; set; } 107 | public string _operator { get; set; } 108 | public string value { get; set; } 109 | public bool combineUsingOr { get; set; } 110 | public bool isSpecificValue { get; set; } 111 | } 112 | } -------------------------------------------------------------------------------- /UtilityNetworkPropertiesExtractor/MachineInfoButton.cs: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021 Esri 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | http://www.apache.org/licenses/LICENSE-2.0 7 | Unless required by applicable law or agreed to in writing, software 8 | distributed under the License is distributed on an "AS IS" BASIS, 9 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10 | See the License for the specific language governing permissions and 11 | limitations under the License. 12 | */ 13 | using ArcGIS.Desktop.Framework.Contracts; 14 | using System; 15 | using System.Diagnostics; 16 | using System.Management; 17 | using System.Reflection; 18 | using System.Windows; 19 | 20 | namespace UtilityNetworkPropertiesExtractor 21 | { 22 | internal class MachineInfoButton : Button 23 | { 24 | protected override void OnClick() 25 | { 26 | string machineName = "Machine: " + Environment.MachineName; 27 | 28 | Assembly assembly = Assembly.GetEntryAssembly(); 29 | FileVersionInfo fvi = FileVersionInfo.GetVersionInfo(assembly.Location); 30 | string proVersion = $"ArcGIS Pro {fvi.ProductMajorPart}.{fvi.ProductMinorPart}.{fvi.ProductBuildPart}"; 31 | string operatingSystem = "Operating System: " + Environment.OSVersion.VersionString; 32 | string cpu = "CPU: " + CpuName(); 33 | string coreCount = "Number Of Cores: " + NumberOfCores(); 34 | string processorCount = "Logical Processor Count: " + Environment.ProcessorCount; 35 | string memory = "Total Physical Memory: " + TotalPhysicalMemory(); 36 | string videoControllerInfo = "\nVideo Controllers:\n" + VideoControllers(); 37 | 38 | string mesg = machineName + "\n" + 39 | proVersion + "\n" + 40 | operatingSystem + "\n" + 41 | cpu + "\n" + 42 | coreCount + "\n" + 43 | processorCount + "\n" + 44 | memory + "\n" + 45 | videoControllerInfo; 46 | 47 | Clipboard.SetText(mesg); 48 | MessageBox.Show(mesg + "\n\nThis information has been copied to the clipboard!", machineName); 49 | } 50 | 51 | private static int NumberOfCores() 52 | { 53 | int coreCount = 0; 54 | ObjectQuery wql = new ObjectQuery("SELECT * FROM Win32_Processor"); 55 | ManagementObjectSearcher searcher = new ManagementObjectSearcher(wql); 56 | ManagementObjectCollection results = searcher.Get(); 57 | 58 | foreach (ManagementObject result in results) 59 | coreCount = Convert.ToInt32(result["NumberOfCores"]); 60 | 61 | return coreCount; 62 | } 63 | 64 | private static string TotalPhysicalMemory() 65 | { 66 | ObjectQuery wql = new ObjectQuery("SELECT * FROM Win32_OperatingSystem"); 67 | ManagementObjectSearcher searcher = new ManagementObjectSearcher(wql); 68 | ManagementObjectCollection results = searcher.Get(); 69 | 70 | double res; 71 | double fres = 0; 72 | 73 | foreach (ManagementObject result in results) 74 | { 75 | res = Convert.ToDouble(result["TotalVisibleMemorySize"]); 76 | fres = Math.Round((res / (1024 * 1024)), 2); 77 | } 78 | return fres.ToString() + " GB"; 79 | } 80 | 81 | private static string CpuName() 82 | { 83 | string cpuName = string.Empty; 84 | using (ManagementObject Mo = new ManagementObject("Win32_Processor.DeviceID='CPU0'")) 85 | { 86 | cpuName = (string)(Mo["Name"]); 87 | } 88 | return cpuName; 89 | } 90 | 91 | private static string VideoControllers() 92 | { 93 | string retVal = string.Empty; 94 | ManagementObjectSearcher myVideoObject = new ManagementObjectSearcher("select * from Win32_VideoController"); 95 | 96 | foreach (ManagementObject obj in myVideoObject.Get()) 97 | { 98 | retVal += "\n DeviceID - " + obj["DeviceID"] + "\n"; 99 | retVal += " Name - " + obj["Name"] + "\n"; 100 | 101 | //Console.WriteLine("Name - " + obj["Name"]; 102 | //Console.WriteLine("Status - " + obj["Status"]; 103 | //Console.WriteLine("Caption - " + obj["Caption"]; 104 | //Console.WriteLine("DeviceID - " + obj["DeviceID"]; 105 | //Console.WriteLine("AdapterRAM - " + obj["AdapterRAM"]; 106 | //Console.WriteLine("AdapterDACType - " + obj["AdapterDACType"]; 107 | //Console.WriteLine("Monochrome - " + obj["Monochrome"]; 108 | //Console.WriteLine("InstalledDisplayDrivers - " + obj["InstalledDisplayDrivers"]; 109 | //Console.WriteLine("DriverVersion - " + obj["DriverVersion"]; 110 | //Console.WriteLine("VideoProcessor - " + obj["VideoProcessor"]; 111 | //Console.WriteLine("VideoArchitecture - " + obj["VideoArchitecture"]; 112 | //Console.WriteLine("VideoMemoryType - " + obj["VideoMemoryType"]; 113 | } 114 | return retVal; 115 | } 116 | } 117 | } -------------------------------------------------------------------------------- /UtilityNetworkPropertiesExtractor/Module1.cs: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021 Esri 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | http://www.apache.org/licenses/LICENSE-2.0 7 | Unless required by applicable law or agreed to in writing, software 8 | distributed under the License is distributed on an "AS IS" BASIS, 9 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10 | See the License for the specific language governing permissions and 11 | limitations under the License. 12 | */ 13 | using ArcGIS.Desktop.Framework; 14 | using ArcGIS.Desktop.Framework.Contracts; 15 | 16 | namespace UtilityNetworkPropertiesExtractor 17 | { 18 | internal class Module1 : Module 19 | { 20 | private static Module1 _this = null; 21 | 22 | /// 23 | /// Retrieve the singleton instance to this module here 24 | /// 25 | public static Module1 Current 26 | { 27 | get 28 | { 29 | return _this ?? (_this = (Module1)FrameworkApplication.FindModule("UtilityNetworkPropertiesExtractor_Module")); 30 | } 31 | } 32 | 33 | #region Overrides 34 | /// 35 | /// Called by Framework when ArcGIS Pro is closing 36 | /// 37 | /// False to prevent Pro from closing, otherwise True 38 | protected override bool CanUnload() 39 | { 40 | //TODO - add your business logic 41 | //return false to ~cancel~ Application close 42 | return true; 43 | } 44 | 45 | #endregion Overrides 46 | } 47 | } -------------------------------------------------------------------------------- /UtilityNetworkPropertiesExtractor/NetworkAttributesButton.cs: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021 Esri 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | http://www.apache.org/licenses/LICENSE-2.0 7 | Unless required by applicable law or agreed to in writing, software 8 | distributed under the License is distributed on an "AS IS" BASIS, 9 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10 | See the License for the specific language governing permissions and 11 | limitations under the License. 12 | */ 13 | using ArcGIS.Core.Data; 14 | using ArcGIS.Core.Data.UtilityNetwork; 15 | using ArcGIS.Desktop.Framework.Contracts; 16 | using ArcGIS.Desktop.Framework.Threading.Tasks; 17 | using System; 18 | using System.Collections.Generic; 19 | using System.IO; 20 | using System.Linq; 21 | using System.Reflection; 22 | using System.Threading.Tasks; 23 | using System.Windows; 24 | using MessageBox = System.Windows.MessageBox; 25 | 26 | namespace UtilityNetworkPropertiesExtractor 27 | { 28 | internal class NetworkAttributesButton : Button 29 | { 30 | protected async override void OnClick() 31 | { 32 | Common.CreateOutputDirectory(); 33 | ProgressDialog progDlg = new ProgressDialog("Extracting Network Attributes to: \n" + Common.ExtractFilePath); 34 | 35 | try 36 | { 37 | progDlg.Show(); 38 | await ExtractNetworkAttributesAsync(true); 39 | } 40 | catch (Exception ex) 41 | { 42 | MessageBox.Show(ex.Message, "Extract Network Attributes"); 43 | } 44 | finally 45 | { 46 | progDlg.Dispose(); 47 | } 48 | } 49 | 50 | public static Task ExtractNetworkAttributesAsync(bool showNoUtilityNetworkPrompt) 51 | { 52 | return QueuedTask.Run(() => 53 | { 54 | List utilityNetworkDataSourceInMapList = DataSourcesInMapHelper.GetUtilityNetworkDataSourcesInMap(); 55 | if (utilityNetworkDataSourceInMapList.Count == 0) 56 | { 57 | if (showNoUtilityNetworkPrompt) 58 | MessageBox.Show("A Utility Network was not found in the active map", "Extract Network Attributes", MessageBoxButton.OK, MessageBoxImage.Error); 59 | 60 | return; 61 | } 62 | 63 | foreach (UtilityNetworkDataSourceInMap utilityNetworkDataSourceInMap in utilityNetworkDataSourceInMapList) 64 | { 65 | using (Geodatabase geodatabase = utilityNetworkDataSourceInMap.Geodatabase) 66 | { 67 | string outputFile = Common.BuildCsvName("NetworkAttributes", utilityNetworkDataSourceInMap.Name); 68 | using (StreamWriter sw = new StreamWriter(outputFile)) 69 | { 70 | //Header information 71 | UtilityNetworkDefinition utilityNetworkDefinition = utilityNetworkDataSourceInMap.UtilityNetwork.GetDefinition(); 72 | Common.WriteHeaderInfoForUtilityNetwork(sw, utilityNetworkDataSourceInMap, "Network Attributes"); 73 | 74 | //Network Attributes 75 | List CSVLayoutNetworkAttributesList = new List(); 76 | 77 | //Get all properties defined in the class. This will be used to generate the CSV file 78 | CSVLayoutNetworkAttributes emptyRec = new CSVLayoutNetworkAttributes(); 79 | PropertyInfo[] properties = Common.GetPropertiesOfClass(emptyRec); 80 | 81 | //Write column headers based on properties in the class 82 | string columnHeader = Common.ExtractClassPropertyNamesToString(properties); 83 | sw.WriteLine(columnHeader); 84 | 85 | IEnumerable networkAttributes = utilityNetworkDefinition.GetNetworkAttributes().OrderBy(x => x.Name); 86 | foreach (NetworkAttribute networkAttribute in networkAttributes) 87 | { 88 | CSVLayoutNetworkAttributes rec = new CSVLayoutNetworkAttributes() 89 | { 90 | Name = networkAttribute.Name, 91 | DataType = networkAttribute.Type.ToString(), 92 | Domain = networkAttribute.Domain?.GetName() 93 | }; 94 | CSVLayoutNetworkAttributesList.Add(rec); 95 | } 96 | CSVLayoutNetworkAttributesList.Add(emptyRec); 97 | 98 | foreach (CSVLayoutNetworkAttributes row in CSVLayoutNetworkAttributesList) 99 | { 100 | string output = Common.ExtractClassValuesToString(row, properties); 101 | sw.WriteLine(output); 102 | } 103 | 104 | //Network Attribute Assignments 105 | List CSVLayoutNetworksAttributesAssignmentsList = new List(); 106 | 107 | CSVLayoutNetworksAttributesAssignments emptyAssignmentRec = new CSVLayoutNetworksAttributesAssignments(); 108 | properties = Common.GetPropertiesOfClass(emptyAssignmentRec); 109 | 110 | //Write column headers based on properties in the class 111 | columnHeader = Common.ExtractClassPropertyNamesToString(properties); 112 | sw.WriteLine(columnHeader); 113 | 114 | foreach (NetworkAttribute networkAttribute in networkAttributes) 115 | { 116 | IReadOnlyList assignments = networkAttribute.Assignments; 117 | foreach (NetworkAttributeAssignment assignment in assignments) 118 | { 119 | CSVLayoutNetworksAttributesAssignments assignRec = new CSVLayoutNetworksAttributesAssignments() 120 | { 121 | NetworkAttribute = networkAttribute.Name, 122 | ClassName = assignment.NetworkSource.Name, 123 | FieldName = assignment.Field?.Name 124 | }; 125 | CSVLayoutNetworksAttributesAssignmentsList.Add(assignRec); 126 | } 127 | } 128 | 129 | foreach (CSVLayoutNetworksAttributesAssignments row in CSVLayoutNetworksAttributesAssignmentsList) 130 | { 131 | string output = Common.ExtractClassValuesToString(row, properties); 132 | sw.WriteLine(output); 133 | } 134 | 135 | sw.Flush(); 136 | sw.Close(); 137 | } 138 | } 139 | } 140 | }); 141 | } 142 | 143 | private class CSVLayoutNetworkAttributes 144 | { 145 | public string NetworkAttributes { get; set; } 146 | public string Name { get; set; } 147 | public string DataType { get; set; } 148 | public string Domain { get; set; } 149 | } 150 | 151 | private class CSVLayoutNetworksAttributesAssignments 152 | { 153 | public string Assignments { get; set; } 154 | public string NetworkAttribute { get; set; } 155 | public string ClassName { get; set; } 156 | public string FieldName { get; set; } 157 | } 158 | } 159 | } -------------------------------------------------------------------------------- /UtilityNetworkPropertiesExtractor/NetworkCategoriesButton.cs: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021 Esri 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | http://www.apache.org/licenses/LICENSE-2.0 7 | Unless required by applicable law or agreed to in writing, software 8 | distributed under the License is distributed on an "AS IS" BASIS, 9 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10 | See the License for the specific language governing permissions and 11 | limitations under the License. 12 | */ 13 | using ArcGIS.Core.Data; 14 | using ArcGIS.Core.Data.UtilityNetwork; 15 | using ArcGIS.Desktop.Framework.Contracts; 16 | using ArcGIS.Desktop.Framework.Threading.Tasks; 17 | using System; 18 | using System.Collections.Generic; 19 | using System.IO; 20 | using System.Linq; 21 | using System.Reflection; 22 | using System.Threading.Tasks; 23 | using System.Windows; 24 | using MessageBox = System.Windows.MessageBox; 25 | 26 | namespace UtilityNetworkPropertiesExtractor 27 | { 28 | internal class NetworkCategoriesButton : Button 29 | { 30 | protected async override void OnClick() 31 | { 32 | Common.CreateOutputDirectory(); 33 | ProgressDialog progDlg = new ProgressDialog("Extracting Network Categories to: \n" + Common.ExtractFilePath); 34 | 35 | try 36 | { 37 | progDlg.Show(); 38 | await ExtractNetworkCategoriesAsync(true); 39 | } 40 | catch (Exception ex) 41 | { 42 | MessageBox.Show(ex.Message, "Extract Network Categories"); 43 | } 44 | finally 45 | { 46 | progDlg.Dispose(); 47 | } 48 | } 49 | 50 | public static Task ExtractNetworkCategoriesAsync(bool showNoUtilityNetworkPrompt) 51 | { 52 | return QueuedTask.Run(() => 53 | { 54 | List utilityNetworkDataSourceInMapList = DataSourcesInMapHelper.GetUtilityNetworkDataSourcesInMap(); 55 | if (utilityNetworkDataSourceInMapList.Count == 0) 56 | { 57 | if (showNoUtilityNetworkPrompt) 58 | MessageBox.Show("A Utility Network was not found in the active map", "Extract Network Categories", MessageBoxButton.OK, MessageBoxImage.Error); 59 | 60 | return; 61 | } 62 | 63 | foreach (UtilityNetworkDataSourceInMap utilityNetworkDataSourceInMap in utilityNetworkDataSourceInMapList) 64 | { 65 | using (Geodatabase geodatabase = utilityNetworkDataSourceInMap.Geodatabase) 66 | { 67 | string outputFile = Common.BuildCsvName("NetworkCategories", utilityNetworkDataSourceInMap.Name); 68 | using (StreamWriter sw = new StreamWriter(outputFile)) 69 | { 70 | //Header information 71 | UtilityNetworkDefinition utilityNetworkDefinition = utilityNetworkDataSourceInMap.UtilityNetwork.GetDefinition(); 72 | Common.WriteHeaderInfoForUtilityNetwork(sw, utilityNetworkDataSourceInMap, "Network Categories"); 73 | 74 | //Network Categories 75 | sw.WriteLine(); 76 | sw.WriteLine("Network Categories"); 77 | IEnumerable categories = utilityNetworkDefinition.GetAvailableCategories().OrderBy(x => x).ToList(); 78 | foreach (string category in categories) 79 | sw.WriteLine("," + category); 80 | 81 | sw.WriteLine(""); 82 | 83 | List csvLayoutList = new List(); 84 | 85 | //Get all properties defined in the class. This will be used to generate the CSV file 86 | CSVLayout emptyRec = new CSVLayout(); 87 | PropertyInfo[] properties = Common.GetPropertiesOfClass(emptyRec); 88 | 89 | //Write column headers based on properties in the class 90 | string columnHeader = Common.ExtractClassPropertyNamesToString(properties); 91 | sw.WriteLine(columnHeader); 92 | 93 | IReadOnlyList networkSourceList = utilityNetworkDefinition.GetNetworkSources(); 94 | foreach (NetworkSource networkSource in networkSourceList) 95 | { 96 | //Network Categories 97 | IReadOnlyList assetGroupList = networkSource.GetAssetGroups(); 98 | foreach (AssetGroup assetGroup in assetGroupList) 99 | { 100 | //Asset Types 101 | IReadOnlyList assetTypeList = assetGroup.GetAssetTypes(); 102 | foreach (AssetType assetType in assetTypeList) 103 | { 104 | //Categories 105 | IReadOnlyList categoriesList = assetType.CategoryList; 106 | foreach (string category in categoriesList) 107 | { 108 | CSVLayout rec = new CSVLayout() 109 | { 110 | NetworkCategory = category, 111 | ClassName = networkSource.Name, 112 | AssetGroupCode = assetGroup.Code.ToString(), 113 | AssetGroup = assetGroup.Name, 114 | AssetTypeCode = assetType.Code.ToString(), 115 | AssetType = assetType.Name, 116 | }; 117 | 118 | csvLayoutList.Add(rec); 119 | } 120 | } 121 | } 122 | } 123 | 124 | foreach (CSVLayout row in csvLayoutList.OrderBy(x => x.NetworkCategory)) 125 | { 126 | string output = Common.ExtractClassValuesToString(row, properties); 127 | sw.WriteLine(output); 128 | } 129 | 130 | sw.Flush(); 131 | sw.Close(); 132 | } 133 | } 134 | } 135 | }); 136 | } 137 | 138 | private class CSVLayout 139 | { 140 | public string Assignments { get; set; } 141 | public string NetworkCategory { get; set; } 142 | public string ClassName { get; set; } 143 | public string AssetGroupCode { get; set; } 144 | public string AssetGroup { get; set; } 145 | public string AssetTypeCode { get; set; } 146 | public string AssetType { get; set; } 147 | } 148 | } 149 | } -------------------------------------------------------------------------------- /UtilityNetworkPropertiesExtractor/NetworkDiagramsButton.cs: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021 Esri 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | http://www.apache.org/licenses/LICENSE-2.0 7 | Unless required by applicable law or agreed to in writing, software 8 | distributed under the License is distributed on an "AS IS" BASIS, 9 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10 | See the License for the specific language governing permissions and 11 | limitations under the License. 12 | */ 13 | using ArcGIS.Core.CIM; 14 | using ArcGIS.Core.Data; 15 | using ArcGIS.Core.Data.NetworkDiagrams; 16 | using ArcGIS.Core.Data.UtilityNetwork; 17 | using ArcGIS.Desktop.Core; 18 | using ArcGIS.Desktop.Framework.Contracts; 19 | using ArcGIS.Desktop.Framework.Threading.Tasks; 20 | using Newtonsoft.Json; 21 | using System; 22 | using System.Collections.Generic; 23 | using System.IO; 24 | using System.Linq; 25 | using System.Reflection; 26 | using System.Threading.Tasks; 27 | using System.Windows; 28 | using MessageBox = System.Windows.MessageBox; 29 | 30 | namespace UtilityNetworkPropertiesExtractor 31 | { 32 | internal class NetworkDiagramsButton : Button 33 | { 34 | protected async override void OnClick() 35 | { 36 | Common.CreateOutputDirectory(); 37 | ProgressDialog progDlg = new ProgressDialog("Extracting Network Diagram Info to: \n" + Common.ExtractFilePath); 38 | 39 | try 40 | { 41 | progDlg.Show(); 42 | await ExtractNetworkDiagramsAsync(true); 43 | } 44 | catch (Exception ex) 45 | { 46 | MessageBox.Show(ex.Message, "Extract Network Diagram Info"); 47 | } 48 | finally 49 | { 50 | progDlg.Dispose(); 51 | } 52 | } 53 | 54 | public static Task ExtractNetworkDiagramsAsync(bool showNoUtilityNetworkPrompt) 55 | { 56 | return QueuedTask.Run(() => 57 | { 58 | List utilityNetworkDataSourceInMapList = DataSourcesInMapHelper.GetUtilityNetworkDataSourcesInMap(); 59 | if (utilityNetworkDataSourceInMapList.Count == 0) 60 | { 61 | if (showNoUtilityNetworkPrompt) 62 | MessageBox.Show("A Utility Network was not found in the active map", "Extract Network Diagram Info", MessageBoxButton.OK, MessageBoxImage.Error); 63 | 64 | return; 65 | } 66 | 67 | foreach (UtilityNetworkDataSourceInMap utilityNetworkDataSourceInMap in utilityNetworkDataSourceInMapList) 68 | { 69 | using (Geodatabase geodatabase = utilityNetworkDataSourceInMap.Geodatabase) 70 | { 71 | string outputFile = Common.BuildCsvName("NetworkDiagramInfo", utilityNetworkDataSourceInMap.Name); 72 | using (StreamWriter sw = new StreamWriter(outputFile)) 73 | { 74 | List csvLayoutList = new List(); 75 | 76 | //Header information 77 | UtilityNetworkDefinition utilityNetworkDefinition = utilityNetworkDataSourceInMap.UtilityNetwork.GetDefinition(); 78 | Common.WriteHeaderInfoForUtilityNetwork(sw, utilityNetworkDataSourceInMap, "Network Diagram Info"); 79 | 80 | //Get all properties defined in the class. This will be used to generate the CSV file 81 | CSVLayout emptyRec = new CSVLayout(); 82 | PropertyInfo[] properties = Common.GetPropertiesOfClass(emptyRec); 83 | 84 | //Write column headers based on properties in the class 85 | string columnHeader = Common.ExtractClassPropertyNamesToString(properties); 86 | sw.WriteLine(columnHeader); 87 | 88 | if (utilityNetworkDataSourceInMap.WorkspaceFactory == WorkspaceFactory.FeatureService.ToString()) 89 | { 90 | ArcGISPortal portal = ArcGISPortalManager.Current.GetActivePortal(); 91 | if (portal == null) 92 | throw new Exception("You must be logged into portal to extract the Utility Network FeatureService Info"); 93 | 94 | string unFeatureServiceURL = Common.AppendTokenToUrl(utilityNetworkDataSourceInMap.URI, portal.GetToken()); 95 | string diagramDatasetServiceURL = unFeatureServiceURL.Replace("FeatureServer", "NetworkDiagramServer/diagramDataset"); 96 | EsriHttpResponseMessage response = Common.QueryRestPointUsingGet(diagramDatasetServiceURL); 97 | 98 | string json = response?.Content?.ReadAsStringAsync()?.Result; 99 | if (json == null) 100 | throw new Exception("Failed to get data from Utility Network Feature Service endpoint"); 101 | 102 | JSONMappings.ArcRestError arcRestError = JsonConvert.DeserializeObject(json); 103 | if (arcRestError?.error != null) 104 | throw new Exception(arcRestError?.error.code + " - " + arcRestError?.error.message + "\n" + diagramDatasetServiceURL); 105 | 106 | JSONMappings.NetworkDiagramTemplateJSONMapping parsedJson = JsonConvert.DeserializeObject(json); 107 | 108 | for (int i = 0; i < parsedJson.diagramTemplateInfos.Length; i++) 109 | { 110 | //globalids needed for GP Tool 111 | CSVLayout rec = new CSVLayout() 112 | { 113 | Name = Common.EncloseStringInDoubleQuotes(Convert.ToString(parsedJson.diagramTemplateInfos[i].name)), 114 | LastModifiedTime = Convert.ToString(Common.ConvertEpochTimeToReadableDate(parsedJson.diagramTemplateInfos[i].lastUpdateDate)), 115 | DiagramStorage = parsedJson.diagramTemplateInfos[i].enableDiagramStorage.ToString(), 116 | IsSystem = parsedJson.diagramTemplateInfos[i].usedByATier.ToString(), 117 | ExtendDiagram = parsedJson.diagramTemplateInfos[i].enableDiagramExtend.ToString(), 118 | Description = Common.EncloseStringInDoubleQuotes(Convert.ToString(parsedJson.diagramTemplateInfos[i].description)), 119 | CreationDate = Convert.ToString(Common.ConvertEpochTimeToReadableDate(parsedJson.diagramTemplateInfos[i].creationDate)) 120 | }; 121 | csvLayoutList.Add(rec); 122 | } 123 | } 124 | else 125 | { 126 | DiagramManager diagramManager = utilityNetworkDataSourceInMap.UtilityNetwork.GetDiagramManager(); 127 | IEnumerable diagramTemplateList = diagramManager.GetDiagramTemplates().OrderBy(x => x.Name); 128 | foreach (DiagramTemplate diagramTemplate in diagramTemplateList) 129 | { 130 | CSVLayout rec = new CSVLayout 131 | { 132 | Name = diagramTemplate.Name, 133 | }; 134 | csvLayoutList.Add(rec); 135 | } 136 | } 137 | 138 | foreach (CSVLayout row in csvLayoutList.OrderBy(x => x.Name)) 139 | { 140 | string output = Common.ExtractClassValuesToString(row, properties); 141 | sw.WriteLine(output); 142 | } 143 | 144 | sw.Flush(); 145 | sw.Close(); 146 | } 147 | } 148 | } 149 | }); 150 | } 151 | 152 | private class CSVLayout 153 | { 154 | public string DiagramTemplate { get; set; } 155 | public string Name { get; set; } 156 | public string CreationDate { get; set; } 157 | public string LastModifiedTime { get; set; } 158 | public string DiagramStorage { get; set; } 159 | public string IsSystem { get; set; } 160 | public string ExtendDiagram { get; set; } 161 | public string Description { get; set; } 162 | } 163 | } 164 | } -------------------------------------------------------------------------------- /UtilityNetworkPropertiesExtractor/NoNetworkRulesButton.cs: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021 Esri 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | http://www.apache.org/licenses/LICENSE-2.0 7 | Unless required by applicable law or agreed to in writing, software 8 | distributed under the License is distributed on an "AS IS" BASIS, 9 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10 | See the License for the specific language governing permissions and 11 | limitations under the License. 12 | */ 13 | using ArcGIS.Core.Data; 14 | using ArcGIS.Core.Data.UtilityNetwork; 15 | using ArcGIS.Desktop.Framework.Contracts; 16 | using ArcGIS.Desktop.Framework.Threading.Tasks; 17 | using System; 18 | using System.Collections.Generic; 19 | using System.IO; 20 | using System.Reflection; 21 | using System.Threading.Tasks; 22 | using System.Windows; 23 | using MessageBox = System.Windows.MessageBox; 24 | 25 | namespace UtilityNetworkPropertiesExtractor 26 | { 27 | internal class NoNetworkRulesButton : Button 28 | { 29 | protected async override void OnClick() 30 | { 31 | Common.CreateOutputDirectory(); 32 | ProgressDialog progDlg = new ProgressDialog("Extracting No Network Rules to: \n" + Common.ExtractFilePath); 33 | 34 | try 35 | { 36 | progDlg.Show(); 37 | await ExtractNoNetworkRulesAsync(true); 38 | } 39 | catch (Exception ex) 40 | { 41 | MessageBox.Show(ex.Message, "Extract No Network Rules"); 42 | } 43 | finally 44 | { 45 | progDlg.Dispose(); 46 | } 47 | } 48 | 49 | public static Task ExtractNoNetworkRulesAsync(bool showNoUtilityNetworkPrompt) 50 | { 51 | return QueuedTask.Run(() => 52 | { 53 | List utilityNetworkDataSourceInMapList = DataSourcesInMapHelper.GetUtilityNetworkDataSourcesInMap(); 54 | if (utilityNetworkDataSourceInMapList.Count == 0) 55 | { 56 | if (showNoUtilityNetworkPrompt) 57 | MessageBox.Show("A Utility Network was not found in the active map", "Extract No Network Rules", MessageBoxButton.OK, MessageBoxImage.Error); 58 | 59 | return; 60 | } 61 | 62 | foreach (UtilityNetworkDataSourceInMap utilityNetworkDataSourceInMap in utilityNetworkDataSourceInMapList) 63 | { 64 | using (Geodatabase geodatabase = utilityNetworkDataSourceInMap.Geodatabase) 65 | { 66 | string outputFile = Common.BuildCsvName("NoNetworkRules", utilityNetworkDataSourceInMap.Name); 67 | using (StreamWriter sw = new StreamWriter(outputFile)) 68 | { 69 | //Header information 70 | UtilityNetworkDefinition utilityNetworkDefinition = utilityNetworkDataSourceInMap.UtilityNetwork.GetDefinition(); 71 | Common.WriteHeaderInfoForUtilityNetwork(sw, utilityNetworkDataSourceInMap, "No Network Rule Assignments"); 72 | 73 | List csvLayoutList = new List(); 74 | 75 | //Get all properties defined in the class. This will be used to generate the CSV file 76 | CSVLayout emptyRec = new CSVLayout(); 77 | PropertyInfo[] properties = Common.GetPropertiesOfClass(emptyRec); 78 | 79 | //Write column headers based on properties in the class 80 | string columnHeader = Common.ExtractClassPropertyNamesToString(properties); 81 | sw.WriteLine(columnHeader); ; 82 | 83 | IReadOnlyList allRules = utilityNetworkDefinition.GetRules(); 84 | IReadOnlyList networkSourceList = utilityNetworkDefinition.GetNetworkSources(); 85 | foreach (NetworkSource networkSource in networkSourceList) 86 | { 87 | IReadOnlyList assetGroupList = networkSource.GetAssetGroups(); 88 | foreach (AssetGroup assetGroup in assetGroupList) 89 | { 90 | //Asset Types 91 | IReadOnlyList assetTypeList = assetGroup.GetAssetTypes(); 92 | foreach (AssetType assetType in assetTypeList) 93 | { 94 | if (!AreRulesAssigned(networkSource.ID, assetGroup.Code, assetType.Code, allRules)) 95 | { 96 | CSVLayout rec = new CSVLayout() 97 | { 98 | ClassName = networkSource.Name, 99 | AssetGroupCode = assetGroup.Code.ToString(), 100 | AssetGroup = assetGroup.Name, 101 | AssetTypeCode = assetType.Code.ToString(), 102 | AssetType = assetType.Name 103 | }; 104 | csvLayoutList.Add(rec); 105 | } 106 | } 107 | } 108 | } 109 | 110 | //Write body 111 | foreach (CSVLayout row in csvLayoutList) 112 | { 113 | string output = Common.ExtractClassValuesToString(row, properties); 114 | sw.WriteLine(output); 115 | } 116 | 117 | sw.Flush(); 118 | sw.Close(); 119 | } 120 | } 121 | } 122 | }); 123 | } 124 | 125 | private static bool AreRulesAssigned(int networkSourceID, int assetGroup, int assetType, IReadOnlyList allRules) 126 | { 127 | //Return true if at least 1 network rule is assigned 128 | foreach (Rule rule in allRules) 129 | { 130 | if (rule.RuleElements[0].NetworkSource.ID == networkSourceID) 131 | { 132 | if (rule.RuleElements[0].AssetGroup.Code == assetGroup && rule.RuleElements[0].AssetType.Code == assetType) 133 | return true; 134 | } 135 | else if (rule.RuleElements[1].NetworkSource.ID == networkSourceID) 136 | { 137 | if (rule.RuleElements[1].AssetGroup.Code == assetGroup && rule.RuleElements[1].AssetType.Code == assetType) 138 | return true; 139 | } 140 | } 141 | return false; 142 | } 143 | 144 | private class CSVLayout 145 | { 146 | public string ClassName { get; set; } 147 | public string AssetGroupCode { get; set; } 148 | public string AssetGroup { get; set; } 149 | public string AssetTypeCode { get; set; } 150 | public string AssetType { get; set; } 151 | } 152 | } 153 | } -------------------------------------------------------------------------------- /UtilityNetworkPropertiesExtractor/ProjectItemsButton.cs: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021 Esri 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | http://www.apache.org/licenses/LICENSE-2.0 7 | Unless required by applicable law or agreed to in writing, software 8 | distributed under the License is distributed on an "AS IS" BASIS, 9 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10 | See the License for the specific language governing permissions and 11 | limitations under the License. 12 | */ 13 | using ArcGIS.Desktop.Core; 14 | using ArcGIS.Desktop.Framework.Threading.Tasks; 15 | using System; 16 | using System.Collections.Generic; 17 | using System.IO; 18 | using System.Linq; 19 | using System.Reflection; 20 | using Button = ArcGIS.Desktop.Framework.Contracts.Button; 21 | using MessageBox = System.Windows.Forms.MessageBox; 22 | 23 | namespace UtilityNetworkPropertiesExtractor 24 | { 25 | internal class ProjectItemsButton : Button 26 | { 27 | protected override void OnClick() 28 | { 29 | Common.CreateOutputDirectory(); 30 | ProgressDialog progDlg = new ProgressDialog("Extracting Project Items to: \n" + Common.ExtractFilePath); 31 | 32 | try 33 | { 34 | progDlg.Show(); 35 | ExtractProjectItem(); 36 | } 37 | catch (Exception ex) 38 | { 39 | MessageBox.Show(ex.Message, "Extract Project Items"); 40 | } 41 | finally 42 | { 43 | progDlg.Dispose(); 44 | } 45 | } 46 | 47 | public static void ExtractProjectItem() 48 | { 49 | Common.CreateOutputDirectory(); 50 | 51 | string outputFile = Common.BuildCsvNameContainingMapName("ProjectItems"); 52 | using (StreamWriter sw = new StreamWriter(outputFile)) 53 | { 54 | sw.WriteLine(DateTime.Now + "," + "Project Items"); 55 | sw.WriteLine(); 56 | sw.WriteLine("Project," + Project.Current.Path); 57 | sw.WriteLine(); 58 | 59 | List csvLayoutList = new List(); 60 | 61 | //Get all properties defined in the class. This will be used to generate the CSV file 62 | CSVLayout emptyRec = new CSVLayout(); 63 | PropertyInfo[] properties = Common.GetPropertiesOfClass(emptyRec); 64 | 65 | //Write column headers based on properties in the class 66 | string columnHeader = Common.ExtractClassPropertyNamesToString(properties); 67 | sw.WriteLine(columnHeader); 68 | 69 | IEnumerable items = Project.Current.GetItems(); 70 | foreach (Item item in items) 71 | { 72 | CSVLayout rec = new CSVLayout() 73 | { 74 | ItemType = item.Type, 75 | ItemName = item.Name, 76 | Description = Common.EncloseStringInDoubleQuotes(item.Description) 77 | }; 78 | 79 | csvLayoutList.Add(rec); 80 | } 81 | 82 | //Write body of report 83 | foreach (CSVLayout row in csvLayoutList.OrderBy(x => x.ItemType).ThenBy(x => x.ItemName)) 84 | { 85 | string output = Common.ExtractClassValuesToString(row, properties); 86 | sw.WriteLine(output); 87 | } 88 | 89 | sw.Flush(); 90 | sw.Close(); 91 | } 92 | } 93 | 94 | private class CSVLayout 95 | { 96 | public string ItemType { get; set; } 97 | public string ItemName { get; set; } 98 | public string Description { get; set; } 99 | } 100 | } 101 | } -------------------------------------------------------------------------------- /UtilityNetworkPropertiesExtractor/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("UtilityNetworkPropertiesExtractor")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("Acme")] 12 | [assembly: AssemblyProduct("UtilityNetworkPropertiesExtractor")] 13 | [assembly: AssemblyCopyright("Copyright © Acme 2021")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("6aa85a02-e8ed-4abd-bb53-a38424c747bc")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /UtilityNetworkPropertiesExtractor/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "profiles": { 3 | "UtilityNetworkPropertiesExtractor": { 4 | "commandName": "Executable", 5 | "executablePath": "C:\\Program Files\\ArcGIS\\Pro\\bin\\ArcGISPro.exe", 6 | "commandLineArgs": "" 7 | } 8 | } 9 | } -------------------------------------------------------------------------------- /UtilityNetworkPropertiesExtractor/RelationshipClassButton.cs: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021 Esri 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | http://www.apache.org/licenses/LICENSE-2.0 7 | Unless required by applicable law or agreed to in writing, software 8 | distributed under the License is distributed on an "AS IS" BASIS, 9 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10 | See the License for the specific language governing permissions and 11 | limitations under the License. 12 | */ 13 | using ArcGIS.Core.CIM; 14 | using ArcGIS.Core.Data; 15 | using ArcGIS.Desktop.Framework.Contracts; 16 | using ArcGIS.Desktop.Framework.Threading.Tasks; 17 | using System; 18 | using System.Collections.Generic; 19 | using System.IO; 20 | using System.Linq; 21 | using System.Reflection; 22 | using System.Threading.Tasks; 23 | using MessageBox = System.Windows.MessageBox; 24 | 25 | namespace UtilityNetworkPropertiesExtractor 26 | { 27 | internal class RelationshipClassButton : Button 28 | { 29 | protected async override void OnClick() 30 | { 31 | Common.CreateOutputDirectory(); 32 | ProgressDialog progDlg = new ProgressDialog("Extracting Relationship Classes to: \n" + Common.ExtractFilePath); 33 | 34 | try 35 | { 36 | progDlg.Show(); 37 | await ExtractRelationshipClassesAsync(); 38 | } 39 | catch (Exception ex) 40 | { 41 | MessageBox.Show(ex.Message, "Extracting Relationship Classes"); 42 | } 43 | finally 44 | { 45 | progDlg.Dispose(); 46 | } 47 | } 48 | 49 | public static Task ExtractRelationshipClassesAsync() 50 | { 51 | return QueuedTask.Run(() => 52 | { 53 | List dataSourceInMapList = DataSourcesInMapHelper.GetDataSourcesInMap(); 54 | foreach (DataSourceInMap dataSourceInMap in dataSourceInMapList) 55 | { 56 | if (dataSourceInMap.WorkspaceFactory != WorkspaceFactory.Shapefile.ToString()) 57 | { 58 | using (Geodatabase geodatabase = dataSourceInMap.Geodatabase) 59 | { 60 | string outputFile = Common.BuildCsvName("RelationshipClasses", dataSourceInMap.Name); 61 | using (StreamWriter sw = new StreamWriter(outputFile)) 62 | { 63 | //Header information 64 | IReadOnlyList relateDefList = geodatabase.GetDefinitions(); 65 | Common.WriteHeaderInfoForGeodatabase(sw, dataSourceInMap, "Relationship Classes"); 66 | sw.WriteLine("Relationship Class Count," + relateDefList.Count); 67 | sw.WriteLine(); 68 | 69 | //Get all properties defined in the class. This will be used to generate the CSV file 70 | CSVLayout emptyRec = new CSVLayout(); 71 | PropertyInfo[] properties = Common.GetPropertiesOfClass(emptyRec); 72 | 73 | //Write column headers based on properties in the class 74 | string columnHeader = Common.ExtractClassPropertyNamesToString(properties); 75 | sw.WriteLine(columnHeader); 76 | 77 | List csvLayoutList = new List(); 78 | 79 | foreach (RelationshipClassDefinition relateDef in relateDefList) 80 | { 81 | CSVLayout rec = new CSVLayout() 82 | { 83 | RelationshipClass = relateDef.GetName(), 84 | Cardinality = relateDef.GetCardinality().ToString(), 85 | OriginName = relateDef.GetOriginClass(), 86 | OriginPrimaryKey = relateDef.GetOriginKeyField(), 87 | OriginForeignKey = relateDef.GetOriginForeignKeyField(), 88 | DestinationName = relateDef.GetDestinationClass(), 89 | SplitPolicy = relateDef.GetRelationshipSplitPolicy().ToString(), 90 | AttachmentRelationship = relateDef.IsAttachmentRelationship().ToString(), 91 | IsComposite = relateDef.IsComposite().ToString() 92 | }; 93 | csvLayoutList.Add(rec); 94 | } 95 | 96 | //Write body of CSV 97 | foreach (CSVLayout row in csvLayoutList.OrderBy(x => x.RelationshipClass)) 98 | { 99 | string output = Common.ExtractClassValuesToString(row, properties); 100 | sw.WriteLine(output); 101 | } 102 | } 103 | } 104 | } 105 | } 106 | }); 107 | } 108 | 109 | private class CSVLayout 110 | { 111 | public string RelationshipClass { get; set; } 112 | public string Cardinality { get; set; } 113 | public string OriginName { get; set; } 114 | public string OriginPrimaryKey { get; set; } 115 | public string OriginForeignKey { get; set; } 116 | public string DestinationName { get; set; } 117 | public string SplitPolicy { get; set; } 118 | public string AttachmentRelationship { get; set; } 119 | public string IsComposite { get; set; } 120 | } 121 | } 122 | } -------------------------------------------------------------------------------- /UtilityNetworkPropertiesExtractor/TerminalConfigurationButton.cs: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021 Esri 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | http://www.apache.org/licenses/LICENSE-2.0 7 | Unless required by applicable law or agreed to in writing, software 8 | distributed under the License is distributed on an "AS IS" BASIS, 9 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10 | See the License for the specific language governing permissions and 11 | limitations under the License. 12 | */ 13 | using ArcGIS.Core.Data; 14 | using ArcGIS.Core.Data.UtilityNetwork; 15 | using ArcGIS.Desktop.Framework.Contracts; 16 | using ArcGIS.Desktop.Framework.Threading.Tasks; 17 | using System; 18 | using System.Collections.Generic; 19 | using System.IO; 20 | using System.Linq; 21 | using System.Reflection; 22 | using System.Threading.Tasks; 23 | using System.Windows; 24 | using MessageBox = System.Windows.MessageBox; 25 | 26 | namespace UtilityNetworkPropertiesExtractor 27 | { 28 | internal class TerminalConfigurationButton : Button 29 | { 30 | protected async override void OnClick() 31 | { 32 | Common.CreateOutputDirectory(); 33 | ProgressDialog progDlg = new ProgressDialog("Extracting Terminal Configuration to: \n" + Common.ExtractFilePath); 34 | 35 | try 36 | { 37 | progDlg.Show(); 38 | await ExtractTerminalConfigurationAsync(true); 39 | } 40 | catch (Exception ex) 41 | { 42 | MessageBox.Show(ex.Message, "Extract Terminal Configuration"); 43 | } 44 | finally 45 | { 46 | progDlg.Dispose(); 47 | } 48 | } 49 | public static Task ExtractTerminalConfigurationAsync(bool showNoUtilityNetworkPrompt) 50 | { 51 | return QueuedTask.Run(() => 52 | { 53 | List utilityNetworkDataSourceInMapList = DataSourcesInMapHelper.GetUtilityNetworkDataSourcesInMap(); 54 | if (utilityNetworkDataSourceInMapList.Count == 0) 55 | { 56 | if (showNoUtilityNetworkPrompt) 57 | MessageBox.Show("A Utility Network was not found in the active map", "Extract Terminal Configuration", MessageBoxButton.OK, MessageBoxImage.Error); 58 | 59 | return; 60 | } 61 | 62 | foreach (UtilityNetworkDataSourceInMap utilityNetworkDataSourceInMap in utilityNetworkDataSourceInMapList) 63 | { 64 | using (Geodatabase geodatabase = utilityNetworkDataSourceInMap.Geodatabase) 65 | { 66 | string outputFile = Common.BuildCsvName("TerminalConfig", utilityNetworkDataSourceInMap.Name); 67 | using (StreamWriter sw = new StreamWriter(outputFile)) 68 | { 69 | //Header information 70 | UtilityNetworkDefinition utilityNetworkDefinition = utilityNetworkDataSourceInMap.UtilityNetwork.GetDefinition(); 71 | Common.WriteHeaderInfoForUtilityNetwork(sw, utilityNetworkDataSourceInMap, "Terminal Configuration"); 72 | 73 | List csvLayoutList = new List(); 74 | 75 | //Get all properties defined in the class. This will be used to generate the CSV file 76 | CSVLayout emptyRec = new CSVLayout(); 77 | PropertyInfo[] properties = Common.GetPropertiesOfClass(emptyRec); 78 | 79 | //Write column headers based on properties in the class 80 | string columnHeader = Common.ExtractClassPropertyNamesToString(properties); 81 | sw.WriteLine(columnHeader); 82 | 83 | IEnumerable terminalConfigList = utilityNetworkDefinition.GetTerminalConfigurations().OrderBy(x => x.Name); 84 | foreach (TerminalConfiguration terminalConfig in terminalConfigList) 85 | { 86 | CSVLayout rec = new CSVLayout() 87 | { 88 | Name = terminalConfig.Name, 89 | DirectionalityModel = terminalConfig.Directionality.ToString() 90 | }; 91 | csvLayoutList.Add(rec); 92 | 93 | IReadOnlyList terminals = terminalConfig.Terminals; 94 | foreach (Terminal terminal in terminals) 95 | { 96 | rec = new CSVLayout() 97 | { 98 | ID = terminal.ID.ToString(), 99 | TerminalName = terminal.Name, 100 | UpstreamTerminal = terminal.IsUpstreamTerminal.ToString() 101 | }; 102 | csvLayoutList.Add(rec); 103 | } 104 | 105 | // add blank line 106 | csvLayoutList.Add(emptyRec); 107 | } 108 | 109 | //Write body 110 | foreach (CSVLayout row in csvLayoutList) 111 | { 112 | string output = Common.ExtractClassValuesToString(row, properties); 113 | sw.WriteLine(output); 114 | } 115 | 116 | sw.Flush(); 117 | sw.Close(); 118 | } 119 | } 120 | } 121 | }); 122 | } 123 | 124 | private class CSVLayout 125 | { 126 | public string Name { get; set; } 127 | public string DirectionalityModel { get; set; } 128 | public string ID { get; set; } 129 | public string TerminalName { get; set; } 130 | public string UpstreamTerminal { get; set; } 131 | } 132 | } 133 | } -------------------------------------------------------------------------------- /UtilityNetworkPropertiesExtractor/UtilityNetworkPropertiesExtractor.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net8.0-windows7.0 5 | win10-x64 6 | false 7 | true 8 | false 9 | CA1416 10 | true 11 | true 12 | 13 | 14 | 15 | 16 | 17 | 18 | C:\Program Files\ArcGIS\Pro\bin\ArcGIS.Desktop.Framework.dll 19 | False 20 | False 21 | 22 | 23 | C:\Program Files\ArcGIS\Pro\bin\ArcGIS.Core.dll 24 | False 25 | False 26 | 27 | 28 | C:\Program Files\ArcGIS\Pro\bin\Extensions\Core\ArcGIS.Desktop.Core.dll 29 | False 30 | False 31 | 32 | 33 | C:\Program Files\ArcGIS\Pro\bin\Extensions\Mapping\ArcGIS.Desktop.Mapping.dll 34 | False 35 | False 36 | 37 | 38 | C:\Program Files\ArcGIS\Pro\bin\Extensions\Catalog\ArcGIS.Desktop.Catalog.dll 39 | False 40 | False 41 | 42 | 43 | C:\Program Files\ArcGIS\Pro\bin\Extensions\Editing\ArcGIS.Desktop.Editing.dll 44 | False 45 | False 46 | 47 | 48 | C:\Program Files\ArcGIS\Pro\bin\Extensions\DesktopExtensions\ArcGIS.Desktop.Extensions.dll 49 | False 50 | False 51 | 52 | 53 | C:\Program Files\ArcGIS\Pro\bin\Extensions\GeoProcessing\ArcGIS.Desktop.GeoProcessing.dll 54 | False 55 | False 56 | 57 | 58 | C:\Program Files\ArcGIS\Pro\bin\Extensions\Layout\ArcGIS.Desktop.Layouts.dll 59 | False 60 | False 61 | 62 | 63 | C:\Program Files\ArcGIS\Pro\bin\ArcGIS.Desktop.Shared.Wpf.dll 64 | False 65 | False 66 | 67 | 68 | C:\Program Files\ArcGIS\Pro\bin\ArcGIS.Desktop.Ribbon.Wpf.dll 69 | False 70 | False 71 | 72 | 73 | C:\Program Files\ArcGIS\Pro\bin\ArcGIS.Desktop.DataGrid.Contrib.Wpf.dll 74 | False 75 | False 76 | 77 | 78 | C:\Program Files\ArcGIS\Pro\bin\ArcGIS.Desktop.Resources.dll 79 | False 80 | False 81 | 82 | 83 | C:\Program Files\ArcGIS\Pro\bin\ArcGIS.Desktop.Resources.dll 84 | False 85 | False 86 | 87 | 88 | C:\Program Files\ArcGIS\Pro\bin\ESRI.ArcGIS.ItemIndex.dll 89 | False 90 | False 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | -------------------------------------------------------------------------------- /UtilityNetworkPropertiesExtractor/UtilityNetworkPropertiesExtractor.csproj.bak: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Debug 5 | AnyCPU 6 | 8.0.30703 7 | 2.0 8 | {6AA85A02-E8ED-4ABD-BB53-A38424C747BC} 9 | Library 10 | Properties 11 | UtilityNetworkPropertiesExtractor 12 | UtilityNetworkPropertiesExtractor 13 | v4.8 14 | 512 15 | {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} 16 | 17 | 18 | true 19 | full 20 | false 21 | bin\Debug\ 22 | DEBUG;TRACE 23 | prompt 24 | 4 25 | Program 26 | C:\Program Files\ArcGIS\Pro\bin\ArcGISPro.exe 27 | x64 28 | 29 | 30 | pdbonly 31 | true 32 | bin\Release\ 33 | TRACE 34 | prompt 35 | 4 36 | Program 37 | C:\Program Files\ArcGIS\Pro\bin\ArcGISPro.exe 38 | AnyCPU 39 | 40 | 41 | $([MSBuild]::GetRegistryValueFromView('HKEY_LOCAL_MACHINE\SOFTWARE\ESRI\ArcGISPro', 'InstallDir', null, RegistryView.Registry64)) 42 | $(registry:HKEY_CURRENT_USER\SOFTWARE\ESRI\ArcGISPro@InstallDir) 43 | 44 | 45 | 46 | packages\Newtonsoft.Json.13.0.1\lib\net45\Newtonsoft.Json.dll 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | C:\Program Files\ArcGIS\Pro\bin\ArcGIS.Desktop.Framework.dll 65 | False 66 | 67 | 68 | C:\Program Files\ArcGIS\Pro\bin\ArcGIS.Core.dll 69 | False 70 | 71 | 72 | C:\Program Files\ArcGIS\Pro\bin\Extensions\Core\ArcGIS.Desktop.Core.dll 73 | False 74 | 75 | 76 | C:\Program Files\ArcGIS\Pro\bin\Extensions\Mapping\ArcGIS.Desktop.Mapping.dll 77 | False 78 | 79 | 80 | C:\Program Files\ArcGIS\Pro\bin\Extensions\Catalog\ArcGIS.Desktop.Catalog.dll 81 | False 82 | 83 | 84 | C:\Program Files\ArcGIS\Pro\bin\Extensions\Editing\ArcGIS.Desktop.Editing.dll 85 | False 86 | 87 | 88 | C:\Program Files\ArcGIS\Pro\bin\Extensions\DesktopExtensions\ArcGIS.Desktop.Extensions.dll 89 | False 90 | 91 | 92 | C:\Program Files\ArcGIS\Pro\bin\Extensions\GeoProcessing\ArcGIS.Desktop.GeoProcessing.dll 93 | False 94 | 95 | 96 | C:\Program Files\ArcGIS\Pro\bin\Extensions\Layout\ArcGIS.Desktop.Layouts.dll 97 | False 98 | 99 | 100 | C:\Program Files\ArcGIS\Pro\bin\ArcGIS.Desktop.Shared.Wpf.dll 101 | False 102 | 103 | 104 | C:\Program Files\ArcGIS\Pro\bin\ArcGIS.Desktop.Ribbon.Wpf.dll 105 | False 106 | 107 | 108 | C:\Program Files\ArcGIS\Pro\bin\ArcGIS.Desktop.DataGrid.Contrib.Wpf.dll 109 | False 110 | 111 | 112 | C:\Program Files\ArcGIS\Pro\bin\ArcGIS.Desktop.Resources.dll 113 | False 114 | 115 | 116 | C:\Program Files\ArcGIS\Pro\bin\ArcGIS.Desktop.Resources.dll 117 | False 118 | 119 | 120 | C:\Program Files\ArcGIS\Pro\bin\ESRI.ArcGIS.ItemIndex.dll 121 | False 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 180 | 181 | BuildDefault 182 | 183 | 184 | BuildDefault 185 | 186 | 187 | 188 | 189 | 190 | 191 | 198 | 201 | -------------------------------------------------------------------------------- /UtilityNetworkPropertiesExtractor/UtilityNetworkPropertiesExtractor.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.31205.134 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UtilityNetworkPropertiesExtractor", "UtilityNetworkPropertiesExtractor.csproj", "{6AA85A02-E8ED-4ABD-BB53-A38424C747BC}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {6AA85A02-E8ED-4ABD-BB53-A38424C747BC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {6AA85A02-E8ED-4ABD-BB53-A38424C747BC}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {6AA85A02-E8ED-4ABD-BB53-A38424C747BC}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {6AA85A02-E8ED-4ABD-BB53-A38424C747BC}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {3061E0DC-454F-4C9B-A565-16844BCE441C} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /UtilityNetworkPropertiesExtractor/VersionInfoButton.cs: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021 Esri 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | http://www.apache.org/licenses/LICENSE-2.0 7 | Unless required by applicable law or agreed to in writing, software 8 | distributed under the License is distributed on an "AS IS" BASIS, 9 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10 | See the License for the specific language governing permissions and 11 | limitations under the License. 12 | */ 13 | using ArcGIS.Core.CIM; 14 | using ArcGIS.Core.Data; 15 | using ArcGIS.Desktop.Framework.Contracts; 16 | using ArcGIS.Desktop.Framework.Threading.Tasks; 17 | using System; 18 | using System.Collections.Generic; 19 | using System.IO; 20 | using System.Reflection; 21 | using System.Threading.Tasks; 22 | using MessageBox = System.Windows.MessageBox; 23 | 24 | namespace UtilityNetworkPropertiesExtractor 25 | { 26 | internal class VersionInfoButton : Button 27 | { 28 | protected async override void OnClick() 29 | { 30 | Common.CreateOutputDirectory(); 31 | ProgressDialog progDlg = new ProgressDialog("Extracting Version Info to:\n" + Common.ExtractFilePath); 32 | 33 | try 34 | { 35 | progDlg.Show(); 36 | await ExtractVersionInfoAsync(); 37 | } 38 | catch (Exception ex) 39 | { 40 | MessageBox.Show(ex.Message, "Extract Version Info"); 41 | } 42 | finally 43 | { 44 | progDlg.Dispose(); 45 | } 46 | } 47 | 48 | public static Task ExtractVersionInfoAsync() 49 | { 50 | return QueuedTask.Run(() => 51 | { 52 | List dataSourceInMapList = DataSourcesInMapHelper.GetDataSourcesInMap(); 53 | foreach (DataSourceInMap dataSourceInMap in dataSourceInMapList) 54 | { 55 | if (dataSourceInMap.WorkspaceFactory != WorkspaceFactory.Shapefile.ToString()) 56 | { 57 | using (Geodatabase geodatabase = dataSourceInMap.Geodatabase) 58 | { 59 | if (! geodatabase.IsVersioningSupported()) 60 | continue; //move onto next geodatabase 61 | 62 | string outputFile = Common.BuildCsvName("Versions", dataSourceInMap.Name); 63 | using (StreamWriter sw = new StreamWriter(outputFile)) 64 | { 65 | //Header information 66 | Common.WriteHeaderInfoForGeodatabase(sw, dataSourceInMap, "Versions"); 67 | 68 | //Branch versions are only available in the Featureservice in which they were created. 69 | //https://pro.arcgis.com/en/pro-app/2.9/help/data/geodatabases/overview/manage-branch-versions.htm 70 | if (dataSourceInMap.WorkspaceFactory == WorkspaceFactory.SDE.ToString()) 71 | { 72 | sw.WriteLine("Branch Versions can't be accessed via a database connection"); 73 | continue; 74 | } 75 | 76 | List csvLayoutList = new List(); 77 | 78 | //Get all properties defined in the class. This will be used to generate the CSV file 79 | CSVLayout emptyRec = new CSVLayout(); 80 | PropertyInfo[] properties = Common.GetPropertiesOfClass(emptyRec); 81 | 82 | using (VersionManager versionManager = geodatabase.GetVersionManager()) 83 | { 84 | string owner = string.Empty; 85 | string name = string.Empty; 86 | string parentOwner = string.Empty; 87 | string parentName = string.Empty; 88 | 89 | //Get listings of all version names 90 | IReadOnlyList versionNamesList = versionManager.GetVersionNames(); 91 | 92 | sw.WriteLine("Versioning Type," + versionManager.GetVersioningType().ToString()); 93 | sw.WriteLine("Version Count," + versionNamesList.Count); 94 | sw.WriteLine(); 95 | 96 | //Write column headers based on properties in the class 97 | string columnHeader = Common.ExtractClassPropertyNamesToString(properties); 98 | sw.WriteLine(columnHeader); ; 99 | 100 | int i = 0; 101 | foreach (string versionName in versionNamesList) 102 | { 103 | ArcGIS.Core.Data.Version version = versionManager.GetVersion(versionName); 104 | 105 | //Parse version 106 | ParseVersion(version, out owner, out name); 107 | 108 | //Parse Parent (if exists) 109 | if (!string.IsNullOrEmpty(version.GetParent()?.GetName())) 110 | ParseVersion(version.GetParent(), out parentOwner, out parentName); 111 | 112 | i++; 113 | 114 | CSVLayout rec = new CSVLayout() 115 | { 116 | ID = i.ToString(), 117 | Name = name, 118 | Owner = owner, 119 | ParentName = parentName, 120 | ParentOwner = parentOwner, 121 | Description = Common.EncloseStringInDoubleQuotes(version.GetDescription()), 122 | Access = version.GetAccessType().ToString(), 123 | Created = version.GetCreatedDate().ToString(), 124 | Modified = version.GetModifiedDate().ToString() 125 | }; 126 | 127 | 128 | if (! version.GetName().ToUpper().Equals("SDE.DEFAULT")) 129 | rec.HasConflicts = version.HasConflicts().ToString(); 130 | 131 | csvLayoutList.Add(rec); 132 | 133 | //if traditional versioning, list out child versions 134 | if (versionManager.GetVersioningType() == VersionType.Traditional) 135 | { 136 | IReadOnlyList childList = version.GetChildren(); 137 | foreach (ArcGIS.Core.Data.Version child in childList) 138 | { 139 | CSVLayout childRec = new CSVLayout() 140 | { 141 | ChildVersions = child.GetName() 142 | }; 143 | 144 | csvLayoutList.Add(childRec); 145 | } 146 | } 147 | 148 | parentOwner = string.Empty; 149 | parentName = string.Empty; 150 | } 151 | } 152 | 153 | foreach (CSVLayout row in csvLayoutList) 154 | { 155 | string output = Common.ExtractClassValuesToString(row, properties); 156 | sw.WriteLine(output); 157 | } 158 | 159 | sw.Flush(); 160 | sw.Close(); 161 | } 162 | } 163 | } 164 | } 165 | }); 166 | } 167 | 168 | private static void ParseVersion(ArcGIS.Core.Data.Version version, out string owner, out string name) 169 | { 170 | int pos = version.GetName().LastIndexOf('.'); 171 | owner = version.GetName().Substring(0, pos); 172 | name = version.GetName().Substring(pos + 1); 173 | } 174 | 175 | private class CSVLayout 176 | { 177 | public string ID { get; set; } 178 | public string Name { get; set; } 179 | public string Owner { get; set; } 180 | public string ParentName { get; set; } 181 | public string ParentOwner { get; set; } 182 | public string Description { get; set; } 183 | public string Access { get; set; } 184 | public string HasConflicts { get; set; } 185 | public string Created { get; set; } 186 | public string Modified { get; set; } 187 | public string ChildVersions { get; set; } 188 | } 189 | } 190 | } -------------------------------------------------------------------------------- /UtilityNetworkPropertiesExtractor/obj/Debug/.NETFramework,Version=v4.8.AssemblyAttributes.cs: -------------------------------------------------------------------------------- 1 | // 2 | using System; 3 | using System.Reflection; 4 | [assembly: global::System.Runtime.Versioning.TargetFrameworkAttribute(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] 5 | -------------------------------------------------------------------------------- /UtilityNetworkPropertiesExtractor/obj/Debug/DesignTimeResolveAssemblyReferencesInput.cache: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Esri/utility-network-properties-extractor/5f5b769bc5e4dba64e782683b3aea8da27f6c04b/UtilityNetworkPropertiesExtractor/obj/Debug/DesignTimeResolveAssemblyReferencesInput.cache -------------------------------------------------------------------------------- /UtilityNetworkPropertiesExtractor/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /contributing.md: -------------------------------------------------------------------------------- 1 | Esri welcomes contributions from anyone and everyone. Please see our [guidelines for contributing](https://github.com/esri/contributing). 2 | -------------------------------------------------------------------------------- /license.txt: -------------------------------------------------------------------------------- 1 | Apache License - 2.0 2 | 3 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 4 | 5 | 1. Definitions. 6 | 7 | "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. 8 | 9 | "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. 10 | 11 | "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control 12 | with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management 13 | of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial 14 | ownership of such entity. 15 | 16 | "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. 17 | 18 | "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, 19 | and configuration files. 20 | 21 | "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to 22 | compiled object code, generated documentation, and conversions to other media types. 23 | 24 | "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice 25 | that is included in or attached to the work (an example is provided in the Appendix below). 26 | 27 | "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the 28 | editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes 29 | of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, 30 | the Work and Derivative Works thereof. 31 | 32 | "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work 33 | or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual 34 | or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of 35 | electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on 36 | electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for 37 | the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing 38 | by the copyright owner as "Not a Contribution." 39 | 40 | "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and 41 | subsequently incorporated within the Work. 42 | 43 | 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, 44 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, 45 | publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 46 | 47 | 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, 48 | non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, 49 | sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are 50 | necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was 51 | submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work 52 | or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You 53 | under this License for that Work shall terminate as of the date such litigation is filed. 54 | 55 | 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, 56 | and in Source or Object form, provided that You meet the following conditions: 57 | 58 | 1. You must give any other recipients of the Work or Derivative Works a copy of this License; and 59 | 60 | 2. You must cause any modified files to carry prominent notices stating that You changed the files; and 61 | 62 | 3. You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices 63 | from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and 64 | 65 | 4. If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a 66 | readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the 67 | Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the 68 | Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever 69 | such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. 70 | You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, 71 | provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to 72 | Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your 73 | modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with 74 | the conditions stated in this License. 75 | 76 | 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You 77 | to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, 78 | nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 79 | 80 | 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except 81 | as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 82 | 83 | 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides 84 | its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, 85 | any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for 86 | determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under 87 | this License. 88 | 89 | 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required 90 | by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, 91 | including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the 92 | use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or 93 | any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 94 | 95 | 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a 96 | fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting 97 | such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree 98 | to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your 99 | accepting any such warranty or additional liability. 100 | 101 | END OF TERMS AND CONDITIONS 102 | --------------------------------------------------------------------------------