Download Excel file in IE 11 - javascript

I have this ExtJS code which is for converting a grid data into Excel format and write to a file, the code will ultimately export the grid data into downloadable Excel file. This works great in firefox and chrome but fails to function in IE browser (IE 11).
on analyzing found that the code will ultimately post below string onto URL box which will download the excel file.
data:application/vnd.ms-excel;base64,<base64 encoded string follows here>
at first, I thought problem might be somewhere in the code, then i happen to check below steps.
if i paste below content either in chrome or firefox, it prompts for file download and downloads a dummy file.
data:application/vnd.ms-excel;base64,blahblahblahblahblah
however if i paste the above same string in IE 11, it does nothing. So i am on the assumption that code is working fine but i may have to do something more to make it compatible for IE browser. But i dont know what else i could try.
any pointer is deeply appreciated.
below is my ExtJS code, if it helps.
//here xmlString has the constructed xml string which holds
//grid column headers + grid rows with Table, Column, Cell and Worksheet tags.
var ctx = {
created : (new Date()).getTime(),
worksheets : xmlString
};
var uri = 'data:application/vnd.ms-excel;base64,',
tmplWorkbookXML = '<?xml version="1.0"?><?mso-application progid="Excel.Sheet"?><Workbook xmlns="urn:schemas-microsoft-com:office:spreadsheet" xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet">' + '<DocumentProperties xmlns="urn:schemas-microsoft-com:office:office"><Author>BlahBlah</Author><Created>{created}</Created></DocumentProperties>' + '<Styles>' + '<Style ss:ID="columnHeader"><Font ss:Size="11" ss:Bold="1" /><Interior ss:Color="#CCFFCC" ss:Pattern="Solid"/> </Style>' + '</Styles>' + '{worksheets}</Workbook>',
base64 = function(s) {
return window.btoa(unescape(encodeURIComponent(s)));
},
format = function(s, c) {
return s.replace(/{(\w+)}/g, function(m, p) {
return c[p];
});
};
var workbookXML = format(tmplWorkbookXML, ctx);
var link = document.createElement("A");
link.href = uri + base64(workbookXML);
link.download = sheetName + " Level Report - " + Ext.Date.format(new Date(), 'Y-m-d H:i:s') + '.xls';
link.target = '_blank';
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
PS: I have tried this on both ExtJS V4.1 and V6.0 but same behaviour.

Related

JS Export HTMLArray to CSV - delimer issue

i have data which i need to export to .csv, for Excel.
I have a function which is working fine but the result file contains all data in first row, in Excel.
Then i need to go to the "Data" tab, then "Text to columns" and pick comma as a delimer.
This is not acceptable.
How can i generate .csv file to avoid this formatting issue ?
I tried \t as a delimer but its not working :/
function download_csv_file(data) {
//define the heading for each row of the data
var csv = 'Header A, Header B, Header C\n';
//merge the data with CSV
data.forEach(function(parentRow) {
parentRow.childNodes.forEach(function(row) {
csv += row.text.concat(',');
});
csv += "\n";
});
//display the created CSV data on the web browser
document.write(csv);
var hiddenElement = document.createElement('a');
hiddenElement.href = 'data:text/csv;charset=utf-8,\uFEFF' + encodeURIComponent(csv);
hiddenElement.target = '_blank';
//provide the name for the CSV file to be downloaded
hiddenElement.download = 'File_name.csv';
hiddenElement.click();
}
thank in advance for all suggestions

How to write data in JSON file in the EJS template file [duplicate]

I want to Write Data to existing file using JavaScript.
I don't want to print it on console.
I want to Actually Write data to abc.txt.
I read many answered question but every where they are printing on console.
at some place they have given code but its not working.
So please can any one help me How to actually write data to File.
I referred the code but its not working:
its giving error:
Uncaught TypeError: Illegal constructor
on chrome and
SecurityError: The operation is insecure.
on Mozilla
var f = "sometextfile.txt";
writeTextFile(f, "Spoon")
writeTextFile(f, "Cheese monkey")
writeTextFile(f, "Onion")
function writeTextFile(afilename, output)
{
var txtFile =new File(afilename);
txtFile.writeln(output);
txtFile.close();
}
So can we actually write data to file using only Javascript or NOT?
You can create files in browser using Blob and URL.createObjectURL. All recent browsers support this.
You can not directly save the file you create, since that would cause massive security problems, but you can provide it as a download link for the user. You can suggest a file name via the download attribute of the link, in browsers that support the download attribute. As with any other download, the user downloading the file will have the final say on the file name though.
var textFile = null,
makeTextFile = function (text) {
var data = new Blob([text], {type: 'text/plain'});
// If we are replacing a previously generated file we need to
// manually revoke the object URL to avoid memory leaks.
if (textFile !== null) {
window.URL.revokeObjectURL(textFile);
}
textFile = window.URL.createObjectURL(data);
// returns a URL you can use as a href
return textFile;
};
Here's an example that uses this technique to save arbitrary text from a textarea.
If you want to immediately initiate the download instead of requiring the user to click on a link, you can use mouse events to simulate a mouse click on the link as Lifecube's answer did. I've created an updated example that uses this technique.
var create = document.getElementById('create'),
textbox = document.getElementById('textbox');
create.addEventListener('click', function () {
var link = document.createElement('a');
link.setAttribute('download', 'info.txt');
link.href = makeTextFile(textbox.value);
document.body.appendChild(link);
// wait for the link to be added to the document
window.requestAnimationFrame(function () {
var event = new MouseEvent('click');
link.dispatchEvent(event);
document.body.removeChild(link);
});
}, false);
Some suggestions for this -
If you are trying to write a file on client machine, You can't do this in any cross-browser way. IE does have methods to enable "trusted" applications to use ActiveX objects to read/write file.
If you are trying to save it on your server then simply pass on the text data to your server and execute the file writing code using some server side language.
To store some information on the client side that is considerably small, you can go for cookies.
Using the HTML5 API for Local Storage.
If you are talking about browser javascript, you can not write data directly to local file for security reason. HTML 5 new API can only allow you to read files.
But if you want to write data, and enable user to download as a file to local. the following code works:
function download(strData, strFileName, strMimeType) {
var D = document,
A = arguments,
a = D.createElement("a"),
d = A[0],
n = A[1],
t = A[2] || "text/plain";
//build download link:
a.href = "data:" + strMimeType + "charset=utf-8," + escape(strData);
if (window.MSBlobBuilder) { // IE10
var bb = new MSBlobBuilder();
bb.append(strData);
return navigator.msSaveBlob(bb, strFileName);
} /* end if(window.MSBlobBuilder) */
if ('download' in a) { //FF20, CH19
a.setAttribute("download", n);
a.innerHTML = "downloading...";
D.body.appendChild(a);
setTimeout(function() {
var e = D.createEvent("MouseEvents");
e.initMouseEvent("click", true, false, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
a.dispatchEvent(e);
D.body.removeChild(a);
}, 66);
return true;
}; /* end if('download' in a) */
//do iframe dataURL download: (older W3)
var f = D.createElement("iframe");
D.body.appendChild(f);
f.src = "data:" + (A[2] ? A[2] : "application/octet-stream") + (window.btoa ? ";base64" : "") + "," + (window.btoa ? window.btoa : escape)(strData);
setTimeout(function() {
D.body.removeChild(f);
}, 333);
return true;
}
to use it:
download('the content of the file', 'filename.txt', 'text/plain');
Try
let a = document.createElement('a');
a.href = "data:application/octet-stream,"+encodeURIComponent("My DATA");
a.download = 'abc.txt';
a.click();
If you want to download binary data look here
Update
2020.06.14 I upgrade Chrome to 83.0 and above SO snippet stop works (reason: sandbox security restrictions) - but JSFiddle version works - here
Above answer is useful but, I found code which helps you to download text file directly on button click.
In this code you can also change filename as you wish. It's pure javascript function with HTML5.
Works for me!
function saveTextAsFile()
{
var textToWrite = document.getElementById("inputTextToSave").value;
var textFileAsBlob = new Blob([textToWrite], {type:'text/plain'});
var fileNameToSaveAs = document.getElementById("inputFileNameToSaveAs").value;
var downloadLink = document.createElement("a");
downloadLink.download = fileNameToSaveAs;
downloadLink.innerHTML = "Download File";
if (window.webkitURL != null)
{
// Chrome allows the link to be clicked
// without actually adding it to the DOM.
downloadLink.href = window.webkitURL.createObjectURL(textFileAsBlob);
}
else
{
// Firefox requires the link to be added to the DOM
// before it can be clicked.
downloadLink.href = window.URL.createObjectURL(textFileAsBlob);
downloadLink.onclick = destroyClickedElement;
downloadLink.style.display = "none";
document.body.appendChild(downloadLink);
}
downloadLink.click();
}
const data = {name: 'Ronn', age: 27}; //sample json
const a = document.createElement('a');
const blob = new Blob([JSON.stringify(data)]);
a.href = URL.createObjectURL(blob);
a.download = 'sample-profile'; //filename to download
a.click();
Check Blob documentation here - Blob MDN to provide extra parameters for file type. By default it will make .txt file
In the case it is not possibile to use the new Blob solution, that is for sure the best solution in modern browser, it is still possible to use this simpler approach, that has a limit in the file size by the way:
function download() {
var fileContents=JSON.stringify(jsonObject, null, 2);
var fileName= "data.json";
var pp = document.createElement('a');
pp.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(fileContents));
pp.setAttribute('download', fileName);
pp.click();
}
setTimeout(function() {download()}, 500);
$('#download').on("click", function() {
function download() {
var jsonObject = {
"name": "John",
"age": 31,
"city": "New York"
};
var fileContents = JSON.stringify(jsonObject, null, 2);
var fileName = "data.json";
var pp = document.createElement('a');
pp.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(fileContents));
pp.setAttribute('download', fileName);
pp.click();
}
setTimeout(function() {
download()
}, 500);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="download">Download me</button>
Use the code by the user #useless-code above (https://stackoverflow.com/a/21016088/327386) to generate the file.
If you want to download the file automatically, pass the textFile that was just generated to this function:
var downloadFile = function downloadURL(url) {
var hiddenIFrameID = 'hiddenDownloader',
iframe = document.getElementById(hiddenIFrameID);
if (iframe === null) {
iframe = document.createElement('iframe');
iframe.id = hiddenIFrameID;
iframe.style.display = 'none';
document.body.appendChild(iframe);
}
iframe.src = url;
}
I found good answers here, but also found a simpler way.
The button to create the blob and the download link can be combined in one link, as the link element can have an onclick attribute. (The reverse seems not possible, adding a href to a button does not work.)
You can style the link as a button using bootstrap, which is still pure javascript, except for styling.
Combining the button and the download link also reduces code, as fewer of those ugly getElementById calls are needed.
This example needs only one button click to create the text-blob and download it:
<a id="a_btn_writetofile" download="info.txt" href="#" class="btn btn-primary"
onclick="exportFile('This is some dummy data.\nAnd some more dummy data.\n', 'a_btn_writetofile')"
>
Write To File
</a>
<script>
// URL pointing to the Blob with the file contents
var objUrl = null;
// create the blob with file content, and attach the URL to the downloadlink;
// NB: link must have the download attribute
// this method can go to your library
function exportFile(fileContent, downloadLinkId) {
// revoke the old object URL to avoid memory leaks.
if (objUrl !== null) {
window.URL.revokeObjectURL(objUrl);
}
// create the object that contains the file data and that can be referred to with a URL
var data = new Blob([fileContent], { type: 'text/plain' });
objUrl = window.URL.createObjectURL(data);
// attach the object to the download link (styled as button)
var downloadLinkButton = document.getElementById(downloadLinkId);
downloadLinkButton.href = objUrl;
};
</script>
Here is a single-page local-file version for use when you need the extra processing functionality of a scripting language.
Save the code below to a text file
Change the file extension from '.txt' to '.html'
Right-click > Open With... > notepad
Program word processing as needed, then save
Double-click html file to open in default browser
Result will be previewed in the black box, click download to get the resulting text file
Code:
<!DOCTYPE HTML>
<HTML>
<HEAD>
</HEAD>
<BODY>
<SCRIPT>
// do text manipulation here
let string1 = 'test\r\n';
let string2 = 'export.';
// assemble final string
const finalText = string1 + string2;
// convert to blob
const data = new Blob([finalText], {type: 'text/plain'});
// create file link
const link = document.createElement('a');
link.innerHTML = 'download';
link.setAttribute('download', 'data.txt');
link.href = window.URL.createObjectURL(data);
document.body.appendChild(link);
// preview the output in a paragraph
const htmlBreak = string => {
return string.replace(/(?:\r\n|\r|\n)/g, '<br>');
}
const preview = document.createElement('p');
preview.innerHTML = htmlBreak(finalText);
preview.style.border = "1px solid black";
document.body.appendChild(preview);
</SCRIPT>
</BODY>
</HTML>

Export contents inside <div> as a .docx File

I am having trouble exporting the contents of a div into a .docx file. I am using FileSaver.js which can be found here: https://github.com/eligrey/FileSaver.js/.
My JavaScript Function:
function exportNote(){
var blob = new Blob([document.getElementById('editor').innerHTML], {
type: "application/vnd.openxmlformats-officedocument.wordprocessingml.document;charset=utf-8"
});
saveAs(blob, "note.docx");
}
I get a download that appears to be a word file but when I open it I get the following error:
The Open XML file note.docx cannot be opened because
there are problems with the contents or the file name
might contain invalid characters (for example. /).
Details:
The file is corrupt and cannot be opened.
For graphical purposes:
The text area is the area I am trying to export into a word document which is under <div id="editor"></div>.
jsfiddle
Html
<div id="main">
this is content of div
</div>
JavaScript
function downloadInnerHtml(filename, elId) {
var elHtml = document.getElementById(elId).innerHTML;
var link = document.createElement('a');
link.setAttribute('download', filename);
link.setAttribute('href', 'data:' + 'text/doc' + ';charset=utf-8,' + encodeURIComponent(elHtml));
link.click();
}
var fileName = 'tags.doc'; // You can use the .txt extension if you want
downloadInnerHtml(fileName, 'main');
There is another solution to this problem using an open source library on github under the MIT license: https://github.com/evidenceprime/html-docx-js.
My solution:
function exportNote(contentId){
var filename = 'note.html'
var htmlDoc = document.getElementById(contentId).innerHTML;
var converted = htmlDocx.asBlob(htmlDoc);
saveAs(converted, "notes.docx");
}
Since somebody had a problem in the comments, I'm pasting in what I am actively using. The function I pasted here is darn near verbatim from this site: https://www.codexworld.com/export-html-to-word-doc-docx-using-javascript/
So credit to them. The key to this is that saving the contents of a div to a file is not a proper HTML document, and that causes Word to balk. It needs a BODY, HTML and some of that xmlns attributing. This function gets the innerHtml and wraps it with that, before doing the actual save.
Simply call Export2Word() with the name of the element that holds the content you want to save and the filename:
Export2Word('divMyContent','MyFileNameWithoutExtension');
function Export2Word(element, filename = ''){
var preHtml = "<html xmlns:o='urn:schemas-microsoft-com:office:office' xmlns:w='urn:schemas-microsoft-com:office:word' xmlns='http://www.w3.org/TR/REC-html40'><head><meta charset='utf-8'><title>Export HTML To Doc</title></head><body>";
var postHtml = "</body></html>";
var content = document.getElementById(element).innerHTML;
var html = preHtml+content+postHtml;
var blob = new Blob(['\ufeff', html], {
type: 'application/msword'
});
// Specify link url
var url = 'data:application/vnd.ms-word;charset=utf-8,' + encodeURIComponent(html);
// Specify file name
filename = filename?filename+'.docx':'document.docx';
// Create download link element
var downloadLink = document.createElement("a");
document.body.appendChild(downloadLink);
if(navigator.msSaveOrOpenBlob ){
navigator.msSaveOrOpenBlob(blob, filename);
}else{
// Create a link to the file
downloadLink.href = url;
// Setting the file name
downloadLink.download = filename;
//triggering the function
downloadLink.click();
}
document.body.removeChild(downloadLink);
}

upload file to google drive folder instead of user browser javascript/jsquery

My current script uses the code below to download a CSV file to local drive,
function table2CSV() {
var dataURL = '',
fieldSeparator = ',',
textField = '"',
lineSeparator = '\n',
regExpTesto = /(")/g,
regExp = /[";]/;
$('table tr').each(function() {
var dataRow = '';
if ($('input:checkbox', this).is(':checked') || $(this).is(':first- child'))
{
$('td', this).not(':last').each(function() {
var value = $(this).text();
if (dataRow !== '') dataRow += fieldSeparator;
if (regExp.test(value)) {
value = textField + value.replace(regExpTesto, '$1$1') + textField;
}
dataRow += value;
});
if (dataURL !== '') dataURL += lineSeparator;
dataURL += dataRow;
}
});
window.location.href = 'data:text/csv;charset=utf-8;base64,' + btoa(dataURL);
}
The download is done bye this line as far as I can tell :
window.location.href = 'data:text/csv;charset=utf-8;base64,' + btoa(dataURL);
I would like to be able to have it download(upload/saved) to a shared google drive folder instead.
I have seen similar questions on the forum but can't seem to see how to point the download to a shared google-drive folder.
What must code must be added/changed in order to achieve this ?
Thank you
EDIT: Nevermind, just realised they say it does not support data URIs:
Data URIs and file:// URLs are not supported
I will keep this answer in case anyone else searches for non-data URI uploading
Having a quick look, I came upon Save to Drive
While this might not be exactly what you want, it looks like an easy way to add the ability to save the contents of any URI (hopefully a data URI too) to Google Drive, like so:
<script src="https://apis.google.com/js/platform.js" async defer></script>
<div class="g-savetodrive"
data-src="//example.com/path/to/myfile.pdf"
data-filename="My Statement.pdf"
data-sitename="My Company Name">
</div>

How to support "\n" when exporting csv file with javascript

I am trying to export an array data to a csv file, which works fine unless it has break line("\n"). I hope to make it support break line in a single cell, is it possible?
I tried replace \n into "\n" or "'\n'" but it does not work
The function I am using:
function arrayToCSVConvertor(arrData, ReportTitle) {
var CSV='';
arrData.forEach(function(infoArray, index){
var dataString = infoArray.join(",");
//dataString= dataString.split('\n').join('\\n');//Here, need something to suport "\n"
CSV += dataString+ "\n";
});
if (CSV == '') {
alert("Invalid data");
return;
}
//create a link and click then remove
var link = document.createElement("a");
link.id="lnkDwnldLnk";
//this part will append the anchor tag and remove it after automatic click
document.body.appendChild(link);
var csv = CSV;
/* window.open(encodeURI(csv));*/
var blob = new Blob([csv], { type: 'text/csv' });
//var csvUrl = window.webkitURL.createObjectURL(blob);
var csvUrl = createObjectURL(blob);
var filename = ReportTitle+'.csv';
if(navigator.msSaveBlob){//IE 10
return navigator.msSaveBlob(blob, filename);
}else{
$("#lnkDwnldLnk")
.attr({
'download': filename,
'href': csvUrl
});
$('#lnkDwnldLnk')[0].click();
document.body.removeChild(link);
}
}
PS: I have Chinese words inside the array
I suggest avoiding the pain of working with CSV directly and all it's little variants and just use some library like Papa Parse to handle the job for you.
Basically, the new line to be used within a value should be a \n and the new line to end a record should be \r\n but as #user2864740 commented the results vary based on the encoding of the file and where you are going to open it.

Categories

Resources