Filter Data on Map and then Export Filtered Data to CSV

793
9
Jump to solution
04-05-2024 01:24 PM
RezaTehranifar2
New Contributor III

I have an application that has filter widgets that interacts with the map on the page. The client would now like to be able to export the data to csv. I am a little tight in space I dont want nor need to see the data in a table. Has someone created a widget that does this? I dont think I found one yet but I will continue looking while I wait for responses.
Is there a hack? Ideally I just want a button that says export to csv.

0 Kudos
1 Solution

Accepted Solutions
JeffreyThompson2
MVP Regular Contributor
function customExportCSV() {
    let query = featureLayer.createQuery()
    query.where = '1=1'
    let csv = ''
    let headers = ''

    featureLayer.queryFeatures(query).then((featureSet) => {
        headers = Object.keys(featureSet.features[0].attributes).join(',')

        for (let i = 0; i < featureSet.features.length; i++) {
            const data = Object.values(featureSet.features[i].attributes).join(',')
            csv += data + '\n'
        }

        csv = headers + '\n' + csv

        downloadCSV(csv)
    })   
}   

function downloadCSV(csv) {
    const csvFile = new Blob([csv], { type: 'text/csv' });
    const downloadLink = document.createElement("a");
    downloadLink.download = 'search_results.csv';
    downloadLink.href = window.URL.createObjectURL(csvFile);
    downloadLink.style.display = "none";

    document.body.appendChild(downloadLink);
    downloadLink.click();
}  

Here's my function for downloading a csv from a FeatureLayer.

GIS Developer
City of Arlington, Texas

View solution in original post

9 Replies
JeffreyThompson2
MVP Regular Contributor
function customExportCSV() {
    let query = featureLayer.createQuery()
    query.where = '1=1'
    let csv = ''
    let headers = ''

    featureLayer.queryFeatures(query).then((featureSet) => {
        headers = Object.keys(featureSet.features[0].attributes).join(',')

        for (let i = 0; i < featureSet.features.length; i++) {
            const data = Object.values(featureSet.features[i].attributes).join(',')
            csv += data + '\n'
        }

        csv = headers + '\n' + csv

        downloadCSV(csv)
    })   
}   

function downloadCSV(csv) {
    const csvFile = new Blob([csv], { type: 'text/csv' });
    const downloadLink = document.createElement("a");
    downloadLink.download = 'search_results.csv';
    downloadLink.href = window.URL.createObjectURL(csvFile);
    downloadLink.style.display = "none";

    document.body.appendChild(downloadLink);
    downloadLink.click();
}  

Here's my function for downloading a csv from a FeatureLayer.

GIS Developer
City of Arlington, Texas
RezaTehranifar2
New Contributor III

This is great. Thanks!

This is assuming there is only one layer in the map. Correct? My map has multiple layers.

0 Kudos
JeffreyThompson2
MVP Regular Contributor

It will download data from whatever feature layer is assigned to the variable featureLayer. To make it more flexible, make featureLayer a parameter of the customExportCSV function, then create another function that finds a feature layer from a user input and calls customExportCSV(featureLayer).

GIS Developer
City of Arlington, Texas
0 Kudos
RezaTehranifar2
New Contributor III

Thanks. I am so so on JS, so I may hardcoded as you have it above at first, but I will work on the additional code to make it for flexible. Thank you for the outline of that part.

0 Kudos
ShahranNewaz
New Contributor

Hey, so I'm currently working on this, and I just need a little help as I'm not too familiar with esri. In regards to the featureLayer variable, how are you pulling the layer from the map and assigning it to the variable?

0 Kudos
JeffreyThompson2
MVP Regular Contributor

If you added the layer to the map, you can use the variable you created at assignment.

If you need to get a layer out of the map, this line of code should work, assuming you have captured the mapView created by Experience Builder to the jimuMapView variable and found the correct id of the layer to plug into the string.

const featureLayer = jimuMapView.view.map.findLayerById('layerId')

 

GIS Developer
City of Arlington, Texas
0 Kudos
ShahranNewaz
New Contributor

This is the code I have. I'm saving the mapView state into jimuMapView variable in line 12. But, Im running into an "Property 'createQuery/queryFeatures()' does not exist on type 'Layer'." on lines 23 and 28. Can you take a look thx

 

import React from 'react';
import { AllWidgetProps } from 'jimu-core';
import Setting from '../setting/setting';
import { UseDataSource } from 'jimu-core'
import { JimuMapViewComponent, type JimuMapView } from 'jimu-arcgis'


const { useState } = React


const Widget = (props: AllWidgetProps<unknown>) => {
  const [jimuMapView, setJimuMapView] = useState<JimuMapView>()

  const buttonStyle = {
    fontSize: '',
    padding: '10px 20px',
    borderRadius: '5px',
  }

  function customExportCSV() {

    const featureLayer = jimuMapView.view.map.findLayerById('layerId');
    let query = featureLayer.createQuery();
    query.where = '1=1'
    let csv = ''
    let headers = ''

    featureLayer.queryFeatures(query).then((featureSet) => {
      headers = Object.keys(featureSet.features[0].attributes).join(',')

      for (let i = 0; i < featureSet.features.length; i++) {
        const data = Object.values(featureSet.features[i].attributes).join(',')
        csv += data + '\n'
      }

      csv = headers + '\n' + csv

      downloadCSV(csv)
    })
  }

    function downloadCSV(csv) {
      const csvFile = new Blob([csv], { type: 'text/csv' });
      const downloadLink = document.createElement("a");
      downloadLink.download = 'search_results.csv';
      downloadLink.href = window.URL.createObjectURL(csvFile);
      downloadLink.style.display = "none";

      document.body.appendChild(downloadLink);
      downloadLink.click();
    }
  }

  return (
    <div className="widget-demo jimu-widget m-2">
      <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css"></link>
      <div className='inside-card'>
        <header>{Setting.value}</header>
        <Button style={buttonStyle} onClick={customExportCSV}>Export Data</Button>
      </div>
    </div>
  )
}

export default Widget;

 

0 Kudos
JeffreyThompson2
MVP Regular Contributor

https://community.esri.com/t5/experience-builder-tips-and-tricks/boilerplate-for-a-map-related-custo...

You aren't actually capturing the jimuMapView with your code. The easiest way to fix this would be to start over with this boilerplate code and add the csv function to it.

GIS Developer
City of Arlington, Texas
0 Kudos
MK13
by
Occasional Contributor

@JeffreyThompson2 after applying the where clause and running queryFeatures, how do you get the mapview to update and show the filtered layer? 

0 Kudos