PDA

View Full Version : Export store to Excel



Pages : [1] 2

wiznia
10 Jun 2011, 4:08 AM
Well, here's an exporter that can export a grid, tree or simply a store to excel. It's a fork from another project, I adapted it to work with ExtJs 4, using the new class system and fixed a couple of bugs.
The Csv exporter isn't implemented and the example and compiled files are not updated (so don't use Exporter-all.js).
It exports all the data in the store loaded at that time. If a grid is used it uses the renderers and column configurations from it.
The download is made through a button and uses datauri, so it doesn't work in older ie versions.
I hope it's useful, if you find bugs or make improvements, just fork it and send me a pull request.
https://github.com/iwiznia/Ext.ux.Exporter

dawesi
10 Jun 2011, 5:52 AM
nice work. I'll check it out this weekend! :-)

nuskin
18 Jul 2011, 4:03 PM
I did not use the Exporter-all.js file as the author suggested but included all other files:
<script type="text/javascript" src="Base64.js"></script>
<script type="text/javascript" src="Button.js"></script>
<script type="text/javascript" src="Formatter.js"></script>
<script type="text/javascript" src="./excelFormatter/ExcelFormatter.js"></script>
<script type="text/javascript" src="./excelFormatter/Workbook.js"></script>
<script type="text/javascript" src="./excelFormatter/Worksheet.js"></script>
<script type="text/javascript" src="./excelFormatter/Cell.js"></script>
<script type="text/javascript" src="./excelFormatter/Style.js"></script>
<script type="text/javascript" src="Exporter.js"></script>

However, I got the namspace undefined error when loading:
namespace is undefined

if (namespace === from...substring(0, from.length) === from) { ext-all-debug.js (line 3487)

Any idea?

wiznia
19 Jul 2011, 1:52 AM
You don't have to include all the files if you have the ext loader activated. It uses the new class method and defines it's dependencies. You only have to include Exporter.js

vaucer
19 Jul 2011, 5:25 AM
Hello,

It does not work for me on ext4.

I just add the script in my index:


<script type="text/javascript" src="app/lib/Exporter-all.js">

And add the button to my grid:


dockedItems:[{
xtype: 'toolbar',
dock: 'top',
items: [{
text: 'Nouveau ticket',
iconCls:'addticket',
action: 'newticket'
},{
text: 'Prendre en charge',
iconCls:'linkticket',
action: 'chrg',
hidden:true
},{
iconCls: 'summary',
text: 'Aperçu',
enableToggle: true,
pressed: true,
scope: this,
toggleHandler: this.onSummaryToggle
},'->',{
text: 'Archiver',
iconCls:'datab',
action: 'archi'
},new Ext.ux.Exporter.Button({
component: this,
text : "Download as .xls"
})]
}],

I get Ext.ux.Exporter is undefined

Thx in advance for your help
Vaucer

wiznia
19 Jul 2011, 6:43 AM
The exporter-all.js is not updated, so you have to include Exporter.js

Teemac
19 Jul 2011, 9:56 AM
Ran into the same problem as nuskin, but happened for me when I tried just including Exporter.js, when I included all the files, I was able actually get into the button class when adding the button but not sure what I need to set in the buttons config to get it to work. Tried the storeId, tried the store itself, and even tried the grid as the component. Any ideas?

wiznia
19 Jul 2011, 11:36 AM
I use it like this. If the exporterebutton is inside a grid or a tree it autodetects the store. You can use it in a grid without creating a new class, just add the 'uses' config and the exporterbutton in the dockedItems.



Ext.Loader.setConfig({enabled: true});
Ext.Loader.setPath('Ext.ux', '/path-to-ext-ux');

Ext.define('App.view.SomeGrid', {
extend: 'Ext.grid.Panel',
uses: [
'Ext.ux.exporter.Exporter'
],

initComponent: function() {
this.store = "SomeStore";

this.dockedItems = [{
xtype: 'toolbar',
dock: 'top',
items: [{
xtype: 'exporterbutton'
}];
this.columns = [/* YOUR COLUMNS */];
this.callParent(arguments);
}
});

Teemac
19 Jul 2011, 12:59 PM
Thanks that worked except that in the button class setComponent function the columns don't have the .on function off them, seem like a simple array. Also the show and hide events never seemed to get fired. So I set it on the render and used the headerCt instead of columns, which seems to work but when I actually click the download, it navigates to data:application/vnd.ms-excel;base64,PD94bWwgdm....Lots more just like it, but doens't do anything more. As I haven't tried to use the data stuff before not sure what's it's supposed to do. I'm trying to make a simpler version of my grid to show as an example and see if it works, but wanted to see if you had ideas ahead of time, thanks again for any help you can provide.



Ext.Array.each(



this.component.headerCt.items.items, function(col) {

col.on(



"render", setLink, me);

});

Ewoq
20 Jul 2011, 1:25 AM
Hi all

I have the same problem as teemac, I think.

I get the same result from my app, as I get from the exporter example. When I click the button in both the example and my app, I get a part file from firefox and this only contains some column information plus some other values that doesn't appear in the grid.

I'm using the Exporter.js in my app, so that should be okay.

I made a small change to the Worksheet.js after line 150:


if(record.fields.get(name)) {
var value = record.get(name),
type = this.typeMappings[col.type || record.fields.get(name).type.type];
}I changed it because I have an empty column that it didn't like. But I don't think that is a problem.

Any suggestions?

wiznia
20 Jul 2011, 1:32 AM
The data is downloaded via a data uri. That's the "data:application/vnd.ms-excel;base64,PD94bWwgdm...." it should be prompting for a download. Which browser are you using?

Ewoq
20 Jul 2011, 2:07 AM
If you mean me, I'm using firefox 5.0.

I do get prompted for at download, but for a .part file. It ends up being a xls.part.xls file. Like in the example, it contains something like this in the first cell:

Exportable grid900050000falsefalse 0">Exportable gridCompanyPriceChange% ChangeLast UpdatedBlank132767600FalseFalse

wiznia
20 Jul 2011, 3:03 AM
mmm, no idea. It seems like something is going wrong in the generation of the file... no idea what, maybe a "strange" character that isn't being escaped?

Ewoq
20 Jul 2011, 5:20 AM
What version of excel are you using? 2007?

It seems that all the information is present before the Base64 encoding, but using the xml without the encoding this produces an incorrect "sheet". So now I'm thinking that the xml format is wrong for my very old excel version (2003)...

Update: Seems I was using a very very old version of excel (2000!) and it worked as soon as I changed to excel 2003. So thanks for your replies wiznia:)

wiznia
20 Jul 2011, 8:01 AM
Great! I'm glad to help.

Teemac
20 Jul 2011, 8:59 AM
I'm using IE9 and get no prompt, is there possibly a browser setting that is preventing it?
To be clear it opens a new tab with the url set to the "data:application/vnd.ms-excel;base64,PD94bWwgdm..."

wiznia
20 Jul 2011, 9:13 AM
I haven't tested it on IE, until IE7 I think there was no support for data uri, but in IE8 and 9 there is... in theory it should work.

nuskin
20 Jul 2011, 4:34 PM
I include the Exporter.js file in the <header> tag <script type="text/javascript" src="./examples/ux/exporter/Exporter.js"></script> and put all other files under ext-4.0.2a\examples\ux\exporter and csvFormatter and excelFormatter sub-folders.

I also use:
Ext.Loader.setConfig({enabled: true});
Ext.Loader.setPath('Ext.ux', './examples/ux');

I add this config param in my Ext.grid.Panel object:
dockedItems: [
{
xtype: 'toolbar',
dock: 'bottom',
items: [ { xtype: 'exporterbutton'} ]
}
]

However, I still got the same error:
namespace is undefined
if (namespace === from...substring(0, from.length) === from) { ext-all-debug.js (line 3487)

This error is from ext-all-debug.js (line 3487) file.

Any idea?

wiznia
21 Jul 2011, 2:19 AM
mmm, which namespace is undefined? Are the files loading correctly?
You don't need to include the file in the head, just add it to the 'uses' config option.

Ewoq
21 Jul 2011, 5:07 AM
Again I have a similar problem...

I can only get the exporter to work if I put it in a /src/ux/ folder in my ext directory. I do not want it there.
I have tried moving it to another folder and changing the Ext.Loader.setPath to this new folder, but can't get it to work at all. Is that even the right way to do it?

Any thoughts?

wiznia
21 Jul 2011, 6:03 AM
You can put it wherever you want, but you have to specify it to the loader with the setPath method.



Ext.Loader.setPath('Ext.ux', './src/ux'); // All the Ext.ux.* classes will be searched in ./src/ux

Ext.Loader.setPath('Ext.ux.exporter', './something/exporter'); // Only the Ext.ux.exporter.* classes will be searched in ./something/exporter'

nuskin
21 Jul 2011, 10:29 AM
hi Wiznia,

I copied the array-grid example from ext-4.0.2a/examples/grid/ folder and made my own MyExcelExporter.html file under the same directory as the example itself. I added the dockedItems item to the grid object and added Ext.require(['Ext.ux.exporter.*', 'Ext.ux.exporter.excelFormatter.*', 'Ext.ux.exporter.csvFormatter.*']). Yes, I copied all other files to their perspective directories under ext-4.0.2a/examples/ux folder. However, I still get the same problem/error. I am new to this Extjs 4.0.2a framework. So, any help to get this excel-exporter working is really appreciated. Here are the source codes of my MyExcelExporter.html file:

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>My Excel Exporter</title>
<style> body, html {margin:65px; padding: 1px; overflow: auto;} </style>
<link rel="stylesheet" type="text/css" href="../../resources/css/ext-all.css" />
<link rel="stylesheet" type="text/css" href="../shared/example.css" />
<script type="text/javascript" src="../../bootstrap.js"></script>
</head>

<body>

<div id="grid-place"></div>

<script type="text/javascript">

Ext.Loader.setConfig({enabled: true});
Ext.Loader.setPath('Ext.ux', '../ux');

Ext.require([
'Ext.grid.*',
'Ext.data.*',
'Ext.util.*',
'Ext.state.*',
'Ext.ux.exporter.*',
'Ext.ux.exporter.excelFormatter.*',
'Ext.ux.exporter.csvFormatter.*'
]);

Ext.onReady(function() {

Ext.QuickTips.init();

// setup the state provider, all state information will be saved to a cookie
Ext.state.Manager.setProvider(Ext.create('Ext.state.CookieProvider'));

// sample static data for the store
var myData = [
['3m Co', 71.72, 0.02, 0.03, '9/1 12:00am'],
['Alcoa Inc', 29.01, 0.42, 1.47, '9/1 12:00am'],
['Altria Group Inc', 83.81, 0.28, 0.34, '9/1 12:00am'],
['American Express Company', 52.55, 0.01, 0.02, '9/1 12:00am'],
['American International Group, Inc.', 64.13, 0.31, 0.49, '9/1 12:00am'],
['AT&T Inc.', 31.61, -0.48, -1.54, '9/1 12:00am'],
['Boeing Co.', 75.43, 0.53, 0.71, '9/1 12:00am'],
['Caterpillar Inc.', 67.27, 0.92, 1.39, '9/1 12:00am'],
['Citigroup, Inc.', 49.37, 0.02, 0.04, '9/1 12:00am'],
['E.I. du Pont de Nemours and Company', 40.48, 0.51, 1.28, '9/1 12:00am'],
['Exxon Mobil Corp', 68.1, -0.43, -0.64, '9/1 12:00am'],
['General Electric Company', 34.14, -0.08, -0.23, '9/1 12:00am'],
['General Motors Corporation', 30.27, 1.09, 3.74, '9/1 12:00am'],
['Hewlett-Packard Co.', 36.53, -0.03, -0.08, '9/1 12:00am'],
['Honeywell Intl Inc', 38.77, 0.05, 0.13, '9/1 12:00am'],
['Intel Corporation', 19.88, 0.31, 1.58, '9/1 12:00am'],
['International Business Machines', 81.41, 0.44, 0.54, '9/1 12:00am'],
['Johnson & Johnson', 64.72, 0.06, 0.09, '9/1 12:00am'],
['JP Morgan & Chase & Co', 45.73, 0.07, 0.15, '9/1 12:00am'],
['McDonald\'s Corporation', 36.76, 0.86, 2.40, '9/1 12:00am'],
['Merck & Co., Inc.', 40.96, 0.41, 1.01, '9/1 12:00am'],
['Microsoft Corporation', 25.84, 0.14, 0.54, '9/1 12:00am'],
['Pfizer Inc', 27.96, 0.4, 1.45, '9/1 12:00am'],
['The Coca-Cola Company', 45.07, 0.26, 0.58, '9/1 12:00am'],
['The Home Depot, Inc.', 34.64, 0.35, 1.02, '9/1 12:00am'],
['The Procter & Gamble Company', 61.91, 0.01, 0.02, '9/1 12:00am'],
['United Technologies Corporation', 63.26, 0.55, 0.88, '9/1 12:00am'],
['Verizon Communications', 35.57, 0.39, 1.11, '9/1 12:00am'],
['Wal-Mart Stores, Inc.', 45.45, 0.73, 1.63, '9/1 12:00am']
];

/**
* Custom function used for column renderer
* @param {Object} val
*/
function change(val) {
if (val > 0) {
return '<span style="color:green;">' + val + '</span>';
} else if (val < 0) {
return '<span style="color:red;">' + val + '</span>';
}
return val;
}

/**
* Custom function used for column renderer
* @param {Object} val
*/
function pctChange(val) {
if (val > 0) {
return '<span style="color:green;">' + val + '%</span>';
} else if (val < 0) {
return '<span style="color:red;">' + val + '%</span>';
}
return val;
}

// create a business model
Ext.define('Business', { extend: 'Ext.data.Model', fields: [
{name: 'company'},
{name: 'price', type: 'float'},
{name: 'change', type: 'float'},
{name: 'pctChange', type: 'float'},
{name: 'lastChange', type: 'date', dateFormat: 'n/j h:ia'}
]});

// create the data store
var myStore = Ext.create('Ext.data.ArrayStore', {
model: 'Business',
data: myData
});

// create the Grid object
var grid = Ext.create('Ext.grid.Panel', {
title: 'Array Grid',
renderTo: 'grid-example',
height: 350,
width: 600,
store: myStore,
stateful: true,
stateId: 'stateGrid',
columns: [
{
text : 'Company',
flex : 1,
sortable : false,
dataIndex: 'company'
},
{
text : 'Price',
width : 75,
sortable : true,
renderer : 'usMoney',
dataIndex: 'price'
},
{
text : 'Change',
width : 75,
sortable : true,
renderer : change,
dataIndex: 'change'
},
{
text : '% Change',
width : 75,
sortable : true,
renderer : pctChange,
dataIndex: 'pctChange'
},
{
text : 'Last Updated',
width : 85,
sortable : true,
renderer : Ext.util.Format.dateRenderer('m/d/Y'),
dataIndex: 'lastChange'
},
{
xtype: 'actioncolumn',
width: 50,
items: [
{
icon: '../shared/icons/fam/delete.gif', // Use a URL in the icon config
tooltip: 'Sell stock',
handler: function(grid, rowIndex, colIndex) {
var rec = myStore.getAt(rowIndex);
alert("Sell " + rec.get('company'));
}
},
{
getClass: function(v, meta, rec) { // Or return a class from a function
if (rec.get('change') < 0) {
this.items[1].tooltip = 'Hold stock';
return 'alert-col';
} else {
this.items[1].tooltip = 'Buy stock';
return 'buy-col';
}
},
handler: function(grid, rowIndex, colIndex) {
var rec = myStore.getAt(rowIndex);
alert((rec.get('change') < 0 ? "Hold " : "Buy ") + rec.get('company'));
}
}
]
}
],
viewConfig: {
stripeRows: true
},
dockedItems: [
{
xtype: 'toolbar',
dock: 'bottom',
items: [ { xtype: 'exporterbutton'} ]
}
]
});

});
</script>

</body>
</html>

Ewoq
22 Jul 2011, 12:10 AM
I solved my problem:

I moved the setPath...

Ext.Loader.setConfig({enabled: true});
Ext.Loader.setPath('Ext.ux.exporter', '/any/Directory');...into the Exporter.js and then it worked.

Maybe that could help you too nuskin?

Thanks again wiznia;)

nuskin
22 Jul 2011, 5:01 PM
Well, i made some progress; however, i ran into different problem in the Button.js file.

col.on is not a function col.on("show", setLink, me);
Button...2614604 (line 51)

Any idea?

I resolved the "namespace is undefined" problem by explicitly list out as:
Ext.require([
'Ext.ux.exporter.Base64',
'Ext.ux.exporter.Button',
'Ext.ux.exporter.csvFormatter.CsvFormatter',
'Ext.ux.exporter.excelFormatter.ExcelFormatter'
]);

Thanks for helping.

nuskin
25 Jul 2011, 12:39 PM
Thanks Wizina and Teemac. I got it worked in Firfox 5.0, but it does not work in IE 7 or IE 8. For IE 7, it got stuck right away, nothing display at all, not even the array grid; for IE 8, the array grid and button show up, but when I click on the button for download or export, a new IE browser instance was launched but no data, just like Teemac discribed in IE 9.

The following source codes will work in Firfox 5.0:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Stateful Array Grid Example</title>
<link rel="stylesheet" type="text/css" href="../../resources/css/ext-all.css" />
<link rel="stylesheet" type="text/css" href="../shared/example.css" />
<script type="text/javascript" src="../../bootstrap.js"></script>
<!-- page specific -->
<style type="text/css">
/* style rows on mouseover */
.x-grid-row-over .x-grid-cell-inner {
font-weight: bold;
}
/* shared styles for the ActionColumn icons */
.x-action-col-cell img {
height: 16px;
width: 16px;
cursor: pointer;
}
/* custom icon for the "buy" ActionColumn icon */
.x-action-col-cell img.buy-col {
background-image: url(../shared/icons/fam/accept.gif);
}
/* custom icon for the "alert" ActionColumn icon */
.x-action-col-cell img.alert-col {
background-image: url(../shared/icons/fam/error.gif);
}
</style>
</head>
<body>
<h1>Export an Array Grid to Excel</h1>

<div id="grid-example"></div>
<script type="text/javascript">

Ext.Loader.setConfig({ enabled: true });
Ext.Loader.setPath('Ext.ux.exporter', '../ux/exporter');
Ext.require([
'Ext.grid.*',
'Ext.data.*',
'Ext.util.*',
'Ext.ux.exporter.Base64',
'Ext.ux.exporter.Button',
'Ext.ux.exporter.Formatter',
'Ext.ux.exporter.csvFormatter.CsvFormatter',
'Ext.ux.exporter.excelFormatter.Workbook',
'Ext.ux.exporter.excelFormatter.Worksheet',
'Ext.ux.exporter.excelFormatter.Cell',
'Ext.ux.exporter.excelFormatter.Style',
'Ext.ux.exporter.excelFormatter.ExcelFormatter',
'Ext.ux.exporter.Exporter'
]);
Ext.onReady(function() {

// sample static data for the store
var myData = [
['3m Co', 71.72, 0.02, 0.03, '9/1 12:00am'],
['Alcoa Inc', 29.01, 0.42, 1.47, '9/1 12:00am'],
['Altria Group Inc', 83.81, 0.28, 0.34, '9/1 12:00am'],
['American Express Company', 52.55, 0.01, 0.02, '9/1 12:00am'],
['American International Group, Inc.', 64.13, 0.31, 0.49, '9/1 12:00am'],
['AT&T Inc.', 31.61, -0.48, -1.54, '9/1 12:00am'],
['Boeing Co.', 75.43, 0.53, 0.71, '9/1 12:00am'],
['Caterpillar Inc.', 67.27, 0.92, 1.39, '9/1 12:00am'],
['Citigroup, Inc.', 49.37, 0.02, 0.04, '9/1 12:00am'],
['E.I. du Pont de Nemours and Company', 40.48, 0.51, 1.28, '9/1 12:00am'],
['Exxon Mobil Corp', 68.1, -0.43, -0.64, '9/1 12:00am'],
['General Electric Company', 34.14, -0.08, -0.23, '9/1 12:00am'],
['General Motors Corporation', 30.27, 1.09, 3.74, '9/1 12:00am'],
['Hewlett-Packard Co.', 36.53, -0.03, -0.08, '9/1 12:00am'],
['Honeywell Intl Inc', 38.77, 0.05, 0.13, '9/1 12:00am'],
['Intel Corporation', 19.88, 0.31, 1.58, '9/1 12:00am'],
['International Business Machines', 81.41, 0.44, 0.54, '9/1 12:00am'],
['Johnson & Johnson', 64.72, 0.06, 0.09, '9/1 12:00am'],
['JP Morgan & Chase & Co', 45.73, 0.07, 0.15, '9/1 12:00am'],
['McDonald\'s Corporation', 36.76, 0.86, 2.40, '9/1 12:00am'],
['Merck & Co., Inc.', 40.96, 0.41, 1.01, '9/1 12:00am'],
['Microsoft Corporation', 25.84, 0.14, 0.54, '9/1 12:00am'],
['Pfizer Inc', 27.96, 0.4, 1.45, '9/1 12:00am'],
['The Coca-Cola Company', 45.07, 0.26, 0.58, '9/1 12:00am'],
['The Home Depot, Inc.', 34.64, 0.35, 1.02, '9/1 12:00am'],
['The Procter & Gamble Company', 61.91, 0.01, 0.02, '9/1 12:00am'],
['United Technologies Corporation', 63.26, 0.55, 0.88, '9/1 12:00am'],
['Verizon Communications', 35.57, 0.39, 1.11, '9/1 12:00am'],
['Wal-Mart Stores, Inc.', 45.45, 0.73, 1.63, '9/1 12:00am']
];
// create a model for the Business
Ext.define('Business', { extend: 'Ext.data.Model',
fields: [
{name: 'company'},
{name: 'price', type: 'float'},
{name: 'change', type: 'float'},
{name: 'pctChange', type: 'float'},
{name: 'lastChange', type: 'date', dateFormat: 'n/j h:ia'}
]});
// create the data store
var myStore = Ext.create('Ext.data.ArrayStore', {
model: 'Business',
data: myData
});
// create the Grid
var grid = Ext.create('Ext.grid.Panel', {
store: myStore,
stateful: true,
stateId: 'stateGrid',
columns: [
{
text : 'Company',
flex : 1,
sortable : false,
dataIndex: 'company'
},
{
text : 'Price',
width : 75,
sortable : true,
renderer : 'usMoney',
dataIndex: 'price'
},
{
text : 'Change',
width : 75,
sortable : true,

dataIndex: 'change'
},
{
text : '% Change',
width : 75,
sortable : true,

dataIndex: 'pctChange'
},
{
text : 'Last Updated',
width : 85,
sortable : true,
renderer : Ext.util.Format.dateRenderer('m/d/Y'),
dataIndex: 'lastChange'
}
],
height: 350,
width: 600,
title: 'Array Grid',
renderTo: 'grid-example',
viewConfig: {
stripeRows: true
},
dockedItems: [{
xtype: 'toolbar',
dock: 'bottom',
items: [{
xtype: 'exporterbutton', text: 'Export-to-Excel'
}]
}]
});
});
</script>
</body>
</html>

vispiron
28 Jul 2011, 11:12 PM
Hi,

i include following:


Ext.Loader.setConfig({ enabled: true });
Ext.Loader.setPath('Ext.ux.exporter', 'ext/examples/ux/exporter');
Ext.require([
'Ext.grid.*',
'Ext.data.*',
'Ext.util.*',
'Ext.form.*',
'Ext.toolbar.Paging',
'Ext.ux.exporter.Exporter'
]);
The Script loads but ux/exporter/excelFormatter/Workbook.js give me an Error 500 Internal Server Error?

What can i do?

Ewoq
29 Jul 2011, 1:05 AM
What is the exact error message?

Is your directory called ext? or ext-4.0.2?

I think you also need a / in front of your path:


Ext.Loader.setConfig({ enabled: true });
Ext.Loader.setPath('Ext.ux.exporter', '/ext-4.0.2/examples/ux/exporter');

Would be my guess.

wiznia
29 Jul 2011, 1:48 AM
mmm An error 500 makes no sense, the exporter doesn't talk to the server in any way. The store does, and the exporter uses its data, so maybe there's an error in the call to the server by the store.

edspencer
29 Jul 2011, 4:35 PM
Glad someone revived this old thing :) I haven't touched the code in a year or more. Would love to have this come into the framework but finding it hard to find staffing for it at the moment given everything else we need to do.

wiznia
30 Jul 2011, 9:56 AM
It's far from ready and it doesn't work with IE...
Besides there are a lot more important things to get fixed.

Ewoq
2 Aug 2011, 5:31 AM
I would like to help you with it wiznia, if you'd like?

wiznia
2 Aug 2011, 6:08 AM
IE support would be nice, although I don't know how to tackle it, since there's no support for data uris (which are being used right now). Besides if we can get rid of the datauris, maybe we can optimize a little bit the plugin. Now, it is generating the file every time a load is made on the store, so even if you don't click the export button, the file is being generated...
Apart from that I wasn't going to add mucho more functionality since the functionality provided works for me, so suggestions are welcome.

nimda13
19 Aug 2011, 2:15 AM
col.on is not a function col.on("show", setLink, me);
Button...2614604 (line 51)
Any idea?

var exportButton = Ext.create('Ext.ux.exporter.Button', {
component: Ext.getCmp('grid'),
icon: '/odminko/extjs/examples/ux/exporter/page_white_excel.png',
text : "Сохранить в Excel"
});

Or comment
lines:
// col.on("show", setLink, me);
// col.on("hide", setLink, me);

nimda13
19 Aug 2011, 2:24 AM
I load the table with AJAX and eval() then processed.
At first, everything works fine.
But if I upload the same table again, unloads a blank file with the table name in the title.

My Code (all in eval() after AJAX request):



if (!Ext.ModelManager.isRegistered('ModelMyGrid<?php echo $service_id;?>')){
Ext.define('ModelMyGrid<?php echo $service_id;?>', {
extend: 'Ext.data.Model',
fields: [<?php echo $fields;?>],
idProperty: '<?php echo $id;?>'
});
}

// create the Data Store
var gridstore = Ext.create('Ext.data.Store', {
pageSize: 50,
model: 'ModelMyGrid<?php echo $service_id;?>',
autoLoad: true,
autoSync: true,
remoteSort: true,
proxy: {
type: 'ajax',
//url: '/extadmin/get_data_for_store/<?php echo $service_id;?>/',
api: {
read: '/extadmin/get_data_for_store/<?php echo $service_id;?>',
//create: 'app.php/users/create', создавать буду через форму
update: '/extadmin/fast_update_item/<?php echo $service_id;?>',
destroy: '/extadmin/delete_item/<?php echo $service_id;?>'
},
reader: {
type: 'json',
root: 'baseData',
totalProperty: 'totalCount'
},
writer: {
type: 'json',
writeAllFields: false, //передаются параметры только исправленных ячеек + ID
root: 'baseData' //массив, в котором закодированы данные
}

},
sorters: [{
property: '<?php echo $id;?>',
direction: 'DESC'
}],
listeners: {
write: function(gridstore, operation){
Ext.example.msg('Сохранено', 'Запись <b>' + record.getId() + '</b> сохранена');
gridstore.load();
}
}
});

var pluginExpanded = true;

var rowEditing = Ext.create('Ext.grid.plugin.CellEditing', {
clicksToEdit: 2
});

var filters = {
ftype: 'filters',
filters: [<?php echo $filters_data;?>]
};

var exportButton = Ext.create('Ext.ux.exporter.Button', {
component: Ext.getCmp('grid'),
icon: '/odminko/extjs/examples/ux/exporter/page_white_excel.png',
text : "Сохранить в Excel"
});

var grid = Ext.create('Ext.grid.Panel', {
id: 'central_body<?php echo $service_id;?>', //обязательный идентификатор для виджета, который будет грузиться в центральную часть. уникальный для каждого сервиса
title:'<?php echo $task_name;?>',
store: gridstore,
columnLines: true,
multiSelect: true, //можно выделить несколько строк
columns: [ <?php echo $columns_data;?>],
autoExpandColumn: '<?php echo $id;?>',
loadMask: true,
features: [filters],
plugins: [rowEditing],
dockedItems: [{
xtype: 'toolbar',
items: [ exportButton]
});
}
}
}]
}],
// paging bar on the bottom
bbar: Ext.create('Ext.PagingToolbar', {
store: gridstore,
displayInfo: true,
displayMsg: 'Записи {0} - {1}. Всего {2}',
emptyMsg: "Нет записей"
})
});

gridstore.loadPage(1);

bee
4 Sep 2011, 2:59 PM
@winzia,

I am facing below error 3487 (http://localhost:8080/i/lib/ext-4.0.2a/ext-all-debug.js)
Uncaught TypeError: Cannot call method 'substring' of undefined
I specified all what you mentioned. please help me

wiznia
5 Sep 2011, 2:34 AM
@bee, when are you getting this error? When loading the data in the store? When you click the button?
Also, what is that error 3487? Is it the line number? In which file? Do you have the stacktrace?

clarkbanks
5 Sep 2011, 5:43 PM
Is there anyway to specify the name of the xls file being downloaded? In chrome it just downloads a file called 'download' which has to be renamed with an '.xls' extension to work.

wiznia
6 Sep 2011, 1:19 AM
Right now there's not a way of specifying the name of the file, I don't know if this is possible since it's a data uri. I think you need flash in order to do that, I found this library https://github.com/dcneiner/Downloadify that uses a flash component to serve the file. It would solve the IE incompatibility and add some nice features like choosing the name and events on download. It should't be difficult to integrate it with the exporter button. Right now I don't have time to do it, but you can fork my project and then add a pull request.

bee
7 Sep 2011, 11:29 AM
I got this error when loading my grid itself. That line no is of debug file I guess. Even I am not sure about this.

wiznia
8 Sep 2011, 5:47 AM
mmm, you'll have to do a little debugging by yourself and give me more info if you want some help...
Or post a complete example that fails.

SMMJ_Dev
9 Sep 2011, 7:10 PM
Thank you very much! I downloaded your Exporter-all.js file, went through and converted all the ExtJS3 code from your individual ExtJS4 updates. I modified the code so that exportGrid, exportStore, and exportTree do not return the encoded data. Then I updated the button to call the encode directly. So now, in my code, I make a call to exportGrid to get the data. I check the browser to see if it can use the data urls. If so, I do a redirect to the data url. Otherwise I send the non-encoded data to a java servlet so that browsers like IE7 can export the grid to excel :)

Everything worked great! I liked the format update to your code from ExtJS3 :)

wiznia
12 Sep 2011, 11:51 AM
great!!! did you forked it in gIthub? Send my a pull request and I'll add It.

ma1986
13 Sep 2011, 5:03 PM
i load the <script src="../toexcel/Exporter-all.js" type="text/javascript"></script>
but firebug find a erro like Ext.reg is not a function in "Ext.reg('exportbutton', Ext.ux.Exporter.Button)" why? i uses Ext4.0

can you help me thank you

ma1986
13 Sep 2011, 9:45 PM
dear wiznia (http://www.sencha.com/forum/member.php?40722-wiznia)

I have get the excel successfully,thank you.however ,my grid has the Subtotal,how can i export excel with the Subtotal. i know the store don't have Subtotal field .but how i can do it? thanks
like this:
name price
one 10
two 20
Subtotal: 30
three 15
...

I think a methd that can i load a new store which is not the store of grid ? i don't know it will be work or not

SMMJ_Dev
14 Sep 2011, 2:41 PM
Ok, I have created the fork and pull I think :)

SMMJ_Dev
14 Sep 2011, 2:48 PM
I have also added a check on the exportGrid function to not export any action columns. This was messed up before. The columns were not lining up correctly.

semialcruz
16 Sep 2011, 8:33 AM
Same here, can anyone help me with this ?

Firebug Error:



Uncaught TypeError: Object #<Object> has no method 'reg'

SMMJ_Dev
17 Sep 2011, 8:00 AM
The code has not gotten my updates yet if you are using ExtJS4, try this code to see if it works for you:

This should be the only file you include below. It is my recommended update for Exporter-all.js. I have not personally tried the export button. I have only used the code for the export function, so let me know if it works for you.



/**** Base64 encode / decode* http://www.webtoolkit.info/***/(function() { // private property var keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; // private method for UTF-8 encoding function utf8Encode(string) { string = string.replace(/\r\n/g,"\n"); var utftext = ""; for (var n = 0; n < string.length; n++) { var c = string.charCodeAt(n); if (c < 128) { utftext += String.fromCharCode(c); } else if((c > 127) && (c < 2048)) { utftext += String.fromCharCode((c >> 6) | 192); utftext += String.fromCharCode((c & 63) | 128); } else { utftext += String.fromCharCode((c >> 12) | 224); utftext += String.fromCharCode(((c >> 6) & 63) | 128); utftext += String.fromCharCode((c & 63) | 128); } } return utftext; } Ext.define("Ext.ux.exporter.Base64", { statics: { //This was the original line, which tries to use Firefox's built in Base64 encoder, but this kept throwing exceptions.... // encode : (typeof btoa == 'function') ? function(input) { return btoa(input); } : function (input) { encode : function (input) { var output = ""; var chr1, chr2, chr3, enc1, enc2, enc3, enc4; var i = 0; input = utf8Encode(input); while (i < input.length) { chr1 = input.charCodeAt(i++); chr2 = input.charCodeAt(i++); chr3 = input.charCodeAt(i++); enc1 = chr1 >> 2; enc2 = ((chr1 & 3) << 4) | (chr2 >> 4); enc3 = ((chr2 & 15) << 2) | (chr3 >> 6); enc4 = chr3 & 63; if (isNaN(chr2)) { enc3 = enc4 = 64; } else if (isNaN(chr3)) { enc4 = 64; } output = output + keyStr.charAt(enc1) + keyStr.charAt(enc2) + keyStr.charAt(enc3) + keyStr.charAt(enc4); } return output; }} });})();/** * @class Ext.ux.Exporter * @author Ed Spencer (http://edspencer.net), with modifications from iwiznia. * Class providing a common way of downloading data in .xls or .csv format */Ext.define("Ext.ux.exporter.Exporter", { uses: [ "Ext.ux.exporter.Base64", "Ext.ux.exporter.Button", "Ext.ux.exporter.csvFormatter.CsvFormatter", "Ext.ux.exporter.excelFormatter.ExcelFormatter" ], statics: { exportAny: function(component, formatter, config) { var func = "export"; if(!component.is) { func = func + "Store"; } else if(component.is("gridpanel")) { func = func + "Grid"; } else if (component.is("treepanel")) { func = func + "Tree"; } else { func = func + "Store"; component = component.getStore(); } return this[func](component, formatter, config); }, /** * Exports a grid, using the .xls formatter by default * @param {Ext.grid.GridPanel} grid The grid to export from * @param {Object} config Optional config settings for the formatter */ exportGrid: function(grid, formatter, config) { config = config || {}; formatter = formatter || new Ext.ux.exporter.excelFormatter.ExcelFormatter(); var columns = Ext.Array.filter(grid.columns, function(col) { if(col.xtype){ return !col.hidden && col.xtype != "actioncolumn"; } return !col.hidden; }); Ext.applyIf(config, { title : grid.title, columns: columns }); return Ext.ux.exporter.Base64.encode(formatter.format(grid.store, config)); }, exportStore: function(store, formatter, config) { config = config || {}; formatter = formatter || new Ext.ux.exporter.excelFormatter.ExcelFormatter(); Ext.applyIf(config, { columns: store.fields ? store.fields.items : store.model.prototype.fields.items }); return Ext.ux.exporter.Base64.encode(formatter.format(store, config)); }, exportTree: function(tree, formatter, config) { config = config || {}; formatter = formatter || new Ext.ux.exporter.excelFormatter.ExcelFormatter(); var store = tree.store || config.store; Ext.applyIf(config, { title: tree.title }); return Ext.ux.exporter.Base64.encode(formatter.format(store, config)); } }});/** * @class Ext.ux.Exporter.Button * @extends Ext.Button * @author Nige White, with modifications from Ed Spencer, with modifications from iwiznia. * Specialised Button class that allows downloading of data via data: urls. * Internally, this is just a link. * Pass it either an Ext.Component subclass with a 'store' property, or just a store or nothing and it will try to grab the first parent of this button that is a grid or tree panel: * new Ext.ux.Exporter.Button({component: someGrid}); * new Ext.ux.Exporter.Button({store: someStore}); * @cfg {Ext.Component} component The component the store is bound to * @cfg {Ext.data.Store} store The store to export (alternatively, pass a component with a getStore method) */Ext.define("Ext.ux.exporter.Button", { extend: "Ext.Button", alias: "widget.exporterbutton", constructor: function(config) { config = config || {}; Ext.applyIf(config, { disabled : true, text : 'Download', cls : 'download', href : "/" }); Ext.ux.exporter.Button.superclass.constructor.call(this, config); if (this.store || this.component) { this.setComponent(this.store || this.component, config); } else { var self = this; this.on("render", function() { // We wait for the combo to be rendered, so we can look up to grab the component containing it self.setComponent(self.up("gridpanel") || self.up("treepanel"), config); }); } }, setComponent: function(component, config) { this.component = component; this.store = !component.is ? component : component.getStore(); // only components or stores, if it doesn't respond to is method, it's a store var setLink = function() { var newConf = Ext.clone(config); this.el.query('a', true)[0].href = 'data:application/vnd.ms-excel;base64,' + Ext.ux.exporter.Exporter.exportAny(this.component, null, newConf); this.enable(); }; var me = this; this.store.on("load", setLink, this); if(Ext.ComponentQuery.is(this.component, "gridpanel")) { Ext.Array.each(this.component.columns, function(col) { col.on("show", setLink, me); col.on("hide", setLink, me); }); } }, onClick : function(e){ if (e.button != 0) return; if (!this.disabled){ this.fireEvent("click", this, e); if (this.handler) this.handler.call(this.scope || this, this, e); } }});/** * @class Ext.ux.Exporter.Formatter * @author Ed Spencer (http://edspencer.net) * @cfg {Ext.data.Store} store The store to export */Ext.define("Ext.ux.exporter.Formatter", { /** * Performs the actual formatting. This must be overridden by a subclass */ format: Ext.emptyFn, constructor: function(config) { config = config || {}; Ext.applyIf(config, { }); }});/** * @class Ext.ux.Exporter.ExcelFormatter * @extends Ext.ux.Exporter.Formatter * Specialised Format class for outputting .xls files */Ext.define("Ext.ux.exporter.excelFormatter.ExcelFormatter", { extend: "Ext.ux.exporter.Formatter", uses: [ "Ext.ux.exporter.excelFormatter.Cell", "Ext.ux.exporter.excelFormatter.Style", "Ext.ux.exporter.excelFormatter.Worksheet", "Ext.ux.exporter.excelFormatter.Workbook" ], format: function(store, config) { var workbook = new Ext.ux.exporter.excelFormatter.Workbook(config); workbook.addWorksheet(store, config || {}); return workbook.render(); }});/** * @class Ext.ux.Exporter.ExcelFormatter.Workbook * @extends Object * Represents an Excel workbook */Ext.define("Ext.ux.exporter.excelFormatter.Workbook", { constructor: function(config) { config = config || {}; Ext.apply(this, config, { /** * @property title * @type String * The title of the workbook (defaults to "Workbook") */ title: "Workbook", /** * @property worksheets * @type Array * The array of worksheets inside this workbook */ worksheets: [], /** * @property compileWorksheets * @type Array * Array of all rendered Worksheets */ compiledWorksheets: [], /** * @property cellBorderColor * @type String * The colour of border to use for each Cell */ cellBorderColor: "#e4e4e4", /** * @property styles * @type Array * The array of Ext.ux.Exporter.ExcelFormatter.Style objects attached to this workbook */ styles: [], /** * @property compiledStyles * @type Array * Array of all rendered Ext.ux.Exporter.ExcelFormatter.Style objects for this workbook */ compiledStyles: [], /** * @property hasDefaultStyle * @type Boolean * True to add the default styling options to all cells (defaults to true) */ hasDefaultStyle: true, /** * @property hasStripeStyles * @type Boolean * True to add the striping styles (defaults to true) */ hasStripeStyles: true, windowHeight : 9000, windowWidth : 50000, protectStructure: false, protectWindows : false }); if (this.hasDefaultStyle) this.addDefaultStyle(); if (this.hasStripeStyles) this.addStripedStyles(); this.addTitleStyle(); this.addHeaderStyle(); }, render: function() { this.compileStyles(); this.joinedCompiledStyles = this.compiledStyles.join(""); this.compileWorksheets(); this.joinedWorksheets = this.compiledWorksheets.join(""); return this.tpl.apply(this); }, /** * Adds a worksheet to this workbook based on a store and optional config * @param {Ext.data.Store} store The store to initialize the worksheet with * @param {Object} config Optional config object * @return {Ext.ux.Exporter.ExcelFormatter.Worksheet} The worksheet */ addWorksheet: function(store, config) { var worksheet = new Ext.ux.exporter.excelFormatter.Worksheet(store, config); this.worksheets.push(worksheet); return worksheet; }, /** * Adds a new Ext.ux.Exporter.ExcelFormatter.Style to this Workbook * @param {Object} config The style config, passed to the Style constructor (required) */ addStyle: function(config) { var style = new Ext.ux.exporter.excelFormatter.Style(config || {}); this.styles.push(style); return style; }, /** * Compiles each Style attached to this Workbook by rendering it * @return {Array} The compiled styles array */ compileStyles: function() { this.compiledStyles = []; Ext.each(this.styles, function(style) { this.compiledStyles.push(style.render()); }, this); return this.compiledStyles; }, /** * Compiles each Worksheet attached to this Workbook by rendering it * @return {Array} The compiled worksheets array */ compileWorksheets: function() { this.compiledWorksheets = []; Ext.each(this.worksheets, function(worksheet) { this.compiledWorksheets.push(worksheet.render()); }, this); return this.compiledWorksheets; }, tpl: new Ext.XTemplate( '<?xml version="1.0" encoding="utf-8"?>', '<ss:Workbook xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet" xmlns:x="urn:schemas-microsoft-com:office:excel" xmlns:o="urn:schemas-microsoft-com:office:office">', '<o:DocumentProperties>', '<o:Title>{title}</o:Title>', '</o:DocumentProperties>', '<ss:ExcelWorkbook>', '<ss:WindowHeight>{windowHeight}</ss:WindowHeight>', '<ss:WindowWidth>{windowWidth}</ss:WindowWidth>', '<ss:ProtectStructure>{protectStructure}</ss:ProtectStructure>', '<ss:ProtectWindows>{protectWindows}</ss:ProtectWindows>', '</ss:ExcelWorkbook>', '<ss:Styles>', '{joinedCompiledStyles}', '</ss:Styles>', '{joinedWorksheets}', '</ss:Workbook>' ), /** * Adds the default Style to this workbook. This sets the default font face and size, as well as cell borders */ addDefaultStyle: function() { var borderProperties = [ {name: "Color", value: this.cellBorderColor}, {name: "Weight", value: "1"}, {name: "LineStyle", value: "Continuous"} ]; this.addStyle({ id: 'Default', attributes: [ { name: "Alignment", properties: [ {name: "Vertical", value: "Top"}, {name: "WrapText", value: "1"} ] }, { name: "Font", properties: [ {name: "FontName", value: "arial"}, {name: "Size", value: "10"} ] }, {name: "Interior"}, {name: "NumberFormat"}, {name: "Protection"}, { name: "Borders", children: [ { name: "Border", properties: [{name: "Position", value: "Top"}].concat(borderProperties) }, { name: "Border", properties: [{name: "Position", value: "Bottom"}].concat(borderProperties) }, { name: "Border", properties: [{name: "Position", value: "Left"}].concat(borderProperties) }, { name: "Border", properties: [{name: "Position", value: "Right"}].concat(borderProperties) } ] } ] }); }, addTitleStyle: function() { this.addStyle({ id: "title", attributes: [ {name: "Borders"}, {name: "Font"}, { name: "NumberFormat", properties: [ {name: "Format", value: "@"} ] }, { name: "Alignment", properties: [ {name: "WrapText", value: "1"}, {name: "Horizontal", value: "Center"}, {name: "Vertical", value: "Center"} ] } ] }); }, addHeaderStyle: function() { this.addStyle({ id: "headercell", attributes: [ { name: "Font", properties: [ {name: "Bold", value: "1"}, {name: "Size", value: "10"} ] }, { name: "Interior", properties: [ {name: "Pattern", value: "Solid"}, {name: "Color", value: "#A3C9F1"} ] }, { name: "Alignment", properties: [ {name: "WrapText", value: "1"}, {name: "Horizontal", value: "Center"} ] } ] }); }, /** * Adds the default striping styles to this workbook */ addStripedStyles: function() { this.addStyle({ id: "even", attributes: [ { name: "Interior", properties: [ {name: "Pattern", value: "Solid"}, {name: "Color", value: "#CCFFFF"} ] } ] }); this.addStyle({ id: "odd", attributes: [ { name: "Interior", properties: [ {name: "Pattern", value: "Solid"}, {name: "Color", value: "#CCCCFF"} ] } ] }); Ext.each(['even', 'odd'], function(parentStyle) { this.addChildNumberFormatStyle(parentStyle, parentStyle + 'date', "[ENG][$-409]dd\-mmm\-yyyy;@"); this.addChildNumberFormatStyle(parentStyle, parentStyle + 'int', "0"); this.addChildNumberFormatStyle(parentStyle, parentStyle + 'float', "0.00"); }, this); }, /** * Private convenience function to easily add a NumberFormat style for a given parentStyle * @param {String} parentStyle The ID of the parentStyle Style * @param {String} id The ID of the new style * @param {String} value The value of the NumberFormat's Format property */ addChildNumberFormatStyle: function(parentStyle, id, value) { this.addStyle({ id: id, parentStyle: "even", attributes: [ { name: "NumberFormat", properties: [{name: "Format", value: value}] } ] }); }});/** * @class Ext.ux.Exporter.ExcelFormatter.Worksheet * @extends Object * Represents an Excel worksheet * @cfg {Ext.data.Store} store The store to use (required) */Ext.define("Ext.ux.exporter.excelFormatter.Worksheet", { constructor: function(store, config) { config = config || {}; this.store = store; Ext.applyIf(config, { hasTitle : true, hasHeadings: true, stripeRows : true, title : "Workbook", columns : store.fields == undefined ? {} : store.fields.items }); Ext.apply(this, config); Ext.ux.exporter.excelFormatter.Worksheet.superclass.constructor.apply(this, arguments); }, /** * @property dateFormatString * @type String * String used to format dates (defaults to "Y-m-d"). All other data types are left unmolested */ dateFormatString: "Y-m-d", worksheetTpl: new Ext.XTemplate( '<ss:Worksheet ss:Name="{title}">', '<ss:Names>', '<ss:NamedRange ss:Name="Print_Titles" ss:RefersTo="=\'{title}\'!R1:R2" />', '</ss:Names>', '<ss:Table x:FullRows="1" x:FullColumns="1" ss:ExpandedColumnCount="{colCount}" ss:ExpandedRowCount="{rowCount}">', '{columns}', '<ss:Row ss:Height="38">', '<ss:Cell ss:StyleID="title" ss:MergeAcross="{colCount - 1}">', '<ss:Data xmlns:html="http://www.w3.org/TR/REC-html40" ss:Type="String">', '<html:B><html:U><html:Font html:Size="15">{title}', '</html:Font></html:U></html:B></ss:Data><ss:NamedCell ss:Name="Print_Titles" />', '</ss:Cell>', '</ss:Row>', '<ss:Row ss:AutoFitHeight="1">', '{header}', '</ss:Row>', '{rows}', '</ss:Table>', '<x:WorksheetOptions>', '<x:PageSetup>', '<x:Layout x:CenterHorizontal="1" x:Orientation="Landscape" />', '<x:Footer x:Data="Page &amp;P of &amp;N" x:Margin="0.5" />', '<x:PageMargins x:Top="0.5" x:Right="0.5" x:Left="0.5" x:Bottom="0.8" />', '</x:PageSetup>', '<x:FitToPage />', '<x:Print>', '<x:PrintErrors>Blank</x:PrintErrors>', '<x:FitWidth>1</x:FitWidth>', '<x:FitHeight>32767</x:FitHeight>', '<x:ValidPrinterInfo />', '<x:VerticalResolution>600</x:VerticalResolution>', '</x:Print>', '<x:Selected />', '<x:DoNotDisplayGridlines />', '<x:ProtectObjects>False</x:ProtectObjects>', '<x:ProtectScenarios>False</x:ProtectScenarios>', '</x:WorksheetOptions>', '</ss:Worksheet>' ), /** * Builds the Worksheet XML * @param {Ext.data.Store} store The store to build from */ render: function(store) { return this.worksheetTpl.apply({ header : this.buildHeader(), columns : this.buildColumns().join(""), rows : this.buildRows().join(""), colCount: this.columns.length, rowCount: this.store.getCount() + 2, title : this.title }); }, buildColumns: function() { var cols = []; Ext.each(this.columns, function(column) { cols.push(this.buildColumn()); }, this); return cols; }, buildColumn: function(width) { return Ext.String.format('<ss:Column ss:AutoFitWidth="1" ss:Width="{0}" />', width || 164); }, buildRows: function() { var rows = []; this.store.each(function(record, index) { rows.push(this.buildRow(record, index)); }, this); return rows; }, buildHeader: function() { var cells = []; Ext.each(this.columns, function(col) { var title; //if(col.dataIndex) { if (col.text != undefined) { title = col.text; } else if(col.name) { //make columns taken from Record fields (e.g. with a col.name) human-readable title = col.name.replace(/_/g, " "); title = title.charAt(0).toUpperCase() + title.substr(1).toLowerCase(); } cells.push(Ext.String.format('<ss:Cell ss:StyleID="headercell"><ss:Data ss:Type="String">{0}</ss:Data><ss:NamedCell ss:Name="Print_Titles" /></ss:Cell>', title)); //} }, this); return cells.join(""); }, buildRow: function(record, index) { var style, cells = []; if (this.stripeRows === true) style = index % 2 == 0 ? 'even' : 'odd'; Ext.each(this.columns, function(col) { var name = col.name || col.dataIndex; if(name) { //if given a renderer via a ColumnModel, use it and ensure data type is set to String if (Ext.isFunction(col.renderer)) { var value = col.renderer(record.get(name), null, record), type = "String"; } else { var value = record.get(name), type = this.typeMappings[col.type || record.fields.get(name).type.type]; } cells.push(this.buildCell(value, type, style).render()); } }, this); return Ext.String.format("<ss:Row>{0}</ss:Row>", cells.join("")); }, buildCell: function(value, type, style) { if (type == "DateTime" && Ext.isFunction(value.format)) value = value.format(this.dateFormatString); return new Ext.ux.exporter.excelFormatter.Cell({ value: value, type : type, style: style }); }, /** * @property typeMappings * @type Object * Mappings from Ext.data.Record types to Excel types */ typeMappings: { 'int' : "Number", 'string': "String", 'float' : "Number", 'date' : "DateTime" }});/** * @class Ext.ux.Exporter.ExcelFormatter.Cell * @extends Object * Represents a single cell in a worksheet */Ext.define("Ext.ux.exporter.excelFormatter.Cell", { constructor: function(config) { Ext.applyIf(config, { type: "String" }); Ext.apply(this, config); Ext.ux.exporter.excelFormatter.Cell.superclass.constructor.apply(this, arguments); }, render: function() { return this.tpl.apply(this); }, tpl: new Ext.XTemplate( '<ss:Cell ss:StyleID="{style}">', '<ss:Data ss:Type="{type}"><![CDATA[{value}]]></ss:Data>', '</ss:Cell>' )});/** * @class Ext.ux.Exporter.ExcelFormatter.Style * @extends Object * Represents a style declaration for a Workbook (this is like defining CSS rules). Example: * * new Ext.ux.Exporter.ExcelFormatter.Style({ * attributes: [ * { * name: "Alignment", * properties: [ * {name: "Vertical", value: "Top"}, * {name: "WrapText", value: "1"} * ] * }, * { * name: "Borders", * children: [ * name: "Border", * properties: [ * {name: "Color", value: "#e4e4e4"}, * {name: "Weight", value: "1"} * ] * ] * } * ] * }) * * @cfg {String} id The ID of this style (required) * @cfg {Array} attributes The attributes for this style * @cfg {String} parentStyle The (optional parentStyle ID) */Ext.define("Ext.ux.exporter.excelFormatter.Style", { constructor: function(config) { config = config || {}; Ext.apply(this, config, { parentStyle: '', attributes : [] }); Ext.ux.exporter.excelFormatter.Style.superclass.constructor.apply(this, arguments); if (this.id == undefined) throw new Error("An ID must be provided to Style"); this.preparePropertyStrings(); }, /** * Iterates over the attributes in this style, and any children they may have, creating property * strings on each suitable for use in the XTemplate */ preparePropertyStrings: function() { Ext.each(this.attributes, function(attr, index) { this.attributes[index].propertiesString = this.buildPropertyString(attr); this.attributes[index].children = attr.children || []; Ext.each(attr.children, function(child, childIndex) { this.attributes[index].children[childIndex].propertiesString = this.buildPropertyString(child); }, this); }, this); }, /** * Builds a concatenated property string for a given attribute, suitable for use in the XTemplate */ buildPropertyString: function(attribute) { var propertiesString = ""; Ext.each(attribute.properties || [], function(property) { propertiesString += Ext.String.format('ss:{0}="{1}" ', property.name, property.value); }, this); return propertiesString; }, render: function() { return this.tpl.apply(this); }, tpl: new Ext.XTemplate( '<tpl if="parentStyle.length == 0">', '<ss:Style ss:ID="{id}">', '</tpl>', '<tpl if="parentStyle.length != 0">', '<ss:Style ss:ID="{id}" ss:Parent="{parentStyle}">', '</tpl>', '<tpl for="attributes">', '<tpl if="children.length == 0">', '<ss:{name} {propertiesString} />', '</tpl>', '<tpl if="children.length > 0">', '<ss:{name} {propertiesString}>', '<tpl for="children">', '<ss:{name} {propertiesString} />', '</tpl>', '</ss:{name}>', '</tpl>', '</tpl>', '</ss:Style>' )});

Ext.reg is not an ExtJS4 function, only ExtJS3.

semialcruz
20 Sep 2011, 8:15 AM
Thanks for the reply SMMJ_Dev

I copy&paste the code you give me above in a new file that I called "temp.js" but now I got the next error:

Uncaught TypeError: Cannot read property 'Button' of undefined
And I include only that file.

Can you help me with this ?

P.D. sorry for my bad English

grisevich
20 Sep 2011, 11:30 PM
Thanks for you work. But can you give more details how to make it work with IE?

SMMJ_Dev
21 Sep 2011, 5:53 AM
Yeah, I see the problem. It looks like in the code when they are creating a button they are Extending Ext.Button instead of Ext.button.Button.

Also this does not work in IE due to IE's restrictions on data urls. What I did to get around this is posted the XML back to the server and had the server export an excel document.




/**** Base64 encode / decode* http://www.webtoolkit.info/***/(function() { // private property var keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; // private method for UTF-8 encoding function utf8Encode(string) { string = string.replace(/\r\n/g,"\n"); var utftext = ""; for (var n = 0; n < string.length; n++) { var c = string.charCodeAt(n); if (c < 128) { utftext += String.fromCharCode(c); } else if((c > 127) && (c < 2048)) { utftext += String.fromCharCode((c >> 6) | 192); utftext += String.fromCharCode((c & 63) | 128); } else { utftext += String.fromCharCode((c >> 12) | 224); utftext += String.fromCharCode(((c >> 6) & 63) | 128); utftext += String.fromCharCode((c & 63) | 128); } } return utftext; } Ext.define("Ext.ux.exporter.Base64", { statics: { //This was the original line, which tries to use Firefox's built in Base64 encoder, but this kept throwing exceptions.... // encode : (typeof btoa == 'function') ? function(input) { return btoa(input); } : function (input) { encode : function (input) { var output = ""; var chr1, chr2, chr3, enc1, enc2, enc3, enc4; var i = 0; input = utf8Encode(input); while (i < input.length) { chr1 = input.charCodeAt(i++); chr2 = input.charCodeAt(i++); chr3 = input.charCodeAt(i++); enc1 = chr1 >> 2; enc2 = ((chr1 & 3) << 4) | (chr2 >> 4); enc3 = ((chr2 & 15) << 2) | (chr3 >> 6); enc4 = chr3 & 63; if (isNaN(chr2)) { enc3 = enc4 = 64; } else if (isNaN(chr3)) { enc4 = 64; } output = output + keyStr.charAt(enc1) + keyStr.charAt(enc2) + keyStr.charAt(enc3) + keyStr.charAt(enc4); } return output; }} });})();/** * @class Ext.ux.Exporter * @author Ed Spencer (http://edspencer.net), with modifications from iwiznia. * Class providing a common way of downloading data in .xls or .csv format */Ext.define("Ext.ux.exporter.Exporter", { uses: [ "Ext.ux.exporter.Base64", "Ext.ux.exporter.Button", "Ext.ux.exporter.csvFormatter.CsvFormatter", "Ext.ux.exporter.excelFormatter.ExcelFormatter" ], statics: { exportAny: function(component, formatter, config) { var func = "export"; if(!component.is) { func = func + "Store"; } else if(component.is("gridpanel")) { func = func + "Grid"; } else if (component.is("treepanel")) { func = func + "Tree"; } else { func = func + "Store"; component = component.getStore(); } return this[func](component, formatter, config); }, /** * Exports a grid, using the .xls formatter by default * @param {Ext.grid.GridPanel} grid The grid to export from * @param {Object} config Optional config settings for the formatter */ exportGrid: function(grid, formatter, config) { config = config || {}; formatter = formatter || new Ext.ux.exporter.excelFormatter.ExcelFormatter(); var columns = Ext.Array.filter(grid.columns, function(col) { if(col.xtype){ return !col.hidden && col.xtype != "actioncolumn"; } return !col.hidden; }); Ext.applyIf(config, { title : grid.title, columns: columns }); return Ext.ux.exporter.Base64.encode(formatter.format(grid.store, config)); }, exportStore: function(store, formatter, config) { config = config || {}; formatter = formatter || new Ext.ux.exporter.excelFormatter.ExcelFormatter(); Ext.applyIf(config, { columns: store.fields ? store.fields.items : store.model.prototype.fields.items }); return Ext.ux.exporter.Base64.encode(formatter.format(store, config)); }, exportTree: function(tree, formatter, config) { config = config || {}; formatter = formatter || new Ext.ux.exporter.excelFormatter.ExcelFormatter(); var store = tree.store || config.store; Ext.applyIf(config, { title: tree.title }); return Ext.ux.exporter.Base64.encode(formatter.format(store, config)); } }});/** * @class Ext.ux.Exporter.Button * @extends Ext.Button * @author Nige White, with modifications from Ed Spencer, with modifications from iwiznia. * Specialised Button class that allows downloading of data via data: urls. * Internally, this is just a link. * Pass it either an Ext.Component subclass with a 'store' property, or just a store or nothing and it will try to grab the first parent of this button that is a grid or tree panel: * new Ext.ux.Exporter.Button({component: someGrid}); * new Ext.ux.Exporter.Button({store: someStore}); * @cfg {Ext.Component} component The component the store is bound to * @cfg {Ext.data.Store} store The store to export (alternatively, pass a component with a getStore method) */Ext.define("Ext.ux.exporter.Button", { extend: "Ext.button.Button", alias: "widget.exporterbutton", constructor: function(config) { config = config || {}; Ext.applyIf(config, { disabled : true, text : 'Download', cls : 'download', href : "/" }); Ext.ux.exporter.Button.superclass.constructor.call(this, config); if (this.store || this.component) { this.setComponent(this.store || this.component, config); } else { var self = this; this.on("render", function() { // We wait for the combo to be rendered, so we can look up to grab the component containing it self.setComponent(self.up("gridpanel") || self.up("treepanel"), config); }); } }, setComponent: function(component, config) { this.component = component; this.store = !component.is ? component : component.getStore(); // only components or stores, if it doesn't respond to is method, it's a store var setLink = function() { var newConf = Ext.clone(config); this.el.query('a', true)[0].href = 'data:application/vnd.ms-excel;base64,' + Ext.ux.exporter.Exporter.exportAny(this.component, null, newConf); this.enable(); }; var me = this; this.store.on("load", setLink, this); if(Ext.ComponentQuery.is(this.component, "gridpanel")) { Ext.Array.each(this.component.columns, function(col) { col.on("show", setLink, me); col.on("hide", setLink, me); }); } }, onClick : function(e){ if (e.button != 0) return; if (!this.disabled){ this.fireEvent("click", this, e); if (this.handler) this.handler.call(this.scope || this, this, e); } }});/** * @class Ext.ux.Exporter.Formatter * @author Ed Spencer (http://edspencer.net) * @cfg {Ext.data.Store} store The store to export */Ext.define("Ext.ux.exporter.Formatter", { /** * Performs the actual formatting. This must be overridden by a subclass */ format: Ext.emptyFn, constructor: function(config) { config = config || {}; Ext.applyIf(config, { }); }});/** * @class Ext.ux.Exporter.ExcelFormatter * @extends Ext.ux.Exporter.Formatter * Specialised Format class for outputting .xls files */Ext.define("Ext.ux.exporter.excelFormatter.ExcelFormatter", { extend: "Ext.ux.exporter.Formatter", uses: [ "Ext.ux.exporter.excelFormatter.Cell", "Ext.ux.exporter.excelFormatter.Style", "Ext.ux.exporter.excelFormatter.Worksheet", "Ext.ux.exporter.excelFormatter.Workbook" ], format: function(store, config) { var workbook = new Ext.ux.exporter.excelFormatter.Workbook(config); workbook.addWorksheet(store, config || {}); return workbook.render(); }});/** * @class Ext.ux.Exporter.ExcelFormatter.Workbook * @extends Object * Represents an Excel workbook */Ext.define("Ext.ux.exporter.excelFormatter.Workbook", { constructor: function(config) { config = config || {}; Ext.apply(this, config, { /** * @property title * @type String * The title of the workbook (defaults to "Workbook") */ title: "Workbook", /** * @property worksheets * @type Array * The array of worksheets inside this workbook */ worksheets: [], /** * @property compileWorksheets * @type Array * Array of all rendered Worksheets */ compiledWorksheets: [], /** * @property cellBorderColor * @type String * The colour of border to use for each Cell */ cellBorderColor: "#e4e4e4", /** * @property styles * @type Array * The array of Ext.ux.Exporter.ExcelFormatter.Style objects attached to this workbook */ styles: [], /** * @property compiledStyles * @type Array * Array of all rendered Ext.ux.Exporter.ExcelFormatter.Style objects for this workbook */ compiledStyles: [], /** * @property hasDefaultStyle * @type Boolean * True to add the default styling options to all cells (defaults to true) */ hasDefaultStyle: true, /** * @property hasStripeStyles * @type Boolean * True to add the striping styles (defaults to true) */ hasStripeStyles: true, windowHeight : 9000, windowWidth : 50000, protectStructure: false, protectWindows : false }); if (this.hasDefaultStyle) this.addDefaultStyle(); if (this.hasStripeStyles) this.addStripedStyles(); this.addTitleStyle(); this.addHeaderStyle(); }, render: function() { this.compileStyles(); this.joinedCompiledStyles = this.compiledStyles.join(""); this.compileWorksheets(); this.joinedWorksheets = this.compiledWorksheets.join(""); return this.tpl.apply(this); }, /** * Adds a worksheet to this workbook based on a store and optional config * @param {Ext.data.Store} store The store to initialize the worksheet with * @param {Object} config Optional config object * @return {Ext.ux.Exporter.ExcelFormatter.Worksheet} The worksheet */ addWorksheet: function(store, config) { var worksheet = new Ext.ux.exporter.excelFormatter.Worksheet(store, config); this.worksheets.push(worksheet); return worksheet; }, /** * Adds a new Ext.ux.Exporter.ExcelFormatter.Style to this Workbook * @param {Object} config The style config, passed to the Style constructor (required) */ addStyle: function(config) { var style = new Ext.ux.exporter.excelFormatter.Style(config || {}); this.styles.push(style); return style; }, /** * Compiles each Style attached to this Workbook by rendering it * @return {Array} The compiled styles array */ compileStyles: function() { this.compiledStyles = []; Ext.each(this.styles, function(style) { this.compiledStyles.push(style.render()); }, this); return this.compiledStyles; }, /** * Compiles each Worksheet attached to this Workbook by rendering it * @return {Array} The compiled worksheets array */ compileWorksheets: function() { this.compiledWorksheets = []; Ext.each(this.worksheets, function(worksheet) { this.compiledWorksheets.push(worksheet.render()); }, this); return this.compiledWorksheets; }, tpl: new Ext.XTemplate( '<?xml version="1.0" encoding="utf-8"?>', '<ss:Workbook xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet" xmlns:x="urn:schemas-microsoft-com:office:excel" xmlns:o="urn:schemas-microsoft-com:office:office">', '<o:DocumentProperties>', '<o:Title>{title}</o:Title>', '</o:DocumentProperties>', '<ss:ExcelWorkbook>', '<ss:WindowHeight>{windowHeight}</ss:WindowHeight>', '<ss:WindowWidth>{windowWidth}</ss:WindowWidth>', '<ss:ProtectStructure>{protectStructure}</ss:ProtectStructure>', '<ss:ProtectWindows>{protectWindows}</ss:ProtectWindows>', '</ss:ExcelWorkbook>', '<ss:Styles>', '{joinedCompiledStyles}', '</ss:Styles>', '{joinedWorksheets}', '</ss:Workbook>' ), /** * Adds the default Style to this workbook. This sets the default font face and size, as well as cell borders */ addDefaultStyle: function() { var borderProperties = [ {name: "Color", value: this.cellBorderColor}, {name: "Weight", value: "1"}, {name: "LineStyle", value: "Continuous"} ]; this.addStyle({ id: 'Default', attributes: [ { name: "Alignment", properties: [ {name: "Vertical", value: "Top"}, {name: "WrapText", value: "1"} ] }, { name: "Font", properties: [ {name: "FontName", value: "arial"}, {name: "Size", value: "10"} ] }, {name: "Interior"}, {name: "NumberFormat"}, {name: "Protection"}, { name: "Borders", children: [ { name: "Border", properties: [{name: "Position", value: "Top"}].concat(borderProperties) }, { name: "Border", properties: [{name: "Position", value: "Bottom"}].concat(borderProperties) }, { name: "Border", properties: [{name: "Position", value: "Left"}].concat(borderProperties) }, { name: "Border", properties: [{name: "Position", value: "Right"}].concat(borderProperties) } ] } ] }); }, addTitleStyle: function() { this.addStyle({ id: "title", attributes: [ {name: "Borders"}, {name: "Font"}, { name: "NumberFormat", properties: [ {name: "Format", value: "@"} ] }, { name: "Alignment", properties: [ {name: "WrapText", value: "1"}, {name: "Horizontal", value: "Center"}, {name: "Vertical", value: "Center"} ] } ] }); }, addHeaderStyle: function() { this.addStyle({ id: "headercell", attributes: [ { name: "Font", properties: [ {name: "Bold", value: "1"}, {name: "Size", value: "10"} ] }, { name: "Interior", properties: [ {name: "Pattern", value: "Solid"}, {name: "Color", value: "#A3C9F1"} ] }, { name: "Alignment", properties: [ {name: "WrapText", value: "1"}, {name: "Horizontal", value: "Center"} ] } ] }); }, /** * Adds the default striping styles to this workbook */ addStripedStyles: function() { this.addStyle({ id: "even", attributes: [ { name: "Interior", properties: [ {name: "Pattern", value: "Solid"}, {name: "Color", value: "#CCFFFF"} ] } ] }); this.addStyle({ id: "odd", attributes: [ { name: "Interior", properties: [ {name: "Pattern", value: "Solid"}, {name: "Color", value: "#CCCCFF"} ] } ] }); Ext.each(['even', 'odd'], function(parentStyle) { this.addChildNumberFormatStyle(parentStyle, parentStyle + 'date', "[ENG][$-409]dd\-mmm\-yyyy;@"); this.addChildNumberFormatStyle(parentStyle, parentStyle + 'int', "0"); this.addChildNumberFormatStyle(parentStyle, parentStyle + 'float', "0.00"); }, this); }, /** * Private convenience function to easily add a NumberFormat style for a given parentStyle * @param {String} parentStyle The ID of the parentStyle Style * @param {String} id The ID of the new style * @param {String} value The value of the NumberFormat's Format property */ addChildNumberFormatStyle: function(parentStyle, id, value) { this.addStyle({ id: id, parentStyle: "even", attributes: [ { name: "NumberFormat", properties: [{name: "Format", value: value}] } ] }); }});/** * @class Ext.ux.Exporter.ExcelFormatter.Worksheet * @extends Object * Represents an Excel worksheet * @cfg {Ext.data.Store} store The store to use (required) */Ext.define("Ext.ux.exporter.excelFormatter.Worksheet", { constructor: function(store, config) { config = config || {}; this.store = store; Ext.applyIf(config, { hasTitle : true, hasHeadings: true, stripeRows : true, title : "Workbook", columns : store.fields == undefined ? {} : store.fields.items }); Ext.apply(this, config); Ext.ux.exporter.excelFormatter.Worksheet.superclass.constructor.apply(this, arguments); }, /** * @property dateFormatString * @type String * String used to format dates (defaults to "Y-m-d"). All other data types are left unmolested */ dateFormatString: "Y-m-d", worksheetTpl: new Ext.XTemplate( '<ss:Worksheet ss:Name="{title}">', '<ss:Names>', '<ss:NamedRange ss:Name="Print_Titles" ss:RefersTo="=\'{title}\'!R1:R2" />', '</ss:Names>', '<ss:Table x:FullRows="1" x:FullColumns="1" ss:ExpandedColumnCount="{colCount}" ss:ExpandedRowCount="{rowCount}">', '{columns}', '<ss:Row ss:Height="38">', '<ss:Cell ss:StyleID="title" ss:MergeAcross="{colCount - 1}">', '<ss:Data xmlns:html="http://www.w3.org/TR/REC-html40" ss:Type="String">', '<html:B><html:U><html:Font html:Size="15">{title}', '</html:Font></html:U></html:B></ss:Data><ss:NamedCell ss:Name="Print_Titles" />', '</ss:Cell>', '</ss:Row>', '<ss:Row ss:AutoFitHeight="1">', '{header}', '</ss:Row>', '{rows}', '</ss:Table>', '<x:WorksheetOptions>', '<x:PageSetup>', '<x:Layout x:CenterHorizontal="1" x:Orientation="Landscape" />', '<x:Footer x:Data="Page &amp;P of &amp;N" x:Margin="0.5" />', '<x:PageMargins x:Top="0.5" x:Right="0.5" x:Left="0.5" x:Bottom="0.8" />', '</x:PageSetup>', '<x:FitToPage />', '<x:Print>', '<x:PrintErrors>Blank</x:PrintErrors>', '<x:FitWidth>1</x:FitWidth>', '<x:FitHeight>32767</x:FitHeight>', '<x:ValidPrinterInfo />', '<x:VerticalResolution>600</x:VerticalResolution>', '</x:Print>', '<x:Selected />', '<x:DoNotDisplayGridlines />', '<x:ProtectObjects>False</x:ProtectObjects>', '<x:ProtectScenarios>False</x:ProtectScenarios>', '</x:WorksheetOptions>', '</ss:Worksheet>' ), /** * Builds the Worksheet XML * @param {Ext.data.Store} store The store to build from */ render: function(store) { return this.worksheetTpl.apply({ header : this.buildHeader(), columns : this.buildColumns().join(""), rows : this.buildRows().join(""), colCount: this.columns.length, rowCount: this.store.getCount() + 2, title : this.title }); }, buildColumns: function() { var cols = []; Ext.each(this.columns, function(column) { cols.push(this.buildColumn()); }, this); return cols; }, buildColumn: function(width) { return Ext.String.format('<ss:Column ss:AutoFitWidth="1" ss:Width="{0}" />', width || 164); }, buildRows: function() { var rows = []; this.store.each(function(record, index) { rows.push(this.buildRow(record, index)); }, this); return rows; }, buildHeader: function() { var cells = []; Ext.each(this.columns, function(col) { var title; //if(col.dataIndex) { if (col.text != undefined) { title = col.text; } else if(col.name) { //make columns taken from Record fields (e.g. with a col.name) human-readable title = col.name.replace(/_/g, " "); title = title.charAt(0).toUpperCase() + title.substr(1).toLowerCase(); } cells.push(Ext.String.format('<ss:Cell ss:StyleID="headercell"><ss:Data ss:Type="String">{0}</ss:Data><ss:NamedCell ss:Name="Print_Titles" /></ss:Cell>', title)); //} }, this); return cells.join(""); }, buildRow: function(record, index) { var style, cells = []; if (this.stripeRows === true) style = index % 2 == 0 ? 'even' : 'odd'; Ext.each(this.columns, function(col) { var name = col.name || col.dataIndex; if(name) { //if given a renderer via a ColumnModel, use it and ensure data type is set to String if (Ext.isFunction(col.renderer)) { var value = col.renderer(record.get(name), null, record), type = "String"; } else { var value = record.get(name), type = this.typeMappings[col.type || record.fields.get(name).type.type]; } cells.push(this.buildCell(value, type, style).render()); } }, this); return Ext.String.format("<ss:Row>{0}</ss:Row>", cells.join("")); }, buildCell: function(value, type, style) { if (type == "DateTime" && Ext.isFunction(value.format)) value = value.format(this.dateFormatString); return new Ext.ux.exporter.excelFormatter.Cell({ value: value, type : type, style: style }); }, /** * @property typeMappings * @type Object * Mappings from Ext.data.Record types to Excel types */ typeMappings: { 'int' : "Number", 'string': "String", 'float' : "Number", 'date' : "DateTime" }});/** * @class Ext.ux.Exporter.ExcelFormatter.Cell * @extends Object * Represents a single cell in a worksheet */Ext.define("Ext.ux.exporter.excelFormatter.Cell", { constructor: function(config) { Ext.applyIf(config, { type: "String" }); Ext.apply(this, config); Ext.ux.exporter.excelFormatter.Cell.superclass.constructor.apply(this, arguments); }, render: function() { return this.tpl.apply(this); }, tpl: new Ext.XTemplate( '<ss:Cell ss:StyleID="{style}">', '<ss:Data ss:Type="{type}"><=!=[=C=D=A=T=A=[{value}]=]=></ss:Data>', '</ss:Cell>' )});/** * @class Ext.ux.Exporter.ExcelFormatter.Style * @extends Object * Represents a style declaration for a Workbook (this is like defining CSS rules). Example: * * new Ext.ux.Exporter.ExcelFormatter.Style({ * attributes: [ * { * name: "Alignment", * properties: [ * {name: "Vertical", value: "Top"}, * {name: "WrapText", value: "1"} * ] * }, * { * name: "Borders", * children: [ * name: "Border", * properties: [ * {name: "Color", value: "#e4e4e4"}, * {name: "Weight", value: "1"} * ] * ] * } * ] * }) * * @cfg {String} id The ID of this style (required) * @cfg {Array} attributes The attributes for this style * @cfg {String} parentStyle The (optional parentStyle ID) */Ext.define("Ext.ux.exporter.excelFormatter.Style", { constructor: function(config) { config = config || {}; Ext.apply(this, config, { parentStyle: '', attributes : [] }); Ext.ux.exporter.excelFormatter.Style.superclass.constructor.apply(this, arguments); if (this.id == undefined) throw new Error("An ID must be provided to Style"); this.preparePropertyStrings(); }, /** * Iterates over the attributes in this style, and any children they may have, creating property * strings on each suitable for use in the XTemplate */ preparePropertyStrings: function() { Ext.each(this.attributes, function(attr, index) { this.attributes[index].propertiesString = this.buildPropertyString(attr); this.attributes[index].children = attr.children || []; Ext.each(attr.children, function(child, childIndex) { this.attributes[index].children[childIndex].propertiesString = this.buildPropertyString(child); }, this); }, this); }, /** * Builds a concatenated property string for a given attribute, suitable for use in the XTemplate */ buildPropertyString: function(attribute) { var propertiesString = ""; Ext.each(attribute.properties || [], function(property) { propertiesString += Ext.String.format('ss:{0}="{1}" ', property.name, property.value); }, this); return propertiesString; }, render: function() { return this.tpl.apply(this); }, tpl: new Ext.XTemplate( '<tpl if="parentStyle.length == 0">', '<ss:Style ss:ID="{id}">', '</tpl>', '<tpl if="parentStyle.length != 0">', '<ss:Style ss:ID="{id}" ss:Parent="{parentStyle}">', '</tpl>', '<tpl for="attributes">', '<tpl if="children.length == 0">', '<ss:{name} {propertiesString} />', '</tpl>', '<tpl if="children.length > 0">', '<ss:{name} {propertiesString}>', '<tpl for="children">', '<ss:{name} {propertiesString} />', '</tpl>', '</ss:{name}>', '</tpl>', '</tpl>', '</ss:Style>' )});

Try this new code

semialcruz
23 Sep 2011, 7:13 AM
Same error... I tried everything yesterday and nothing seems to work :((

I copy&paste your code and included on my index.php

This is part of my code:
GRID


var gridPanel = Ext.create('Ext.grid.Panel', {
flex: 0.60,
store: store,
id: 'store-form',
title:'Datos de Cotizaciones',
layout: 'fit',
columns: [
{ text: 'Codigo', flex: 0.10, sortable: true, dataIndex: 'code', align: 'left' },
{ id: 'stores', text: 'Tienda', flex: 0.55, sortable: true, dataIndex: 'stores', align: 'left' },
{ text: 'Abiertas', flex: 0.15, sortable: true, dataIndex: 'opened', align: 'right', renderer: function(val){ return '<span style="color:#ff0000;">' + val + '</span>';} },
{ text: 'Cerradas', flex: 0.15, sortable: true, dataIndex: 'closed', align: 'right', renderer: function(val){ return '<span style="color:#318021;">' + val + '</span>';} },
{ text: 'Total Cotizaciones', flex: 0.15, sortable: true, dataIndex: 'quotes', align: 'right' }
],
listeners: {
selectionchange: function(model, records) {
var json, name, i, l, items, series, fields;
if (records[0]) {
rec = records[0];
form = form || this.up('form').getForm();
fields = form.getFields();
fields.each(function(field){ field.suspendEvents(); });
form.loadRecord(rec);
updateRecord(rec);
fields.each(function(field){ field.resumeEvents(); });
}
}
}
});

BUTTON


var exportButton = new Ext.ux.Exporter.Button({
component: gridPanel,
text : "Download as .xls"
});

FORM


var gridForm = Ext.create('Ext.form.Panel', {
id: 'gridForm',
title: 'Cotizaciones',
frame: true,
bodyPadding: 5,
width: 870,
height: 720,
fieldDefaults: { labelAlign: 'left', msgTarget: 'side' },
layout: { type: 'vbox',align: 'stretch' },
items: [{
height: 180,
layout: 'fit',
margin: '0 0 3 0',
items: [barChart]
},{
layout: {type: 'hbox', align: 'stretch'},
flex: 3,
border: false,
bodyStyle: 'background-color: transparent',
items: [gridPanel, {
flex: 0.4,
layout: { type: 'vbox', align:'stretch' },
margin: '0 0 0 5',
title: 'Detalle de Cotizaciones',
items: [{
margin: '5',
xtype: 'fieldset',
flex: 1,
title:'Detalle de Cotizaciones',
defaults: { width: 240, labelWidth: 90 },
defaultType: 'textfield',
autoScroll: true,
items: [
{ fieldLabel: 'Tienda', name: 'stores', disabled: true },
{ fieldLabel: 'Abiertas', name: 'opened' },
{ fieldLabel: 'Cerradas', name: 'closed' },
{ fieldLabel: 'Total', name: 'quotes' }
]
},pieChart]
}]
}],
dockedItems: [{
xtype: 'toolbar',
cls: 'absolute-form-toolbar',
items: [{
text: 'Exportar Excel',
iconCls: 'icon-excel',
handler: function() {
alert('Exportando...');
}
},{
text: 'Exportar PDF',
iconCls: 'icon-pdf',
handler: function() {
alert('Exportando...');
}
},exportButton]
}]
});

SMMJ_Dev
25 Sep 2011, 7:19 AM
I looked at the button code, and it is still messed up.
For now if you need this you can do what I'm currently doing.

Replace your button code with a standard Ext.button.Button


Ext.create('Ext.button.Button',{
text:'Download as .xls',
handler:function(button){
var gridPanel=button.up('gridpanel');
var dataURL='data:application/vnd.ms-excel;base64,'+Ext.ux.exporter.Exporter.exportGrid(gridPanel);
window.location.href=dataURL;
}
})

SMMJ_Dev
25 Sep 2011, 7:45 AM
OK, I think I fixed it. Try out this as your Exporter-all.js. I finally put a test scenario together for you and fixed the button.



/**
*
* Base64 encode / decode
* http://www.webtoolkit.info/
*
**/


(function() {


// private property
var keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";


// private method for UTF-8 encoding
function utf8Encode(string) {
string = string.replace(/\r\n/g,"\n");
var utftext = "";
for (var n = 0; n < string.length; n++) {
var c = string.charCodeAt(n);
if (c < 128) {
utftext += String.fromCharCode(c);
}
else if((c > 127) && (c < 2048)) {
utftext += String.fromCharCode((c >> 6) | 192);
utftext += String.fromCharCode((c & 63) | 128);
}
else {
utftext += String.fromCharCode((c >> 12) | 224);
utftext += String.fromCharCode(((c >> 6) & 63) | 128);
utftext += String.fromCharCode((c & 63) | 128);
}
}
return utftext;
}


Ext.define("Ext.ux.exporter.Base64", {
statics: {
//This was the original line, which tries to use Firefox's built in Base64 encoder, but this kept throwing exceptions....
// encode : (typeof btoa == 'function') ? function(input) { return btoa(input); } : function (input) {
encode : function (input) {
var output = "";
var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
var i = 0;
input = utf8Encode(input);
while (i < input.length) {
chr1 = input.charCodeAt(i++);
chr2 = input.charCodeAt(i++);
chr3 = input.charCodeAt(i++);
enc1 = chr1 >> 2;
enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
enc4 = chr3 & 63;
if (isNaN(chr2)) {
enc3 = enc4 = 64;
} else if (isNaN(chr3)) {
enc4 = 64;
}
output = output +
keyStr.charAt(enc1) + keyStr.charAt(enc2) +
keyStr.charAt(enc3) + keyStr.charAt(enc4);
}
return output;
}}
});
})();


/**
* @class Ext.ux.Exporter
* @author Ed Spencer (http://edspencer.net), with modifications from iwiznia.
* Class providing a common way of downloading data in .xls or .csv format
*/
Ext.define("Ext.ux.exporter.Exporter", {
uses: [
"Ext.ux.exporter.Base64",
"Ext.ux.exporter.Button",
"Ext.ux.exporter.csvFormatter.CsvFormatter",
"Ext.ux.exporter.excelFormatter.ExcelFormatter"
],


statics: {
exportAny: function(component, formatter, config) {
var func = "export";
if(!component.is) {
func = func + "Store";
} else if(component.is("gridpanel")) {
func = func + "Grid";
} else if (component.is("treepanel")) {
func = func + "Tree";
} else {
func = func + "Store";
component = component.getStore();
}
return this[func](component, formatter, config);
},


/**
* Exports a grid, using the .xls formatter by default
* @param {Ext.grid.GridPanel} grid The grid to export from
* @param {Object} config Optional config settings for the formatter
*/
exportGrid: function(grid, formatter, config) {
config = config || {};
formatter = formatter || new Ext.ux.exporter.excelFormatter.ExcelFormatter();
var columns = Ext.Array.filter(grid.columns, function(col) {
if(col.xtype){
return !col.hidden && col.xtype != "actioncolumn";
}
return !col.hidden;
});


Ext.applyIf(config, {
title : grid.title,
columns: columns
});


return Ext.ux.exporter.Base64.encode(formatter.format(grid.store, config));
},


exportStore: function(store, formatter, config) {
config = config || {};
formatter = formatter || new Ext.ux.exporter.excelFormatter.ExcelFormatter();


Ext.applyIf(config, {
columns: store.fields ? store.fields.items : store.model.prototype.fields.items
});


return Ext.ux.exporter.Base64.encode(formatter.format(store, config));
},


exportTree: function(tree, formatter, config) {
config = config || {};
formatter = formatter || new Ext.ux.exporter.excelFormatter.ExcelFormatter();


var store = tree.store || config.store;


Ext.applyIf(config, {
title: tree.title
});


return Ext.ux.exporter.Base64.encode(formatter.format(store, config));
}
}
});


/**
* @class Ext.ux.Exporter.Button
* @extends Ext.Button
* @author Nige White, with modifications from Ed Spencer, with modifications from iwiznia.
* Specialised Button class that allows downloading of data via data: urls.
* Internally, this is just a link.
* Pass it either an Ext.Component subclass with a 'store' property, or just a store or nothing and it will try to grab the first parent of this button that is a grid or tree panel:
* new Ext.ux.Exporter.Button({component: someGrid});
* new Ext.ux.Exporter.Button({store: someStore});
* @cfg {Ext.Component} component The component the store is bound to
* @cfg {Ext.data.Store} store The store to export (alternatively, pass a component with a getStore method)
*/
Ext.define("Ext.ux.exporter.Button", {
extend: "Ext.Button",
alias: "widget.exporterbutton",
initComponent: function(config) {
var me=this;
config = config || {};


Ext.applyIf(config, {
disabled : true,
text : 'Download',
cls : 'download',
href : "/"
});
me.callParent(arguments);


if (me.store || me.component) {
me.setComponent(me.store || me.component, config);
} else {
var self = me;
me.on("render", function() { // We wait for the combo to be rendered, so we can look up to grab the component containing it
self.setComponent(self.up("gridpanel") || self.up("treepanel"), config);
});
}
},


setComponent: function(component, config) {
var me=this;
me.component = component;
me.store = !component.is ? component : component.getStore(); // only components or stores, if it doesn't respond to is method, it's a store
var setLink = function() {
var newConf=Ext.clone(config);
me.handler=function(){
window.location.href='data:application/vnd.ms-excel;base64,' + Ext.ux.exporter.Base64.encode(Ext.ux.exporter.Exporter.exportAny(me.component, null, newConf));
}
me.enable();
};


me.store.on("load", setLink, me);
if(me.component.isXType){
if(me.component.isXType("gridpanel")) {
Ext.Array.each(me.component.columns, function(col) {
col.on("show", setLink, me);
col.on("hide", setLink, me);
});
}
}
},


onClick : function(e){
var me=this;
if (e.button != 0) return;


if (!me.disabled){
me.fireEvent("click", me, e);


if (me.handler) me.handler.call(me.scope || me, me, e);
}
}
});


/**
* @class Ext.ux.Exporter.Formatter
* @author Ed Spencer (http://edspencer.net)
* @cfg {Ext.data.Store} store The store to export
*/
Ext.define("Ext.ux.exporter.Formatter", {
/**
* Performs the actual formatting. This must be overridden by a subclass
*/
format: Ext.emptyFn,
constructor: function(config) {
config = config || {};


Ext.applyIf(config, {


});
}
});


/**
* @class Ext.ux.Exporter.ExcelFormatter
* @extends Ext.ux.Exporter.Formatter
* Specialised Format class for outputting .xls files
*/
Ext.define("Ext.ux.exporter.excelFormatter.ExcelFormatter", {
extend: "Ext.ux.exporter.Formatter",
uses: [
"Ext.ux.exporter.excelFormatter.Cell",
"Ext.ux.exporter.excelFormatter.Style",
"Ext.ux.exporter.excelFormatter.Worksheet",
"Ext.ux.exporter.excelFormatter.Workbook"
],


format: function(store, config) {
var workbook = new Ext.ux.exporter.excelFormatter.Workbook(config);
workbook.addWorksheet(store, config || {});


return workbook.render();
}
});


/**
* @class Ext.ux.Exporter.ExcelFormatter.Workbook
* @extends Object
* Represents an Excel workbook
*/
Ext.define("Ext.ux.exporter.excelFormatter.Workbook", {


constructor: function(config) {
config = config || {};


Ext.apply(this, config, {
/**
* @property title
* @type String
* The title of the workbook (defaults to "Workbook")
*/
title: "Workbook",


/**
* @property worksheets
* @type Array
* The array of worksheets inside this workbook
*/
worksheets: [],


/**
* @property compileWorksheets
* @type Array
* Array of all rendered Worksheets
*/
compiledWorksheets: [],


/**
* @property cellBorderColor
* @type String
* The colour of border to use for each Cell
*/
cellBorderColor: "#e4e4e4",


/**
* @property styles
* @type Array
* The array of Ext.ux.Exporter.ExcelFormatter.Style objects attached to this workbook
*/
styles: [],


/**
* @property compiledStyles
* @type Array
* Array of all rendered Ext.ux.Exporter.ExcelFormatter.Style objects for this workbook
*/
compiledStyles: [],


/**
* @property hasDefaultStyle
* @type Boolean
* True to add the default styling options to all cells (defaults to true)
*/
hasDefaultStyle: true,


/**
* @property hasStripeStyles
* @type Boolean
* True to add the striping styles (defaults to true)
*/
hasStripeStyles: true,


windowHeight : 9000,
windowWidth : 50000,
protectStructure: false,
protectWindows : false
});


if (this.hasDefaultStyle) this.addDefaultStyle();
if (this.hasStripeStyles) this.addStripedStyles();


this.addTitleStyle();
this.addHeaderStyle();
},


render: function() {
this.compileStyles();
this.joinedCompiledStyles = this.compiledStyles.join("");


this.compileWorksheets();
this.joinedWorksheets = this.compiledWorksheets.join("");


return this.tpl.apply(this);
},


/**
* Adds a worksheet to this workbook based on a store and optional config
* @param {Ext.data.Store} store The store to initialize the worksheet with
* @param {Object} config Optional config object
* @return {Ext.ux.Exporter.ExcelFormatter.Worksheet} The worksheet
*/
addWorksheet: function(store, config) {
var worksheet = new Ext.ux.exporter.excelFormatter.Worksheet(store, config);


this.worksheets.push(worksheet);


return worksheet;
},


/**
* Adds a new Ext.ux.Exporter.ExcelFormatter.Style to this Workbook
* @param {Object} config The style config, passed to the Style constructor (required)
*/
addStyle: function(config) {
var style = new Ext.ux.exporter.excelFormatter.Style(config || {});


this.styles.push(style);


return style;
},


/**
* Compiles each Style attached to this Workbook by rendering it
* @return {Array} The compiled styles array
*/
compileStyles: function() {
this.compiledStyles = [];


Ext.each(this.styles, function(style) {
this.compiledStyles.push(style.render());
}, this);


return this.compiledStyles;
},


/**
* Compiles each Worksheet attached to this Workbook by rendering it
* @return {Array} The compiled worksheets array
*/
compileWorksheets: function() {
this.compiledWorksheets = [];


Ext.each(this.worksheets, function(worksheet) {
this.compiledWorksheets.push(worksheet.render());
}, this);


return this.compiledWorksheets;
},


tpl: new Ext.XTemplate(
'<?xml version="1.0" encoding="utf-8"?>',
'<ss:Workbook xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet" xmlns:x="urn:schemas-microsoft-com:office:excel" xmlns:o="urn:schemas-microsoft-com:office:office">',
'<o:DocumentProperties>',
'<o:Title>{title}</o:Title>',
'</o:DocumentProperties>',
'<ss:ExcelWorkbook>',
'<ss:WindowHeight>{windowHeight}</ss:WindowHeight>',
'<ss:WindowWidth>{windowWidth}</ss:WindowWidth>',
'<ss:ProtectStructure>{protectStructure}</ss:ProtectStructure>',
'<ss:ProtectWindows>{protectWindows}</ss:ProtectWindows>',
'</ss:ExcelWorkbook>',
'<ss:Styles>',
'{joinedCompiledStyles}',
'</ss:Styles>',
'{joinedWorksheets}',
'</ss:Workbook>'
),


/**
* Adds the default Style to this workbook. This sets the default font face and size, as well as cell borders
*/
addDefaultStyle: function() {
var borderProperties = [
{name: "Color", value: this.cellBorderColor},
{name: "Weight", value: "1"},
{name: "LineStyle", value: "Continuous"}
];


this.addStyle({
id: 'Default',
attributes: [
{
name: "Alignment",
properties: [
{name: "Vertical", value: "Top"},
{name: "WrapText", value: "1"}
]
},
{
name: "Font",
properties: [
{name: "FontName", value: "arial"},
{name: "Size", value: "10"}
]
},
{name: "Interior"}, {name: "NumberFormat"}, {name: "Protection"},
{
name: "Borders",
children: [
{
name: "Border",
properties: [{name: "Position", value: "Top"}].concat(borderProperties)
},
{
name: "Border",
properties: [{name: "Position", value: "Bottom"}].concat(borderProperties)
},
{
name: "Border",
properties: [{name: "Position", value: "Left"}].concat(borderProperties)
},
{
name: "Border",
properties: [{name: "Position", value: "Right"}].concat(borderProperties)
}
]
}
]
});
},


addTitleStyle: function() {
this.addStyle({
id: "title",
attributes: [
{name: "Borders"},
{name: "Font"},
{
name: "NumberFormat",
properties: [
{name: "Format", value: "@"}
]
},
{
name: "Alignment",
properties: [
{name: "WrapText", value: "1"},
{name: "Horizontal", value: "Center"},
{name: "Vertical", value: "Center"}
]
}
]
});
},


addHeaderStyle: function() {
this.addStyle({
id: "headercell",
attributes: [
{
name: "Font",
properties: [
{name: "Bold", value: "1"},
{name: "Size", value: "10"}
]
},
{
name: "Interior",
properties: [
{name: "Pattern", value: "Solid"},
{name: "Color", value: "#A3C9F1"}
]
},
{
name: "Alignment",
properties: [
{name: "WrapText", value: "1"},
{name: "Horizontal", value: "Center"}
]
}
]
});
},


/**
* Adds the default striping styles to this workbook
*/
addStripedStyles: function() {
this.addStyle({
id: "even",
attributes: [
{
name: "Interior",
properties: [
{name: "Pattern", value: "Solid"},
{name: "Color", value: "#CCFFFF"}
]
}
]
});


this.addStyle({
id: "odd",
attributes: [
{
name: "Interior",
properties: [
{name: "Pattern", value: "Solid"},
{name: "Color", value: "#CCCCFF"}
]
}
]
});


Ext.each(['even', 'odd'], function(parentStyle) {
this.addChildNumberFormatStyle(parentStyle, parentStyle + 'date', "[ENG][$-409]dd\-mmm\-yyyy;@");
this.addChildNumberFormatStyle(parentStyle, parentStyle + 'int', "0");
this.addChildNumberFormatStyle(parentStyle, parentStyle + 'float', "0.00");
}, this);
},


/**
* Private convenience function to easily add a NumberFormat style for a given parentStyle
* @param {String} parentStyle The ID of the parentStyle Style
* @param {String} id The ID of the new style
* @param {String} value The value of the NumberFormat's Format property
*/
addChildNumberFormatStyle: function(parentStyle, id, value) {
this.addStyle({
id: id,
parentStyle: "even",
attributes: [
{
name: "NumberFormat",
properties: [{name: "Format", value: value}]
}
]
});
}
});


/**
* @class Ext.ux.Exporter.ExcelFormatter.Worksheet
* @extends Object
* Represents an Excel worksheet
* @cfg {Ext.data.Store} store The store to use (required)
*/
Ext.define("Ext.ux.exporter.excelFormatter.Worksheet", {


constructor: function(store, config) {
config = config || {};


this.store = store;


Ext.applyIf(config, {
hasTitle : true,
hasHeadings: true,
stripeRows : true,


title : "Workbook",
columns : store.fields == undefined ? {} : store.fields.items
});


Ext.apply(this, config);


Ext.ux.exporter.excelFormatter.Worksheet.superclass.constructor.apply(this, arguments);
},


/**
* @property dateFormatString
* @type String
* String used to format dates (defaults to "Y-m-d"). All other data types are left unmolested
*/
dateFormatString: "Y-m-d",


worksheetTpl: new Ext.XTemplate(
'<ss:Worksheet ss:Name="{title}">',
'<ss:Names>',
'<ss:NamedRange ss:Name="Print_Titles" ss:RefersTo="=\'{title}\'!R1:R2" />',
'</ss:Names>',
'<ss:Table x:FullRows="1" x:FullColumns="1" ss:ExpandedColumnCount="{colCount}" ss:ExpandedRowCount="{rowCount}">',
'{columns}',
'<ss:Row ss:Height="38">',
'<ss:Cell ss:StyleID="title" ss:MergeAcross="{colCount - 1}">',
'<ss:Data xmlns:html="http://www.w3.org/TR/REC-html40" ss:Type="String">',
'<html:B><html:U><html:Font html:Size="15">{title}',
'</html:Font></html:U></html:B></ss:Data><ss:NamedCell ss:Name="Print_Titles" />',
'</ss:Cell>',
'</ss:Row>',
'<ss:Row ss:AutoFitHeight="1">',
'{header}',
'</ss:Row>',
'{rows}',
'</ss:Table>',
'<x:WorksheetOptions>',
'<x:PageSetup>',
'<x:Layout x:CenterHorizontal="1" x:Orientation="Landscape" />',
'<x:Footer x:Data="Page &amp;P of &amp;N" x:Margin="0.5" />',
'<x:PageMargins x:Top="0.5" x:Right="0.5" x:Left="0.5" x:Bottom="0.8" />',
'</x:PageSetup>',
'<x:FitToPage />',
'<x:Print>',
'<x:PrintErrors>Blank</x:PrintErrors>',
'<x:FitWidth>1</x:FitWidth>',
'<x:FitHeight>32767</x:FitHeight>',
'<x:ValidPrinterInfo />',
'<x:VerticalResolution>600</x:VerticalResolution>',
'</x:Print>',
'<x:Selected />',
'<x:DoNotDisplayGridlines />',
'<x:ProtectObjects>False</x:ProtectObjects>',
'<x:ProtectScenarios>False</x:ProtectScenarios>',
'</x:WorksheetOptions>',
'</ss:Worksheet>'
),


/**
* Builds the Worksheet XML
* @param {Ext.data.Store} store The store to build from
*/
render: function(store) {
return this.worksheetTpl.apply({
header : this.buildHeader(),
columns : this.buildColumns().join(""),
rows : this.buildRows().join(""),
colCount: this.columns.length,
rowCount: this.store.getCount() + 2,
title : this.title
});
},


buildColumns: function() {
var cols = [];


Ext.each(this.columns, function(column) {
cols.push(this.buildColumn());
}, this);


return cols;
},


buildColumn: function(width) {
return Ext.String.format('<ss:Column ss:AutoFitWidth="1" ss:Width="{0}" />', width || 164);
},


buildRows: function() {
var rows = [];


this.store.each(function(record, index) {
rows.push(this.buildRow(record, index));
}, this);


return rows;
},


buildHeader: function() {
var cells = [];


Ext.each(this.columns, function(col) {
var title;


//if(col.dataIndex) {
if (col.text != undefined) {
title = col.text;
} else if(col.name) {
//make columns taken from Record fields (e.g. with a col.name) human-readable
title = col.name.replace(/_/g, " ");
title = title.charAt(0).toUpperCase() + title.substr(1).toLowerCase();
}


cells.push(Ext.String.format('<ss:Cell ss:StyleID="headercell"><ss:Data ss:Type="String">{0}</ss:Data><ss:NamedCell ss:Name="Print_Titles" /></ss:Cell>', title));
//}
}, this);


return cells.join("");
},


buildRow: function(record, index) {
var style,
cells = [];
if (this.stripeRows === true) style = index % 2 == 0 ? 'even' : 'odd';


Ext.each(this.columns, function(col) {
var name = col.name || col.dataIndex;


if(name) {
//if given a renderer via a ColumnModel, use it and ensure data type is set to String
if (Ext.isFunction(col.renderer)) {
var value = col.renderer(record.get(name), null, record),
type = "String";
} else {
var value = record.get(name),
type = this.typeMappings[col.type || record.fields.get(name).type.type];
}


cells.push(this.buildCell(value, type, style).render());
}
}, this);


return Ext.String.format("<ss:Row>{0}</ss:Row>", cells.join(""));
},


buildCell: function(value, type, style) {
if (type == "DateTime" && Ext.isFunction(value.format)) value = value.format(this.dateFormatString);


return new Ext.ux.exporter.excelFormatter.Cell({
value: value,
type : type,
style: style
});
},


/**
* @property typeMappings
* @type Object
* Mappings from Ext.data.Record types to Excel types
*/
typeMappings: {
'int' : "Number",
'string': "String",
'float' : "Number",
'date' : "DateTime"
}
});


/**
* @class Ext.ux.Exporter.ExcelFormatter.Cell
* @extends Object
* Represents a single cell in a worksheet
*/


Ext.define("Ext.ux.exporter.excelFormatter.Cell", {
constructor: function(config) {
Ext.applyIf(config, {
type: "String"
});


Ext.apply(this, config);


Ext.ux.exporter.excelFormatter.Cell.superclass.constructor.apply(this, arguments);
},


render: function() {
return this.tpl.apply(this);
},


tpl: new Ext.XTemplate(
'<ss:Cell ss:StyleID="{style}">',
'<ss:Data ss:Type="{type}"><![CDATA[{value}]]></ss:Data>',
'</ss:Cell>'
)
});


/**
* @class Ext.ux.Exporter.ExcelFormatter.Style
* @extends Object
* Represents a style declaration for a Workbook (this is like defining CSS rules). Example:
*
* new Ext.ux.Exporter.ExcelFormatter.Style({
* attributes: [
* {
* name: "Alignment",
* properties: [
* {name: "Vertical", value: "Top"},
* {name: "WrapText", value: "1"}
* ]
* },
* {
* name: "Borders",
* children: [
* name: "Border",
* properties: [
* {name: "Color", value: "#e4e4e4"},
* {name: "Weight", value: "1"}
* ]
* ]
* }
* ]
* })
*
* @cfg {String} id The ID of this style (required)
* @cfg {Array} attributes The attributes for this style
* @cfg {String} parentStyle The (optional parentStyle ID)
*/
Ext.define("Ext.ux.exporter.excelFormatter.Style", {
constructor: function(config) {
config = config || {};


Ext.apply(this, config, {
parentStyle: '',
attributes : []
});


Ext.ux.exporter.excelFormatter.Style.superclass.constructor.apply(this, arguments);


if (this.id == undefined) throw new Error("An ID must be provided to Style");


this.preparePropertyStrings();
},


/**
* Iterates over the attributes in this style, and any children they may have, creating property
* strings on each suitable for use in the XTemplate
*/
preparePropertyStrings: function() {
Ext.each(this.attributes, function(attr, index) {
this.attributes[index].propertiesString = this.buildPropertyString(attr);
this.attributes[index].children = attr.children || [];


Ext.each(attr.children, function(child, childIndex) {
this.attributes[index].children[childIndex].propertiesString = this.buildPropertyString(child);
}, this);
}, this);
},


/**
* Builds a concatenated property string for a given attribute, suitable for use in the XTemplate
*/
buildPropertyString: function(attribute) {
var propertiesString = "";


Ext.each(attribute.properties || [], function(property) {
propertiesString += Ext.String.format('ss:{0}="{1}" ', property.name, property.value);
}, this);


return propertiesString;
},


render: function() {
return this.tpl.apply(this);
},


tpl: new Ext.XTemplate(
'<tpl if="parentStyle.length == 0">',
'<ss:Style ss:ID="{id}">',
'</tpl>',
'<tpl if="parentStyle.length != 0">',
'<ss:Style ss:ID="{id}" ss:Parent="{parentStyle}">',
'</tpl>',
'<tpl for="attributes">',
'<tpl if="children.length == 0">',
'<ss:{name} {propertiesString} />',
'</tpl>',
'<tpl if="children.length > 0">',
'<ss:{name} {propertiesString}>',
'<tpl for="children">',
'<ss:{name} {propertiesString} />',
'</tpl>',
'</ss:{name}>',
'</tpl>',
'</tpl>',
'</ss:Style>'
)
});

RAD001
28 Sep 2011, 12:56 PM
Hi All,



did anyone able to get this working??
I am getting this error on FF and IE8


'Downloadify' is undefined


any idea ???

wiznia
29 Sep 2011, 2:09 AM
Ouch, I've been updating this yesterday and didn't have time to comment it in the documentation. I changed the downloading mechanism from data-uris to a flash based solution.
The reason for that was:
1) Some browsers didn't support data uris.
2) There was a limit (I don't know exactly the number) on the size of the data uris that made the browsers crash when set.
So, now it's based on downloadify, which is flash. So you need to include downloadify.min.js (supplied) and configure on the button, the paths to the
swf and the image, this are the defaults:


swfPath: '/flash/downloadify.swf',
downloadImage: '/images/ext_reports/download.png',
width: 62,
height: 22, downloadName: "download"



When I have a little time I will update the docs. Oh, and don't use the exporter-all.js since it's not updated I need to write a build script so it generates the minified version.
Let me know if you encounter problems.

RAD001
29 Sep 2011, 7:59 AM
Hi Wiznia,

I did include the downloadify.min.js but then it complained about 'swfobject'
So I downloaded the downloadify and included the swfobject as well

here is my html


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Stateful Array Grid Example</title>
<link rel="stylesheet" type="text/css" href="../../resources/css/ext-all.css" />
<link rel="stylesheet" type="text/css" href="../shared/example.css" />
<script type="text/javascript" src="../../bootstrap.js"></script>
<script type="text/javascript" src="../ux/exporter/swfobject.js"></script>
<script type="text/javascript" src="../ux/exporter/downloadify.min.js"></script>
<!-- page specific -->
<style type="text/css">
/* style rows on mouseover */
.x-grid-row-over .x-grid-cell-inner {
font-weight: bold;
}
/* shared styles for the ActionColumn icons */
.x-action-col-cell img {
height: 16px;
width: 16px;
cursor: pointer;
}
/* custom icon for the "buy" ActionColumn icon */
.x-action-col-cell img.buy-col {
background-image: url(../shared/icons/fam/accept.png);
}
/* custom icon for the "alert" ActionColumn icon */
.x-action-col-cell img.alert-col {
background-image: url(../shared/icons/fam/error.png);
}
.x-ie6 .x-action-col-cell img.buy-col {
background-image: url(../shared/icons/fam/accept.gif);
}
.x-ie6.x-action-col-cell img.alert-col {
background-image: url(../shared/icons/fam/error.gif);
}
.x-ie6 .x-action-col-cell img {
position:relative;
top:-1px;
}
</style>
<script type="text/javascript" src="array-grid.js"></script>
</head>
<body>
<h1>Stateful Array Grid Example</h1>
<p>This example shows how to create a grid from Array data.</p>
<p>The grid is stateful so you can move or hide columns, reload the page, and come
back to the grid in the same state you left it in.</p>
<p>Note that the js is not minified so it is readable. See <a href="array-grid.js">array-grid.js</a>.</p>
<div id="grid-example"></div>
</body>
</html>



here is my js code

/*
This file is part of Ext JS 4
Copyright (c) 2011 Sencha Inc
Contact: http://www.sencha.com/contact
Commercial (http://www.sencha.com/contactCommercial) Usage
Licensees holding valid commercial licenses may use this file in accordance with the Commercial Software License Agreement provided with the Software or, alternatively, in accordance with the terms contained in a written agreement between you and Sencha.
If you are unsure which license is appropriate for your use, please contact the sales department at http://www.sencha.com/contact.
*/ (http://www.sencha.com/contact.*/)
Ext.Loader.setConfig({ enabled: true });
Ext.Loader.setPath('Ext.ux.exporter','../ux/exporter');
Ext.require([
'Ext.grid.*',
'Ext.data.*',
'Ext.util.*',
'Ext.state.*',
'Ext.ux.exporter.Exporter.*',
'Ext.ux.exporter.excelFormatter.*',
'Ext.ux.exporter.csvFormatter.*'
]);
Ext.onReady(function () {
Ext.QuickTips.init();
// setup the state provider, all state information will be saved to a cookie
Ext.state.Manager.setProvider(Ext.create('Ext.state.CookieProvider'));
// sample static data for the store
var myData = [
['3m Co', 71.72, 0.02, 0.03, '9/1 12:00am'],
['Alcoa Inc', 29.01, 0.42, 1.47, '9/1 12:00am'],
['Altria Group Inc', 83.81, 0.28, 0.34, '9/1 12:00am'],
['American Express Company', 52.55, 0.01, 0.02, '9/1 12:00am'],
['American International Group, Inc.', 64.13, 0.31, 0.49, '9/1 12:00am'],
['AT&T Inc.', 31.61, -0.48, -1.54, '9/1 12:00am'],
['Boeing Co.', 75.43, 0.53, 0.71, '9/1 12:00am'],
['Caterpillar Inc.', 67.27, 0.92, 1.39, '9/1 12:00am'],
['Citigroup, Inc.', 49.37, 0.02, 0.04, '9/1 12:00am'],
['E.I. du Pont de Nemours and Company', 40.48, 0.51, 1.28, '9/1 12:00am'],
['Exxon Mobil Corp', 68.1, -0.43, -0.64, '9/1 12:00am'],
['General Electric Company', 34.14, -0.08, -0.23, '9/1 12:00am'],
['General Motors Corporation', 30.27, 1.09, 3.74, '9/1 12:00am'],
['Hewlett-Packard Co.', 36.53, -0.03, -0.08, '9/1 12:00am'],
['Honeywell Intl Inc', 38.77, 0.05, 0.13, '9/1 12:00am'],
['Intel Corporation', 19.88, 0.31, 1.58, '9/1 12:00am'],
['International Business Machines', 81.41, 0.44, 0.54, '9/1 12:00am'],
['Johnson & Johnson', 64.72, 0.06, 0.09, '9/1 12:00am'],
['JP Morgan & Chase & Co', 45.73, 0.07, 0.15, '9/1 12:00am'],
['McDonald\'s Corporation', 36.76, 0.86, 2.40, '9/1 12:00am'],
['Merck & Co., Inc.', 40.96, 0.41, 1.01, '9/1 12:00am'],
['Microsoft Corporation', 25.84, 0.14, 0.54, '9/1 12:00am'],
['Pfizer Inc', 27.96, 0.4, 1.45, '9/1 12:00am'],
['The Coca-Cola Company', 45.07, 0.26, 0.58, '9/1 12:00am'],
['The Home Depot, Inc.', 34.64, 0.35, 1.02, '9/1 12:00am'],
['The Procter & Gamble Company', 61.91, 0.01, 0.02, '9/1 12:00am'],
['United Technologies Corporation', 63.26, 0.55, 0.88, '9/1 12:00am'],
['Verizon Communications', 35.57, 0.39, 1.11, '9/1 12:00am'],
['Wal-Mart Stores, Inc.', 45.45, 0.73, 1.63, '9/1 12:00am']
];
/**
* Custom function used for column renderer
* @param {Object} val
*/
function change(val) {
if (val > 0) {
return '<span style="color:green;">' + val + '</span>';
} else if (val < 0) {
return '<span style="color:red;">' + val + '</span>';
}
return val;
}
/**
* Custom function used for column renderer
* @param {Object} val
*/
function pctChange(val) {
if (val > 0) {
return '<span style="color:green;">' + val + '%</span>';
} else if (val < 0) {
return '<span style="color:red;">' + val + '%</span>';
}
return val;
}
// create the data store
var store = Ext.create('Ext.data.ArrayStore', {
fields: [
{ name: 'company' },
{ name: 'price', type: 'float' },
{ name: 'change', type: 'float' },
{ name: 'pctChange', type: 'float' },
{ name: 'lastChange', type: 'date', dateFormat: 'n/j h:ia' }
],
data: myData
});
var exportButton = Ext.create('Ext.ux.exporter.Button', {
component: Ext.getCmp('grid'),
icon: '../ux/exporter/download.png',
text: "export Excel"
});

// create the Grid
var grid = Ext.create('Ext.grid.Panel', {
store: store,
stateful: true,
stateId: 'stateGrid',
columns: [
{
text: 'Company',
flex: 1,
sortable: false,
dataIndex: 'company'
},
{
text: 'Price',
width: 75,
sortable: true,
renderer: 'usMoney',
dataIndex: 'price'
},
{
text: 'Change',
width: 75,
sortable: true,
renderer: change,
dataIndex: 'change'
},
{
text: '% Change',
width: 75,
sortable: true,
renderer: pctChange,
dataIndex: 'pctChange'
},
{
text: 'Last Updated',
width: 85,
sortable: true,
renderer: Ext.util.Format.dateRenderer('m/d/Y'),
dataIndex: 'lastChange'
},
{
xtype: 'actioncolumn',
width: 50,
items: [{
icon: '../shared/icons/fam/delete.gif', // Use a URL in the icon config
tooltip: 'Sell stock',
handler: function (grid, rowIndex, colIndex) {
var rec = store.getAt(rowIndex);
alert("Sell " + rec.get('company'));
}
}, {
getClass: function (v, meta, rec) { // Or return a class from a function
if (rec.get('change') < 0) {
this.items[1].tooltip = 'Hold stock';
return 'alert-col';
} else {
this.items[1].tooltip = 'Buy stock';
return 'buy-col';
}
},
handler: function (grid, rowIndex, colIndex) {
var rec = store.getAt(rowIndex);
alert((rec.get('change') < 0 ? "Hold " : "Buy ") + rec.get('company'));
}
}]
}
],
dockedItems: [{
xtype: 'toolbar',
//cls: 'absolute-form-toolbar',
items: [{ xtype: 'exporterbutton'}]
}]
,
height: 350,
width: 600,
title: 'Array Grid',
renderTo: 'grid-example',
viewConfig: {
stripeRows: true
}
});
});



since you have the download.png and downloadify.swf in the same dir
I change the button config

config: {
swfPath: 'downloadify.swf',
downloadImage: 'download.png',
width: 62,
height: 22,
downloadName: "download"
},


now I am not getting any error on both ie8 and ff but I don't see the button on the toolbar...
am I missing something here????

wiznia
29 Sep 2011, 5:08 PM
i'll try to put an example to clarify things, for now, here's what you need to do:
- include swfobject2 (not incñuded)
- include downloadify.min.hs
- create an exporterButton with the appropriate configuration pointing to the image and the swf.
- require with ext loader the Ext.ux.Exporter class.
- don't you use the exporter-all file since it's outdated.

don't forget to download the new code aince I updated it yesterday.
I promise to put an example project and update the documentation, just give me some time.

RAD001
30 Sep 2011, 7:30 AM
Hi Wiznia,

thanks for the info but still it's not working for me.


I am getting this.el is undefined


Downloadify.create(this.el.down('p').id,{
filename: function() {
return self.getDownloadName() + "." + Ext.ux.exporter.Exporter.getFormatterByName(self.formatter).extension;
},
data: function() {
return Ext.ux.exporter.Exporter.exportAny(self.component, self.formatter, config);
},
transparent: false,
swf: this.getSwfPath(),
downloadImage: this.getDownloadImage(),
width: this.getWidth(),
height: this.getHeight(),
transparent: true,
append: false
});




here is my html


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Stateful Array Grid Example</title>
<link rel="stylesheet" type="text/css" href="../../resources/css/ext-all.css" />
<link rel="stylesheet" type="text/css" href="../shared/example.css" />
<script type="text/javascript" src="../../bootstrap.js"></script>
<script type="text/javascript" src="../ux/exporter/swfobject.js"></script>

<script type="text/javascript" src="../ux/exporter/downloadify.min.js"></script>
<script type="text/javascript" src="../ux/exporter/Button.js"></script>
<!-- page specific -->
<style type="text/css">
/* style rows on mouseover */
.x-grid-row-over .x-grid-cell-inner {
font-weight: bold;
}
/* shared styles for the ActionColumn icons */
.x-action-col-cell img {
height: 16px;
width: 16px;
cursor: pointer;
}
/* custom icon for the "buy" ActionColumn icon */
.x-action-col-cell img.buy-col {
background-image: url(../shared/icons/fam/accept.png);
}
/* custom icon for the "alert" ActionColumn icon */
.x-action-col-cell img.alert-col {
background-image: url(../shared/icons/fam/error.png);
}
.x-ie6 .x-action-col-cell img.buy-col {
background-image: url(../shared/icons/fam/accept.gif);
}
.x-ie6.x-action-col-cell img.alert-col {
background-image: url(../shared/icons/fam/error.gif);
}
.x-ie6 .x-action-col-cell img {
position:relative;
top:-1px;
}
</style>
<script type="text/javascript" src="array-grid.js"></script>
</head>
<body>
<h1>Stateful Array Grid Example</h1>
<p>This example shows how to create a grid from Array data.</p>
<p>The grid is stateful so you can move or hide columns, reload the page, and come
back to the grid in the same state you left it in.</p>
<p>Note that the js is not minified so it is readable. See <a href="array-grid.js">array-grid.js</a>.</p>
<div id="grid-example"></div>
</body>
</html>



here is my js code

/*
This file is part of Ext JS 4
Copyright (c) 2011 Sencha Inc
Contact: http://www.sencha.com/contact
Commercial (http://www.sencha.com/contactCommercial) Usage
Licensees holding valid commercial licenses may use this file in accordance with the Commercial Software License Agreement provided with the Software or, alternatively, in accordance with the terms contained in a written agreement between you and Sencha.
If you are unsure which license is appropriate for your use, please contact the sales department at http://www.sencha.com/contact.
*/ (http://www.sencha.com/contact.*/)
Ext.Loader.setConfig({ enabled: true });
Ext.Loader.setPath('Ext.ux.exporter','../ux/exporter');
Ext.require([
'Ext.grid.*',
'Ext.data.*',
'Ext.util.*',
'Ext.form.*',
'Ext.state.*',
'Ext.ux.exporter.Exporter.*',
'Ext.ux.exporter.excelFormatter.*',
'Ext.ux.exporter.csvFormatter.*',
'Ext.ux.exporter.Button.*'
]);
Ext.onReady(function () {
Ext.QuickTips.init();
// setup the state provider, all state information will be saved to a cookie
Ext.state.Manager.setProvider(Ext.create('Ext.state.CookieProvider'));
// sample static data for the store
var myData = [
['3m Co', 71.72, 0.02, 0.03, '9/1 12:00am'],
['Alcoa Inc', 29.01, 0.42, 1.47, '9/1 12:00am'],
['Altria Group Inc', 83.81, 0.28, 0.34, '9/1 12:00am'],
['American Express Company', 52.55, 0.01, 0.02, '9/1 12:00am'],
['American International Group, Inc.', 64.13, 0.31, 0.49, '9/1 12:00am'],
['AT&T Inc.', 31.61, -0.48, -1.54, '9/1 12:00am'],
['Boeing Co.', 75.43, 0.53, 0.71, '9/1 12:00am'],
['Caterpillar Inc.', 67.27, 0.92, 1.39, '9/1 12:00am'],
['Citigroup, Inc.', 49.37, 0.02, 0.04, '9/1 12:00am'],
['E.I. du Pont de Nemours and Company', 40.48, 0.51, 1.28, '9/1 12:00am'],
['Exxon Mobil Corp', 68.1, -0.43, -0.64, '9/1 12:00am'],
['General Electric Company', 34.14, -0.08, -0.23, '9/1 12:00am'],
['General Motors Corporation', 30.27, 1.09, 3.74, '9/1 12:00am'],
['Hewlett-Packard Co.', 36.53, -0.03, -0.08, '9/1 12:00am'],
['Honeywell Intl Inc', 38.77, 0.05, 0.13, '9/1 12:00am'],
['Intel Corporation', 19.88, 0.31, 1.58, '9/1 12:00am'],
['International Business Machines', 81.41, 0.44, 0.54, '9/1 12:00am'],
['Johnson & Johnson', 64.72, 0.06, 0.09, '9/1 12:00am'],
['JP Morgan & Chase & Co', 45.73, 0.07, 0.15, '9/1 12:00am'],
['McDonald\'s Corporation', 36.76, 0.86, 2.40, '9/1 12:00am'],
['Merck & Co., Inc.', 40.96, 0.41, 1.01, '9/1 12:00am'],
['Microsoft Corporation', 25.84, 0.14, 0.54, '9/1 12:00am'],
['Pfizer Inc', 27.96, 0.4, 1.45, '9/1 12:00am'],
['The Coca-Cola Company', 45.07, 0.26, 0.58, '9/1 12:00am'],
['The Home Depot, Inc.', 34.64, 0.35, 1.02, '9/1 12:00am'],
['The Procter & Gamble Company', 61.91, 0.01, 0.02, '9/1 12:00am'],
['United Technologies Corporation', 63.26, 0.55, 0.88, '9/1 12:00am'],
['Verizon Communications', 35.57, 0.39, 1.11, '9/1 12:00am'],
['Wal-Mart Stores, Inc.', 45.45, 0.73, 1.63, '9/1 12:00am']
];
/**
* Custom function used for column renderer
* @param {Object} val
*/
function change(val) {
if (val > 0) {
return '<span style="color:green;">' + val + '</span>';
} else if (val < 0) {
return '<span style="color:red;">' + val + '</span>';
}
return val;
}
/**
* Custom function used for column renderer
* @param {Object} val
*/
function pctChange(val) {
if (val > 0) {
return '<span style="color:green;">' + val + '%</span>';
} else if (val < 0) {
return '<span style="color:red;">' + val + '%</span>';
}
return val;
}
// create the data store
var store = Ext.create('Ext.data.ArrayStore', {
fields: [
{ name: 'company' },
{ name: 'price', type: 'float' },
{ name: 'change', type: 'float' },
{ name: 'pctChange', type: 'float' },
{ name: 'lastChange', type: 'date', dateFormat: 'n/j h:ia' }
],
data: myData
});
// var exportButton = Ext.create('Ext.ux.exporter.Button', {
// component: Ext.getCmp('grid'),
// icon: '../ux/exporter/download.png',
// text: "export Excel"
// });

// create the Grid
var gridPanel = Ext.create('Ext.grid.Panel', {
store: store,
stateful: true,
stateId: 'stateGrid',
columns: [
{
text: 'Company',
flex: 1,
sortable: false,
dataIndex: 'company'
},
{
text: 'Price',
width: 75,
sortable: true,
renderer: 'usMoney',
dataIndex: 'price'
},
{
text: 'Change',
width: 75,
sortable: true,
renderer: change,
dataIndex: 'change'
},
{
text: '% Change',
width: 75,
sortable: true,
renderer: pctChange,
dataIndex: 'pctChange'
},
{
text: 'Last Updated',
width: 85,
sortable: true,
renderer: Ext.util.Format.dateRenderer('m/d/Y'),
dataIndex: 'lastChange'
},
{
xtype: 'actioncolumn',
width: 50,
items: [{
icon: '../shared/icons/fam/delete.gif', // Use a URL in the icon config
tooltip: 'Sell stock',
handler: function (grid, rowIndex, colIndex) {
var rec = store.getAt(rowIndex);
alert("Sell " + rec.get('company'));
}
}, {
getClass: function (v, meta, rec) { // Or return a class from a function
if (rec.get('change') < 0) {
this.items[1].tooltip = 'Hold stock';
return 'alert-col';
} else {
this.items[1].tooltip = 'Buy stock';
return 'buy-col';
}
},
handler: function (grid, rowIndex, colIndex) {
var rec = store.getAt(rowIndex);
alert((rec.get('change') < 0 ? "Hold " : "Buy ") + rec.get('company'));
}
}]
}
],
// dockedItems: [{
// xtype: 'toolbar',
// cls: 'absolute-form-toolbar',
// items: [exportButton]
// }]
//,
height: 350,
width: 600,
title: 'Array Grid',

viewConfig: {
stripeRows: true
}
});
var exportButton = new Ext.ux.exporter.Button({
component: gridPanel,
text: "Download as .xls"
});
var gridForm = Ext.create('Ext.form.Panel', {
id: 'gridForm',
title: 'Cotizaciones',
frame: true,
renderTo: 'grid-example',
bodyPadding: 5,
width: 870,
height: 720,
fieldDefaults: { labelAlign: 'left', msgTarget: 'side' },
layout: { type: 'vbox', align: 'stretch' },
items: [ {
layout: { type: 'hbox', align: 'stretch' },
flex: 3,
border: false,
bodyStyle: 'background-color: transparent',
items: [gridPanel]
}],
dockedItems: [{
xtype: 'toolbar',
cls: 'absolute-form-toolbar',
items: [exportButton]
}]
});
});



I have attached the exporter code also.

I really need to get this working soon.

thanks

wiznia
30 Sep 2011, 8:10 AM
Download the latest code, it should be fixed now.

RAD001
30 Sep 2011, 12:59 PM
Hi Wiznia,

I downloaded the updated code and I used swfobject2

still no luck
now I am not getting any error msg and I don't see a button on the toolbar... but if I highlighted i see it something there...but it's not clickable...

can you please look into it.

thanks,

html code

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Stateful Array Grid Example</title>
<link rel="stylesheet" type="text/css" href="../../resources/css/ext-all.css" />
<link rel="stylesheet" type="text/css" href="../shared/example.css" />
<script type="text/javascript" src="../../bootstrap.js"></script>
<script type="text/javascript" src="../ux/exporter/swfobject.js"></script>

<script type="text/javascript" src="../ux/exporter/downloadify.min.js"></script>
<script type="text/javascript" src="../ux/exporter/Button.js"></script>
<!-- page specific -->
<style type="text/css">
/* style rows on mouseover */
.x-grid-row-over .x-grid-cell-inner {
font-weight: bold;
}
/* shared styles for the ActionColumn icons */
.x-action-col-cell img {
height: 16px;
width: 16px;
cursor: pointer;
}
/* custom icon for the "buy" ActionColumn icon */
.x-action-col-cell img.buy-col {
background-image: url(../shared/icons/fam/accept.png);
}
/* custom icon for the "alert" ActionColumn icon */
.x-action-col-cell img.alert-col {
background-image: url(../shared/icons/fam/error.png);
}
.x-ie6 .x-action-col-cell img.buy-col {
background-image: url(../shared/icons/fam/accept.gif);
}
.x-ie6.x-action-col-cell img.alert-col {
background-image: url(../shared/icons/fam/error.gif);
}
.x-ie6 .x-action-col-cell img {
position:relative;
top:-1px;
}
</style>
<script type="text/javascript" src="array-grid.js"></script>
</head>
<body>
<h1>Stateful Array Grid Example</h1>
<p>This example shows how to create a grid from Array data.</p>
<p>The grid is stateful so you can move or hide columns, reload the page, and come
back to the grid in the same state you left it in.</p>
<p>Note that the js is not minified so it is readable. See <a href="array-grid.js">array-grid.js</a>.</p>
<div id="grid-example"></div>
</body>
</html>

js code

/*
This file is part of Ext JS 4
Copyright (c) 2011 Sencha Inc
Contact: http://www.sencha.com/contact
Commercial (http://www.sencha.com/contactCommercial) Usage
Licensees holding valid commercial licenses may use this file in accordance with the Commercial Software License Agreement provided with the Software or, alternatively, in accordance with the terms contained in a written agreement between you and Sencha.
If you are unsure which license is appropriate for your use, please contact the sales department at http://www.sencha.com/contact.
*/ (http://www.sencha.com/contact.*/)
Ext.Loader.setConfig({ enabled: true });
Ext.Loader.setPath('Ext.ux.exporter','../ux/exporter');
Ext.require([
'Ext.grid.*',
'Ext.data.*',
'Ext.util.*',
'Ext.form.*',
'Ext.state.*',
'Ext.ux.exporter.Exporter.*',
'Ext.ux.exporter.excelFormatter.*',
'Ext.ux.exporter.csvFormatter.*',
'Ext.ux.exporter.Button.*'
]);
Ext.onReady(function () {
Ext.QuickTips.init();
// setup the state provider, all state information will be saved to a cookie
Ext.state.Manager.setProvider(Ext.create('Ext.state.CookieProvider'));
// sample static data for the store
var myData = [
['3m Co', 71.72, 0.02, 0.03, '9/1 12:00am'],
['Alcoa Inc', 29.01, 0.42, 1.47, '9/1 12:00am'],
['Altria Group Inc', 83.81, 0.28, 0.34, '9/1 12:00am'],
['American Express Company', 52.55, 0.01, 0.02, '9/1 12:00am'],
['American International Group, Inc.', 64.13, 0.31, 0.49, '9/1 12:00am'],
['AT&T Inc.', 31.61, -0.48, -1.54, '9/1 12:00am'],
['Boeing Co.', 75.43, 0.53, 0.71, '9/1 12:00am'],
['Caterpillar Inc.', 67.27, 0.92, 1.39, '9/1 12:00am'],
['Citigroup, Inc.', 49.37, 0.02, 0.04, '9/1 12:00am'],
['E.I. du Pont de Nemours and Company', 40.48, 0.51, 1.28, '9/1 12:00am'],
['Exxon Mobil Corp', 68.1, -0.43, -0.64, '9/1 12:00am'],
['General Electric Company', 34.14, -0.08, -0.23, '9/1 12:00am'],
['General Motors Corporation', 30.27, 1.09, 3.74, '9/1 12:00am'],
['Hewlett-Packard Co.', 36.53, -0.03, -0.08, '9/1 12:00am'],
['Honeywell Intl Inc', 38.77, 0.05, 0.13, '9/1 12:00am'],
['Intel Corporation', 19.88, 0.31, 1.58, '9/1 12:00am'],
['International Business Machines', 81.41, 0.44, 0.54, '9/1 12:00am'],
['Johnson & Johnson', 64.72, 0.06, 0.09, '9/1 12:00am'],
['JP Morgan & Chase & Co', 45.73, 0.07, 0.15, '9/1 12:00am'],
['McDonald\'s Corporation', 36.76, 0.86, 2.40, '9/1 12:00am'],
['Merck & Co., Inc.', 40.96, 0.41, 1.01, '9/1 12:00am'],
['Microsoft Corporation', 25.84, 0.14, 0.54, '9/1 12:00am'],
['Pfizer Inc', 27.96, 0.4, 1.45, '9/1 12:00am'],
['The Coca-Cola Company', 45.07, 0.26, 0.58, '9/1 12:00am'],
['The Home Depot, Inc.', 34.64, 0.35, 1.02, '9/1 12:00am'],
['The Procter & Gamble Company', 61.91, 0.01, 0.02, '9/1 12:00am'],
['United Technologies Corporation', 63.26, 0.55, 0.88, '9/1 12:00am'],
['Verizon Communications', 35.57, 0.39, 1.11, '9/1 12:00am'],
['Wal-Mart Stores, Inc.', 45.45, 0.73, 1.63, '9/1 12:00am']
];
/**
* Custom function used for column renderer
* @param {Object} val
*/
function change(val) {
if (val > 0) {
return '<span style="color:green;">' + val + '</span>';
} else if (val < 0) {
return '<span style="color:red;">' + val + '</span>';
}
return val;
}
/**
* Custom function used for column renderer
* @param {Object} val
*/
function pctChange(val) {
if (val > 0) {
return '<span style="color:green;">' + val + '%</span>';
} else if (val < 0) {
return '<span style="color:red;">' + val + '%</span>';
}
return val;
}
// create the data store
var store = Ext.create('Ext.data.ArrayStore', {
fields: [
{ name: 'company' },
{ name: 'price', type: 'float' },
{ name: 'change', type: 'float' },
{ name: 'pctChange', type: 'float' },
{ name: 'lastChange', type: 'date', dateFormat: 'n/j h:ia' }
],
data: myData
});
// var exportButton = Ext.create('Ext.ux.exporter.Button', {
// component: Ext.getCmp('grid'),
// icon: '../ux/exporter/download.png',
// text: "export Excel"
// });

// create the Grid
var gridPanel = Ext.create('Ext.grid.Panel', {
store: store,
stateful: true,
stateId: 'stateGrid',
columns: [
{
text: 'Company',
flex: 1,
sortable: false,
dataIndex: 'company'
},
{
text: 'Price',
width: 75,
sortable: true,
renderer: 'usMoney',
dataIndex: 'price'
},
{
text: 'Change',
width: 75,
sortable: true,
renderer: change,
dataIndex: 'change'
},
{
text: '% Change',
width: 75,
sortable: true,
renderer: pctChange,
dataIndex: 'pctChange'
},
{
text: 'Last Updated',
width: 85,
sortable: true,
renderer: Ext.util.Format.dateRenderer('m/d/Y'),
dataIndex: 'lastChange'
},
{
xtype: 'actioncolumn',
width: 50,
items: [{
icon: '../shared/icons/fam/delete.gif', // Use a URL in the icon config
tooltip: 'Sell stock',
handler: function (grid, rowIndex, colIndex) {
var rec = store.getAt(rowIndex);
alert("Sell " + rec.get('company'));
}
}, {
getClass: function (v, meta, rec) { // Or return a class from a function
if (rec.get('change') < 0) {
this.items[1].tooltip = 'Hold stock';
return 'alert-col';
} else {
this.items[1].tooltip = 'Buy stock';
return 'buy-col';
}
},
handler: function (grid, rowIndex, colIndex) {
var rec = store.getAt(rowIndex);
alert((rec.get('change') < 0 ? "Hold " : "Buy ") + rec.get('company'));
}
}]
}
],
dockedItems: [{
xtype: 'toolbar',
cls: 'absolute-form-toolbar',
items: [{
text: 'Exportar PDF',
iconCls: 'icon-pdf',
handler: function () {
alert('Exportando...');
}
},
{ xtype: 'exporterbutton'}]
}],
// dockedItems: [{
// xtype: 'toolbar',
// cls: 'absolute-form-toolbar',
// items: [exportButton]
// }]
//,
height: 350,
width: 600,
title: 'Array Grid',
viewConfig: {
stripeRows: true
}
});
// var exportButton = new Ext.ux.exporter.Button({
// component: gridPanel,
// text: "Download as .xls"
// });
var gridForm = Ext.create('Ext.form.Panel', {
id: 'gridForm',
title: 'Cotizaciones',
frame: true,
renderTo: 'grid-example',
bodyPadding: 5,
width: 870,
height: 720,
fieldDefaults: { labelAlign: 'left', msgTarget: 'side' },
layout: { type: 'vbox', align: 'stretch' },
items: [{
layout: { type: 'hbox', align: 'stretch' },
flex: 3,
border: false,
bodyStyle: 'background-color: transparent',
items: [gridPanel]
}]
});
});

wiznia
30 Sep 2011, 6:43 PM
rad001, you have to point the exporter button to the correct image and the downloadIfy swf fIle. look at the exporter button code for the appropriate names of the confIg and remember that paths are relative to your page, not the js file.

RAD001
3 Oct 2011, 6:50 AM
Hi wiznia,

thanx for the tip, now I got the button to show up and it's clickable. BUT now when I click on it nothing happens.

Please help me out.

Am I missing something?? is it working for you?

wiznia
3 Oct 2011, 7:30 AM
Is there a message in the console? Like a js error or something?
Try debugging it, put breakpoints in the Button.js.
Put one in the setDownloadify function, one inside the filename function config that is passed to Downloadify.create, and one in the data function config.
Let me know what results you get....

RAD001
3 Oct 2011, 7:46 AM
Hi Wiznia,

I am not getting any error msg on console, when I debug the button js
Filename and data is getting set as null after Downloadify.create in button.js

inside the filename function config that is passed to downloadify.create the Ext.ux.expoerter.Exporter is undefined, same in data function config.

wiznia
3 Oct 2011, 9:41 AM
I don't quite understand what you say.
I get that the Downloadify.create is getting called.
Then you need to set a breakpoint INSIDE the data function and see if the value that function is returning is correct. This code should be called when you click the download button.
As for the Ext.ux.expoerter.Exporter being undefined, it doesn't make sense, unless you typed it exactly as posted, which has a typo "expoerter".

RAD001
3 Oct 2011, 10:12 AM
Hi Wiznia,

sorry for the unclear post and typo.

Yes the Downloadify.create getting called when I click on the button and I set a break point inside the data function and filename function.
In both functions the 'Ext.ux.exporter.Exporter' is undefined therefor null is getting set for filename and data.

RAD001
3 Oct 2011, 10:21 AM
Hi Wiznia,

I finally got it working..



Ext.Loader.setPath('Ext.ux.exporter','../ux/exporter');
Ext.require([
'Ext.grid.*',
'Ext.data.*',
'Ext.util.*',
'Ext.form.*',
'Ext.state.*',
'Ext.ux.exporter.Exporter.*',
'Ext.ux.exporter.excelFormatter.*',
'Ext.ux.exporter.csvFormatter.*',
'Ext.ux.exporter.Button.*'
]);



even though I have the exporter.Exporter as part of the require I still had to include it in the html header


<scripttype="text/javascript"src="../ux/exporter/Exporter.js"></script>

and now it's working...

thanks alot for the help.

wiznia
4 Oct 2011, 1:58 AM
Strange... if it was undefined, then both functions should have thrown an error.
As for the manual require, it shouldn't be necessary, do you have a call to?:
Ext.Loader.setConfig({enabled: true});

Anyway, I'm glad you got it working.

jjerome
6 Oct 2011, 2:05 PM
Wiznia,

All the work you have done on this is great. It is appreciated by all. I have been reading through this thread and trying to ger this working with one of our grids. I have all the JS's loading, I have the swfObject.js loaded, I can see the image in the toolbar. When I click on the image in the toolbar I never go into the "filename" function in button.js. The Downloadify.create runs but I never go into the filename function. Also, it "does" go into the "data" function but Ext.ux.exporter.Exporter.exportAny(self.component, self.formatter, config) returns a "TypeError".

self.formater is undefined but self.component is my grid and config appears to be looking at the column set up. We are using multiline heading for the grid so I am not sure if that will cause a problem or not.

Should I be going into the filename function before the data function? I never hit filename. Any ideas?

Thanks,
Jason Jerome

wiznia
7 Oct 2011, 4:18 AM
Can you post the line number (and trace if possible) of the error?
Also, the config of the button and grid would be usefull.
You can also try to configure the button with the option "formatter" (it accepts "csv" or "excel" as values). This shouldn't be necessary as the excel formatter is the default, so if you can post me the error in more detail I can see if there's an error in the plugin.

supermarcos
10 Oct 2011, 7:28 AM
Hi, everybody!

I have the extjs 4.0.2 framework and I'm trying export a grid to an excel file, but I can't.
Allways I read the "Uncaught TypeError: Cannot set property 'Exporter' of undefined" error and the "Uncaught TypeError: Cannot call method 'substring' of undefined", too... I supuse I have a bad path for the Exporter-all.js file, but I'm not sure now...
Where I should to put this file?
What's the path tham I must include in my index.html header (<script... src=xxxxxx>)?
I must to put a require call in my view?
The sample that is included in the zip file that you can dowload references extjs 3, not extjs 4... then, this plug-in is suported in extjs 4 version??

A lot of thanks.

wiznia
10 Oct 2011, 8:54 AM
The exporter-all and examples are outdated, I will update them and the documentation when I have some spare time...
- You should use the Ext.Loader to load the Ext.ux.exporter.Exporter (Exporter.js file), then the loader will load all the other necessary files.
- Include the exporterbutton for in a toolbar of the gridpanel.
That should be all...

parkcity
10 Oct 2011, 10:13 PM
Does this work in Chrome browser?

supermarcos
10 Oct 2011, 10:33 PM
Hi, wiznia

I have added this line in my app.js:

Ext.Loader.setPath('Ext.ux.exporter','extjs/src/Exporter');

And, in my Ext.grid.Panel, the dockedItems collection, I have added the next one inside a toolbar:
,{
xtype : 'exportbutton',
action : 'exportXLS',
text : 'Export to XLS',
store : myStore
}

But the do not load and throw me an exception like this:
Uncaught TypeError: Cannot call method 'substring' of undefined
In ext-debug.js file, in line 5981...

What happen?
Thank you so much.

wiznia
11 Oct 2011, 2:02 AM
Try posting a backtrace or something... I can't know where it's failing only with the line of the ext-all.js
If you remove the exporterbutton it works?

supermarcos
11 Oct 2011, 2:26 AM
Hi, wiznia

Yes, If I remove the exportbutton from the grid the error does not appear...
Exists any other way to call any export method without an exportbutton or any way to create an exportbutton not directly in the grid?

What do you need when you said "backtrace"? (sorry if the question is a quite stupid question...)

Thanks a lot!

wiznia
11 Oct 2011, 2:49 AM
You need the button, because it's using a flash library to make the download possible from the browser without using data uris. (I think I didn't mention that to you... sorry I forgot since I just added it). So you need to include the swfobject2 library (not included). And configure the button with:
{
xtype: "exporterbutton",
swfPath: '/flash/downloadify.swf', // this file is included
downloadImage: '/images/ext_reports/download.png', // this one too
width: 62, // mantain the width and height
height: 22,
downloadName: "download" // this is the name of the file
formatter: "excel" // Or "csv"
}

Backtrace is the full trace of the exception, in the firebug console you can open the error and see the trace...

supermarcos
11 Oct 2011, 3:04 AM
Hi, again, wiznia
:-)

Thank you so much for your help...
Well, I don't know nothing about swfobject2... where I can find it to download it?

I'm trying another way to put a button... Now I trying to put a standard ext button in my toolbar and then capture the click event, like this:
alerta: function() {
var gridPanel= Ext.ComponentQuery.query('actividadeslist')[0]; //button.up('gridpanel');
var dataURL='data:application/vnd.ms-excel; base64,'+Ext.ux.exporter.Exporter.exportGrid(gridPanel);
window.location.href=dataURL;
},


But, when I do click in the button...



Uncaught TypeError: Cannot read property 'Exporter' of undefined
Ext.define.alerta ActividadesController.js:43 (http://localhost:8080/SICAPWebAdministracion/app/controller/ActividadesController.js?_dc=1318330188064)
fire ext-debug.js:16353 (http://localhost:8080/SICAPWebAdministracion/extjs/ext-debug.js)
Ext.define.dispatch EventBus.js:64 (http://localhost:8080/SICAPWebAdministracion/extjs/src/app/EventBus.js?_dc=1318330186722)
Ext.override.fireEvent EventBus.js:39 (http://localhost:8080/SICAPWebAdministracion/extjs/src/app/EventBus.js?_dc=1318330186722)
Ext.define.onClick Button.js:1007 (http://localhost:8080/SICAPWebAdministracion/extjs/src/button/Button.js?_dc=1318330187027)
(anonymous function)
wrap

I use chrome and this is the error trace that it show me, does it help you?

Thanks again...

parkcity
11 Oct 2011, 6:19 AM
I needed to work it in chrome and guess what it works!!.. Thanks a lot wiznia.!!!

I am attaching a complete demo along with extJS 4 lib on google docs. The file name is: exportTest.zip
Here is the link:

https://docs.google.com/leaf?id=0B3HqAmWhfIrBYzczY2EzMTgtZWNkZi00ODQwLTlmMmUtNjFiNmY0Y2UwMjRj&hl=en_GB

One just needs to download the attachment and extract it to the webapps or other directory of the webserver.

Invoke the app using the following url:
http://localhost:8080/exportTest/index.html

( (http://localhost:8080/exportTest/index.html)where localhost is the address and 8080 is the port on which webserver is listening for requests).

The plugin is located in exportTest\extJS402a\examples\ux\exporter

wiznia
11 Oct 2011, 6:47 AM
I'm glad you got it working, but I think you are using an outdated version. I moved away from data-uris and used a flash component for the export because of 3 problems:
- IE doesn't support data uris.
- You cant specify the name of the file and the extension you get is a .part
- There's a limit on the ammount of data you can post in a data-uri, so when big data was exported, the browser plainly crashed.

So I incorporated downloadify (included) which uses the swfobject2 library (http://lmgtfy.com/?q=swfobject2) and is a flash solution.

parkcity
11 Oct 2011, 10:58 AM
I have updated the package to exportTest2.zip . This package works well. It uses extJS from CDN.
Deploy it in your server and invoke using the app using the following:


http://host:port/exportTest2/index.html

supermarcos
12 Oct 2011, 10:50 PM
Hi, parkcity

Your work is excellent !!
But I have a little issue... How can I do to save/download the export result like a file?
When I put the "exporterbutton" in my toolbar it appears, but it does not do nothing when I click it (and does not say nothing in the javascript console... no error, at least...), then I put a button with this code:

var gridPanel= Ext.ComponentQuery.query('actividadeslist')[0]; //button.up('gridpanel');
var dataURL='data:application/vnd.ms-excel;base64,'+Ext.ux.exporter.Exporter.exportGrid(gridPanel);
window.location.href=dataURL;

But, when it redirect to the new url instead download, the browser (chrome, in my case) try to load it into and show a very awfull string...

Can you help me, please?

Thanks!

parkcity
13 Oct 2011, 7:01 AM
supermarcos > Have you defined the header field for your Grid Columns. If not the export button will not work. Also If any of your column is of type date, then you need to have a renderer.

An example of grid column with header and date renderer field is:

columns: [
{
header: 'Anchor Time',
text: 'Anchor Time',
width: 100,
dataIndex: 'ANCHOR_DTIME',
renderer: Ext.util.Format.dateRenderer('Y-m-d H:i:s')

}
]

supermarcos
14 Oct 2011, 1:00 AM
Hi, parkcity!

Thank you for your help. Ok, yes, I have defined the columns in the grid, the problem was the config 'store'... I have defined it in the exporterbutton definition and it is not necesary... without it all works well, but, I have a little problem:
I need to make my own style in the button, so, I need to use a standard button and then call (when the user does click) the print method... but I don't know how can I do that...
What is the method in the exporter.js that I must call in the click event of the my button??
Can you help me, please?
I try to call the printAny / printStore / printGrid method of the exporter.js file, but it does not work (but does not throw any exception...).
I use this code (I supousse that only that must not be enough):

{
xtype : 'button',
text : 'Exportar XLS',
action : 'exportarExcel',
iconCls : 'icon-tb-imprimir',
handler : function(){
debugger;
click : Ext.ux.exporter.Exporter.exportAny(myGrid, 'excel',{
swfPath: 'app/lib/components/gridexporter/ux/exporter/downloadify.swf',
downloadImage: 'app/lib/components/gridexporter/ux/exporter/download.png',
width: 62,
height: 22,
downloadName: "miDownload"
});
}
}

Can you help me, please?
Thank you so much!

jjerome
17 Oct 2011, 1:26 PM
Adding the formatter: 'csv' definitely got me further but... I am running into 2 other problems now:

1) We are using multiline column headings and csvformater.js "format:" config.columns is only picking up 3 of our 7 columns. store.model.prototype.fields.items does reference all 7 of the columns. Our columns are like this:
Facility ....Admission .....Discharges
...........Daily MTD YTD ..Daily MTD YTD
abc fac .....5 ...10 100 ....4 ...8 ..95
(ignore the ... I just put them to aide in spacing)
As you can see there are actually 7 columns but Config.columns is only picking up the "Facility, Admissions, Discharges".

I changed the code to use store.model.prototype.fields.items to get the column cound but now I am not getting the headings I want. I am getting the fields name instead.

2) csvformater.js "geCell:" attempts to call the column renderer. Our renderer function blows up because we are expecting more parameters then your col.renderer(record.get(name), null, record). I added some additional parms to your call to pass which column we are working with.

Note: csv formatter should have the separator set to "," in my opinion instead of ";"

mmuzamil
18 Oct 2011, 8:14 AM
Wiznia,

First of all great work, I really liked your work. It has made export from Grid to excel very easy. But I have few questions regarding this plug-in. I'll appreciate if you can respond to them.

1. I have a grid with paging toolbar, and I want to export data of all pages to Excel/CSV. Can I do that using this plug-in?

2. Is it possible to export data of a column in a different format as compared to what is used on UI e.g in a column, I am displaying product code with a hyperlink but In my exported file the hyperlink may not make sense. So can i export data of that column in plain text?

3. I used this plug-in on a grid which had first column of type 'actioncolumn', which had icons for edit and delete. When I exported data from this grid in Excel format, it generated the column headers appropriately in the excel file but instead of leaving first column blank (or copying HTML for delete/edit icons), it copied text of 2nd column in this. Actually all data of my grid got shifted on the left i.e. data of 3rd column was copied to 2nd, 4th to 3rd and so on. Is it a know issue or am I doing something wrong?

Thanks in advance

jjerome
18 Oct 2011, 8:18 AM
To resolve my first problem above I changed the exportGrid function in exporter.js. If a column has a groupheader I now pick up the multiple headings (and combine them) and also pick up the sub column data. I had to remove the array filter code you were using and to it a bit more manually. (note: since both CSV and EXCEL type use this function it fixes it for both.

exportGrid: function(grid, formatter, config) {
config = config || {};
//var columns = Ext.Array.filter(grid.columns, function(col) {
var columns = new Array();
var colcnt = -1;
var colidx = -1;
for (var i = 0; i< grid.columns.length; i++) {
if(grid.columns[i].isGroupHeader) {
if (!(grid.columns[i].hidden)) {
Ext.each(grid.columns[i].items.items, function(col2) {
colcnt++;
colidx++;
columns[colcnt] = col2;
var chkpos = col2.text.trim().indexOf(grid.columns[i].text.trim());
if (chkpos === -1) {
columns[colcnt].text = grid.columns[i].text + ' ' + col2.text;
}
columns[colcnt].colIndex = colidx;
//alert('sub col text: ' + columns[colcnt].text);
});
} else {
colidx++;
}
} else {
if (!(grid.columns[i].hidden)) {
colcnt++;
colidx++;
columns[colcnt] = grid.columns[i];
columns[colcnt].colIndex = colidx;
//alert('main col text: ' + columns[colcnt].text);
} else {
colidx++;

ssuarez
22 Nov 2011, 2:21 PM
Any idea what is causing this? I, admittedly, am a complete novice...

This is the error in firebug:

Downloadify is not defined
Downloadify.create(this.el.down('p').id,{

jjerome
22 Nov 2011, 2:33 PM
Do you have downloadify.min.js and downloadify.swf somewhere where the app can find them.

ssuarez
22 Nov 2011, 2:47 PM
I have them in the same directory as the Base64, Exporter.js, Button.js, etc files....

Do I need to do anything to reference where that is? I have this in the top of my js file:

Ext.Loader.setConfig({enabled: true});
Ext.Loader.setPath('Ext.ux.exporter', './UX');

wiznia
23 Nov 2011, 3:02 AM
When you create the exporter button, you should pass the configurations:
swfPath and downloadImage. The first is the complete path to the downloadify.swf file, the second to the download.png provided.

ssuarez
28 Nov 2011, 10:48 AM
Winzia,

Thank you very much for the reply, but I am still getting the same error....(Downloadify is not defined)

This is what I changed based on how I interpreted your response...Did I misunderstand?

,{
xtype: 'exporterbutton',
store: DetailedStore,
text: 'Excel',
swfPath: './UX/downloadify.swf',
downloadImage: './UX/download.png'
}

wiznia
29 Nov 2011, 2:37 AM
Sorry, I forgot, you also have to include the downloadify.min.js (https://github.com/iwiznia/Ext.ux.Exporter/blob/master/downloadify.min.js) in your page

ssuarez
29 Nov 2011, 7:48 AM
Thank you so much Winzia! I've got it working now!

I needed to add the swfobject.js as well.

wiznia
29 Nov 2011, 8:58 AM
Yes. I need to update the help and add a working example....

edykstra
11 Dec 2011, 11:33 AM
Hello Wiznia,

Some questions:

1. Why is exporter-all.js included if it is outdated and we are not to use it?
2. How to I force CSV export?
3. The store has pagination applied. Is it possible for export to over-ride the limit value so that pagination is ignored and the entire data set is downloaded?
4. What is 'downloadify'?
5. Where is the latest code? GitHub? Is it current?
6. I am using Chrome, and I get a download prompt, but the data will not open in Open Office as an Excel file. It seems to think it is a CSV with a single cell.

Thanks

wiznia
12 Dec 2011, 3:59 AM
1. exporter-all.js is not included, if you have it, you have an old version.
2. Configure the button with the 'formatter: "csv"'.
3. Right now, the exporter only exports what's loaded in the store. You could load the store with all the rows to export everything...
4. https://github.com/dcneiner/Downloadify It's a flash library that allows the generation and downloading of a file on the browser. It's better than a data-uri.
5. https://github.com/iwiznia/Ext.ux.Exporter
6. That's odd. I'm using libreOffice and it opens correctly... open the file with a text editor to see if it has all your data.

edykstra
12 Dec 2011, 4:57 AM
I'm not sure where I went wrong, but the Readme file clearly states to use exporter-all.js. It also references the ExtJS3 version of Exporter, and references a non existent example file.

Please update the Readme, so that others are not first confused like I was.

Thanks.

wiznia
12 Dec 2011, 7:35 AM
Like I said several times in this post, the readme is not updated and the examples are missing. I don't have the time right now to update it. You are welcome to create an example and readme in a fork and send me a pull request so I include it in the project.

edykstra
12 Dec 2011, 7:51 AM
I think that the main confusion is a result of the current state being defined in so many places, including this post.

I see the most recent update at GitHub states; "Removed example and exporter-all since they were outdated." For the exact same logic, you should remove the Readme too. Relying on someone to find this post in addition to the GitHub project is unreasonable.

Although I would like to provide an example, clearly I can't get it working so I can't provide an example.

Does anyone else subscribed to this post have an example?

Wiznia, I appreciate the effort to provide this user extension, and that you don't have time right now. But, neither do the people who want to use the extension. For others, at the very least, please add a line in the Readme that states it is out of date.

Thanks

wiznia
12 Dec 2011, 8:05 AM
ok, updated.

amishra06
13 Dec 2011, 10:21 AM
Hi Wiznia,


I needed the csv/excel download feature and implemented as mentioned in the post. But I get error as mentioned below:


Uncaught TypeError: Cannot call method 'substring' of undefined.


When I expand this error (I am using chrome developer tool) I see several lines of messages basically function call mostly pointing to
7th line of ext-all.js except one line which points to my app js file where I have defined the grid.


Is it because I am using grouped column headers its not able to get the store columns correctly ?


Ashish

wiznia
13 Dec 2011, 3:25 PM
It could be the grouped column headers, I never tried this plugin in such a grid. Does it work on a regular grid?

shawon
20 Dec 2011, 1:54 AM
ssuarez i m facing the problem as yours. I wonder where can i find that "swfobject.js" file???

balajivaikar
20 Dec 2011, 11:56 AM
shawon, swfobject.js is bundled with downloadify zip file, also you can manually download it from
here http://code.google.com/p/swfobject/downloads/detail?name=swfobject_2_2.zip
(http://code.google.com/p/swfobject/downloads/detail?name=swfobject_2_2.zip)

sebas2515
21 Dec 2011, 1:16 PM
i don't know where is gonna placed the exporter.js
file in my mvc architecture proyect's

30221

HIG
22 Dec 2011, 1:53 AM
1、need server-side(flash player bug)
2、check your file path

sebas2515
22 Dec 2011, 8:45 AM
thanks. it worked nice

sebas2515
23 Dec 2011, 7:14 AM
Hi HIG,

can you help me to learn to customize the template of the excel report that generete exporter pluggin?

balajivaikar
23 Dec 2011, 6:52 PM
I'm having a datagrid with multi level of headers, and these header-text and row data for these headers are not getting exported to excel. Could anyone help me out ?

isaac
29 Dec 2011, 3:52 PM
I have tried both the example downloads as well as tried to use this in my grid. The sw is working great. But MS Office for Mac 2011 cannot open the xls file (which I rename to xlsx, since xls is binary format) It complains about the format of the file being incorrect. OpenOffice on my linux box will open the downloaded file. But open office and office 2011 on my mac will not. Also, google docs will produce an error when trying to import the xlsx. I think the resulting xlsx file being generated is invalid. But I'm not sure how to proceed.

wiznia
30 Dec 2011, 2:55 AM
Yeah, there are problems with different versions and programs, that's why I ended up using the csv exporter, which is included.
For multi-header grids, I never tried it and it's probably not working right now, pull requests are wellcome in the github project.

Vasanthoo7
19 Jan 2012, 10:38 AM
HI Wiznia, this is a great post. I got everything through with the set up and when I tried to download the file as excel, it downloads it.

When I open the excel file I get the following error.

The file you are trying to open 'download.xls' is in a different format than specified by the extension, Verify that the file is not corrupted. I am using EXTJS4. Can you please help me out with this.

wiznia
19 Jan 2012, 11:21 AM
As I said, there seems to be problems with different versions and programs to open the xls.Try it first with the csv exporter to see if the data gets exported correctly

Vasanthoo7
19 Jan 2012, 12:20 PM
Hi Wiznia, Thanks for the quick reply. the CSV export works well except a few issues:

The first column in the header is taking this character: &#160;

Also the date columns are showing as ####### as the value for start and end date.

===

If you could also point me in the right direction for uploading excel or csv file onto a grid using EXTJS 4. that would be great.

wiznia
20 Jan 2012, 3:01 AM
What is the config for the first column? It should be using the column text or name properties. As for the dates, is the xtype of the column "datecolumn"? Do you have a format specified?
I don't know if it's possible to upload an excel or csv to a grid. You should probably receive the file server side and then serve it to the grid.

Vasanthoo7
24 Jan 2012, 12:45 PM
HI Wiznia, Thank you for replying. I was able to do it successfully with CSV, now the excel, really need to get it working as a excel, It is downloading a excel file, when i open the excel with notepad i see the Grid data in the notepad.

When i open as Excel, it gives me the following error:


The file you are trying to open is in a difffernt format than specified by the extension. Verify that the file is from a trusted source before opening the file. Do you want to open the file now.

When i click on yes, I still am nt able to open the file.

wiznia
25 Jan 2012, 2:26 AM
mmm, you can try the fixes that are in this pull request:
https://github.com/iwiznia/Ext.ux.Exporter/pull/3
If it works I can merge it with the main branch.

acteon
26 Jan 2012, 6:53 AM
I think exporter should not require Button since exporter works without it .

wiznia
27 Jan 2012, 2:55 AM
It can produce the data without a button, but without it you can't download it, and it's not that easy to serve a file through the browser directly. That's why I use downloadify.js

acteon
27 Jan 2012, 9:04 AM
In our case creating a button(xtype : button) with an empty href config attribute then changing its content on the fly with office xml might help ? namely data URL's but there will some compability issues (http://stackoverflow.com/questions/1765342/which-browsers-support-data-uris-and-since-which-version)


Thanks for the code It saved a lot of effort for me .

wiznia
27 Jan 2012, 9:22 AM
That was my previous approach, using data uri's, but it had 3 problems:
- No support for some browsers (IE).
- There's a limit for the data uri length. If trying to save a lot of data, some browsers crashed.
- I was setting the data uri everytime the store loads, this probably could be avoided by adding a click event to the link, and setting the data uri there, and then allowing the event to continue regularly.

Mainly because of the first 2 things I decided to add a button, and downloadify to avoid them.

pavanextjs
6 Feb 2012, 8:25 AM
Hi Wiznia,

I was trying to add your fixes from github (https://github.com/iwiznia/Ext.ux.Exporter/pull/3), but no luck. I am not able to open the exported excel file in my code, but CSV works fine. Also, the excel file exported from the example given in the exporter download works fine from my local iis server.

I can give you the code snippets & json data if you want to take a look. Please let me know, this is an important functionality in my app.

Thanks in advance,
Pavan.

wiznia
6 Feb 2012, 10:51 AM
Like I said before the excel support is a little bit tricky with different versions of different programs in different platforms behaving differently.
I ended up using the csv exporter which can be easily imported into any program in any version in any platform...
The excel formatter that is in the master branch right now, sort of worked for me on openoffice on linux, and on office 2000 on mac and windows.

pavanextjs
7 Feb 2012, 8:15 AM
OK, i see what you are saying. Thanks Wiznia for the inputs.

When i debugged into it, i noticed the XML generated by the exporter has these 0"> extra tags, thought this might give you a clue in finding/fixing the issue.

Below is the XML:



<?xml version="1.0" encoding="utf-8" ?>
<ss:Workbook xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet" xmlns:x="urn:schemas-microsoft-com:office:excel"
xmlns:o="urn:schemas-microsoft-com:office:office">
<o:DocumentProperties>
<o:Title>
Workbook
</o:Title>
</o:DocumentProperties>
<x:ExcelWorkbook>
<x:WindowHeight>
9000
</x:WindowHeight>
<x:WindowWidth>
50000
</x:WindowWidth>
<x:ProtectStructure>
false
</x:ProtectStructure>
<x:ProtectWindows>
false
</x:ProtectWindows>
</x:ExcelWorkbook>
<ss:Styles>
<ss:Style ss:ID="Default">
<ss:Alignment ss:Vertical="Top" ss:WrapText="1" />
0">
<ss:Alignment ss:Vertical="Top" ss:WrapText="1">
</ss:Alignment>
<ss:Font ss:FontName="arial" ss:Size="10" />
0">
<ss:Font ss:FontName="arial" ss:Size="10">
</ss:Font>
<ss:Interior />
0">
<ss:Interior>
</ss:Interior>
<ss:NumberFormat />
0">
<ss:NumberFormat>
</ss:NumberFormat>
<ss:Protection />
0">
<ss:Protection>
</ss:Protection>
0">
<ss:Borders>
<ss:Border ss:Position="Top" ss:Color="#e4e4e4" ss:Weight="1" ss:LineStyle="Continuous"
/>
<ss:Border ss:Position="Bottom" ss:Color="#e4e4e4" ss:Weight="1" ss:LineStyle="Continuous"
/>
<ss:Border ss:Position="Left" ss:Color="#e4e4e4" ss:Weight="1" ss:LineStyle="Continuous"
/>
<ss:Border ss:Position="Right" ss:Color="#e4e4e4" ss:Weight="1" ss:LineStyle="Continuous"
/>
</ss:Borders>
</ss:Style>
<ss:Style ss:ID="even">
<ss:Interior ss:Pattern="Solid" ss:Color="#CCFFFF" />
0">
<ss:Interior ss:Pattern="Solid" ss:Color="#CCFFFF">
</ss:Interior>
</ss:Style>
<ss:Style ss:ID="odd">
<ss:Interior ss:Pattern="Solid" ss:Color="#CCCCFF" />
0">
<ss:Interior ss:Pattern="Solid" ss:Color="#CCCCFF">
</ss:Interior>
</ss:Style>
<ss:Style ss:ID="evendate" ss:Parent="even">
<ss:NumberFormat ss:Format="[ENG][$-409]dd-mmm-yyyy;@" />
0">
<ss:NumberFormat ss:Format="[ENG][$-409]dd-mmm-yyyy;@">
</ss:NumberFormat>
</ss:Style>
<ss:Style ss:ID="evenint" ss:Parent="even">
<ss:NumberFormat ss:Format="0" />
0">
<ss:NumberFormat ss:Format="0">
</ss:NumberFormat>
</ss:Style>
<ss:Style ss:ID="evenfloat" ss:Parent="even">
<ss:NumberFormat ss:Format="0.00" />
0">
<ss:NumberFormat ss:Format="0.00">
</ss:NumberFormat>
</ss:Style>
<ss:Style ss:ID="odddate" ss:Parent="even">
<ss:NumberFormat ss:Format="[ENG][$-409]dd-mmm-yyyy;@" />
0">
<ss:NumberFormat ss:Format="[ENG][$-409]dd-mmm-yyyy;@">
</ss:NumberFormat>
</ss:Style>
<ss:Style ss:ID="oddint" ss:Parent="even">
<ss:NumberFormat ss:Format="0" />
0">
<ss:NumberFormat ss:Format="0">
</ss:NumberFormat>
</ss:Style>
<ss:Style ss:ID="oddfloat" ss:Parent="even">
<ss:NumberFormat ss:Format="0.00" />
0">
<ss:NumberFormat ss:Format="0.00">
</ss:NumberFormat>
</ss:Style>
<ss:Style ss:ID="title">
<ss:Borders />
0">
<ss:Borders>
</ss:Borders>
<ss:Font />
0">
<ss:Font>
</ss:Font>
<ss:NumberFormat ss:Format="@" />
0">
<ss:NumberFormat ss:Format="@">
</ss:NumberFormat>
<ss:Alignment ss:WrapText="1" ss:Horizontal="Center" ss:Vertical="Center"
/>
0">
<ss:Alignment ss:WrapText="1" ss:Horizontal="Center" ss:Vertical="Center">
</ss:Alignment>
</ss:Style>
<ss:Style ss:ID="headercell">
<ss:Font ss:Bold="1" ss:Size="10" />
0">
<ss:Font ss:Bold="1" ss:Size="10">
</ss:Font>
<ss:Interior ss:Pattern="Solid" ss:Color="#A3C9F1" />
0">
<ss:Interior ss:Pattern="Solid" ss:Color="#A3C9F1">
</ss:Interior>
<ss:Alignment ss:WrapText="1" ss:Horizontal="Center" />
0">
<ss:Alignment ss:WrapText="1" ss:Horizontal="Center">
</ss:Alignment>
</ss:Style>
</ss:Styles>
<ss:Worksheet ss:Name="Workbook">
<ss:Names>
<ss:NamedRange ss:Name="Print_Titles" ss:RefersTo="='Workbook'!R1:R2"
/>
</ss:Names>
<ss:Table x:FullRows="1" x:FullColumns="1" ss:ExpandedColumnCount="4"
ss:ExpandedRowCount="4">
<ss:Column ss:AutoFitWidth="1" ss:Width="164" />
<ss:Column ss:AutoFitWidth="1" ss:Width="164" />
<ss:Column ss:AutoFitWidth="1" ss:Width="164" />
<ss:Column ss:AutoFitWidth="1" ss:Width="164" />
<ss:Row ss:Height="38">
<ss:Cell ss:StyleID="title" ss:MergeAcross="3">
<ss:Data xmlns:html="http://www.w3.org/TR/REC-html40" ss:Type="String">
<html:B>
<html:U>
<html:Font html:Size="15">
Workbook
</html:Font>
</html:U>
</html:B>
</ss:Data>
<ss:NamedCell ss:Name="Print_Titles" />
</ss:Cell>
</ss:Row>
<ss:Row ss:AutoFitHeight="1">
<ss:Cell ss:StyleID="headercell">
<ss:Data ss:Type="String">
AlertId
</ss:Data>
<ss:NamedCell ss:Name="Print_Titles" />
</ss:Cell>
<ss:Cell ss:StyleID="headercell">
<ss:Data ss:Type="String">
Network
</ss:Data>
<ss:NamedCell ss:Name="Print_Titles" />
</ss:Cell>
<ss:Cell ss:StyleID="headercell">
<ss:Data ss:Type="String">
Message
</ss:Data>
<ss:NamedCell ss:Name="Print_Titles" />
</ss:Cell>
<ss:Cell ss:StyleID="headercell">
<ss:Data ss:Type="String">
Id
</ss:Data>
<ss:NamedCell ss:Name="Print_Titles" />
</ss:Cell>
</ss:Row>
<ss:Row>
<ss:Cell ss:StyleID="even">
<ss:Data ss:Type="String">
123
</ss:Data>
</ss:Cell>
<ss:Cell ss:StyleID="even">
<ss:Data ss:Type="String">
NICK
</ss:Data>
</ss:Cell>
<ss:Cell ss:StyleID="even">
<ss:Data ss:Type="String">
SpongeBob 60% delivery
</ss:Data>
</ss:Cell>
<ss:Cell ss:StyleID="even">
<ss:Data ss:Type="String">
</ss:Data>
</ss:Cell>
</ss:Row>
<ss:Row>
<ss:Cell ss:StyleID="odd">
<ss:Data ss:Type="String">
233
</ss:Data>
</ss:Cell>
<ss:Cell ss:StyleID="odd">
<ss:Data ss:Type="String">
MTV
</ss:Data>
</ss:Cell>
<ss:Cell ss:StyleID="odd">
<ss:Data ss:Type="String">
Sweet Sixteen 67% delivery
</ss:Data>
</ss:Cell>
<ss:Cell ss:StyleID="odd">
<ss:Data ss:Type="String">
</ss:Data>
</ss:Cell>
</ss:Row>
</ss:Table>
<x:WorksheetOptions>
<x:PageSetup>
<x:Layout x:CenterHorizontal="1" x:Orientation="Landscape" />
<x:Footer x:Data="Page &amp;P of &amp;N" x:Margin="0.5" />
<x:PageMargins x:Top="0.5" x:Right="0.5" x:Left="0.5" x:Bottom="0.8" />
</x:PageSetup>
<x:FitToPage />
<x:Print>
<x:PrintErrors>
Blank
</x:PrintErrors>
<x:FitWidth>
1
</x:FitWidth>
<x:FitHeight>
32767
</x:FitHeight>
<x:ValidPrinterInfo />
<x:VerticalResolution>
600
</x:VerticalResolution>
</x:Print>
<x:Selected />
<x:DoNotDisplayGridlines />
<x:ProtectObjects>
False
</x:ProtectObjects>
<x:ProtectScenarios>
False
</x:ProtectScenarios>
</x:WorksheetOptions>
</ss:Worksheet>
</ss:Workbook>


Thanks,
Pavan

wiznia
7 Feb 2012, 8:37 AM
That's odd. If you delete them manually then it opens correctly in excel??
Maybe it has something to do with your data / grid config.... It seems like it's trying to export a column and doesn't know how.

pavanextjs
7 Feb 2012, 9:16 AM
I tried that by manually removing those tags and excel couldn't open it. But the XML is successfully validated after manually removing those extra tags. I used this (http://validator.w3.org/check) for XML validation.

I am trying to export a "store" which has 3 fields in its model (all strings) and 2 rows of data.

Store:


Ext.define('ASDF.AlertsStore', {
extend: 'Ext.data.Store',
requires: 'ASDF.DBAlert',
model: 'ASDF.DBAlert',
proxy: {
type: 'ajax',
url: 'data/Alerts.json',
reader: {
type: 'json',
root: 'data.results'
}
}
});


Model:


Ext.define('ASDF.DBAlert', {
extend: 'Ext.data.Model',
idProperty: 'AlertId',
fields: ['AlertId', 'Network', 'Message']
});


JSON Data:


{
"data": {
"success": true,
"results": [{
"AlertId": 123,
"Network": 'NICK',
"Message": 'SpongeBob 60% delivery'
},
{
"AlertId": 233,
"Network": 'MTV',
"Message": 'Sweet Sixteen 67% delivery'
}]
}
}


Thanks,
Pavan

wiznia
7 Feb 2012, 9:40 AM
Can you paste the grid's code?

pavanextjs
7 Feb 2012, 9:53 AM
Here it is...

ExtJS Ver:4.1.0 Beta
Browsers: FF10, IE9, Chrome16.0.912.77 m



//store
var alertsStore = Ext.data.StoreManager.lookup('​AlertsStore

');


//grid panel inside a border layout's center region
Ext.create('Ext.grid.Panel', {
title: 'Alerts',
itemId: 'alerts-grid',
layout: 'fit',
store: alertsStore,
columns: [{
header: 'Network',
dataIndex: 'Network',
width: 150
},
{
header: 'Message',
dataIndex: 'Message',
flex: 1
}],
tools: [{
type: 'refresh',
tooltip: 'Refresh Alerts',
handler: function (event, toolEl, panel) {
// refresh logic
_me.down('#alerts-grid').getStore().load({
callback: function (alerts) {
_me.down('#alerts-grid').setTitle('Alerts (' + alerts.length + ')');
}
});
}
}],
dockedItems: [{
xtype: 'toolbar',
border: true,
dock: 'top',
items: [{
xtype: 'exporterbutton', //exportbutton
text: 'Export Grid Data',
store: alertsStore
}]
}]
});

wiznia
8 Feb 2012, 2:28 AM
mmmm, I can't find anything worng with the code. I know it had some problems with custom columns, and with the groupheader plugin, but yours is pretty straightforward.... Try debugging it.

pavanextjs
8 Feb 2012, 8:38 AM
OK i will try to debug it.

droessner
23 Feb 2012, 8:43 AM
wiznia,

Thanks for porting this plugin. Iv'e had it installed for a couple of months now and it's been working great. I just recently noticed that there seems to be an issue with this plugin when using Ext.History. However, this seems to be an issue only in Internet Explorer (I'm using IE8). It looks like when the button is rendered, the title of my page is changed to my title + the history link. I added the plugin to the history example, and after the button is rendered the page looks as follows (notice the title).

32070

When I click on the button, the title is changed again. See below:

32071

I've done a little debugging and as far as I can tell it may be swfobject.js that is causing this title change. I'm a little hesitant on changing swfobject so I figured I'd ask if this is something that you've come across and/or if you have any suggestions on what changes I could make to fix this issue.

Any help is appreciated!

Thanks,
Danny

wiznia
24 Feb 2012, 3:05 AM
I have no idea what could be changing the title... It only happens when you use Ext.History?
I doubt it's a swfobject issue, since it's widely used, but I really don't know what could be causing the issue... sorry.

droessner
24 Feb 2012, 5:18 AM
I actually just created a simple grid (without any of the Ext.History stuff) and added the exporter button and then just added "#text" to the end of my url and it still happened. I guess I'll keep digging, thanks anyway!

BlackLine
24 Feb 2012, 5:28 AM
Hi, wiznia.
I'm using your plugin and it works fine, thank you!

But I have a question about button - can I use there a simple button, without underlying png-image?
Could you tell me what code I should change to do it?

wiznia
24 Feb 2012, 6:24 AM
droessner, it only happens in IE? Can you post an example code?

BlackLine, you can't use a simple ext button, because the png is there to allow the download of the file (via downloadify). In previous versions a regular button was used, and a data-uri link but there's no support for data-uri in older browsers and there's a limit on the size of the data-uri that made browsers crash when the file was too large.

droessner
24 Feb 2012, 6:41 AM
Yes, I've only seen this issue come up in IE. I'm using IE8. Here is a really simple example. When you run this just add "#text" to the end of the url and load the page. When I initially load the page it adds "#text" to the title. When I click on the button it changes the title to just "#text"



<!DOCTYPE html>
<html>
<head>
<title>Exporter Example</title>
<link rel="stylesheet" type="text/css" href="../ext/resources/css/ext-all.css"/>
<script type="text/javascript" src="../ext/ext-all-debug.js"></script>
<script type="text/javascript" src="exporter/downloadify.min.js"></script>
<script type="text/javascript" src="exporter/swfobject.js"></script>
<script type="text/javascript" src="exporter/Formatter.js"></script>
<script type="text/javascript" src="exporter/Base64.js"></script>
<script type="text/javascript" src="exporter/Button.js"></script>
<script type="text/javascript" src="exporter/csvFormatter/CsvFormatter.js"></script>
<script type="text/javascript" src="exporter/excelFormatter/Cell.js"></script>
<script type="text/javascript" src="exporter/excelFormatter/Style.js"></script>
<script type="text/javascript" src="exporter/excelFormatter/Workbook.js"></script>
<script type="text/javascript" src="exporter/excelFormatter/Worksheet.js"></script>
<script type="text/javascript" src="exporter/excelFormatter/ExcelFormatter.js"></script>
<script type="text/javascript" src="exporter/Exporter.js"></script>
<script type="text/javascript">
Ext.onReady(function(){
Ext.create('Ext.grid.Panel', {
title: 'test',
height: 200,
width: 200,
renderTo: Ext.getBody(),
tbar: [{
xtype: 'exporterbutton'
}],
store: [['test', 'test']],
columns: [{
header: 'test'
}]
});
});
</script>
</head>
<body>
</body>
</html>


Thanks!
Danny

jarobi
27 Feb 2012, 5:56 AM
How this works if i use a Ext Js Chart. The 'exporterbutton' have to be inside the chart implementation? But how i put a button or toolbar to the Chart?

wiznia
27 Feb 2012, 9:26 AM
The button can be configured in 3 ways:
1) By putting it inside a gridpanel or treepanel (no extra config needed).
2) By passing a 'component' config option with an ext component that responds to getStore method.
3) By passing a 'store' config option.

I haven't used it with a chart, but I guess that if you provide the store of the chart it should work.

droessner
1 Mar 2012, 12:56 PM
I have no idea what could be changing the title... It only happens when you use Ext.History?
I doubt it's a swfobject issue, since it's widely used, but I really don't know what could be causing the issue... sorry.

Just a quick follow-up for this. I debugged and it looks like it's happening in swfobject but I assume that the bug itself is because of Internet Explorer. I narrowed it down to the exact line that changes the title when it is rendered. When swfobject sets aa.outerHTML the title of the document changes. I just put some listeners on the exporter component to change the title back so I don't have to mess with swfobject.

RNL
1 Mar 2012, 10:41 PM
Hello,

Is it possible to download all the records if it has pagination??
It only include the current page..

thx

wiznia
2 Mar 2012, 2:39 AM
droessner, glad you found a workaround, not very pretty, but if it works...
RNL, the export only has the loaded records, I thought it would be too dangerous to ask the server for all the data, since there may be millions of records...

jeora
12 Mar 2012, 10:44 PM
32667

my columns are code, name, price and add checkboxSelection model!...
i added export button and success download excel file.. but this(upload image) is what i don't want..
So i tried edit Export.js file.... and try try try..but i failed..
(
var columns = Ext.Array.filter(grid.columns, function(col) {
return ((!col.hidden) && (col.xtype != "checkbox")); // && (!col.xtype || col.xtype != "actioncolumn");
});
)

Anyone help me plz..

wiznia
13 Mar 2012, 2:35 AM
mmm, I don't remember quite well, but for some reason I commented out the part that filtered the actioncolumns... although I don't know what xtype the column of the checkboxselectionmodel is...
Your solution seems pretty much right, there it's filtering all the hidden columns.
Put a breakpoint in there and look at what xtype should be and filter it.

Aranair
13 Mar 2012, 11:19 PM
Hi Wiznia, Thanks for the quick reply. the CSV export works well except a few issues:

The first column in the header is taking this character:

Also the date columns are showing as ####### as the value for start and end date.

===

If you could also point me in the right direction for uploading excel or csv file onto a grid using EXTJS 4. that would be great.

I think I am facing the same problem with the output.
I believe that may be because of the checkbox column, which I have no idea how to avoid :/
Is there anyway I can get it to bypass the checkbox/first column?


-Nevermind, solved it. I just disabled the checkboxcolumn instead for that download section. Btw Wiznia thanks for the work!

Also, I was just wondering if you have any intentions to make the excel formatter work? Currently, my data is getting correctly rendered in CSV format but it seems that whenever I use excel formatter, none of my programs can open it :/

wiznia
14 Mar 2012, 2:34 AM
There are a lot of problems with the excel formatter and different versions and platforms of excel or other spreadsheet programs. For now, I'm using the csv which is easily imported into any program.

Aranair
14 Mar 2012, 3:02 AM
Yeah.. I removed some code and changed some stuff and it could work for excel 2010. But, it broke compatibility with OpenOffice unless I change it to xlsx manually lol. I believe most of the problems are just in the tags:/

wiznia
14 Mar 2012, 3:29 AM
Ok, if you find a solution, make me a pull request on github...

Aranair
15 Mar 2012, 12:49 AM
we decided to just cater to excel users heh and leave openoffice with csv instead lol.

Btw, have you got downloadify to work on firefox/safari? The buttons aren't showing up at all for me in those browsers. The script isn't even there if i inspect the elements heh.

wiznia
15 Mar 2012, 2:46 AM
Yes, it's working on all browsers. Do you have all the paths configured?

Aranair
15 Mar 2012, 7:29 AM
Yes, it's working on all browsers. Do you have all the paths configured?

jeesh, this is embarrassing to say even, found out I didn't have the flash plugin on firefox heh =.=

Then again, there lies the inert problem of using a flash downloader I guess haha.

Jay Tanwar
21 Mar 2012, 4:59 AM
Hi,
Nice work wiznia.
I have a query..
Does it work on Sencha Touch 2.0..?

wiznia
21 Mar 2012, 6:41 AM
I have't tried it, but it should. On the other hand, it uses downloadify to download the file, which is flash, so it would work only on devices that support flash.

Jay Tanwar
21 Mar 2012, 9:16 PM
First of all thanx for the quick reply.. :)

I am getting this error in console..

Uncaught TypeError: Cannot set property 'Exporter' of undefined
Uncaught TypeError: Cannot read property 'Button' of undefined

I went through the complete thread and tried the following:
Activated the loader:

Ext.Loader.setConfig({enabled: true});
Ext.Loader.setPath('Ext.ux.exporter', './Library/ux/exporter');




Added the 'uses' config:
uses:[ 'Ext.ux.exporter.Exporter'],
Another Issue is. As you said, if requires flash. Then it will not work in iOS (iPhone and iPad) devices?
So do we have any other solution available for iOS devices?

wiznia
22 Mar 2012, 2:57 AM
mmm, are the files actually loaded? Where is the error thrown?
As for iOS, I don't know how could you do it, maybe there's some html5 way to serve a download from a webpage, but I don't know.

kalchas
31 Mar 2012, 2:51 AM
Many thanks,
it's a terrific component, it works flawlessly.
I tried to put the exportbutton in a docking toolbar of another panel and in the configuration I put
component: Ext.getCmp('gridpanel')
or I put
store: Ext.getCmp('gridpanel').getStore().

Neiither of them has worked.

Thanks,
Harry

rdominelli
4 Apr 2012, 12:07 PM
Since upgrading to 4.1 (which fixed a whole bunch of IE issues I am receiving an error when loading the output of this plugin.
Excel 2010 Message says problems came up in the following areas during load, with a listbox containing the word Style and a reference to a log file in temporary internet files. The log file contains






XML ERROR in Style
REASON: Too many tags
FILE: C:\Users\Rich\Desktop\downloadtest.xls
GROUP: Style
TAG: Alignment




XML ERROR in Style
REASON: Too many tags
FILE: C:\Users\Rich\Desktop\downloadtest.xls
GROUP: Style
TAG: Font




XML ERROR in Style
REASON: Too many tags
FILE: C:\Users\Rich\Desktop\downloadtest.xls
GROUP: Style
TAG: Interior




XML ERROR in Style
REASON: Too many tags
FILE: C:\Users\Rich\Desktop\downloadtest.xls
GROUP: Style
TAG: NumberFormat




XML ERROR in Style
REASON: Too many tags
FILE: C:\Users\Rich\Desktop\downloadtest.xls
GROUP: Style
TAG: Protection




XML ERROR in Style
REASON: Too many tags
FILE: C:\Users\Rich\Desktop\downloadtest.xls
GROUP: Style
TAG: Interior




XML ERROR in Style
REASON: Too many tags
FILE: C:\Users\Rich\Desktop\downloadtest.xls
GROUP: Style
TAG: Interior




XML ERROR in Style
REASON: Too many tags
FILE: C:\Users\Rich\Desktop\downloadtest.xls
GROUP: Style
TAG: NumberFormat




XML ERROR in Style
REASON: Too many tags
FILE: C:\Users\Rich\Desktop\downloadtest.xls
GROUP: Style
TAG: NumberFormat




XML ERROR in Style
REASON: Too many tags
FILE: C:\Users\Rich\Desktop\downloadtest.xls
GROUP: Style
TAG: NumberFormat




XML ERROR in Style
REASON: Too many tags
FILE: C:\Users\Rich\Desktop\downloadtest.xls
GROUP: Style
TAG: NumberFormat




XML ERROR in Style
REASON: Too many tags
FILE: C:\Users\Rich\Desktop\downloadtest.xls
GROUP: Style
TAG: NumberFormat




XML ERROR in Style
REASON: Too many tags
FILE: C:\Users\Rich\Desktop\downloadtest.xls
GROUP: Style
TAG: NumberFormat




XML ERROR in Style
REASON: Too many tags
FILE: C:\Users\Rich\Desktop\downloadtest.xls
GROUP: Style
TAG: Borders




XML ERROR in Style
REASON: Too many tags
FILE: C:\Users\Rich\Desktop\downloadtest.xls
GROUP: Style
TAG: Font




XML ERROR in Style
REASON: Too many tags
FILE: C:\Users\Rich\Desktop\downloadtest.xls
GROUP: Style
TAG: NumberFormat




XML ERROR in Style
REASON: Too many tags
FILE: C:\Users\Rich\Desktop\downloadtest.xls
GROUP: Style
TAG: Alignment




XML ERROR in Style
REASON: Too many tags
FILE: C:\Users\Rich\Desktop\downloadtest.xls
GROUP: Style
TAG: Font




XML ERROR in Style
REASON: Too many tags
FILE: C:\Users\Rich\Desktop\downloadtest.xls
GROUP: Style
TAG: Interior




XML ERROR in Style
REASON: Too many tags
FILE: C:\Users\Rich\Desktop\downloadtest.xls
GROUP: Style
TAG: Alignment


Has any one else experienced/solved this?
Rich

rdominelli
4 Apr 2012, 12:35 PM
OK loading the output into an xml editor I see the issue, in the style section for much of the style information a given tag will be outputted x2 for example
<ss:Alignment ss:Vertical="Top" ss:WrapText="1"/> 0"><ss:Alignment ss:Vertical="Top" ss:WrapText="1"/>
<ss:Font ss:FontName="arial" ss:Size="10"/> 0"><ss:Font ss:FontName="arial" ss:Size="10"/>

In each case the first occurrence has that orphaned 0">

In my grid I have alternating rows turned on but no other formatting except what comes by default. seeing if turning it off fixes the issue.

Aranair
4 Apr 2012, 5:22 PM
Since upgrading to 4.1 (which fixed a whole bunch of IE issues I am receiving an error when loading the output of this plugin.
Excel 2010 Message says problems came up in the following areas during load, with a listbox containing the word Style and a reference to a log file in temporary internet files. The log file contains






XML ERROR in Style
REASON: Too many tags
FILE: C:\Users\Rich\Desktop\downloadtest.xls
GROUP: Style
TAG: Alignment




XML ERROR in Style
REASON: Too many tags
FILE: C:\Users\Rich\Desktop\downloadtest.xls
GROUP: Style
TAG: Font




XML ERROR in Style
REASON: Too many tags
FILE: C:\Users\Rich\Desktop\downloadtest.xls
GROUP: Style
TAG: Interior




XML ERROR in Style
REASON: Too many tags
FILE: C:\Users\Rich\Desktop\downloadtest.xls
GROUP: Style
TAG: NumberFormat




XML ERROR in Style
REASON: Too many tags
FILE: C:\Users\Rich\Desktop\downloadtest.xls
GROUP: Style
TAG: Protection




XML ERROR in Style
REASON: Too many tags
FILE: C:\Users\Rich\Desktop\downloadtest.xls
GROUP: Style
TAG: Interior




XML ERROR in Style
REASON: Too many tags
FILE: C:\Users\Rich\Desktop\downloadtest.xls
GROUP: Style
TAG: Interior




XML ERROR in Style
REASON: Too many tags
FILE: C:\Users\Rich\Desktop\downloadtest.xls
GROUP: Style
TAG: NumberFormat




XML ERROR in Style
REASON: Too many tags
FILE: C:\Users\Rich\Desktop\downloadtest.xls
GROUP: Style
TAG: NumberFormat




XML ERROR in Style
REASON: Too many tags
FILE: C:\Users\Rich\Desktop\downloadtest.xls
GROUP: Style
TAG: NumberFormat




XML ERROR in Style
REASON: Too many tags
FILE: C:\Users\Rich\Desktop\downloadtest.xls
GROUP: Style
TAG: NumberFormat




XML ERROR in Style
REASON: Too many tags
FILE: C:\Users\Rich\Desktop\downloadtest.xls
GROUP: Style
TAG: NumberFormat




XML ERROR in Style
REASON: Too many tags
FILE: C:\Users\Rich\Desktop\downloadtest.xls
GROUP: Style
TAG: NumberFormat




XML ERROR in Style
REASON: Too many tags
FILE: C:\Users\Rich\Desktop\downloadtest.xls
GROUP: Style
TAG: Borders




XML ERROR in Style
REASON: Too many tags
FILE: C:\Users\Rich\Desktop\downloadtest.xls
GROUP: Style
TAG: Font




XML ERROR in Style
REASON: Too many tags
FILE: C:\Users\Rich\Desktop\downloadtest.xls
GROUP: Style
TAG: NumberFormat




XML ERROR in Style
REASON: Too many tags
FILE: C:\Users\Rich\Desktop\downloadtest.xls
GROUP: Style
TAG: Alignment




XML ERROR in Style
REASON: Too many tags
FILE: C:\Users\Rich\Desktop\downloadtest.xls
GROUP: Style
TAG: Font




XML ERROR in Style
REASON: Too many tags
FILE: C:\Users\Rich\Desktop\downloadtest.xls
GROUP: Style
TAG: Interior




XML ERROR in Style
REASON: Too many tags
FILE: C:\Users\Rich\Desktop\downloadtest.xls
GROUP: Style
TAG: Alignment


Has any one else experienced/solved this?
Rich


Those are happening because Excel has changed some syntax for their XML stuff I think. You can go through their documentation and manually edit the excelformatter and get it to work for a specific version of excel. But otherwise you're stuck with csvformatter

rdominelli
5 Apr 2012, 5:15 AM
Actually I do not think this is an excel 2010 thing. Prior to upgrading to 4.1 excel would give a warning but would open the file.

Since upgrading to 4.1, the xml produced by the formatter is no longer valid xml. For example

<ss:Alignment ss:Vertical="Top" ss:WrapText="1"/> 0"><ss:Alignment ss:Vertical="Top" ss:WrapText="1"/>

Cleaning up the dupes and removing the extra 0"> fixes the xml so excel is able to open the file again.
Trying to pin down in the Style.js file where the issue is.
Rch

Aranair
5 Apr 2012, 6:52 AM
Mmm, that is possible too I guess.

For me, I modified the code to remove ALOT of tags that were being generated and it does open in Excel 2010 thankfully. It no longer has any formatting though lol.

Also, I'm on 4.1 mm

rdominelli
5 Apr 2012, 10:32 AM
The attached replacement for Style.js seems to do the trick. Place this (after backing up the original) in exporter\excelFormatter

I still get a warning opening the file in excel, but it will open it correctly now.

Rich

Aranair
5 Apr 2012, 6:16 PM
Anyone know if its possible to create a REAL excel spreadsheet that doesn't consist of XML?:P

shawon
11 Apr 2012, 7:53 AM
thanks rdominelli, your file did the trick now its showing the excel file, but shows an warning in the beginning.

Can anyone have any solution for this?

krishnarn1
13 Apr 2012, 4:16 AM
Where can i download the latest code for export excel

Mental
13 Apr 2012, 7:07 AM
I had successfully add button on my panel, but when i am clicking nothing happened, and i don't get any errors.
What can i do with that ?

code:


{
xtype: 'exporterbutton',
store: this.store,
formatter: 'excel',
downloadName: 'Trial licenses (new)',
swfPath: '/extjs/ux/exporter/downloadify.swf',
downloadImage: '/extjs/ux/exporter/download.png'
}


I don't using grid, I have panel with buttons and store with data.

Plz help.

shawon
13 Apr 2012, 8:00 AM
I also went through this kind of issues, its definitely failing on some where in the formatter, but that doesn't throws an error. Best is you have debug through the formatter, dig it down and see from which point it failing. I resolved that way.

Mental
17 Apr 2012, 12:11 AM
It seems that this error is in Swf file, I have used flash with debuging and firefox gave this error.

34105

Mental
17 Apr 2012, 1:07 AM
I found why I have this problem, it happens because I didn't set fields for the store and Exporter was not able to send fields to swf.

shawon
10 May 2012, 1:55 AM
Hi Everybody,

I need a help its very urgent, exproter was working fine on my environment, thanks for the very good work. But the problem is my clients environment doesn't allows swf, so that in their environment its not working.

Can anyone help me with bypassing the swf to format grid to xcel? Its very urgent...

Thanks in advance..

yoisen
15 May 2012, 1:11 AM
:((,I always have the error when I display the button: ext-debug.js:4486 (http://localhost:8099/App/static/extjs-4.1/ext-debug.js)
Uncaught TypeError: Cannot call method 'substring' of undefined

How can I fix it?I'm using EXTJS4.It looks like a namespace problem


Uncaught TypeError: Cannot call method 'substring' of undefined

Ext.ClassManager.parseNamespaceext-debug.js:4486 (http://localhost:8099/App/static/extjs-4.1/ext-debug.js)
Ext.ClassManager.getext-debug.js:4594 (http://localhost:8099/App/static/extjs-4.1/ext-debug.js)
Ext.ClassManager.instantiateext-debug.js:4822 (http://localhost:8099/App/static/extjs-4.1/ext-debug.js)
Ext.ClassManager.instantiateByAliasext-debug.js:4804 (http://localhost:8099/App/static/extjs-4.1/ext-debug.js)
Ext.apply.widgetext-debug.js:5081 (http://localhost:8099/App/static/extjs-4.1/ext-debug.js)
Ext.define.createComponentManager.js:39 (http://localhost:8099/App/static/extjs-4.1/src/ComponentManager.js)
Ext.define.lookupComponentAbstractContainer.js:464 (http://localhost:8099/App/static/extjs-4.1/src/container/AbstractContainer.js)
Ext.define.prepareItemsAbstractContainer.js:437 (http://localhost:8099/App/static/extjs-4.1/src/container/AbstractContainer.js)
Ext.define.addAbstractContainer.js:531 (http://localhost:8099/App/static/extjs-4.1/src/container/AbstractContainer.js)
Ext.define.initItemsAbstractContainer.js:314 (http://localhost:8099/App/static/extjs-4.1/src/container/AbstractContainer.js)
Base.implement.callParentext-debug.js:3728 (http://localhost:8099/App/static/extjs-4.1/ext-debug.js)
Ext.define.initItemsAbstractPanel.js:162 (http://localhost:8099/App/static/extjs-4.1/src/panel/AbstractPanel.js)
Ext.define.initComponentAbstractContainer.js:294 (http://localhost:8099/App/static/extjs-4.1/src/container/AbstractContainer.js)
Base.implement.callParentext-debug.js:3728 (http://localhost:8099/App/static/extjs-4.1/ext-debug.js)
Ext.define.initComponentAbstractPanel.js:152 (http://localhost:8099/App/static/extjs-4.1/src/panel/AbstractPanel.js)
Base.implement.callParentext-debug.js:3728 (http://localhost:8099/App/static/extjs-4.1/ext-debug.js)
Ext.define.initComponentPanel.js:496 (http://localhost:8099/App/static/extjs-4.1/src/panel/Panel.js)
Ext.define.constructorAbstractComponent.js:1019 (http://localhost:8099/App/static/extjs-4.1/src/AbstractComponent.js)
Base.implement.callParentext-debug.js:3728 (http://localhost:8099/App/static/extjs-4.1/ext-debug.js)
Ext.define.constructorComponent.js:365 (http://localhost:8099/App/static/extjs-4.1/src/Component.js)
constructorext-debug.js:3892 (http://localhost:8099/App/static/extjs-4.1/ext-debug.js)
Ext.apply.widgetext-debug.js:5083 (http://localhost:8099/App/static/extjs-4.1/ext-debug.js)
Ext.define.createComponentManager.js:39 (http://localhost:8099/App/static/extjs-4.1/src/ComponentManager.js)
Ext.define.lookupComponentAbstractContainer.js:464 (http://localhost:8099/App/static/extjs-4.1/src/container/AbstractContainer.js)
Ext.define.prepareItemsAbstractContainer.js:437 (http://localhost:8099/App/static/extjs-4.1/src/container/AbstractContainer.js)
Ext.define.addAbstractContainer.js:531 (http://localhost:8099/App/static/extjs-4.1/src/container/AbstractContainer.js)
Ext.define.initItemsAbstractContainer.js:314 (http://localhost:8099/App/static/extjs-4.1/src/container/AbstractContainer.js)
Ext.define.initComponentAbstractContainer.js:294 (http://localhost:8099/App/static/extjs-4.1/src/container/AbstractContainer.js)
Base.implement.callParentext-debug.js:3728 (http://localhost:8099/App/static/extjs-4.1/ext-debug.js)
Ext.define.initComponentstatic/extjs-4.1/src/form/FieldSet.js:171 (http://localhost:8099/App/static/extjs-4.1/src/form/FieldSet.js)
Ext.define.constructorAbstractComponent.js:1019 (http://localhost:8099/App/static/extjs-4.1/src/AbstractComponent.js)
Base.implement.callParentext-debug.js:3728 (http://localhost:8099/App/static/extjs-4.1/ext-debug.js)
Ext.define.constructorComponent.js:365 (http://localhost:8099/App/static/extjs-4.1/src/Component.js)
constructorext-debug.js:3892 (http://localhost:8099/App/static/extjs-4.1/ext-debug.js)
(anonymous function)
Ext.ClassManager.instantiateext-debug.js:4859 (http://localhost:8099/App/static/extjs-4.1/ext-debug.js)
Ext.ClassManager.instantiateByAliasext-debug.js:4804 (http://localhost:8099/App/static/extjs-4.1/ext-debug.js)
Ext.apply.widgetext-debug.js:5081 (http://localhost:8099/App/static/extjs-4.1/ext-debug.js)
Ext.define.createComponentManager.js:39 (http://localhost:8099/App/static/extjs-4.1/src/ComponentManager.js)
Ext.define.lookupComponentAbstractContainer.js:464 (http://localhost:8099/App/static/extjs-4.1/src/container/AbstractContainer.js)
Ext.define.prepareItemsAbstractContainer.js:437 (http://localhost:8099/App/static/extjs-4.1/src/container/AbstractContainer.js)
Ext.define.addAbstractContainer.js:531 (http://localhost:8099/App/static/extjs-4.1/src/container/AbstractContainer.js)
Ext.define.initItemsAbstractContainer.js:314 (http://localhost:8099/App/static/extjs-4.1/src/container/AbstractContainer.js)
Base.implement.callParentext-debug.js:3728 (http://localhost:8099/App/static/extjs-4.1/ext-debug.js)
Ext.define.initItemsAbstractPanel.js:162 (http://localhost:8099/App/static/extjs-4.1/src/panel/AbstractPanel.js)
Base.implement.callParentext-debug.js:3728 (http://localhost:8099/App/static/extjs-4.1/ext-debug.js)
Ext.define.initItemsstatic/extjs-4.1/src/form/Panel.js:215 (http://localhost:8099/App/static/extjs-4.1/src/form/Panel.js)
Ext.define.initComponentAbstractContainer.js:294 (http://localhost:8099/App/static/extjs-4.1/src/container/AbstractContainer.js)
Base.implement.callParentext-debug.js:3728 (http://localhost:8099/App/static/extjs-4.1/ext-debug.js)
Ext.define.initComponentAbstractPanel.js:152 (http://localhost:8099/App/static/extjs-4.1/src/panel/AbstractPanel.js)
Base.implement.callParentext-debug.js:3728 (http://localhost:8099/App/static/extjs-4.1/ext-debug.js)
Ext.define.initComponentPanel.js:496 (http://localhost:8099/App/static/extjs-4.1/src/panel/Panel.js)
Base.implement.callParentext-debug.js:3728 (http://localhost:8099/App/static/extjs-4.1/ext-debug.js)
Ext.define.initComponentstatic/extjs-4.1/src/form/Panel.js:174 (http://localhost:8099/App/static/extjs-4.1/src/form/Panel.js)
Ext.define.constructorAbstractComponent.js:1019 (http://localhost:8099/App/static/extjs-4.1/src/AbstractComponent.js)
Base.implement.callParentext-debug.js:3728 (http://localhost:8099/App/static/extjs-4.1/ext-debug.js)
Ext.define.constructorComponent.js:365 (http://localhost:8099/App/static/extjs-4.1/src/Component.js)
constructorext-debug.js:3892 (http://localhost:8099/App/static/extjs-4.1/ext-debug.js)
(anonymous function)
Ext.ClassManager.instantiateext-debug.js:4859 (http://localhost:8099/App/static/extjs-4.1/ext-debug.js)
Ext.ClassManager.instantiateByAliasext-debug.js:4804 (http://localhost:8099/App/static/extjs-4.1/ext-debug.js)
Ext.apply.widgetext-debug.js:5081 (http://localhost:8099/App/static/extjs-4.1/ext-debug.js)
Ext.define.createComponentManager.js:39 (http://localhost:8099/App/static/extjs-4.1/src/ComponentManager.js)
Ext.define.lookupComponentAbstractContainer.js:464 (http://localhost:8099/App/static/extjs-4.1/src/container/AbstractContainer.js)
Ext.define.prepareItemsAbstractContainer.js:437 (http://localhost:8099/App/static/extjs-4.1/src/container/AbstractContainer.js)
Ext.define.addAbstractContainer.js:531 (http://localhost:8099/App/static/extjs-4.1/src/container/AbstractContainer.js)
Ext.define.initItemsAbstractContainer.js:314 (http://localhost:8099/App/static/extjs-4.1/src/container/AbstractContainer.js)
Base.implement.callParentext-debug.js:3728 (http://localhost:8099/App/static/extjs-4.1/ext-debug.js)
Ext.define.initItemsAbstractPanel.js:162 (http://localhost:8099/App/static/extjs-4.1/src/panel/AbstractPanel.js)
Ext.define.initComponentAbstractContainer.js:294 (http://localhost:8099/App/static/extjs-4.1/src/container/AbstractContainer.js)
Base.implement.callParentext-debug.js:3728 (http://localhost:8099/App/static/extjs-4.1/ext-debug.js)
Ext.define.initComponentAbstractPanel.js:152 (http://localhost:8099/App/static/extjs-4.1/src/panel/AbstractPanel.js)
Base.implement.callParentext-debug.js:3728 (http://localhost:8099/App/static/extjs-4.1/ext-debug.js)
Ext.define.initComponentPanel.js:496 (http://localhost:8099/App/static/extjs-4.1/src/panel/Panel.js)
Base.implement.callParentext-debug.js:3728 (http://localhost:8099/App/static/extjs-4.1/ext-debug.js)
Ext.define.initComponentList.js:270 (http://localhost:8099/App/static/js/app/view/attendanceDay/List.js)
Ext.define.constructorAbstractComponent.js:1019 (http://localhost:8099/App/static/extjs-4.1/src/AbstractComponent.js)
Base.implement.callParentext-debug.js:3728 (http://localhost:8099/App/static/extjs-4.1/ext-debug.js)
Ext.define.constructorComponent.js:365 (http://localhost:8099/App/static/extjs-4.1/src/Component.js)
constructorext-debug.js:3892 (http://localhost:8099/App/static/extjs-4.1/ext-debug.js)
(anonymous function)
Ext.ClassManager.instantiateext-debug.js:4859 (http://localhost:8099/App/static/extjs-4.1/ext-debug.js)
(anonymous function)ext-debug.js:1839 (http://localhost:8099/App/static/extjs-4.1/ext-debug.js)
Ext.define.onMenuClickedMain.js:27 (http://localhost:8099/App/static/js/app/controller/Main.js)
control.viewport pageHeader buttongroup button.clickMain.js:14 (http://localhost:8099/App/static/js/app/controller/Main.js)
fireext-debug.js:8586 (http://localhost:8099/App/static/extjs-4.1/ext-debug.js)
Ext.define.dispatchEventBus.js:49 (http://localhost:8099/App/static/extjs-4.1/src/app/EventBus.js)
Ext.override.fireEventEventBus.js:23 (http://localhost:8099/App/static/extjs-4.1/src/app/EventBus.js)
Ext.define.fireHandlerButton.js:1125 (http://localhost:8099/App/static/extjs-4.1/src/button/Button.js)
Ext.define.onClickButton.js:1117 (http://localhost:8099/App/static/extjs-4.1/src/button/Button.js)
(anonymous function)
Ext.apply.createListenerWrap.wrapext-debug.js:9171 (http://localhost:8099/App/static/extjs-4.1/ext-debug.js)

skotamreddy
16 May 2012, 7:41 AM
Hi Shawon,

I am in the same situation. Did you figure out if you can use exporter without using swf?

- Srinivas

yoisen
16 May 2012, 4:49 PM
I now export excel from server.That is reliable

mrhomer
17 May 2012, 1:19 AM
I have implemented the export button but when I click on it nothing happened, and I don't have any error. What can be wrong please help

opms
21 May 2012, 10:03 AM
hi parkcity
Awesome work...........i tried implementing it, but nothing happens when i click on the exporter button in the toolbar..........i have defined headers and dataindexes for the grid ...................no errors too...........my code is.....

var myStore = new Ext.create('Ext.data.Store', {
storeId:'simpsonsStore',
fields:['name', 'email', 'phone'],
data:{'items':[
{ 'name': 'Lisa', "email":"lisa@simpsons.com", "phone":"555-111-1224" },
{ 'name': 'Bart', "email":"bart@simpsons.com", "phone":"555-222-1234" },
{ 'name': 'Homer', "email":"home@simpsons.com", "phone":"555-222-1244" },
{ 'name': 'Marge', "email":"marge@simpsons.com", "phone":"555-222-1254" }
]},
proxy: {
type: 'memory',
reader: {
type: 'json',
root: 'items'
}
}
});


var myGrid = new Ext.create('Ext.grid.Panel', {
title: 'Simpsons',
store: myStore,
tbar : [
{
xtype: 'exporterbutton',
store: myStore
}],
columns: [
{ header: 'Name', text:'name',dataIndex: 'name' },
{ header: 'Email', dataIndex: 'email', flex: 1 },
{ header: 'Phone', dataIndex: 'phone' }
]});




Ext.onReady(function(){


var myWindow = Ext.create('Ext.window.Window',{
height: 250,
width: 450,
renderTo:Ext.getBody(),
items:[myGrid]
});
myWindow.show()


});



35466

Kindly suggest something.....

pierrocknroll
31 May 2012, 5:03 AM
wiznia can you update your github with the Style.js fix for extjs 4.1 made by rdominelli ? (and other older fixes if any)

http://www.sencha.com/forum/showthread.php?136598-Export-store-to-Excel&p=773479&viewfull=1#post773479

Thanks

wiznia
31 May 2012, 6:40 AM
Can somebody make a pull request on github? Does the fix also works in Ext 4.0?

mrhomer
4 Jun 2012, 6:34 AM
Can I use a button that is not on the grid panel with this plugin and a store that is not shown in grid on the page?

wiznia
4 Jun 2012, 7:31 AM
Yes, you can put the button anywhere.
The config goes as follows:
- if the store config is sent, it will use that.
- if the component config is sent, it will use the store of that component (and if it's a grid the colModel).
- if none of those configurations is found, it will use the first gridpanel that's a container of the button itself, and if it's not found a treepanel.

If none of those work, it will probably throw an error (I haven't tried it), the exporter needs a store to function.

mrhomer
4 Jun 2012, 10:44 PM
Yes, you can put the button anywhere.
The config goes as follows:
- if the store config is sent, it will use that.
- if the component config is sent, it will use the store of that component (and if it's a grid the colModel).
- if none of those configurations is found, it will use the first gridpanel that's a container of the button itself, and if it's not found a treepanel.

If none of those work, it will probably throw an error (I haven't tried it), the exporter needs a store to function.

U think something like this:


Ext.Define('KA.view.Panel',{
extend:'Ext.panel.Panel',
items:[
{
xtype: 'exporterbutton',
store: 'GridStore',
component: Ext.getCmp('GridView')
}
]
});

wiznia
5 Jun 2012, 1:13 AM
You have to specify the store OR the component, not both. If it's a grid it's better to specify the component, because it uses the column model of the grid to format the output.

mrhomer
5 Jun 2012, 1:25 AM
Nothing happens on the click of the button. I have no error what could be the problem ?

wiznia
5 Jun 2012, 1:49 AM
Try debugging it....

mrhomer
5 Jun 2012, 2:00 AM
Nothing :( I am using ExtJs 4 MVC maybe that is the problem or pls give me an example

droessner
5 Jun 2012, 4:39 AM
The swfobject.js has some try/catch blocks in it that don't do anything on an error. It's possible that an error is occurring somewhere in there and it is not being caught by the debugger.

mrhomer
6 Jun 2012, 3:07 AM
Can I add a action to the button ?

trinitrotoluen
8 Jun 2012, 11:02 PM
Can somebody make a pull request on github? Does the fix also works in Ext 4.0?

I'm using Ext-4.1.0 now.
I already tested on MS Office 2007 (windows), Style.js fix made by rdominelli does work but still show a warning when opening the file.
On MS Office 2011 (Mac) it doesn't work still error.
How about other version does it work ? anyone

Thanks Wiznia Great work ~o)

talha06
11 Jun 2012, 6:49 AM
Hello everyone,

I'm getting 404 Not found Error despite the path that I wrote is true.. I'm including some other sources from same path. :-?

Here's my Export Button configuration:

this.btnExport = Ext.create('Ext.ux.exporter.Button', {
component: this,
text : "Download as .xls",
swfPath : 'ux/exporter/downloadify.swf',
icon : 'ux/exporter/download.png'
});

Here's my project directory:
36122

wiznia
11 Jun 2012, 9:16 AM
The path you are setting is relative... the relative path is relative of the url of the browser you are seeing, not from the js file.

mrhomer
13 Jun 2012, 4:04 AM
the plugin works great on all borwser except on IE9 could you tell me what seems to be the problem?

I'm using extjs 4.

Thx

talha06
13 Jun 2012, 6:44 AM
The path you are setting is relative... the relative path is relative of the url of the browser you are seeing, not from the js file.
OK thanks for your care wiznia.. Now I don't get any errors but the expoerted excel file is damaged; I couldn't open it.. It is giving an error like this : "The file has a different extension than .xls; do you still want to open it?" Then I clicked yes but I couldn't see anything. How can I solve this error?
Thanks in advance..

neerajbherwal
12 Jul 2012, 11:14 AM
Hello ,

The exporter is working fine for me for EXTJS 4.1 and in Chrome and Firefox. But the button does not appear in IE.

Would you know what could cause this to happen?

Thanks,

another_i
13 Jul 2012, 2:52 AM
I rewrote exporter button for my purposes:
I don't use UX (and haven't enough free time for now to write a new exporter ux). I use ExtJS 4.1.1 GA application with MVC architecture.
In grid's dockedItems i have toolbar with button whitch have itemId: "exportXls" and in controller i have next control function:



init: function(){
this.control({
//...
'grid button[itemId=exportXls]': {click: this.exportxlsFn}
//...
});
},


exportxlsFn: function (btn) {
// Base64 encode / decode http://www.webtoolkit.info/
var Base64 = (function() {
// private property
var keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";


// private method for UTF-8 encoding
function utf8Encode(string) {
string = string.replace(/\r\n/g,"\n");
var utftext = "";
for (var n = 0; n < string.length; n++) {
var c = string.charCodeAt(n);
if (c < 128) {
utftext += String.fromCharCode(c);
}
else if((c > 127) && (c < 2048)) {
utftext += String.fromCharCode((c >> 6) | 192);
utftext += String.fromCharCode((c & 63) | 128);
}
else {
utftext += String.fromCharCode((c >> 12) | 224);
utftext += String.fromCharCode(((c >> 6) & 63) | 128);
utftext += String.fromCharCode((c & 63) | 128);
}
}
return utftext;
}


// public method for encoding
return {
encode : (typeof btoa == 'function') ? function(input) { return btoa(input); } : function (input) {
var output = "";
var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
var i = 0;
input = utf8Encode(input);
while (i < input.length) {
chr1 = input.charCodeAt(i++);
chr2 = input.charCodeAt(i++);
chr3 = input.charCodeAt(i++);
enc1 = chr1 >> 2;
enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
enc4 = chr3 & 63;
if (isNaN(chr2)) {
enc3 = enc4 = 64;
} else if (isNaN(chr3)) {
enc4 = 64;
}
output = output +
keyStr.charAt(enc1) + keyStr.charAt(enc2) +
keyStr.charAt(enc3) + keyStr.charAt(enc4);
}
return output;
}
};
})();


var grid = btn.up("gridpanel"),
counter = 0;
var columns = Ext.Array.filter(grid.columns, function (col) {
return !col.hidden; // && (!col.xtype || col.xtype != "actioncolumn");
});
// columns = grid.store.fields.items;
var sm = grid.getSelectionModel().getSelection();
var title = grid.title;
var returner = "";
var data = [];
for (var i = 0; i < grid.store.data.items.length; i++)
data[i] = grid.store.data.items[i].data;


var compiledWorksheets;

var typeMappings = {
'int': "Number",
'string': "String",
'float': "Number",
'date': "DateTime"
}


function buildColumns() {
var cols = [];


Ext.each(columns, function (column) {
cols.push(buildColumn());
}, this);


return cols;
}


function buildColumn(width) {
return Ext.String.format('<ss:Column ss:Width="200" />');
}


function buildRows(store) {
var rows = [];
counter = 0;
store.each(function (record, index) {
if (sm.length != 0) {
Ext.Array.forEach(sm, function (smm) {
if (index == smm.index) {
rows.push(buildRow(record, index));
counter += 1;
}


}, this);
} else {
rows.push(buildRow(record, index));
counter += 1;
}
}, this);
return rows.join("");
}


function buildHeader() {
var cells = [];


Ext.each(columns, function (col) {
var title;


//if(col.dataIndex) {
if (col.text != undefined && col.text != " " && col.text != "&#160" && col.text != "&nbsp;") {
title = col.text;
} else if (col.name) {


//make columns taken from Record fields (e.g. with a col.name) human-readable
title = col.name.replace(/_/g, " ");
title = Ext.String.capitalize(title);


}
if (title != undefined && title != " " && title != "&#160") cells.push(Ext.String.format('<ss:Cell ss:StyleID="headercell"><ss:Data ss:Type="String">{0}</ss:Data><ss:NamedCell ss:Name="Print_Titles" /></ss:Cell>', title));
//}
}, this);


return cells.join("");
}


function buildRow(record, index) {
var style, cells = [];
// if (this.stripeRows === true)
style = index % 2 == 0 ? 'even' : 'odd';


Ext.each(columns, function (col) {
var name = col.name || col.dataIndex;


if (name) {
//if given a renderer via a ColumnModel, use it and ensure data type is set to String
if (Ext.isFunction(col.renderer)) {
var value = col.renderer(record.get(name), null, record),
type = "String";
} else {
var value = record.get(name),
type = typeMappings[col.type || record.fields.get(name).type.type];
}


cells.push(buildCell(value, type, style));
}


}, this);


return Ext.String.format("<ss:Row>{0}</ss:Row>", cells.join(""));
}


function buildCell(value, type, style) {
if (type == "DateTime" && Ext.isFunction(value.format)) value = value.format(dateFormatString);
if (value.indexOf("checked") != -1) value = "true";
if (value.indexOf("checked") == -1 && value.indexOf("checkheader") != -1) value = "false";
if (value.indexOf("$$$") != -1) value = value.substring(3);
// value.replace("$","");
if (value == "$$$String") value = "String";
if (value == "$$$Number") value = "Number";
if (value == "$$$Boolean") value = "Boolean";
var celltpl = '<ss:Cell ss:StyleID="' + style + '">' + '<ss:Data ss:Type="' + type + '"><=!=[=C=D=A=T=A=[' + value + ']=]=></ss:Data>' + '</ss:Cell>';
return celltpl;
}


var colCount = columns.length - 2;
var rowCount = grid.store.getCount();


var resultstring = '<?xml version="1.0" encoding="utf-8"?>'+
'<ss:Workbook xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet" xmlns:x="urn:schemas-microsoft-com:office:excel" xmlns:o="urn:schemas-microsoft-com:office:office">' +
'<o:DocumentProperties><o:Title>'+title+'</o:Title></o:DocumentProperties>'+
'<ss:ExcelWorkbook>'+
'<ss:WindowHeight>9000</ss:WindowHeight>'+
'<ss:WindowWidth>50000</ss:WindowWidth>'+
'<ss:ProtectStructure>false</ss:ProtectStructure>'+
'<ss:ProtectWindows>false</ss:ProtectWindows>'+
'</ss:ExcelWorkbook>'+
'<ss:Styles>'+
'<ss:Style ss:ID="Default">'+
'<ss:Alignment ss:Vertical="Top" ss:WrapText="1" />'+
'<ss:Font ss:FontName="arial" ss:Size="10" />'+
'<ss:Interior />'+
'<ss:NumberFormat />'+
'<ss:Protection />'+
'<ss:Borders >'+
'<ss:Border ss:Position="Top" ss:Color="#e4e4e4" ss:Weight="1" ss:LineStyle="Continuous" />'+
'<ss:Border ss:Position="Bottom" ss:Color="#e4e4e4" ss:Weight="1" ss:LineStyle="Continuous" />'+
'<ss:Border ss:Position="Left" ss:Color="#e4e4e4" ss:Weight="1" ss:LineStyle="Continuous" />'+
'<ss:Border ss:Position="Right" ss:Color="#e4e4e4" ss:Weight="1" ss:LineStyle="Continuous" />'+
'</ss:Borders>'+
'</ss:Style>'+
'<ss:Style ss:ID="even">'+
'<ss:Interior ss:Pattern="Solid" ss:Color="#CCFFFF" />'+
'</ss:Style>'+
'<ss:Style ss:ID="odd">'+
'<ss:Interior ss:Pattern="Solid" ss:Color="#CCCCFF" />'+
'</ss:Style>'+
'<ss:Style ss:ID="evendate" ss:Parent="even">'+
'<ss:NumberFormat ss:Format="[ENG][$-409]dd-mmm-yyyy;@" />'+
'</ss:Style>'+
'<ss:Style ss:ID="evenint" ss:Parent="even">'+
'<ss:NumberFormat ss:Format="0" />'+
'</ss:Style>'+
'<ss:Style ss:ID="evenfloat" ss:Parent="even">'+
'<ss:NumberFormat ss:Format="0.00" />'+
'</ss:Style>'+
'<ss:Style ss:ID="odddate" ss:Parent="even">'+
'<ss:NumberFormat ss:Format="[ENG][$-409]dd-mmm-yyyy;@" />'+
'</ss:Style>'+
'<ss:Style ss:ID="oddint" ss:Parent="even">'+
'<ss:NumberFormat ss:Format="0" />'+
'</ss:Style>'+
'<ss:Style ss:ID="oddfloat" ss:Parent="even">'+
'<ss:NumberFormat ss:Format="0.00" />'+
'</ss:Style>'+
'<ss:Style ss:ID="title">'+
'<ss:Borders />'+
'<ss:Font />'+
'<ss:NumberFormat ss:Format="@" />'+
'<ss:Alignment ss:WrapText="1" ss:Horizontal="Center" ss:Vertical="Center" />'+
'</ss:Style>'+
'<ss:Style ss:ID="headercell">'+
'<ss:Font ss:Bold="1" ss:Size="10" />'+
'<ss:Interior ss:Pattern="Solid" ss:Color="#A3C9F1" />'+
'<ss:Alignment ss:WrapText="1" ss:Horizontal="Center" />'+
'</ss:Style>'+
'</ss:Styles>'+


'<ss:Worksheet>'+
'<ss:Table x:FullRows="1" x:FullColumns="1" ss:ExpandedColumnCount="'+colCount+'" ss:ExpandedRowCount="'+rowCount+'">'+
buildColumns().join("")+
'<ss:Row ss:AutoFitHeight="1">'+
buildHeader()+
'</ss:Row>'+
buildRows(grid.store)+
'</ss:Table>'+


'<x:WorksheetOptions>'+
'<x:PageSetup>'+
'<x:Layout x:CenterHorizontal="1" x:Orientation="Landscape" />'+
'<x:Footer x:Data="Page &amp;P of &amp;N" x:Margin="0.5" />'+
'<x:PageMargins x:Top="0.5" x:Right="0.5" x:Left="0.5" x:Bottom="0.8" />'+
'</x:PageSetup>'+
'<x:FitToPage />'+
'<x:Print>'+
'<x:PrintErrors>Blank</x:PrintErrors>'+
'<x:FitWidth>1</x:FitWidth>'+
'<x:FitHeight>32767</x:FitHeight>'+
'<x:ValidPrinterInfo />'+
'<x:VerticalResolution>600</x:VerticalResolution>'+
'</x:Print>'+
'<x:Selected />'+
'<x:DoNotDisplayGridlines />'+
'<x:ProtectObjects>False</x:ProtectObjects>'+
'<x:ProtectScenarios>False</x:ProtectScenarios>'+
'</x:WorksheetOptions>'+
'</ss:Worksheet>'+
'</ss:Workbook>';


returner += resultstring;


window.location.href = window.location.href = 'data:application/vnd.ms-excel;base64,' +
Base64.encode(returner);

Ext.MessageBox.show({
title: 'System message',
msg: 'You saved ' + counter + ' rows.',
buttons: Ext.MessageBox.OK,
});
},


Grids have checkbox select model and export function exports selected or all (if selection is null) rows.
You can use this code for define a new exporter button (which is in grid's toolbar) if you need.

I hope it will be helpful for you.

gabsoftware
17 Jul 2012, 1:14 AM
Thanks, but the generated XLS file is corrupt... Renaming it to .xslx does not help.

another_i
17 Jul 2012, 3:11 AM
@gabsoftware, a generated file is corrupted in MS Office? I use LibreOffice 3.5 and it open the file correct.

ferchotipin
17 Jul 2012, 3:36 AM
the plugin works great on all borwser except on IE9 could you tell me what seems to be the problem?

I'm using extjs 4.

Thx

What did you do to make it work, I have the same problem that I click the button and I don't get any error, but it doesn't do anything...

Thx

another_i
17 Jul 2012, 5:07 AM
Also saving Base64 String as an Excel .xls/.xlsx file using JavaScript impossible in IE7 without a server-side proxy. So, generally, it is better to use server-side code for a generation files, or you can also output an HTML table and ask the user to copy and paste it into Excel.
Server-side libraries are:

http://phpexcel.codeplex.com/ and on github: https://github.com/PHPOffice/PHPExcel
(https://github.com/PHPOffice/PHPExcel)
[/URL]http://www.tinybutstrong.com/tools.php (https://github.com/PHPOffice/PHPExcel)
https://github.com/IamSmith/node-excel for node.js
[URL="http://phpexcel.codeplex.com/"] (http://www.tinybutstrong.com/tools.php)And i think there are an other ones.

gabsoftware
17 Jul 2012, 5:09 AM
I use LibreOffice 3.5 as well (I do not have MS Office). I got a general error whenever I try to open the file. The
generated file is in attachment.

Note : I tried to indent the file to find out why it causes this error, and removed the "=" from the CDATA sections. Changed nothing, same error.

37226

gabsoftware
17 Jul 2012, 5:26 AM
By the way, here is my attempt at exporting a grid to CSV (based on the function from another_i) :




btn_csv_click: function( btn, e, options)
{
// Base64 encode / decode http://www.webtoolkit.info/
var Base64 =
(
function()
{
// private property
var keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";


// private method for UTF-8 encoding
function utf8Encode(string)
{
string = string.replace(/\r\n/g,"\n");
var utftext = "";
for( var n = 0; n < string.length; n++ )
{
var c = string.charCodeAt(n);
if( c < 128 )
{
utftext += String.fromCharCode(c);
}
else if( (c > 127) && (c < 2048) )
{
utftext += String.fromCharCode((c >> 6) | 192);
utftext += String.fromCharCode((c & 63) | 128);
}
else
{
utftext += String.fromCharCode((c >> 12) | 224);
utftext += String.fromCharCode(((c >> 6) & 63) | 128);
utftext += String.fromCharCode((c & 63) | 128);
}
}
return utftext;
}


// public method for encoding
return {
encode : (typeof btoa == 'function') ? function(input) { return btoa(input); } : function (input)
{
var output = "";
var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
var i = 0;
input = utf8Encode(input);
while( i < input.length )
{
chr1 = input.charCodeAt(i++);
chr2 = input.charCodeAt(i++);
chr3 = input.charCodeAt(i++);
enc1 = chr1 >> 2;
enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
enc4 = chr3 & 63;
if (isNaN(chr2))
{
enc3 = enc4 = 64;
} else if (isNaN(chr3))
{
enc4 = 64;
}
output = output +
keyStr.charAt(enc1) + keyStr.charAt(enc2) +
keyStr.charAt(enc3) + keyStr.charAt(enc4);
}
return output;
}
};
}
)();


var grid = btn.up("gridpanel"),
counter = 0;

var columns = Ext.Array.filter
(
grid.columns, function (col)
{
return ! col.hidden; // && (!col.xtype || col.xtype != "actioncolumn");
}
);

var sm = grid.getSelectionModel().getSelection();
var title = grid.title;

var returner = "";

var data = [];
for (var i = 0; i < grid.store.data.items.length; i++)
{
data[i] = grid.store.data.items[i].data;
}
counter = data.length;

//build the header line
for( var i = 0; i < columns.length; i++ )
{
if( i > 0 )
{
returner += ",";
}
returner += columns[i].dataIndex;
}


var value;

//For each line
for( var i = 0; i < data.length; i++ )
{
//begins a new line
returner += "\n";

//builds a line
for( var j = 0; j < columns.length; j++ )
{
if( j > 0 )
{
returner += ",";
}
value = data[ i ][ columns[ j ].dataIndex ];
if( value === null )
{
value = "";
}
returner += value;
}
}

//send the file
downloadDataURI
(
{
filename: "export.csv",
data: "data:text/csv;base64," + Base64.encode(returner)
}
);

//display how many exported rows
Ext.MessageBox.show
(
{
title: 'Export',
msg: counter + ' lignes ont été exportées.',
buttons: Ext.MessageBox.OK
}
);
}


File download-data_uri.js to include as a resource as well as jQuery:


/* dependency: jquery (include in resources) */

var downloadDataURI = function(options) {
if(!options) {
return;
}
$.isPlainObject(options) || (options = {data: options});
if(!$.browser.webkit) {
location.href = options.data;
}
options.filename || (options.filename = "download." + options.data.split(",")[0].split(";")[0].substring(5).split("/")[1]);
options.url || (options.url = "http://download-data-uri.appspot.com/");
$('<form method="post" action="'+options.url+'" style="display:none"><input type="hidden" name="filename" value="'+options.filename+'"/><input type="hidden" name="data" value="'+options.data+'"/></form>').submit().remove();
}



Note that I use the download-data_uri.js script to force the filetype of the saved file, but that is optional if you don't mind.

another_i
17 Jul 2012, 5:28 AM
@gabsoftware, ok.
What structure is in your grid? What columns is in it?

And you can insert debugger here and look in firebug or chrome debugger tool your xml, in variable returner, that will be encoded by Base64 in next step:


//...
returner += resultstring;
debugger;
window.location.href = window.location.href = 'data:application/vnd.ms-excel;base64,' +Base64.encode(returner);
//...

another_i
17 Jul 2012, 5:32 AM
CSV is great format, yes. =)

ferchotipin
19 Jul 2012, 4:57 AM
@gabsoftware
(http://www.sencha.com/forum/member.php?465432-gabsoftware)
I tried and it is working in Chrome in a test version I did:



Ext.define('SomeGrid', {
extend: 'Ext.grid.Panel',
uses: ['Ext.ux.exporter.Exporter'],


initComponent: function() {
this.callParent(arguments);
}
})


Ext.onReady(function() {


Ext.create('Ext.data.Store', {
storeId: 'simpsonsStore',
fields: ['name', 'email', 'phone'],
data: {
'items': [{
"name": "Lisa",
"email": "lisa@simpsons.com",
"phone": "555-111-1224"
}, {
"name": "Bart",
"email": "bart@simpsons.com",
"phone": "555--222-1234"
}, {
"name": "Homer",
"email": "home@simpsons.com",
"phone": "555-222-1244"
}, {
"name": "Marge",
"email": "marge@simpsons.com",
"phone": "555-222-1254"
}]
},
proxy: {
type: 'memory',
reader: {
type: 'json',
root: 'items'
}
}
});


Ext.create('SomeGrid', {
title: 'Simpsons',
store: Ext.data.StoreManager.lookup('simpsonsStore'),
tbar: [{
xtype: 'button',
handler: function(btn, e, options) {
// Base64 encode / decode http://www.webtoolkit.info/
var Base64 = (


function() {
// private property
var keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";




// private method for UTF-8 encoding


function utf8Encode(string) {
string = string.replace(/\r\n/g, "\n");
var utftext = "";
for (var n = 0; n < string.length; n++) {
var c = string.charCodeAt(n);
if (c < 128) {
utftext += String.fromCharCode(c);
} else if ((c > 127) && (c < 2048)) {
utftext += String.fromCharCode((c >> 6) | 192);
utftext += String.fromCharCode((c & 63) | 128);
} else {
utftext += String.fromCharCode((c >> 12) | 224);
utftext += String.fromCharCode(((c >> 6) & 63) | 128);
utftext += String.fromCharCode((c & 63) | 128);
}
}
return utftext;
}




// public method for encoding
return {
encode: (typeof btoa == 'function') ?
function(input) {
return btoa(input);
} : function(input) {
var output = "";
var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
var i = 0;
input = utf8Encode(input);
while (i < input.length) {
chr1 = input.charCodeAt(i++);
chr2 = input.charCodeAt(i++);
chr3 = input.charCodeAt(i++);
enc1 = chr1 >> 2;
enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
enc4 = chr3 & 63;
if (isNaN(chr2)) {
enc3 = enc4 = 64;
} else if (isNaN(chr3)) {
enc4 = 64;
}
output = output + keyStr.charAt(enc1) + keyStr.charAt(enc2) + keyStr.charAt(enc3) + keyStr.charAt(enc4);
}
return output;
}
};
})();




var grid = btn.up("gridpanel"),
counter = 0;


var columns = Ext.Array.filter(
grid.columns, function(col) {
return !col.hidden; // && (!col.xtype || col.xtype != "actioncolumn");
});


var sm = grid.getSelectionModel().getSelection();
var title = grid.title;


var returner = "";


var data = [];
for (var i = 0; i < grid.store.data.items.length; i++) {
data[i] = grid.store.data.items[i].data;
}
counter = data.length;


//build the header line
for (var i = 0; i < columns.length; i++) {
if (i > 0) {
returner += ",";
}
returner += columns[i].dataIndex;
}




var value;


//For each line
for (var i = 0; i < data.length; i++) {
//begins a new line
returner += "\n";


//builds a line
for (var j = 0; j < columns.length; j++) {
if (j > 0) {
returner += ",";
}
value = data[i][columns[j].dataIndex];
if (value === null) {
value = "";
}
returner += value;
}
}


//send the file
downloadDataURI({
filename: "export.csv",
data: "data:text/csv;base64," + Base64.encode(returner)
});


//display how many exported rows
Ext.MessageBox.show({
title: 'Export',
msg: counter + ' lignes ont été exportées.',
buttons: Ext.MessageBox.OK
});
}
}],
columns: [{
header: 'Name',
dataIndex: 'name'
}, {
header: 'Email',
dataIndex: 'email',
flex: 1
}, {
header: 'Phone',
dataIndex: 'phone'
}],
height: 200,
width: 400,
renderTo: Ext.getBody()
});
});


var downloadDataURI = function(options) {
if (!options) {
return;
}
$.isPlainObject(options) || (options = {
data: options
});
if (!$.browser.webkit) {
location.href = options.data;
}
options.filename || (options.filename = "download." + options.data.split(",")[0].split(";")[0].substring(5).split("/")[1]);
options.url || (options.url = "http://download-data-uri.appspot.com/");
$('<form method="post" action="' + options.url + '" style="display:none"><input type="hidden" name="filename" value="' + options.filename + '"/><input type="hidden" name="data" value="' + options.data + '"/></form>').submit().remove();

}
but when I try it in Firefox it downloads a .part file with a random characters name, I open it, it has the information, and in IE it doesn't do anything it send me to this address:


data:text/csv;base64,bmFtZSxlbWFpbCxwaG9uZQpMaXNhLGxpc2FAc2ltcHNvbnMuY29tLDU1NS0xMTEtMTIyNApCYXJ0LGJhcnRAc2ltcHNvbnMuY29tLDU1NS0tMjIyLTEyMzQKSG9tZXIsaG9tZUBzaW1wc29ucy5jb20sNTU1LTIyMi0xMjQ0Ck1hcmdlLG1hcmdlQHNpbXBzb25zLmNvbSw1NTUtMjIyLTEyNTQ=

Now when I try it in my server version in chrome it send me to this address:

http://download-data-uri.appspot.com/

in firefox does the same as the local it downloads a .part file with the info inside.

in IE does the same as the local.


Any thoughts!...thx

MeDigital
2 Aug 2012, 12:43 PM
It does not seems to work on firefox...

seems to work only at Chrome and IE

arpeggian
2 Aug 2012, 6:19 PM
Hi, i get a blank toolbar.. whats wrong with my code?

index.html


...
<script type="text/javascript" src="extjs/src/ux/exporter/downloadify.min.js"></script>
<script type="text/javascript" src="extjs/src/ux/exporter/swfobject.js"></script>
...


app.js


....
Ext.require([
'Ext.tree.Panel',
'Ext.data.TreeStore',
'Ext.tab.Panel',
'Ext.Viewport',
'Ext.ux.exporter.Exporter'
]);
.....


in my grid

...
tbar : [
{
xtype: 'exporterbutton'
}
],
...


If i need include expressinstall? for flash? or anything wrong with my code?
please help me... thanks a lot before and sorry for my poor english.

regards.

arpeggian
2 Aug 2012, 6:33 PM
Opps, sorry.. i can figure out.. my problem is path of swf and the image. but now, when i click the download button, nothing happened... i also check it with firebug, but nothing to display


Hi, i get a blank toolbar.. whats wrong with my code?

index.html


...
<script type="text/javascript" src="extjs/src/ux/exporter/downloadify.min.js"></script>
<script type="text/javascript" src="extjs/src/ux/exporter/swfobject.js"></script>
...


app.js


....
Ext.require([
'Ext.tree.Panel',
'Ext.data.TreeStore',
'Ext.tab.Panel',
'Ext.Viewport',
'Ext.ux.exporter.Exporter'
]);
.....


in my grid

...
tbar : [
{
xtype: 'exporterbutton'
}
],
...


If i need include expressinstall? for flash? or anything wrong with my code?
please help me... thanks a lot before and sorry for my poor english.

regards.

arpeggian
2 Aug 2012, 6:42 PM
37715

Now, i get this error when i open the file downloaded.. help me please

KostasP
7 Aug 2012, 11:31 AM
I downloaded the code from here https://github.com/iwiznia/Ext.ux.Exporter

(https://github.com/iwiznia/Ext.ux.Exporter)It throws an error Uncaught ReferenceError: Downloadify is not defined

What should I do to make it working? There are 16 pages of comments so any quickhint will be appreciated...

KostasP
7 Aug 2012, 2:50 PM
I included Downloadify code from here https://github.com/dcneiner/Downloadify

a (https://github.com/dcneiner/Downloadify)nd i get the same error with the Style described 2 posts above...

carlosgoias
14 Aug 2012, 5:36 AM
This post is some how frustrating!

But, some how I made It work for OpenOffice... for Excel still file corrupted :(

pardha
5 Sep 2012, 8:19 PM
Hi, Can someone cleanup and show an working example of Excel export without flash.. I have tried of example given in this thread but no luck. I keep getting one another error.

a_kanin
8 Sep 2012, 11:11 AM
Hi Wisnia, first of all its amazing all your work. I want to congratulate you for all this.

I already read de 22 pages of the forum. I was struggling to get the example you gave working, but i managed to do it.

Now i tried to integrate it to my app and i want to export a complete store, and i am struggilng with it.
For example i use this:

Ext.define('SomeGrid', {
extend: 'Ext.grid.Panel',
uses: [
'Ext.ux.exporter.Exporter'
],

initComponent: function() {
this.dockedItems = [{
xtype: 'toolbar',
dock: 'top',
items: [{
xtype: 'exporterbutton'
}]
}]
this.callParent(arguments);
}
})

with that ext.define in any you put 'someGrid' and automatically brings the download button and detects store and columns.
but it sends only the records that seens in the page.
and to send the full sotre I believe that you need a different method ... or i dont know what am doing wrong.

Regards.

Ecthelion
11 Sep 2012, 4:50 AM
rdominelli's Style.js worked for me, too but the template should be more like this in my opinion:




tpl: new Ext.XTemplate(
'<tpl if="parentStyle.length == 0">',
'<ss:Style ss:ID="{id}">',
'</tpl>',
'<tpl if="parentStyle.length != 0">',
'<ss:Style ss:ID="{id}" ss:Parent="{parentStyle}">',
'</tpl>',
'<tpl for="attributes">',
'<tpl if="children.length == 0">',
'<ss:{name} {propertiesString} />',
'</tpl>',
'<tpl if="children.length &gt; 0">',
'<ss:{name} {propertiesString}>',
'<tpl for="children">',
'<ss:{name} {propertiesString} />',
'</tpl>',
'</ss:{name}>',
'</tpl>',
'</tpl>',
'</ss:Style>'
)



&gt; is used instead of '>' and that also prevents the unwanted '0">' characters. The excel warning is still there, though.




'<tpl if="children.length == 0">',
'<ss:{name} {propertiesString} />',
'</tpl>',



This part reduces the file size as it closes the tags without an end tag, so it's better we leave it there.

alex9311
13 Sep 2012, 2:18 PM
Hey all,

I would really like to get this working for my grid project but I'm having a lot of trouble. I have been scouring the internet for a couple days and havn'y found anything very helpful in this topic. Even trying to set the loader is crashing my page. I'm using MVC architechture.

Where should I be setting the loader? In the grid view file or in the top app.js file? Are either of the commented out sections in my grid code the right way to create a print button?

Here is the code for my List.js (my grid)


Ext.Loader.setConfig({enabled: true});
Ext.Loader.setPath('Ext.ux', '/var/wwww/application/ux');
Ext.define('AM.view.user.List' , {
extend: 'Ext.grid.Panel',
alias: 'widget.userlist',
store: 'Users',
uses: [
'Ext.ux.exporter.Exporter'
],
dockedItems: [{
xtype: 'toolbar',
dock: 'bottom',
layout:{
pack: 'center'
},
items: [
{
xtype: 'exporterbutton'
}
// new Ext.ux.Exporter.Button({
// component: this,
// text : "Download as .xls"
// })
]
}],
initComponent: function() {
this.columns=[
{header: 'First Name', dataIndex: 'FirstName', width: 75},
{header: 'Last Name', dataIndex: 'Last', width: 75},
{header: 'Perm', dataIndex: 'Perm', width: 60},
{header: 'PreReq', dataIndex: 'PreReq', width: 50,


];
this.callParent(arguments);
}
});




And here is my index.php


<html>
<head>
<title>Waitlist</title>
<link rel="stylesheet" type="text/css" href="ext/resources/css/ext-all.css">
<script type="text/javascript" src="ext/ext-debug.js"></script>
<script type="text/javascript" src="app.js"></script>
<script type="text/javascript" src="ux/exporter/Exporter.js">
</head>
<body></body>
</html>

Any advice or tips are much appreciated!!

Oxii
21 Sep 2012, 6:16 AM
Hi, Can someone cleanup and show an working example of Excel export without flash.. I have tried of example given in this thread but no luck. I keep getting one another error.

Yes, pleeeease .. we really need someone to do that

pksiv
2 Oct 2012, 12:20 PM
37715

Now, i get this error when i open the file downloaded.. help me please

Getting this same problem.

scaddenp
11 Oct 2012, 8:26 PM
I too browsed this thread looking for a way to use a non-flash download. It turns out that the core of Ext.ux.exporter is actually just responsible for extracting the data from a grid / store in the correct format. This data is then being passed to Downloadify for presentation to the user.

From memory, it is not easy to directly download data from the client-side (although I may be wrong). However, it is quite easy to initiate from the server-side by setting the src of a hidden iframe to point to a jsp (I presume other server-side languages will work just as well) that initiates a download with the correct response headers and output stream.

Therefore, I have now created a version of Ext.ux.exporter which will safely initiate a download using this server-side code. Check out https://github.com/stormtek/Ext.ux.Exporter for the latest version. This has been tested in Chrome, Firefox, and IE9, and it should work in older browser as well. Also, I have added an example of this being used (which will be great news for many people).

this-is-sparta
15 Oct 2012, 11:16 PM
rdominelli,
Although excel opens it, the file exported using your version of Style.js is stiil invalid xml (one may encounter unnecessary 0">)
Actually threr is a simple bug in Style.js: it should be &gt; instead of > in this line:
'<tpl if="children.length > 0">',

talha06
17 Oct 2012, 4:03 AM
I have just clone the source from github and applied to one of my grids : Getting an error like this with Ext JS 4.1.1.a on Ubuntu 64-bit while trying to open newly created Excel file:

General Error
General Input/Output Error

terjeio
17 Oct 2012, 5:10 AM
Here is some changes to the CSV-formatter, now quotes strings and escapes double quotes in strings, exports dates in ISO-format. It could be extended by setting ";" as default separator to avoid problems in locales using comma as decimal point.


//**
* @class Ext.ux.Exporter.CSVFormatter
* @extends Ext.ux.Exporter.Formatter
* Specialised Format class for outputting .csv files
*/
Ext.define("Ext.ux.exporter.csvFormatter.CsvFormatter", {
extend: "Ext.ux.exporter.Formatter",
contentType: 'data:text/csv;base64,',
separator: ",",
extension: "csv",

format: function(store, config) {
this.columns = config.columns || (store.fields ? store.fields.items : store.model.prototype.fields.items);
return this.getHeaders() + "\n" + this.getRows(store);
},
getHeaders: function() {
var columns = [], title;
Ext.each(this.columns, function(col) {
var title;
if (col.text != undefined) {
title = col.text;
} else if(col.name) {
title = col.name.replace(/_/g, " ");
title = Ext.String.capitalize(title);
}

columns.push(title);
}, this);

return columns.join(this.separator);
},
getRows: function(store) {
var rows = [];
store.each(function(record, index) {
rows.push(this.geCell(record, index));
}, this);

return rows.join("\n");
},
geCell: function(record) {
var cells = [];
Ext.each(this.columns, function(col) {
var name = col.name || col.dataIndex;
if(name) {
var value;
if (Ext.isFunction(col.renderer) && !col.xtype == 'datecolumn') {
value = col.renderer(record.get(name), null, record);
} else {
value = record.get(name);
}
cells.push(Ext.isDate(value) ? (value ? Ext.Date.format(value, 'Y-m-d') : '') : (typeof(value) == "string" ? '"' + value.replace(/"/g, '""') + '"' : value));


}
}, this);

return cells.join(this.separator);
}
});

chandrima31
17 Oct 2012, 7:20 AM
@scaddenp : your stormtek/Ext.us.Exporter in github is not working in chrome or IE. The download as CSV / Excel buttons are not producing any file-download on click. Kindly suggest me what changes I need to make.

feiji1983
26 Oct 2012, 12:34 AM
I looked at the button code, and it is still messed up.
For now if you need this you can do what I'm currently doing.

Replace your button code with a standard Ext.button.Button


Ext.create('Ext.button.Button',{
text:'Download as .xls',
handler:function(button){
var gridPanel=button.up('gridpanel');
var dataURL='data:application/vnd.ms-excel;base64,'+Ext.ux.exporter.Exporter.exportGrid(gridPanel);
window.location.href=dataURL;
}
})




i did this like


var exButton = Ext.create('Ext.button.Button',{

text:'Download as .xls',
handler:function(button){
var gridPanel=button.up('gridpanel');
var dataURL='data:application/vnd.ms-excel;base64,'+ Ext.ux.exporter.Exporter.exportGrid(gridPanel);
// var dataURL='data:application/vnd.ms-excel;base64,'+ exportGrid(gridPanel);
window.location.href=dataURL;
}
})

but got the error message : Ext.ux.exporter is undefined

any one can tell me how to fix it? @wiznia

aladdina
2 Nov 2012, 11:52 PM
There are still issues when use it on ExtJS 4.1.1a, I made some fix on CSV formater, and make it work. Here is the modified code on GitHub:
https://github.com/MasonZhang/Ext.ux.Exporter

Please note: there are some issues when excel parse the exported xml format file, I just make csv format work.

sarz
3 Nov 2012, 1:16 AM
Hi ,
I used your code to export into a xls file while opening in excel it shows some style error problem . How can i view that file without styles attached to it . please say how to remove style from that xls file ..

mpasacrita@escholar.com
5 Nov 2012, 10:23 AM
I've spent the last 2 days going through and trying all the posted solutions here and I found the following result:

All solutions posted here are either:
1) Not compatible with ExtJS4.1
2) Depend on a Flash SWF or the JQuery library
3) Have some issues in either firefox or webkit
4) Suggesting we use a server-side solution

Is there anyone who has gotten this working entirely with the ExtJS 4.x library, and no 3rd party dependencies or cross-browser issues? Thank you in advance.

sarz
5 Nov 2012, 8:49 PM
Yes its true i used 4.1 extjs lib so only it was not working . It works 4.0 and less

psnprasad
6 Nov 2012, 7:23 AM
Hi,
I have the same problem. Any plans to provide fix for 4.1

Thanks in Advance.

9josh
28 Nov 2012, 12:25 AM
May I know how to export the store after i reconfigure the grid? When I try to export the store, it only shows the first column of the grid not after reconfigure. Thanks.

Garry Hawkins
5 Dec 2012, 6:24 PM
is this can work in extjs 4.1.1? thanks

scaddenp
5 Dec 2012, 6:30 PM
Sorry, 4.1.1a broke other things so this one isnt at top of the worry list at the moment. Wont be looking at this till have renderers in tree + Geoext sorted out.

delusion
12 Dec 2012, 8:16 AM
Has anyone used this with a tree panel? I have it working for a grid, but when i try to give it a tree componenet, or a tree store, it goes into the excelFormatter, tries to render a workbook,

then does on this


try { __flash__toXML(Downloadify.getTextForSave("downloadify_1355328296803")) ;} catch (e) { "<undefined/>"; }

which i assume is from the downloadify.swf, and then dies with the catch(e) being a TypeError : undefined_method

It's very strange as it gets past this point when using a grid component.

thanks for any ideas anyone might have

mikih
19 Dec 2012, 5:34 AM
does anyone have a clue whats wrong with the generated excel source? I am happy to help, but have no starting point


Cheers

Florian

Sheng_Yunzhou
24 Dec 2012, 1:41 AM
Hi Sarz,

I had the same style problem too but I used the updated Style.js here http://www.sencha.com/forum/showthread.php?136598-Export-store-to-Excel&p=773479&viewfull=1#post773479

vitalz
4 Jan 2013, 2:55 AM
I use a different button which events a controller handles and then the controller tries to fire event on a hidden exporter button.

Ext.define("MyApp.view.MyPanel", {
extend:"Ext.panel.Panel",
requires:['MyApp.view.component.Table'],
alias:"widget.mypanel",
title:"Table Data",
itemId:"mypanelId",
layout:'fit',
items: [
{
xtype:'exporterbutton',
itemId:'exportmytableId',
hidden:true,
store: Ext.create("MyApp.store.data.SomeData"), /* why should I define store two times initially? */
swfPath: '../myapp/ux/exporter/downloadify.swf',
downloadImage: '../myapp/ux/exporter/download.png'
},
{
xtype:'mytable',
itemId:'mytableId',
forceFit: true,
store: Ext.create("MyApp.store.data.SomeData")
}
]

});



Ext.define("MyApp.controller.Export", {
extend: "Ext.app.Controller",

...blah de blah...

/* handle event from tbar button */
exportMe : function() {
var mytable = Ext.ComponentQuery.query('mytable[itemId="mytableId"]');
var exporter = Ext.ComponentQuery.query('exporterbutton[itemId="exportmytableId"]')[0];
exporter.setComponent(mytable, {});
exporter.fireEvent('click'); /* 'down' event also never works; the same is applicable to exporter.body variable */
}

});




But it seems that event never happens. I do not see Save download dialogue...

I have also tried to use Downloadify JS without Ext.ux.exporter.Button but it looks when the ExtJS extension requires (absolutely useless in my current case) swf path, download image... it is completely locked by button logics somewhere in the source code that is why I suppose to use Downloadify JS separately (without knowing implementation details) is still not a good idea!

xdengli
6 Jan 2013, 6:13 AM
export to csv , use notepad to open normal ,but use excel to open garbled Chinese
character
what can i do ? tks。

Sheng_Yunzhou
6 Jan 2013, 6:11 PM
Vitalz: I think the problem is because the exportbutton is actually a swf file (which triggers the opening of download window), not a button, therefore fireEvent('click') may not work.

I'm also waiting for solutions.

vitalz
8 Jan 2013, 2:03 AM
export to csv , use notepad to open normal ,but use excel to open garbled Chinese
character
what can i do ? tks。

Well... that is a hack way. Surely I personally may do it.
But I am developing system for customers who will never go such painful way. What means when user clicks export button browser downloads an Excel file.

vitalz
8 Jan 2013, 2:12 AM
Vitalz: I think the problem is because the exportbutton is actually a swf file (which triggers the opening of download window), not a button, therefore fireEvent('click') may not work.

I'm also waiting for solutions.

Yes, flash is going to be completely removed. Otherwise flash is a reason to never use Ext.ux.exporter user exentension. So, it looks Downloadify is based on flash... we have to hope something will change. B)

First heard flash became main reason we refused Ext.ux.exporter and replaced it by server side Apache POI. :)

The other important feature after no flash is good news that multi stores/tables may be exported to one file. For instance, there are some tables on the screen and those tables need to be exported to one *.xls

kalchas
28 Jan 2013, 4:43 AM
I modified the Ed Spencer, Mason Zhang files and now export to Office 2003,2007,2010, Libreoffice is possible.

vitalz
28 Jan 2013, 4:45 AM
I modified the Ed Spencer, Mason Zhang files and now
did you remove flash? ;)

kalchas
28 Jan 2013, 5:14 AM
No, flash remains. It's needed for the Save As dialog popup to be triggered.

vitalz
28 Jan 2013, 5:17 AM
No, flash remains. It's needed for the Save As dialog popup to be triggered.
Well... Is there no way to open 'Save As' dialogue without flash?

kalchas
28 Jan 2013, 5:20 AM
Well... Is there no way to open 'Save As' dialogue without flash?
I think downlodify needs flash to work. Without it you are restricted to the size of records the grid stores.

vitalz
28 Jan 2013, 6:07 AM
I think downlodify needs flash to work. Without it you are restricted to the size of records the grid stores.
Sorry, have no time to change those JS plugins... I think if possible Ext JS community needs to fix Downloadify by flash removement (or replacement). Hope such solution is existing. Need to be implemented. B)

P.S. I haven't got why the Downloadify developer used flash. Why he made such solution. :-/

jwcraig
1 Feb 2013, 8:43 AM
I haven't tried it yet, but this looks promising: XLSX.js

http://blog.innovatejs.com/?p=50

here's a fiddle:

http://jsfiddle.net/innovatejs/ueETX/

nitingogia@gmail.com
8 Feb 2013, 8:03 AM
I am trying to give my custom image by specifying downloadImage attribute in the config, but any image i put in the image flickers and on clicking hides. Can anyone please help if seen this issue or what I need to do exactly to specify my image rather using the download.png provided by the library.

{
xtype: 'exporterbutton',
store: <<my store>>,
downloadImage: <<path to image>> //pointing to my image on my local
}

sudrak
17 Feb 2013, 11:47 PM
Hi

Can we export charts with this tool?

Thank you in advance

sarz
18 Feb 2013, 2:40 AM
No its only a excel exporter ... you can export extjs chart component from grid store that will be more useful for you .

dbrin
26 Feb 2013, 4:31 PM
I haven't tried it yet, but this looks promising: XLSX.js

http://blog.innovatejs.com/?p=50

here's a fiddle:

http://jsfiddle.net/innovatejs/ueETX/

looks fantastic, could use a store to worksheet adapter.

sarz
26 Feb 2013, 9:21 PM
Please help in this version of EXT ... Thanks in advance ...