31

I want to convert excel sheet data to json. It has to be dynamic, so there is an upload button where user uploads the excel sheet and the data is then converted into json. Could you please provide me the javascript code? I tried SheetJS but couldn't figure out. I would prefer something straight forward :)

I really appreciate your help!

Programmer
  • 407
  • 2
  • 6
  • 9
  • 2
    People on SOF wont just give you code if you dont supply your own code/examples/attempts.. As a hint, use PHP to read the file into an array, then use json_encode... – Angry 84 Feb 28 '15 at 13:17
  • Would converting it client side with Javascript be the best option? – Jared Teng Feb 28 '15 at 13:21
  • I only want to use javascript. I don't have my own code, i just took the code from SheetJS and tried to manipulate but it doesn't suit. So i am looking for straight forward javascript code – Programmer Feb 28 '15 at 13:23
  • hmm, give me a few minutes and i'll see what i can work up for you – Angry 84 Feb 28 '15 at 13:39
  • Updated and also added second example to show how to generate a table – Angry 84 Feb 28 '15 at 14:37

5 Answers5

37

NOTE: Not 100% Cross Browser

Check browser compatibility @ http://caniuse.com/#search=FileReader

as you will see people have had issues with the not so common browsers, But this could come down to the version of the browser.. I always recommend using something like caniuse to see what generation of browser is supported... This is only a working answer for the user, not a final copy and paste code for people to just use..

The Fiddle: http://jsfiddle.net/d2atnbrt/3/

THE HTML CODE:

<input type="file" id="my_file_input" />
<div id='my_file_output'></div>

THE JS CODE:

var oFileIn;

$(function() {
    oFileIn = document.getElementById('my_file_input');
    if(oFileIn.addEventListener) {
        oFileIn.addEventListener('change', filePicked, false);
    }
});


function filePicked(oEvent) {
    // Get The File From The Input
    var oFile = oEvent.target.files[0];
    var sFilename = oFile.name;
    // Create A File Reader HTML5
    var reader = new FileReader();

    // Ready The Event For When A File Gets Selected
    reader.onload = function(e) {
        var data = e.target.result;
        var cfb = XLS.CFB.read(data, {type: 'binary'});
        var wb = XLS.parse_xlscfb(cfb);
        // Loop Over Each Sheet
        wb.SheetNames.forEach(function(sheetName) {
            // Obtain The Current Row As CSV
            var sCSV = XLS.utils.make_csv(wb.Sheets[sheetName]);   
            var oJS = XLS.utils.sheet_to_row_object_array(wb.Sheets[sheetName]);   

            $("#my_file_output").html(sCSV);
            console.log(oJS)
        });
    };

    // Tell JS To Start Reading The File.. You could delay this if desired
    reader.readAsBinaryString(oFile);
}

This also requires https://cdnjs.cloudflare.com/ajax/libs/xls/0.7.4-a/xls.js to convert to a readable format, i've also used jquery only for changing the div contents and for the dom ready event.. so jquery is not needed

This is as basic as i could get it,

EDIT - Generating A Table

The Fiddle: http://jsfiddle.net/d2atnbrt/5/

This second fiddle shows an example of generating your own table, the key here is using sheet_to_json to get the data in the correct format for JS use..

One or two comments in the second fiddle might be incorrect as modified version of the first fiddle.. the CSV comment is at least

Test XLS File: http://www.whitehouse.gov/sites/default/files/omb/budget/fy2014/assets/receipts.xls

This does not cover XLSX files thought, it should be fairly easy to adjust for them using their examples.

Angry 84
  • 2,935
  • 1
  • 25
  • 24
  • 1
    Unfortunately , i tried the fiddle and it does nothing after i upload the excel sheet. – Programmer Feb 28 '15 at 15:31
  • Try using this file: http://www.whitehouse.gov/sites/default/files/omb/budget/fy2014/assets/receipts.xls as it was the one i was testing with, its the suggested one on their demo page. – Angry 84 Feb 28 '15 at 15:33
  • Can you check your browser console for js errors, what browser are you using? – Angry 84 Feb 28 '15 at 15:38
  • Yes it works! . Sorry, i was uploading the wrong file. – Programmer Feb 28 '15 at 15:48
  • Instead of table, i want the data to be stored and displayed in json – Programmer Feb 28 '15 at 15:49
  • As already commented, the function "sheet_to_json" returns a json object/array. So you would simply work with that function and continue from there, as for storing it.. well that depends how you want to? on line 27 in the second fiddle you will see var data =... that data var contains the worksheet from the xls... You can either post that to server side/php or assign to a global variable instead so it can be used later.. – Angry 84 Feb 28 '15 at 15:59
  • 2
    I think i've given you more than enough here, if you need any more assistance here,, i would suggest tutorials and some basics. – Angry 84 Feb 28 '15 at 16:05
  • I wrote it myself after reading up on File Reader and xls.js, Check http://www.javascripture.com/FileReader and https://github.com/SheetJS/js-xls – Angry 84 Mar 01 '15 at 00:14
  • var data = XLS.utils.sheet_to_json(wb.Sheets[sheetName], {header:1}) – Programmer Mar 01 '15 at 18:05
  • What is that line doing? When i console.log the variable data, it says Array[75] and so on. – Programmer Mar 01 '15 at 18:05
  • @Mayhem, thank you for the example. Its working well with xls. Do you have a snippet which you can share of the working of xlsx as well. Thanks in advance! – rafavinu May 30 '16 at 10:46
  • If you follow the link in my above comment, you will see they have merged the package with https://github.com/SheetJS/js-xlsx so that should lead you to a working version. They advise there is no change in the API.. so existing code may work or only slight changes needed. – Angry 84 May 30 '16 at 10:50
  • Tried with the existing code and posted the same in http://stackoverflow.com/questions/37524747/xlsx-parser-for-parsing-excel. Not working mate! – rafavinu May 30 '16 at 11:40
  • @mayhem this works fine in crome but I am having issue running the same in IE. Anything I need to add specifically for IE – Yogesh Nov 07 '16 at 16:09
  • Anything specific for IE... Well firstly that is the most broken browser in the world lol.. But it really comes down to your IE version mostly.. Check out http://caniuse.com/#search=FileReader and you can see it requires verson 11 and even then its only partially supported... Just a reminder people, i simply did this answer over a year ago.. All i did was learn the code and make a working example. People, use your browsers console and debug the code if it does not work. – Angry 84 Nov 07 '16 at 22:53
16

js-xlsx library makes it easy to convert Excel/CSV files into JSON objects.

Download the xlsx.full.min.js file from here. Write below code on your HTML page Edit the referenced js file link (xlsx.full.min.js) and link of the Excel file

<!doctype html>
<html>

<head>
    <title>Excel to JSON Demo</title>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/xlsx/0.18.5/xlsx.full.min.js"></script>
</head>

<body>
    <input type="file" id="data" accept=".xlsx" />
    <script>
        document.querySelector('input').addEventListener('change', function() {
            var reader = new FileReader();
            reader.onload = function() {
                var arrayBuffer = this.result,
                    array = new Uint8Array(arrayBuffer),
                    binaryString = String.fromCharCode.apply(null, array);
                /* set up XMLHttpRequest */
                // var url = "http://myclassbook.org/wp-content/uploads/2017/12/Test.xlsx";
                // var oReq = new XMLHttpRequest();
                // oReq.open("GET", url, true);
                // oReq.responseType = "arraybuffer";

                // oReq.onload = function(e) {
                // var arraybuffer = oReq.response;

                /* convert data to binary string */
                // var data = new Uint8Array(arraybuffer);
                // var arr = new Array();
                // for (var i = 0; i != data.length; ++i) arr[i] = String.fromCharCode(data[i]);
                // var bstr = arr.join("");

                /* Call XLSX */
                var workbook = XLSX.read(binaryString, {
                    type: "binary"
                });

                /* DO SOMETHING WITH workbook HERE */
                var first_sheet_name = workbook.SheetNames[0];
                /* Get worksheet */
                var worksheet = workbook.Sheets[first_sheet_name];
                console.log(XLSX.utils.sheet_to_json(worksheet, {
                    raw: true
                }));
                // }

                // oReq.send();
            }
            reader.readAsArrayBuffer(this.files[0]);
        });
    </script>
</body>

</html>

Input:
Click here to see the input Excel file

Output:
Click here to see the output of above code

Jordy
  • 1,802
  • 2
  • 6
  • 25
user7456320
  • 161
  • 1
  • 3
  • Nice, but the question was to upload an Excel file. He didn't specify if he wanted to convert it on the client or the server. Your example is downloading an Excel file from the server. – NealWalters Aug 19 '20 at 20:42
  • actually I was looking for this solution, but how can I print the json data into the html body? – user2989513 Dec 15 '20 at 14:11
  • I have been trying for 3 days to read an excel directly from the local folder without having to trigger it with an event & had not luck till I came across this. This worked perfectly! Thank you so so much (up Voted). – moys Dec 10 '21 at 04:42
  • I have 2 questions on this. You have answerd both the questions here! If you can put this same answer on the 2 questions, I would be happy to accept your answer. https://stackoverflow.com/questions/70260394/read-excel-that-is-in-the-src-folder-of-react-app https://stackoverflow.com/questions/70285330/execl-to-an-array-of-objects-in-javascript – moys Dec 10 '21 at 04:45
  • @user7456320, `myclassbook.org` links are broken. – Ayan Mullick Jan 17 '22 at 23:11
  • **Note** : specify `{raw: true, header: 1}` for ignore headers. – Jordy Apr 13 '23 at 10:16
8

The answers are working fine with xls format but, in my case, it didn't work for xlsx format. Thus I added some code here. it works both xls and xlsx format.

I took the sample from the official sample link.

Hope it may help !

function fileReader(oEvent) {
        var oFile = oEvent.target.files[0];
        var sFilename = oFile.name;

        var reader = new FileReader();
        var result = {};

        reader.onload = function (e) {
            var data = e.target.result;
            data = new Uint8Array(data);
            var workbook = XLSX.read(data, {type: 'array'});
            console.log(workbook);
            var result = {};
            workbook.SheetNames.forEach(function (sheetName) {
                var roa = XLSX.utils.sheet_to_json(workbook.Sheets[sheetName], {header: 1});
                if (roa.length) result[sheetName] = roa;
            });
            // see the result, caution: it works after reader event is done.
            console.log(result);
        };
        reader.readAsArrayBuffer(oFile);
}

// Add your id of "File Input" 
$('#fileUpload').change(function(ev) {
        // Do something 
        fileReader(ev);
}
Kwang-Chun Kang
  • 351
  • 3
  • 12
  • Nice, but the question was to upload an Excel file. He didn't specify if he wanted to convert it on the client or the server. Your example is downloading an Excel file from the server. – NealWalters Aug 19 '20 at 20:42
4

@Kwang-Chun Kang Thanks Kang a lot! I found the solution is working and very helpful, it really save my day. For me I am trying to create a React.js component that convert *.xlsx to json object when user upload the excel file to a html input tag. First I need to install XLSX package with:

npm install xlsx --save

Then in my component code, import with:

import XLSX from 'xlsx'

The component UI should look like this:

<input
  accept=".xlsx"
  type="file"
  onChange={this.fileReader}
/>

It calls a function fileReader(), which is exactly same as the solution provided. To learn more about fileReader API, I found this blog to be helpful: https://blog.teamtreehouse.com/reading-files-using-the-html5-filereader-api

0

This is my expansion on https://stackoverflow.com/a/52237535/5079799

While it was working/great example, I'm not using an input form, but fetching from a URL and I have other things to do after fething workbook so I needed to wrap the onload into a promise.

See --> adjust onload function to be used with async/await

Here is what I ended up w/

async function Outside_Test(){
    var reso = await Get_JSON()
    console.log('reso_out')
    console.log(reso)
}

async function Get_JSON() {
    var url = "http://MyworkbookURL"
    var workbook = await Get_XLSX_As_Workbook_From_URL(url)

    /* DO SOMETHING WITH workbook HERE */
    var first_sheet_name = workbook.SheetNames[0];
    /* Get worksheet */
    var worksheet = workbook.Sheets[first_sheet_name];
    var reso = (XLSX.utils.sheet_to_json(worksheet, {
        raw: true
    }));
    return reso
}

async function Get_XLSX_As_Workbook_From_URL(url) {
    const arrayBuffer = await new Promise((resolve, reject) => {
        var oReq = new XMLHttpRequest();
        oReq.open("GET", url, true);
        oReq.responseType = "arraybuffer";
        oReq.onload = () => resolve(oReq.response);
        oReq.onerror = reject;
        oReq.send();
    });
    var data = new Uint8Array(arrayBuffer);
    var arr = new Array();
    for (var i = 0; i != data.length; ++i) arr[i] = String.fromCharCode(data[i]);
    var bstr = arr.join("");
    var workbook = XLSX.read(bstr, {
        type: "binary"
    });
    return workbook
}
FreeSoftwareServers
  • 2,271
  • 1
  • 33
  • 57