Home >Web Front-end >H5 Tutorial >How to export HTML to generate word document?

How to export HTML to generate word document?

零下一度
零下一度Original
2018-05-18 13:41:0523767browse

Foreword:

During project development, I encountered the need to export the content of the HTML page into a word document, so I wrote this essay.

Of course, the project development time was a bit tight, and the first thing I thought of was to use plug-ins, so Baidu took a look. Here are two methods for exporting word documents.

Method 1: Export word through jquery.wordexport.js

Remarks: Compatible with IE9 and above

After browsing the code of the jquery.wordexport.js plug-in, I learned that through This plug-in can export text and pictures, and the pictures are first drawn in the form of canvas

, and the text needs to rely on the FileSaver.js plug-in. The FileSaver.js plug-in mainly uses the new file operation feature of H5 new Blob() and new FileReader()

to implement text export.

Plug-in source code:

FileSaver.js

  1 /* FileSaver.js  
  2  * A saveAs() FileSaver implementation.  
  3  * 1.3.2  
  4  * 2016-06-16 18:25:19  
  5  *  
  6  * By Eli Grey,   
  7  * License: MIT  
  8  *   See   
  9  */ 
  10  
  11 /*global self */ 
  12 /*jslint bitwise: true, indent: 4, laxbreak: true, laxcomma: true, smarttabs: true, plusplus: true */ 
  13  
  14 /*! @source  */ 
  15  
  16 var saveAs = saveAs || (function(view) { 
  17         "use strict"; 
  18         // IE <10 is explicitly unsupported 
  19         if (typeof view === "undefined" || typeof navigator !== "undefined" && /MSIE [1-9]\./.test(navigator.userAgent)) { 
  20             return; 
  21         } 
  22         var 
  23             doc = view.document 
  24         // only get URL when necessary in case Blob.js hasn&#39;t overridden it yet 
  25             , get_URL = function() { 
  26                 return view.URL || view.webkitURL || view; 
  27             } 
  28             , save_link = doc.createElementNS("", "a") 
  29             , can_use_save_link = "download" in save_link 
  30             , click = function(node) { 
  31                 var event = new MouseEvent("click"); 
  32                 node.dispatchEvent(event); 
  33             } 
  34             , is_safari = /constructor/i.test(view.HTMLElement) 
  35             , is_chrome_ios =/CriOS\/[\d]+/.test(navigator.userAgent) 
  36             , throw_outside = function(ex) { 
  37                 (view.setImmediate || view.setTimeout)(function() { 
  38                     throw ex; 
  39                 }, 0); 
  40             }
  41             , force_saveable_type = "application/octet-stream" 
  42         // the Blob API is fundamentally broken as there is no "downloadfinished" event to subscribe to 
  43             , arbitrary_revoke_timeout = 1000 * 40 // in ms 
  44             , revoke = function(file) { 
  45                 var revoker = function() { 
  46                     if (typeof file === "string") { // file is an object URL 
  47                         get_URL().revokeObjectURL(file); 
  48                     } else { // file is a File 
  49                         file.remove(); 
  50                     } 
  51                 }; 
  52                 setTimeout(revoker, arbitrary_revoke_timeout); 
  53             } 
  54             , dispatch = function(filesaver, event_types, event) { 
  55                 event_types = [].concat(event_types); 
  56                 var i = event_types.length; 
  57                 while (i--) { 
  58                     var listener = filesaver["on" + event_types[i]]; 
  59                     if (typeof listener === "function") { 
  60                         try { 
  61                             listener.call(filesaver, event || filesaver); 
  62                         } catch (ex) { 
  63                             throw_outside(ex); 
  64                         } 
  65                     } 
  66                 } 
  67             } 
  68             , auto_bom = function(blob) { 
  69                 // prepend BOM for UTF-8 XML and text/* types (including HTML) 
  70                 // note: your browser will automatically convert UTF-16 U+FEFF to EF BB BF 
  71                 if (/^\s*(?:text\/\S*|application\/xml|\S*\/\S*\+xml)\s*;.*charset\s*=\s*utf-8/i.test(blob.type)) { 
  72                     return new Blob([String.fromCharCode(0xFEFF), blob], {type: blob.type}); 
  73                 } 
  74                 return blob; 
  75             } 
  76             , FileSaver = function(blob, name, no_auto_bom) { 
  77                 if (!no_auto_bom) { 
  78                     blob = auto_bom(blob); 
  79                 } 
  80                 // First try a.download, then web filesystem, then object URLs 
  81                 var 
  82                     filesaver = this 
  83                     , type = blob.type 
  84                     , force = type === force_saveable_type 
  85                     , object_url 
  86                     , dispatch_all = function() { 
  87                         dispatch(filesaver, "writestart progress write writeend".split(" ")); 
  88                     } 
  89                 // on any filesys errors revert to saving with object URLs 
  90                     , fs_error = function() { 
  91                         if ((is_chrome_ios || (force && is_safari)) && view.FileReader) { 
  92                             // Safari doesn&#39;t allow downloading of blob urls 
  93                             var reader = new FileReader(); 
  94                             reader.onloadend = function() { 
  95                                 var url = is_chrome_ios ? reader.result : reader.result.replace(/^data:[^;]*;/, &#39;data:attachment/file;&#39;); 
  96                                 var popup = view.open(url, &#39;_blank&#39;); 
  97                                 if(!popup) view.location.href = url; 
  98                                 url=undefined; // release reference before dispatching 
  99                                 filesaver.readyState = filesaver.DONE;
  100                                 dispatch_all();
  101                             };
  102                             reader.readAsDataURL(blob);
  103                             filesaver.readyState = filesaver.INIT;
  104                             return;
  105                         }
  106                         // don&#39;t create more object URLs than needed
  107                         if (!object_url) {
  108                             object_url = get_URL().createObjectURL(blob);
  109                         }
  110                         if (force) {
  111                             view.location.href = object_url;
  112                         } else {
  113                             var opened = view.open(object_url, "_blank");
  114                             if (!opened) {
  115                                 // Apple does not allow window.open, see 
  116                                 view.location.href = object_url;
  117                             }
  118                         }
  119                         filesaver.readyState = filesaver.DONE;
  120                         dispatch_all();
  121                         revoke(object_url);
  122                     }
  123                     ;
  124                 filesaver.readyState = filesaver.INIT;
  125 
  126                 if (can_use_save_link) {
  127                     object_url = get_URL().createObjectURL(blob);
  128                     setTimeout(function() {
  129                         save_link.href = object_url;
  130                         save_link.download = name;
  131                         click(save_link);
  132                         dispatch_all();
  133                         revoke(object_url);
  134                         filesaver.readyState = filesaver.DONE;
  135                     });
  136                     return;
  137                 }
  138 
  139                 fs_error();
  140             }
  141             , FS_proto = FileSaver.prototype
  142             , saveAs = function(blob, name, no_auto_bom) {
  143                 return new FileSaver(blob, name || blob.name || "download", no_auto_bom);
  144             }
  145             ;
  146         // IE 10+ (native saveAs)
  147         if (typeof navigator !== "undefined" && navigator.msSaveOrOpenBlob) {
  148             return function(blob, name, no_auto_bom) {
  149                 name = name || blob.name || "download";
  150 
  151                 if (!no_auto_bom) {
  152                     blob = auto_bom(blob);
  153                 }
  154                 return navigator.msSaveOrOpenBlob(blob, name);
  155             };
  156         }
  157 
  158         FS_proto.abort = function(){};
  159         FS_proto.readyState = FS_proto.INIT = 0;
  160         FS_proto.WRITING = 1;
  161         FS_proto.DONE = 2;
  162 
  163         FS_proto.error =
  164             FS_proto.onwritestart =
  165                 FS_proto.onprogress =
  166                     FS_proto.onwrite =
  167                         FS_proto.onabort =
  168                             FS_proto.onerror =
  169                                 FS_proto.onwriteend =
  170                                     null;
  171 
  172         return saveAs;
  173     }(
  174         typeof self !== "undefined" && self
  175         || typeof window !== "undefined" && window
  176         || this.content
  177     ));
  178 // `self` is undefined in Firefox for Android content script context
  179 // while `this` is nsIContentFrameMessageManager
  180 // with an attribute `content` that corresponds to the window
  181 
  182 if (typeof module !== "undefined" && module.exports) {
  183     module.exports.saveAs = saveAs;
  184 } else if ((typeof define !== "undefined" && define !== null) && (define.amd !== null)) {
  185     define([], function() {
  186         return saveAs;
  187     });
  188 }

View Code

jquery.wordexport.js

 1 if (typeof jQuery !== "undefined" && typeof saveAs !== "undefined") { 
 2     (function($) { 
 3         $.fn.wordExport = function(fileName) {
 4             fileName = typeof fileName !== &#39;undefined&#39; ? fileName : "jQuery-Word-Export"; 
 5             var static = { 
 6                 mhtml: { 
 7                     top: "Mime-Version: 1.0\nContent-Base: " + location.href + "\nContent-Type: Multipart/related; boundary=\"NEXT.ITEM-BOUNDARY\";type=\"text/html\"\n\n--NEXT.ITEM-BOUNDARY\nContent-Type: text/html; charset=\"utf-8\"\nContent-Location: " + location.href + "\n\n<!DOCTYPE html>\n<html>\n_html_</html>", 
 8                     head: "<head>\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">\n<style>\n_styles_\n</style>\n</head>\n", 
 9                     body: "<body>_body_</body>"
 10                 }
 11             };
 12             var options = {
 13                 maxWidth: 624
 14             };
 15             // Clone selected element before manipulating it
 16             var markup = $(this).clone();
 17 
 18             // Remove hidden elements from the output
 19             markup.each(function() {
 20                 var self = $(this);
 21                 if (self.is(&#39;:hidden&#39;))
 22                     self.remove();
 23             });
 24 
 25             // Embed all images using Data URLs
 26             var images = Array();
 27             var img = markup.find(&#39;img&#39;);
 28             for (var i = 0; i < img.length; i++) {
 29                 // Calculate dimensions of output image
 30                 var w = Math.min(img[i].width, options.maxWidth);
 31                 var h = img[i].height * (w / img[i].width);
 32                 // Create canvas for converting image to data URL
 33                 var canvas = document.createElement("CANVAS");
 34                 canvas.width = w;
 35                 canvas.height = h;
 36                 // Draw image to canvas
 37                 var context = canvas.getContext(&#39;2d&#39;);
 38                 context.drawImage(img[i], 0, 0, w, h);
 39                 // Get data URL encoding of image
 40                 var uri = canvas.toDataURL("image/png/jpg");
 41                 $(img[i]).attr("src", img[i].src);
 42                 img[i].width = w;
 43                 img[i].height = h;
 44                 // Save encoded image to array
 45                 images[i] = {
 46                     type: uri.substring(uri.indexOf(":") + 1, uri.indexOf(";")),
 47                     encoding: uri.substring(uri.indexOf(";") + 1, uri.indexOf(",")),
 48                     location: $(img[i]).attr("src"),
 49                     data: uri.substring(uri.indexOf(",") + 1)
 50                 };
 51             }
 52 
 53             // Prepare bottom of mhtml file with image data
 54             var mhtmlBottom = "\n";
 55             for (var i = 0; i < images.length; i++) {
 56                 mhtmlBottom += "--NEXT.ITEM-BOUNDARY\n";
 57                 mhtmlBottom += "Content-Location: " + images[i].location + "\n";
 58                 mhtmlBottom += "Content-Type: " + images[i].type + "\n";
 59                 mhtmlBottom += "Content-Transfer-Encoding: " + images[i].encoding + "\n\n";
 60                 mhtmlBottom += images[i].data + "\n\n";
 61             }
 62             mhtmlBottom += "--NEXT.ITEM-BOUNDARY--";
 63 
 64             //TODO: load css from included stylesheet
 65 
 66             //var styles=&#39; /* Font Definitions */@font-face{font-family:宋体;panose-1:2 1 6 0 3 1 1 1 1 1;mso-font-alt:SimSun;mso-font-charset:134;mso-generic-font-family:auto;mso-font-pitch:variable;mso-font-signature:3 680460288 22 0 262145 0;}  @font-face{font-family:"Cambria Math";panose-1:2 4 5 3 5 4 6 3 2 4;mso-font-charset:1;mso-generic-font-family:roman;mso-font-format:other;mso-font-pitch:variable;mso-font-signature:0 0 0 0 0 0;}  @font-face{font-family:"\@宋体";panose-1:2 1 6 0 3 1 1 1 1 1;mso-font-charset:134;mso-generic-font-family:auto;mso-font-pitch:variable;mso-font-signature:3 680460288 22 0 262145 0;}/* Style Definitions */p.MsoNormal, li.MsoNormal, p.MsoNormal{mso-style-unhide:no;mso-style-qformat:yes;mso-style-parent:"";margin:0cm;margin-bottom:.0001pt;mso-pagination:widow-orphan;font-size:14.0pt;font-family:宋体;mso-bidi-font-family:宋体;}p.MsoHeader, li.MsoHeader, p.MsoHeader{mso-style-noshow:yes;mso-style-priority:99;mso-style-link:"页眉 Char";margin:0cm;margin-bottom:.0001pt;text-align:center;mso-pagination:widow-orphan;layout-grid-mode:char;font-size:9.0pt;font-family:宋体;mso-bidi-font-family:宋体;}p.MsoFooter, li.MsoFooter, p.MsoFooter{mso-style-noshow:yes;mso-style-priority:99;mso-style-link:"页脚 Char";margin:0cm;margin-bottom:.0001pt;mso-pagination:widow-orphan;layout-grid-mode:char;font-size:9.0pt;font-family:宋体;mso-bidi-font-family:宋体;}p.MsoAcetate, li.MsoAcetate, p.MsoAcetate{mso-style-noshow:yes;mso-style-priority:99;mso-style-link:"批注框文本 Char";margin:0cm;margin-bottom:.0001pt;mso-pagination:widow-orphan;font-size:9.0pt;font-family:宋体;mso-bidi-font-family:宋体;}span.Char{mso-style-name:"页眉 Char";mso-style-noshow:yes;mso-style-priority:99;mso-style-unhide:no;mso-style-locked:yes;mso-style-link:页眉;font-family:宋体;mso-ascii-font-family:宋体;mso-fareast-font-family:宋体;mso-hansi-font-family:宋体;}span.Char0{mso-style-name:"页脚 Char";mso-style-noshow:yes;mso-style-priority:99;mso-style-unhide:no;mso-style-locked:yes;mso-style-link:页脚;font-family:宋体;mso-ascii-font-family:宋体;mso-fareast-font-family:宋体;mso-hansi-font-family:宋体;}span.Char1{mso-style-name:"批注框文本 Char";mso-style-noshow:yes;mso-style-priority:99;mso-style-unhide:no;mso-style-locked:yes;mso-style-link:批注框文本;font-family:宋体;mso-ascii-font-family:宋体;mso-fareast-font-family:宋体;mso-hansi-font-family:宋体;}p.msochpdefault, li.msochpdefault, p.msochpdefault{mso-style-name:msochpdefault;mso-style-unhide:no;mso-margin-top-alt:auto;margin-right:0cm;mso-margin-bottom-alt:auto;margin-left:0cm;mso-pagination:widow-orphan;font-size:10.0pt;font-family:宋体;mso-bidi-font-family:宋体;}span.msonormal0{mso-style-name:msonormal;mso-style-unhide:no;}.MsoChpDefault{mso-style-type:export-only;mso-default-props:yes;font-size:10.0pt;mso-ansi-font-size:10.0pt;mso-bidi-font-size:10.0pt;mso-ascii-font-family:"Times New Roman";mso-hansi-font-family:"Times New Roman";mso-font-kerning:0pt;}/* Page Definitions */  @page WordSection1{size:595.3pt 841.9pt;margin:72.0pt 90.0pt 72.0pt 90.0pt;mso-header-margin:42.55pt;mso-footer-margin:49.6pt;mso-paper-source:0;}p.WordSection1{page:WordSection1;}&#39;;
 67 
 68             var styles="";
 69 
 70             // Aggregate parts of the file together
 71             var fileContent = static.mhtml.top.replace("_html_", static.mhtml.head.replace("_styles_", styles) + static.mhtml.body.replace("_body_", markup.html())) + mhtmlBottom;
 72 
 73             // Create a Blob with the file contents
 74             var blob = new Blob([fileContent], {
 75                 type: "application/msword;charset=utf-8"
 76             });
 77             saveAs(blob, fileName + ".doc");
 78         };
 79     })(jQuery);
 80 } else {
 81     if (typeof jQuery === "undefined") {
 82         console.error("jQuery Word Export: missing dependency (jQuery)");
 83     }
 84     if (typeof saveAs === "undefined") {
 85         console.error("jQuery Word Export: missing dependency (FileSaver.js)");
 86     }
 87 }

View Code

Plug-in call:

 1 <!DOCTYPE html> 
 2 <html> 
 3 <head lang="en"> 
 4     <meta charset="UTF-8"> 
 5     <title>生成word文档</title> 
 6 </head> 
 7 <body lang=ZH-CN style=&#39;tab-interval:21.0pt&#39;> 
 8 <p class="word"> 
 9     <p align="center" style="font-size:20pt;font-weight:bold;">JS导出Word文档</p>
 10 </p>
 11 <input type="button" value="导出word">
 12 <script src="https://cdn.bootcss.com/jquery/2.2.4/jquery.js?1.1.11"></script>
 13 <script type="text/javascript" src="js/FileSaver.js?1.1.11"></script>
 14 <script type="text/javascript" src="js/jquery.wordexport.js?1.1.11"></script>
 15 <script>
 16     $(function(){
 17         $("input[type=&#39;button&#39;]").click(function(event) {
 18             $(".word").wordExport(&#39;生成word文档&#39;);
 19         });
 20     })
 21 </script>
 22 </body>
 23 </html>

You can export a word document by directly calling the wordExport() interface, and the passed parameter is the name of the exported word file.

Additional:

It is invalid to set the style through our regular external style writing. Through personal practice, I found that it is necessary to write inline style to take effect, and the unit also needs to follow the configuration of word

Unit pt setting.

The jquery.wordexport.js plug-in is configured with a style style for us to supplement the style settings:

But after personal practice, I set it The style cannot take effect, it can only take effect through inline setting.

Screenshot:

Method 2: Generate word document through Baidu js template engine

Mainly through js template setting corresponding tag, and then XDoc.to(baidu.template()) exports word, and the advantage of using Baidu js template engine is that it can also export PDF files.

Complete demo:

 1 <!DOCTYPE html> 
 2 <html> 
 3 <head> 
 4     <meta charset="UTF-8"> 
 5     <script type="text/javascript" src="www.xdocin.com/xdoc.js?1.1.11"></script> 
 6     <script type="text/javascript" src="http://www.xdocin.com/baiduTemplate.js?1.1.11"></script> 
 7     <style> 
 8         .head{ 
 9             font-size: 29px;
 10             display: block;
 11         }
 12         .content{
 13             display: block;
 14         }
 15     </style>
 16 </head>
 17 <body>
 18 <input type="button" onclick="gen(&#39;pdf&#39;)" value="生成PDF"/>
 19 <input type="button" onclick="gen(&#39;docx&#39;)" value="生成Word"/>
 20 <br/>
 21 <script id="tmpl" type="text/html">
 22     <xdoc version="A.3.0">
 23         <body>
 24         <para heading="1" lineSpacing="28">
 25             <text class="head" valign="center" fontName="标宋" fontSize="29"><%=title%></text>
 26         </para>
 27         <para>
 28             <img  src="<%=img%>" sizeType="autosize"/>
 29         </para>
 30         <para lineSpacing="9">
 31             <text class="content" fontName="仿宋" fontSize="18"><%=content%></text>
 32         </para>
 33         </body>
 34     </xdoc>
 35 </script>
 36 <script src="https://cdn.bootcss.com/jquery/2.2.4/jquery.js?1.1.11"></script>
 37 <script type="text/javascript">
 38     var type="docx";//pdf
 39     var data = {
 40         title: "导出"+type+"文件",
 41         img: "",
 42         content: "我这样就可以导出"+type+"格式的文件了,是不是很方便",
 43     };
 44     function renderTemplate(){
 45         var template=$("#tmpl").html();
 46         var html=template.replace(/<%=title%>/,data.title)
 47                 .replace(/<%=img%>/,data.img)
 48                 .replace(/<%=content%>/,data.content);
 49         $("body").append(html);
 50     }
 51     renderTemplate();
 52     function gen(type) {
 53         XDoc.to(baidu.template(&#39;tmpl&#39;, data), type, {}, "_blank");
 54     }
 55     console.log(&#39;&#39;);
 56 </script>
 57 </body>
 58 </html>

Here I call the js template to render into HTML through the renderTemplate function, realizing the combination of text display and exported content. And because the word document exported here needs to be specially styled, we can set it by adding .class under the page style display.

Attached are some exported word document style settings:

Screenshot:

The above is the detailed content of How to export HTML to generate word document?. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn