项目开发过程中,我们要把数据以各种各样的形式展现给客户。把数据以文档的形式展现给客户相信是一种比较头疼的问题,如果没有好的方法会

使得我的开发繁琐,而且满足不了客户的需求。接下来我会通过两种开发方式介绍如何将数据输出到Word 文档上。我会分两篇文章介绍,第一篇

介绍不使用插件的情况下操作word,第二篇文章将介绍一种强大的插件操作word。下面开始第一篇文章。[本次实例源代码从这里下载]

文章梗概:

♦ 不使用模板将数据输出到 word

♦ 输出数据到 word 在后端设置输出内容

♦ 输出数据到 word 在前端设置输出内容

♦ 通过设置模板将数据输出到 word

♦ 通过把word另存为html 文件的形式做成模板输出到word

♦ 通过把word另存为mht 文件的形式做成模板输出到word

一、不用模板将数据输出到 word

1、输出数据到 word 在后端设置输出内容

前端定义两个服务器按钮:

 <div id="container" style="">
不利用模板:<br />
<br />
<asp:Button ID="CreateWordBehind" runat="server" Text="输出数据到word(后台设置内容)" OnClick="CreateWordBehind_Click" />
<asp:Button ID="CreateWordFront" runat="server" Text="输出数据到word(前台设置内容)" OnClick="CreateWordFront_Click" />
<hr />
</div>

后端代码输出到word,代码很简单只要设置输出头为word,而输出的内容放到 StringBuilder 里,并且通过 StringBuilder实例,去设置要输出的内容,包括字体、颜色....

         /// <summary>
/// 输出数据到word(后台设置内容)
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected void CreateWordBehind_Click(object sender, EventArgs e)
{
HttpContext.Current.Response.Clear();
HttpContext.Current.Response.Buffer = true;
HttpContext.Current.Response.Charset = ""; // 设置输出头
HttpContext.Current.Response.AddHeader("Content-Disposition", "attachment;filename=" + System.Web.HttpUtility.UrlEncode("CreateWord", System.Text.Encoding.UTF8) + ".doc"); // 设置输出的编码格式
HttpContext.Current.Response.ContentEncoding = System.Text.Encoding.Default; // Response.ContentType指定文件类型 可以为application/ms-excel || application/ms-word || application/ms-txt || application/ms-html
// 因为是输出word 所以这里就指定为 application/ms-word
HttpContext.Current.Response.ContentType = "application/ms-word"; // 定义StringBuilder 把要输出的内容写到里面,并且可以设置字体、颜色、大小等...
StringBuilder sb = new StringBuilder();
sb.AppendLine("<div style='text-align:center;font-size:18px;font-weight:bold;'>导出数据到word</div>");
sb.AppendLine("这是导出到word的数据<br />");
sb.AppendLine("<span style='color:blue;'>这是导出到word的数据</span>"); HttpContext.Current.Response.Output.Write(sb);
HttpContext.Current.Response.Flush();
HttpContext.Current.Response.End();
}

运行、点击按钮、打开word文档,效果如下:

2、输出数据到 word 在前端设置输出内容

前端设置输出的html内容。以输出一个表格为例。其中有两个div 标记了runat="server",这样后台就可以取到这个id,用途一会介绍。

 <div id="WordContent" runat="server">
<div runat="server" id="title">表头</div>
<table border="1" style="width:400px;line-height: 25px;">
<tr style="width:400px; height:25px;">
<td>
编号
</td>
<td>
姓名
</td>
<td>
成绩
</td>
</tr>
<tr style="width:400px; height:25px;">
<td>
</td>
<td>
</td>
<td>
</td>
</tr>
</table>
</div>

至此前端的全部代码如下:

 <form id="form1" runat="server">
<div id="WordContent" runat="server">
<div runat="server" id="title">表头</div>
<table border="1" style="width:400px;line-height: 25px;">
<tr style="width:400px; height:25px;">
<td>
编号
</td>
<td>
姓名
</td>
<td>
成绩
</td>
</tr>
<tr style="width:400px; height:25px;">
<td>
</td>
<td>
</td>
<td>
</td>
</tr>
</table>
</div>
<div id="container" style="">
不利用模板:<br />
<br />
<asp:Button ID="CreateWordBehind" runat="server" Text="输出数据到word(后台设置内容)" OnClick="CreateWordBehind_Click" />
<asp:Button ID="CreateWordFront" runat="server" Text="输出数据到word(前台设置内容)" OnClick="CreateWordFront_Click" />
<hr />
</div>
</form>

后端代码输出到word的代码和就是把之前的StringBuilder 换成了StringWriter,StringWriter的信息其实也是通过Stringbulider存储的。另外加上一个

HtmlTextWriter对象,HtmlTextWriter可以把前端渲染后的页面以流的形式输出。

这是候我们就可以看出在前端html中标记的id的用途了,这样就可以把id标记为WordContent的里面的内容全部输出到word,而其他的内容也不会输出到word上了。

又由于前端html中id标记了title的div标签在后台设置了title.Style.Add(HtmlTextWriterStyle.Display, "none");所以它也不会被输出到word上。

 /// <summary>
/// 输出数据到word(前台设置内容)
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected void CreateWordFront_Click(object sender, EventArgs e)
{
HttpContext.Current.Response.Clear();
HttpContext.Current.Response.Buffer = true;
HttpContext.Current.Response.Charset = ""; // 设置输出头
HttpContext.Current.Response.AddHeader("Content-Disposition", "attachment;filename=" + System.Web.HttpUtility.UrlEncode("CreateWord", System.Text.Encoding.UTF8) + ".doc"); // 设置输出的编码格式
HttpContext.Current.Response.ContentEncoding = System.Text.Encoding.Default; // Response.ContentType指定文件类型 可以为application/ms-excel || application/ms-word || application/ms-txt || application/ms-html
// 因为是输出word 所以这里就指定为 application/ms-word
HttpContext.Current.Response.ContentType = "application/ms-word"; // 定义输出流,其信息也是存储在StringBuilder中的
System.IO.StringWriter oStringWriter = new System.IO.StringWriter(); // 定义一个服务器控件输出流(可以把前端渲染后的页面以流的形式输出)
System.Web.UI.HtmlTextWriter oHtmlTextWriter = new System.Web.UI.HtmlTextWriter(oStringWriter); // 控制前端的样式 (HtmlTextWriterStyle 枚举用来控制 显示、字体、大小、颜色...)
title.Style.Add(HtmlTextWriterStyle.Display, "none"); // 这样会把前端的整个页面输出,由于有些其他元素不需要输出,所以注释
//this.RenderControl(oHtmlTextWriter); // 指定我们前端标记要输出的容器,容器包含的内容都可以输出
this.WordContent.RenderControl(oHtmlTextWriter); HttpContext.Current.Response.Output.Write(oStringWriter);
HttpContext.Current.Response.Flush();
HttpContext.Current.Response.End();
}

运行、点击按钮发现报错,提示"只能在执行 Render() 的过程中调用 RegisterForEventValidation;"这个错误的原因就是怀疑通过post方法发送恶意的数据,解决方法:

在当前aspx页面头部加上:EnableEventValidation="false",默认为true。

 <%@ Page Language="C#" AutoEventWireup="true" EnableEventValidation="false" CodeBehind="OperateWord.aspx.cs"
Inherits="OperateWordPro.OperateWordDemo1.OperateWord" %>

再运行、点击按钮、打开word,效果如下(当然需求不可能那么简单,具体输出的样式就要在html中慢慢的调整了):

二、通过提前设置模板将数据输出到 word

因为如果用前面的方式,将数据都是自己拼接的,包括样式全是自己控制,难度将非常大,并且效果也很让到客户的满意(如:要求页眉、页脚)。所以如果能够程序直接读取word模板把要输出的内容填充进去将会大大的缩短我们的时间,最主要的是版式不用我们太关心。

1、 通过把word另存为html 文件的形式做成模板输出到word

把word文档做成模板的思路就是把word文档保存为html程序可以直接读取的形式。由于篇幅的问题,具体把word另存为html的细节可以请参考这篇博文。下面有这样一个结构的word文档需要输出,通过用读取模板的形式我们只要把下面几个站位符替换掉就可以了(如,要输出名字的地方加上了{name}...),思路很简单。

前台html代码:

         利用模板输出到word:<br /><br />
<asp:Button ID="CreateWordByHtmlTemplate" runat="server" Text="通过htm模板生成Word" OnClick="CreateWordByHtmlTemplate_Click" />
<asp:Button ID="CreateWordBymhtTemplate" runat="server" Text="通过mht模板生成Word" OnClick="CreateWordBymhtTemplate_Click" />

在项目中添加一个Document文件夹,将模板文件“通知.html”拷贝到这个问价夹下。

下面是后台代码:

 /// <summary>
/// 通过htm模板生成Word
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected void CreateWordByHtmlTemplate_Click(object sender, EventArgs e)
{
// 获取模板的路径 通过ExprotToWord处理返回 字符串
string strWord = DealTemplate(Server.MapPath("../Document/通知.html")); Response.ContentEncoding = System.Text.Encoding.Default;
Response.ClearContent();
Response.ClearHeaders();
Response.AddHeader("content-disposition", "attachment;filename=合同.doc"); //必须的
Response.AddHeader("Content-type", "application");
Response.ContentType = "application/ms-html";
Response.ContentEncoding = System.Text.Encoding.Default; Response.Write(strWord);
Response.Flush();
Response.Close();
} /// <summary>
/// 处理模板 返回处理结果
/// </summary>
/// <param name="templatePath"></param>
/// <returns></returns>
public string DealTemplate(string templatePath)
{
StringBuilder sb = new StringBuilder(); // 读取文档内容并转换成流的形式 编码为默认编码
StreamReader sr = new StreamReader(templatePath, Encoding.Default); // 将流转换成字符串加进StringBuilder中
sb.Append(Encoding.Default.GetString(Encoding.Default.GetBytes(sr.ReadToEnd()))); // 把文档中我们设置的标志位换成我们想要的内容
sb.Replace("{name}", "张三");
sb.Replace("{orderNumber}", "ooxx124512");
sb.Replace("{tel}", ""); return sb.ToString();
}

运行、点击按钮、打开word,效果如下

2、 通过把word另存为mht 文件的形式做成模板输出到word

通过把word存储为html的形式解决了大量手工拼接数据和word的基本版式问题,但是如果这个word中含有图片和页眉页脚就无法通过这种方式处理了,因为html存储的是单文件,是和图片这些“其他元素”分开的。所以如果还是要通过模板的方式解决那么这个模板要含有文字、图片、页眉设置、页脚设置。经过一番测试,发现把word另存为.mht的方式可以解决这个问题。上网查了资料说.mht就是htm和图片等的复合文件。那么我们继续吧。

制作一个word在上一个word的基础上添加了一个含有图片的word:

把这个word另存为"通知2.mht",并复制到Document文件夹下。

后台代码和上面代码一样,只是换了个模板而已,但是编码格式要做微调,红字部分标注了:

 /// <summary>
/// 通过mht模板生成Word
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected void CreateWordBymhtTemplate_Click(object sender, EventArgs e)
{
// 获取模板的路径 通过ExprotToWord处理返回 字符串
string strWord = DealTemplate(Server.MapPath("../Document/通知2.mht")); Response.ContentEncoding = System.Text.Encoding.Default;
Response.ClearContent();
Response.ClearHeaders();
Response.AddHeader("content-disposition", "attachment;filename=合同.doc"); //必须的
Response.AddHeader("Content-type", "application");
Response.ContentType = "application/ms-html";
Response.ContentEncoding = System.Text.Encoding.Default; Response.Write(strWord);
Response.Flush();
Response.Close();
} /// <summary>
/// 处理模板 返回处理结果
/// </summary>
/// <param name="templatePath"></param>
/// <returns></returns>
public string DealTemplate(string templatePath)
{
StringBuilder sb = new StringBuilder(); // 读取文档内容并转换成流的形式 此处编码要设置为UTF8
StreamReader sr = new StreamReader(templatePath, Encoding.UTF8); // 将流转换成字符串加进StringBuilder中
sb.Append(Encoding.Default.GetString(Encoding.Default.GetBytes(sr.ReadToEnd()))); // 把文档中我们设置的标志位换成我们想要的内容
sb.Replace("{name}", "张三");
sb.Replace("{orderNumber}", "ooxx124512");
sb.Replace("{tel}", ""); return sb.ToString();
}

运行、点击按钮、打开word效果如下:

总结

以上文章介绍的是没有通过组件将数据输出到word上,如果客户需求简单,格式不是太难控制完全可以根据文章中通过模板的方式输出到word。其中最容易出问题的我认为就是编码问题,模板格式不一样可能程序中的编码格式也要做相应的调整。

虽然以上方式演示没问题,但是实际开发中需求并没有上面的例子简单。如果客户要求的word版式比较复杂,且数据要循环输出那么通过上面任何一种方式都不好解决。但是通过第三方组件就可以解决这种问题,如果这个组件用熟练了,上面的方式我相信你几乎不会用的。下一篇文章将介绍用第三方组件的方式把内容输出到word。

把数据输出到Word (非插件形式)的更多相关文章

  1. 把数据输出到Word (组件形式)

    上一篇的文章中我们介绍了在不使用第三方组件的方式,多种数据输出出到 word的方式,最后我们也提到了不使用组件的弊端,就是复杂的word我们要提前设置模板.编码不易控制.循环输出数据更是难以控制.接下 ...

  2. Spark Structured Streaming框架(3)之数据输出源详解

    Spark Structured streaming API支持的输出源有:Console.Memory.File和Foreach.其中Console在前两篇博文中已有详述,而Memory使用非常简单 ...

  3. 【matlab】将matlab中数据输出保存为txt或dat格式

    将matlab中数据输出保存为txt或dat格式 总结网上各大论坛,主要有三种方法. 第一种方法:save(最简单基本的) 具体的命令是:用save *.txt -ascii x x为变量 *.txt ...

  4. 将matlab中数据输出保存为txt或dat格式

    :FID= FOPEN(filename,permission) 用指定的方式打开文件 FID=+N(N是正整数):表示文件打开成功,文件代号是N. FID=-1            : 表示文件打 ...

  5. ffmpeg 从内存中读取数据(或将数据输出到内存)

    更新记录(2014.7.24): 1.为了使本文更通俗易懂,更新了部分内容,将例子改为从内存中打开. 2.增加了将数据输出到内存的方法. 从内存中读取数据 ffmpeg一般情况下支持打开一个本地文件, ...

  6. 【C语言】- 数据输出-printf( )和putchar( )

    格式化输出函数printf( ) printf( )功能: 向系统指定输出设备按指定的格式输入任意个任意类型的数据,并返回实际输出的字符数.若出错,将返回负数. printf( )使用形式: prin ...

  7. C#仪器数据文件解析-Word文件(doc、docx)

    不少仪器数据报告输出为Word格式文件,同Excel文件,Word文件doc和docx的存储格式是不同的,相应的解析Word文件的方式也类似,主要有以下方式: 1.通过MS Word应用程序的DCOM ...

  8. 将excel中的数据填入word模板中-VBA

    首先将word模板中需要填写excel中数据的空白处用自己独特的字符串标记,比如   数据001  什么的.如下图: 这样,就可以用vba搜寻这些自己独特的标记来根据excel内容填充word了. 第 ...

  9. 二叉树前中后/层次遍历的递归与非递归形式(c++)

    /* 二叉树前中后/层次遍历的递归与非递归形式 */ //*************** void preOrder1(BinaryTreeNode* pRoot) { if(pRoot==NULL) ...

随机推荐

  1. vue.js在windows本地下搭建环境和创建项目

    Vue.js是一套构建用户界面的渐进式框架.与其他重量级框架不同的是,Vue 采用自底向上增量开发的设计.Vue 的核心库只关注视图层,并且非常容易学习,非常容易与其它库或已有项目整合.另一方面,Vu ...

  2. Ubuntu 下安装 Mysql

    这里讲用Ubuntu下安装MySql ubuntu上安装mysql非常简单只需要几条命令就可以完成. 1. sudo apt-get install mysql-server   2. apt-get ...

  3. c++模板函数实例化的偏序机制

    一:废话 今天在stackoverflow上看到一个关于c++模板specialization的问题: http://stackoverflow.com/questions/18283851/temp ...

  4. 虚拟机下CentOS 6.5配置IP地址的三种方法

    实验软件环境:虚拟机Vmware Workstation10.0 .CentOS 6.5 32位 1.自动获取IP地址 虚拟机使用桥接模式,相当于连接到物理机的网络里,物理机网络有DHCP服务器自动分 ...

  5. left join on 和where条件的放置

    先看个例子 以下P1与S1是一对多的关系 结果分别是:1746,1748,1748,1277525,307 由此看出: P1 left join S1 on ... and ...是将S1表中数据先过 ...

  6. nginx 配置https

    firewall-cmd --zone=public --add-port=80/tcp --permanent firewall-cmd --zone=public --add-port=3306/ ...

  7. 在Ubuntu 12.04下采用apt-get的方法安装Qt4

    在Ubuntu 12.04下采用apt-get的方法安装Qt4 注:之前发表的一篇博客是采用编译源码的方式安装Qt4,这是很有用的方式,因为源码安装对于所有系统都是通用的,其次,在使用交叉编译器的时候 ...

  8. javaweb 学习资源

    http://jinnianshilongnian.iteye.com/category/231099

  9. [转]asp三级select菜单联动(加数据库)

    '数据库结构'类别1表名称:a 字段:ID,Name 说明:ID为主键是类别1的ID值,Name为类别1的名称'类别2表名称:aa 字段:ID,aID,Name 说明:ID为主键是类别2的ID值,aI ...

  10. iOS 开发:利用第三方插件来安装CoCoapods

    引言:通过上一篇博客我们知道了怎么样去通过终端来安装CoCoapods,这一篇我们着重与用第三方插件来安装CoCoapods: 1. 首先在提下链接下载插件 https://github.com/ka ...