Propagating Page properties of a server generated "Telerik.Windows.Documents.Spreadsheet.Model.Workbook" in a web rendered "Telerik.Web.Spreadsheet.Workbook"
Heads up, this is only for licensed developers who can access the commercial library source code.
At present the documents.spreadsheet workbook has a richer capacity than a web.spreadsheet workbook, especially around page setting. I don't know the roadmap, but expect at some point the web Spreadsheet component will take on a richer feature set that aligns with Excel application.
A Telerik document workbook is converted to it's web version for viewing in a browser by using the FromDocument() method. The features that are lost from the sheets of the original document workbook include:
The listed items are those I wanted to deal with, there may be more but they were of no concern to me at this time.
My project has a Controller/ViewModel
Telerik.Windows.Documents.Spreadsheet.Model.Workbook serverSideModel;
... lots of serverSideModel method calls that create a spreadsheet, including page settings ...
return
View(serverSideModel);
and a View
@model Telerik.Windows.Documents.Spreadsheet.Model.Workbook
...
@(
Html.Kendo().Spreadsheet()
.Name(
"mySpreadsheet"
)
.BindTo(Telerik.Web.Spreadsheet.Workbook.FromDocument(Model))
// <--- convert to web version for viewing in browser
...
)
At this point the Spreadsheet component in the browser will display the spreadsheet that was created server side.
The component has a download button and you can select to download as an .xlsx.
The downloaded Excel will have lost any page properties that were in the original server side Telerik document. This is because the internal javascript for creating the excel download does not render any Excel xml related to page layout.
Why not?
Because web spreadsheet model does not implement page setup features. The FromDocument() conversion works, but all the page properties info in the document spreadsheet is ignored.
How can this be remedied ?
1. Explicitly add the original pageSetup features to the converted object.
2. Modify library source code to render pageSetup features in the Excel xml that becomes the download.
Step 1.
After the web spreadsheet (as a FromDocument) is rendered, the document page properties can be explicitly reattached by code in a kendo.syncReady funtion.
For example, at bottom of the View, add a script block:
<script>
kendo.syncReady(
function
() {
var
book = $(
"#mySpreadsheet"
).data(
"kendoSpreadsheet"
);
@
for
(
var
index=0; index < Model.Sheets.Count; index++)
{
var
sheet = Model.Worksheets[index];
var
pageSetup = sheet.WorksheetPageSetup;
var
left = (pageSetup.Margins.Left > 4) ? UnitHelper.DipToInch(UnitHelper.PointToDip(pageSetup.Margins.Left)) : pageSetup.Margins.Left;
var
right = (pageSetup.Margins.Right > 4) ? UnitHelper.DipToInch(UnitHelper.PointToDip(pageSetup.Margins.Right)) : pageSetup.Margins.Right;
var
top = (pageSetup.Margins.Top > 4) ? UnitHelper.DipToInch(UnitHelper.PointToDip(pageSetup.Margins.Top)) : pageSetup.Margins.Top;
var
bottom = (pageSetup.Margins.Bottom > 4) ? UnitHelper.DipToInch(UnitHelper.PointToDip(pageSetup.Margins.Bottom)) : pageSetup.Margins.Bottom;
var
header = (pageSetup.Margins.Header > 4) ? UnitHelper.DipToInch(UnitHelper.PointToDip(pageSetup.Margins.Header)) : pageSetup.Margins.Header;
var
footer = (pageSetup.Margins.Footer > 4) ? UnitHelper.DipToInch(UnitHelper.PointToDip(pageSetup.Margins.Footer)) : pageSetup.Margins.Footer;
var
orientation = (pageSetup.PageOrientation == Telerik.Windows.Documents.Model.PageOrientation.Landscape) ?
"Landscape"
:
"Portrait"
;
var
scale = pageSetup.ScaleFactor.Width * 100;@* convert from telerik scaleFactor to excel scale % *@
<text>
book.sheets()[@index].showGridLines(
false
);
book.sheets()[@index].pageSetup = {
viewTags:
'view="pageBreakPreview" zoomScaleNormal="85" zoomScaleSheetLayoutView="100"'
,
// I know the innards of Excel xml enough to to this. I did not want to deal making changes in the library source that handled view, zoomScalNormal and zoomScaleSheetLayoutView as actual properties
margins: {
left: @left,
right: @right,
top: @top,
bottom: @bottom,
header: @header,
footer: @footer},
orientation:
"@(orientation.ToLower())"
,
scale: @scale,
headerFooterSettings: {
header: {
leftSection: {
text:
"@pageSetup.HeaderFooterSettings.Header.LeftSection.Text"
},
centerSection: {
text:
"@pageSetup.HeaderFooterSettings.Header.CenterSection.Text"
},
rightSection: {
text:
"@pageSetup.HeaderFooterSettings.Header.RightSection.Text"
}
},
footer: {
leftSection: {
text:
"@pageSetup.HeaderFooterSettings.Footer.LeftSection.Text"
},
centerSection: {
text:
"@pageSetup.HeaderFooterSettings.Footer.CenterSection.Text"
},
rightSection: {
text:
"@pageSetup.HeaderFooterSettings.Footer.RightSection.Text"
}
}
}
};
</text>
}
@*
replace standard download button response of a Export... dialog
with
a direct download as Excel
*@
$(
"#mySpreadsheet .k-i-download"
)
.parent(
".k-button"
)
.unbind()
.on(
"click"
,
function
(e) {
$(
"#mySpreadsheet"
).data(
"kendoSpreadsheet"
).saveAsExcel();
return
false
;
});
});
</script>
Step 2. Modify kendo.all.js
This is for licensed developers only.
Patch your licensed copy of the commercial library source code (v 2017.3.1026) with the attached patch file.
The view must include the modified library code that has been copied into your asp-net mvc project, and can not use the minified cdn version. The original licensed kendo-ui complete library source code can be downloaded from your account login.
Myview.cshtml
...
<script src=
"~/Scripts/kendo/2017.3.1026/js/kendo.all.js"
></script>
// modified version contains new magic
...
V
Now when you download your richly featured server side generated spreadsheet from the view it will still contain those rich features.
Scenario:
I have a Grid, and a column with text, with inline editing and OnChange event.
User Clicks a cell and the OnChange event it fired
Once clicked, a modal window is opened (Standard Bootstrap)
Question:
How do I update that Cell again from the Modal. How do I pass the ID or context of the Cell down the stack to the Modal Window?
I have seen there is a TR data-uid, but I'm not sure how to get it in the click event or how to select it with the api down the road in the modal.
Hi!
I would like to use the expandRow(...) function on all of my master-rows in grid. All detail records are loaded via Ajax(...) so I need to wait until each and every detail record is loaded.
My code is simple:
myGrid.expandRow(myGrid.tbody.find(
"tr.k-master-row"
));
How can I wait until every row is expanded?
Regards
Heiko
I'm using 2017.3.1026, and when I add a column menu to my grid, in IE 11 (version 11.0.9600.18762CO) the menu showing the sort, filter and column options appears on a click, but the fly-out menus don't appear.
However, loading the page in Chrome, the menus work as they should, showing the filter options, and the columns to show / hide.
Is this a bug, or do I need to do anything to fix this in IE?
I have a remote bound grid with a ~1000 row dataset. I have the set the page to refresh the grid every 30 seconds since it is desired to keep the data live. When the grid does refresh, it takes a few seconds to repopulate. Users find this disrupting as the grid greys out and cannot be scrolled during this time. Is there a method to refresh the data "in-place"? Basically in the dataset there may be only 1 or 2 rows that actually change some in the 30s time. Is there a method to efficiently update the grid only updating the rows that have changed?
I'm looking at this page http://demos.telerik.com/aspnet-mvc/grid/editing-custom
But there is no editor defined for this control columns.Bound(p => p.Category).ClientTemplate("#=Category.CategoryName#").Width(180);
It's just the client view template.
Is there a way you could add information to the demo around how the custom editor is working? I see there is a categories viewbag filled with the options but it is never called on the UI or used.
I am trying to export to excel using Kendo Grid with grouping enabled.
When the data is exported without any grouping applied, the HTML encoding / decoding works as expected and the text is displayed correctly when I open up the spreadsheet in Excel. However when I group by a column whose value contains an apostrophe (or any character needing encoding), the grouped row is exported to excel without decoding the apostrophe which the users find unpleasant.
The grouping row is being auto-generated from Kendo MVC HTMLHelper for Grid and ​after reviewing the documentation regarding limitations around Kendo templates when exporting data to Excel.
What is the correct way to export a grid with grouping enabled -- in particular, how does one use Kendo Export To Excel functionality with grouping row values whose text contains characters ​​that must be HTML encoded? Is this functionality possible by default, or is custom code required to address this scenario when using ASP.NET MVC?
Hi there guys and gals. There appears to be a problem with bool field(check box) in kendo grid. When you click on a bool field, a check box appears and when you click on the check box to change it from true to false and vice versa, it doesn't change. But when you click on the check box field and then press the space bar, then it changes. This is probably a bug.
example, try changing the Discontinued field in the grid
Hi I have issue with displaying dropdownlist [object object]. I tried everyway and even followed some solution in this issue but none worked. Its simple SelectListItem Bind to dropdownlist. Value is loading without any list. when you click it it displays the list but when you select the list item nothing changed and remain as loaded displaying [Object Object]. but how ever Developer toolls shows Dropdownlist value and text field values. Could you please kindly tell me why and where I am wrong. I am new to Kendo but OK with MVC I have used all other dropDownList using Html helper methods even using models, Enums etc. but why this simple Vlaue, text list is not displaying and selecting. but loading perfectly. Please I am really stuck with other places as well with different kendo grid bind to different tables. Please note I am using ADO.NET and stored Proc to retrieve data as I am migrating to MVC. Please see attached images as well. Hope someone will give me solution to this burning issues. -Please note in my Drondownlist editor template, when I used read metid (Line 14 - 17) I get list as 'undefined' without displaying [object object]. its again same SelectListItem only thing is I manually bind to datasource via read method. Do i have to do anything in DropDownChnage event.
My Grid View.
_CategiryGrid.cshtml
@model IEnumerable<StB.ViewModels.CategoryViewModel>
@{
var imagePath =
"~\\Content\\images\\Info.gif"
;
}
@*
// Ajax Grid // *@
@*@(Html.Kendo().Grid(Model).Name(
"CategoryGrid"
)*@
@(Html.Kendo().Grid<StB.ViewModels.CategoryViewModel>().Name(
"CategoryGrid"
)
.Columns(columns =>
{
columns.Bound(c => c.ClientCode).Hidden(
true
);
columns.Bound(c => c.Category).ClientGroupHeaderTemplate(
"Category: "
+
"#= value#"
).Width(60);
columns.Bound(c => c.Attribute).Title(
"Attribute"
).Width(100);
columns.Bound(c => c.Description).Width(150);
//.ClientTemplate(@"<div><img id='tooltipIconItem' src='@imagePath' ToolTip =#:data:ToolTip# /></div>" + @"<div> @Html.Label('fieldValueItem', #:data:Description#)</div>");
columns.Bound(c => c.Required).Width(30);
//.ClientTemplate(@"<div><img id='reqEdit' src='~\\Content\\images\\RedStar.gif' /></div>");
columns.Bound(c => c.FieldType).Hidden(
true
);
columns.Bound(c => c.DomainID).Hidden(
true
);
columns.Bound(c => c.AttrType).Hidden(
true
);
columns.Bound(c => c.Tooltip).Hidden(
true
);
columns.Bound(c => c.FieldValue).Width(80).Title(
"Value"
).EditorTemplateName(
"FieldValueEditor"
).ClientTemplate(
"#:FieldValue #"
)
.HtmlAttributes(
new
{ id =
"ddlFieldvalues"
});
//.EditorTemplateName("FieldValueEditor");
})
.Editable(editabel => editabel.Mode(GridEditMode.InCell).Enabled(
true
))
.Navigatable()
.Scrollable()
.Groupable()
.Sortable()
.Selectable(selectable => selectable.Mode(GridSelectionMode.Single).Type(GridSelectionType.Cell))
.AutoBind(
false
)
.Pageable(pageable => pageable
.ButtonCount(2))
.DataSource(datasource => datasource
.Ajax()
.Read(read => read.Action(
"DisplayGridData"
,
"HierarchyBuilder"
).Type(HttpVerbs.Post))
.Update(update => update.Action(
"UpdateCategory"
,
"HierarchyBuilder"
))
.ServerOperation(
false
)
.Batch(
true
)
.PageSize(60)
.Model(model => model.Id(p => p.Attribute))
.Model(model =>
{
model.Field(f => f.Category).Editable(
false
);
model.Field(f => f.Attribute).Editable(
false
);
model.Field(f => f.Description).Editable(
false
);
model.Field(f => f.Required).Editable(
false
);
model.Field(f => f.FieldValue).Editable(
true
).DefaultValue(
"1"
);
})
.Aggregates(aggregates => { aggregates.Add(p => p.Category == p.Category).Count(); })
.Group(groups => groups.Add(m => m.Category))
)
.Events(events => { events.Edit(
"onCategoryGridEdit"
).DataBound(
"onCategoryGridDataBound"
).Change(
"onCategoryGridChange"
); })
)
@Html.Hidden(
"ClientCode"
, HttpContext.Current.Session[
"ClientCode"
])
Model for Grid
CategoryViewModel
public
class
CategoryViewModel
{
public
string
OrgCode {
get
;
set
;}
public
string
SiteCode {
get
;
set
;}
public
string
ClientCode {
get
;
set
; }
public
string
StructureCode {
get
;
set
; }
public
string
Category {
get
;
set
; }
public
string
Attribute {
get
;
set
; }
public
string
Description {
get
;
set
; }
[UIHint(
"FieldValueEditor"
)]
public
string
FieldValue {
get
;
set
;}
public
string
AttrType {
get
;
set
; }
public
string
Required {
get
;
set
; }
public
int
FieldType {
get
;
set
; }
public
string
DomainID {
get
;
set
; }
public
string
Tooltip {
get
;
set
; }
public
IList<DomainViewModel> AllDomains {
get
;
set
; }
}
Controller Action method (this is where I get drodowlist as SelectListiem list. I initially directly bound to Domain List and it displays list prefectly but with [object object]. Then I changed to SelectList by creating SelectListItem by reading Domain Model and loading Vlaue text into SelectListItem. I bound to SelectList. Results exactly same. then Finally I chnaged to SelectListItem as show by kendo documentation. Its very simple text value list. and my Grid FieldVlaue in categoryViewModel is string value.
Below is my controller method
public
IEnumerable<SelectListItem> LoadDropDownlistForValueField(
string
type,
string
Client,
bool
required,
string
CurrentVal)
{
StB.DAL.Domain domainRepo =
new
DAL.Domain();
List<StB.Models.Domain> domains =
new
List<Models.Domain>();
domains = domainRepo.GetDomainValueList(type, Client, CurrentVal, required);
SelectListItem sli =
null
;
List<SelectListItem> selectlists =
new
List<SelectListItem>();
foreach
(var d
in
domains)
{
sli =
new
SelectListItem() { Text = d.ShortDescription, Value = d.Value, Selected = d.Value == CurrentVal };
selectlists.Add(sli);
}
ViewData[
"FieldValueList"
] = selectlists;
return
(System.Collections.Generic.IEnumerable<SelectListItem>)ViewData[
"FieldValueList"
];
}
below is my DropDownList editor template for my Grid column.
01.
@(Html.Kendo().DropDownList()
02.
.Name(
"FieldValue"
)
03.
.HtmlAttributes(
new
{ id =
"ddlFieldValues"
})
04.
.ValuePrimitive(
true
)
05.
.DataTextField(
"Text"
)
06.
.DataValueField(
"Value"
)
07.
08.
.AutoBind(
false
)
09.
10.
.Events(e => e.Change(
"onFiledVaueDropDownChange"
).DataBound(
"onFiledVaueDataBound"
))
11.
12.
.BindTo((IEnumerable<SelectListItem>)ViewData[
"FieldValueList"
])
13.
14.
//.DataSource(datasource =>
15.
//{
16.
// datasource.Read(read => read.Action("LoadDropDownlistForValueField", "HierarchyBuilder").Data("additionalInfo('CategoryGrid')"));
17.
//})
18.
19.
)