The issue with the converting from HTML to DOC is with the input field. Is it possible to extract to DOC only value from input field but not the whole element directly from browser?
Example HTML:
<html>
<head>
<title>How to Export HTML to Word Document with JavaScript</title>
</head>
<body>
<div class="source-html-outer">
<div id="source-html">
<h1>
<center>Artificial Intelligence</center>
</h1>
<h2>Overview</h2>
<p>
Artificial Intelligence(AI) is an emerging technology
demonstrating machine intelligence. The sub studies like <u><i>Neural
Networks</i>, <i>Robatics</i> or <i>Machine Learning</i></u>
are the parts of AI. This technology is expected to be a
prime part of the real world in all levels.
</p>
<input type="text" value="123456" />
<input type="text" value="123456" style="margin-left: 150px;"/>
</div>
<div class="content-footer">
<button id="btn-export" onclick="exportHTML();">Export to word
doc</button>
</div>
</div>
Javascript code that I'm using:
function exportHTML(){
var header = "<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 Word Document with JavaScript</title></head><body>";
var footer = "</body></html>";
var sourceHTML = header+document.getElementById("source-html").innerHTML+footer;
var source = 'data:application/vnd.ms-word;charset=utf-8,' + encodeURIComponent(sourceHTML);
var fileDownload = document.createElement("a");
document.body.appendChild(fileDownload);
fileDownload.href = source;
fileDownload.download = 'document.doc';
fileDownload.click();
document.body.removeChild(fileDownload);
}
Exported doc looks like this, but I would love to export it without input field (just the value)
Please check the JSFIDDLE link for the sample app: https://jsfiddle.net/0cLp8q9e/
You can move those input out from the elements that will render your DOC document. In order to print the values of those input you can create different element and put it there:
function exportHTML(){
// Add inputs values to the document before it rendered:
var inputs = document.querySelectorAll('input');
for (var i=0; i < inputs.length; i++) {
let ps = document.createElement('p');
document.getElementById("source-html").appendChild(ps)
ps.textContent = inputs[i].value;
}
// continue with your code
var header = "<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 Word Document with JavaScript</title></head><body>";
var footer = "</body></html>";
var sourceHTML = header+document.getElementById("source-html").innerHTML+footer;
var source = 'data:application/vnd.ms-word;charset=utf-8,' + encodeURIComponent(sourceHTML);
var fileDownload = document.createElement("a");
document.body.appendChild(fileDownload);
fileDownload.href = source;
fileDownload.download = 'document.doc';
fileDownload.click();
document.body.removeChild(fileDownload);
}
<body>
<div class="source-html-outer">
<div id="source-html">
<h1>
<center>Artificial Intelligence</center>
</h1>
<h2>Overview</h2>
<p>
Artificial Intelligence(AI) is an emerging technology
demonstrating machine intelligence. The sub studies like <u><i>Neural
Networks</i>, <i>Robatics</i> or <i>Machine Learning</i></u>
are the parts of AI. This technology is expected to be a
prime part of the real world in all levels.
</p>
</div>
<div class="content-footer">
<!-- move this form the div you convert to DOC-->
<input type="text" value="123456" />
<input type="text" value="123456" style="margin-left: 150px;"/>
<button id="btn-export" onclick="exportHTML();">Export to word
doc</button>
</div>
</div>
Note: This snippet doesn't work on this site. Copy and paste it to your machine.
I would consider using regex to find and replace the input fields with their raw values. You can use the capture groups to get the value of the input box as per the below example.
This would have the added advantage of not being destructive to the page.
let re = /(\w+)\s(\w+)/;
let str = 'John Smith';
let newstr = str.replace(re, '$2, $1');
console.log(newstr); // Smith, John
Related
I have created a web app to track the working hours of employees at my company, the web app is simple, it just asks employees to enter their entry time when they arrive to work and the time when they leave. I have them enter first, their ID number and a password, then they just fill out the date, the time at which they arrived/left and I added a string for any other details they would like to add. Bringing this data to a google spreadsheet, as seen in the picture. What I want to do is add a VLOOKUP function, in the column that says "Name", that will search for the employees name by looking up their ID number in a data base, the problem is once I add the formula to the column labeled "Name", the spreadsheet stops receiving new data from the web app. Here's a link to a copy of the sheet (https://docs.google.com/spreadsheets/d/1fjpKRi3k0VQ8MOoa5ruCZurXcz6vmVsQt2g3NbELSJA/edit#gid=1409321990) and an here is the simplified the JavaScript and HTML code.
function doGet(e) {
return HtmlService.createHtmlOutputFromFile('Form');
}
function AddRecord(DateEntry, username, ArrivalTime, ExitTime ) {
// get spreadsheet details
var url = 'https://docs.google.com/spreadsheets/d/1fjpKRi3k0VQ8MOoa5ruCZurXcz6vmVsQt2g3NbELSJA/edit#gid=';
//Paste URL of GOOGLE SHEET
var ss1= SpreadsheetApp.openByUrl(url);
var webAppSheet1 = ss1.getSheetByName('ReceivedData');
const Lrow = webAppSheet1.getLastRow();
const sep_col = 2;
const data = [DateEntry, username, ArrivalTime, ExitTime, new Date()];
const data1 = data.slice(0,sep_col);
const data2 = data.slice(sep_col,data.length);
const start_col = 1;
const space_col = 1;
webAppSheet1.getRange(Lrow+1,start_col, 1, data1.length).setValues([data1]);
webAppSheet1.getRange(Lrow+1,start_col+data1.length + space_col, 1, data2.length).setValues([data2]);
}
<!DOCTYPE html>
<html>
<head>
<base target="_top">
<title>Time Tracking</title>
<script>
function AddRow()
{
var DateEntry = document.getElementById("DateEntry").value;
var username = document.getElementById("username").value;
var ArrivalTime = document.getElementById("ArrivalTime").value;
var ExitTime = document.getElementById("ExitTime").value;
google.script.run.AddRecord(DateEntry, username, ArrivalTime, ExitTime);
document.getElementById("DateEntry").value = '';
document.getElementById("username").value = '';
document.getElementById("ArrivalTime").value = '';
document.getElementById("ExitTime").value = '';
}
</script>
</head>
<body>
<div class="content">
<div class="header">
<h2>Time Tracking</h2>
</div>
<div>
<label>ID</label><br>
<input class="field" id="username" type="text">
</div>
<div>
<label>Date</label><br>
<input class="field" type="date" id="DateEntry" />
</div>
<div >
<label>Arrival Time</label><br>
<input class="time" type="time" id="ArrivalTime" /><br>
</div>
<div >
<label>Exit Time</label><br>
<input class="time" type="time" id="ExitTime" /><br>
</div>
<div class="btn">
<button type="button" value="Add" onclick="AddRow()">Send</button>
</div>
</div>
</body>
</html>
Explanation / Issue:
The issue is that you are using an arrayformula which expands until the last available row in the sheet.
However, your goal is to append a new row everytime after the last row with content.
Therefore, by using getLastRow you are getting the wrong row.
Instead of using arrayformula use a single vlookup formula and
take advantage of template literals in order to dynamically
change the vlookup value:
=IFERROR(VLOOKUP(B${Lrow+1};DataBase!A2:B250;2;0);"")
In this way you don't need two different arrays (data1 and data2) because the data can be pasted directly into the sheet:
const vlp_form = `=IFERROR(VLOOKUP(B${Lrow+1};DataBase!A2:B250;2;0);"")`;
const data = [DateEntry, username ,vlp_form, ArrivalTime, ExitTime, new Date()];
webAppSheet1.getRange(Lrow+1,1, 1, data.length).setValues([data]);
I changed your formula to match the DataBase sheet from BBDD to DataBase. Change that back (in the script) if you are using the other sheet name.
Solution:
Modify only AddRecord as follows:
function AddRecord(DateEntry, username, ArrivalTime, ExitTime ) {
// get spreadsheet details
const url = 'https://docs.google.com/spreadsheets/d/1fjpKRi3k0VQ8MOoa5ruCZurXcz6vmVsQt2g3NbELSJA/edit#gid=';
//Paste URL of GOOGLE SHEET
const ss1= SpreadsheetApp.openByUrl(url);
const webAppSheet1 = ss1.getSheetByName('ReceivedData');
const Lrow = webAppSheet1.getLastRow();
const vlp_form = `=IFERROR(VLOOKUP(B${Lrow+1};DataBase!A2:B250;2;0);"")`;
const data = [DateEntry, username ,vlp_form, ArrivalTime, ExitTime, new Date()];
webAppSheet1.getRange(Lrow+1,1, 1, data.length).setValues([data]);
}
Be careful:
In order for the changes to take effect you need to re-deploy your
webApp (either new deployment in the new script editor) or if you are
using the older editor, deploy the web app again by selecting project
version new and click on update.
Also don't forget to save the script changes.
I have a project where we have a compare the original code and code written by the user. The user can code and then on button click we have to compare the written code with original code.
I have both original and new code in string
originalHtml : <html><body style='color:white;background:purple;'></body></html>
newHtml : <html> <body style="background:purple;color:white;"> </body> . </html>
Here there are 3 things to keep in mind
1) White space (should not show the difference for white space)
2) ' and " (should not compare quotes, both are valid in HTML)
3) Attribute order (should show difference only for missing attribute, ignore attributes order)
Any suggestions or alternative solution will be appreciated.
I have created a code pen for you, this will solve your problem.
https://codepen.io/bearnithi/pen/KEPXrX
const textArea = document.getElementById('code');
const btn = document.getElementById('checkcode');
const result = document.getElementById('result');
let originalHTML = `<html><head>
<title>Hello </title>
</head><body>
<p class="hello"></p>
</body>
</html>`
btn.addEventListener('click', checkCode);
function checkCode() {
let newHTMLCode = textArea.value.replace(/\s/g,"");
let oldHTMLCode = originalHTML.replace(/\s/g,"");
if(newHTMLCode === oldHTMLCode) {
console.log(true);
result.innerHTML = 'TRUE';
} else {
console.log(false);
result.innerHTML = 'FALSE';
}
}
<textarea id="code">
</textarea>
</br>
<button id="checkcode">Check Code</button>
<p id="result"></p>
You can convert all of them to one uniform and compare them.
Example:
remove all space, tab (with one space)
replace all ' to "
sort attribute.
and some rule you defined
Example cheerio to get attribute:
var cheerio = require('cheerio');
var yourString = `<html><body attr2='hi' attr1='hello' style='color:white;background:purple;'></body></html>`;
var $ = cheerio.load(yourString);
var yourAttrs = $('body')[0].attribs;
var sorted = {};
Object.keys(yourAttrs).sort().forEach(function(key) {
sorted[key] = yourAttrs[key];
});
console.log(sorted);
As I know, writing a new line is "\n", so I tried many times but it wasn't working. This is my source code and screen shot of result
var ary3 = new Array('seven','eight', 'nine');
for (var i =0; i<ary3.length ; i++){
document.getElementById('demo3').innerHTML += i+"'\nth element\n[enter image description here][1] : " + ary3[i]+"\n";
}
<h1>Show me the array object's entry</h1>
<div id = 'demo3'></div>
<br>
Whitespace is generically collapsed to at most a single space in HTML. Example
<div>a
b c</div>
Will appear as just a b c
You have a few options
Use pre
<pre>a
b</pre>
Will appear as
a
b
Use white-space: pre; CSS on your div
<div style="white-space: pre;">a
b</div>
Will break line breaks
Insert <br/> for `\n' as in
var someString = "a\nb\nc";
someElement.innerHTML = someString.replace(/\n/g, "<br/>");
As for your specific example of looping you also have the option to insert separate elements
function insertDivWithText(parent, text) {
var div = document.createElement("div");
div.appendChild(document.createTextNode(text));
parent.appendChild(div);
}
var demo3 = document.querySelector("#demo3");
var ary3 = ['seven','eight', 'nine'];
for (var i = 0; i < ary3.length ; ++i) {
var div = document.createElement("div");
insertDivWithText(demo3, i + "th element");
insertDivWithText(demo3, "[enter image description here][1] : " + ary3[i]);
}
<h1>Show me the array object's entry</h1>
<div id = 'demo3'></div>
<br>
Also note that using .innerHTML with user data is likely going to expose you to scripting vulnerabilities. Consider using document.createTextNode or element.textContent or element.innerText
The problem is that the newline from JS will be rendered as plain space. HTML is responsible for new line showing, but HTML will not pay attention to simple new line in text. You can check your HTML using developer's tools. You will see that JS made new lines:
derveloper tools
To make new line work, you should add <br /> tag
var ary3 = new Array('seven','eight', 'nine');
for (var i =0; i<ary3.length ; i++){
document.getElementById('demo3').innerHTML += i+"'<br/>\nth element<br/>\n[enter image description here][1] : " + ary3[i]+"<br/>\n";
}
<h1>Show me the array object's entry</h1>
<div id = 'demo3'></div>
<br>
You are writing HTML, DOM, so you have to use <br> tag, not newline.
If you are trying to create a HTML new line, use <br>.
Html code for new line is <br>.
As in:
document.getElementById('demo3').innerHTML += i+"'nth element<br>[enter image description
Your output is html. In html, use the <br /> tag to break the line.
Using a client side script in a webpage (no server code), like javascript, how do I import, edit, and replace text in a txt file? I am simply trying to use two variables (Name and IP Address) and replace them in a text file. The existing text file is very long and I would like to automate this process. It would be nice for the script to also automatically create a new text file each time it is submitted. THANKS!
Here's my code:
<html>
<head>
<title>TExt File Changer v1</title>
<script type="text/javascript">
function findaNamendReplaceAll() {
var findaName = "Site_Name";
var findaCIP = "192.168.0.5";
var replaceaName = document.myInput.replaceWithName.value;
var replaceaCIP = document.myInput.replaceWithCIP.value;
var fulltexta = document.myInput.fulltext.value;
/*
var nr = new RegExp(findaName,"ig");
var tmp = fulltexta.replace(/Site_Name/gi, replaceaName).replace(/192.168.0.5 /gi,replaceaCIP);
document.myInput.fulltext.value = tmp;
*/
document.myInput.fulltext.value = fulltexta.replace(/Site_Name/gi, replaceaName).replace(/192.168.0.5/gi,replaceaCIP);
}
var str += ‘SECTION ethernet’/n;
str += ‘ETHERNET=UP’/n;
str += ‘BOOTP=server’/n;
str += ‘HOSTNAME=Site_Name’/n;
str += ‘IPADDR=192.168.0.4’/n;
str += ‘NETMASK=255.255.255.0’/n;
str += ‘DNS=‘/n;
str += ‘DHCP_RANGE_L=192.168.0.20’/n;
str += ‘DHCP_RANGE_U=192.168.0.100’/n;
str += ‘SEARCH=‘/n;
str += ‘ZEROCONF=YES’/n;
str += ‘ETH0_ADD_DEFAULT=on’/n;
str += ‘ENDSECTION ethernet’/n;
str += ‘‘;
</script>
</head>
<body>
<form name="myInput" onsubmit="return false">
<h1>Configuration Tool</h1>
New Site Name: <input type="text" id="replaceWithName" name="replaceWithName" value="">
<br><br>
New Camera IP: <input type="text" id="replaceWithCIP" name="replaceWithCIP" value="">
<br><br>
<button onclick="findaNamendReplaceAll()">Go</button>
<br><br>
<textarea id="fulltext" name="fulltext" rows="20" cols="100">
SECTION ethernet
ETHERNET=UP
BOOTP=no
HOSTNAME=Site_Name
IPADDR=192.168.0.4
NETMASK=255.255.255.0
DNS=
DHCP_RANGE_L=
DHCP_RANGE_U=
SEARCH=
ZEROCONF=YES
ETH0_ADD_DEFAULT=on
ENDSECTION ethernet
</textarea>
<br>
<button onclick="document.getElementById('fulltext').value = ''">Clear</button>
<button onclick="document.getElementById('fulltext').value = str">Restore</button>
</form>
</body>
</html></pre>
You can do it easily, provided you adhere to two limitations.
1) Internet Explorer on windows
2) Use of ActiveXObjects
I did a project that required assembling various data as found in excel spreadsheets. My input file was a hand-edited json file - specifying things like filenames and paths. Once the json was loaded, I used an ActiveXObject to open and control Excel in just the same manner as one would from within a VBA program.
As a result, I don't have any code to load arbitrary data from an arbitrary filename.
However, this snippet should give you enough to get started.
Note: The code assumes that IE still gives you a fully qualified path for any file selected with an <input type='file'/> Chrome, FF and Opera only give you the filename - they do not tell you which folder it resides in.
function byId(e){return document.getElementById(e);}
function writeDataToFile()
{
var mFSO = new ActiveXObject("Scripting.FileSystemObject");
var mFile = mFSO.createtextfile(outputFilename);
mFile.write( byId('outputTextArea').value );
mFile.close();
alert("text saved to '" + outputFilename + "'");
}
var theNewParagraph = document.createElement('p');
var theBoldBit = document.createElement('b');
var theBR = document.createElement('br');
theNewParagraph.setAttribute('title','The test paragraph');
var theText1 = document.createTextNode('This is a sample of some ');
var theText2 = document.createTextNode('HTML you might');
var theText3 = document.createTextNode('have');
var theText4 = document.createTextNode(' in your document');
theBoldBit.appendChild(theText2);
theBoldBit.appendChild(theBR);
theBoldBit.appendChild(theText3);
theNewParagraph.appendChild(theText1);
theNewParagraph.appendChild(theBoldBit);
theNewParagraph.appendChild(theText4);
document.getElementById('someElementId').appendChild(theNewParagraph);
Also, can anyone help me by explaining this?
What you have is a snippet of JavaScript code. I've added comments to the code to explain each section:
// Create 3 elements, a <p>, a <b> and a <br>
var theNewParagraph = document.createElement('p');
var theBoldBit = document.createElement('b');
var theBR = document.createElement('br');
// Set the title attribute of the <p> element we created
theNewParagraph.setAttribute('title','The test paragraph');
// Create 4 "text nodes", these appear as text when added to elements
var theText1 = document.createTextNode('This is a sample of some ');
var theText2 = document.createTextNode('HTML you might');
var theText3 = document.createTextNode('have');
var theText4 = document.createTextNode(' in your document');
/* Add the second text node, the <br> element and the 3rd text node to the
<b> element we created */
theBoldBit.appendChild(theText2);
theBoldBit.appendChild(theBR);
theBoldBit.appendChild(theText3);
/* Add the first text node, the <b> element and the 4th text node to the
<p> element we created. All nodes are now descendants of the <p> */
theNewParagraph.appendChild(theText1);
theNewParagraph.appendChild(theBoldBit);
theNewParagraph.appendChild(theText4);
/* Finally, add the <p> element to an element with an id attribute of
someElementId, so we can see all the content on our page */
document.getElementById('someElementId').appendChild(theNewParagraph);
The result is the following HTML as the content of someElementId:
<p title="The test paragraph">This is a sample of some <b>HTML you might<br>
have</b> in your document</p>
Others have explained how to add this script to your document using the <script> element.
Put the above in a <script type="text/javascript"> at the bottom of your page and make sure there's an <div id="someElementId"> in your document.
What it's doing is creating a new <p>, <b> and <br> tag. It then sets the title on the paragraph, adds some text to all tags and finally adds the whole mess to an element with id #someElementId.
You can see it in action here.
Here is a suitable test harness. Paste the following into a new .html file:
<html><head><script language="javascript"><!--// your javascript here:
function _onload()
{
var theNewParagraph = document.createElement('p');
var theBoldBit = document.createElement('b');
var theBR = document.createElement('br');
theNewParagraph.setAttribute('title','The test paragraph');
var theText1 = document.createTextNode('This is a sample of some ');
var theText2 = document.createTextNode('HTML you might');
var theText3 = document.createTextNode('have');
var theText4 = document.createTextNode(' in your document');
theBoldBit.appendChild(theText2);
theBoldBit.appendChild(theBR);
theBoldBit.appendChild(theText3);
theNewParagraph.appendChild(theText1);
theNewParagraph.appendChild(theBoldBit);
theNewParagraph.appendChild(theText4);
document.getElementById('someElementId').appendChild(theNewParagraph);
}
//--></script></head><body onload='_onload()' id='someElementId'></body></html>
How to run:
<head>
<script type="text/javascript">
function CreateTestParagraph () {
var theNewParagraph = document.createElement('p');
var theBoldBit = document.createElement('b');
var theBR = document.createElement('br');
theNewParagraph.setAttribute('title','The test paragraph');
var theText1 = document.createTextNode('This is a sample of some ');
var theText2 = document.createTextNode('HTML you might');
var theText3 = document.createTextNode('have');
var theText4 = document.createTextNode(' in your document');
theBoldBit.appendChild(theText2);
theBoldBit.appendChild(theBR);
theBoldBit.appendChild(theText3);
theNewParagraph.appendChild(theText1);
theNewParagraph.appendChild(theBoldBit);
theNewParagraph.appendChild(theText4);
document.getElementById('someElementId').appendChild(theNewParagraph);
}
</script>
</head>
<body onload="CreateTestParagraph ()">
<div id="someElementId"></div>
</body>
Your CreateTestParagraph method creates the following HTML content dynamically:
<p title="The test paragraph">This is a sample of some <b>HTML you might<br>have</b> in your document</p>
and put that contents into the someElementId element.
Related links:
createElement method,
createTextNode method,
appendChild method,
getElementById method,
onload event