Select to view content in your preferred language

Autonumber in Pro when feature is created in Arcade

2754
4
08-13-2020 10:40 AM
CourtneyDunn
Occasional Contributor

I am trying to create an attribute rule in ArcGIS Pro that creates an ID for the feature when it is created as well as choose features with '::' leading the ID and assign a new unique ID. There seems to be an issue with the NextSequenceValue function.

We previously were achieving this with the Generate ID function in a dynamic table.

Any suggestions are appreciated. So far I am unsuccessful but here is my code:

// This rule will create a new unique id when a road centerline is created // If the road was created from a split its original id will have a prefix of '::' // We will use this to find the original road and its related alias road names  if (Left($feature.CTRLINEID, 2) == "::" || IsEmpty($feature.CTRLINEID)) { var id = NextSequenceValue('CTRLINEID')      // If the centerlineid is not set return the new id if (IsEmpty($feature.CTRLINEID)) return id;   // Find the original ID of the road that was split     var original_id = Mid($feature.centerlineid, 2, Count($feature.centerlineid) - 2);     if (IsEmpty(original_id)) return id;      // Store an add for every road alias and related it to the new road that was added after the cut var newAttributes = {}; newAttributes['CTRLINEID'] = id }
0 Kudos
4 Replies
HusseinNasser2
Esri Contributor

Hey Courtney,

What problems are you having with NextSequenceValue? that should be the solution to get you to sequence your table.

1) You need to create a database sequence, using the Create Database Sequence.

2) Create an Attribute Rule  and use the NextSequenceValue to get a sequence from the DB and store it in the field, make sure its on Insert 

3) Finally create few features 

XanderBakker
Esri Esteemed Contributor

Hi Hussein Nasser ,

I am looking at the code shared by Courtney Dunn :

// This rule will create a new unique id when a road centerline is created 
// If the road was created from a split its original id will have a prefix of '::' 
// We will use this to find the original road and its related alias road names  
if (Left($feature.CTRLINEID, 2) == "::" || IsEmpty($feature.CTRLINEID)) { 
    var id = NextSequenceValue('CTRLINEID');
    // If the centerlineid is not set return the new id 
    if (IsEmpty($feature.CTRLINEID)) {
        return id;
    }   
    // Find the original ID of the road that was split     
    var original_id = Mid($feature.centerlineid, 2, Count($feature.centerlineid) - 2);
    if (IsEmpty(original_id)) {
        return id;
    }      
    // Store an add for every road alias and related it to the new road that was added after the cut 
    var newAttributes = {}; 
    newAttributes['CTRLINEID'] = id;
}

... and I notice that the last part has not been implemented yet (lines 16 and 17). Maybe the idea is to update related features, but that part is missing. Courtney Dunn , can you explain what you want to achieve with this last part. Currently it does not do anything. 

Before lines 11 I would check if your centerlineid is not empty. Because if it is, line 11 will fail using the Count.

In general you have a couple of If statements, but no else. There can be several cases that return no value. Is that what you want?

JoeBorgione
MVP Emeritus

The code snippet appears to be from the ESRI Address Data Management Solution and specifically the Centerline ID and Copy Road Aliases rule, shown in it's entirety below.  Xander Bakker, lines 16 & 17 above taken out of context are meaningless on their own; line 15 above is line 24 below.

I think that Hussein Nasser‌ has hit the nail on the head.  Courtney Dunn‌ have you created the sequence first in you data base?  The fgdb that comes with the solution should have it already.  You can use the arcpy.da.ListDatabaseSequences() like this to see what is there.  In a python window or the python ide of your choice:

import arcpy

gdb = r'C:\path\to\your\geodatabase'

for s in arcpy.da.ListDatabaseSequences(gdb):
    print(f'Name = {s.name}  StartValue = {s.startValue}  IncrementValue = {s.incrementValue}  CurrentValue = {s.currentValue})
‍‍‍‍‍‍

If you are using an EGDB for your data, the da.ListDatabaseSequences() function isn't available. See arcpy.ListDatabaseSequences() for EGDB  to vote for it or you can try to use what ESRI Tech Support provided me as a SQL work around which I haven't got to work yet.

Arcade rule below: (looping in Chris Fox‌ too...)

// This rule will create a new unique id when a road centerline is created
// This will also copy related road alias names for any roads that were added as a result of a split

// Define the leading text and the delimiter for the ID
var prefix = "RD"
var join_char = "-"

// Define any fields to be copied from the road name aliases table (lower case)
var alias_field_names = ["roadpremod", "roadpredir", "roadpretype", "roadpretypesep", "roadname", "roadtype", "roadpostdir", "roadpostmod", "fullname", "municipality"]

// If the road was created from a split its oirginal id will have a prefix of '::'
// We will use this to find the original road and its related alias road names
if (Left($feature.centerlineid, 2) == "::" || IsEmpty($feature.centerlineid)) {
    var id = Concatenate([prefix, NextSequenceValue("CenterlineID")], join_char)
    
    // If the centerlineid is not set return the new id
    if (IsEmpty($feature.centerlineid)) return id;
   
    // Find the original ID of the road that was split
    var original_id = Mid($feature.centerlineid, 2, Count($feature.centerlineid) - 2);
    if (IsEmpty(original_id)) return id;
    
    // Find all the related road alias names for the split road
    // Store an add for every road alias and related it to the new road that was added after the cut
    var adds = []
    var roadNameAliases = Filter(FeatureSetByName($datastore, "AliasRoadName"), "centerlineid = '" + original_id + "'");
    for (var roadNameAlias in roadNameAliases) {
        var featureAttributes = Dictionary(Text(roadNameAlias))['attributes'];
        var newAttributes = {};
        for (var k in featureAttributes) {
            if (IndexOf(alias_field_names, Lower(k)) > -1 && featureAttributes != null) {
                newAttributes = featureAttributes;
            } else {
                continue;
            }
        }
        newAttributes['centerlineid'] = id
        adds[Count(adds)] = {
            'attributes': newAttributes
        }
    }
    
    // Using the edit parameter return the list of updates and adds for the intersecting roads and a list of adds for related road alias names
    return {
        'result': id,
        'edit': [{'className': 'AliasRoadName', 'adds': adds}]
    };
}
else {
   return $feature.centerlineid
}‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍
That should just about do it....
HusseinNasser2
Esri Contributor

Here is some more content (video form) on generating unique id 

Video Link : 6803