i am using exceljs and try to write value in a cell but it does not working. However workbook.xlsx.readFile(filename) is working but workbook.xlsx.writeFile(filename) won't.
Here is my code:-
var Excel = require('exceljs');
var fs = require('fs')
module.exports.summary = function(req, res, next) {
try {
var filename = process.cwd() + '/template/report/summary.xlsx';
var workbook = new Excel.Workbook();
workbook.xlsx.writeFile(filename)
.then(function() {
var worksheet = workbook.getWorksheet(1);
console.log('worksheet',worksheet);
var row = worksheet.getRow(5);
row.getCell('C').value = new Date();
row.commit();
worksheet.commit();
workbook.commit().then(function() {
console.log('xls file is written.');
});
res.json({ msg: done })
});
} catch (e) {
next(e);
}
}
Try this code, Hope this will help you
const excel = require('exceljs');
//Creating New Workbook
var workbook = new excel.Workbook();
//Creating Sheet for that particular WorkBook
var sheetName = 'Sheet1';
var sheet = workbook.addWorksheet(sheetName);
//Header must be in below format
sheet.columns = [{key:"name", header:"name"}, {key: "age", header: "age"}];
//Data must be look like below, key of data must be match to header.
var data = [{name:"Kalai", age: 24}, {name:"Vignesh", age:24}];
//adding each in sheet
for(i in data){
sheet.addRow(data[i]);
}
//Finally creating XLSX file
var fileName = "Sample.xlsx";
workbook.xlsx.writeFile(fileName).then(() => {
callback(null);
});
writeFile is no longer supported, so I suggest you to exchange it for "writeBuffer".
This code worked to me:
const buffer = workbook.xlsx.writeBuffer();
const fileType = 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=UTF-8';
let EXCEL_EXTENSION = '.xlsx';
const blob= new Blob([buffer], {type: fileType});
saveAs(blob, 'filename' + EXCEL_EXTENSION);
In my case i have name like "data2022/2023" the main problem is "/" when i remove the slash "data2020" its work. Dunno why cant use unicoden"/"
Related
I am thinking if i can read the contents of an excel sheet using XLSX and display its contents on front-end.
I tried reading a file using
tmpArray= [];
reader.onload = function(e : any) {
var data = new Uint8Array(e.target.result);
var workbook = XLSX.read(data, {type: 'array'});
let worksheet = workbook.Sheets[workbook.SheetNames[0]];
// sample values //
let desired_cell = worksheet['B5'];
let cellB16 = worksheet['B16'];
// sample values //
let desired_value12 = (cellB16 ? cellB16.v : undefined);
tmpArray.push[desired_value12];
};
but outside this onload function, array of tmpArray don't exist anymore.
So what i wanted is to access the tmpArray and it's contents after the onload function. Is there any work around to do this?
Try this example on stackblitz
In your typescript file
import * as XLSX from 'xlsx';
onFileChange(evt: any) {
/* wire up file reader */
const target: DataTransfer = <DataTransfer>(evt.target);
if (target.files.length !== 1) throw new Error('Cannot use multiple files');
const reader: FileReader = new FileReader();
reader.onload = (e: any) => {
/* read workbook */
const bstr: string = e.target.result;
const wb: XLSX.WorkBook = XLSX.read(bstr, { type: 'binary' });
/* grab first sheet */
const wsname: string = wb.SheetNames[0];
const ws: XLSX.WorkSheet = wb.Sheets[wsname];
/* save data */
this.data = <AOA>(XLSX.utils.sheet_to_json(ws, { header: 1 }));
console.log(this.data);
};
reader.readAsBinaryString(target.files[0]);
}
export(): void {
/* generate worksheet */
const ws: XLSX.WorkSheet = XLSX.utils.aoa_to_sheet(this.data);
/* generate workbook and add the worksheet */
const wb: XLSX.WorkBook = XLSX.utils.book_new();
XLSX.utils.book_append_sheet(wb, ws, 'Sheet1');
/* save to file */
XLSX.writeFile(wb, this.fileName);
}
try this - excel file Read
import * as XLSX from 'xlsx';
this.ExcelData = [];
this.ngxLoader.start();
this.file = event.target.files[0];
let fileReader = new FileReader();
fileReader.onload = (e) => {
this.arrayBuffer = fileReader.result;
var data = new Uint8Array(this.arrayBuffer);
var arr = new Array();
for (var i = 0; i != data.length; ++i) arr[i] = String.fromCharCode(data[i]);
var bstr = arr.join("");
var workbook = XLSX.read(bstr, { type: "binary" });
var first_sheet_name = workbook.SheetNames[0];
var worksheet = workbook.Sheets[first_sheet_name];
let jsondata = XLSX.utils.sheet_to_json(worksheet, { raw: true });
this.ExcelData = jsondata;
}
fileReader.readAsArrayBuffer(this.file);
this.file = null;
Please make the following change and you will be able to access the value of tmpArray from anywhere.
tmpArray; // changed here and moved it to outside the function
let self = this; // please note this change
reader.onload = function(e : any) {
var data = new Uint8Array(e.target.result);
var workbook = XLSX.read(data, {type: 'array'});
let worksheet = workbook.Sheets[workbook.SheetNames[0]];
// sample values //
let desired_cell = worksheet['B5'];
let cellB16 = worksheet['B16'];
// sample values //
let desired_value12 = (cellB16 ? cellB16.v : undefined);
self.tmpArray = desired_value12; // changed here
};
MY file writes in the function convertfile() after formatworkbook() activates, therefore, throwing an error since the xlsxWorkbook variable does not exist until we've converted the file. I am new to async-await and promises but I did try to make it asynchronous (using both)
A couple of things I tried:
1) Trying to set it up to return the written file as a result of a promise (which using the .then keyword I still think I am doing a little) and then telling format workbook to await convertFile (declaring it as an async function)
2) Calling formatWorkbook within convertFile() after the then statement.
var express = require('express');
var router = express.Router();
const multer = require('multer');
var Excel = require('exceljs');
const index = require("../routes/index")
const path = require('path')
const fs = require('fs')
var workbook = new Excel.Workbook();
//var myworkbook = workbook.csv.readFile('uploads/HVACresultfile.csv')
// if no workbook await the file function should go here or something.
convertFile(workbook)
function convertFile(workbook) {
var workbook = new Excel.Workbook();
csvWorkbook = workbook.csv.readFile('uploads/HVACresultfile.csv')
csvWorkbook.then(function(result){
try {
workbook.xlsx.writeFile('uploads/success.xlsx')
console.log('converted')
} catch(err){
console.log(err)
}
})
}
function formatWorkbook(workbook) {
var workbook = new Excel.Workbook();
var xlsxWorkbook = workbook.xlsx.readFile('uploads/success.xlsx')
var xlsxWorksheet = workbook.getWorksheet('sheet1')
xlsxWorkbook.then(function(result){
try {
assessFile(xlsxWorkbook,xlsxWorksheet)
console.log('assessing')
} catch(err) {
console.log(err)
}
})
}
function assessFile(workbook,xlsxWorkbook,xlsxWorksheet) {
console.log('burf')
}
formatWorkbook()
running these functions would console.log assessing , burf and then converted. my ideal would of course to ensure that the file is converted first.
My ideal here is when this file is done , we read the file - perform multiple functions on it , and then write the file with the edits. What am I missing here?
ps. success.xlsx does write the CSV file as an xlsx correctly.
Place the convertFile(workbook) call inside of the .then method of your formatWorkbook like this:
async function convertFile(workbook) {
var workbook = new Excel.Workbook();
csvWorkbook = workbook.csv.readFile('./products.xlsx')
await csvWorkbook.then(async function(result){
await workbook.xlsx.writeFile('./products2-teste-stack.xlsx').then( () => {
console.log('converted')
})
})
}
function formatWorkbook(workbook) {
var workbook = new Excel.Workbook();
var xlsxWorkbook = workbook.xlsx.readFile('uploads/success.xlsx')
var xlsxWorksheet = workbook.getWorksheet('sheet1')
xlsxWorkbook.then(async function(result){
try {
// CALL CONVERT WHEN YOU FINISH READING YOUR FILE
await convertFile(workbook)
assessFile(xlsxWorkbook,xlsxWorksheet)
console.log('assessing')
} catch(err) {
console.log(err)
}
})
}
This way, it will not be called before you have finished reading your file.
If you convert your function to an async function you can await for the convertFile promise to resolve before executing the next lines of code.
You can also do it like this:
workbook.xlsx.readFile('uploads/success.xlsx').then(async function() {
try {
var xlsxWorksheet = workbook.getWorksheet('sheet1')
await convertFile(xlsxWorksheet)
assessFile(xlsxWorkbook,xlsxWorksheet)
console.log('assessing')
} catch(err) {
console.log(err)
}
})
I want to get the first row(name,email,mobile) as array from an uploaded excel file.
I am using XLSX.
I am getting whole data into array. But, I want only to read top line. because,
my excel file is quite large.
onFileChange(event) { //when user uploads xls file
const fileList: FileList = event.target.files;
if (fileList.length > 0) {
const file: File = fileList[0];
const reader = new FileReader();
reader.onload = function (e) {
const arrayBuffer = this.result,
data = new Uint8Array(arrayBuffer),
arr = new Array();
for (let i = 0; i !== data.length; ++i) {
arr[i] = String.fromCharCode(data[i]);
}
const bstr = arr.join('');
const workbook: XLSX.WorkBook = XLSX.read(bstr, { type: 'binary' });
const firstSheetName: string = workbook.SheetNames[0];
const worksheet: XLSX.WorkSheet = workbook.Sheets[firstSheetName];
// getting all rows
console.log(XLSX.utils.sheet_to_json(worksheet, { header: 1 }));
// I want to get top row only.
console.log(XLSX.utils.decode_row('A1'));
};
reader.readAsArrayBuffer(file);
}
}
function get_header_row(sheet)
{
var headers = [];
var range = XLSX.utils.decode_range(sheet['!ref']);
var C, R = range.s.r;
* start in the first row */
/* walk every column in the range */
for(C = range.s.c; C <= range.e.c; ++C)
{
var cell = sheet[XLSX.utils.encode_cell({c:C, r:R})]
/* find the cell in the first row */
var hdr = "UNKNOWN " + C; // <-- replace with your desired default
if(cell && cell.t)
hdr = XLSX.utils.format_cell(cell);
headers.push(hdr);
}
return headers;
}
I've tried the file upload and below is my steps and result with both data and header,
This will also support multiple sheet within the excel sheet,
1.npm install --save xlsx
2.import * as XLSX from 'xlsx';
3.HTML Code:
<input type="file" (change)="onFileChange($event)">
4.Angular Typescript:
exceltoJson = {};
onFileChange(event: any) {
this.exceltoJson = {};
let headerJson = {};
/* wire up file reader */
const target: DataTransfer = <DataTransfer>(event.target);
// if (target.files.length !== 1) {
// throw new Error('Cannot use multiple files');
// }
const reader: FileReader = new FileReader();
reader.readAsBinaryString(target.files[0]);
console.log("filename", target.files[0].name);
this.exceltoJson['filename'] = target.files[0].name;
reader.onload = (e: any) => {
/* create workbook */
const binarystr: string = e.target.result;
const wb: XLSX.WorkBook = XLSX.read(binarystr, { type: 'binary' });
for (var i = 0; i < wb.SheetNames.length; ++i) {
const wsname: string = wb.SheetNames[i];
const ws: XLSX.WorkSheet = wb.Sheets[wsname];
const data = XLSX.utils.sheet_to_json(ws); // to get 2d array pass 2nd parameter as object {header: 1}
this.exceltoJson[`sheet${i + 1}`] = data;
const headers = this.get_header_row(ws);
headerJson[`header${i + 1}`] = headers;
// console.log("json",headers)
}
this.exceltoJson['headers'] = headerJson;
console.log(this.exceltoJson);
};
}
get_header_row(sheet) {
var headers = [];
var range = XLSX.utils.decode_range(sheet['!ref']);
var C, R = range.s.r; /* start in the first row */
/* walk every column in the range */
for (C = range.s.c; C <= range.e.c; ++C) {
var cell = sheet[XLSX.utils.encode_cell({ c: C, r: R })] /* find the cell in the first row */
// console.log("cell",cell)
var hdr = "UNKNOWN " + C; // <-- replace with your desired default
if (cell && cell.t) {
hdr = XLSX.utils.format_cell(cell);
headers.push(hdr);
}
}
return headers;
}
5.Result
{filename: "uploadedexcel.xlsx", sheet1: Array(212), sheet2: Array(8), headers: {…}}
Results holds the uploaded excel name, data in the sheet1 and sheet2 and also header in the sheet1 and sheet2.
The uploaded excel sheets has sheet1 and sheet2.
I am using this code for single row header in excel sheet, but I want a two row header. Suggestions are welcome.
var Heading =[
[ "EMPLOYEE","SCORES","COMMENTS"]
];
const myworksheet: XLSX.WorkSheet = XLSX.utils.json_to_sheet(this.emp ,{skipHeader:true});
XLSX.utils.sheet_add_json(myworksheet,this.emp,{skipHeader:true , origin: 'A2'});
XLSX.utils.sheet_add_aoa(myworksheet, Heading);
Here i am taking excel sheet from the blob
public DisplayExcelRows(ExcelURL from blob) {
var url = ExcelURL;
var oReq = new XMLHttpRequest();
oReq.open("GET", url, true);
oReq.responseType = "arraybuffer";
var excelrows: any;
oReq.onload = () => {
var arraybuffer = oReq.response;
/* convert data to binary string */
var data = new Uint8Array(arraybuffer);
var arr = new Array();
for (var i = 0; i != data.length; ++i) arr[i] = String.fromCharCode(data[i]);
var bstr = arr.join("");
/* Call XLSX */
var workbook = XLSX.read(bstr, { type: "binary" });
/* DO SOMETHING WITH workbook HERE */
var first_sheet_name = workbook.SheetNames[0];
/* Get worksheet */
var worksheet = workbook.Sheets[first_sheet_name];
excelrows = XLSX.utils.sheet_to_json(worksheet, { header: 1 });
//this will extract headers and other rows separately
this.data = excelrows;
this.header = this.data.shift(); //splitting headers and other rows
}
simplest way i found of doing this if you are using the json method then that is already generating objects with KEYS from the header so when using:
this.decoded = utils.sheet_to_json(workSheet);
just do this to get headers (assuming there was anything decoded):
this.columns = Object.keys(this.decoded[0]);
that will give you the columns, simply by getting the object keys which it used to generate them from the column names initially
// getting all rows
this.data = (XLSX.utils.sheet_to_json(worksheet, { header: 1 }));
// Fetch the first row
const header = this.data.shift();
I am new to nodejs. Need your help. From the nodejs terminal, i want to download an excel file and convert it to csv (say, mocha online.js). Note: i don't want to do this via a browser.
Below is a script i am working on to download and convert to csv. There is no error nor the expected result:
online.js
if (typeof require !== 'undefined') XLSX = require('xlsx');
var XMLHttpRequest = require("xmlhttprequest").XMLHttpRequest;
/* set up XMLHttpRequest */
var url = "http://oss.sheetjs.com/js-xlsx/test_files/formula_stress_test_ajax.xlsx";
var xhr = new XMLHttpRequest();
xhr.open("GET", url, true);
xhr.responseType = "arraybuffer";
describe('suite', function () {
it('case', function () {
var arraybuffer = xhr.response;
/* convert data to binary string */
var data = new Uint8Array(arraybuffer);
var arr = new Array();
for (var i = 0; i != data.length; ++i) arr[i] = String.fromCharCode(data[i]);
var bstr = arr.join("");
/* Call XLSX */
var sheetName = 'Database';
var workbook = XLSX.read(bstr, { type: "binary" });
var worksheet = workbook.Sheets[sheetName];
var csv = XLSX.utils.sheet_to_csv(worksheet);
console.log(csv);
xhr.send();
//.... perform validations here using the csv data
});
})}
I tried myself with this code, and it seems it is working, the only thing is that I spent 15 minutes trying to understand why my open office would not open the file, I eventually understood that they were sending a zip file ... here is the full code, the doc of the http get function is here http.get
You could have used the request module, but it isn't native, request is easier though.
enjoy!
const url = 'http://oss.sheetjs.com/js-xlsx/test_files/formula_stress_test_ajax.xlsx'
const http = require('http')
const fs = require('fs')
http.get(url, (res) => {
debugger
const {
statusCode
} = res;
const contentType = res.headers['content-type'];
console.log(`The type of the file is : ${contentType}`)
let error;
if (statusCode !== 200) {
error = new Error(`Request Failed.\n` +
`Status Code: ${statusCode}`);
}
if (error) {
console.error(error.message);
// consume response data to free up memory
res.resume();
return;
}
res.setEncoding('binary');
let rawData = '';
res.on('data', (chunk) => {
rawData += chunk;
});
res.on('end', () => {
try {
const parsedData = xlsxToCSVFunction(rawData);
// And / Or just put it in a file
fs.writeFileSync('fileName.zip', rawData, 'binary')
// console.log(parsedData);
} catch (e) {
console.error(e.message);
}
});
}).on('error', (e) => {
console.error(`Got error: ${e.message}`);
});
function xlsxToCSVFunction(rawData) {
return rawData //you should return the csv file here whatever your tools are
}
I actually encountered the same problem 3 months ago : here is what I did!
I did not find any nodeJS module that was exactly as I wanted, so I used in2csv (a python shell program) to transform the data; the t option is to use tabulation as the delimiter
1) Step 1: transforming the xlsx file into csv using in2csv
This code takes all the xlsx files in the current directory, transform them into csv files and put them in another directory
var shelljs = require('shelljs/global')
var dir = pwd().stdout.split('/')
dir = dir[dir.length - 1].replace(/\s/g, '\\ ')
mkdir('../'+ dir + 'CSV')
ls('*.xlsx').forEach(function(file) {
// below are the two lines you need
let string = 'in2csv -t ' + file.replace(/\s/g, '\\ ') + ' > ../'+ dir + 'CSV/' + file.replace('xlsx','csv').replace(/\s/g, '\\ ')
exec(string, {silent:true}, function(code, stdout, stderr){
console.log('new file : ' + file.replace('xlsx','csv'))
if(stderr){
console.log(string)
console.log('Program stderr:', stderr)
}
})
});
Step 2: loading the data in a nodejs program:
my script is very long but the main two lines are :
const args = fileContent.split('\n')[0].split(',')
const content = fileContent.split('\n').slice(1).map(e => e.split(','))
And for the benefit of seekers like me...here is a solution using mocha, request and xlsx
var request = require('request');
var XLSX = require('xlsx');
describe('suite', function () {
it('case', function (done) {
var url = "http://oss.sheetjs.com/js-xlsx/test_files/formula_stress_test_ajax.xlsx";
var options = {
url: url,
headers: {
'Content-Type': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
},
encoding: null
};
request.get(options, function (err, res, body){
var arraybuffer = body;
/* convert data to binary string */
var data = arraybuffer;
//var data = new Uint8Array(arraybuffer);
var arr = new Array();
for (var i = 0; i != data.length; ++i) arr[i] = String.fromCharCode(data[i]);
var bstr = arr.join("");
/* Call XLSX */
var sheetName = 'Database';
var workbook = XLSX.read(bstr, { type: "binary" });
var worksheet = workbook.Sheets[sheetName];
var csv = XLSX.utils.sheet_to_csv(worksheet);
console.log(csv);
done();
});
});
});
I am trying to perform bulk upload in node js and mongodb is my db,can anyone suggest me some best articles regarding this.Thanks in advance.
You can use Model.collection.insert or Model.insertMany as below where collections is array of items in bulk.
Model.collection.insert(collections, function (err, models) {
next(err, models);
});
OR,
Model.insertMany(collections, function (err, models) {
next(err, models);
});
Mongoose reference: http://mongoosejs.com/docs/api.html#model_Model.insertMany
Mongo reference: https://docs.mongodb.com/v3.2/reference/method/db.collection.insert/
You can insert multiple records with batch/bulk insert in mongoose.
var arr = [{ name: 'Star Wars' }, { name: 'The Empire Strikes Back' }];
Movies.insertMany(arr, function(error, docs) {});
Let's say i have an excel file employees.xlsx with following data and i want perform bulk write.
There are several libraries out there for converting excel data to json in node, i use xlsx but it's personal taste you can use whatever is convenient for you.
Here is a helper i use for reading "/public/employees.xlsx" file.I found the content from here here.
//** helper/excel-reader.js **//
var excelReader = {};
excelReader.readExcel = function(filePath){
var XLSX = require('xlsx');
var workbook = XLSX.readFile(filePath);
var sheet_name_list = workbook.SheetNames;
var data = [];
sheet_name_list.forEach(function(y) {
var worksheet = workbook.Sheets[y];
var headers = {};
for(z in worksheet) {
if(z[0] === '!') continue;
//parse out the column, row, and value
var tt = 0;
for (var i = 0; i < z.length; i++) {
if (!isNaN(z[i])) {
tt = i;
break;
}
};
var col = z.substring(0,tt);
var row = parseInt(z.substring(tt));
var value = worksheet[z].v;
//store header names
if(row == 1 && value) {
headers[col] = value;
continue;
}
if(!data[row]) data[row]={};
data[row][headers[col]] = value;
}
//drop those first two rows which are empty
data.shift();
data.shift();
});
return data;
}
module.exports = excelReader;
Now the employee model somehow looks like this.
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var employee = new Schema({
name: String,
adderess: String,
phonenumber: String
});
module.exports = mongoose.model('Employee', employee);
Now let's use the above code so here is my users.js route whenever i type "localhost:3000/users" it write the csv content to database.
var express = require('express');
var router = express.Router();
var excelReader = require('../helpers/excel-reader');
var mongoose = require('mongoose');
var Employee = require('../models/employee');
/* GET users listing. */
router.get('/', function(req, res, next) {
var employeesJsonArray = excelReader.readExcel('./public/employees.xlsx')
Employee.insertMany(employeesJsonArray,function(error, docs) {
if(error){
next(error)
}
else{
res.json(docs);//just rendering the document i got
}
});
});
module.exports = router;
Hope this helps!!