|
POST
|
As you're asking this in the ArcGIS Pro community, I'm assuming you mean Attribute Rules, not Assistant. Introduction to attribute rules—ArcGIS Pro | Documentation If you indeed mean Assistant, I'll move your question to the ArcMap community. // Attribute Rule on the Address Points
// triggers: Insert
// load the parcels
var parcels = FeatureSetByName($datastore, "Databasename.Dataowner.Parcels", ["ParcelNumber"], false)
// intersect with the new point
var intersecting_parcel = First(Intersects(parcels, $feature))
// return null if no parcel was intersected
if(intersecting_parcel == null) {
return null
}
// else return that parcel's number
return intersecting_parcel.ParcelNumber
... View more
09-14-2022
11:08 PM
|
1
|
3
|
2176
|
|
POST
|
Everything you need is actually already in my scripts, we just need to rearrange a little. You could do something like this: // What is your datetime and name field?
var datetime = "AngelegtAm"
var name = "AngelegtVon"
// function to get mean edits per day over the whole period
function total(fs, user) {
var first_datetime = First(OrderBy(fs, datetime))[datetime]
var last_datetime = First(OrderBy(fs, datetime + " DESC"))[datetime]
var first_date = Date(Text(first_datetime, "Y-MM-DD"))
var last_date = Date(Text(last_datetime, "Y-MM-DD"))
var days = DateDiff(last_date, first_date, "days") + 1
var edits = Count(Filter(fs, `${name} = @user`))
//return edits / days
return {edits: edits, days: days, mean: edits/days}
}
// function to get mean edits per day where the user actually edited
function specific(fs, user) {
var fs = Filter(fs, `${name} = @user`)
var extract_date_string = `CONCAT(EXTRACT(YEAR FROM ${datetime}), '-', EXTRACT(MONTH FROM ${datetime}), '-', EXTRACT(DAY FROM ${datetime}))`
var grouped_by_date = GroupBy(fs,
[{name: "DateString", expression: extract_date_string}],
[{name: "Count", expression: "1", statistic: "COUNT"}])
var edits = Sum(grouped_by_date, "Count")
var days = Count(grouped_by_date)
//return edits / days
return {edits: edits, days: days, mean: edits/days}
} To show the difference between the functions: // Load data
var p = Portal("...")
var id = "b19c6cfbacaf46489495b5b896ad9490"
var lyr = 16
var layer = FeaturesetByPortalItem(p, id, lyr, [datetime, name], false)
layer = Filter(layer, `${name} IS NOT NULL AND ${datetime} IS NOT NULL`)
// get users
var users = Distinct(layer, name)
// create output featureset
var output_fs = {
fields: [
{name: "User", type: "esriFieldTypeString"},
{name: "TotalDays", type: "esriFieldTypeInteger"},
{name: "SpecDays", type: "esriFieldTypeInteger"},
{name: "Edits", type: "esriFieldTypeInteger"},
{name: "TotalMean", type: "esriFieldTypeDouble"},
{name: "SpecMean", type: "esriFieldTypeDouble"},
],
geometryType: "",
features: []
}
// fill the output featureset
for(var user in users) {
var total_mean = total(layer, user[name])
var spec_mean = specific(layer, user[name])
var new_feature = {
attributes: {
User: user[name],
Edits: total_mean.edits,
TotalDays: total_mean.days,
SpecDays: spec_mean.days,
TotalMean: total_mean.mean,
SpecMean: spec_mean.mean
}}
Push(output_fs.features, new_feature)
}
// return
Featureset(Text(output_fs))
... View more
09-14-2022
10:48 PM
|
1
|
3
|
4316
|
|
POST
|
Sorry, completely forgot to answer you. I didn't mean to let you hanging... The $datapoint global is only available in the advanced formatting of indicators. What exactly are you trying to do? Here is an example of what you could do. Data expression: // What is your datetime field?
var datetime = "Zeitstempel"
// load data
var p = Portal("...")
var id = "82c62b3205874b139191f6ca0db43ac3"
var lyr = 1
var layer = FeaturesetByPortalItem(p, id, lyr, [datetime], false)
// get first and last datetime
var first_datetime = First(OrderBy(layer, datetime))[datetime]
var last_datetime = First(OrderBy(layer, datetime + " DESC"))[datetime]
// convert to date and get number of days
var first_date = Date(Text(first_datetime, "Y-MM-DD"))
var last_date = Date(Text(last_datetime, "Y-MM-DD"))
var days = DateDiff(last_date, first_date, "days") + 1
// group the featureset by date, get count
// convert to text to remove time
var extract_date_string = `CONCAT(EXTRACT(YEAR FROM ${datetime}), '-', EXTRACT(MONTH FROM ${datetime}), '-', EXTRACT(DAY FROM ${datetime}))`
var grouped_by_date = GroupBy(layer,
[{name: "DateString", expression: extract_date_string}],
[{name: "Count", expression: "1", statistic: "COUNT"}])
// create output featureset
var output_fs = {
fields: [
{name: "Date", type: "esriFieldTypeDate"},
{name: "Responses", type: "esriFieldTypeInteger"},
{name: "Weekday", type: "esriFieldTypeString"},
],
geometryType: "",
features: []
}
// fill the output featureset
for(var row in grouped_by_date) {
var date_parts = Split(row.DateString, "-")
var current_date = Date(date_parts[0], date_parts[1]-1, date_parts[2])
var new_feature = {
attributes: {"Date": Number(current_date), "Responses": row.Count, "Weekday": Text(current_date, "dddd")}
}
Push(output_fs.features, new_feature)
}
// return
Featureset(Text(output_fs)) Use that Data Expression in a pie chart (show percentage of responses on each weekday):
... View more
09-14-2022
10:07 AM
|
0
|
0
|
4336
|
|
POST
|
The Filter() function doesn't find anything. I tested with dates without time, so searching for "DateField = @current_date" returned values. If you use a datetime field, that won't work. But of course, datetime fields will be the majority of cases, so I reworked the script. The main difference: convert the datetime to date, change the Filter() expression: // What is your datetime field?
var datetime = "Zeitstempel"
// get first and last datetime
var first_datetime = First(OrderBy($layer, datetime))[datetime]
var last_datetime = First(OrderBy($layer, datetime + " DESC"))[datetime]
// convert to date and get number of days
var first_date = Date(Text(first_datetime, "Y-MM-DD"))
var last_date = Date(Text(last_datetime, "Y-MM-DD"))
var days = DateDiff(last_date, first_date, "days") + 1
var workdays = 0
var days_without_response = 0
var weekday_bins = [0, 0, 0, 0, 0, 0, 0]
var current_date = first_date
for(var i = 0; i < days; i++) {
var next_date = DateAdd(current_date, 1, "days")
var sql = `${datetime} >= @current_date AND ${datetime} < @next_date`
var responses = Count(Filter($layer, sql))
var iso_day = IsoWeekday(current_date)
weekday_bins[iso_day-1] += responses
workdays += (iso_day < 6)
days_without_response += (responses == 0)
current_date = next_date
}
var return_lines = [
`The survey was running from ${Text(first_date, "Y-MM-DD")} to ${Text(last_date, "Y-MM-DD")} (${days} days, ${workdays} work days).`,
`In this time, ${Sum(weekday_bins)} responses were submitted. There were ${days_without_response} days without response.`,
`Mo: ${weekday_bins[0]}`,
`Tu: ${weekday_bins[1]}`,
`We: ${weekday_bins[2]}`,
`Th: ${weekday_bins[3]}`,
`Fr: ${weekday_bins[4]}`,
`Sa: ${weekday_bins[5]}`,
`Su: ${weekday_bins[6]}`,
]
return Concatenate(return_lines, TextFormatting.NewLine) I tested this with a layer that spans 15 years. The for loop took way too long, so I used a GroupBy to get the count of responses on each distinct date. That massively shortens the for loop but it means that we have to calculate the workdays instead of counting them. // What is your datetime field?
var datetime = "Zeitstempel"
// get first and last datetime
var first_datetime = First(OrderBy($layer, datetime))[datetime]
var last_datetime = First(OrderBy($layer, datetime + " DESC"))[datetime]
// convert to date and get number of days
var first_date = Date(Text(first_datetime, "Y-MM-DD"))
var last_date = Date(Text(last_datetime, "Y-MM-DD"))
var days = DateDiff(last_date, first_date, "days") + 1
// calculate work days
// can be approximated with Round(days/7*5), but this can be off by several days
var workdays = 0
// get first monday, add "surplus" work days
var first_monday = first_date
var first_weekday = IsoWeekday(first_date)
if(first_weekday > 1) {
first_monday = DateAdd(first_date, 8 - first_weekday, "days")
workdays += Max(6 - first_weekday, 0)
}
// get last monday, add "surplus" work days
var last_monday = last_date
var last_weekday = IsoWeekday(last_date)
if(last_weekday > 1) {
last_monday = DateAdd(last_date, -last_weekday + 1, "days")
workdays += Min(last_weekday - 1, 4)
}
// add 5 workdays for every week, add the last monday
workdays += DateDiff(last_monday, first_monday, "days") / 7 * 5 + 1
// group the featureset by date, get count
// convert to text to remove time
var extract_date_string = `CONCAT(EXTRACT(YEAR FROM ${datetime}), '-', EXTRACT(MONTH FROM ${datetime}), '-', EXTRACT(DAY FROM ${datetime}))`
var grouped_by_date = GroupBy($layer,
[{name: "DateString", expression: extract_date_string}],
[{name: "Count", expression: "1", statistic: "COUNT"}])
// loop through the grouped records and fill weekday bins
var weekday_bins = [0, 0, 0, 0, 0, 0, 0]
for(var row in grouped_by_date) {
var date_parts = Split(row.DateString, "-")
var current_date = Date(date_parts[0], date_parts[1]-1, date_parts[2])
var iso_day = IsoWeekday(current_date)
weekday_bins[iso_day-1] += row.Count
}
// get total responses and days without response
var responses = Sum(weekday_bins) // same as Count($layer)
var days_without_response = days - Count(grouped_by_date)
// return
var return_lines = [
`The survey was running from ${Text(first_date, "Y-MM-DD")} to ${Text(last_date, "Y-MM-DD")} (${days} days, ${workdays} work days).`,
`In this time, ${responses} responses were submitted. There were ${days_without_response} days without response.`,
`Mo: ${weekday_bins[0]}`,
`Tu: ${weekday_bins[1]}`,
`We: ${weekday_bins[2]}`,
`Th: ${weekday_bins[3]}`,
`Fr: ${weekday_bins[4]}`,
`Sa: ${weekday_bins[5]}`,
`Su: ${weekday_bins[6]}`,
]
return Concatenate(return_lines, TextFormatting.NewLine)
... View more
09-14-2022
09:43 AM
|
1
|
7
|
4340
|
|
POST
|
You can use Text() to format: var d1 = Today()
var d2 = Now()
// Compare directly
Console(d1)
Console(d2)
Console("Dates are equal: " + (d1 == d2))
// Remove time and compare
var d1 = Date(Text(d1, "Y-MM-DD"))
var d2 = Date(Text(d2, "Y-MM-DD"))
Console(d1)
Console(d2)
Console("Dates are equal: " + (d1 == d2)) 2022-09-14T00:00:00+02:00
2022-09-14T18:04:23.078+02:00
Dates are equal: false
2022-09-14T00:00:00+02:00
2022-09-14T00:00:00+02:00
Dates are equal: true
... View more
09-14-2022
09:06 AM
|
2
|
1
|
2170
|
|
POST
|
Indeed, the angle is dependent on the vertex order: Removing that dependency is easy, but it wasn't quite as trivial as I thought. I thought I just had to replace the modulo 360 with modulo 180 (last line). That works for lines with a single segment, but polylines are still wrong: Instead, you have to convert to geographic angle inside the loop, not at the end: // get a list of line parts
var paths = Geometry($feature).paths
// for each part, loop through each segment and get its geographic angle
var angles = []
for(var p in paths) {
var count_p = Count(paths[p])
for(var q = 1; q < count_p; q ++) {
var a_arith = Angle(paths[p][q], paths[p][q-1])
var a_geo = (450 - a_arith) % 180 // 180 instead of 360, so that vertex order doesn't matter
Push(angles, a_geo)
}
}
// return the mean
return Mean(angles)
... View more
09-14-2022
06:46 AM
|
2
|
0
|
7464
|
|
POST
|
I don't think there is a tool that does that out of the box (edit: nevermind, see above). But you can easily calculate the value with Calculate Field. angle of the lines in the image respect to the North Do you mean the geographic angle (North=0°, East=90°)? If so, use this Arcade expression in the tool: // get a list of line parts
var paths = Geometry($feature).paths
// for each part, loop through each segment and get its angle (arithmetic angle -> East=0°, North=90°)
var angles = []
for(var p in paths) {
var count_p = Count(paths[p])
for(var q = 1; q < count_p; q ++) {
var a = Angle(paths[p][q], paths[p][q-1])
Push(angles, a)
}
}
// get the mean arithmetic angle
var arith_angle = Mean(angles)
// convert to geographic and return
return (450 - arith_angle) % 360 Or do you mean the arithmetic angle (rotating counter-clockwise) but with North = 0°? Then use this expression: // get a list of line parts
var paths = Geometry($feature).paths
// for each part, loop through each segment and get its angle (arithmetic angle -> East=0°, North=90°)
var angles = []
for(var p in paths) {
var count_p = Count(paths[p])
for(var q = 1; q < count_p; q ++) {
var a = Angle(paths[p][q], paths[p][q-1])
Push(angles, a)
}
}
// get the mean arithmetic angle
var arith_angle = Mean(angles)
// rotate so that North = 0°
var north_arith_angle = arith_angle - 90
return north_arith_angle + IIF(north_arith_angle < 0, 180, 0) Or do you mean something else? Then please clarify.
... View more
09-13-2022
08:04 AM
|
2
|
2
|
7494
|
|
POST
|
Try it without the quotes. Just layerdikte.BOTTOMSAND - layerdikte.TOPSAND >= 3.5
... View more
09-12-2022
12:18 AM
|
0
|
0
|
2812
|
|
POST
|
I was asking the questions to determine if you need the if statement at all. Turns out you don't, because you're mapping all the percentages to 100100. // Filter the table for same species and percentage 100100
var species = $feature.Name
var target = First(Filter($featureset, "Name = @species AND Percentage = 100100"))
// nothing found? -> return null
if(target == null) { return null }
// else return that Value
return target.Value
... View more
09-10-2022
02:32 AM
|
0
|
0
|
2628
|
|
POST
|
This code uses FeatureSetByRelationshipName(), which returns the related features based on a relationship class. SepticLocations is the name of the relationship class, inspect_freq is the name of a field in the related table. If you haven't built a relationship class, you can load the related table with FeatureSetByName() or one of the other FeatureSetBy*() functions and then Filter() it.
... View more
09-10-2022
02:23 AM
|
0
|
0
|
3248
|
|
POST
|
That means the script doesn't find the corresponding values in the geometry update table. make sure the common field has the same data type if WrongGeometry.CommonField is an integer field, CorrectGeometry.CommonField must also be an integer field. make sure there are actually matching values if you want to update an entry in WrongGeometry with CommonField = 5, you need an entry in CorrectGeometry with CommonField = 5.
... View more
09-08-2022
08:23 AM
|
0
|
0
|
6623
|
|
POST
|
There's probably a way to do it with tools, but you can easily do this with a Python script: in_features = "TestPoints"
inner = 400
outer = 800
out_dir = "memory"
out_name = "ring_buffer"
# create the output fc
sr = arcpy.Describe(in_features).spatialReference
out_feature = arcpy.management.MakeFeatureclass(out_dir, out_name, "POLYGON", spatial_reference=sr)
arcpy.management.AddField(out_feature, "Orig_FID", "LONG")
with arcpy.da.InsertCursor(out_feature, ["SHAPE@", "Orig_FID"]) as i_cursor:
with arcpy.da.SearchCursor(in_features, ["SHAPE@", "OID@"]) as s_cursor:
for shp, oid in s_cursor:
# create inner and outer buffers
b_inner = shp.buffer(inner)
b_outer = shp.buffer(outer)
# get the geometric difference -> the ring
ring_shp = b_outer.difference(b_inner)
# write the ring into the output fc
i_cursor.insertRow([ring_shp, oid])
... View more
09-08-2022
01:03 AM
|
1
|
0
|
1207
|
|
POST
|
This is the map we're talking about: Tacoma City Council Districts Web Map Update-Copy (arcgis.com) The old and hard way: figure out how many links you need at max let's say the biggest district has 5 neighbothood counlics, then you need 5 links. create the expressions: for each council: 1 expression for the name, 1 for the url create the popup // Expression for the name
index = 0 // <- change this number in each name expression
var areas =FeatureSetByName($map,"Neighborhood Council Districts (Tacoma)");
var Onefifty = Buffer($Feature, -150, 'feet')
var countp = Intersects(areas,Onefifty);
var i = 0
for(var c in countp) {
if(i == index) {
return c.Neighborhood
}
i++
}
return '' // Expression for the url
index = 0 // <- change this number in each name expression
var areas =FeatureSetByName($map,"Neighborhood Council Districts (Tacoma)");
var Onefifty = Buffer($Feature, -150, 'feet')
var countp = Intersects(areas,Onefifty);
var i = 0
for(var c in countp) {
if(i == index) {
return c.URL
}
i++
}
return '' Your popup would look like this: The new and far better way: Just use an Arcade element! With this element, you can return HTML code which will be interpreted by the popup. var areas =FeatureSetByName($map,"Neighborhood Council Districts (Tacoma)");
var Onefifty = Buffer($Feature, -150, 'feet')
var countp = Intersects(areas,Onefifty);
var result = "";
for (var item in countp){
var name = item["Neighborhood"];
var url = item["URL"]
result += `<a href="${url}" target="_blank">${name}</a><br/>`
}
return {
type : 'text',
text : result
}
... View more
09-07-2022
11:40 PM
|
3
|
2
|
2040
|
|
POST
|
Hey @John_Shell (and @PedroSoares1 , if you care), this thread is messy enough, I'll post in the original question: Arcade Popups with multiple web links - Esri Community
... View more
09-07-2022
11:25 PM
|
1
|
1
|
3250
|
|
POST
|
Ah, OK. So, if you only care about Atlantic Croaker and 5050, this should work: if($feature.Name == "Atlabtic Croaker" && $feature.Percentage == 5050) {
// Filter the table
var target = First(Filter($featureset, "Name = 'Atlantic Croaker' AND Percentage = 100100"))
// nothing found? -> return null
if(target == null) { return null }
return target.Value
}
return FWOA_Value If you care about multiple combinations of Name and Percentage, you can either calculate each combination manually (change the if statement and change the Filter query) or you can do it automatically. To do it automatically, please answer these questions about your data: do you have more Percentage values (other than 5050 and 100100)? what value do you want to copy for "AtlanticCroaker" & 100100? what value do you want to copy for "AtlanticCroaker" & 2525? what value do you want to copy for "SomeSpecies" & 5050?
... View more
09-07-2022
11:04 PM
|
0
|
2
|
2646
|
| Title | Kudos | Posted |
|---|---|---|
| 1 | 01-30-2023 09:57 AM | |
| 1 | 05-18-2023 12:51 AM | |
| 1 | 03-05-2023 12:46 PM | |
| 1 | 12-07-2022 07:01 AM | |
| 1 | 06-21-2022 08:27 AM |
| Online Status |
Offline
|
| Date Last Visited |
02-03-2024
06:14 PM
|