Skip to content

Commit 3dca971

Browse files
committed
Sync with Kendo UI Professional
1 parent 1f7260c commit 3dca971

File tree

3 files changed

+222
-42
lines changed

3 files changed

+222
-42
lines changed
Lines changed: 216 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,216 @@
1+
---
2+
title: Exporting Grid Rows to Excel with Group Paging
3+
description: This article provides a workaround for exporting Grid rows to Excel when using group paging in the Grid with server operations.
4+
type: how-to
5+
page_title: How to Export Grid Rows to Excel with Group Paging
6+
slug: export-grid-rows-excel-group-paging
7+
tags: grid, export, excel, group paging
8+
res_type: kb
9+
---
10+
## Environment
11+
| Property | Value |
12+
| --- | --- |
13+
| Product | Grid for Progress Kendo UI |
14+
| Version | 2019.3.917 |
15+
16+
## Description
17+
18+
I want to export Grid rows to Excel, but when using group paging in the Grid with server operations, the exported file only includes the top-level grouping titles and not the actual rows. Even when opening some of the rows, they are still not exported.
19+
20+
## Solution
21+
22+
Exporting a [`group-paged Grid to Excel with server operations`](https://demos.telerik.com/kendo-ui/grid/grouppaging) is not officially supported. The Excel export component creates its own dataSource and is not aware of the current state of the expanded groups. This means that the exported dataSource is not able to fetch the correct ranges of data.
23+
24+
However, there is a workaround available that allows you to export a group-paged Grid to Excel. Please note that this is not an official approach and it requires overriding internal logic, so side effects may occur.
25+
26+
The example below demonstrates how to achieve the desired scenario.
27+
28+
```dojo
29+
<div id="grid"></div>
30+
<script>
31+
$(document).ready(function () {
32+
$("#grid").kendoGrid({
33+
sortable: true,
34+
columns: [{
35+
title: "Customer ID",
36+
width: "100px",
37+
field: "customerID"
38+
}, {
39+
title: "Country",
40+
width: "100px",
41+
field: "country"
42+
}, {
43+
title: "Company Name",
44+
width: "100px",
45+
field: "companyName"
46+
}, {
47+
title: "City",
48+
width: "100px",
49+
field: "city"
50+
}, {
51+
title: "Postal Code",
52+
width: "100px",
53+
field: "postalCode"
54+
}],
55+
filterable: true,
56+
scrollable: {
57+
virtual: true,
58+
height: "400px"
59+
},
60+
toolbar: ["excel"],
61+
dataSource: {
62+
type: 'aspnetmvc-ajax',
63+
transport: {
64+
read: {
65+
url: "https://demos.telerik.com/aspnet-core/service/api/customers"
66+
}
67+
},
68+
pageSize: 50,
69+
page: 1,
70+
groupPaging: true,
71+
total: 0,
72+
serverPaging: true,
73+
serverSorting: true,
74+
serverFiltering: true,
75+
serverGrouping: true,
76+
serverAggregates: true,
77+
group: [{
78+
field: "city",
79+
dir: "asc"
80+
}, {
81+
field: "companyName",
82+
dir: "asc"
83+
}],
84+
schema: {
85+
data: "data",
86+
total: "total",
87+
errors: "errors"
88+
}
89+
},
90+
excelExport: function(e) {
91+
e.preventDefault();
92+
var that = this;
93+
var excel = this.options.excel || {};
94+
95+
var options = {
96+
columns: that.columns,
97+
dataSource: that.dataSource,
98+
allPages: excel.allPages,
99+
filterable: excel.filterable,
100+
hierarchy: excel.hierarchy,
101+
collapsible: excel.collapsible
102+
}
103+
104+
var book = new kendo.excel.ExcelExporter($.extend({}, options, null, {
105+
data: that.dataSource.view(),
106+
groups: that.dataSource.group(),
107+
aggregates: that.dataSource.aggregates()
108+
})).workbook();
109+
110+
var workbook = new kendo.ooxml.Workbook(book);
111+
112+
if (!workbook.options) {
113+
workbook.options = {};
114+
}
115+
workbook.options.skipCustomHeight = true;
116+
117+
workbook.toDataURLAsync().then(function (dataURI) {
118+
kendo.saveAs({
119+
dataURI: dataURI,
120+
fileName: book.fileName || excel.fileName,
121+
proxyURL: excel.proxyURL,
122+
forceProxy: excel.forceProxy
123+
});
124+
});
125+
}
126+
});
127+
128+
kendo.excel.ExcelExporter.fn._dataRow = function (dataItem, level, depth) {
129+
var this$1 = this;
130+
131+
var cells = this._createPaddingCells(level);
132+
133+
// grouped
134+
if (dataItem.itemCount && depth) {
135+
cells = cells.concat(this._groupHeaderCells(dataItem, level, depth));
136+
var rows = dataItem.items ? this._dataRows(dataItem.items, level + 1) : [];
137+
138+
rows.unshift({
139+
type: "group-header",
140+
cells: cells,
141+
level: this.collapsible ? level : null
142+
});
143+
144+
return rows.concat(this._footer(dataItem, level));
145+
}
146+
147+
var dataCells = [];
148+
149+
for (var cellIdx = 0; cellIdx < this.columns.length; cellIdx++) {
150+
dataCells[cellIdx] = this$1._cell(dataItem, this$1.columns[cellIdx]);
151+
}
152+
153+
if (this.hierarchy) {
154+
dataCells[0].colSpan = depth - level + 1;
155+
}
156+
157+
return [{
158+
type: "data",
159+
cells: cells.concat(dataCells),
160+
level: this.collapsible ? level : null
161+
}];
162+
}
163+
164+
kendo.excel.ExcelExporter.fn._groupHeaderCells = function (dataItem, level, depth) {
165+
var cells = [];
166+
167+
var column = this.allColumns.filter(function (column) {
168+
return column.field === dataItem.field;
169+
})[0] || {};
170+
171+
var title = column && column.title ? column.title : dataItem.field;
172+
var template = column ? column.groupHeaderTemplate || column.groupHeaderColumnTemplate : null;
173+
var group = $.extend({
174+
title: title,
175+
field: dataItem.field,
176+
value: column && column.values ? column.values[dataItem.value] : dataItem.value,
177+
aggregates: dataItem.aggregates,
178+
items: dataItem.items
179+
}, dataItem.aggregates[dataItem.field]);
180+
181+
var value = template ? template(group) : (title + ": " + (dataItem.value));
182+
183+
cells.push($.extend({
184+
value: value,
185+
background: "#dfdfdf",
186+
color: "#333",
187+
colSpan: (this.hasGroupHeaderColumn ? 1 : this.columns.length) + depth - level
188+
}, column.groupHeaderCellOptions));
189+
190+
if (this.hasGroupHeaderColumn) {
191+
this.columns.forEach(function (column, index) {
192+
if (index > 0) {
193+
cells.push($.extend({
194+
background: "#dfdfdf",
195+
color: "#333",
196+
value: column.groupHeaderColumnTemplate ?
197+
column.groupHeaderColumnTemplate($.extend({ group: group }, group, dataItem.aggregates[column.field])) :
198+
undefined
199+
}, column.groupHeaderCellOptions));
200+
}
201+
});
202+
}
203+
204+
return cells;
205+
}
206+
});
207+
</script>
208+
```
209+
210+
## Notes
211+
Keep in mind that this workaround is not officially supported and may have side effects. Use it at your own discretion.
212+
213+
## See Also
214+
215+
* [JavaScript API Reference of the Kendo UI for jQuery Grid](/api/javascript/ui/grid)
216+
* [Grid Group Paging of Remote Data(Demo)](https://demos.telerik.com/kendo-ui/grid/grouppaging)

src/kendo.popup.js

Lines changed: 6 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,6 @@ var __meta__ = {
3434
VISIBLE = "visible",
3535
EFFECTS = "effects",
3636
ACTIVE = "k-active",
37-
ACTIVEBORDER = "k-state-border",
38-
ACTIVEBORDERREGEXP = /k-state-border-(\w+)/,
3937
ACTIVECHILDREN = ".k-picker-wrap, .k-dropdown-wrap, .k-link",
4038
MOUSEDOWN = "down",
4139
DOCUMENT_ELEMENT = $(document.documentElement),
@@ -197,7 +195,7 @@ var __meta__ = {
197195
}
198196

199197
if (that.options.anchor != BODY) {
200-
that._hideDirClass();
198+
that._hideActiveClass();
201199
}
202200

203201
that._closing = false;
@@ -301,7 +299,7 @@ var __meta__ = {
301299
animation = that._openAnimation();
302300

303301
if (options.anchor != BODY && !that.element.hasClass("k-tooltip")) {
304-
that._showDirClass(animation);
302+
that._addActiveClass();
305303
}
306304

307305
parent.hide();
@@ -367,36 +365,23 @@ var __meta__ = {
367365
return animation;
368366
},
369367

370-
_hideDirClass: function() {
368+
_hideActiveClass: function() {
371369
var anchor = $(this.options.anchor);
372-
var direction = ((anchor.attr("class") || "").match(ACTIVEBORDERREGEXP) || ["", "down"])[1];
373-
var dirClass = ACTIVEBORDER + "-" + direction;
374-
375370
anchor
376-
.removeClass(dirClass)
377371
.children(ACTIVECHILDREN)
378-
.removeClass(ACTIVE)
379-
.removeClass(dirClass);
372+
.removeClass(ACTIVE);
380373

381-
this.element.removeClass(ACTIVEBORDER + "-" + kendo.directions[direction].reverse);
382374
},
383375

384-
_showDirClass: function(animation) {
385-
var direction = animation.effects.slideIn ? animation.effects.slideIn.direction : "down";
386-
var dirClass = ACTIVEBORDER + "-" + direction;
387-
376+
_addActiveClass: function() {
388377
$(this.options.anchor)
389-
.addClass(dirClass)
390378
.children(ACTIVECHILDREN)
391-
.addClass(ACTIVE)
392-
.addClass(dirClass);
379+
.addClass(ACTIVE);
393380
},
394381

395382
position: function() {
396383
if (this.visible()) {
397384
this.flipped = this._position();
398-
//this._hideDirClass();
399-
//this._showDirClass(this._openAnimation());
400385
}
401386
},
402387

tests/popup/popup.js

Lines changed: 0 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -751,27 +751,6 @@
751751
assert.equal(anchor.css("font-style"), div.css("font-style"));
752752
});
753753

754-
it("add direction class to the anchor and popup", function() {
755-
anchor = $("<div style='background:blue;position:absolute;left:100px;top:100px;'><div class='k-dropdown-wrap'>anchor</div></div>").appendTo($("#qunit-fixture"));
756-
popup = new Popup(div, { anchor: anchor });
757-
popup.open();
758-
759-
assert.equal(anchor.hasClass("k-state-border-down"), true);
760-
assert.equal(anchor.find(".k-dropdown-wrap").hasClass("k-state-border-down"), true);
761-
});
762-
763-
it("removes direction class from the anchor and popup", function() {
764-
anchor = $("<div style='background:blue;position:absolute;left:100px;top:100px;'><div class='k-dropdown-wrap'>anchor</div></div>").appendTo($("#qunit-fixture"));
765-
popup = new Popup(div, { anchor: anchor });
766-
767-
popup.open();
768-
popup.close();
769-
770-
assert.equal(anchor.hasClass("k-state-border-down"), false);
771-
assert.equal(anchor.find(".k-dropdown-wrap").hasClass("k-state-border-down"), false);
772-
assert.equal(div.hasClass("k-state-border-up"), false);
773-
});
774-
775754
it("calculate position correctly when content height is 'auto'", function() {
776755
popup = new Popup(div, { anchor: anchor });
777756
popup.open();

0 commit comments

Comments
 (0)