SheetJS js-xlsx - Add hyperlink formula in cell range - javascript

I am unable to decrypt the documentation...
The goal is to create a link formula in each cell based on another cell.
let wb = XLSX.utils.book_new();
wb.Props = {
Title: `export`,
Subject: "export",
};
let ws_data = [
[
"sku",
"product",
"picture"
]
];
products.map(item => {
ws_data.push([
item.sku,
item.product,
`=HYPERLINK("/pics/"&${item.sku}&".jpg";"link")`,
])
})
wb.SheetNames.push("data");
let ws = XLSX.utils.aoa_to_sheet(ws_data);
wb.Sheets["data"] = ws;
let wbout = XLSX.write(wb, { bookType: 'xlsx', type: 'binary' });
saveByteArray([convertBinaryToOctetStream(wbout)], `export.xlsx`);
Obviously, this simply puts the =HYPERLINK("/pics/all/"&sku&".jpg";"link") text in the cell. How can it be the actual formula?

Could you try mapping the array separately and then use it in the worksheet? I am guessing you want the link in the third column.
products.map(item => {
ws_data.push([
item.sku,
item.product,
'link',
])
})
products.foreach(item => {
ws_links.push("/pics/" + item.sku + ".jpg" )
})
wb.SheetNames.push("data");
let ws = XLSX.utils.aoa_to_sheet(ws_data);
for (let i = 0; i < json.length; i++) {
ws[XLSX.utils.encode_cell({
c: 3,
r: i
})].l = { Target: ws_links[i] };
}
wb.Sheets["data"] = ws;
let wbout = XLSX.write(wb, { bookType: 'xlsx', type: 'binary' });

Related

calculate list of the sums of each column from csv

I'm trying to calculate sums of each columns of csv. I'm able to read a csv in js using readfile method. I also was able to loop through it and parsed data into array of objects. Now I just to figure out a way to add up all the column elements, that's where I'm struggling. My csv object is in array of object format which looks like this.
[
{ item: '18', count: '180' },
{ item: '19', count: '163' },
{ item: '20', count: '175' },
{ item: '', count: undefined }
]
CSV input is like this:
item,count
18,180
19,163
20,175
I want to add 18 + 19 + 20 and final answer should look like this [57,518].
Here's I've done so far, I just need help to make this better and column wise adding logic in JS, please help.
const fs = require('fs')
let result = []
var dataArray = []
fs.readFile(filename, 'utf8', function (err, data) {
dataArray = data.split(/\r?\n/);
// console.log("dataArray", dataArray)
var headers = dataArray[0].split(",");
for (var i = 1; i < dataArray.length; i++) {
var obj = {};
console.log("dataArray", dataArray)
var currentline = dataArray[i].split(",");
for (var j = 0; j < headers.length; j++) {
obj[headers[j]] = currentline[j];
}
result.push(obj);
}
})
You can iterate through each row of your csv and sum up values of items and count using array#reduce and array#forEach.
const fs = require('fs').promises;
const fileName = 'data.csv'
const calculateSum = async () => {
const data = await fs.readFile(fileName, 'utf-8');
const dataArray = data.split(/\r?\n/);
const header = dataArray[0].split(',')
const result = dataArray.slice(1).reduce((sum, arr) => {
arr.split(',').forEach((v, i) => {
sum[i] = (sum[i] || 0) + Number(v.trim());
})
return sum;
}, []);
console.log(result);
}
Generic function
let dataArray = [
{ item: '18', count: '180' },
{ item: '19', count: '163' },
{ item: '20', count: '175' },
{ item: '', count: undefined }
]
const sums = dataArray.reduce((sum, tableRow) => {
Object.keys(tableRow).forEach((obj) => {
if (Number(tableRow[obj])) sum[obj] = (sum[obj] || 0) + Number(tableRow[obj]);
})
return sum;
}, []);
console.log(sums) // [ item: 57, count: 518 ]

Export data to multiple table from XLSX using Angular js

I was trying to export data from two tables into one excel sheet, I already export two table in to two sheets, how can I get all data in to sheet.
exportAsExcel(excelObj: ExcelExport,excelObjHeader: ExcelExport): void {
let wb: XLSX.WorkBook;
let header = excelObj.header
const ws: XLSX.WorkSheet = XLSXUtils.json_to_sheet(excelObj.data);
const ws1: XLSX.WorkSheet = XLSXUtils.json_to_sheet(excelObjHeader.data);
wb = XLSXUtils.book_new();
XLSXUtils.book_append_sheet(wb, ws, excelObj.sheetName);
XLSXUtils.book_append_sheet(wb, ws1, excelObjHeader.sheetName);
writeFile(wb, `${excelObj.fileName.trim()}${this.fileExtension}`);}
I am try to ger this format
I used exceljs module and I remodelled my problem using that module.
exportExcelReport(result)
{
this.sName = 'tsetName';
this.excelFileName = 'Teat_Excel.xlsx';
this.cols =['ID','ItemCode','ItemName','Quantity','Price','LineTotal']
var excelItem = [];
for (let index = 0; index < result.Details.length; index++) {
const element = result.Details[index].ID;
console.log(element);
excelItem.push({
ID: result.Details[index].ID,
ItemCode: result.Details[index].ItemCode,
ItemName: result.Details[index].ItemName,
Quantity: result.Details[index].Quantity,
Price: result.Details[index].Price,
LineTotal: result.Details[index].LineTotal
}); }
this.data=excelItem
var workbook = new Excel.Workbook();
workbook.creator = 'Web';
workbook.lastModifiedBy ='Web';
workbook.created = new Date();
workbook.modified = new Date();
workbook.addWorksheet(this.sName, { views: [{ state: 'frozen', ySplit: 4, activeCell: 'A1', showGridLines: true }] })
var sheet = workbook.getWorksheet(1);
var head1 = ["Document No.",result.Code , " Status" , result.Name, " Date Range",this.datePipe.transform( result.FromDate,'yyyy/mm/dd') +" - "+this.datePipe.transform( result.ToDate,'yyyy/mm/dd') ];
sheet.addRow("");
sheet.addRow(head1);
sheet.addRow("");
sheet.getRow(4).values = this.cols;
sheet.columns = [
{ key: 'ID' },
{ key: 'ItemCode' },
{ key: 'ItemName' },
{ key: 'Quantity' },
{ key: 'Price' },
{ key: 'LineTotal' },
];
sheet.addRows(this.data);
workbook.xlsx.writeBuffer().then(data => {
var blob = new Blob([data], { type: this.blobType });
var url = window.URL.createObjectURL(blob);
var a = document.createElement("a");
document.body.appendChild(a);
a.href = url;
a.download = this.excelFileName;
a.click();
});
}
refrense1
refrense2

How to sum all values in column?

I'm using exceljs and i must sum all values from my column, how can i do this?
at issue on github, i found one solution, but not work for me:
workSheet.getCell(`B${endRow}`).value = { formula: `SUM(B4:B${endRow-1})` };
because vscode throw me: Type '{ formula: string; }' is not assignable to type 'CellValue'. Type '{ formula: string; }' is missing the following properties from type 'CellSharedFormulaValue': sharedFormula, date1904
can somebody tell me how to sum each values from column?
Ciao, try to modify your code like this:
workSheet.getCell(`B${endRow}`).value = { formula: `SUM(B4:B${endRow-1})`, date1904: false };
Im a bit late im adding this for anyone who came across the same issue.
point number one your array object values must be of type number not string.
I created a method to do that for me which is convertStringToNumber(data);
Example data
[{ItemPrice: 69.99, name: "Kellogs Cornflakes", brand: "Kellogs", Quantity_Purchased: 2, QaunititySaleValue: 139.98}, {ItemPrice: 19.99, name: "Castle Lite", brand: "Castle", Quantity_Purchased: 2, QaunititySaleValue: 39.98}]
Code
async createExcel(data, fileName) {
let xlsData = this.convertStringToNumber(data);
const fs = require('fs')
const workbook = new Excel.Workbook();
const worksheet = workbook.addWorksheet(fileName);
worksheet.columns = [
{ header: 'name', key: 'name', width: 10 },
{ header: 'brand', key: 'brand', width: 32 },
{ header: 'Quantity_Purchased', key: 'Quantity_Purchased', width: 15, },
{ header: 'ItemPrice', key: 'ItemPrice', width: 15, },
{ header: 'QaunititySaleValue', key: 'QaunititySaleValue', width: 15, }
];
worksheet.addRows(xlsData);
const endRow = worksheet.lastRow._number + 1;
worksheet.getCell(`C${endRow}`).value = { formula: `SUM(C2:C${endRow - 1})` };
worksheet.getCell(`D${endRow}`).value = { formula: `SUM(D2:D${endRow - 1})` };
worksheet.getCell(`E${endRow}`).value = { formula: `SUM(E2:E${endRow - 1})` };
// save under export.xlsx
let buffResult = await workbook.xlsx.writeBuffer();
fs.writeFileSync(fileName + ".xlsx", buffResult); }
convertStringToNumber(objects) {
for (var i = 0; i < objects.length; i++) {
var obj = objects[i];
for (var prop in obj) {
if (obj.hasOwnProperty(prop) && obj[prop] !== null && !isNaN(obj[prop])) {
obj[prop] = +obj[prop];
}
}
}
return objects; }
Output

JSON to excel conversion

I am converting JSON data to an excel file format. So far I have been able to create a file with the data.
I am looking forward to add a custom message to be displayed (image below) in the first row and thereafter data should be displayed in the file with column headers.
I have taken reference from this stackblitz link
How can I achieve this ?
New Issue
Missing headers firstName, lastName, email, phone
I assume when you say JSON, you mean a Javascript object that have been parsed from a JSON file.
in my example it's myObject.
We create a worksheet using XLSX.utils.json_to_sheet(myObject);
We add a row to the start of the worksheet using: XLSX.utils.sheet_add_aoa(myWorkSheet, [["Your Mesage Goes Here"]], { origin: 0 });
this will insert an aoa (array of arrays) to a new row at the position defined by origin.
{ origin: 0 } means first row
{ origin: 1 } means 2nd row
{ origin: -1 } means last row
in our case we add just one cell (A1) with the content: "Your Mesage Goes Here"
we merge the cells in range A1:D1 (4 cells) using myWorkSheet['!merges'] = [{ s: 'A1', e: 'D1' }];
The rest is self explanatory I think
Here's a working example
myObject = [
{ name: "Moran", role: "back" },
{ name: "Alain", role: "front" },
{ name: "Tony", role: "back" },
{ name: "Mike", role: "back" },
{ name: "Abo", role: "back" },
{ name: "Toni", role: "back" }
];
function exportWS() {
var myFile = "myFile.xlsx";
var myWorkSheet = XLSX.utils.json_to_sheet(myObject);
var myWorkBook = XLSX.utils.book_new();
XLSX.utils.book_append_sheet(myWorkBook, myWorkSheet, "myWorkSheet");
XLSX.writeFile(myWorkBook, myFile);
}
function exportWSPlus() {
var myFile = "myFilePlus.xlsx";
var myWorkSheet = XLSX.utils.json_to_sheet(myObject);
XLSX.utils.sheet_add_aoa(myWorkSheet, [["Your Mesage Goes Here"]], { origin: 0 });
var merges = myWorkSheet['!merges'] = [{ s: 'A1', e: 'D1' }];
var myWorkBook = XLSX.utils.book_new();
XLSX.utils.book_append_sheet(myWorkBook, myWorkSheet, "myWorkSheet");
XLSX.writeFile(myWorkBook, myFile);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/xlsx/0.14.3/xlsx.full.min.js"></script>
<button type="button" onclick="exportWS()">Export Worksheet</button>
<button type="button" onclick="exportWSPlus()">Export Worksheet+</button>
feel free to ask any questions you may have.
I researched about this a lot and finally I could come up with a solution to this.
public exportAsExcelFile(json: Array<object>, excelFileName: string): void {
var worksheet: XLSX.WorkSheet = XLSX.utils.aoa_to_sheet([
[`${excelFileName}`]]); // message to display
worksheet['!merges'] = [{ s: { r: 0, c: 0 }, e: { r: 0, c: 3 } }]; //for merging columns. s : start, e: end, c: column, r: row
XLSX.utils.sheet_add_json(worksheet, json, { origin: "A2" }); //origin for json data
const workbook: XLSX.WorkBook = { Sheets: { 'data': worksheet }, SheetNames: ['data'] };
const excelBuffer: any = XLSX.write(workbook, { bookType: 'xlsx', type: 'array' });
var range = XLSX.utils.decode_range(worksheet['!ref']);
for (var C = range.s.r; C <= range.e.r; ++C) {
var address = XLSX.utils.encode_col(C) + "1";
if (!worksheet[address]) continue;
worksheet[address].v = worksheet[address].v.charAt(0).toUpperCase() + worksheet[address].v.substr(1).toLowerCase();
}
}

How to fix csv to json converter module?

I can't figure out how to match the title and genre correctly based on what I have in my module.
The csv_json module has an exception where it doesn't match each of the properties accordingly and that is when the title has "The" in it.
//csv file
movieId,title,genre
1,"American President, The (1995)",Comedy|Drama|Romance
2,"Creation, The creator(xxxx)",Comedy|Drama|Romance
3,"Destruction, The destroyer(xxxxx)",Comedy|Drama|Romance
//csv_json module
const readline = require('readline');
const fs = require('fs');
function readCsv(pathToFile) {
return new Promise((resolve, reject) => {
const csvReader = readline.createInterface({
input: fs.createReadStream(pathToFile)
});
let headers;
const rows = [];
let tempRows = [];
csvReader
.on('line', row => {
if (!headers) {
headers = row.split(','); // header name breed age
} else {
rows.push(row.split(','));
}
})
.on('close', () => {
// then iterate through all of the "rows", matching them to the "headers"
for (var i = 0; i < rows.length; i++) {
var obj = {};
var currentline = rows[i];
for (var j = 0; j < headers.length; j++) {
obj[headers[j]] = currentline[j]; //Kitty Siamese 14
}
tempRows.push(obj);
}
resolve(JSON.stringify(tempRows));
});
// This would be in place of the "return" statement you had before
});
}
module.exports = readCsv;
//js file
const readCsv = require('./csvjson.js');
readCsv('movieTest.csv').then((data) => {
console.log(data)
let movieJson = JSON.parse(data);
console.log(movieJson)
/*data output:
[{"movieId":"1","title":"\"American President","genre":" The (1995)\""},{"movieId":"2","title":"\"Creation","genre":" The creator(xxxx)\""},{"movieId":"3","title":"\"Destruction","genre":" The destroyer(xxxxx)\""}]
*/
/*movieJson output:
[ { movieId: '1',
title: '"American President',
genre: ' The (1995)"' },
{ movieId: '2',
title: '"Creation',
genre: ' The creator(xxxx)"' },
{ movieId: '3',
title: '"Destruction',
genre: ' The destroyer(xxxxx)"' } ]
*/
});
I expect the output to match:
[ { movieId: '1',
title: "American President, The (1995)",
genre:'Comedy|Drama|Romance' },
{ movieId: '2',
title: "The creator(xxxx) Creation",
genre: ' Comedy|Drama|Romance' },
{ movieId: '3',
title: "Destruction The destroyer(xxx)",
genre: ' Comedy|Drama|Romance' } ]
This is probably since you're splitting each row on every occurrence of a comma.
const row = '1,"American President, The (1995)",Comedy|Drama|Romance'
row.split(',')
// returns ["1", ""American President", " The (1995)"", "Comedy|Drama|Romance"]
Try replacing every comma that is not followed by a whitespace with some unique string that wouldn't occur anywhere else in the CSV file, and then split on that:
row.replace(/\,(\S)/g, '&unique;$1').split('&unique;')
// returns ["1", ""American President, The (1995)"", "Comedy|Drama|Romance"]
Hope this helps! :)

Categories