PDA

View Full Version : Ext.ux.CSVImport, import data from CSV to Ext.grid.GridPanel



goldledoigt
12 Aug 2010, 5:06 AM
Hello all,

This is a grid's plugin to import data from CSV to grid's store.
It uses HTML5 native drag & drop and FileReader.
This plugin works with FireFox 3.6+ and Chrome 6 (dev channel) only.

Sources with example on GitHub : http://github.com/goldledoigt/Ext.ux.grid.CSVImport


Ext.ns("Ext.ux.grid");

Ext.ux.grid.CSVImport = function() {

var grid = null;
var strDelimiter = ",";
var endLine = "\n";

function csvToArray(strData, strDelimiter){
var arrData = [[]];
var arrMatches = null;
var objPattern = new RegExp((
"(\\" + strDelimiter + "|\\r?\\n|\\r|^)" +
"(?:\"([^\"]*(?:\"\"[^\"]*)*)\"|" +
"([^\"\\" + strDelimiter + "\\r\\n]*))"
), "gi");

while (arrMatches = objPattern.exec(strData)) {
var strMatchedDelimiter = arrMatches[ 1 ];
if (strMatchedDelimiter.length && (strMatchedDelimiter != strDelimiter)) {
arrData.push([]);
}
if (arrMatches[2]) {
var strMatchedValue = arrMatches[ 2 ].replace(new RegExp( "\"\"", "g" ),"\"");
} else {
var strMatchedValue = arrMatches[ 3 ];
}
arrData[ arrData.length - 1 ].push(strMatchedValue);
}

return(arrData);
}

function addRow(row) {
row = csvToArray(row, strDelimiter);
grid.store.loadData(row, true);
}

function processFile(file) {
var reader = new FileReader();
reader.onload = function(e) {
var rows = atob(e.target.result.split(",")[1]).split(endLine);
Ext.each(rows, addRow);
grid.fireEvent("read", grid, file, rows, reader);
};
reader.readAsDataURL(file);
}

function onFilesDrop(e) {
e.stopPropagation();
e.preventDefault();
var files = e.browserEvent.dataTransfer.files;
if (
files && files.length &&
grid.fireEvent("beforedrop", grid, files) !== false
) {
// no defer, no load mask...
(function() {
Ext.each(files, processFile);
grid.fireEvent("drop", grid, files);
}).defer(50);
}
}

function initDD() {
grid.body.on({
scope:grid
,dragover:function(e) {
e.stopPropagation();
e.preventDefault();
if (!Ext.isGecko) { // prevents drop in FF ;-(
e.browserEvent.dataTransfer.dropEffect = 'copy';
}
grid.fireEvent("dragstart", grid);
return;
}
,dragleave:function(e) {
e.stopPropagation();
e.preventDefault();
grid.fireEvent("dragstop", grid);
return;
}
,drop:onFilesDrop
});
}

function init(component) {
grid = component;
grid.on({afterrender:initDD})
}

return {init:init};

};


Ext.onReady(function() {

// BASIC

new Ext.grid.GridPanel({
renderTo:Ext.getBody()
,width:500
,height:400
,plugins:[new Ext.ux.grid.CSVImport()]
,store:new Ext.data.ArrayStore({
fields:["a", "b", "c", "d", "e", "f", "g", "h", "i"]
})
,columns:[
{dataIndex:"a", header:"A"}
,{dataIndex:"b", header:"B"}
,{dataIndex:"c", header:"C"}
,{dataIndex:"d", header:"D"}
,{dataIndex:"e", header:"E"}
,{dataIndex:"f", header:"F"}
,{dataIndex:"g", header:"G"}
,{dataIndex:"h", header:"H"}
,{dataIndex:"i", header:"I"}
]
});

// ADVANCED

new Ext.grid.GridPanel({
renderTo:Ext.getBody()
,width:500
,height:400
,plugins:[new Ext.ux.grid.CSVImport()]
,store:new Ext.data.ArrayStore({
fields:["a", "b", "c", "d", "e", "f", "g", "h", "i"]
})
,columns:[
{dataIndex:"a", header:"A"}
,{dataIndex:"b", header:"B"}
,{dataIndex:"c", header:"C"}
,{dataIndex:"d", header:"D"}
,{dataIndex:"e", header:"E"}
,{dataIndex:"f", header:"F"}
,{dataIndex:"g", header:"G"}
,{dataIndex:"h", header:"H"}
,{dataIndex:"i", header:"I"}
]
,listeners:{
dragstart:function(grid) {
grid.view.scroller.setStyle("background-color", "#FFFDF6");
}
,dragstop:function(grid) {
grid.view.scroller.setStyle("background-color", "#FFFFFF");
}
,beforedrop:function(grid, files) {
if (!grid.mask) {
grid.mask = new Ext.LoadMask(
grid.body
,{msg:"Loading data, please wait..."}
);
}
grid.mask.show();
// return false to cancel import
}
,drop:function(grid, files) {
grid.view.scroller.setStyle("background-color", "#FFFFFF");
}
,read:function(grid, file, content, reader) {
grid.mask.hide();
}
}
});

});


Drop CSV file over grid's body, wait a bit, and voila :)

sosy
12 Aug 2010, 7:42 PM
I will give it a try today. What i was wondering about is, why (and it seems to happen often by others to) you dont put an simple demo online, where people can give it a try. It often says more than 100 rows of source.

Regards
Sosy

joeri
13 Aug 2010, 1:33 AM
Thanks for sharing.

But I thought I'd mention that the plugin as it exists probably won't work for quoted strings (strings containing a " character, and possibly a , character).

You could try integrating the parsing logic from http://stackoverflow.com/questions/1293147/javascript-code-to-parse-csv-data

ashaihullin
13 Aug 2010, 10:24 AM
very usefull if it work... gonna try little later... thanx

goldledoigt
13 Aug 2010, 3:42 PM
It now works with quoted strings.
Thanks to you Joeri and to kirtan (http://stackoverflow.com/users/83664/kirtan).

code updated.

verbi
3 Nov 2010, 4:16 AM
do you have example with browse file (not dragDrop)? thankyou.

goldledoigt
3 Nov 2010, 4:30 AM
do you have example with browse file (not dragDrop)? thankyou.

The same thing can't work without HTML5 D&D. The system D&D allows the browser to read the file content. As far as I know, file browsing upload process can't do that, you will have to wait for the file to be uploaded before you could read the content.

If you are looking for a complete upload ExtJS object supporting file browsing + D&D you can take a look to:
my Ext.ux.upload plugin (https://github.com/revolunet/Ext.ux.upload)

verbi
3 Nov 2010, 3:33 PM
The same thing can't work without HTML5 D&D. The system D&D allows the browser to read the file content. As far as I know, file browsing upload process can't do that, you will have to wait for the file to be uploaded before you could read the content.

If you are looking for a complete upload ExtJS object supporting file browsing + D&D you can take a look to:
my Ext.ux.upload plugin (https://github.com/revolunet/Ext.ux.upload)
Thankyou gold, HTML5 D&D is great method.
Just in my case ancient browse method needed. If i able to make own project with own specification i will use HTML5 D&D.
still learning from your link (my Ext.ux.upload plugin).