史上最贱的word报表生成解决方案
注:未成年人请在父母陪同下观看此贴,有心脏病者勿入,有洁癖者勿入,看帖过程中如有觉得头晕、恶心者请立即关闭浏览器,到阳台呼吸一下新鲜空气
最近手头一个项目要生成周报、月报,要求是word文档类型,时间只有3天,今天花了一天时间找各种方案,有VSTO,有OpenXML,看了半天以后发现,如果从头开始熟悉这些东西,3天时间出报表程序根本来不及,因为如果用替换书签的方法,一个周报几百个书签的空,一天下来也填不了几个空,如果用手动生成,基本代码没问题,但是设置样式让人蛋疼得很,于是上网找其他的方案,最后找到一个史上最贱的方案,一解燃眉之急,以后再慢慢学习VSTO和OpenXML,今天就把这个方案介绍给大家,众所周知,doc格式文件是可以识别htm格式的,说到这里大家应该都明白了,大致思路就是先根据内容生成htm格式的string数据,然后直接保存成.doc文件格式就行了。至于样式的话,html样式比openxml样式简单太多了,也是我们所熟悉的东西。我把生成html脚本的过程封装成了一个dll,暂时先封装需要的标签,以后用的话再加就行了,闲话少说,看代码
1、Html类,这个类保存的是所有的周报数据,可以自己设置Title,body体内容通过AppendToBody(string content)方法添加
1 using System.Text; 2 3 namespace HtmlEncapsulation 4 { 5 /// <summary> 6 /// html脚本类 7 /// </summary> 8 public class Html 9 { 10 /// <summary> 11 /// 标题 12 /// </summary> 13 public string Title { get; set; } 14 15 /// <summary> 16 /// 内容 17 /// </summary> 18 private StringBuilder _body; 19 20 21 public Html() 22 { 23 this._body = new StringBuilder(); 24 } 25 26 /// <summary> 27 /// 生成html 28 /// </summary> 29 /// <returns></returns> 30 public string GenerateHtml() 31 { 32 StringBuilder sb = new StringBuilder(); 33 sb.AppendFormat("<html><title>{0}</title><body>{1}</body></html>", Title, _body); 34 return sb.ToString(); 35 } 36 37 /// <summary> 38 /// 添加到html页的body内 39 /// </summary> 40 /// <param name="content"></param> 41 public void AppendToBody(string content) 42 { 43 _body.Append(content); 44 } 45 } 46 }
2、HtmlEncap,这个类就是封装了生成html脚本过程的类,目前就用到生成标题(一共4级标题)、生成正文内容、表格、换行、空格、图片这些
1 using System.Text; 2 using System.Data; 3 4 namespace HtmlEncapsulation 5 { 6 public static class HtmlEncap 7 { 8 /// <summary> 9 /// 设置标题,默认居中 10 /// </summary> 11 /// <param name="content">要设置为标题的内容</param> 12 /// <param name="header">字号,有4级字号</param> 13 /// <returns></returns> 14 public static string GetHeader(string content, Header header, bool isLeft = false) 15 { 16 StringBuilder sb = new StringBuilder(); 17 string size = string.Empty; 18 switch (header) 19 { 20 case Header.Header1: 21 size = "50"; 22 break; 23 case Header.Header2: 24 size = "40"; 25 break; 26 case Header.Header4: 27 size = "20"; 28 break; 29 default: 30 size = "30"; 31 break; 32 } 33 sb.AppendFormat("<p style='font-size:{0}px; text-align:{1}'><strong>{2}<strong></p>", size, isLeft == false ? "center" : "left", content); 34 return content = sb.ToString(); 35 } 36 37 /// <summary> 38 /// 设置为正文内容 39 /// </summary> 40 /// <param name="content"></param> 41 /// <returns></returns> 42 public static string GetContent(string content) 43 { 44 return "<p>" + content + "</p>"; 45 } 46 47 /// <summary> 48 /// 生成html表格 49 /// </summary> 50 /// <param name="table"></param> 51 /// <returns></returns> 52 public static string GetTable(DataTable table) 53 { 54 StringBuilder sb = new StringBuilder(); 55 56 sb.Append("<div style='text-align:center'><table border='1' cellspacing='0' bordercolor='#000000' width = '80%' style='border-collapse:collapse;'>"); 57 58 //增加表头 59 sb.Append("<tr>"); 60 for (int i = 0; i < table.Columns.Count; i++) 61 { 62 sb.AppendFormat("<th style='background-color:Silver'>{0}</th>", table.Columns[i].ColumnName); 63 } 64 sb.Append("</tr>"); 65 66 //增加数据 67 for (int i = 0; i < table.Rows.Count; i++) 68 { 69 sb.Append("<tr>");//增加一行 70 for (int j = 0; j < table.Columns.Count; j++) 71 { 72 sb.AppendFormat("<td>{0}</td>", table.Rows[i][j].ToString());//增加一列 73 } 74 sb.Append("</tr>"); 75 } 76 sb.Append("</table></div>"); 77 return sb.ToString(); 78 } 79 80 /// <summary> 81 /// 换行或者空格 82 /// </summary> 83 /// <param name="count">换行或者空格数量</param> 84 /// <param name="space">br为换行,nbsp为空格</param> 85 /// <returns></returns> 86 public static string GetSpace(int count, Space space) 87 { 88 StringBuilder sb = new StringBuilder(); 89 string content = space == Space.Br ? "<br/>" : " "; 90 for (int i = 0; i < count; i++) 91 { 92 sb.Append(content); 93 } 94 return sb.ToString(); 95 } 96 97 /// <summary> 98 /// 获取图片 99 /// </summary> 100 /// <param name="path">图片路径</param> 101 /// <param name="width">宽度</param> 102 /// <param name="height">高度</param> 103 /// <param name="isCenter">是否居中显示,默认为居中</param> 104 /// <returns></returns> 105 public static string GetImage(string path, int width, int height, bool isCenter = true) 106 { 107 string content = string.Format("<img src='{0}' width='{1}px' height='{2}px'></img>", path, width, height); 108 109 content = isCenter == true ? "<div style='text-align:center'>" + content + "</div>" : content; 110 111 return content; 112 } 113 } 114 }
3、还有一个通用枚举类,这个简单,不做解释
1 namespace HtmlEncapsulation 2 { 3 /// <summary> 4 /// 标题字号 5 /// </summary> 6 public enum Header 7 { 8 Header1, 9 Header2, 10 Header3, 11 Header4 12 } 13 14 /// <summary> 15 /// Br 换行,Space 空格 16 /// </summary> 17 public enum Space 18 { 19 Br, 20 Space 21 } 22 }
使用方法:
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Data; 6 using System.IO; 7 using HtmlEncapsulation; 8 9 namespace HtmlEncaps 10 { 11 class Program 12 { 13 static void Main(string[] args) 14 { 15 Html html = new Html(); 16 html.Title = "周报"; 17 18 //加载标题 19 html.AppendToBody(HtmlEncap.GetHeader("NorthWind报表样例", Header.Header2)); 20 html.AppendToBody(HtmlEncap.GetHeader("2013年3月6日周报", Header.Header3)); 21 html.AppendToBody(HtmlEncap.GetSpace(3, Space.Br)); 22 23 //加载客户信息表 24 html.AppendToBody(HtmlEncap.GetHeader("1、客户信息", Header.Header4, true)); 25 string sql = "select * from Customers"; 26 DataTable table = new DbHelper().GetTable(sql); 27 html.AppendToBody(HtmlEncap.GetTable(table)); 28 29 //加载员工信息表 30 html.AppendToBody(HtmlEncap.GetHeader("2、员工信息", Header.Header4, true)); 31 sql = "select * from Employees"; 32 DataTable table2 = new DbHelper().GetTable(sql); 33 html.AppendToBody(HtmlEncap.GetTable(table2)); 34 35 //加载图片 36 html.AppendToBody(HtmlEncap.GetImage(@"http://www.cnblogs.com/img/logo.png", 300, 300)); 37 38 File.WriteAllText("周报.doc", html.GenerateHtml()); 39 40 Console.WriteLine("OK"); 41 } 42 } 43 }
效果:
显示表格数据
显示图片
这个封装的dll比较草率,以后再加入保存为真正的doc功能