Download data as Excel file using web api and angular JS - javascript

I have a scenario to download file from the web app that uses a) Angular JS as front end b) Web api as server and the browser is IE9.
I have tried lot of plugins for converting HTML table to excel,csv but none of them worked for IE9.So i have decided generate the file in web api and download in the client.But that too does not work.
Can any one share an working example for this scenario ?
Angular JS Code:
var app = angular.module('myApp', []);
app.controller('myCtrl', function ($scope, exportToExcelService) {
$scope.export = function () {
exportToExcelService.download().success(
function (response) {
})
.error(function (response, status) {
});
}
}).
factory('exportToExcelService', function ($http) {
var sampleAPI = {};
sampleAPI.download = function () {
return $http({
method: 'POST',
url: 'api/Sample/download'
});
}
return sampleAPI;
});
Web APi Controller code:
[HttpPost]
public HttpResponseMessage download()
{
List<Record> obj = new List<Record>();
obj = RecordInfo();
StringBuilder str = new StringBuilder();
str.Append("<table border=`" + "1px" + "`b>");
str.Append("<tr>");
str.Append("<td><b><font face=Arial Narrow size=3>FName</font></b></td>");
str.Append("<td><b><font face=Arial Narrow size=3>LName</font></b></td>");
str.Append("<td><b><font face=Arial Narrow size=3>Address</font></b></td>");
str.Append("</tr>");
foreach (Record val in obj)
{
str.Append("<tr>");
str.Append("<td><font face=Arial Narrow size=" + "14px" + ">" + val.FName.ToString() + "</font></td>");
str.Append("<td><font face=Arial Narrow size=" + "14px" + ">" + val.LName.ToString() + "</font></td>");
str.Append("<td><font face=Arial Narrow size=" + "14px" + ">" + val.Address.ToString() + "</font></td>");
str.Append("</tr>");
}
str.Append("</table>");
HttpResponseMessage result = null;
// serve the file to the client
result = Request.CreateResponse(HttpStatusCode.OK);
byte[] array = Encoding.ASCII.GetBytes(str.ToString());
MemoryStream mem = new MemoryStream(array);
result.Content = new StreamContent(mem);
result.Content.Headers.ContentType = new MediaTypeHeaderValue("application/vnd.ms-excel");
result.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
{
FileName = "Data.xls"
};
return result;
}
public List<Record> RecordInfo()
{
List<Record> recordobj = new List<Record>();
recordobj.Add(new Record { FName = "Smith", LName = "Singh", Address = "Knpur" });
recordobj.Add(new Record { FName = "John", LName = "Kumar", Address = "Lucknow" });
recordobj.Add(new Record { FName = "Vikram", LName = "Kapoor", Address = "Delhi" });
recordobj.Add(new Record { FName = "Tanya", LName = "Shrma", Address = "Banaras" });
recordobj.Add(new Record { FName = "Malini", LName = "Ahuja", Address = "Gujrat" });
recordobj.Add(new Record { FName = "Varun", LName = "Katiyar", Address = "Rajasthan" });
recordobj.Add(new Record { FName = "Arun ", LName = "Singh", Address = "Jaipur" });
recordobj.Add(new Record { FName = "Ram", LName = "Kapoor", Address = "Panjab" });
return recordobj;
}

I found the solution by using the following code and it works like a charm.We just need to add window.location.href.
app.controller('myCtrl', function ($scope, exportToExcelService,$location) {
$scope.export = function () {
exportToExcelService.download().success(
function (response) {
window.location.href = 'api/sample/download'
})
.error(function (response, status) {
var str = 'Hello'
});
}
}).

Related

MVC Partial View Not Displaying Image

I have a Kendo Grid where one of the columns is actually a link to open a pop up to view the image. I'm able to get the image back but I'm unsuccessful so far. Here is what I have so far-
Controller-
public ActionResult OpenImagePopUp(int? id)
{
Help request2 = new Help();
request2.id = id;
var response = apiHelp.GetHelpRecords(request2);
if (response.Error != null)
{
ErrorLogRequest errorReq = new ErrorLogRequest()
{
LogDate = DateTime.Now,
LogMethod = "GetHelpRecords",
LogPage = "Canopy Help",
LogPerson = User.Identity.Name,
LogInfo = response.Error.ErrorCode + " " + response.Error.ErrorMessage + " " + response.Error.ExceptionObject.Message
};
apiErrorLog.InsertErrorLog(errorReq);
}
var helpRecords = response.data.Select(s => new Help()
{
Image = s.Image
}).FirstOrDefault();
var base64string = Convert.ToBase64String(helpRecords.Image);
request2.ImgSrcBase64 = String.Format("data:image/gif;base64,{0}", base64string);
return PartialView("ImagePopUp", request2);
}
My View / Javascript -
<div>
#(Html.Kendo().Window()
.Name("ImagePopUp")
//.LoadContentFrom("OpenPopUpWindow", "BlueButtonView")
.Draggable()
.Actions(actions => actions.Close())
.Modal(true).Visible(false)
.HtmlAttributes(new { style = "margin: 10px" })
.LoadContentFrom("OpenImagePopUp", "Help")
.Draggable()
.Resizable()
.Width(600)
.Actions(actions => actions.Close())
)
</div>
function showImage(e) {
var grid = $("#CanopyHelpGrid").getKendoGrid();
var item = grid.dataItem($(e.target).closest("tr"));
$("#ImagePopUp").data("kendoWindow").open().center(true);
$.ajax({
datatype: "image",
type: "GET",
url: '#Url.Action("OpenImagePopUp", "Help")',
data: { id: item.id },
success: function (data) {
//$("#imgPopUp").attr('src', data);
}
})
}
Then finally my partial view -
#model OSH.Domain.Models.CanopyHelp.Help
<img id="imgPopUp" alt="Image" src='#Model.ImgSrcBase64'>
I tried to convert the array to a base64 string then format it to be the image source but I keep seeing no image.
As Stephen have suggested, adding this to my ajax solved the problem!
$.ajax({
datatype: "html",
type: "GET",
url: '#Url.Action("OpenImagePopUp", "Help")',
data: { id: item.id },
success: function (html) {
$("#ImagePopUp").html(html);
$("#ImagePopUp").data("kendoWindow").open().center(true);
}
})
I also made my controller return html content instead and removed the image tag on my partial view-
public ActionResult OpenImagePopUp(int? id)
{
if (id != null)
{
string html = string.Empty;
Help request2 = new Help();
request2.id = id;
var response = apiHelp.GetHelpRecords(request2);
if (response.Error != null)
{
ErrorLogRequest errorReq = new ErrorLogRequest()
{
LogDate = DateTime.Now,
LogMethod = "GetHelpRecords",
LogPage = "Canopy Help",
LogPerson = User.Identity.Name,
LogInfo = response.Error.ErrorCode + " " + response.Error.ErrorMessage + " " + response.Error.ExceptionObject.Message
};
apiErrorLog.InsertErrorLog(errorReq);
}
var helpRecords = response.data.Select(s => new Help()
{
id = s.id,
Image = s.Image
}).Where(w => w.id == id).FirstOrDefault();
if (helpRecords.Image != null)
{
var base64string = Convert.ToBase64String(helpRecords.Image);
request2.ImgSrcBase64 = string.Format("data:image/gif;base64,{0}", base64string);
html = string.Format("<img id='imgPopUp' src='{0}' alt='Image'/>", request2.ImgSrcBase64);
return Content(html, "text/html");
}
else
{
html = "<h4>This record has no image attached!</h4>";
return Content(html, "text/html");
}
}
else return new EmptyResult();
}

Node.js shortened url

I have just started learning to code about 5 days ago and what I'm struggling to achieve, is to have an rssfeed-to-twitter script that posts a shortened url instead of a full website/article feed url. I found a node.js module called TinyURL that could do that but i struggle to get it to work. Here's the full script:
var simpleTwitter = require('simple-twitter');
var fs = require('fs');
var http = require('http');
http.createServer(function (req, res) {
res.writeHead(200, {'Content-Type' : 'text/plain'});
res.end('RSS Twitter Bot\n');
}).listen(5693);
var timeInterval = 300000; // run every 30m
var timerVar = setInterval (function () {runBot()}, timeInterval);
function runBot(){
var lastCompleted = Date.parse(new Date(0));
console.log(lastCompleted);
try {
var lastcompletedData = fs.readFileSync('./lastCompleted.json', 'utf8');
var timeData = JSON.parse(lastcompletedData);
var lastCompletedFromFile = Date.parse(new Date(timeData.lastCompleted));
if ( isNaN(lastCompletedFromFile) == false ) {
lastCompleted = lastCompletedFromFile;
}
} catch (e) {
console.log(e);
}
fs.readFile('./config.json', 'utf8', function (err, data) {
if (err) console.log(err); // we'll not consider error handling for now
var configData = JSON.parse(data);
console.log(configData);
var twitter = new simpleTwitter( configData.consumerKey //consumer key from twitter api
, configData.consumerSecret //consumer secret key from twitter api
, configData.accessToken //access token from twitter api
, configData.accessTokenSecret //access token secret from twitter api
, 3600);
var dateNow = Date.parse(new Date());
var FeedParser = require('feedparser');
var request = require('request');
var req = request(configData.feedUrl);
var feedparser = new FeedParser();
req.on('error', function (error) {
console.log(error);
});
req.on('response', function (res){
var stream = this;
if (res.statusCode != 200 ) return this.emit('error', new Error('Bad status code'));
stream.pipe(feedparser);
});
feedparser.on('error', function(error) {
console.log(error);
});
feedparser.on('readable', function() {
var stream = this;
var meta = this.meta;
var item;
while (item = stream.read()) {
var itemDate = Date.parse(item.date);
//check to not publish older articles
if (itemDate > lastCompleted){
var titleLength = item.title.length;
var itemTitle = item.title;
var itemLink = item.link;
if (titleLength > 100) {
itemTitle = itemTitle.substring(0, 100);
}
twitter.post('statuses/update'
, {'status' : itemTitle + ' ' + itemLink + " " + configData.tags}
, function (error, data) {
console.dir(data);
});
console.log(itemTitle + ' ' + item.link + configData.tags);
}
}
//TO KNOW WHEN FROM TO START POSTING
var dateCompleted = new Date();
console.log('loop completed at ' + dateCompleted);
var outputData = {
lastCompleted : dateCompleted
}
var outputFilename = './lastCompleted.json';
fs.writeFile(outputFilename, JSON.stringify(outputData, null, 4), function(err) {
if(err) {
console.log(err);
} else {
console.log("JSON saved to " + outputFilename);
}
});
});
});
}
And this is the TinyURL node.js module
var TinyURL = require('tinyurl');
TinyURL.shorten('http://google.com', function(res) {
console.log(res); //Returns a tinyurl
});
Changing the 'http://google.com' string to itemLink var works just fine and prints it in the terminal as expected.
TinyURL.shorten(itemLink, function(res) {
console.log(res); //Returns a tinyurl
});
What i'm trying to achieve is:
twitter.post('statuses/update', {'status' : itemTitle + ' ' + tinyurlLink + " " + configData.tags}
How can i get the response turned into a e.g var tinyurlLink to replace the itemLink var? Any help would be much appreciated!
As suggested by #zerkms sending a tweet from inside the TinyURL.shorten worked!

Saving Javascript objects to Chrome.Storage

This code for a Google Chrome Extension doesn't work. I am new to Javascript and I am not sure what the problem is. Any help would be greatly appreciated.
JS/jQuery
var userV = serviceName + 'Username';
var passV = serviceName + 'Password';
boolean works = true;
var User = {
passV: password,
userV: username,
works = true;
}
chrome.storage.sync.set({User : userV}, function() {
console.log('');
});
chrome.storage.sync.set({User : passV }, function() {
console.log('');
});
Script
chrome.storage.sync.get("userV", function (User) {
sUsername = User.userV;
};
chrome.storage.sync.get("passV", function (User) {
sPassword = User.passV;
};
Thank you for any help.
In your code you are storing User and Password in the same Key Name hence you will get only Last assigned value,
as well as your retrieving the value by value not by key
JS/jQuery
var userV = serviceName + 'Username';
var passV = serviceName + 'Password';
boolean works = true;
var User = {
passV: password,
userV: username,
works = true;
}
chrome.storage.sync.set({User : userV}, function() {
console.log('');
});
chrome.storage.sync.set({Pass : passV }, function() {
console.log('');
});
Script
chrome.storage.sync.get("User", function (data) {
sUsername = data.User;
};
chrome.storage.sync.get("Pass", function (data) {
sPassword = data.Pass;
};
For more simplify, you can store the whole User object into the storage. When you want to store your user data, the code is like the following:
var userV = serviceName + 'Username';
var passV = serviceName + 'Password';
boolean worksV = true;
var user = {
password: passV,
username: userV,
works: worksV
};
chrome.storage.sync.set({"user" : user}, function() {
// Do something...
});
Then, when you want to retrieve the stored data, the code is:
chrome.storage.sync.get("user", function(data) {
var user = data.user;
var passV = user.password;
var userV = user.username;
var worksV = user.works;
// Do something...
});
I think that you don't need to store each data item as each property. I recommend that it will be stored as one object.

Handlebars.js - Combining Templates

Each section of my code below creates a new handlebars.js template to call the "User Behance API". As you can see, each section has similar code, with a variable or two difference.
Is there a way to clean up this code, and combine these separate functions into one? Just seems like a lot of code, but then again I am new to handlebars.
// BEHANCE API INFO ---
var apiKey = 'ZLBxK9rEfHwJf9K0rmseNr2fS2gS2HJW';
var userID = 'creativemints';
var perPage = 10;
var behanceUserAPI = 'http://www.behance.net/v2/users/' + userID + '?callback=?&api_key=' + apiKey;
var behanceProjectAPI = 'http://www.behance.net/v2/users/' + userID + '/projects?callback=?&api_key=' + apiKey + '&per_page=' + perPage;
// BEHANCE - USER HEADER ---
(function () {
function setUserTemplate() {
var userData = JSON.parse(sessionStorage.getItem('behanceUser')),
getTemplate = $('#userHead').html(),
template = Handlebars.compile(getTemplate),
result = template(userData);
$('header').html(result);
}
if (sessionStorage.getItem('behanceUser')) {
setUserTemplate();
} else {
$.getJSON(behanceUserAPI, function (user) {
var data = JSON.stringify(user);
sessionStorage.setItem('behanceUser', data);
setUserTemplate();
});
}
})();
// BEHANCE - USER ABOUT ---
(function () {
function setUserTemplate() {
var userData = JSON.parse(sessionStorage.getItem('behanceUser')),
getTemplate = $('#userAbout').html(),
template = Handlebars.compile(getTemplate),
result = template(userData);
$('.about').html(result);
}
if (sessionStorage.getItem('behanceUser')) {
setUserTemplate();
} else {
$.getJSON(behanceUserAPI, function (user) {
var data = JSON.stringify(user);
sessionStorage.setItem('behanceUser', data);
setUserTemplate();
});
}
})();
// BEHANCE - USER FOOTER ---
(function () {
function setUserTemplate() {
var userData = JSON.parse(sessionStorage.getItem('behanceUser')),
getTemplate = $('#userFoot').html(),
template = Handlebars.compile(getTemplate),
result = template(userData);
$('footer').html(result);
}
if (sessionStorage.getItem('behanceUser')) {
setUserTemplate();
} else {
$.getJSON(behanceUserAPI, function (user) {
var data = JSON.stringify(user);
sessionStorage.setItem('behanceUser', data);
setUserTemplate();
});
}
})();
// BEHANCE - USER COPYRIGHT ---
(function () {
function setUserTemplate() {
var userData = JSON.parse(sessionStorage.getItem('behanceUser')),
getTemplate = $('#userCopyright').html(),
template = Handlebars.compile(getTemplate),
result = template(userData);
$('#copyright').html(result);
}
if (sessionStorage.getItem('behanceUser')) {
setUserTemplate();
} else {
$.getJSON(behanceUserAPI, function (user) {
var data = JSON.stringify(user);
sessionStorage.setItem('behanceUser', data);
setUserTemplate();
});
}
})();
Haven't tested this but you should be able to simply the code to something similar to this
// BEHANCE API INFO ---
var apiKey = 'ZLBxK9rEfHwJf9K0rmseNr2fS2gS2HJW';
var userID = 'creativemints';
var perPage = 10;
var behanceUserAPI = 'http://www.behance.net/v2/users/' + userID + '?callback=?&api_key=' + apiKey;
var behanceProjectAPI = 'http://www.behance.net/v2/users/' + userID + '/projects?callback=?&api_key=' + apiKey + '&per_page=' + perPage;
// BEHANCE - USER HEADER ---
(function () {
function setUserTemplate(templateSelector, htmlSelector) {
var userData = JSON.parse(sessionStorage.getItem('behanceUser')),
getTemplate = $(templateSelector).html(),
template = Handlebars.compile(getTemplate),
result = template(userData);
$(htmlSelector).html(result);
}
if (!sessionStorage.getItem('behanceUser')) {
$.getJSON(behanceUserAPI, function (user) {
var data = JSON.stringify(user);
sessionStorage.setItem('behanceUser', data);
});
}
setUserTemplate('#userHead','header');
setUserTemplate('#userAbout','.about');
setUserTemplate('#userFoot','footer');
setUserTemplate('#userCopyright','#copyright');
})();

angularjs post data to mvc controller in json format with multiple arrays

I am working on a project in which I have used angularjs and mvc.I am passing data from angular js controller to my mvc controller by $http.post().For now I am using single object/json array to retreive data like this -public bool UpdateIssueDetails(IssueBO issue).But I want that if I could do like this public public bool UpdateIssueDetails(IssueBO issue,List lstMembersToNotify).I want to send two json arrays from ny angular js controller to my above mvc controller method.
angularjs controller code
$scope.saveIssueDetails = function (issue) {
var milestoneId = "";
var milestoneName = "";
if ($scope.selectedIssue.Milestone== undefined) {
milestoneId = "";
milestoneName = "";
} else {
milestoneId = $scope.selectedIssue.Milestone.Id;
milestoneName = $scope.selectedIssue.Milestone.Name;
}
var arrMembersToNotify = [];
var arrMembersToNotifyNew = [];
var iCount = 0;
$("#membersToNotify input[type=checkbox]:checked").each(function () {
arrMembersToNotify = $(this).val().split("~");
arrMembersToNotifyNew.push({ "UserId": arrMembersToNotify[0], "UserDisplayName": arrMembersToNotify[1], "Email": arrMembersToNotify[2] });
});
var issueDetails =
{
Id: issue.Id,
ProjectId: issue.ProjectId,
ProjectName: issue.ProjectName,
IssueStatusId: $scope.selectedIssue.Status.Id,
StatusName: $scope.selectedIssue.Status.Name,
IssuePriorityId: $scope.selectedIssue.Priority.Id,
PriorityName: $scope.selectedIssue.Priority.Name,
AssignedUserId: $scope.selectedIssue.AssignedTo.Id,
AssigneeDisplayName: $scope.selectedIssue.AssignedTo.DisplayName,
IssueCategoryId: $scope.selectedIssue.Category.Id,
CategoryName: $scope.selectedIssue.Category.Name,
DueDate: $scope.selectedIssue.DueDate,
OwnerUserId: $scope.selectedIssue.OwnedBy.Id,
OwnerDisplayName: $scope.selectedIssue.OwnedBy.DisplayName,
IssueTypeId: $scope.selectedIssue.Type.Id,
IssueTypeName: $scope.selectedIssue.Type.Name,
IssueResolutionId: $scope.selectedIssue.Resolution.Id,
ResolutionName: $scope.selectedIssue.Resolution.Name,
MilestoneId: milestoneId,
MilestoneName: milestoneName,
Estimation: $scope.selectedIssue.Estimation,
Progress: $scope.selectedIssue.Progress,
};
var url = window.location.protocol + '//' + window.location.host + '/api/Issues' + '/UpdateIssueDetails/';
$http.post(url, [issueDetails, arrMembersToNotifyNew]).success(function (data, status, headers, config) {
if (data != '' || data.length >= 0 || data == true) {
//$scope.selectedIssue = issue;
//$scope.showIssueDetails($scope.selectedIssue);
$scope.GetAssignedIssues();
}
else if (data == '' || data == false) {
$scope.selectedIssue = null;
} else {
$scope.errors.push(data.error);
}
});
};
mvc controller code
[HttpPost]
[AuthenticationRequired]
public bool UpdateIssueDetails(IssueBO issue,List<IssueNotification> lstMembersToNotify)
{
try
{
//var issueDetails = JsonConvert.DeserializeObject<Dictionary<string, dynamic>>(issueAllDetails[0].ToString());
//List<Dictionary<string, string>> membersToNotifyDetails = JsonConvert.DeserializeObject<List<Dictionary<string, string>>>(issueAllDetails[1].ToString());
var membersToNotify = lstMembersToNotify.Select(membersToNotifyDetail =>
new IssueNotification()
{
UserId =membersToNotifyDetail.UserId,
Email =
membersToNotifyDetail.Email,
UserDisplayName =
membersToNotifyDetail.UserDisplayName
}).ToList();
var newIssue = new IssueBO
{
OwnerUserId = issue.OwnerUserId,
OwnerDisplayName = issue.OwnerDisplayName,
LastUpdatedUserId = SessionItems.UserId,
LastUpdaterDisplayName = SessionItems.DisplayName,
LastUpdatedOn = DateTime.Now,
ProjectId = issue.ProjectId,
ProjectName = issue.ProjectName,
Id = issue.Id,
AssignedUserId = issue.AssignedUserId,
AssigneeDisplayName = issue.AssigneeDisplayName,
IssueStatusId = issue.IssueStatusId,
StatusName = issue.StatusName,
Progress = issue.Progress,
IssuePriorityId = issue.IssuePriorityId,
PriorityName = issue.PriorityName,
IssueTypeId = issue.IssueTypeId,
IssueTypeName = issue.IssueTypeName,
IssueCategoryId = issue.IssueCategoryId,
CategoryName = issue.CategoryName,
IssueResolutionId = issue.IssueResolutionId,
ResolutionName = issue.ResolutionName,
DueDate = issue.DueDate,
Estimation = issue.Estimation,
MilestoneId = issue.MilestoneId,
MilestoneName = issue.MilestoneName
};
var result = BLL.AdminLayer.UpdateIssueDetail(newIssue, membersToNotify);
return result.IsSuccessful && result.Result;
}
catch (Exception ex)
{
BLL.Base.BaseLayer.WriteApplicationLog(ex);
return false;
}
}
I am passing two json array from my angularjs controller like this-$http.post(url, [issueDetails, arrMembersToNotifyNew]).success(function (data, status, headers, config).But I am getting error trying this.Please suggest how to achieve this.Thanks
You need to pass data to the action by using JSON.stringify()
$http.post(url, JSON.stringify({ issue: issueDetails,
lstMembersToNotify: arrMembersToNotifyNew
});
Post it as properties of an object.
$http.post(url, { issue: issueDetails, lstMembersToNotify: arrMembersToNotifyNew });

Categories