Select to view content in your preferred language

Arcade Expression throws Data Error / null

3993
21
07-31-2020 07:54 PM
MattCreaney
Occasional Contributor

I'm trying to cross reference work done on a site by the amount of time a vehicle was there.  I have this Arcade script, which tests ok in the script editor but on the map data table shows Data Error and in the popup is null.  Here's the script, can anyone please help to debug?

var Asset;
var DateOfVisit;

//Get Date of Commission, add to result
var DateOfCommission = Date(year($feature.CreationDate),month($feature.CreationDate),day($feature.CreationDate));
var result = "Date Of Commission = " + DateOfCommission;
Console($feature.CreationDate);
Console(DateOfCommission);

var VehicleIntersecting;
var FirstAsset;
var AssetGeometry;
var AssetArea;
var Buffer_Distance = 100;
var AssetID;
var BayID = $feature["bay_guid"];
Console(BayID);
var QueryBay = "GlobalID = '" + BayID + "'";
var QueryAsset;
Console(QueryBay);

// Get Associated Bay Record
var Bay = Filter(FeatureSetById($map, /* Production_database - Bay */ "Production_database_3775"), QueryBay);
Console(Bay)

// Find GUID of Associated Asset Record
for (var FilteredBay in Bay) {
var AssetID = FilteredBay.asset_guid
Console(AssetID);
var QueryAsset = "GlobalID = '" + AssetID + "'";
Console(QueryAsset);

// Get Associated Asset Record
var Asset = Filter(FeatureSetById($map, /* Production_database */ "Production_database_8049"), QueryAsset);
Console(Asset);
for (var FilteredAsset in Asset) {
var FirstAsset = First(Asset)
var AssetGeometry = Geometry(FirstAsset);
Console(AssetGeometry);

//Buffer 50m around Asset
var Asset_Area = Buffer(FirstAsset, Buffer_Distance, 'meters');
Console(Asset_Area);

//Find Vehicles that intersect Asset Bugger
var VehicleIntersecting = Intersects(FeatureSetById($map, /* Vehicle Locations */ "Vehicle_Locations_8121"), Asset_Area);
for (var VehicleStop in VehicleIntersecting) {

//Get Date of Visit
var DateOfVisit = Date(year(VehicleStop.date_visited), month(VehicleStop.date_visited), day(VehicleStop.date_visited));
Console (DateOfVisit);
Console (DateOfCommission);
// Add Date of Visit to Result
var result =+ " //// Date Of Visit = " + DateOfVisit;
Console(result);

//Add Visit Duration if Dates of Visit and Commission Match
if (DateOfVisit == DateOfCommission) {
var result =+ " //// Visit Duration = " + VehicleStop.visit_duration;
}
}

}
}
return result;

Tags (1)
0 Kudos
21 Replies
XanderBakker
Esri Esteemed Contributor

Hi mcreaney ,

I still haven't had much time to look at it, but I do see a couple of things. Most importantly, I don't really understand to what layer the "Assets" refer. Can you tell me what it is called in the web map? Are you sure they have geometry? When I look at what the geometry returns, I don't have any result. 

0 Kudos
MattCreaney
Occasional Contributor

Hi Xander Bakker

Assets are the production database layer which has geography.

0 Kudos
XanderBakker
Esri Esteemed Contributor

Hi Matt Creaney ,

In that case, it does not make sense to start with the assets and find the bays and use the first bay to find the assets. Or does it?

Have a look at the code below and an example result to see if it comes anywhere near what you are looking for.

Using the following expression:

var Buffer_Distance = 100;
var dateFormat = "MM/DD/Y";
var result = "";

//Get Date of Commission
var DateOfCommission = Text($feature.CreationDate, dateFormat);
Console(DateOfCommission);

var Asset_buffer = Buffer($feature, Buffer_Distance, 'meters');
Console("Asset Area is " + Area(Asset_buffer, "square-meters"));

// Find Vehicles that intersect Asset Buffer
var VehicleIntersecting = Intersects(FeatureSetById($map, /* Vehicle Locations */ "Vehicle_Locations_8121", ["date_visited", "visit_duration"], false), Asset_buffer);
var IntersectCount = Count(VehicleIntersecting);
Console("Intersect Count = " + IntersectCount);
        
// If an intersecting vehicle record is found
var cnt = 0;
result = "Date of Commission: " + DateOfCommission + TextFormatting.NewLine;
if (IntersectCount > 0) {
	for (var VehicleStop in VehicleIntersecting) {
		
		//Get Date of Visit
		var DateOfVisit = Text(VehicleStop["date_visited"], dateFormat);
		Console("Date of Visit = " + DateOfVisit);
		Console("Date of Commission = " + DateOfCommission);
			
		// Set result as Visit Duration if Dates of Visit and Commission Match
		if (DateOfVisit == DateOfCommission) {
			result += " - Duration: " + VehicleStop["visit_duration"] + "h" + TextFormatting.NewLine;
		} else {
		    // switch this off, since you are not interesting in this
		    cnt += 1;
			//result += " - Duration: (" + DateOfVisit + ") = " + VehicleStop["visit_duration"] + "h" + TextFormatting.NewLine;
			Console("other date: " + VehicleStop["visit_duration"]);
		}
	}
    if (cnt > 0) {
        result += " - " + cnt + " vehicle stops found at different dates..." ;        
    }	
} else {
	// handle: no interecting vehicles found
	result = "No Intersecting Vehicle Records Found with the same date";
}

return result;
0 Kudos
MattCreaney
Occasional Contributor

Hi Xander Bakker‌ - thanks, thats exactly what I'm looking for, except I want the expression on the Product Commission ITP layer..

0 Kudos
XanderBakker
Esri Esteemed Contributor

Hi Matt Creaney ,

Since the Product Commission ITP "layer" is a table, it does not have a pop-up. So it can't start there. I assume you start at the Production Database point feature layer. From your last code I deduce the following:

  • You read the creation date of the Production Database point feature the user clicks on
  • You get the related bay from the bay table
  • Based on the first related bay, you access the Production Database point feature layer again and get the first "asset"
  • You buffer the asset geometry and look for vehicle stops in the buffer
  • You return information of the vehicle stop when the date of visit is equal to the data of commission. 

The part that I can't wrap my head around is why you would want to start with an asset (Production Database point feature) and use the bays to get back to a Production Database point feature (asset)?

0 Kudos
MattCreaney
Occasional Contributor

Hi Xander Bakker

The expression I wrote is in the Product Commission ITP layer - I am testing through a web mapping application I've just added to the group. In other maps I have using the same database I have many many scripts that successfully execute although none of these access related tables.  The popups are accessed through the relate table links.

In this application the expression is supposed to appear under the asset name..

0 Kudos
XanderBakker
Esri Esteemed Contributor

Hi Matt Creaney ,

As far as I have seen you only shared a map with me and the layers. The map has two point feature layers:

  • Product database
  • Vehicle locations

And the map also has a list of tables. When I click on a feature of the product database not all tables are presented and related tables. Especially the table Product Commission ITP does not appear as related table in the map (no sure of this is because the list is too long). 

In order to see how you workflow works, I would need access to the App that you showed. I still believe that it might be more effective to use the Arcade expression to extract all the necessary information and present it in the pop-up, although this depend how the application is configured. 

0 Kudos
MattCreaney
Occasional Contributor

Xander Bakker‌ An Asset (production database feature) has 1 or more Bays and a Bay has 1 or more Product Commission ITPs, so you have to get to the ITP via the Bay record.

I've shared the app to the group, not sure why you can't see it.  Here's the URL ArcGIS Web Application 

0 Kudos
XanderBakker
Esri Esteemed Contributor

Hi Matt Creaney ,

I have no access to the WebApp.

Based on your last comment I did a little test, taking the production database feature (the asset) and get the related bays and for each bay get the related Product Commission ITP and for each  Product Commission ITP  get back to the assets (in this case I used a query based on the asset name) and did a buffer around each asset to get the vehicles within the buffer:

// An Asset (production database feature) has 1 or more Bays 
// and a Bay has 1 or more Product Commission ITPs, 
// so you have to get to the ITP via the Bay record.

var result = "";
var Buffer_Distance = 100;
var dateFormat = "MM/DD/Y";
var DateOfCommission = Text($feature.CreationDate, dateFormat);

result = "Asset OID:" + $feature.OBJECTID;
result += TextFormatting.NewLine + "Asset name:" + $feature["asset_name"];
result += TextFormatting.NewLine + "DateOfCommission:" + DateOfCommission;

var bays = FeatureSetByRelationshipName($feature, "Bay");
result += TextFormatting.NewLine + " # bays count:" + Count(bays);
for (var bay in bays) {
    result += TextFormatting.NewLine + " # bay.bay_number:" + bay.bay_number;
    var itps = FeatureSetByRelationshipName(bay, "Product_Commission_ITP");
    result += TextFormatting.NewLine + " ## itps count:" + Count(itps);
    for (var itp in itps) {
        var assetname = itp.asset_name;
        result += TextFormatting.NewLine + " ## itp asset_name:" + assetname;
        var sql = "asset_name = @assetname";
        var assets = Filter($layer, sql);
        result += TextFormatting.NewLine + " ## assets count:" + Count(assets);
        for (var asset in assets) {
            result += TextFormatting.NewLine + " ### asset OID:" + asset.OBJECTID;
            var assetbuffer = Buffer(asset, Buffer_Distance, 'meters');
            var vehicles = Intersects(FeatureSetById($map, "Vehicle_Locations_8121"), assetbuffer);
            result += TextFormatting.NewLine + " #### vehicles count:" + Count(vehicles);
            for (var vehicle in vehicles) {
                result += TextFormatting.NewLine + " ##### vehicle:" + vehicle.vehicle;
                var visited = Text(vehicle["date_visited"], dateFormat);
                var duration = vehicle["visit_duration"];
                result += TextFormatting.NewLine + " ##### visited:" + visited;
                result += TextFormatting.NewLine + " ##### duration:" + duration;
            }
        }
    }    
}

return result;

However, no matter where I look it will only find a single asset:

Asset OID:2450
Asset name:RO5310
DateOfCommission:07/20/2020
# bays count:1
# bay.bay_number:1
## itps count:1
## itp asset_name:RO5310
## assets count:1
### asset OID:2450
#### vehicles count:4
##### vehicle:RV20 - Matt B
##### visited:07/20/2020
##### duration:2:08:35
##### vehicle:RV1 - Locky
##### visited:07/23/2020
##### duration:0:26:01
##### vehicle:RV10 - Nibs
##### visited:07/27/2020
##### duration:0:12:44
##### vehicle:RV9 - Macca
##### visited:07/30/2020
##### duration:3:54:38 

Can you point out a location where you have either multiple bays or multiple product commission ITP's?

0 Kudos
MattCreaney
Occasional Contributor

Sorry Xander Bakker‌ - I should say that an asset has a 1:M relationship to bays and a bay has a 1:M relationship to product commission ITP but this can be zero (commission not yet completed).

Asset RG-2-622 has multiple bays and these do have ITPs although I'm not sure if the dates will line up as these records were uploaded rather than created on site.  Not sure if this affects your test.

0 Kudos