Reputation: 512
I am using angular2 and I want to generate a docx file using an object. I want my docx file to contain footers, headers, tables etc. The best solution i can come up with is first creating an HTML file, then converting it to docx file. But this does not seem right. Is there an easier and more convenient way to do what I want to do? Here is the method I use:
exportAsDoc() {
const 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>';
const postHtml = '</body></html>';
let innerHtml = '';
// Specify file name
const filename = this.respSheet.title + '.doc';
const respSheetKpis = this.respSheet.sheet_kpis;
respSheetKpis.forEach(x => {
const footer = '<p style="text-align: center">' + x.kpi.name + ' - ' + x.kpiValue + '</p>';
innerHtml += footer;
x.sheet_kpi_dimensions.forEach(dimension => {
if (dimension.dimension !== undefined) innerHtml += dimension.dimension.name;
let table = '<table>\n' +
' <tr>\n' +
' <th>Istatistik adi</th>\n' +
' <th>Degeri</th> \n' +
' </tr>\n';
const data = dimension.data;
if (data !== undefined) {
for ( let i = 0 ; i < data.length ; i ++ ) {
table += ' <tr>\n' +
' <th>' + data[ i ].title + '</th>\n' +
' <th>' + data[ i ].value + '</th> \n' +
' </tr>\n';
}
table += '</table>';
innerHtml += table;
}
})
});
const html = preHtml + innerHtml + postHtml;
const blob = new Blob(['\ufeff', html], {
type: 'application/msword'
});
// Specify link url
const url = 'data:application/vnd.ms-word;charset=utf-8,' + encodeURIComponent(html);
// Create download link element
const 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);
}
Upvotes: 3
Views: 18887
Reputation: 1083
Too late for the reply but this might be helpful for someone else. One way to implement this is using the docx.js
I have added simple example and link to example and documentation
https://stackblitz.com/edit/angular-afvxtz
TS file:
import { Component } from '@angular/core';
import { Packer } from 'docx';
import { saveAs } from 'file-saver/FileSaver';
import { DocumentCreator } from './cv-generator';
@Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
name = 'Angular';
public download(): void {
const documentCreator = new DocumentCreator();
const doc = documentCreator.create();
doc.createParagraph("Test heading1, bold and italicized").heading1();
doc.createParagraph("Some simple content");
const packer = new Packer();
packer.toBlob(doc).then(blob => {
console.log(blob);
saveAs(blob, "example.docx");
console.log("Document created successfully");
});
}
}
cv-generator.ts file:
import { Document, Paragraph, Packer, TextRun } from 'docx';
export class DocumentCreator {
create() {
const title = 'EXECUTIVE SUMMARY';
const document = new Document();
document.addParagraph(new Paragraph(title).title());
document.addParagraph(this.createHeading('Exception Overview'));
return document;
}
createHeading(text) {
return new Paragraph(text).heading1().thematicBreak();
}
}
HTML:
<button class="em-primary-button" (click)="download()">Download file</button>
Upvotes: 7
Reputation: 778
in my opinion the simplest tool to work for generating documents on the front end is Docx.js. I think it can help you solve your problem.
In this project you generate a simple HTML using a Javascript (or typescript) code, and save as a Docx file. Something like that:
<script>
function exportAsDoc() {
var content = '<!DOCTYPE html>';
var items = [
{col1: "foo", col2: "bar"}
];
content += "<html><body><table>";
content += "<tr>";
content += "<th>col1</th><th>col2</th>";
content += "</tr>";
for (var i=0; i<items.length; i++) {
content += "<tr>";
content += "<td>" + items[i].col1 + "</td>";
content += "<td>" + items[i].col2 + "</td>";
content += "</tr>";
}
content += "</table></body></html>";
var converted = htmlDocx.asBlob(content, {orientation: "landscape"});
console.log(converted);
saveAs(converted, 'test.docx');
}
</script>
On the project website you have a complete example using an online editor. Just follow the example and adapt to your project
http://evidenceprime.github.io/html-docx-js/
Upvotes: 1