c# 导出带格式 图片 的Word文档·转

原帖地址http://blog.sina.com.cn/s/blog_7016da1e0100wr2p.html

VS2003已经装好,可以开始做了。

第一步,做好Xml模板,这个直接在Word中另存为Xml格式就可,这个Xml可用Word打开,也要用记事本打开。

第二步,用Word打开Xml模板,在表格中要填数据的地方做好标记,如图所示带格式图片的Word <wbr>文档导出(2)

第三步,读取Xml模板

string modePath = HttpContext.Current.Server.MapPath("同业对标专家库.xml");

XmlDocument xmlDoc = new XmlDocument();

xmlDoc.Load(modePath);

string docstr = xmlDoc.InnerXml.ToString();

第四步,将模板中相应位置的值替换掉

docstr = docstr.Replace("{branch_name}",this.LabelDW.Text);

docstr = docstr.Replace("NAME",this.NAME.Value);

docstr = docstr.Replace("SEX",this.SEX.Value);

docstr = docstr.Replace("BIRTHDAY",this.BIRTHDAY.Value);

docstr = docstr.Replace("PLACE",this.PLACE.Value);

第五步,替换照片。照片导出是比较麻烦的部分。照片在Xml(Word转换)中以Base64编码保存,在上面的模板中,“userphoto”代表照片,在Xml中,userphoto的整个代码是<w:r><w:rPr><w:rFonts w:ascii="宋体" w:h-ansi="宋体" w:hint="fareast"/><wx:font wx:val="宋体"/></w:rPr><w:t>{userphoto}</w:t></w:r>

替换照片时要把整个代码替换

string userphotoXml = "<w:r><w:rPr><w:rFonts w:ascii=\"宋体\" w:h-ansi=\"宋体\" w:hint=\"fareast\" /><wx:font wx:val=\"宋体\" /></w:rPr><w:t>userphoto</w:t></w:r>";

 

string PhotoXml = "<w:r><w:pict><w:binData w:name=\"wordml://02000001.jpg\" xml:space=\"preserve\">";

//中间加Base64位编码的图片信息

picStr = Convert.ToBase64String(pic);//pic为照片的byte[]格式,由数据库中读出

PhotoXml +=picStr;

PhotoXml +="</w:binData><v:shape id=\"_x0000_i1025\" type=\"#_x0000_t75\" style=\"75pt;height:100pt\"><v:imagedata src=\"wordml://02000001.jpg\" o:title=\"11163428_012248\"/> </v:shape></w:pict></w:r>";

 

docstr = docstr.Replace(userphotoXml,PhotoXml);

 

第六步,将Xml模板保存为Word

xmlDoc.InnerXml = docstr;

string filename = this.LabelDW.Text+"同业对标专家库.doc";

filename = HttpContext.Current.Server.MapPath(filename);

xmlDoc.Save(filename);

 

第七步,导出文档

private   void   FileDownload(string   FullFileName)

{

     FileInfo   DownloadFile   =   new   FileInfo(FullFileName);  

     Response.Clear();

     Response.ClearHeaders();

     Response.Buffer= true;

     Response.ContentType= "application/octet-stream";

     Response.AppendHeader( "Content-Disposition ", "attachment;filename= "  +HttpUtility.UrlEncode("同业对标专家库压缩包.rar",System.Text.Encoding.UTF8));

 

     Response.AppendHeader( "Content-Length ",DownloadFile.Length.ToString());

     Response.WriteFile(DownloadFile.FullName);

     Response.Flush();

     Response.End();

}

至此,导出带格式Word完成,在本机运行成功。另外,多个文档打包导出,先用上述方法逐个生成文档,再打包保存,再导出下载。

打包实现:

在网上下了一个ICSharpCode.SharpZipLib.dll。

using ICSharpCode.SharpZipLib.Zip;

using ICSharpCode.SharpZipLib.Core;

/// <summary>

         /// 压缩

          /// </summary>

         /// <param name="filesPath">要压缩的文件路径</param>

         /// <param name="zipFilePath">压缩完文件存放路径</param>

         private void CreateZipFile(string filesPath, string zipFilePath,string branchid)

         {

 

              if (!Directory.Exists(filesPath))

              {

                  

              }

              else

              {

                   try

                   {

                                          //*****读取文件

                       string[] filenames = Directory.GetFiles(filesPath);

                       using (ZipOutputStream s = new ZipOutputStream(File.Create(zipFilePath)))

                       {

 

                            s.SetLevel(9); // 压缩级别 0-9

                            //s.Password = "123"; //Zip压缩文件密码

                            byte[] buffer = new byte[4096]; //缓冲区大小

                            foreach (string file in filenames)

                            {

                                 ZipEntry entry = new ZipEntry(Path.GetFileName(file));

                                 entry.DateTime = DateTime.Now;

                                 s.PutNextEntry(entry);

                                 using (FileStream fs = File.OpenRead(file))

                                 {

                                     buffer = new byte[fs.Length];

                                     int sourceBytes;

                                     do

                                     {

                                          sourceBytes = fs.Read(buffer, 0, buffer.Length);

                                          s.Write(buffer, 0, sourceBytes);

                                     } while (sourceBytes > 0);

                                }

                            }

                            s.Finish();

                            s.Close();

                       }

                   }

                   catch (Exception ex)

                   {

                   }

              }

         }

打包下载也在本地运行成功,但布署到服务器(Win2003)上时,报错了,导出单个文档时不出下载保存对话框,而是将文档的XmL格式读取在页面上;导出压缩包时,报错The XML Page cannot be displayed带格式图片的Word <wbr>文档导出(2)

 

布署在同事(Win XP)电脑上也报同样的错。我不能理解为什么,只能归结于系统不能识别文档到底是Xml格式还是Word格式,将Response.ContentType= "application/octet-stream";这句换成Word格式或Xml格式都不行,依然报错。折腾了很久,最后决定放弃下载文档的方式,将文档保存在数据库,从数据库中导出下载。

////将导出文件保存到数据库中

SaveAsBLOB(filename,dr["branch_id"].ToString());

private void SaveAsBLOB(string filename,string sid)

         {

              string fileShortName = filename.Substring(filename.LastIndexOf('\\')+1);

              System.Data.OracleClient.OracleConnection oc = new System.Data.OracleClient.OracleConnection(System.Configuration.ConfigurationSettings.AppSettings["DBConnString"].ToString());

              byte[] buffer = null;

              string sFileType = "",sFileName = "";

             

              FileStream fs = new FileStream(filename,FileMode.Open);

              buffer = new byte[fs.Length];

              fs.Read(buffer,0,(int)fs.Length);

              sFileType="text/xml";

              sFileName = TellHow.StringUtil.FileNameStringFunc.getFileName(filename);

 

              try

              {

 

                   System.Data.OracleClient.OracleCommand cmdSql = new System.Data.OracleClient.OracleCommand();

                   System.Text.StringBuilder sb = new System.Text.StringBuilder();

                   sb.Remove(0,sb.Length);

 

                   sb.AppendFormat(" update pu_zjinfo set AttachName='"+sFileName+"',AttachCont=:AttachCont");

                   sb.AppendFormat(" where branch_id='"+sid+"'");

 

                   cmdSql.CommandText = sb.ToString();

                   System.Data.OracleClient.OracleParameter attachCont=new System.Data.OracleClient.OracleParameter();

                   attachCont.Value=buffer;

                   attachCont.ParameterName="AttachCont";

                   attachCont.OracleType=System.Data.OracleClient.OracleType.Blob;

                   attachCont.Size=buffer.Length;

                   cmdSql.Parameters.Add(attachCont);

                   //cmdSql.Parameters.Add("@ImageData",OracleType.Blob,buffer.Length).Value = buffer;

                   cmdSql.Connection = oc;

                   oc.Open();

                   cmdSql.ExecuteNonQuery();

 

                   oc.Close();

              }

              catch(Exception e)

              {

                   Response.Write("<script language='javascript'>");

                   Response.Write("alert('导出失败,原因是:"+e.Message+"!');");

                   Response.Write("</script>");

              }

                       fs.Flush();

              fs.Close();

         }

这样,终于能够在WinXP 上实现下载。正准备更新到服务器时,又发现了一个新的问题,在弹出的文件下载框上多点击了几次取消后,再点击“导出”时

带格式图片的Word <wbr>文档导出(2)

 

报错:"该进程无法访问文件“D:\工作\DBPMIS\Experts\zip\南昌供电公司同业对标专家库.doc”,因为该文件正由另一进程使用。

导出时生成在服务器的文档发生了死锁。可能在某处操作文档后未释放,解决方法:干脆在文档保存在数据库后删除,以绝后患。

//保存到数据库后,将文件删除

if(File.Exists( filename))

File.Delete(filename);

终于大功告成!

最后的最后,客户使用时发现导出后的文档在“工作简历”栏没有换行,希望能换行。这个功能分析找到实现方法,“工作简历”用户输入时使用的TextArea控件,TextArea控件本身有换行符\r\n,根据换行符将内容分开,再按格式替换

//工作简历,工作简历格式要求有换行

                            string gzjlStr = dr["GZJL"].ToString();//工作简历原值

                            gzjlStr = gzjlStr.Replace("\r\n","^");//先将换行符换成特殊符号

                            string[] gzjlArray = gzjlStr.Split('^');

 

                            string gzjl=gzjlArray[0];//用来替换“工作经历”(GZJL</w:t></w:r></w:p>)的字符串

 

                            gzjl+="</w:t></w:r></w:p>";

 

                            //从第二个开始,

                            for (int i =1;i<gzjlArray.Length;i++)

                            {

                                 gzjl+="<w:p><w:pPr><w:rPr><w:rFonts w:ascii=\"宋体\" w:h-ansi=\"宋体\" w:hint=\"fareast\"/><wx:font wx:val=\"宋体\"/></w:rPr></w:pPr>";

                                 //上一句表示换行

                                 gzjl+="<w:r><w:rPr><w:rFonts w:ascii=\"宋体\" w:h-ansi=\"宋体\" w:hint=\"fareast\"/><wx:font wx:val=\"宋体\"/></w:rPr><w:t>";

                                 gzjl += gzjlArray[i];

                                 gzjl+="</w:t></w:r></w:p>";

                            }

 

                            docstr= docstr.Replace("GZJL</w:t></w:r></w:p>",gzjl);

原文地址:https://www.cnblogs.com/fcq121/p/2811377.html