|
POST
|
Hi @KellyGerrow. Just wondering if the above outcomes are still the recommended best practice approach for including contractors in your ArcGIS Org. Can't find anything else that clearly discusses this in the last 10 years and was wondering if it's possible to setup groups that can't see content shared to the organisation yet, or if we should also pursue a 2nd org for managing contractors.
... View more
06-05-2025
12:17 AM
|
1
|
0
|
673
|
|
IDEA
|
Thanks for the link. I did search but didn't find that one.
... View more
04-08-2025
08:53 PM
|
0
|
0
|
1184
|
|
IDEA
|
I just followed up on this after being approached by Esri to see if it was still a problem. We're now on 3.3.2 and it all seemed to work as advertised. Test results below. I tested by publishing a new feature service with 25,180 rows (polygons), then ran the whole lot through the Delete Rows tool ("Enable Undo" turned off). It took 1 min 51 secs to run (pretty good). I then ran the Append tool to upload the original 25,180 features again and that only took 55 secs to run.
... View more
04-08-2025
08:50 PM
|
0
|
0
|
587
|
|
IDEA
|
When downloading mobile map packages created from WebMaps in ArcGIS Online > Settings > Manage Offline Areas, include the layers of the map package and not just the basemap. We want to be able to create detail rich offline maps for use in Survey123, but limit file sizes. Our data also changes regularly, so utilising a webmap with scheduled repackaging makes sense. But only the basemap shows up in Survey123 - no map layers. The only way it seems to get imagery and map layers at present is to create a .tpk in ArcGIS Pro - slow and manual. No thanks!
... View more
04-07-2025
10:23 PM
|
1
|
2
|
1239
|
|
BLOG
|
You got! I implemented the 3 changes you suggested, and it worked for rows that had null area values, but not incorrect. I then removed the 2nd suggestion (if valueDict[keyValue] != None and updateRow[1] == None:) and it worked for all missing and incorrect values. It also only "edited" the features requiring an update an nothing else (though I've now implemented disabling and enabling of editor tracking in the script so this is less important from an editor tracking perspective, but I'm sure is still a huge performance boon). print("Updating data")
with arcpy.da.UpdateCursor(featureservice, updateFieldsList) as updateRows:
for updateRow in updateRows:
print(updateRow)
# store the Join value of the row being updated in a keyValue variable
keyValue = updateRow[0].upper()
# verify that the keyValue is in the Dictionary
if keyValue in valueDict:
print(f"KeyValue found: {keyValue}")
if valueDict[keyValue] != updateRow[1]:
print("Yep")
# A newer value exists
for n in range (1,len(sourceFieldsList)):
print(n)
updateRow[n] = valueDict[keyValue]
updateRows.updateRow(updateRow)
# transfer the values stored under the keyValue from the dictionary to the updated fields.
del valueDict
print(f"AreaHa field updated successfully for {fc_name}") Thank you again for your assistance. It's been invaluable.
... View more
03-17-2025
12:14 AM
|
0
|
0
|
10244
|
|
BLOG
|
We're working beyond my knowledge base here, thus my inept adaptations of your original code. At that point, it should just be getting the keyValue that matches the updateRow and updating the associated Area value.
... View more
03-16-2025
09:42 PM
|
0
|
0
|
10254
|
|
IDEA
|
Just went searching for this idea. I've started implementing MS Power Automate/Flow and webhooks for form emailing functionality, but it has limitations! Once a form gets too big, Flow won't import the data (even in a truncated format). This means that either the form needs to be completely rebuilt using sub-forms (something that was intentionally not done the first time). It would be good if Survey123 had even just a simple in-built email function that could send a copy of the record in csv or pdf format to either a preset email address or email addresses entered into an email question/s in the submitted form. After moving our corporate system from iForms to Survey123, it's frustrating that this function isn't easier to implement!
... View more
03-16-2025
07:54 PM
|
0
|
0
|
610
|
|
BLOG
|
Woohoo! Progress. Thank you. Now on to the next bit... float object is not iterable.... I've put in some print statements to debug - looks like this is the problem line: list(valueDict[keyValue])
... View more
03-12-2025
08:49 PM
|
0
|
0
|
10331
|
|
BLOG
|
I have no idea what is going on here, but it seems that something is not playing nice between ArcGIS Online and ArcGIS Pro/arcpy. In AGOL, the GlobalID is all lowercase: but the same feature in ArcGIS Pro is all uppercase: So I have no idea what to do now. Found this thread, but seems it's still not resolved. I wonder if this is what is causing my issues.
... View more
03-12-2025
08:34 PM
|
0
|
0
|
10339
|
|
BLOG
|
Getting Exception: name 'upper' is not defined for the keyValue = upper(updateRow[0]) line. I've tried applying it this way as well, but still not working despite not throwing an exception: keyValue = (updateRow[0].upper)
... View more
03-12-2025
08:21 PM
|
0
|
0
|
10341
|
|
BLOG
|
Hi @RichardFairhurst. I'm having a go at implementing this in another application. This time, seemingly a lot simpler, but I must still be missing something. I'm only trying to check and update an area field (AreaHa) and want to use the GlobalID as the join field. Below is the code I'm currently working with and the print statements. I'm guessing it isn't happy because the GlobalID's don't match case, but I can't seem to force this to be consistent. Also tried to store the original ObjectID's in a temp field to use and couldn't get that to work either (couldn't get the field to export). # Create a temporary directory
temp_dir = tempfile.mkdtemp()
# Define the path for the temporary File Geodatabase
temp_gdb = os.path.join(temp_dir, "tempAreaHa.gdb")
# Create the File Geodatabase
arcpy.CreateFileGDB_management(temp_dir, "tempAreaHa.gdb")
# Set the workspace to the temporary File Geodatabase
arcpy.env.workspace = temp_gdb
def remove_last_part(url):
# Split the URL by '/' and join all parts except the last one
return '/'.join(url.split('/')[:-1])
def extract_fc_name(url):
# Extract the feature class name from the URL and clean it
path_parts = url.split('/')
fc_name = path_parts[-3]
return fc_name
# Read the CSV file containing feature service URLs
# Example service url value in csv: https://services-ap1.arcgis.com/#############/arcgis/rest/services/Plantation_Concept_Areas_Test/FeatureServer/0
with open('FeatureServiceAreaUpdates.csv', mode='r') as file:
csv_reader = csv.reader(file)
next(csv_reader) # Skip header row if present
for row in csv_reader:
featureservice = row[0]
fc_name = extract_fc_name(featureservice)
with arcpy.EnvManager(preserveGlobalIds=True):
temp_Areas = arcpy.conversion.ExportFeatures(
in_features=featureservice,
out_features=arcpy.env.workspace + "\\" + fc_name,
where_clause="",
use_field_alias_as_name="NOT_USE_ALIAS",
field_mapping=f'AreaHa "Area (ha)" true true false 0 Double 0 0,First,#,{fc_name},AreaHa,-1,-1;GlobalID "GlobalID" false false true 38 GlobalID 0 0,First,#,{fc_name},GlobalID,-1,-1',
sort_field=None
)
print(f"Features exported for {fc_name}")
arcpy.management.CalculateGeometryAttributes(
in_features=temp_Areas,
geometry_property="AreaHa AREA",
length_unit="",
area_unit="HECTARES",
coordinate_system='PROJCS["GDA_1994_MGA_Zone_50",GEOGCS["GCS_GDA_1994",DATUM["D_GDA_1994",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",500000.0],PARAMETER["False_Northing",10000000.0],PARAMETER["Central_Meridian",117.0],PARAMETER["Scale_Factor",0.9996],PARAMETER["Latitude_Of_Origin",0.0],UNIT["Meter",1.0]]',
coordinate_format="SAME_AS_INPUT"
)
print(f"Areas calculated for {fc_name}")
# Remove the last part of the URL
modified_url = remove_last_part(featureservice)
# Access the feature layer collection
flc = FeatureLayerCollection(modified_url, gis)
# Disable editor tracking
disable_params = {
"editorTrackingInfo": {
"enableEditorTracking": False
}
}
flc.manager.update_definition(disable_params)
print(f"Editor tracking disabled for {fc_name}")
# Create a dictionary from the exported table
sourceFieldsList = ['GlobalID', 'AreaHa']
valueDict = {r[0]: r[1] for r in arcpy.da.SearchCursor(temp_Areas, sourceFieldsList)}
print(valueDict)
# Update the feature service using the dictionary
updateFieldsList = ['GlobalID', 'AreaHa']
with arcpy.da.UpdateCursor(featureservice, updateFieldsList) as updateRows:
for updateRow in updateRows:
print(updateRow)
# store the Join value of the row being updated in a keyValue variable
keyValue = updateRow[0]
# verify that the keyValue is in the Dictionary
if keyValue in valueDict:
print(keyValue)
if list(valueDict[keyValue]) and updateRow[1:1]:
# A newer value exists
changeCnt += 1
for n in range (1,len(sourceFieldsList)):
print(n)
updateRow[n] = valueDict[keyValue][n-1]
updateRows.updateRow(updateRow)
# transfer the values stored under the keyValue from the dictionary to the updated fields.
del valueDict
print(f"AreaHa field updated successfully for {fc_name}")
# Re-enable editor tracking
enable_params = {
"editorTrackingInfo": {
"enableEditorTracking": True,
"enableOwnershipAccessControl": True,
"allowOthersToUpdate": True,
"allowOthersToDelete": True
}
}
flc.manager.update_definition(enable_params)
print(f"Editor tracking re-enabled for {fc_name}")
endTime = time.time()
print(f"Script completed in {endTime - startTime} seconds.")
... View more
03-12-2025
05:14 PM
|
0
|
0
|
10355
|
|
BLOG
|
Nice work. I've implemented and tested the revised code and can confirm that it only updates fields that have changed and editor tracking info is only updated for those specific features. It's great having these full code snippets to work with too. Completely understand and appreciate having the extra functionality in the Insert/Delete available. I'm sure I will need it myself at some point!
... View more
03-03-2025
11:02 PM
|
0
|
0
|
10486
|
|
BLOG
|
Thanks for trying to figure this out for me @RichardFairhurst. I tested your new code and it seemed to update all found rows with the same value. I did remove the Insert and Delete sections as that wasn't required. I just experiemented with the code I provided above that was working and included a bit extra to disable and renenable editor tracking on the feature service around the Update section. This worked well and is sufficient for my needs. Thanks again for your efforts (especially on your phone!). Updated code below showing editor tracking disable/enable. del valueDict
print("Temp data prepped")
# Update feature service
def remove_last_part(url):
# Split the URL by '/' and join all parts except the last one
return '/'.join(url.split('/')[:-1])
# Remove the last part of the URL
modified_url = remove_last_part(fs2)
# Access the feature layer collection
flc = FeatureLayerCollection(modified_url, gis)
# Disable editor tracking
disable_params = {
"editorTrackingInfo": {
"enableEditorTracking": False
}
}
flc.manager.update_definition(disable_params)
sourceFieldsList = ['Plantation', 'PlantingYear', 'insp_2_weeks', 'insp_4_weeks', 'insp_6_weeks', 'insp_8_weeks', 'insp_10_weeks', 'insp_12_weeks', 'insp_4_months', 'insp_5_months', 'insp_6_months', 'insp_9_months', 'insp_12_months', 'insp_15_months', 'insp_18_months', 'insp_21_months', 'insp_24_months']
# Use list comprehension to build a dictionary from a da SearchCursor where the key values are based on 2 separate feilds
valueDict = {str(r[0]) + "," + str(r[1]):(r[2:]) for r in arcpy.da.SearchCursor(Table2, sourceFieldsList)}
updateFieldsList = ['Plantation', 'PlantingYear', 'insp_2_weeks', 'insp_4_weeks', 'insp_6_weeks', 'insp_8_weeks', 'insp_10_weeks', 'insp_12_weeks', 'insp_4_months', 'insp_5_months', 'insp_6_months', 'insp_9_months', 'insp_12_months', 'insp_15_months', 'insp_18_months', 'insp_21_months', 'insp_24_months']
with arcpy.da.UpdateCursor(fs2, updateFieldsList) as updateRows:
for updateRow in updateRows:
# store the Join value by combining 2 field values of the row being updated in a keyValue variable
keyValue = updateRow[0]+ "," + str(updateRow[1])
# verify that the keyValue is in the Dictionary
if keyValue in valueDict:
if list(updateRow[2:]) != list(valueDict[keyValue]):
# transfer the values stored under the keyValue from the dictionary to the updated fields.
for n in range (2,len(sourceFieldsList)):
if valueDict[keyValue][n-2] == None:
pass
else:
updateRow[n] = valueDict[keyValue][n-2]
updateRows.updateRow(updateRow)
del valueDict
# Enable editor tracking
enable_params = {
"editorTrackingInfo": {
"enableEditorTracking": True
}
}
flc.manager.update_definition(enable_params)
print("Fields updated successfully.")
... View more
03-03-2025
06:03 PM
|
0
|
0
|
10510
|
| Title | Kudos | Posted |
|---|---|---|
| 2 | Monday | |
| 3 | 2 weeks ago | |
| 3 | 2 weeks ago | |
| 2 | 2 weeks ago | |
| 1 | 2 weeks ago |
| Online Status |
Offline
|
| Date Last Visited |
Wednesday
|