Friday, October 25, 2019

jqxGrid Basics

Here are some workarounds for jqxGrid.

(A) For columns to customize below are some of the customized workaround
(1) To set customized header of column
renderer: columnrenderer

var columnrenderer = function (value) {
                return '<div style="text-align: center; margin-top: 5px;">' + value + '</div>';
            }

(2) To set customized cell value for items
cellsrenderer: cellsrenderer

var cellsrenderer = function (row, column, value) {
                return '<div style="text-align: center; margin-top: 5px;">' + value + '</div>';
            }

(3) To give class to cell row
cellclassname: "verticalAlign"

.verticalAlign{
      vertical-align: middle;
   }

(4) To have column of type of checkbox,
columntype: "checkbox"
- in this case, the field associated with column must be a boolean
- there are many column types there like dropdownlist etc.

(5) To have filter type of boolean
filtertype: "bool"

(6) For boolean checkbox to filter
threestatecheckbox: true

(7) To make header text alignment
align: 'center'

(8) To format cell value
cellsformat: "dd/MM/yyyy"

(9) type: 'number' with  
cellsformat: ‘p’
- to view column data in percentage
cellsformat: 'c'
- to view column data in $ sign

(10) To get any cell value
$("#grid").jqxGrid('getcellvalue', rowIndex, 'columnName');

(11) To set any cell value
$("#grid").jqxGrid('setcellvalue', rowIndex, "columnName", value);


(B) Grid Properties
(1) Set row height property of the grid
rowsheight: 30

(2) Set row height to auto height
autorowheight:true & autoheight:true

(3) Set grid column height
columnsheight:50

(4) To resize columns
columnsresize: true

(5) To enable paging for the grid
pageable:true

(6) To enable filter functionality
filterable: true

(7) To enable separate filter row
showfilterrow: false

(8) To enable sort functionality
sortable: true

(9) To enable groupable functionality
groupable: true

(10) To enable separate group row
showgroupsheader: true

(11) columns reordering for grid when there are multiple columns
columnsreorder:true

(12) To edit single cell
selectionmode:'singlecell'

(13) When to edit 
editmode:'dblclick'

(C) Dynamic
(1) set column property dynamically
$("#jqxgrid").jqxGrid('setcolumnproperty', 'columnName', 'width', 300);

(2) show/hide grid column
$("#jqxgrid").jqxGrid('hidecolumn', "columnName");

(3) cell endedit mode
$("#grid").jqxGrid('endcelledit', 'value', 'columnName', false);

(4) set cell value
$("#grid").jqxGrid('setcellvalue', row, "columnName", 'valueToReplace');


(D) Methods
(1) bindingcomplete method will be get called when grid refreshes after loading for first time
$("#jqxgrid").on('bindingcomplete', function (event) {
    alert('bind');
});

(2) cellvaluechanging: this will be an event we can get when grid is having editable cell value and to perform any functionality we can write it out this metho
cellvaluechanging: function (row, datafield, columntype, oldvalue, newvalue) {
            if (newvalue != oldvalue) {
                // perform any operation here when value get changed from old to new
            }
        }

Have came across to these many properties, methods, events but there are some more that need to investigate and once its done will add those as well.


Saturday, October 12, 2019

Send Push Notification using C#

Here is the way by which we can send push notification to mobile device. Below are some steps to perform before sending notification to device.

(1) Google Firebase provides way by which we can send push notification through that. In this case we have valid google account 
(2) From your Firebase account, create project for the android/ios application
(3) Once your application is installed on your device it will register your device for that project to receive notification
(4) When your device is ready with application created on firebase and device id is registered then it is ready to receive push notifications for that application
(5) In step - (4), when your device is registered with device id, this device id to be shared or stored at some repository so that whenever we want to send notification we can pull that device id and send notification with below c# code

var result = "-1";
var httpWebRequest = (HttpWebRequest)WebRequest.Create("https://fcm.googleapis.com/fcm/send");
httpWebRequest.ContentType = "application/json";
httpWebRequest.Headers.Add(string.Format("Authorization: key={0}", "server key"));
httpWebRequest.Headers.Add(string.Format("Sender: id={0}", "Test Sender"));
httpWebRequest.Method = "POST";

var payload = new
{
to = "device token",
priority = "high",
        content_available = true,
notification = new
        {
        body = "body of notification",
        title = "notification title"
        },
};

using (var streamWriter = new StreamWriter(httpWebRequest.GetRequestStream()))
{
string json = JsonConvert.SerializeObject(payload);
        streamWriter.Write(json);
        streamWriter.Flush();
}

var httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();
using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
{
result = streamReader.ReadToEnd();
}

Thursday, September 26, 2019

Working with swagger

Here is the way by which we can add swagger to dotnet core api and can customize it with our needs.

(1) To work with swagger search and add below package
Swashbuckle.AspNetCore

(2) Once this is added just to make sure to enter below line of codes under ConfigureServices method in Startup.cs
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new Info { Title = "Api", Version = "v1", Description = "" });
c.OperationFilter();// This will be your step - (4)
var xmlFile = "swagger.XML";
        var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
c.IncludeXmlComments(xmlPath);
});

and add below line of code under Configure method in Startup.cs
app.UseSwagger();

app.UseSwaggerUI(c =>
{
c.SwaggerEndpoint("../swagger/v1/swagger.json", "API V1");
});

(3) swagger.xml file will contain
<doc>
  <assembly>
    <name>Api</name>
  </assembly>
 <members>
    <member name="T:Namespace of member">
      <summary>
        Summary of function
     </summary>
    </member>    
</doc>

(4) Adding SwaggerHeaderFilter
public class SwaggerHeaderFilter : IOperationFilter
{

public void Apply(Swashbuckle.AspNetCore.Swagger.Operation operation, OperationFilterContext context)
{
if (operation.Parameters == null)
                operation.Parameters = new List();

IList filterDescriptors = context.ApiDescription.ActionDescriptor.FilterDescriptors;
            bool isAuthorized = filterDescriptors.Select(filterInfo => filterInfo.Filter).Any(filter => filter is AuthenticationApiAttribute);

if (isAuthorized)
            {
// This will add parameters to each endpoint of passing access token
                operation.Parameters.Add(new NonBodyParameter
                {
                    Name = "X-Auth-Token",
                    In = "header",
                    Type = "string",
                    Required = true,
                    Description = "access token"
                });

// This will add parameters to each endpoint of passing access token
                operation.Parameters.Add(new NonBodyParameter
                {
                    Name = "UserId",
                    In = "header",
                    Type = "integer",
                    Required = true,
                    Description = "user id"
                });
            }

            if (String.IsNullOrWhiteSpace(operation.Description))
                operation.Description = "**Action Name**: " + ((Microsoft.AspNetCore.Mvc.Controllers.ControllerActionDescriptor)context.ApiDescription.ActionDescriptor).ActionName;
            else
                operation.Description = "**Action Name**: " + ((Microsoft.AspNetCore.Mvc.Controllers.ControllerActionDescriptor)context.ApiDescription.ActionDescriptor).ActionName + "  " + operation.Description;

}
}

This way you can configure your swagger with API and for each of the endpoint it will have access token and user id. You can add more parameters like this if you require. In step - (4), attribute created requires to register in step - (2).

Friday, September 20, 2019

Dot Net CORE Tips

(1) Razor Pages: For dotnet core application, we can have advantage of building Razor Pages just like we have ".axpx" pages in traditional web application. But there is also an added advantage of MVC pattern can be implemented with existing structure.

(2) Microsoft.Windows.Compatibility: This package is essential whenever we are performing any operation which is available in .net framework implementation.
for e.g. dataSet.Tables[0].AsEnumerable() - This functionality will not available until you will not add above package. As this is dot net native functionality and to laverage this we need this package support. There are many other functionalities are still there.

(3) File Operation: To perform file operation in web, we have practices of using Server.MapPath(filepath) to work with files. But with dotnet core web app this operation is replace with below
private IHostingEnvironment _env;

public MyController(IHostingEnvironment env)
        {
            _env = env;
        }
var webRoot = _env.WebRootPath;

Now, here _env.webRootPath will be your application wwwroot folder path and here you can perform your operation of saving/sp-net-core
- https://gunnarpeipman.com/aspnet/aspnet-core-content-web-root/
- https://www.mikesdotnetting.com/article/302/server-mappath-equivalent-in-asp-net-core
- https://stackoverflow.com/questions/43992261/how-to-get-absolute-path-in-asp-net-core-alternative-way-for-server-mappath

(4) Upload/Save Image
- https://www.codeproject.com/Tips/4051593/How-to-Upload-Images-on-an-ASP-NET-Core-2-2-MVC-We
- https://stackoverflow.com/questions/42741170/how-to-save-images-to-database-using-asp-net-core

(5) To get all the output in json with no case applied on output of json result, in this case just add below line of code to Startup.cs file under ConfigureServices function.
services.AddMvc().AddJsonOptions(options => options.SerializerSettings.ContractResolver = new DefaultContractResolver());

(6) To work with tag helpers below package to install
Microsoft.AspNetCore.Razor.Runtime

(7) To work with sessions user below package 
Microsoft.AspNetCore.Session

(8) Cookie Authentication
https://www.c-sharpcorner.com/article/cookie-authentication-with-asp-net-core-2-0/

(9) StaticFiles: to work with static files like images, html, js files use below  package
Microsoft.AspNet.StaticFiles

(10) It gives us access to the assemblies and classes provided by the framework.
Microsoft.AspNet.Mvc

(11) to build bundle files for css/js use below package
BuildBundlerMinifier
(1) https://marketplace.visualstudio.com/items?itemName=MadsKristensen.BundlerMinifier
(2) https://www.c-sharpcorner.com/article/bundling-and-minifying-in-asp-net-core-applications/
(3) https://docs.microsoft.com/en-us/aspnet/core/client-side/bundling-and-minification?view=aspnetcore-2.2&tabs=visual-studio

(12) When there is issue of tag is not properly rendered
- In this case, check with Taghelper is added to _ViewImport.cshtml page or not, if not then add like below
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
- https://github.com/aspnet/AspNetCore/issues/534


Friday, August 23, 2019

Validate AntiForgeryToken in Dot Net CORE MVC

To validate authentication based on AntiForgeryToken in dot net CORE MVC application, perform below steps

(1) Add below line of code to Startup.cs --> ConfigureServices
services.AddMvc(options =>
{
    options.Filters.Add(new AutoValidateAntiforgeryTokenAttribute());
});
services.AddAntiforgery(options => options.HeaderName = "Name of token in header");

(2) CSHTML: Put below line of code to view/page where we want to validate token
@Html.AntiForgeryToken()

(3) Controller Method: Put below attribute as an attribute to the method for which we want to validate token
[ValidateAntiForgeryToken]

(4) Token: once above steps get done, from your js/cshtml find token with below line of code
var token = $('[name= "__RequestVerificationToken"]').val();

(5) For ajax calls:For ajax calls put below header line of code
headers: {
                'Name of token in header': token from step-(4)
            },

Here is one reference link that I found good for me
Enable Antiforgery Token with ASP.NET Core and JQuery



Wednesday, August 21, 2019

Logging with NLog

Here are some links and tips & tricks for nLog nuget extension. Find how to work with it and additionally there are some tips to make some more change in its configuration to achieve specific needs.

ASP.NET Core Web API – Logging With NLog

Introduction to NLog

NLog: Rules and filters

- To check with configuration of file
Configuration file

- To working from code base
Configure from code

Things your Dad never told you about NLog

- Tips & Tricks
Turn off Logging during Release from Nlog.config

How to turn ON and OFF logging for specific levels in NLog

how to disable the particular log, dynamically in Nlog using C#?

- Additionally
(1) To log only Info message

<logger name="*" minlevel="Info" maxlevel="Info" writeTo="logfile" />

or

<logger levels="Info" name="*" writeTo="logfile"/>

(2) To log multiple message, below change will log messages for Error and Info and that way we can add other too
<logger levels="Info,Error" name="*" writeTo="logfile"/>

(3) To disable logging set enable to false
<logger name="*" minlevel="Debug" writeTo="logfile"  enabled="false" /
>

Wednesday, July 17, 2019

Useful NugGet Packages

Here are some useful NuGet packages that you would love to include while creating any Dot NET CORE API.

(1) gzip - Compression
Microsoft.AspNetCore.ResponseCompression
- How to enable gzip compression in ASP.NET Core


(2) swagger
Swashbuckle.AspNetCore
Swagger UI Integration With Web API For Testing And Documentation
ASP.NET Core web API help pages with Swagger / OpenAPI

(3) IP Rate Limiter
Install-Package AspNetCoreRateLimit
Rate limiting based on client IP
IpRateLimitMiddleware


(4) Logging with NLog
- ASP.NET Core Web API – Logging With NLog

(5) Firebase: To work with firebase push notifications
Install-Package FirebaseAdmin


Wednesday, June 12, 2019

MySQL Basic Operations

Here are some basic operations need to keep in mind for the MySQL beginners jumping into it from MS-SQL
- First things is, need to have MySQL Workbench to be installed for the same
- For MYSql most of the syntaxes remains same but still there are some points to note and are belows.

(1) ";" required for multiple query in batch
- For query to execute, it requires ";" at the end of statement. Also, same would be apply if there are multiple queries are there .
- for e.g.
MS-SQL - Select * From Table1
Select * From Table2
MySQL  - Select * From Table1;
Select * From Table2;

(2) Finding top item
- With respect to fetch top 1 item, here in MySQL same would be fetched by limit
- for e.g
MS-SQL - Select top 1 * from Table
MySQL  - Select * From Table limit 1;

(3) Call Stored Procedure
MS-SQL - exec procname
MySQL  - CALL `dbname`.`procname`(parameter, if any);

(4) Get Current Date
MS-SQL - GETDATE()
MySQL  - NOW()

(5) Null Check for field
MS-SQL - ISNULL(field, 'default value')
MySQL  - IFNULL(field. 'default value')

(6) If Exist: 
MS-SQL - 
If Exists(Select ID From Table Where ID = 10)
Begin
End
Else
Begin
End
MySQL
if exists(select Id from users where Id=_UserId) then

else

end If;

(7) Temporary Table
MS-SQL - There are couple of way to do so
- Temporary CREATE TABLE #TableName
(
column1 VARCHAR(50) 
)
- Global Temporary Table
SELECT column1 INTO ##TempTable

MySQL
- CREATE TEMPORARY TABLE TempTable

Saturday, May 25, 2019

DevExpress Report Basic Operations

Here are some basic operations performed with dev express reports.
(1) Display Report as LandScape

- Set report landscape property to true
this.Landscape = true;
- Set Page width
this.PageWidth = 1500;
- Define paperkind property
this.PaperKind = System.Drawing.Printing.PaperKind.LegalExtra;
- to show this report as landscapre your ReportToolbar should have width set to width that you want

(2) Access Report's controls: If there needs way where you have to load your report dynamically and before load it you want to assign/change value of your report's controls then perform below steps.
- make control public
On your report, suppose there is one label "Label1", then set its "Modifiers" property to public

- once above step is done, after your report declaration access this label below way
subReport subReporDetail = new subReport();
subReporDetail.Label1.Text = "Your Text";

- Once you are done with report control property changes then load that report dynamically and your label will be loaded with text you have set.

(3) Dynamically assign datasource: Suppose you are loading your report dynamically but before loading it you want to assign its datasource fetch from API/database then follow below steps
- define your report, subReport and datasource
XRSubreport subReport = new XRSubreport();
myDataSource dsource = new myDataSource();
myReport rpt1 = myReport();

- fetch your datasource 
DataTable dt= fetch data from API/database

- assign your service data to datasource
dsource.EnforceConstraints = false;
dsource.Tables["DataTableName"].Merge(dt);

- assign source and then load it to subreport
rpt1.DataSource = dsource.Tables["DataTableName"];
subReport.ReportSource = subReporDetail;

- Once your subreport has been bind with report and its dynamic data, load it dynamically.

(4) Add Button to ReportToolbar
- To add new button to your report toolbar, add like below way

- write client side events to button click callback
                    if (e.item.name == 'rptcustomevent') {
                        Callback1.PerformCallback(e.item.name);
                    }
                }" />
- write callback function at your javascript
$("#dashboard_menu_custom_button_id").click(function () {
... on click of above button, it will comes to here for your logic on button click
});

Friday, April 5, 2019

Add Controls dynamically to report

Here are the way by which we can add controls dynamically to report.

(1) Declare DetailReportBand and DetailBand 

DetailReportBand detailReportBand = new DetailReportBand();
DetailBand subDetailBaind = new DetailBand();

(2) Create any devexpress control you want to add. For e.g
- To load image dynamically, we can do so below way..
XRPictureBox xrPictureBox = new XRPictureBox();
xrPictureBox.Image = "image path";
xrPictureBox.Sizing = DevExpress.XtraPrinting.ImageSizeMode.ZoomImage;
xrPictureBox.SizeF = new SizeF(50, 50);
xrPictureBox.LocationFloat = new DevExpress.Utils.PointFloat(0F, 50F);

- To load pagebreak dynamically
XRPageBreak xrPageBreak = new XRPageBreak();

(3) add picture box to subDetailBand
- add picturebox dynamically
subDetailBaind.Controls.Add(xrPictureBox);

- add pagebreak dynamically
subDetailBaind.Controls.Add(xrPageBreak);

(4) add subDetailBand to detailBandReport
detailReportBand.Bands.Add(subDetailBaind);

(5) add detailReportBand to your repor
mainReport mymainReport = new mainReport();
mymainReport.Bands.Add(detailReportBand);

For this example, we have added XRPictureBox & XRPageBreak, but you can declare any DevExpress control to step - (2) and load them dynamically to your report then after performing step - (3) onwards.

Wednesday, March 27, 2019

Add DevExpress Report Dynamically

Here is the way by which we can add report dynamically to some other report. There is one report which is already there but in some case where we want to add some other report to the main report dynamically or conditionally, we can do so by below way.

(1) Main Report which is already there with some implementation but can also have any other report added to this report dynamically
mainReport mymainReport = new mainReport();

(2) Declare a subreport which is already there but need to add to above main report
XRSubreport otherReport = new XRSubreport();

(3) subrepor which need to add
subReport subReporDetail = new subReport();
... here we can perform some data manipulation for subReport and finally assign it to subreport
otherReport.ReportSource = subReporDetail;

(4) Declare a DetailReportBand and DetailBand 
DetailReportBand detailReportBand = new DetailReportBand();
DetailBand subDetailBand = new DetailBand();

(5) Assign subdetailband height and add otherReport to it
subDetailBaind.HeightF = 0;
subDetailBaind.Controls.Add(otherReport);

(6) Add subDetailBand to detailReportBand
detailReportBand.Bands.Add(subDetailBand);

(7) Finally add detailReportBand to main report which will add this report dynamically
mymainReport.Bands.Add(detailReportBand);

This way we can add report dynamically. In step - (3), If there are many reports already created and conditionally we have to load any report then in this step we can check and add required report dynamically.


Monday, March 25, 2019

Working with DevExpress Reporting

Here is some links by which you can bind your devexpress report with datasource.

(A) Devexpress Reporting: Below are link for what is devexpress reporting and its general information.
(1) Devexpress Reporting

(2) General Information


(B) Bind Report: Below are links by which we can bind report with dynamic data from database.
(1) Bind a Report to a Data Source Schema

(2) Bind a Report to a Stored Procedure

(3) Bind a Report to an MDB Database (Runtime Sample)


(C) To load report below are the steps
(1) Register your assembly to page
<%@ Register Assembly="Your DevExpress.XtraReports Assembly" Namespace="DevExpress.XtraReports.Web" TagPrefix="dx" %>

(2) Define your ReportToolbar and ReportViewer


(3) Assign your report from code
myReport rpt1 = myReport();
rtDashboard.ReportViewer = rvDashboard;
rvDashboard.Report = rptESR;

This way you will get your report loaded to the page.

Saturday, March 2, 2019

jqxGrid APIs

Here are some commands & events that are used for jqxGrid processing. Below are the list of commands that may useful.

(1) $('#jqxGrid').jqxGrid('showrowdetails', 2);
- shows details grid of index 2

(2) $('#jqxGrid').jqxGrid('hiderowdetails', 2);
- hides details grid of index 2

(3) $('#jqxGrid').jqxGrid('expandallgroups');
- expand all groups of grid

(4) $('#jqxGrid').jqxGrid('refreshdata');
- refreshes grid data

(5) $("#jqxGrid").trigger("reloadGrid")
- triggers reload event of jqxgrid

(6) $('#jqxGrid').jqxGrid('destroy');
- destroys grid

(7) $('#jqxGrid').jqxGrid('getrows')
- gets rows of jqxgrid

(8) $('#jqxGrid').jqxGrid('clearselection');
- clears selection of any row in grid

(9) $('#jqxGrid').jqxGrid('updatebounddata', 'cells');
- updates bound data of cell

(10) $("#jqxGrid").jqxGrid('cleargriddata');
- clears grid data

(11) $("#jqxGrid").jqxGrid('updatebounddata');
- update bound data

(12) $("#jqxGrid").jqxGrid('refresh');
- refreshes grid

(13) $('#jqxGrid').jqxGrid('getrowdetails', index);
- gets row details of specified "index"

(14) $("#jqxGrid").jqxGrid('getrowdata', $("#jqxGrid").jqxGrid('getselectedrowindex'));
- gets rowdata of the selected row

(15) $('#jqxGrid').jqxGrid('getselectedrowindex');
- gets row index of he selected row

(16) $("#jqxGrid").jqxGrid('setcellvalue', currRow, colName, newVal);
- sets cell value for the specified row and column with new value

(17) var position = $.jqx.position(event.args);
var cell = $("#jqxGrid").jqxGrid('getcellatposition', position.left,
position.top);
- gets cell position in grid

(18) $("#jqxGrid").jqxGrid('addrow', parseInt(newID + 1), row);
- adds new row to grid

(19) $("#jqxGrid").on("cellvaluechanged", function (event) {});
- cell value changed event

(20) $('#jqxGrid').jqxGrid('getrows').splice(1, 0, newrowdata);
- adds new row at position 1

(21) $("#jqxGrid").jqxGrid('autoresizecolumns');
- sets all column to auto resize

(22) $("#jqxGrid").jqxGrid('showcolumn', 'columnName');
- shows any column which is hidden

(23) $("#jqxGrid").jqxGrid("showcolumn", 'columnname')
- hides any column which is hidden

(24) $("#jqxGrid").jqxGrid('columns')
- fetches all column of the grid

(25) $('#jqxGrid').jqxGrid('getcolumn', 'columnname');
- gets specified column from the grid

(26) $("#jqxGrid").jqxGrid('endupdate');
- grid will have end update

(27) $('#jqxGrid').jqxGrid('getdisplayrows')
- gets display row of the grid

(28) $('#jqxGrid').on('rowselect', function (event) {});
- row select function

(29) $("#jqxGrid").on('cellendedit', function (event) {});
- cell end edit event of the grid

(30) $("#jqxGrid").jqxGrid('clearfilters');
- clears the filters of the grid

(31) $('#jqxGrid').jqxGrid('getdatainformation')
- gets data information of the grid

(32) $("#jqxGrid").jqxGrid('beginupdate');
- for the grid begin update when we want to change anything

(33) $('#jqxGrid').jqxGrid('getboundrows')
- gets bound rows in grid

(34) $('#jqxGrid').jqxGrid('selectrow', 1);
- selects row number 1 in grid

(35) $("#jqxGrid").jqxGrid('getcellvalue', row, 'columnName');
- gets cell value of any row

(36) var filtergroup = new $.jqx.filter();
var filtervalue = value to filter;
var filtercondition = 'equal';
var filter = filtergroup.createfilter('stringfilter', filtervalue, filtercondition);
- to create filter group in grid

(37) $('#jqxGrid').jqxGrid('unselectrow', rowBoundIndex);
- used to unselect selected row

(38) $("#jqxgrid").jqxGrid('showgroupsheader', false);
- To hide the grouping panel, set the 'showgroupsheader' property to false.

(39) $("#jqxgrid").jqxGrid('addgroup', 'lastname');

- The 'addgroup', 'insertgroup', 'removegroup' and 'removegroupat' functions enable groups manipulation with the Grid API. 

These API may used for some small operations we are performing for specific purpose. Some of the commands are pretty straight forward but some of them require some more information.

For more APIs Click Here




Tuesday, February 19, 2019

Bind jqxGrid With Static Data

Here is code to bind jqxGrid with static data. Static data means you have locally some data available and you want to bind it without interacting with service url.

I assume that already have necessary files for jqxGrid to work/load properly.

Html:

Script

//Data fields are responsible for columns and its type
var datafields = [
    { name: 'Column 1', type: 'string' },
    { name: 'Column 2', type: 'string' }
];

//Column Items are columns with their look and feel 
var columnItems = [
    { text: 'Column 1', datafield: 'Column 1' },
    { text: 'Column 2', datafield: 'Column 2' }
];

//Data which holds local data that you want to bind
var data = [];

//Source contains data type and datafields along with local data
var source =
{
    datatype: "xml",
    datafields: datafields,
    localdata: data
};

//Adapter holds source which contains necessary information to load data
var adapter = new $.jqx.dataAdapter(source,
{
    loadError: function (xhr, st, err) {
        ErrorMsg("Technical error occured.");
    }
});

//jqxGrid which holds above information to bind grid and show the data
$("#jqxGrid").jqxGrid(
{
    width: '100%',
    source: adapter,
    filterable: true,
    showfilterrow: true,
    sortable: true,
    pageable: false,
    autoheight: false,
    columnsresize: true,
    columnsreorder: false,
    editable: true,
    autoshowfiltericon: true,
    selectionmode: 'none',
    columns: columnItems
});

Here in source localdata is responsible for binding local data and if case of you want to fetch data from any service then just remove "localdata: data" and add "url:serviceurl" which returns dynamic data.

Tuesday, February 5, 2019

Excel Operations Using Excel Interop Assembly

Here is code to read excel file which will read file and converts its cell to specific format like date format or number format or so and then save new version of file to take effect of the new file converted with provided format and leave original file as it is.

For the excel file to read, it is 2010pia which is installed to read excel file and in reference there will be version with 15.0 for excel is used to read excel file. The link to download is below

Download Microsoft Office 2010: Primary Interop Assemblies Redistributable

Below code to read excel file using office interop excel assembly and perform changes in cell and save that file
Microsoft.Office.Interop.Excel.Application objexcel = new Microsoft.Office.Interop.Excel.Application();

objexcel.DisplayAlerts = false;

Microsoft.Office.Interop.Excel.Workbook workbook = objexcel.Workbooks.Open("your file path", Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing);

Microsoft.Office.Interop.Excel.Worksheet sheet = (Microsoft.Office.Interop.Excel.Worksheet)workbook.Sheets.get_Item(1);

rangeoutput = sheet.UsedRange;

int lastRow = sheet.Cells.SpecialCells(Microsoft.Office.Interop.Excel.XlCellType.xlCellTypeLastCell, Type.Missing).Row;

int lastColumn = sheet.Cells.SpecialCells(Microsoft.Office.Interop.Excel.XlCellType.xlCellTypeLastCell, Type.Missing).Column;

Microsoft.Office.Interop.Excel.Range oRange = (Microsoft.Office.Interop.Excel.Range)sheet.get_Range((Microsoft.Office.Interop.Excel.Range)sheet.Cells[1, 1], (Microsoft.Office.Interop.Excel.Range)sheet.Cells[lastRow, lastColumn]);

oRange.EntireColumn.AutoFit();

for (int i = 0; i < oRange.Columns.Count; i++)
{
    dt.Columns.Add("a" + i.ToString());
}

object[,] cellValues = (object[,])oRange.Value2;

object[] values = new object[lastColumn];

//Loop through the all rows of the excel file and operate to change the type of the cell
for (int i = 1; i <= lastRow; i++)
{
    //Loop through the columns and get the each cell value from rows
    for (int j = 0; j < dt.Columns.Count; j++)
    {
        //This implementation for selecting columns names from excel file
        if (i == 1)
        {
    //If you know the column name then from here set for the entire column format
            sheet.get_Range("B1").EntireColumn.NumberFormat = "dd/MM/yyyy";
        }
        else
        {
    //if entire column format is not get set then go with this else part where if you know the cell index then go with it
            if (j == 13)
            {
//for me it was date operation to perform and i checked statically with 13 which when comes picks the value for cell and convert it
                string str = Convert.ToString(cellValues[i, j + 2]);
                DateFormat numFormat = strColumns.Where(x => x.ColumnIndex == j + 2).FirstOrDefault();
                if (!string.IsNullOrWhiteSpace(str))
                {
                    double dblResult = 0;
                    bool blnIsDbl = double.TryParse(str, out dblResult);
                    if (blnIsDbl)
                    {
(rangeoutput.Cells[i, j + 2] as Microsoft.Office.Interop.Excel.Range).NumberFormat = numFormat.ColumnFormat;
                        double d = double.Parse(str);
                        DateTime conv = DateTime.FromOADate(d);
                        values[j] = conv.ToShortDateString();// cellValues[i, j + 1];
                        string strNewValue = conv.ToString(numFormat.ColumnFormat);
                        (rangeoutput.Cells[i, j + 2] as Microsoft.Office.Interop.Excel.Range).Value = strNewValue;
                        (rangeoutput.Cells[i, j + 2] as Microsoft.Office.Interop.Excel.Range).Value2 = strNewValue;
                    }
                    else
                    {
                        //if cell value are correct then fine but if it is wrong then here in else part checking its value then if it is wrong then keep it as it is
                        try
                        {
                            DateTime dt1;
                            bool IsValidDate = DateTime.TryParseExact(str, numFormat.ColumnFormat, null, DateTimeStyles.None, out dt1);
                            if (IsValidDate)
                            {
                                string strNewValue = dt1.ToString(numFormat.ColumnFormat);
                                (rangeoutput.Cells[i, j + 2] as Microsoft.Office.Interop.Excel.Range).Value = strNewValue;
                                (rangeoutput.Cells[i, j + 2] as Microsoft.Office.Interop.Excel.Range).Value2 = strNewValue;
                            }
                            else
                            {
                                (rangeoutput.Cells[i, j + 2] as Microsoft.Office.Interop.Excel.Range).Value = str;
                                (rangeoutput.Cells[i, j + 2] as Microsoft.Office.Interop.Excel.Range).Value2 = str;
                                intInvalidRows.Add(i);
                            }
                        }
                        catch (Exception Exc)
                        {
                            Exc.Message.ToString();
                            (rangeoutput.Cells[i, j + 2] as Microsoft.Office.Interop.Excel.Range).Value = str;
                            (rangeoutput.Cells[i, j + 2] as Microsoft.Office.Interop.Excel.Range).Value2 = str;
                        }
                    }
                }
            }
        }
    }
}

//Saves the changed excel file and then closes the file along with current workbook
objexcel.DisplayAlerts = false;

objexcel.ActiveWorkbook.SaveAs(Filename: "file path to save", FileFormat: Microsoft.Office.Interop.Excel.XlFileFormat.xlWorkbookDefault, CreateBackup: false);

objexcel.ActiveWorkbook.Close(SaveChanges: false);

objexcel.DisplayAlerts = true;

objexcel.Quit();

There are multiple operations has been performed here like opening file/changing file content/assigning cell format/save file using Excel Interop Assembly.