Unable to show emoji when generate excel file using javascript - javascript

I'm trying to generate an excel file which contains emojis. After the excel file is generated and I opened it in google spreadsheet, the emojis can be shown properly. (in Numbers is fine too), please see the expected link.
However when I opened that file in Ms.excel: I got this:
actual
Here is data I passed to feedbackGenerator to produce excel file in the figure above:
const renderTableHeader = titleArray => {
let row = "";
for (let i in titleArray) {
row += titleArray[i] + ',';
}
row = row.slice(0, -1);
row += '\r\n';
return row;
}
const feedbackGenerator = (data) => {
let arrData = typeof data !== 'object' ? JSON.parse(data) : data;
let file = 'sep=,\r\n\n';
const headerArray = ['Date', 'Feedback'];
file += renderTableHeader(headerArray);
for (let i = 0; i < arrData.length; i++) {
let row = "";
for (var index in arrData[i]) {
row += '"' + arrData[i][index] + '",';
}
row.slice(0, row.length - 1);
file += row + '\r\n';
}
const fileName = `feedback.xls`
generateExcelFile(file, fileName)
};
const generateExcelFile = (file, fileName) => {
let uri = 'data:application/vnd.openxmlformats-officedocument.spreadsheetml.sheet ;charset=utf-8,' + encodeURIComponent(file);
let link = document.createElement("a");
link.href = uri;
link.style = "visibility:hidden";
link.download = fileName;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
};
const data = [
{
Date: '10 Jul 2019 09:41',
Feedback: 'mencoba emoji 😊😊😊😄😄😂😂😂'
},
{
Date: '10 Jul 2019 09:41',
Feedback: 'test emoji lagi 😍😍😍✌🏿✌🏿😳😳😳'
}
]
// generate excel file
feedbackGenerator(data);
I expect the emoji to be shown properly. If it's shown as old emoji, then it's fine as long as it's not unknown chars.
expected

You do not generate an Excel file!
You generate a CSV file and give it the extension ".xls". Excel reports an error, if you try to open such a file. But Excel's default error handling is to open the file as CSV file. But Excel does not allow you to select the input encoding, if you open the file in this way.
Not being able to select the input encoding is your problem. This is what you get, if you open an UTF-8 input as ANSI:
sep=,
Date,Feedback
"10 Jul 2019 09:41","mencoba emoji 😊😊😊😄😄😂😂😂",
"10 Jul 2019 09:41","test emoji lagi ðŸ˜ðŸ˜ðŸ˜âœŒðŸ¿âœŒðŸ¿ðŸ˜³ðŸ˜³ðŸ˜³",
That is exactly what Excel does.
This means you have to encode your XLS labeled CSV file as ANSI. But this is not possible, because it is not possible to encode UTF-8 emojis in ANSI.
So the only option is to generate a CSV file and call it also CSV in order to import it in Excel. How to import a UTF-8 CSV is explained here. If you do so, the Emojis are rendered correctly:

Related

Can i set custom page and margins while generating PDF ? I tried but no luck app script

I am working on a project where i want to generate a pdf of size 52 mm x 25 mm. I use the following code to generate pdf and works fine except the page sizes.
function CreaPDF() {
//The function prints an invoice to PDF. First it copies spreadsheet to a new document.
//Deletes all sheet except the one to print. Saves it to PDF.
//It overwrites any existing doc with same name.
var sourceSpreadsheet = SpreadsheetApp.getActive();
var sheetName = "Factura";
var folderID = getParentFolder(); // Folder id to save in a folder.
var sourceSheet = sourceSpreadsheet.getSheetByName(sheetName);
var folder = DriveApp.getFolderById(folderID);
var numf = sourceSpreadsheet.getRangeByName("NumeroFactura").getValue();
var anof = numf.split("/",2); // Seeks number and year -> filename
var pdfName = anof[1] +"_Factura_" + anof[0]+ "_Dra_Salazar"; // Nombre del documento;
SpreadsheetApp.getActiveSpreadsheet().toast('Creando PDF');
// export url
var url = 'https://docs.google.com/spreadsheets/d/'+sourceSpreadsheet.getId()+'/export?exportFormat=pdf&format=pdf' // export as pdf / csv / xls / xlsx
+ '&size=A4' // paper size legal / letter / A4
+ '&portrait=true' // orientation, false for landscape
+ '&fitw=false' // fit to page width, false for actual size
+ '&sheetnames=false&printtitle=false' // hide optional headers and footers
+ '&pagenumbers=false&gridlines=false' // hide page numbers and gridlines
+ '&fzr=false' // do not repeat row headers (frozen rows) on each page
+ '&gid='+sourceSheet.getSheetId(); // the sheet's Id
var token = ScriptApp.getOAuthToken();
// request export url
var response = UrlFetchApp.fetch(url, {
headers: {
'Authorization': 'Bearer ' + token
}
});
var theBlob = response.getBlob().setName(pdfName+'.pdf');
// delete pdf if already exists
var files = folder.getFilesByName(pdfName);
while (files.hasNext())
{
files.next().setTrashed(true);
}
// create pdf
var newFile = folder.createFile(theBlob);
return true;
}
What i want is to set a custom page size in the link and custom margins. I want to send this pdf to Dymo Label printing automatically.
Any help regarding this will be highly appreciated. Thank you so much.

JavaScript blob encoding for special characters in Excel file

We are using blob to export the result of a report. Code similar as follows:
var dataBlob = '\ufeff';
for (var i = 0; i < data.length; i++) {
dataBlob += data[i];
}
var blob = new Blob([dataBlob], {
type: 'text/plain;charset=utf-8'
});
saveAs(blob, reportName + '.xls');
The file when opened in sublime for example looks like:
"sep=|"
"Header"|"Header"|"Header"|"Header"|"Header"|"Header"|"Header"|
"=""1000"""|"=""1000"""|"=""000000"""|0,00|"="""""|"=""1"""|"=""São Paulo"""|
However, when the file is opened in excel, the encoding is all wrong and the special characters appear like "São Paulo".

Javascript Web API JSON Parsing Format issue

Hi i have an issue with a few lines of code in JS and formatting my JSON data. Basically in my DB i have a field that is set to nchar(10) but some of the data in the fields are for example only 8 characters long.
The problem i have is when my JS generates a link from JSON data it attaches Spaces to the Data to compensate the (10) characters. For example clicking a link generated from the JS Would generate a link for me like this http://....api/Repo/rep10016
In my JSON it passes in this data
rep10016
But my JS is grabbing this data for the link adding spaces up to 10 as it is a nchar(10) like this.
repoCode = "rep10016 "
But i only want
repoCode = "rep10016"
My JS Code
function displayRepos(repo) {
var table = document.getElementByrCode("rList");
table.innerHTML = "";
for (var i = 0; i < arr.length; i++)
{
var rCode = arr[i].repoCode;
cell2.innerHTML = "<a href='#'rCode='" + rCode + "' " + " >Repo List</a>";
document.getElementByrCode(rCode).onclick = getRepo;
}
function getRepo(rep)
{
var repoUrl = genUrl+rep.target.rCode+"?code="+rep.target.rCode;
......
}
The repoUrl variable is generating a link like this
"http://....api/Repo/rep10016 ?code=rep10016 /"
How can i get my code to only take the actual data and not format it to the nchar(10) format that is in my db??
repoCode.trim() will do the trick.
I would use string.trim();
var orig = 'foo ';
console.log(orig.trim()); // 'foo'

HTML Table to Excel (xls) using javascript/jQuery

I am trying to export a html table to an Excel document via a javascript/jquery export. I so far have found 2 solutions but neither meet my requirements:
HTML Table Export
Does not export inline styling (styling is a must-have requirement)
Table2Excel
Does not work in all IE versions (need all browser compatibility)
I am looking for a solution that is as minimal as possible (both of these solutions were very "tidy" but as per my comments above they both had a downfall that fell short of my requirements.
Does anyone know a better solution? My requirements for this export are:
Needs to work on all browsers
Needs to export the inline styling
IF POSSIBLE it would be nice to be able to name the file
Would appreciate any assistance here, pulling my hair out as I can't be the first person that has required this feature...
Thanks!
I'm assuming that PHP / Flash is a no go. (If not, checkout PHPExcel and DataTables' export feature.)
Also, naming the file is nigh impossible without server-side programming of some type. I'm pretty sure this is a security problem for most browsers.
Before we get to the code, some limitations:
You'll probably need to lookup MS Office XML formats for XLS and customize
Once the file downloads (it will be .xls) you will likely get an error like "This file says it's in XLS format but might not be, do you want to open anyway?"
You will likely need to "Save As" some valid excel format to force it to convert from HTML in the excel document body.
I've used this fairly extensively in Chrome / Firefox / Internet Explorer but you should test yourself.
Currently set to freeze rows / columns. Change the XML and / or freeze vars at the top of the tableToExcel() function.
Resource-expensive on the client side. Probably best to use a server-side script of some kind.
There is a limit to the size of the table which is (I'm guessing) based on the size of the javascript variable. I used it with some tables like 50x300 but I wouldn't recommend on much larger tables.
It accepts a string of HTML table text (include <table>). You can format that HTML with inline styles (won't work with a CSS stylesheet unfortunately).
tableToExcel($('table').html(),'Worksheet Name');
Here's the functions. Enjoy!
function b64toBlob(b64Data, contentType, sliceSize) {
contentType = contentType || '';
sliceSize = sliceSize || 512;
var byteCharacters = atob(b64Data);
var byteArrays = [];
for (var offset = 0; offset < byteCharacters.length; offset += sliceSize) {
var slice = byteCharacters.slice(offset, offset + sliceSize);
var byteNumbers = new Array(slice.length);
for (var i = 0; i < slice.length; i++) {
byteNumbers[i] = slice.charCodeAt(i);
}
var byteArray = new Uint8Array(byteNumbers);
byteArrays.push(byteArray);
}
var blob = new Blob(byteArrays, {type: contentType});
return blob;
}
function tableToExcel(table,name) {
var freezeTopRowNumber = '4';
var freezeColNumber = '6';
var template = '<html xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:x="urn:schemas-microsoft-com:office:excel" xmlns="http://www.w3.org/TR/REC-html40">';
template += '<head><!--[if gte mso 9]>';
template += '<xml><x:ExcelWorkbook><x:ExcelWorksheets><x:ExcelWorksheet><x:Name>{worksheet}</x:Name>';
template += '<x:WorksheetOptions><x:Selected/><x:FreezePanes/><x:FrozenNoSplit/><x:SplitHorizontal>'+freezeTopRowNumber+'</x:SplitHorizontal><x:TopRowBottomPane>'+freezeTopRowNumber+'</x:TopRowBottomPane>';
template += '<x:SplitVertical>'+freezeColNumber+'</x:SplitVertical><x:LeftColumnRightPane>'+freezeColNumber+'</x:LeftColumnRightPane>';
template += '<x:ActivePane>2</x:ActivePane><x:Panes><x:Pane><x:Number>3</x:Number></x:Pane><x:Pane><x:Number>2</x:Number></x:Pane></x:Panes>';
template += '<x:ProtectContents>False</x:ProtectContents><x:ProtectObjects>False</x:ProtectObjects><x:ProtectScenarios>False</x:ProtectScenarios>';
template += '<x:DisplayGridlines/></x:WorksheetOptions></x:ExcelWorksheet></x:ExcelWorksheets></x:ExcelWorkbook></xml><![endif]--></head>';
template += '<body>{table}</body></html>';
var base64 = function(s) { return window.btoa(unescape(encodeURIComponent(s))) };
var format = function(s, c) { return s.replace(/{(\w+)}/g, function(m, p) { return c[p]; }) };
var ctx = {worksheet: name || 'Worksheet', table: table};
var b = base64(format(template,ctx));
var blob = b64toBlob(b,'application/vnd.ms-excel');
var blobURL = URL.createObjectURL(blob);
window.location.href = blobURL;
}

How to read files .csv very big with FileReader API javascript, html/jquery only

I'm trying to read a file .csv over 40 MB (with more 20.000 lines), viewing it as a table in html. The system I am designing will be in pure HTML + JQuery only.
My worksheet .csv format that is:
=======================================================================
| rank || place || population || lat || lon |
=======================================================================
| 1 || New York city || 8175133 || 40.71455 || -74.007124 |
-----------------------------------------------------------------------
| 2 || Los Angeles city || 3792621 || 34.05349 || -118.245323 |
-----------------------------------------------------------------------
..........................Thousands of lines..........................
I have a textbox filter that makes me just showing the line that has the same number entered in the field. I have a textbox filter that makes me just showing the line that has the same number entered in the field. And then uploading the file it breaks the browser. :(
Follow my code:
var fileInput = document.getElementById('fileInput');
var fileDisplayArea = document.getElementById('fileDisplayArea');
fileInput.addEventListener('change', function(e) {
var file = fileInput.files[0];
var reader = new FileReader();
reader.onload = function(e) {
//Convert .csv to table html
var data = reader.result;
var rank = $("#rank").val();
if(rank == ""){
alert("digit rank number");
fileInput.value = "";
}
else{
data = data.replace(/\s/, " #");
data = data.replace(/([0-9]\s)/g, "$1#");
var lines = data.split("#"),
output = [],
i;
for (i = 0; i < lines.length; i++)
output.push("<tr><td>" + lines[i].slice(0,-1).split(",").join("</td><td>") + "</td></tr>");
output = "<table>" + output.join("") + "</table>";
var valuefinal = $(output).find('tr').filter(function(){
return $(this).children('td').eq(0).text() == rank;
});
$('#fileDisplayArea').append(valuefinal);
}
}
reader.readAsBinaryString(file);
});
Is it possible to do something that I optimize my code and not let my browser and break my file to be read?
I tried to split the file into pieces and then seal it. (BLOB) But this way he kept crashing my browser too. :(
(Excuse me if something was not clear and enlightening about my question to you, my english is bad.)
DEMO CODE JSFiddle
As I found this thread on my research to parse a very big CSV file in the parser, I wanted to add that my final solution was to use Papa Parse:
http://papaparse.com/

Categories

Resources