[C#][MVC5] 利用Novacode的word下載

  • 5498
  • 0

MVC中的報表列印

不斷複製貼上word文件裡的特定表格塞資料

最後flush檔案供下載

如果不想慢慢數word檔中要擺放的位置,可直接用代碼取代的方式

Novacode權限層級比word檔本身設定還低的樣子

就算Novacode設定,有些細部格式(字型)都會已word檔主題為主

所以能先在word裡調好格式就少寫code省麻煩

ex:在word範本檔中的目標位置先寫「@Test@」,再用ReplaceText("@Test@", "我要填寫的內容在這")

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.MVC;
using ProjectName.Extensions; //一些模組化的雜七雜八,ex:this.HttpContext.取得清單()
using ProjectName.ViewModels;
using ProjectName.Models;

using System.Entity;
using Novacode; //去網路上下載dll檔匯入參考
using System.Drawing;

/// <summary>
/// Summary description for Class1
/// </summary>
public class 列印Controller : Controller
{
    [DeleteFileAfterDownload]
	public ActionResult 列印 (vmType vm, FormCollection fc, string command)
	{
        if (command == "print")
        {
            vm = (vmType)TempData["ViewVm"];
            TempData.Keep("ViewVm");

            FilePathResult file = null;
            string 範本檔名稱 = Server.MapPath("~/TemplateFiles/") + "範本.docx";
            string 暫存檔名稱 = Server.MapPath("~/Temp/") + Guid.NewGuid() + ".docx";

            try
            {
                #region prepare data
                IEnumerable<問題> ie問題 = this.HttpContext.取得清單().Where(x => x.作業序號 == this.HttpContext.取得作業序號());
                #endregion

                using (DocX doc = DocX.Load(範本黨名稱))
                {
                    //複製一份範本文件供「貼上」時使用
                    DocX doc2 = doc.Copy();
                    //選擇字體
                    FontFamily f標楷體 = new FontFamily("DFKai-SB"); //標楷體代碼:DFKai-SB

                    int m = 1;

                    foreach (var empAns in vm.符合清單.Where(x => x.是否確認 == true))
                    {
                        //定位Table的資料位置
                        Table t = doc.Tables[0];
                        Paragraph p資料1 = t.Rows[1].Cells[0].Paragraphs[0];
                        Paragraph p資料2 = t.Rows[2].Cells[0].Paragraphs[0];
                        Paragraph p資料3 = t.Rows[3].Cells[0].Paragraphs[0];
                        Paragraph p資料4 = t.Rows[4].Cells[0].Paragraphs[0];

                        //寫入內容
                        p資料1.ReplaceText(".", "填表日期" + 日期); //用append有時會讓該列word格式跑掉,所以在原始檔裡面加個".",為保存格式改用取代方式
                        p資料2.Append(empAns.姓名).Font(f標楷體);
                        foreach(var liAns in empAns.詳細情況.OrderBy(x => x.問題序號))
                        {
                            if ( liAns.問題序號 == ie問題.Where(x => x.問題內容.Contains("事由")).Select(x => x.問題序號).FirstOrDefault() )
                            {
                                string 事由 = liAns.問題選項.選項名稱;
                                p資料3.Append(事由).FontSize(14);
                            }
                        }

                        //調整格式
                        p資料1.Alignment = Alignment.center;
                        t.Rows[1].Cells[0].VerticalAligment = VerticalAligment.Center;

                        //複製貼上新的表格
                        if(m< vm.符合清單.Where(x => x.是否確認 == true).Count())
                        {
                            //原始的table index為[0],複製的doc2.table[0]會插入在doc.table[0]前變成新的doc.table[0],
                            //而把舊的doc.table[0]往下擠成doc.table[1],以此類推
                            doc.Tables[0].InsertTableBeforeSelf(doc2.Tables[0]);
                            doc.Tables[0].InsertPageBreakAfterSelf();
                            m++;
                        }
                    }

                    doc.SaveAs(暫存檔名稱);                    
                }

                file = File(暫存檔名稱, "application/vnd.openxmlformats-officedocument.wordprocessingml.document", "匯出名稱.docx");
                return file;
            }
            catch(Exception ex)
            {
                return View("Error", new HandleErrorInfo(ex, "controllerName", "actionName"));
            }            
        }
	}
}

public class DeleteFileAfterDownloadAttribute : ActionFilterAttribute
{
    public override void OnResultExecuted(ResultExecutedContext filterContext)
    {
        var fpr = filterContext.Result as FilePathResult;
        filterContext.HttpContext.Response.Flush();
        if (fpr != null)
        {
            System.IO.File.Delete(fpr.FileName);
        }
    }
}