Angular export Excel client side - excel

I'm using Angular v4, i guess how can I build an Excel spreadsheet starting from an object in a component. I need to download the Excel file on the click of a button and I have to do this client side. I have a json file composed of arrays and I need to transfer this on an excel file, possibly customizable in style. Is it possible? If yes, how?
Edit:
No js libraries please, need to do this with Typescript and Angular

yourdata= jsonData
ConvertToCSV(objArray) {
var array = typeof objArray != 'object' ? JSON.parse(objArray) : objArray;
var str = '';
var row = "";
for (var index in objArray[0]) {
//Now convert each value to string and comma-separated
row += index + ',';
}
row = row.slice(0, -1);
//append Label row with line break
str += row + '\r\n';
for (var i = 0; i < array.length; i++) {
var line = '';
for (var index in array[i]) {
if (line != '') line += ','
line += array[i][index];
}
str += line + '\r\n';
}
return str;
}
in your html:
<button (click)="download()">export to excel</button>
in component:
download(){
var csvData = this.ConvertToCSV(yourdata);
var a = document.createElement("a");
a.setAttribute('style', 'display:none;');
document.body.appendChild(a);
var blob = new Blob([csvData], { type: 'text/csv' });
var url= window.URL.createObjectURL(blob);
a.href = url;
a.download = 'User_Results.csv';/* your file name*/
a.click();
return 'success';
}
Hope you it will help you

Vishwanath answer was working for me when i replaced "," with ";". In Typescript the implementation could look like this:
ConvertToCSV(objArray: any) {
const array = typeof objArray !== 'object' ? JSON.parse(objArray) : objArray;
let str = '';
let row = '';
for (const index of Object.keys(objArray[0])) {
row += `${index};`;
}
row = row.slice(0, -1);
str += `${row}\r\n`;
for (let i = 0; i < array.length; i++) {
let line = '';
for (const index of Object.keys(array[i])) {
if (line !== '') {
line += ';';
}
line += array[i][index];
}
str += `${line}\r\n`;
}
return str;
}
I hope this helps someone.

I think you will not get that done without js libraries in the background. What you need are the typings for utilizing it in your Angular project with typescript.
For creating an excel file you could use something like exceljs. To use it in your project also install the typings you can find here. I am not sure if this library fits... haven't used it before.
For downloading you should use FileSaver.js (I have already used it).
npm install file-saver --save
... and the typings:
npm install #types/file-saver --save-dev
For using FileSaver.js put the following import to your component:
import * as FileSaver from 'file-saver';
To trigger the download use that:
FileSaver.saveAs(fileData, "filename.xlsx")
'fileData' has to be a Blob.
Hope this helps a little.

it not is possible.
XLS is a binary format.
The project Apache POI(https://en.wikipedia.org/wiki/Apache_POI) name class as HSSF (Horrible SpreadSheet Format).
my recommendation, make it in server side.

Related

suggest npm packages for Array to excel in Nodejs

All,
I have two simple arrays as below and want to dump the data in to excel in Nodejs. Please suggest a good npm packages for the same.
var Headers = ['ChangeId', 'ChangeDescription', 'ChangeDate', 'Enhancement/Fix', 'ExcutorTeam'];
var Data = ['INC1234', 'Multiple Cert cleanup', '04/07/2022', 'Enhancement', 'IlevelSupport'];
You can use xlsx npm package and do something like this
This is a quick example that works, things could be improved but it will at least give you a starting point
const xlsx = require('xlsx');
let Headers = ['ChangeId', 'ChangeDescription', 'ChangeDate', 'Enhancement/Fix', 'ExcutorTeam'];
let Data = ['INC1234', 'Multiple Cert cleanup', '04/07/2022', 'Enhancement', 'IlevelSupport'];
let workbook = xlsx.utils.book_new();
let worksheet = xlsx.utils.aoa_to_sheet([]);
xlsx.utils.book_append_sheet(workbook, worksheet);
xlsx.utils.sheet_add_aoa(worksheet, [Headers], { origin: 'A1' });
xlsx.utils.sheet_add_aoa(worksheet, [Data], { origin: 'A2' });
xlsx.writeFile(workbook, "Test.xlsx");
CSV format is just comma separated string with new lines. With that in mind we want to create a string that has the format:
ChangeId,ChangeDescription,ChangeDate,Enhancement/Fix,ExcutorTeam
INC1234,Multiple Cert cleanup,04/07/2022,Enhancement,IlevelSupport
We can iterate over Data in Headers.length sized chunks:
const numColumns = Headers.length;
let file = `${Headers.join(",")}\n`;
for (let i = 0; i < Data.length; i += numColumns) {
file += `${Data.slice(i, i + numColumns).join(",")}\n`;
}
fs.writeFileSync("file.csv", file);
Hope that gets you started in the right direction.

Problem Utf-8 decoding nodejs - Invalid continuation byte at readContinuationByte

I'm developping a nodejs server and i want to convert a csv file to a json file. I succeed this part, but on of my data ( the libelle_etape is not on a good format (utf8), the values are like: 'EII/MEA 5ème année' or 'Geau/STE 4ème année' etc...). So in my function i would like to decode those values to have the right format on my json file.
I have the result that i want when i do :
const result= utf8.decode(str)
BUT the problem is : when i want to remplace the old String that i have in my csv file (this one : "EII/MEA 5ème année") by the good one (result = "EII/MEA 5ème année") I have the following error :
*Unhandled rejection Error: Invalid continuation byte
at readContinuationByte *
The entire code is :
CSVToJSON()
.fromFile('./infoEtu.csv')
.then((source) => {
const oneData = source[0];
for (let i = 0; i < source.length; i++) {
for (let j = 0; j < Object.keys(source[i]).length; j++) {
const columnName = Object.keys(source[i]);
columnName.forEach((element) => {
if (element == 'Libelle_etape') {
const str = source[i]['Libelle_etape'];
const result = utf8.decode(str);
console.log(result); // this line show me the good result
source[i]['Libelle_etape'] = String(result); // this line is definitely the problem , i've tried with and withou de String() methods but it's the same error
}
});
}
}
const data = JSON.stringify(source);
FileSystem.writeFileSync('./jsonEtu.json', data);
});
Thank you in advance for your help, i'm searching for a long time now and i can find the same problem anywhere.
UPDATE :
The problem was because of the accents !
By doing that it's working :
const result = accents.remove(utf8.decode(str));
source[i]['Libelle_etape'] = result;

How to get known Windows folder path with Node

I need to access per-machine configuration data in my Node application running on Windows. I've found this documentation for how to find the location:
Where Should I Store my Data and Configuration Files if I Target Multiple OS Versions?
So, in my case, I would like to get the path for CSIDL_COMMON_APPDATA (or FOLDERID_ProgramData). However, the examples are all in C, and I would prefer to not have to write a C extension for this.
Is there any other way to access these paths from Node, or should I just hardcode them?
After doing a bit of research, I've found that it's possible to call the relevant Windows API proc. (SHGetKnownFolderPath) to get these folder locations, see docs at: https://msdn.microsoft.com/en-us/library/windows/desktop/bb762188(v=vs.85).aspx.
We call the APi using the FFI npm module: https://www.npmjs.com/package/ffi.
It is possible to find the GUIDs for any known folder here:
https://msdn.microsoft.com/en-us/library/windows/desktop/dd378457(v=vs.85).aspx
Here is a script that finds the location of several common folders,
some of the code is a little hacky, but is easily cleaned up.
const ffi = require('ffi');
const ref = require('ref');
const shell32 = new ffi.Library('Shell32', {
SHGetKnownFolderPath: ['int', [ ref.refType('void'), 'int', ref.refType('void'), ref.refType(ref.refType("char"))]]
});
function parseGUID(guidStr) {
var fields = guidStr.split('-');
var a1 = [];
for(var i = 0; i < fields.length; i++) {
var a2 = [...Buffer.from(fields[i], 'hex')];
if (i < 3) a2 = a2.reverse();
a1 = a1.concat(a2);
}
return new Buffer(a1);
}
function getWindowsKnownFolderPath(pathGUID) {
let guidPtr = parseGUID(pathGUID);
guidPtr.type = ref.types.void;
let pathPtr = ref.alloc(ref.refType(ref.refType("void")));
let status = shell32.SHGetKnownFolderPath(guidPtr, 0, ref.NULL, pathPtr);
if (status !== 0) {
return "Error occurred getting path: " + status;
}
let pathStr = ref.readPointer(pathPtr, 0, 200);
return pathStr.toString('ucs2').substring(0, (pathStr.indexOf('\0\0') + 1)/2);
}
// See this link for a complete list: https://msdn.microsoft.com/en-us/library/windows/desktop/dd378457(v=vs.85).aspx
const WindowsKnownFolders = {
ProgramData: "62AB5D82-FDC1-4DC3-A9DD-070D1D495D97",
Windows: "F38BF404-1D43-42F2-9305-67DE0B28FC23",
ProgramFiles: "905E63B6-C1BF-494E-B29C-65B732D3D21A",
Documents: "FDD39AD0-238F-46AF-ADB4-6C85480369C7"
}
// Enumerate common folders.
for(let [k,v] of Object.entries(WindowsKnownFolders)) {
console.log(`${k}: `, getWindowsKnownFolderPath(v));
}

Write a line into a .txt file with Node.js

I want to use Node.js to create a simple logging system which prints a line before the past line into a .txt file. However, I don't know how the file system functionality from Node.js works.
Can someone explain it?
Inserting data into the middle of a text file is not a simple task. If possible, you should append it to the end of your file.
The easiest way to append data some text file is to use build-in fs.appendFile(filename, data[, options], callback) function from fs module:
var fs = require('fs')
fs.appendFile('log.txt', 'new data', function (err) {
if (err) {
// append failed
} else {
// done
}
})
But if you want to write data to log file several times, then it'll be best to use fs.createWriteStream(path[, options]) function instead:
var fs = require('fs')
var logger = fs.createWriteStream('log.txt', {
flags: 'a' // 'a' means appending (old data will be preserved)
})
logger.write('some data') // append string to your file
logger.write('more data') // again
logger.write('and more') // again
Node will keep appending new data to your file every time you'll call .write, until your application will be closed, or until you'll manually close the stream calling .end:
logger.end() // close string
Note that logger.write in the above example does not write to a new line. To write data to a new line:
var writeLine = (line) => logger.write(`\n${line}`);
writeLine('Data written to a new line');
Simply use fs module and something like this:
fs.appendFile('server.log', 'string to append', function (err) {
if (err) return console.log(err);
console.log('Appended!');
});
Step 1
If you have a small file
Read all the file data in to memory
Step 2
Convert file data string into Array
Step 3
Search the array to find a location where you want to insert the text
Step 4
Once you have the location insert your text
yourArray.splice(index,0,"new added test");
Step 5
convert your array to string
yourArray.join("");
Step 6
write your file like so
fs.createWriteStream(yourArray);
This is not advised if your file is too big
I created a log file which prints data into text file using "Winston" logger. The source code is here below,
const { createLogger, format, transports } = require('winston');
var fs = require('fs')
var logger = fs.createWriteStream('Data Log.txt', {
flags: 'a'
})
const os = require('os');
var sleep = require('system-sleep');
var endOfLine = require('os').EOL;
var t = ' ';
var s = ' ';
var q = ' ';
var array1=[];
var array2=[];
var array3=[];
var array4=[];
array1[0] = 78;
array1[1] = 56;
array1[2] = 24;
array1[3] = 34;
for (var n=0;n<4;n++)
{
array2[n]=array1[n].toString();
}
for (var k=0;k<4;k++)
{
array3[k]=Buffer.from(' ');
}
for (var a=0;a<4;a++)
{
array4[a]=Buffer.from(array2[a]);
}
for (m=0;m<4;m++)
{
array4[m].copy(array3[m],0);
}
logger.write('Date'+q);
logger.write('Time'+(q+' '))
logger.write('Data 01'+t);
logger.write('Data 02'+t);
logger.write('Data 03'+t);
logger.write('Data 04'+t)
logger.write(endOfLine);
logger.write(endOfLine);
function mydata() //user defined function
{
logger.write(datechar+s);
logger.write(timechar+s);
for ( n = 0; n < 4; n++)
{
logger.write(array3[n]);
}
logger.write(endOfLine);
}
var now = new Date();
var dateFormat = require('dateformat');
var date = dateFormat(now,"isoDate");
var time = dateFormat(now, "h:MM:ss TT ");
var datechar = date.toString();
var timechar = time.toString();
mydata();
sleep(5*1000);

In Node.js, how to read a file, append a string at a specified line or delete a string from a certain line?

I need to open an existing JavaScript file, check if this string exists:
var LocalStrategy = require('passport-local').Strategy;
If it doesn't, then append it at the top with the rest of require() lines.
In another case, I need to check if that string exists, and if it does, I would like to remove just that line.
I have looked at fs.readFile, fs.writeFile, fs.open but I don't think it is capable of doing what I need. Any suggestions?
This is a simplified script:
var fs = require('fs');
var search = "var LocalStrategy = require('passport-local').Strategy;";
function append (line) {
line = line || 0;
var body = fs.readFileSync('example.js').toString();
if (body.indexOf(search) < 0 ) {
body = body.split('\n');
body.splice(line + 1,0,search);
body = body.filter(function(str){ return str; }); // remove empty lines
var output = body.join('\n');
fs.writeFileSync('example.js', output);
}
}
function remove () {
var body = fs.readFileSync('example.js').toString();
var idx = body.indexOf(search);
if (idx >= 0 ) {
var output = body.substr(0, idx) + body.substr(idx + search.length);
fs.writeFileSync('example.js', output);
}
}

Resources