Select to view content in your preferred language

Enable data download in dashboard table when table type is "features" and data source is a data expression

702
2
01-30-2024 08:31 AM
Status: Open
erica_poisson
Frequent Contributor

Enable export/download consistently within Dashboards. The example below is specifically when a Data Expression is used with the Table Element of a Dashboard.

Data export/download currently works if you are referencing a hosted feature layer as the data source, OR if you use a data expression as the data source and select Table type = Grouped values. Data export/download does not work if you data source is a data expression and you select Table Type = Features. 

I've tested this with the same data expression. The data sources used within the expression all have the export capability enabled via the Item Details.

Here is the data expression:

// custom memorize function to increase performance of featureset
function Memorize(fs) {
    var temp_dict = {
        fields: Schema(fs)['fields'],
        geometryType: Schema(fs).geometryType,
        features: []
    }

    for (var f in fs) {
        var attrs = {}

        for (var attr in f) {
            attrs[attr] = Iif(TypeOf(f[attr]) == 'Date', Number(f[attr]), f[attr])
        }

        Push(
            temp_dict['features'],
            {attributes: attrs, geometry: Geometry(f)}
        )
    }

    return FeatureSet(Text(temp_dict))
}
// variable to define the portal URL
var portal = Portal("https://mass-eoeea.maps.arcgis.com");

 
//Quabbin and Ware Encroachments - internally shared layer w/ export enabled
var qEncroach = FeatureSetByPortalItem(portal,"1234abc",0,['Date_Found', 'Type', 'Encroachment_Priority', 'Description'],true);

//Wachusett and Sudbury Encroachments - internally shared layer w/ export enabled
var wEncroach = FeatureSetByPortalItem(portal,"5678def",0,['Date_Found', 'Type', 'Encroachment_Priority', 'Description'],true);

// Create a FeatureSet with all encroachments from Quabbin, Ware and Wachusett

var int_dict = {
    fields: [
        {'name': 'type', 'type': 'esriFieldTypeString'},
        {'name': 'edate', 'type': 'esriFieldTypeDate'},
        {'name': 'priority', 'type': 'esriFieldTypeString'},
        {'name': 'descript', 'type': 'esriFieldTypeString'}],
    geometryType: 'esriGeometryPoint',
    "spatialReference": {
        "wkid": 102100,
        "latestWkid": 3857
    }, 'features':[],
  };


// Fill intermediate FeatureSet with encroachment info
var i = 0;
for (var f in qEncroach) {
    int_dict.features[i] = {
       attributes: {
         'type': f["Type"],
         'edate': DateDiff(f["Date_Found"], Date(1970, 0, 1, 0, 0, 0), "milliseconds"),
         'priority': f["Encroachment_Priority"],
         'descript': f["Description"],
       },
       geometry: Geometry(f),
     }
     i++;
   };

for (var g in wEncroach) {
    int_dict.features[i] = {
       attributes: {
         'type': g["Type"],
         'edate': DateDiff(g["Date_Found"], Date(1970, 0, 1, 0, 0, 0), "milliseconds"),
         'priority': g["Encroachment_Priority"],
         'descript': g["Description"],
       },
       geometry: Geometry(g),
     }
     i++;
   };

Console(Text(int_dict));
var encroach_set = Memorize(FeatureSet(Text(int_dict)))

// Basins - public layer
var basins = Memorize(FeatureSetByPortalItem(portal, "987406d7d0614370b6493dfe58c9e62c", 0, ['District', 'Subbasin_Name'], true))

// create final featureset
var finalDict = {
  fields: [
    {name: "Encroach_Type", type: "esriFieldTypeString"},
    {name: "Encroach_Date", type: "esriFieldTypeDate"},
    {name: "Encroach_Priority", type: "esriFieldTypeString"},
    {name: "Encroach_Description", type: "esriFieldTypeString"},
    {name: "SubbasinName", type: "esriFieldTypeString"},
    {name: "DistrictName", type: "esriFieldTypeString"},
  ],
  geometryType:"esriGeometryPoint",
  "spatialReference": {
    "wkid":102100,
    "latestWkid":3857
  },
  features: [],
}

// intersect CMRs with basins to determine which basin each occured in
for(var e in encroach_set) {
  var i_basin = First(Intersects(e, basins))
  var i_basin_name = Iif(i_basin == null, "No basin", i_basin.Subbasin_Name)
  var i_basin_district = Iif(i_basin == null, "No district", i_basin.District)
  //add to array
  Push(finalDict['features'], 
  {attributes:{
    Encroach_Type: e['type'],
    Encroach_Date: e['edate'],
    Encroach_Priority: e['priority'],
    Encroach_Description: e['descript'],
    SubbasinName: i_basin_name,
    DistrictName: i_basin_district,
  }})
}
Console(Text(finalDict));
return FeatureSet(Text(finalDict))

 

Here are the settings used within the Table Element when download summarized data is an option for me to toggle under "General":

erica_poisson_0-1706632120475.png

 

Here are the settings used with a different Table Element when download summarized data is not an option for me to toggle under "General":

erica_poisson_1-1706632162133.png

 

Some additional details:

I am working in ArcGIS Online and using a data expression to bring two different feature layers together into a new FeatureSet. I need to provide information on individual records, so I can not use Table Type = Grouped Values. Both feature layers referenced in the data expression allow export/download (that was the first thing I checked). 

2 Comments
JulieCulligan

Agreed.  It would be valuable to have the same options available for feature as grouped values so that we don't need to create a second application for the users to grab data and information from. 

IanMackenzie

@erica_poisson    Did you figure out a workaround for this problem?   i.e., a way for user to pull data from the dashboard. 

My basic, clumsy solution is going to be to present the data in a list instead of a table with a delimiter included between the values.  

I will then train users on how to highlight the list contents, paste into an Excel spreadsheet, and use the "Text to Columns" function in Excel to separate the data back out into columns.  

I'm using a list instead of a table only because highlighting is easier, less prone to error, on the former than the latter.  Also, pasting from a Dashboard table into Excel  has poor results. Fairly straight forward from a Dashboard list, can even use shift key to select across a long list of items. 

I have other ideas  (see one below) but they are not viable given the effort involved, complexity  for sustainment, etc.

One idea was to create a new field and populate it with all the values split by a delimiter and then use this field for the Grouped values Category Field and if required some arbitrary field like ObjectID - Count for the value field (would end up being a count of 1 for every record).  I tried creating this new field on-the-fly by creating an expression in the layer in the associated map but unfortunately the Dashboard does not show these expressions as an option to choose.  I could add an actual field to the table and populate it with a calculated expression in a Field Maps Form at the time of record creation (this is the only way users enter data), but I think this is not worth the effort for an imperfect solution.