Reporting

4256
4
01-05-2015 01:11 PM
jaykapalczynski
Frequent Contributor

I am running a couple queries which are returning results to a Grid as seen below.

Everything works great....But now I want to push those results into some sort of exportable/viewable report.  Maybe a PDF export that can be downloaded.  How can I do this and format the report? 

Has anyone tackled this and have some advise or examples?

Thanks and happy new year

var query_troutreach = new Query();

query_troutreach.geometry = bufferGeometry;

flVAFWIS_troutreach.selectFeatures(query_troutreach, FeatureLayer.SELECTION_NEW, function(results){

          });

flVAFWIS_troutreach.queryFeatures(query_troutreach, function (featureSet) {

         updateGrid_troutreach(featureSet);

   });

    function updateGrid_troutreach(featureSet) {

        var data = arrayUtils.map(featureSet.features, function (entry, i) {

          return {

            Waterbody: entry.attributes.Waterbody,

            id: entry.attributes.OBJECTID,

            Comments: entry.attributes.Comments

          };

        });

        // If you use a store...

        dataStore = new Memory({

                "data": data,

                "idProperty": "id"

        });

        gridNoColumnSets_troutreach.set("store", dataStore);

        gridNoColumnSets_troutreach.startup();

0 Kudos
4 Replies
jaykapalczynski
Frequent Contributor

Has anyone done any kind of reporting from Javascript api?  from a selected set of data?

0 Kudos
SteveCole
Frequent Contributor

Hi Jay,

I do some reporting within the JS API but probably not in the way you're probably thinking. Here's the basic idea:

Upon a user mouse click of a button within my app, it performs queries against 3 different census datasets using deferred lists. Once the results are returned, I build the "report" on the fly by creating DOM objects in a secondary browser window (a popup). In the onClick event for the button, you'd create the popup browser window and assign it to a global variable:

//The new browser window must be opened in the function called by the 'onClick' event so 
//the new window is created here and its associated variable is created with a global scope.
//Calculate the center of the screen for placement of the new window 

var center_left = (screen.width / 2) - (1100 / 2); 
var center_top = (screen.height / 2) - (600 / 2); 
newWindow = window.open('demographicReport.html','mywindow','width=1100,height=600,menubar=yes,scrollbars=yes,left=' + center_left + ',top=' + center_top);

In the code above, demographicReport.html is a real HTML file but it's content doesn't really matter. It's only loaded as the initial source for the new window. Once the window is opened, the contents are cleaned out using DOM functions and then my report is constructed. So, in the callback function for the deferredList, I have code to erase the HTML and insert new HTML:

//Create the string based version of the HTML page template 
var bodyContent; 
bodyContent = returnTractHtmlReportTemplate();    
//Open the new window and obtain a reference to it's DOM 
theDocument = newWindow.document; 
//Swap out the empty DOM of the browser for a string based version of the HTML template 
theDocument.open("text/html","replace"); 
theDocument.write(bodyContent); 
theDocument.close();

Once you have the basic HTML set up, you can now use standard JS to add or edit DOM elements:

//Now begin editing/adding page elements as needed 
theDocument.getElementById("prjName").innerHTML = rptProjectName; 
theDocument.getElementById("tractCount").innerHTML = raceResults.length;

It's involved and tedious but it will get the job done. Your user can then print the web page to a PDF if they want to save it for later. Attached is an example output of my process.

0 Kudos
jaykapalczynski
Frequent Contributor

THANK YOU FOR YOUR RESPONSE

gonna take me a bit to wrap my head around that....still confused...

So you have an HTML page all formatted and then pushing variables to that html page?  Not understanding how you are moving the data from one page to the next...

Whats this calling:

       returnTractHtmlReportTemplate();

0 Kudos
SteveCole
Frequent Contributor

[Nothing feels better than having this stupid forum dump your reply and have to start all over.. Grrr.....]

I can see how my response might be confusing. It's quite the hot mess I've developed.

Your workflow would be something like this:

User clicks button to run your report

The HTML button's onClick event would first create and display a new browser window. (in my case, I have a very basic HTML file, demographicReport.html, which is barebones and only contains one of those JSON "Loading" animated GIFs so that the user knows something is happening).

Once the second window is opened, you need to clear the HTML from the page and begin creating your report using javascript and DOM manipulation.

The first step here is some sort of "base template" for your report. Now, my report may or may not contain some elements so I basically had to create the entire report from scratch AND programmatically. If your report is going to be fairly static about what is included, you can probably get away with manually writing some HTML and then passing that file to the window.open() method I've previously discussed and skip what I'm about to talk about next. In my app, here's where that returnTractHtml ReportTemplate function comes into play. I've included a couple screenshots which show the code of the function as well as what that HTML finally looks like once it's inserted into the HTML page. Hopefully you can see the basic structure between this barebones screenshot and the PDF report example I previously attached.

Once I have that template "code" in the variable, I update the page in the second window with that content (also part of the second code snippit in my original reply).

The framework for your report is now in place- let's add some information to it. To do this, you're going to be using a whole lot of DOM manipluation functions such as getElementByID to update/modify any existing HTML page elements and createElement to create new items to insert into the page. Try to keep everything grouped into DIV elements for structure and for keeping tract of everything.

It sounded like the primary feature of your "report" would be the contents of your Grid. In this case, give your report template an empty HTML table framework. Loop through your Grid's values and then manually add that information into your report's HTML Table template using DOM. This reference should give you some idea of what that javascript might look like.

It's a lot of upfront work but unless you can find another solution (geoprocessing service?..), it might be your only bet.

Hope this helps!