5

I have a simple problem but I can't find a simple solution:

I have an Excel file (always the same), with several WorkSheets that non-IT coworkers want to be able to update so that it also updates the Google Charts (or other chart API you can advise me) webpage.

(By the way, I only need a certain part of each worksheet so if you know a way to extract only what I need that would be great :) )

I would like to avoid having server-side operation but it's maybe not possible since I want to read a local file.

I have looked at ways to convert to JSON, or to load as base64 string, using xlsx.js but I find nothing simple that my colleagues could easily use.

Thank you very much.

Edit

I found a way to do exactly what I wanted so if it can help anyone:

First, I put all the data I needed in one csv file.

Then, I used HTML5 FileAPI to read the csv file that I loaded with a file input.

Finally I used a cvstojson script to parse the file then passed it to th google graph dataTable the way I wanted.

However, this allowed to load the data only once so I used a button-styled label for the file input that triggered a hidden "reset" button (actually cloning more than resetting) after the file was loaded so now it looks like a single button that allows to load the file multiple times after I changed the data in it. I also used jQuery's localStorage to populate my json. I know this is pretty messy so here's a code extract:

<div id="load">
    <button id="clear">Clear</button>
    <label id="forcvs" for="cvs" > Load data </label>
    <input type="file" id="cvs" onchange="handleFiles(this.files);" accept=".csv"><br/>
</div>

The "handleFiles" fonction leads to the cvstojson script:

var json = JSON.parse(localStorage.getItem('json'))

function handleFiles(files) {
    // Check for the various File API support.
    if (window.FileReader) {
        // FileReader are supported.
        getAsText(files[0]);
    } else {
        alert('FileReader are not supported in this browser.');
    }
}

function getAsText(fileToRead) {
    var reader = new FileReader();
    // Read file into memory as UTF-8      
    reader.readAsText(fileToRead);
    // Handle errors load
    reader.onload = loadHandler;
    reader.onerror = errorHandler;
}

function loadHandler(event) {
    var csv = event.target.result;
    processData(csv);          
}

function processData(csv) {
  object = $.csv.toObjects(csv, {separator:";"})
    drawOutput(object);
}

function errorHandler(evt) {
    if(evt.target.error.name == "NotReadableError") {
        alert("Canno't read file !");
    }
}

function drawOutput(object){
  json = object
  localStorage.setItem('json', JSON.stringify(json))
  drawChart()
  $( "#clear" ).trigger( "click" );
}

and then before updating my data and drawing my chart I used:

json = JSON.parse(localStorage.getItem('json'))

Here's an extract of the jquery I used for that:

var load = $('#cvs')
$('#clear').click(function () {
load.replaceWith(load = load.clone(true))
})

And the CSS:

#cvs, #clear {
  display: none;
}


#forcvs {
  -webkit-appearance: button;
  -moz-appearance: button;
  appearance: button;
  line-height: 16px;
  padding: .2em .4em;
  margin: .2em;
}

Hope it can help some one and thanks for the replies :)

CyrilFind
  • 634
  • 1
  • 7
  • 16
  • My suggestion is to use Google Docs and [export spreadsheet](http://blog.pamelafox.org/2013/06/exporting-google-spreadsheet-as-json.html) to JSON for charts – ant_Ti Jul 02 '14 at 08:29
  • http://shancarter.github.io/mr-data-converter/ – Jamie Dunstan Jul 02 '14 at 08:42
  • If the data in your spreadsheets isn't sensitive, confidential, or otherwise priviledged, uploading the spreadsheet to Google Docs allows you to use the built-in support for the [Visualization API Queries](https://developers.google.com/chart/interactive/docs/spreadsheets). This is the simplest way to get data from an Excel spreadsheet into Visualization API charts. If that's not an option, you can spin up a local webserver (like [WAMP](www.wampserver.com), if you're on Windows), export the Excel file to CSV, load the CSV via ajax from the webserver, and parse the CSV data into a DataTable. – asgallant Jul 02 '14 at 13:51
  • Indeed, I used the CVS solution because I use confidential data. However, I thus have to export each spreadsheet to a separate CVS file. It's working anyway, thanks for your quick replies! – CyrilFind Jul 04 '14 at 14:01
  • If you had the data in a Google Drive spreadsheet (they re-branded Google Docs a while back, by the way), there is an API for that which you can make a secure connection to in order to access the sensitive data. It would not be a trivial project by any means, but a user could be directed to a login page, and after logging in be sent back to your site with access to data in google drive. I do this in an ASP.Net site to connect to an existing spreadsheet tool someone had created an import data into my web app. Should be doable from javascript. https://developers.google.com/drive/ – nbering Jul 07 '14 at 01:28
  • Thank you, I will take a look at that! However right now I would preferably use the CVS method, maybe ask my coworkers to consolidate the useful data in one spreadsheet to keep it very simple for them to update. Plus, it's a small project to present data in a few days so I won't have time to change every thing now, unless I use this again for an other project, then I'll definitely consider it :) – CyrilFind Jul 08 '14 at 06:57
  • Have you looked at http://oss.sheetjs.com/js-xlsx/ ? You can make a drag-and-drop page that pushes to google charts – SheetJS Aug 02 '14 at 19:30
  • Yes I saw that but I wanted it to be loaded without the user doing anything, which is not possible anyway so I did it my way but my solution looks a bit like that. – CyrilFind Aug 18 '14 at 10:06

2 Answers2

5

You can try Alasql JavaScript library to load XLSX data into JavaScript array without any complex programming. Alasql uses XLSX.js library to work with Excel files.

This is a sample:

<script src="alasql.min.js"></script>
<script src='xlsx.core.min.js'></script>
<script>
    alasql('select * from xlsx("cities.xlsx",{headers:true, sheetid:"Sheet1", range:"A1:B6"})',
           [],function(data) {
                console.log(data);
    });
</script>

You can run this sample at alasql.org site.

By default headers option is false, sheetid is "Sheet1", range - all cell on the sheet.

Alasql also supports TXT, TAB, CSV, JSON, and XLS formats. You also can produce XLSX file back from JavaScript array:

var stars = [{star:"Aldebaran"},{star:"Algol"},{star:"Vega"}];
alasql('SELECT * INTO XSLX("stars.xlsx",{headers:true}) FROM ?',[stars]);
agershun
  • 4,077
  • 38
  • 41
  • Thank you this looks like a very neat solution. I'll probably use it since I might work on this subject again. – CyrilFind Dec 15 '14 at 22:44
1

You can read system excel file without uploading using sheet.js

$(document).ready( function() {
   var data = SheetName = '';
   var fileUrl = "data.xlsx";
   var oReq;

  if(window.XMLHttpRequest) oReq = new XMLHttpRequest();
   else if(window.ActiveXObject) oReq = new ActiveXObject('MSXML2.XMLHTTP.3.0');
   else throw "XHR unavailable for your browser";

   oReq.open("GET", fileUrl, true);

   if(typeof Uint8Array !== 'undefined') {
     oReq.responseType = "arraybuffer"; // Set response type
     oReq.onload = function(e) {
       if(typeof console !== 'undefined')
       var arraybuffer = oReq.response;
       var data = new Uint8Array(arraybuffer);
       var wb = XLSX.read(data, {type:"array"}); // Read file data
       toJson(wb);
    };
  }
  else {
    oReq.setRequestHeader("Accept-Charset", "x-user-defined"); 
    oReq.onreadystatechange = function() {
    if(oReq.readyState == 4 && oReq.status == 200) {
      var ff = convertResponseBodyToText(oReq.responseBody);
      if(typeof console !== 'undefined')
        var wb = XLSX.read(ff, {type:"binary"});
        toJson(wb);
      }
    };
 }
 oReq.send(); // sends request

 function toJson(excel) {
   SheetName = excel.SheetNames[0];
   excel.SheetNames.forEach(function(sheetName) {
    var json = XLSX.utils.sheet_to_json(excel.Sheets[sheetName]); // convert sheet into json format
    if( !json.length ) return false;
    data = json;
   });
}

});

More help you may get here:

http://onegibi.com/programming/javascript-jquery-read-system-excel-file-without-uploading/

Amit Kumar
  • 143
  • 3
  • 15
  • Thanks, someone also mentioned sheet.js in the comments, I'll be sure to check that out if I need to read excel files again – CyrilFind Sep 10 '18 at 14:39