POST
|
Our organisation has recently started implementing Mobile Device Management using InTune on new devices as they are rolled out. This has cause us to hit a bit of a snag. Up to now, we have recommended that users take a Vector Tile Package that is generated by our GIS Team covering the state and sideload it to their device to streamline offline area downloads. This file is then referenced in the webmap settings to be used for offline areas. We don't use Mobile Map Packages or specify offline areas in Field Maps Designer, as our staff are too irregularly dispersed to manage it that way. Staff instead determine what areas they need offline when they need them. This has worked fine until now, where the MDM devices prohibit the user from sideloading our .vtpk onto their device (via USB connection to their PC). No file explorer option is available to them. Does anyone else have experience with this and possible solutions we can look at?
... View more
16 hours ago
|
1
|
1
|
95
|
BLOG
|
Hey @JesseCloutier , it looks like a part of the 2nd paragraph under the Staying True To “We Care for You” heading is incomplete.
... View more
yesterday
|
2
|
0
|
221
|
IDEA
|
When using Model Builder and generating data that is then output to a map using the Collect Values tool with the output set as a parameter, we can currently use the Import Symbology tool to import layer styling from a Layer File saved in an accessible location (i.e. on your machine or network). Whilst this is useful, most of the time I wish I could hard code the layer file into the model so that it's not reliant on a file sitting in a folder somewhere to style the outputs. If I could style a layer in a map with symbology, labels, etc then save a Layer File, instead of referencing that layer file in the model as an input, I would like to be able to Drag and Drop it as a standalone item with all it's information saved directly in the model. This would reduce the chance of the layer file being moved, deleted or modified unintentionally and thereforce impacting the output of the model.
... View more
Monday
|
1
|
0
|
86
|
POST
|
So not too long ago I learnt that the GetUser(fullName) expression always requires an internet connection to work. If used in an Offline map, it still pulls from the web (or tries to). If the device is in Flight Mode, it would fail. We implemented a work around for this to use GetUser(username) which does work offline. What I want to know is, are there other expressions that pull on the internet even when in an offline map? I would like to know so I can avoid using them if possible. I believe these to be causing issues with features returning calculated attributes when there isn't sufficient signal.
... View more
Thursday
|
0
|
0
|
159
|
POST
|
Yep - it's just the Network Analyst extension as you've shown. I do most of my python work using IDLE or within Pro itself. I've never used Jupyter Notebooks or Visual Studio Code.
... View more
a week ago
|
1
|
0
|
126
|
POST
|
I haven't used the Nearest Facility funciton so not sure if this is part of it, but there may be a search distance parameter that limits how far a point can be from a road before it is excluded. If it's beyond the set distance, no route is returned.
... View more
a week ago
|
0
|
0
|
105
|
POST
|
Are you using your own network or an Esri provided one? If it's your own, are you sure that there are valid conections all the way along it?
... View more
a week ago
|
0
|
2
|
118
|
POST
|
Assuming you have access to the Network Analyst extension that Dan has linked, you setup your Start and Finish points with Route Names. You need a start point to go with each corresponding finish point. Think of it like this - if you have Point A and you want to calculate routes to Points M, N & O, you need 3 copies of Point A, each with a unique Route Name that is also referenced by each finish point (i.e. Route A-M, A-N & A-O). When you run the Solve tool to calculate routes, it recognises those route names and calcs the route from A to N, then another for A-M and again for A-O. The same dataset could also then contain start points B, C, etc and other finish points, and as long as you have those start points copied and named to match each required finish location, it will only calculate those routes. It seems like a simple concept, but it took me a while to figure this out so, thought I'd share it. Below is an extract from a python code that generates the Start and Finish points based on 2 input datasets (the start points actually being polygons so you can see the dissolve and conversion steps added in to deal with this). The code goes on to solve the network too, but I haven't added that as I haven't got it running properly in an automated manner (which is how it is supposed to run). I have a model that does this too for users to use in ArcGIS Pro (what I used to build the below code in the first place). # Variables - update these lines
SDPRoutes = "Output feature service" # ArcGIS Online feature service containing routes to be updated
origins = r"\\path\to\input\origin\features" # Input feature class or table (can be .csv/.xls/.xlsx/etc.) or service URL of feature service in ArcGIS Online
destinations = "\\path\to\input\destination\features" # Input feature class or table (can be .csv/.xls/.xlsx/etc.) or service URL of feature service in ArcGIS Online
nd_path = r"\\path\to\network\dataset"
travelmode = "RAV 3"
import arcpy, time, os
from arcgis.gis import GIS
from arcgis.features import FeatureLayer
# Start Timer
startTime = time.time()
# Overwrite Output
arcpy.env.overwriteOutput = True
try:
arcpy.CheckOutExtension("Network")
print ("Network Analyst license checked-out")
# Create GIS object
print("Connecting to AGOL")
#...login to ArcGIS Online section omitted...
# Create temporary FGDB
sdproutesgdb = arcpy.CreateFileGDB_management(arcpy.env.scratchFolder, "sdproutes")
print ("Temp FGDB created")
arcpy.env.workspace = arcpy.env.scratchFolder + "\\sdproutes.gdb"
print ("Workspace set to temp FGDB")
#...checks of routes in existing dataset omitted...
# Prep Origin data
origins_temp = arcpy.conversion.ExportFeatures(
in_features = origins,
out_features = arcpy.env.workspace + "\\Origins_Temp",
where_clause = "PatchClass = 1 AND Map_Symbol = 'Softwood'",
use_field_alias_as_name = "NOT_USE_ALIAS",
field_mapping = ,
sort_field = None
)
print("Origins exported")
origins_dissolved = arcpy.management.Dissolve(
in_features = origins_temp,
out_feature_class = arcpy.env.workspace + "\\Origins_Dissolved",
dissolve_field = "Ops_Code",
statistics_fields = None,
multi_part = "MULTI_PART",
unsplit_lines = "DISSOLVE_LINES",
concatenation_separator = ""
)
print("Origins dissolved by Ops_Code")
origin_points = arcpy.management.FeatureToPoint(
in_features = origins_dissolved,
out_feature_class = arcpy.env.workspace + "\\Origin_Points",
point_location = "CENTROID"
)
print("Dissolved origins converted to points")
origin_points = arcpy.management.AddFields(
in_table = origin_points,
field_description = "Name TEXT # 500 # #;RouteName TEXT # 1024 # #;Sequence LONG # # # #",
template = None
)
print("Route fields added to Origin points")
origin_points = arcpy.management.CalculateField(
in_table = origin_points,
field = "Name",
expression = "!Ops_Code!",
expression_type = "PYTHON3",
code_block = "",
field_type = "TEXT",
enforce_domains = "NO_ENFORCE_DOMAINS"
)
print("Name field calculated")
origin_points = arcpy.management.CalculateField(
in_table = origin_points,
field = "Sequence",
expression = "1",
expression_type = "PYTHON3",
code_block = "",
field_type = "TEXT",
enforce_domains = "NO_ENFORCE_DOMAINS"
)
print("Sequence field calculated")
static_origins = arcpy.analysis.Select(
in_features = origin_points,
out_feature_class = arcpy.env.workspace + "\\Static_Origins",
where_clause = ""
)
print("Static Origin points generated")
# Prep Destination data
fl = FeatureLayer(destinations)
fs = fl.query(where = "Delivery_Location_ID IN ('1015DA1', '1015DA2', '1043DA1', '1043DA6', '344D13', '410D10', '410DA1', '410DA2', '410DA8', '426DA1', '503DA1', '5097DA2', '5097DA7', '5102DA1')") # Query to only return required features
destinations_temp = fs.save(arcpy.env.workspace, "destinations_temp")
print("Required destinations exported from feature service")
destination_points = arcpy.analysis.Select(
in_features = destinations_temp,
out_feature_class = arcpy.env.workspace + "\\destination_points",
where_clause = ""
)
print("Destination Points generated with ObjectID's reset from 1")
destination_points = arcpy.management.AddFields(
in_table = destination_points,
field_description = "Name TEXT # 500 # #;RouteName TEXT # 1024 # #;Sequence LONG # # # #",
template = None
)
print("Route fields added to Destination points")
destination_points = arcpy.management.CalculateField(
in_table = destination_points,
field = "Name",
expression = "!Delivery_Location_ID!",
expression_type = "PYTHON3",
code_block = "",
field_type = "TEXT",
enforce_domains = "NO_ENFORCE_DOMAINS"
)
print("Name field calculated")
destination_points = arcpy.management.CalculateField(
in_table = destination_points,
field = "Sequence",
expression = "2",
expression_type = "PYTHON3",
code_block = "",
field_type = "TEXT",
enforce_domains = "NO_ENFORCE_DOMAINS"
)
print("Sequence field calculated")
_rows = static_destinations
)[0])
print("Static Destination count: " + str(DestinationCount))
TargetCount = OriginCount*DestinationCount
print ("Target Count = " + str(TargetCount))
# Iterate through Origins to replicate points for each Destination
print ("Start iterating Origin points to create 1 set of all Origin points for each Destination point")
while OriginCount < TargetCount:
print ("Origin count (" + str(OriginCount) + ") less than Target Count (" + str(TargetCount) + ") - Append data...")
arcpy.management.Append(
inputs = static_origins,
target = origin_points,
schema_type = "TEST",
field_mapping = None,
subtype = "",
expression = "",
match_fields = None,
update_geometry = "NOT_UPDATE_GEOMETRY"
)
OriginCount = int(arcpy.management.GetCount(
in_rows = origin_points
)[0])
print ("Origins Replicated")
sorted_origins = arcpy.management.Sort(
in_dataset = origin_points,
out_dataset = arcpy.env.workspace + "\\sorted_origins",
sort_field = "Name ASCENDING",
spatial_sort_method = "UR"
)
print ("Origins sorted by Name")
# Iterate through Destinations to replicate points for each Origin
print ("Start iterating Destination points to create 1 set of all Destination points for each Origin point")
while DestinationCount < TargetCount:
print ("Destination count (" + str(DestinationCount) + ") less than Target Count (" + str(TargetCount) + ") - Append data...")
arcpy.management.Append(
inputs = static_destinations,
target = destination_points,
schema_type = "NO_TEST",
field_mapping = r'Name "Name" true true false 500 Text 0 0,First,#,static_destinations,Name,0,500,destination_points,Name,0,500;RouteName "RouteName" true true false 1024 Text 0 0,First,#,static_destinations,RouteName,0,1024,destination_points,RouteName,0,1024;Sequence "Sequence" true true false 4 Long 0 0,First,#,static_destinations,Sequence,-1,-1,destination_points,Sequence,-1,-1',
subtype = "",
expression = "",
match_fields = None,
update_geometry = "NOT_UPDATE_GEOMETRY"
)
DestinationCount = int(arcpy.management.GetCount(
in_rows = destination_points
)[0])
print ("Destinations Replicated")
# Join Origins and Destinations to calculate route details
sorted_origins = arcpy.management.JoinField(
in_data = sorted_origins,
in_field = "OBJECTID",
join_table = destination_points,
join_field = "OBJECTID",
fields = "Name",
fm_option = "NOT_USE_FM",
field_mapping = None
)
print ("Destination names added to Origin points")
sorted_origins = arcpy.management.CalculateField(
in_table = sorted_origins,
field = "RouteName",
expression = '!Name!+"_"+!Name_1!',
expression_type = "PYTHON3",
code_block = "",
field_type = "TEXT",
enforce_domains = "NO_ENFORCE_DOMAINS"
)
print ("Origin Route Names calculated")
arcpy.management.JoinField(
in_data = destination_points,
in_field = "OBJECTID",
join_table = sorted_origins,
join_field = "OBJECTID",
fields = "Name",
fm_option = "NOT_USE_FM",
field_mapping = None
)
print ("Origin names added to Destination points")
destination_points = arcpy.management.CalculateField(
in_table = destination_points,
field = "RouteName",
expression = '!Name_1!+"_"+!Name!',
expression_type = "PYTHON3",
code_block = "",
field_type = "TEXT",
enforce_domains = "NO_ENFORCE_DOMAINS"
)
print ("Destination Route Names calculated")
merged_locations = arcpy.management.Merge(
inputs = [sorted_origins, destination_points],
output = arcpy.env.workspace + "\\MergedLocations",
field_mappings = 'Ops_Code "Ops_Code" true true false 8000 Text 0 0,First,#,sorted_origins,Ops_Code,0,8000;ORIG_FID "ORIG_FID" true true false 4 Long 0 0,First,#,sorted_origins,ORIG_FID,-1,-1;Name "Name" true true false 500 Text 0 0,First,#,sorted_origins,Name,0,500,destination_points,Name,0,500;RouteName "RouteName" true true false 1024 Text 0 0,First,#,sorted_origins,RouteName,0,1024,destination_points,RouteName,0,1024;Sequence "Sequence" true true false 4 Long 0 0,First,#,sorted_origins,Sequence,-1,-1,destination_points,Sequence,-1,-1;ORIG_FID_1 "ORIG_FID_1" true true false 4 Long 0 0,First,#,sorted_origins,ORIG_FID_1,-1,-1;Name_1 "Name" true true false 500 Text 0 0,First,#,sorted_origins,Name_1,0,500,destination_points,Name_1,0,500;Delivery_Location_ID "Delivery Location ID" true true false 255 Text 0 0,First,#,destination_points,Delivery_Location_ID,0,255',
add_source = "NO_SOURCE_INFO"
)
print ("Origins and Destinations merged into single dataset")
static_destinations = arcpy.analysis.Select(
in_features = destination_points,
out_feature_class = arcpy.env.workspace + "\\Static_Destinations",
where_clause = ""
)
print("Static Destination points generated")
# Get counts of input locations
OriginCount = int(arcpy.management.GetCount(
in_rows = static_origins
)[0])
print("Static Origin count: " + str(OriginCount))
DestinationCount = int(arcpy.management.GetCount(
in_rows = static_destinations
)[0])
print("Static Destination count: " + str(DestinationCount))
TargetCount = OriginCount*DestinationCount
print ("Target Count = " + str(TargetCount))
# Iterate through Origins to replicate points for each Destination
print ("Start iterating Origin points to create 1 set of all Origin points for each Destination point")
while OriginCount < TargetCount:
print ("Origin count (" + str(OriginCount) + ") less than Target Count (" + str(TargetCount) + ") - Append data...")
arcpy.management.Append(
inputs = static_origins,
target = origin_points,
schema_type = "TEST",
field_mapping = None,
subtype = "",
expression = "",
match_fields = None,
update_geometry = "NOT_UPDATE_GEOMETRY"
)
OriginCount = int(arcpy.management.GetCount(
in_rows = origin_points
)[0])
print ("Origins Replicated")
sorted_origins = arcpy.management.Sort(
in_dataset = origin_points,
out_dataset = arcpy.env.workspace + "\\sorted_origins",
sort_field = "Name ASCENDING",
spatial_sort_method = "UR"
)
print ("Origins sorted by Name")
# Iterate through Destinations to replicate points for each Origin
print ("Start iterating Destination points to create 1 set of all Destination points for each Origin point")
while DestinationCount < TargetCount:
print ("Destination count (" + str(DestinationCount) + ") less than Target Count (" + str(TargetCount) + ") - Append data...")
arcpy.management.Append(
inputs = static_destinations,
target = destination_points,
schema_type = "NO_TEST",
field_mapping = r'Name "Name" true true false 500 Text 0 0,First,#,static_destinations,Name,0,500,destination_points,Name,0,500;RouteName "RouteName" true true false 1024 Text 0 0,First,#,static_destinations,RouteName,0,1024,destination_points,RouteName,0,1024;Sequence "Sequence" true true false 4 Long 0 0,First,#,static_destinations,Sequence,-1,-1,destination_points,Sequence,-1,-1',
subtype = "",
expression = "",
match_fields = None,
update_geometry = "NOT_UPDATE_GEOMETRY"
)
DestinationCount = int(arcpy.management.GetCount(
in_rows = destination_points
)[0])
print ("Destinations Replicated")
# Join Origins and Destinations to calculate route details
sorted_origins = arcpy.management.JoinField(
in_data = sorted_origins,
in_field = "OBJECTID",
join_table = destination_points,
join_field = "OBJECTID",
fields = "Name",
fm_option = "NOT_USE_FM",
field_mapping = None
)
print ("Destination names added to Origin points")
sorted_origins = arcpy.management.CalculateField(
in_table = sorted_origins,
field = "RouteName",
expression = '!Name!+"_"+!Name_1!',
expression_type = "PYTHON3",
code_block = "",
field_type = "TEXT",
enforce_domains = "NO_ENFORCE_DOMAINS"
)
print ("Origin Route Names calculated")
arcpy.management.JoinField(
in_data = destination_points,
in_field = "OBJECTID",
join_table = sorted_origins,
join_field = "OBJECTID",
fields = "Name",
fm_option = "NOT_USE_FM",
field_mapping = None
)
print ("Origin names added to Destination points")
destination_points = arcpy.management.CalculateField(
in_table = destination_points,
field = "RouteName",
expression = '!Name_1!+"_"+!Name!',
expression_type = "PYTHON3",
code_block = "",
field_type = "TEXT",
enforce_domains = "NO_ENFORCE_DOMAINS"
)
print ("Destination Route Names calculated")
merged_locations = arcpy.management.Merge(
inputs = [sorted_origins, destination_points],
output = arcpy.env.workspace + "\\MergedLocations",
field_mappings = 'Ops_Code "Ops_Code" true true false 8000 Text 0 0,First,#,sorted_origins,Ops_Code,0,8000;ORIG_FID "ORIG_FID" true true false 4 Long 0 0,First,#,sorted_origins,ORIG_FID,-1,-1;Name "Name" true true false 500 Text 0 0,First,#,sorted_origins,Name,0,500,destination_points,Name,0,500;RouteName "RouteName" true true false 1024 Text 0 0,First,#,sorted_origins,RouteName,0,1024,destination_points,RouteName,0,1024;Sequence "Sequence" true true false 4 Long 0 0,First,#,sorted_origins,Sequence,-1,-1,destination_points,Sequence,-1,-1;ORIG_FID_1 "ORIG_FID_1" true true false 4 Long 0 0,First,#,sorted_origins,ORIG_FID_1,-1,-1;Name_1 "Name" true true false 500 Text 0 0,First,#,sorted_origins,Name_1,0,500,destination_points,Name_1,0,500;Delivery_Location_ID "Delivery Location ID" true true false 255 Text 0 0,First,#,destination_points,Delivery_Location_ID,0,255',
add_source = "NO_SOURCE_INFO"
)
print ("Origins and Destinations merged into single dataset")
... View more
a week ago
|
1
|
2
|
185
|
IDEA
|
It would help for field users to also recognise when they are leaving their offline area (which means they can no longer capture/edit data). This has caught a few people out as they just see the basemap and think they can carry on as normal.
... View more
a week ago
|
0
|
0
|
73
|
DOC
|
Regarding the Drawing tools, our staff use the WaB version to place temporary labels on the map for quick prints. This isn't included in ExB yet. The first (February) document doesn't mention it in the Funcationality Description which was disheartening... ...but the other document (March) does list it as planned. The 2 documents seem to contradict each other though. Bit confusing.
... View more
a week ago
|
0
|
0
|
723
|
IDEA
|
@DanPatterson Thanks for the tip - I've made some edits to the post and title to better describe the request.
... View more
2 weeks ago
|
0
|
0
|
111
|
IDEA
|
IDEA: Implement natural sorting in text fields throughout ArcGIS Pro (attribute tables, dynamic table elements, etc). USE CASE: When sorting numerical values in ArcGIS Pro, if these values are in a text field and are sorted in ascending order, it puts any number starting with a 1 (i.e. 101) before any number starting with a 2 (i.e. 20). I know I could add leading zero's to the numbers to get more accurate sorting, but I don't want to have to do this to then have to remove them in labelling (or to educate others to do this). It would be better if text sorting treated numbers holistically (or at least up to the point that a non-numeric character occurs). Note - in below dynamic table element examples, sorting is done on the Rate column first then the Block column. I know it's better to store numbers in integer type fields, but in the above use case, blocks could be labelled with alpha delineators as well: 1A, 1B, 5, 2, 9, 3, 4A, 4B, 6, 7, 8, 10, 11A, 11B ...and I would want these to sort to match the numbers first then the letters (logically) and not end up with 9 after 11A and 11B: 1A, 1B, 2, 3, 4A, 4B, 5, 6, 7, 8, 9, 10, 11A, 11B. Currently these values would sort like this: 10, 11A, 11B, 1A, 1B, 2, 3, 4A, 4B, 5, 6, 7, 8, 9
... View more
2 weeks ago
|
2
|
2
|
250
|
IDEA
|
@AndreaGalligari maybe what is discussed here could help? How to override values for fields with calculated expressions in Forms and the Editor widget (esri.com)
... View more
2 weeks ago
|
0
|
0
|
83
|
IDEA
|
Yes please! Webhooks are still a bit of a mystery to me. One day I'll dive in proper and figure it out as I'm sure we are missing out on opportunities to improve our workflows,m especially regarding feature creation/update/deletion notifications.
... View more
2 weeks ago
|
0
|
0
|
93
|
BLOG
|
I assume it's got something to do with calculating a field if it's empty, but then it's not empty so kid of a circular logic problem. Are there any other fields that get completed when the observation date is done that you could reference instead? Like an Observers Name? Or if the EditDate matches/doesn't match the CreationDate?
... View more
2 weeks ago
|
0
|
0
|
204
|
Title | Kudos | Posted |
---|---|---|
1 | 16 hours ago | |
2 | yesterday | |
1 | 01-24-2024 09:48 PM | |
1 | Monday | |
1 | a week ago |
Online Status |
Offline
|
Date Last Visited |
11 hours ago
|