你的位置:首页 > ASP.net教程

[ASP.net教程]C# 导出word文档及批量导出word文档(4)


      接下来是批量导出word文档和批量打印word文件,批量导出word文档和批量打印word文件的思路差不多,只是批量打印不用打包压缩文件,而是把所有文件合成一个word,然后通过js来调用word,提交打印机,把word文档的内容都打印出来。
     批量导出word文档需要用到ICSharpCode.SharpZipLib.dll 插件,思路是,先单独导出所勾选的数据的单个文档,保存到生成的临时目录下,再把同一个的人相关文档合并一个word文档,并删除已经合并的那个文档(不是合并后生成的文档),以姓名和编号命名生成后的文档,最后将临时目录下的所有文件打包压缩下载,并删除临时目录和临时目录下的所有文件(都是生成在服务器上,所以若文件太大,可能会慢)。批量导出是用form来提交所传的参数,并下载。(因为懒,不解释代码了)
      首先新建一个空文档,插入书签,书签名为“p”(随便定义的),命名文件名为“test.doc”,保存在项目目录下。       
      相关js代码为:     
 1 /*************************************** 2  * @methodname→批量导出word文档 3  * @createtime 2015-05-11 4  ***************************************/ 5 function AllExportWord(objid, tfile) { 6   var ckvalue = "", ntid = "", code = "", name = ""; 7   var chkbox = $("input[type=checkbox][name=chk]:checked"); 8   for (var i = 0; i < chkbox.length; i++) { 9     ckvalue = ckvalue + chkbox[i].value + ","; //主键值 10     ntid = ntid + $(chkbox[i]).attr("data-ntid") + ","; //学生主键 11     code = code + $(chkbox[i]).attr("data-code") + ","; //胸卡号 12     name = name + $(chkbox[i]).attr("data-name") + ","; //姓名 13   } 14   if (ckvalue != "") { 15     ntid = ntid.substring(0, ntid.length - 1); 16     code = code.substring(0, code.length - 1); 17     name = name.substring(0, name.length - 1); 18     $.ajax({ 19       type: "POST", 20       url: "/NewStudent/BatchExportWord", 21       dataType: "json", 22       data: { tempFile: tfile, ntid: ntid }, 23       async: false, 24       success: function (data) { 25         if (data.isOK) { 26           var count = ntid.split(',').length; 27           if (count == data.ls.length && count > 0) { 28             DownLoadWord(objid, tfile, ntid, code, name, true); 29           } 30           else { 31             if (confirm("选择导出的数据中包含没有学习记录的数据,是否确认导出或打印?")) { 32               DownLoadWord(objid, tfile, ntid, code, name, true); 33             } 34           } 35         } 36         else { 37           alert(data.msg); 38         } 39       } 40     }); 41   } 42   else { 43     alert("请选择数据!"); 44   } 45 } 46 /*************************************** 47  * @methodname→批量导出word文档 48  * @createtime 2015-05-11 49  ***************************************/ 50 function BatchExportWord(objid, tfile) {   51   var ckvalue = "", ntid = "", code = "", name = ""; 52   var chkbox = $("input[type=checkbox][name=chk]:checked"); 53   for (var i = 0; i < chkbox.length; i++) { 54     ckvalue = ckvalue + chkbox[i].value + ","; //主键值 55     ntid = $(chkbox[i]).attr("data-ntid"); //学生主键 56     code = $(chkbox[i]).attr("data-code"); //胸卡号 57     name = $(chkbox[i]).attr("data-name"); //姓名 58   } 59   if (ckvalue != "") { 60     ckvalue = ckvalue.substring(0, ckvalue.length - 1); //去掉最后一个逗号 61     $.ajax({ 62       type: "POST", 63       url: "/NewStudent/BatchExportWord", 64       dataType: "json", 65       data: { tempFile: tfile }, 66       async: false, 67       success: function (data) { 68         if (data.isOK) { 69           DownLoadWord(objid, tfile, ntid, code, name, false) 70         } 71         else { 72           alert(data.msg); 73         } 74  75       } 76     }); 77   } 78   else { 79     alert("请选择数据!"); 80   } 81 } 82 /************************************************* 83  * @methodname→只能通过流的方式批量导出word文档 84   在页尾添加form,通过提交form表单才能下载 85  * @createtime 2015-05-12 86  *************************************************/ 87 function DownLoadWord(idName, tfile, ntid, code, name, isAll) {   88   $("body").find("form.#form1").remove(); 89   var form = "<form id='form1'></form>"; 90   var input = "<input />"; 91   var input1 = "", input2 = "", input3 = "", input4 = "", input5 = "", input6 = ""; 92   input1 = $(input); input1.attr("type", "hidden"); input1.attr("name", "tempFile"); input1.attr("value", tfile); 93   input2 = $(input); input2.attr("type", "hidden"); input2.attr("name", "ntid"); input2.attr("value", ntid); 94   input3 = $(input); input3.attr("type", "hidden"); input3.attr("name", "code"); input3.attr("value", code); 95   input4 = $(input); input4.attr("type", "hidden"); input4.attr("name", "name"); input4.attr("value", name); 96   input5 = $(input); input5.attr("type", "hidden"); input5.attr("name", "isAll"); input5.attr("value", isAll); 97   input6 = $(input); input6.attr("type", "hidden"); input6.attr("name", "idName"); input6.attr("value", idName); 98   $("body").append(form); //将表单放置在web中 99   //添加表单属性100   $("#form1").attr("style", "display:none");101   $("#form1").attr("target", "");102   $("#form1").attr("method", "post");  103   $("#form1").attr("action", "/NewStudent/DownLoadWord"); 104  105   //添加input到表单里106   $("#form1").append(input1)107   $("#form1").append(input1);108   $("#form1").append(input2);109   $("#form1").append(input3);110   $("#form1").append(input4);111   $("#form1").append(input5);112   $("#form1").append(input6);113   $("#form1").submit();114 }

js

     相关后台代码如下: 

 1 #region 压缩文件及文件夹 2   /// <summary> 3   /// 压缩文件及文件夹 4   /// </summary> 5   public class CompressFileZip 6   { 7     private ZipOutputStream zos = null; 8     private string strBaseDir = ""; 9  10     #region 临时文件夹名称 11     /// <summary> 12     /// 临时文件夹名称 13     /// </summary> 14     /// <param name="name">学生名称</param> 15     /// <param name="value">学生卡号</param> 16     /// <returns></returns> 17     public string FolderName(string name, string value) 18     { 19       string tempName = ""; 20       if (!string.IsNullOrEmpty(name)) 21       { 22         tempName = name; 23         if (!string.IsNullOrEmpty(value)) 24           tempName += "_" + value; 25         tempName += "_" + DateTime.Now.ToString("yyyyMMddHHmm"); 26       } 27       else 28       { 29         tempName = DateTime.Now.ToString("yyyyMMddHHmmss"); //临时文件夹名称 30       } 31       return tempName; 32     } 33     #endregion 34  35     #region 创建临时文件夹 36     /// <summary> 37     /// 创建临时文件夹 38     /// </summary> 39     /// <param name="name">学生名称</param> 40     /// <param name="value">学生卡号</param> 41     /// <returns></returns> 42     public string CreateTempFolder(string name, string value = null) 43     { 44       //遍历服务器指定文件夹下的所有文件 45       string path = "UploadFile"; 46       string serverPath = WordFilePath.GetFilePath(path); 47       string tempName = ""; 48       if (!string.IsNullOrEmpty(value)) 49         tempName = FolderName(name, value); 50       else 51         tempName = name; 52       string tempFolder = Path.Combine(serverPath, tempName); 53       Directory.CreateDirectory(tempFolder); //创建临时文件夹 54       //DirectoryInfo folder = new DirectoryInfo(serverPath); 55       return tempFolder + "\\"; 56     } 57     #endregion 58  59     #region 添加文件到压缩文件中 60     /// <summary> 61     /// 添加文件到压缩文件中 62     /// </summary> 63     /// <param name="PathStr">路径</param> 64     public void addZipEntry(string PathStr) 65     { 66       DirectoryInfo di = new DirectoryInfo(PathStr); 67       foreach (DirectoryInfo item in di.GetDirectories()) 68       { 69         addZipEntry(item.FullName); 70       } 71       foreach (FileInfo item in di.GetFiles()) 72       { 73         FileStream fs = System.IO.File.OpenRead(item.FullName); 74         byte[] buffer = new byte[fs.Length]; 75         fs.Read(buffer, 0, buffer.Length); 76         string strEntryName = item.FullName.Replace(strBaseDir, ""); 77         ZipEntry entry = new ZipEntry(strEntryName); 78         zos.PutNextEntry(entry); 79         zos.Write(buffer, 0, buffer.Length); 80         fs.Close(); 81       } 82     } 83     #endregion 84  85     #region 输出下载压缩包 86     /// <summary> 87     /// 输出下载压缩包 88     /// </summary> 89     /// <param name="response">页面响应</param> 90     /// <param name="strPath">文件所在的路径</param> 91     /// <param name="strFileName">压缩文件名</param> 92     /// <param name="strExt">压缩文件的扩展名</param> 93     public void dlZipDir(HttpResponseBase response, string strPath, string strFileName, string strExt = null) 94     { 95       if (string.IsNullOrEmpty(strExt)) 96         strExt = ".zip"; //默认压缩文件扩展名 97       MemoryStream ms = null; 98       response.ContentType = "application/octet-stream"; 99       strFileName = HttpUtility.UrlEncode(strFileName).Replace('+', ' ');100       response.AddHeader("Content-Disposition", "attachment; filename=" + strFileName + strExt);101       ms = new MemoryStream();102       zos = new ZipOutputStream(ms);103       strBaseDir = strPath + "\\";104       addZipEntry(strBaseDir);105       zos.Finish();106       zos.Close();107       response.Clear();108       response.BinaryWrite(ms.ToArray());109       //删除临时目录下的所有文件110       DeleteTempFiles(strPath);111       //删除空目录112       Directory.Delete(strPath);113       response.End();114     }115     #endregion116 117     #region 保存文件到临时文件夹中118     /// <summary>119     /// 保存文件到临时文件夹中120     /// </summary>121     /// <param name="content">将流内容写入字节组</param>122     /// <param name="SaveName">保存的文件名</param>123     /// /// <param name="dirPath">保存路径</param>124     /// <param name="fileExtend">保存的文件扩展名</param>125     /// <returns></returns>126     public void SaveFile(byte[] content, string SaveName, string dirPath, string fileExtend = null)127     {128 129       if (string.IsNullOrEmpty(fileExtend))130         fileExtend = ".doc"; //文件扩展名默认是word文档131       try132       {133         DateTime dt = DateTime.Now;134         //设置文件夹路径135         //directory = CreateTempFolder(strName, strCode);136         //文件保存完整路径137         string path = dirPath + SaveName + fileExtend;138         //验证文件夹是否存在  不存在则创建139         if (!Directory.Exists(dirPath))140         {141           Directory.CreateDirectory(dirPath);142         }143         //以创建文件的方式写入内容144         FileStream fs = new FileStream(path, FileMode.CreateNew, FileAccess.Write);145         BinaryWriter w = new BinaryWriter(fs);146         w.Write(content);147         w.Close();148         fs.Close();149       }150       catch (Exception ex)151       {152         throw new System.IO.FileNotFoundException("目录:" + dirPath + "没有找到!");153       }154     }155     #endregion156 157     #region 删除临时目录下的所有文件158     /// <summary>159     /// 删除临时目录下的所有文件160     /// </summary>161     /// <param name="tempPath">临时目录路径</param>162     private void DeleteTempFiles(string tempPath)163     {164       DirectoryInfo directory = new DirectoryInfo(tempPath);165       try166       {167         foreach (FileInfo file in directory.GetFiles())168         {169           if (file.Attributes.ToString().IndexOf("ReadOnly") != -1)170           {171             file.Attributes = FileAttributes.Normal;172           }173           System.IO.File.Delete(file.FullName);174         }175       }176       catch (Exception)177       {178         throw;179       }180     }181     #endregion182 183     #region 获取指定文件夹下的所有文件184     /// <summary>185     /// 获取指定文件夹下的所有文件186     /// </summary>187     /// <param name="Folder">文件夹名称</param>188     /// <param name="strName">文件夹下所包含指定文件名的文件</param>189     /// <returns></returns>190     public List<string> GetFileList(string Folder, string strName = null)191     {192       List<string> lsFile = new List<string>();193       if (!string.IsNullOrEmpty(Folder))194       {195         Folder = WordFilePath.GetFilePath("UploadFile", Folder + "\\");196         DirectoryInfo di = new DirectoryInfo(Folder);197         foreach (FileInfo item in di.GetFiles())198         {199           if (!string.IsNullOrEmpty(strName))200           {201             if (item.FullName.Contains(strName))202               lsFile.Add(item.FullName);203           }204           else205             lsFile.Add(item.FullName);206         }207       }208       return lsFile;209     } 210     #endregion211 212   }213   #endregion 214 215   #region 插入文档216   public class InsertFile217   {218     #region 在书签位置插入另一个文档的内容219     /// <summary>220     /// 使用DocumentBuilder对象插入一些文档对象,如插入书签,插入文本框,插入复选框221     /// 插入一个段落,插入空白页,追加或另一个word文件的内容等。222     /// </summary>223     /// <param name="doc">载入模板</param>224     /// <param name="tempFile"></param>225     /// <param name="mark">载入模版名称</param>226     /// <param name="lsFile"></param>227     public static void InsertDoc(Document doc, string mark, List<string> lsFile, string SaveName = null)228     {229       string savePath = "";230       var builder = new DocumentBuilder(doc);231       if (!string.IsNullOrEmpty(SaveName))232         SaveName = SaveName.Substring(0, SaveName.LastIndexOf("_"));233       Document doc1;234       for (int i = 0; i < lsFile.Count; i++)235       {236         if (i == 0)237           savePath = lsFile[i].Substring(0, lsFile[i].LastIndexOf('\\') + 1);238         doc1 = new Document(lsFile[i]);//新文档239         var bookmark = doc.Range.Bookmarks[mark];240         //清空书签的文本241         //bookmark.Text = "";242         //定位到指定位置进行插入操作243         builder.MoveToBookmark(mark, false, false);244         InsertDocument(bookmark.BookmarkStart.ParentNode, doc1);245         //doc.FirstSection.PageSetup.SectionStart = SectionStart.NewPage;246         //doc1.AppendDocument(doc, ImportFormatMode.KeepSourceFormatting);247 248         System.IO.File.Delete(lsFile[i]); //删除已经插入的文件        249       }250       if (!string.IsNullOrEmpty(SaveName))251         doc.Save(savePath + SaveName + ".doc");252     }253     #endregion254 255     #region 插入文档256     /// <summary>257     /// 插入文档258     /// </summary>259     /// <param name="insertAfterNode">节点在目标文件中的内容后插入。这个节点应该是一个块级节点(段落或表格)。</param>260     /// <param name="srcDoc">插入文档</param>261     private static void InsertDocument(Node insertAfterNode, Document srcDoc)262     {263       // 确保插入点是一个段落或表格。264       if ((!insertAfterNode.NodeType.Equals(NodeType.Paragraph)) &265        (!insertAfterNode.NodeType.Equals(NodeType.Table)))266         throw new ArgumentException("插入的目的节点应该是一个段落或表格。");267 268       // 插入到目标段落269       CompositeNode dstStory = insertAfterNode.ParentNode;270       NodeImporter importer = new NodeImporter(srcDoc, insertAfterNode.Document, ImportFormatMode.KeepSourceFormatting);271 272       //在源文件中循环273       foreach (Section srcSection in srcDoc.Sections)274       {275         foreach (Node srcNode in srcSection.Body)276         {277           // 跳过空节点278           if (srcNode.NodeType.Equals(NodeType.Paragraph))279           {280             Paragraph para = (Paragraph)srcNode;281             if (para.IsEndOfSection && !para.HasChildNodes)282               continue;283           }284           // 插入到目标文档285           Node newNode = importer.ImportNode(srcNode, true);286           // 参考节点后插入新节点287           dstStory.InsertAfter(newNode, insertAfterNode);288           insertAfterNode = newNode;289         }290       }291     }292     #endregion293   }294   #endregion 

Code

    页面调用的方式如下:

1 <input id="Export" type="button" class="s_btn" value="批量导出" onclick="AllExportWord(this.id, '接收进修生手册导出模板')" />2 <input id="Print" type="button" class="s_btn" value="批量打印" onclick="AllExportWord(this.id, '接收进修生手册导出模板')" />3 <input type="checkbox" name="chk" id="chk" value='@item.CardNo' data-ntid="@item.NTID" data-code="@item.CardNo" data-name="@item.NTName" /></td>

Html

    这里的this.id是传当前请求的按钮的id,因为调用的方法都一样,所以同时传id,加以区分页面的请求,以实现不同的功能。
controller调用的方法: 

 1    #region 批量下载文件前的验证 2    /// <summary> 3     /// 批量下载文件前的验证 4   /// </summary> 5     /// <param name="tempFile">模板</param> 6     /// <param name="ntid">学生主键</param> 7     /// <returns></returns> 8     public JsonResult BatchExportWord(string tempFile, string ntid = null) 9     { 10       bool isOK = false; 11       string msg = ""; 12       string strpath = "Content/templates"; 13       List<string> ls = new List<string>(); 14       if (!string.IsNullOrEmpty(tempFile)) 15       { 16         if (Path.GetExtension(tempFile) != ".doc") 17           tempFile = tempFile + ".doc"; 18         isOK = WordFilePath.ExistFile(strpath, tempFile); 19         if (!isOK) 20           msg = "导出的模板不存在!"; 21         else 22         { 23           if (!string.IsNullOrEmpty(ntid)) 24           { 25             string[] strNTID = ntid.Split(','); 26             for (int i = 0; i < strNTID.Length; i++) 27             { 28               NameValueCollection nvc = new NameValueCollection(); 29               nvc.Add(GetPropertyName<Model.MajorCycle>(m => m.NTID), strNTID[i]); 30               IList<Model.MajorCycle> lsMCycle = new BLL.MajorCycle().GetModelList<Model.MajorCycle>(nvc); 31               if (lsMCycle.Count > 0) 32                 ls.Add(string.Join(",", lsMCycle.Select(m => m.ID))); 33             } 34           } 35         } 36       } 37       else 38       { 39         msg = "导出的模板为空!"; 40       } 41       return Json(new { isOK = isOK, msg = msg, ls = ls }); 42     } 43     #endregion 44  45     #region 下载压缩包 46     /// <summary> 47     /// 下载压缩包 48     /// </summary> 49     /// <param name="tempFile">模板</param> 50     /// <param name="ntid">学生主键</param> 51     /// <param name="code">学生编号</param> 52     /// <param name="name">学生名称</param> 53     /// <param name="isAll">是否全部导出</param> 54     /// <param name="idName">请求按钮id名称</param> 55     /// <returns></returns> 56     public FileContentResult DownLoadWord(string tempFile, string ntid, string code, string name, string isAll, string idName) 57     { 58       CompressFileZip fileZip = new CompressFileZip(); 59       string saveName = "", dirPath = "", GzipFileName = "", mid = "", stype = "", sequence = ""; 60       Document doc = new Document(); 61       var docStream = new MemoryStream(); 62       if (!string.IsNullOrEmpty(ntid)) 63       { 64         string[] strNTID = ntid.Split(','); 65         string[] strCode = code.Split(','); 66         string[] strName = name.Split(','); 67         for (int i = 0; i < strNTID.Length; i++) 68         { 69           if (i == 0) //第一次时创建临时文件夹 70           { 71             if (!string.IsNullOrEmpty(isAll) && isAll == "true") 72               GzipFileName = fileZip.FolderName(tempFile.Substring(0, tempFile.IndexOf("生") + 1), ""); 73             else 74               GzipFileName = fileZip.FolderName(strName[i], strCode[i]); 75             dirPath = fileZip.CreateTempFolder(GzipFileName); 76           } 77           NameValueCollection nvc = new NameValueCollection(); 78           nvc.Add(GetPropertyName<Model.MajorCycle>(m => m.NTID), strNTID[i]); 79           IList<Model.MajorCycle> lsMCycle = new BLL.MajorCycle().GetModelList<Model.MajorCycle>(nvc); 80           if (lsMCycle.Count > 0) //如果不以这方式,则没有学习记录的数据导出来会是一个空的压缩包,什么文件也没有 81           { 82             mid = string.Join(",", lsMCycle.Select(m => m.MajorID)); // 轮转科室id 83             stype = lsMCycle[0].StudentType.ToString().Trim(); // 学生类型 84             sequence = string.Join(",", lsMCycle.Select(m => m.Sequence)); // 轮转次数 85           } 86           string[] midArr = mid.Split(','); 87           string[] sequenceArr = sequence.Split(','); 88           mid = ""; sequence = ""; 89           for (int j = 0; j < midArr.Length; j++) 90           { 91             saveName = strName[i] + "_" + strCode[i] + "_" + DateTime.Now.ToString("yyyyMMddHHmmssfff"); 92             WordHelper wordhelper = new WordHelper(tempFile); 93             getWordInfo(wordhelper, tempFile, strNTID[i], stype, midArr[j], sequenceArr[j]); 94             fileZip.SaveFile(wordhelper.ExportDoc().ToArray(), saveName, dirPath); 95           } 96           if (!string.IsNullOrEmpty(isAll) && isAll == "true" && idName == "Export") 97           { 98             doc = new Document(WordFilePath.GetFilePath("Content/templates", "test.doc")); 99             InsertFile.InsertDoc(doc, "p", fileZip.GetFileList(GzipFileName, strName[i]), saveName);100           }101 102         }103         if (idName == "Export")104           fileZip.dlZipDir(Response, WordFilePath.GetFilePath("UploadFile", GzipFileName), GzipFileName); //压缩下载105       }106 107       if (idName == "Print") //打印108       {109         doc = new Document(WordFilePath.GetFilePath("Content/templates", "test.doc"));110         InsertFile.InsertDoc(doc, "p", fileZip.GetFileList(GzipFileName));        111         doc.Save(docStream, SaveOptions.CreateSaveOptions(SaveFormat.Doc));112         Directory.Delete(WordFilePath.GetFilePath("UploadFile", GzipFileName));113       }114       return base.File(docStream.ToArray(), "application/msword", GzipFileName);115     }116     #endregion 

View Code

  导出的效果如下图:             图片              生成的临时文件夹:          

图片

      同一人的首先生成单个文件

图片

        将两个文件合并成一个文件,以姓名和编号命名,同时删除合并前生成的那两个文件:

图片

      循环生成 下一个人的单个文档

图片

     合并文件,以姓名和编号命名,同时删除合并前的文件:

图片     打包压缩合并后的这两个文件,并下载:

图片   

 





       打印的效果如下图:         将所有人的有关文档都生成单个文件 

图片

       最后合并成一个文件,并输出:

图片