-
Notifications
You must be signed in to change notification settings - Fork 120
ProSnippets Arcade
UmaHarano edited this page Nov 12, 2025
·
5 revisions
Language: C#
Subject: Arcade
Contributor: ArcGIS Pro SDK Team <[email protected]>
Organization: Esri, http://www.esri.com
Date: 11/7/2025
ArcGIS Pro: 3.6
Visual Studio: 2022
//Consult https://github.com/Esri/arcade-expressions/ and
//https://developers.arcgis.com/arcade/ for more examples
//and arcade reference
// Note: the following should be embedded in a QueuedTask.Run() statement
{
//construct an expression
var query = @"Count($layer)";//count of features in "layer"
//construct a CIMExpressionInfo
var arcade_expr = new CIMExpressionInfo()
{
Expression = query.ToString(),
//Return type can be string, numeric, or default
//When set to default, add-in is responsible for determining
//the return type
ReturnType = ExpressionReturnType.Default
};
//Construct an evaluator
//select the relevant profile - it must support Pro and it must
//contain any profile variables you are using in your expression.
//Consult: https://developers.arcgis.com/arcade/profiles/
using var arcade = ArcadeScriptEngine.Instance.CreateEvaluator(
arcade_expr, ArcadeProfile.Popups);
//Provision values for any profile variables referenced...
//in our case '$layer'
var variables = new List<KeyValuePair<string, object>>() {
new("$layer", featureLayer)
};
//evaluate the expression
try
{
var result = arcade.Evaluate(variables).GetResult();
System.Diagnostics.Debug.WriteLine($"Result: {result}");
}
//handle any exceptions
catch (InvalidProfileVariableException)
{
//something wrong with the profile variable specified
//TODO...
}
catch (EvaluationException)
{
//something wrong with the query evaluation
//TODO...
}
}//Consult https://github.com/Esri/arcade-expressions/ and
//https://developers.arcgis.com/arcade/ for more examples
//and arcade reference
// Note: the following should be embedded in a QueuedTask.Run() statement
{
//construct an expression
var query = @"$feature.AreaInAcres * 43560.0";//convert acres to ft 2
//construct a CIMExpressionInfo
var arcade_expr = new CIMExpressionInfo()
{
Expression = query.ToString(),
//Return type can be string, numeric, or default
//When set to default, add-in is responsible for determining
//the return type
ReturnType = ExpressionReturnType.Default
};
//Construct an evaluator
//select the relevant profile - it must support Pro and it must
//contain any profile variables you are using in your expression.
//Consult: https://developers.arcgis.com/arcade/profiles/
using var arcade = ArcadeScriptEngine.Instance.CreateEvaluator(
arcade_expr, ArcadeProfile.Popups);
//we are evaluating the expression against all features
using var rc = featureLayer.Search();
while (rc.MoveNext())
{
//Provision values for any profile variables referenced...
//in our case '$feature'
var variables = new List<KeyValuePair<string, object>>() {
new("$feature", rc.Current)
};
//evaluate the expression (per feature in this case)
try
{
var result = arcade.Evaluate(variables).GetResult();
var val = ((double)result).ToString("0.0#");
System.Diagnostics.Debug.WriteLine(
$"{rc.Current.GetObjectID()} area: {val} ft2");
}
//handle any exceptions
catch (InvalidProfileVariableException)
{
//something wrong with the profile variable specified
//TODO...
}
catch (EvaluationException)
{
//something wrong with the query evaluation
//TODO...
}
}
}//Consult https://github.com/Esri/arcade-expressions/ and
//https://developers.arcgis.com/arcade/ for more examples
//and arcade reference
// Note: the following should be embedded in a QueuedTask.Run() statement
{
//construct a query
var query = new StringBuilder();
var layer_name = "USA Current Wildfires - Current Incidents";
//https://developers.arcgis.com/arcade/function-reference/featureset_functions/
query.AppendLine(
$"var features = FeatureSetByName($map,'{layer_name}', ['*'], false);");
query.AppendLine("return Count(features);");
//construct a CIMExpressionInfo
var arcade_expr = new CIMExpressionInfo()
{
Expression = query.ToString(),
//Return type can be string, numeric, or default
//When set to default, add-in is responsible for determining
//the return type
ReturnType = ExpressionReturnType.Default
};
//Construct an evaluator
//select the relevant profile - it must support Pro and it must
//contain any profile variables you are using in your expression.
//Consult: https://developers.arcgis.com/arcade/profiles/
using var arcade = ArcadeScriptEngine.Instance.CreateEvaluator(
arcade_expr, ArcadeProfile.Popups);
//Provision values for any profile variables referenced...
//in our case '$map'
var variables = new List<KeyValuePair<string, object>>() {
new("$map", map)
};
//evaluate the expression
try
{
var result = arcade.Evaluate(variables).GetResult();
System.Diagnostics.Debug.WriteLine($"Result: {result}");
}
//handle any exceptions
catch (InvalidProfileVariableException)
{
//something wrong with the profile variable specified
//TODO...
}
catch (EvaluationException)
{
//something wrong with the query evaluation
//TODO...
}
}//Consult https://github.com/Esri/arcade-expressions/ and
//https://developers.arcgis.com/arcade/ for more examples
//and arcade reference
// Note: the following should be embedded in a QueuedTask.Run() statement
{
//construct a query
var query = new StringBuilder();
//https://developers.arcgis.com/arcade/function-reference/featureset_functions/
query.AppendLine(
"var features = Filter($layer, 'DailyAcres is not NULL');");
query.AppendLine("return Count(features);");
//construct a CIMExpressionInfo
var arcade_expr = new CIMExpressionInfo()
{
Expression = query.ToString(),
//Return type can be string, numeric, or default
//When set to default, add-in is responsible for determining
//the return type
ReturnType = ExpressionReturnType.Default
};
//Construct an evaluator
//select the relevant profile - it must support Pro and it must
//contain any profile variables you are using in your expression.
//Consult: https://developers.arcgis.com/arcade/profiles/
using var arcade = ArcadeScriptEngine.Instance.CreateEvaluator(
arcade_expr, ArcadeProfile.Popups);
//Provision values for any profile variables referenced...
//in our case '$layer'
var variables = new List<KeyValuePair<string, object>>() {
new("$layer", featureLayer)
};
//evaluate the expression
try
{
var result = arcade.Evaluate(variables).GetResult();
System.Diagnostics.Debug.WriteLine($"Result: {result}");
}
//handle any exceptions
catch (InvalidProfileVariableException)
{
//something wrong with the profile variable specified
//TODO...
}
catch (EvaluationException)
{
//something wrong with the query evaluation
//TODO...
}
}//Consult https://github.com/Esri/arcade-expressions/ and
//https://developers.arcgis.com/arcade/ for more examples
//and arcade reference
// Note: the following should be embedded in a QueuedTask.Run() statement
{
//construct a query
var query = new StringBuilder();
//https://developers.arcgis.com/arcade/function-reference/math_functions
query.AppendLine("var features = Filter($layer, 'DailyAcres is not NULL');");
query.AppendLine("var count_feat = Count(features);");
query.AppendLine("var sum_feat = Sum(features, 'DailyAcres');");
query.AppendLine("var max_feat = Max(features, 'DailyAcres');");
query.AppendLine("var min_feat = Min(features, 'DailyAcres');");
query.AppendLine("var avg_feat = Average(features, 'DailyAcres');");
query.AppendLine("var answer = [count_feat, sum_feat, max_feat, min_feat, avg_feat]");
query.AppendLine("return Concatenate(answer,'|');");
//construct a CIMExpressionInfo
var arcade_expr = new CIMExpressionInfo()
{
Expression = query.ToString(),
//Return type can be string, numeric, or default
//When set to default, add-in is responsible for determining
//the return type
ReturnType = ExpressionReturnType.Default
};
//Construct an evaluator
//select the relevant profile - it must support Pro and it must
//contain any profile variables you are using in your expression.
//Consult: https://developers.arcgis.com/arcade/profiles/
using var arcade = ArcadeScriptEngine.Instance.CreateEvaluator(
arcade_expr, ArcadeProfile.Popups);
//Provision values for any profile variables referenced...
//in our case '$layer'
var variables = new List<KeyValuePair<string, object>>() {
new("$layer", featureLayer)
};
//evaluate the expression
try
{
var result = arcade.Evaluate(variables).GetResult();
System.Diagnostics.Debug.WriteLine($"Result: {result}");
}
//handle any exceptions
catch (InvalidProfileVariableException)
{
//something wrong with the profile variable specified
//TODO...
}
catch (EvaluationException)
{
//something wrong with the query evaluation
//TODO...
}
}//Consult https://github.com/Esri/arcade-expressions/ and
//https://developers.arcgis.com/arcade/ for more examples
//and arcade reference
// Note: the following should be embedded in a QueuedTask.Run() statement
{
//construct a query
var query = new StringBuilder();
//https://developers.arcgis.com/arcade/function-reference/featureset_functions/
//Assume we have two layers - a polygon and a points layer.
//Select all points within the relevant polygon boundaries and sum the count
query.AppendLine("var results = [];");
query.AppendLine("var polygons = FeatureSetByName($map, 'PolygonLayerName', ['*'], true);");
query.AppendLine("var sel_polygons = Filter(polygons, 'IDField IN (2, 15, 16)');");
query.AppendLine("for(var polygon in sel_polygons) {");
query.AppendLine(" var name = polygon.Name;");
query.AppendLine(" var PointsInPolygon = Count(Intersects($layer, Geometry(polygon)));");
query.AppendLine(" Insert(results, 0, pointsInPolygon);");
query.AppendLine(" Insert(results, 0, name);");
query.AppendLine("}");
query.AppendLine("return Concatenate(results,'|');");
//construct a CIMExpressionInfo
var arcade_expr = new CIMExpressionInfo()
{
Expression = query.ToString(),
//Return type can be string, numeric, or default
//When set to default, add-in is responsible for determining
//the return type
ReturnType = ExpressionReturnType.Default
};
//Construct an evaluator
//select the relevant profile - it must support Pro and it must
//contain any profile variables you are using in your expression.
//Consult: https://developers.arcgis.com/arcade/profiles/
using var arcade = ArcadeScriptEngine.Instance.CreateEvaluator(
arcade_expr, ArcadeProfile.Popups);
//Provision values for any profile variables referenced...
//in our case '$layer' and '$map'
List<KeyValuePair<string, object>> variables = [
new("$layer", pointsLayer),
new("$map", map)
];
//evaluate the expression
try
{
var result = arcade.Evaluate(variables).GetResult();
var results = result.ToString().Split('|', StringSplitOptions.None);
var entries = results.Length / 2;
int i = 0;
for (var e = 0; e < entries; e++)
{
var name = results[i++];
var count = results[i++];
System.Diagnostics.Debug.WriteLine($"'{name}' points count: {count}");
}
}
//handle any exceptions
catch (InvalidProfileVariableException)
{
//something wrong with the profile variable specified
//TODO...
}
catch (EvaluationException)
{
//something wrong with the query evaluation
//TODO...
}
}string ArcadeLabelingExpressionName = "My Arcade Label Expression";
//Consult https://github.com/Esri/arcade-expressions/ and
//https://developers.arcgis.com/arcade/ for more examples
//and arcade reference
// Note: the following should be embedded in a QueuedTask.Run() statement
{
//Given a layer that has an arcade labeling
//expression and we evaluate it interactively...
var def = featureLayer.GetDefinition() as CIMFeatureLayer;
//Get the label class
var label_class = def.LabelClasses
.FirstOrDefault(lc =>
{
return lc.Name == ArcadeLabelingExpressionName &&
lc.ExpressionEngine == LabelExpressionEngine.Arcade;
});
if (label_class == null)
return;
//evaluate the label expression against the features
var expr_info = new CIMExpressionInfo()
{
Expression = label_class.Expression,
ReturnType = ExpressionReturnType.String
};
//https://developers.arcgis.com/arcade/profiles/labeling/
using var arcade = ArcadeScriptEngine.Instance.CreateEvaluator(
expr_info, ArcadeProfile.Labeling);
//loop through the features
using var rc = featureLayer.Search();
while (rc.MoveNext())
{
var variables = new List<KeyValuePair<string, object>>() {
new("$feature", rc.Current)
};
var result = arcade.Evaluate(variables).GetResult();
//output
System.Diagnostics.Debug.WriteLine(
$"[{rc.Current.GetObjectID()}]: {result}");
}
}//Consult https://github.com/Esri/arcade-expressions/ and
//https://developers.arcgis.com/arcade/ for more examples
//and arcade reference
// Note: the following should be embedded in a QueuedTask.Run() statement
{
//Assume we have a layer that is using Visual Variable
//expressions that we want to evaluate interactively...
var def = featureLayer.GetDefinition() as CIMFeatureLayer;
//Most all feature renderers have a VisualVariable collection
var renderer = def.Renderer as CIMUniqueValueRenderer;
List<CIMVisualVariable> vis_variables = renderer.VisualVariables?.ToList() ??
[];
if (vis_variables.Count == 0)
return;//there are none
var vis_var_with_expr = new Dictionary<string, string>();
//see if any are using expressions
foreach (var vv in vis_variables)
{
if (vv is CIMColorVisualVariable cvv)
{
if (!string.IsNullOrEmpty(cvv.ValueExpressionInfo?.Expression))
vis_var_with_expr.Add("Color", cvv.ValueExpressionInfo?.Expression);
}
else if (vv is CIMTransparencyVisualVariable tvv)
{
if (!string.IsNullOrEmpty(tvv.ValueExpressionInfo?.Expression))
vis_var_with_expr.Add("Transparency", tvv.ValueExpressionInfo?.Expression);
}
else if (vv is CIMSizeVisualVariable svv)
{
if (!string.IsNullOrEmpty(svv.ValueExpressionInfo?.Expression))
vis_var_with_expr.Add("Outline", svv.ValueExpressionInfo?.Expression);
}
}
if (vis_var_with_expr.Count == 0)
return;//there aren't any with expressions
//loop through the features (outer)
//per feature evaluate each visual variable.... (inner)
//....
//the converse is to loop through the expressions (outer)
//then per feature evaluate the expression (inner)
using RowCursor rc = featureLayer.Search();
while (rc.MoveNext())
{
foreach (var kvp in vis_var_with_expr)
{
var expr_info = new CIMExpressionInfo()
{
Expression = kvp.Value,
ReturnType = ExpressionReturnType.Default
};
//per feature eval each expression...
using ArcadeEvaluator arcade = ArcadeScriptEngine.Instance.CreateEvaluator(
expr_info, ArcadeProfile.Visualization);
var variables = new List<KeyValuePair<string, object>>() {
new("$feature", rc.Current)
};
//note 2D maps can also have view scale...
//...if necessary...
if (mv.ViewingMode == MapViewingMode.Map)
{
variables.Add(new("$view.scale", mv.Camera.Scale));
}
var result = arcade.Evaluate(variables).GetResult().ToString();
//output
System.Diagnostics.Debug.WriteLine(
$"[{rc.Current.GetObjectID()}] '{kvp.Key}': {result}");
}
}
}// Note: the following should be embedded in a QueuedTask.Run() statement
{
// GetRenderer from Layer (assumes it is a unique value renderer)
if (featureLayer.GetRenderer() is not CIMUniqueValueRenderer uvRenderer)
{
// not a unique value renderer, leave
return;
}
//layer has STATE_NAME field if using the community sample Data\Admin\AdminSample.aprx
string expression = "if ($view.scale > 21000000) { return $feature.STATE_NAME } else { return 'All' }";
CIMExpressionInfo updatedExpressionInfo = new()
{
Expression = expression,
Title = "Custom" // can be any string used for UI purpose.
};
//set the renderer's expression
uvRenderer.ValueExpressionInfo = updatedExpressionInfo;
//SetRenderer on Layer
featureLayer.SetRenderer(uvRenderer);
}// Note: the following should be embedded in a QueuedTask.Run() statement
{
//Get the layer's definition, using the community sample Data\Admin\AdminSample.aprx
if (featureLayer.GetDefinition() is not CIMFeatureLayer lyrDefn)
{
// not a feature layer, leave
return;
}
//Get the label classes - we need the first one
var listLabelClasses = lyrDefn.LabelClasses.ToList();
var theLabelClass = listLabelClasses.FirstOrDefault();
//set the label class Expression to use the Arcade expression
theLabelClass.Expression = "return $feature.STATE_NAME + TextFormatting.NewLine + $feature.POP2000;";
//Set the label definition back to the layer.
featureLayer.SetDefinition(lyrDefn);
}//Consult https://github.com/Esri/arcade-expressions/ and
//https://developers.arcgis.com/arcade/profiles/attribute-rules/ for
//more examples and arcade reference
// Note: the following should be embedded in a QueuedTask.Run() statement
{
//Retrieve the desired feature class/table
FeatureClassDefinition def = featureLayer.GetFeatureClass().GetDefinition();
//get the desired attribute rule whose expression is to be evaluated.
//AttributeRuleType.All, Calculation, Constraint, Validation
AttributeRuleDefinition validation_rule = def.GetAttributeRules(
AttributeRuleType.Validation).FirstOrDefault();
if (validation_rule == null)
return;
//Get the expression
var expr = validation_rule.GetScriptExpression();
//construct a CIMExpressionInfo
var arcade_expr = new CIMExpressionInfo()
{
Expression = expr,
//Return type can be string, numeric, or default
ReturnType = ExpressionReturnType.Default
};
System.Diagnostics.Debug.WriteLine($"Evaluating {expr}:");
//Construct an evaluator
//we are using ArcadeProfile.AttributeRules profile...
//Consult: https://developers.arcgis.com/arcade/profiles/
using var arcade = ArcadeScriptEngine.Instance.CreateEvaluator(
arcade_expr, ArcadeProfile.AttributeRuleValidation);
//we are evaluating the expression against all features
using var rc = featureLayer.Search();
while (rc.MoveNext())
{
// Provision values for any profile variables referenced...
// we assume '$feature' here
//...use arcade.ProfileVariablesUsed() if necessary...
var variables = new List<KeyValuePair<string, object>>() {
new("$feature", rc.Current)
};
//evaluate the expression per feature
try
{
var result = arcade.Evaluate(variables).GetResult();
//'Validation' attribute rules return true or false...
var valid = bool.Parse(result.ToString());
System.Diagnostics.Debug.WriteLine(
$"{rc.Current.GetObjectID()} valid: {valid}");
}
//handle any exceptions
catch (InvalidProfileVariableException)
{
//something wrong with the profile variable specified
//TODO...
}
catch (EvaluationException)
{
//something wrong with the query evaluation
//TODO...
}
}
}
Home | API Reference | Requirements | Download | Samples | Snippets