2

I want to read the file uploaded by users on the client side and then do processing on them, instead of doing it on server-side. Is it possible read files and do manipulation using javascript on client side. Is it possible to use VBScript for this

4 Answers 4

4

I've done some very simple xlsx parsing in the browser. See https://gist.github.com/3375836. Try it out at http://jsfiddle.net/fAKGA/2. Copied here for convenience:

/*
    Relies on jQuery, underscore.js, Async.js (https://github.com/caolan/async), and zip.js (http://gildas-lormeau.github.com/zip.js).
    Tested only in Chrome on OS X.

    Call xlsxParser.parse(file) where file is an instance of File. For example (untested):

    document.ondrop = function(e) {
        var file = e.dataTransfer.files[0];
        excelParser.parse(file).then(function(data) {
            console.log(data);
        }, function(err) {
            console.log('error', err);
        });
    }
*/

xlsxParser = (function() {
    function extractFiles(file) {
        var deferred = $.Deferred();

        zip.createReader(new zip.BlobReader(file), function(reader) {
            reader.getEntries(function(entries) {
                async.reduce(entries, {}, function(memo, entry, done) {
                    var files = ['xl/worksheets/sheet1.xml', 'xl/sharedStrings.xml'];
                    if (files.indexOf(entry.filename) == -1) return done(null, memo);

                    entry.getData(new zip.TextWriter(), function(data) {
                        memo[entry.filename.split('/').pop()] = data;
                        done(null, memo);
                    });
                }, function(err, files) {
                    if (err) deferred.reject(err);
                    else deferred.resolve(files);
                });
            });
        }, function(error) { deferred.reject(error); });

        return deferred.promise();
    }

    function extractData(files) {
        var sheet = $(files['sheet1.xml']),
            strings = $(files['sharedStrings.xml']),
            data = [];

        var colToInt = function(col) {
            var letters = ["", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"];
            var col = $.trim(col).split('');

            var n = 0;

            for (var i = 0; i < col.length; i++) {
                n *= 26;
                n += letters.indexOf(col[i]);
            }

            return n;
        };

        var Cell = function(cell) {
            cell = cell.split(/([0-9]+)/);
            this.row = parseInt(cell[1]);
            this.column = colToInt(cell[0]);
        };

        var d = sheet.find('dimension').attr('ref').split(':');
        d = _.map(d, function(v) { return new Cell(v); });

        var cols = d[1].column - d[0].column + 1,
            rows = d[1].row - d[0].row + 1;

        _(rows).times(function() {
            var _row = [];
            _(cols).times(function() { _row.push(''); });
            data.push(_row);
        });

        sheet.find('sheetData row c').each(function(i, c) {
            var $cell = $(c),
                cell = new Cell($cell.attr('r')),
                type = $cell.attr('t'),
                value = $cell.find('v').text();

            if (type == 's') value = strings.find('si t').eq(parseInt(value)).text();

            data[cell.row - d[0].row][cell.column - d[0].column] = value;
        });

        return data;
    }

    return {
        parse: function(file) {
            return extractFiles(file).pipe(function(files) {
                return extractData(files);
            });
        }
    }
})();
Sign up to request clarification or add additional context in comments.

6 Comments

I get the error extractFiles(file).pipe is not a function. What am I doing wrong?
@Hache I'm not sure, it works for me (tested in Chrome only) here at this fiddle: jsfiddle.net/fAKGA/2. Does that work for you? Have you tried more than one file?
You're right. I totally messed up and tried in FF..... Sorry... Is there some possibility for FF available?
jsfiddle.net/fAKGA/6 works for me in FF15. What version of Firefox are you using?
Wondering about the purpose of var d = sheet.find('dimension').attr('ref').split(':'); (around line 101) I'm able to select an xlsx document and have it read in; however, sheet doesn't appear to have any children called "dimension", and so I'm getting a JavaScript error at that point. What are "dimension" and "ref" for?
|
1

The browser should make it impossible to access local files (and we all should be happy about that). But the user could install a .HTA that can do short of everything on the local/client computer.

1 Comment

HTA could definitely do it, but at that point, you start to wonder - why not just build a real app. The tools and performance are so much better.
0

In short, No. The is no way for javascript to access the filesystem, this would be a major security threat/attack vector.

1 Comment

ActiveX can do it with excel 2003, haven't been able to find an alternative for 2007
0

Absolutely not. For security purposes, this must be done server side. I can't think of single reason you wouldn't want to do it that way anyway.

2 Comments

Distributing the server load to the client is one example, which totally makes sense. My application has to create thousands of xls so a distribution brings a big benefit
I understand that, but I'm not sure that's an appropriate approach either.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.