excel.js 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261
  1. (function(){
  2. if(typeof Object.keys != 'function') {
  3. Object.keys = function(object) {
  4. var keys = [], property;
  5. for (property in object) {
  6. if (object.hasOwnProperty(property)) {
  7. keys.push(property);
  8. }
  9. }
  10. return keys;
  11. };
  12. }
  13. if(typeof StringBuffer === 'undefined') {
  14. StringBuffer = function() {
  15. this.data = [];
  16. }
  17. StringBuffer.prototype.append = function(s) {
  18. var m = this;
  19. if(s instanceof StringBuffer) {
  20. for(var i = 0,l = s.data.length;i < l;i++ ) {
  21. m.data.push(s.data[i]);
  22. }
  23. } else
  24. m.data.push(s);
  25. return m;
  26. }
  27. StringBuffer.prototype.toString = function() {
  28. return this.data.join("");
  29. };
  30. }
  31. if(typeof $excel === 'undefined') {
  32. $excel = function(){
  33. var self = this, config = function(cfg){
  34. if(cfg) {
  35. for(var p in cfg) {
  36. self[p] = cfg[p];
  37. if(p == 'headers')
  38. self.keys = Object.keys(self[p]);
  39. }
  40. }
  41. if(self.keys) {
  42. generalRowTpl();
  43. }
  44. return self;
  45. }, generalRowTpl = function() {
  46. var tpl = new StringBuffer().append('<Row>'), reg = {}, exp = [], g;
  47. for(var i in self.keys) {
  48. k = self.keys[i];
  49. t = self.types[k];
  50. p = 'String';
  51. y = 'Cell';
  52. g = '!' + (k == '?' ? '#' : k) + '!';// error char ?
  53. if(t == 'yyyy-m-d') {
  54. y = 'Date';
  55. p = 'DateTime';
  56. } else if(t == 'yyyy-m-d hh:MM:ss') {
  57. y = 'DateTime';
  58. p = 'DateTime';
  59. } else if(t && t.substr(0, 1) == '0') {
  60. p = 'Number';
  61. }
  62. tpl.append('<Cell ss:StyleID="' + y + '"><Data ss:Type="' + p + '">' + g + '</Data></Cell>');
  63. exp.push(g.replace(/\(|\)|\\|\^|\$|\[|\]|\.|\*|\+|\?|\||\<|\>|\-|\&/g, function(m){
  64. return m == '?' ? '#' : ('\\' + m);
  65. }));
  66. reg[g] = k;
  67. }
  68. self.rowTpl = tpl.append('</Row>').toString();
  69. self.rowReg = reg;
  70. self.rowExp = new RegExp(exp.join('|'), 'g');
  71. };
  72. config({
  73. headers: [],
  74. widths: [],
  75. types: [],
  76. locks: [],
  77. combos: [],
  78. comboMaps: {},
  79. sheets: 0,
  80. rowCount: 0,
  81. rowTpl: '',
  82. rowReg: {},
  83. rowExp: '',
  84. xml: new StringBuffer()
  85. });
  86. config(arguments[0]);
  87. return self;
  88. };
  89. $excel.prototype.clear = function() {
  90. var self = this;
  91. delete self.xml;
  92. };
  93. $excel.prototype.create = function() {
  94. var self = this;
  95. var url = URL.createObjectURL(self.getBlob());
  96. self.clear();
  97. return url;
  98. };
  99. $excel.prototype.getBlob = function() {
  100. return new Blob([this.getXml().toString()], {type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8"});
  101. };
  102. $excel.prototype.getXml = function() {
  103. var self = this;
  104. if(self.sheets > 0)
  105. self.createOptions();
  106. return new StringBuffer().append('\ufeff<?xml version="1.0" encoding="UTF-8" standalone="yes"?>')
  107. .append('<?mso-application progid="Excel.Sheet"?>')
  108. .append('<Workbook xmlns="urn:schemas-microsoft-com:office:spreadsheet" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:x="urn:schemas-microsoft-com:office:excel" xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet" xmlns:html="http://www.w3.org/TR/REC-html40">')
  109. .append('<DocumentProperties xmlns="urn:schemas-microsoft-com:office:office">')
  110. .append('<Version>12.00</Version>')
  111. .append('</DocumentProperties>')
  112. .append('<ExcelWorkbook xmlns="urn:schemas-microsoft-com:office:excel">')
  113. .append('<WindowHeight>7524</WindowHeight>')
  114. .append('<WindowWidth>17280</WindowWidth>')
  115. .append('<WindowTopX>360</WindowTopX>')
  116. .append('<WindowTopY>276</WindowTopY>')
  117. .append('<ActiveSheet>1</ActiveSheet>')
  118. .append('<ProtectStructure>False</ProtectStructure>')
  119. .append('<ProtectWindows>False</ProtectWindows>')
  120. .append('</ExcelWorkbook>')
  121. .append('<Styles>')
  122. .append('<Style ss:ID="Default" ss:Name="Normal">')
  123. .append('<Alignment ss:Vertical="Bottom"/>')
  124. .append('<Borders />')
  125. .append('<Font ss:FontName="Arial" x:Family="Swiss"/>')
  126. .append('<Interior />')
  127. .append('<NumberFormat />')
  128. .append('<Protection />')
  129. .append('</Style>')
  130. .append('<Style ss:ID="HeaderCell">')
  131. .append('<Alignment ss:Horizontal="Center" />')
  132. .append('<Borders>')
  133. .append('<Border ss:Position="Bottom" ss:LineStyle="Continuous" ss:Weight="1" ss:Color="#000000"/>')
  134. .append('<Border ss:Position="Left" ss:LineStyle="Continuous" ss:Weight="1" ss:Color="#000000"/>')
  135. .append('<Border ss:Position="Right" ss:LineStyle="Continuous" ss:Weight="1" ss:Color="#000000"/>')
  136. .append('<Border ss:Position="Top" ss:LineStyle="Continuous" ss:Weight="1" ss:Color="#000000"/>')
  137. .append('</Borders>')
  138. .append('<Font ss:FontName="宋体" x:CharSet="134" x:Family="Roman" ss:Size="12" ss:Bold="1" />')
  139. .append('<Interior ss:Color="#99CCFF" ss:Pattern="Solid" />')
  140. .append('</Style>')
  141. .append('<Style ss:ID="Cell">')
  142. .append('<Interior />')
  143. .append('</Style>')
  144. .append('<Style ss:ID="Date">')
  145. .append('<Alignment ss:Horizontal="Right" />')
  146. .append('<NumberFormat ss:Format="yyyy\-mm\-dd" />')
  147. .append('</Style>')
  148. .append('<Style ss:ID="DateTime">')
  149. .append('<Alignment ss:Horizontal="Right" />')
  150. .append('<NumberFormat ss:Format="yyyy\-mm\-dd hh:MM:ss" />')
  151. .append('</Style>')
  152. .append('<Style ss:ID="Integer">')
  153. .append('<NumberFormat ss:Format="0" />')
  154. .append('</Style>')
  155. .append('<Style ss:ID="Float">')
  156. .append('<NumberFormat ss:Format="0.00" />')
  157. .append('</Style>')
  158. .append('</Styles>')
  159. .append(self.xml)
  160. .append('</Workbook>');
  161. };
  162. $excel.prototype.createSheet = function(count) {
  163. var self = this;
  164. if(self.sheets > 0)
  165. self.createOptions();
  166. self.append('<Worksheet ss:Name="Sheet' + (++self.sheets) + '">');
  167. self.append('<Table ss:ExpandedColumnCount="' + self.keys.length + '" ss:ExpandedRowCount="' + (count <= 65534 ? (count + 1) :
  168. ((count + self.sheets) > (65535*self.sheets) ? 65535 : (count + self.sheets - 65535*(self.sheets-1)))) +
  169. '" x:FullColumns="1" x:FullRows="1" ss:DefaultColumnWidth="54" ss:DefaultRowHeight="15.6">');
  170. self.createHeader();
  171. return self;
  172. };
  173. $excel.prototype.createHeader = function() {
  174. var self = this, i = 0;
  175. for(var k in self.headers) {
  176. self.append('<Column ss:Index="' + (++i) + '" ss:AutoFitWidth="0" ss:Width="' + self.widths[k] + '" />');
  177. }
  178. self.append('<Row>');
  179. for(var k in self.headers) {
  180. self.append('<Cell ss:StyleID="HeaderCell"><Data ss:Type="String">' + self.headers[k] + '</Data></Cell>');
  181. }
  182. return self.append('</Row>');
  183. };
  184. $excel.prototype.parseComboValue = function(k, v) {
  185. var self = this, s = self.comboMaps[k + v];
  186. if (s)
  187. return s;
  188. else
  189. s = v;
  190. if(self.combos) {
  191. var c;
  192. for(var i in self.combos) {
  193. c = self.combos[i];
  194. if(k == c.dlc_fieldname && v == c.dlc_display) {
  195. s = c.dlc_value;
  196. break;
  197. }
  198. }
  199. }
  200. self.comboMaps[k + v] = s;
  201. return s;
  202. };
  203. $excel.prototype.createRow = function(row) {
  204. var self = this, k, t, v, s = self.rowTpl.replace(self.rowExp, function(match){
  205. k = self.rowReg[match];
  206. t = self.types[k];
  207. if(k) {
  208. v = row[k];
  209. if(typeof v != 'undefined' && v != null) {
  210. if(t == 'yn') {
  211. v = [1, -1, '1', '-1'].indexOf(v) > -1 ? '是' : (0 == v ? '否' : '');
  212. } else if(t == 'combo') {
  213. v = self.parseComboValue(k, v);
  214. } else if(t == 'yyyy-m-d') {
  215. v = v.substr(0, 10);
  216. }
  217. } else
  218. v = '';
  219. } else
  220. v = '';
  221. return v;
  222. });
  223. // empty datefield
  224. return self.append(s.replace(/\<Cell\sss:StyleID="Date"\>\<Data\sss:Type="DateTime"\>\<\/Data\>\<\/Cell\>/g, '<Cell ss:StyleID="DateTime"/>'));
  225. };
  226. $excel.prototype.addData = function(data) {
  227. var self = this;
  228. for(var i = 0,l = data.length;i < l;i++ ) {
  229. if(self.rowCount == 0 || self.rowCount >= 65534) {
  230. self.rowCount = 0;
  231. self.createSheet(l);
  232. }
  233. self.createRow(data[i]);
  234. self.rowCount += 1;
  235. }
  236. return self;
  237. };
  238. $excel.prototype.append = function(s) {
  239. this.xml.append(s);
  240. return this;
  241. };
  242. $excel.prototype.createOptions = function() {
  243. return this.append('</Table>')
  244. .append('<WorksheetOptions xmlns="urn:schemas-microsoft-com:office:excel">')
  245. .append('<Print>')
  246. .append('<ValidPrinterInfo />')
  247. .append('<HorizontalResolution>600</HorizontalResolution>')
  248. .append('<VerticalResolution>600</VerticalResolution>')
  249. .append('</Print>')
  250. .append('<Selected />')
  251. .append('<FreezePanes />')
  252. .append('<FrozenNoSplit />')
  253. .append('<SplitHorizontal>1</SplitHorizontal>')
  254. .append('<TopRowBottomPane>1</TopRowBottomPane>')
  255. .append('<ProtectObjects>False</ProtectObjects>')
  256. .append('<ProtectScenarios>False</ProtectScenarios>')
  257. .append('</WorksheetOptions>')
  258. .append('</Worksheet>');
  259. };
  260. }
  261. })(window);