接下來是批量導出word文檔和批量打印word文件,批量導出word文檔和批量打印word文件的思路差不多,只是批量打印不用打包壓縮文件,而是把所有文件合成一個word,然后通過js來調用word,提交打印機,把word文檔的內容都打印出來。
批量導出word文檔需要用到ICSharpCode.SharpZipLib.dll 插件,思路是,先單獨導出所勾選的數據的單個文檔,保存到生成的臨時目錄下,再把同一個的人相關文檔合並一個word文檔,並刪除已經合並的那個文檔(不是合並后生成的文檔),以姓名和編號命名生成后的文檔,最后將臨時目錄下的所有文件打包壓縮下載,並刪除臨時目錄和臨時目錄下的所有文件(都是生成在服務器上,所以若文件太大,可能會慢)。批量導出是用form來提交所傳的參數,並下載。(因為懶,不解釋代碼了)
首先新建一個空文檔,插入書簽,書簽名為“p”(隨便定義的),命名文件名為“test.doc”,保存在項目目錄下。
相關js代碼為:
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 }
相關后台代碼如下:

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 #endregion 116 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 try 132 { 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 #endregion 156 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 try 166 { 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 #endregion 182 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 else 205 lsFile.Add(item.FullName); 206 } 207 } 208 return lsFile; 209 } 210 #endregion 211 212 } 213 #endregion 214 215 #region 插入文檔 216 public class InsertFile 217 { 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 #endregion 254 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 #endregion 293 } 294 #endregion
頁面調用的方式如下:

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>
這里的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
導出的效果如下圖: 生成的臨時文件夾:

同一人的首先生成單個文件

將兩個文件合並成一個文件,以姓名和編號命名,同時刪除合並前生成的那兩個文件:

循環生成 下一個人的單個文檔

合並文件,以姓名和編號命名,同時刪除合並前的文件:

打包壓縮合並后的這兩個文件,並下載:


打印的效果如下圖: 將所有人的有關文檔都生成單個文件

最后合並成一個文件,並輸出:
