.NET 通過Word模板,使用AsposeWord進行數據動態導出Word

来源:https://www.cnblogs.com/lucasDC/archive/2023/03/25/17255910.html
-Advertisement-
Play Games

@ 先看一下導出的整體效果(如下圖),其中標註的區域都是通過後臺動態生成的: 一、先在Word中建立好表格模板 1.1、參數創建方法(Word和WPS) 1.1.1、Office中Word域的創建 1.1.1.1、選中指定的單元格 -> 點擊頭部工具欄中的”插入“ -> 選擇 ”文檔部件“ -> 選 ...


@

目錄

先看一下導出的整體效果(如下圖),其中標註的區域都是通過後臺動態生成的:

效果圖

一、先在Word中建立好表格模板

Word模板

1.1、參數創建方法(Word和WPS)

1.1.1、Office中Word域的創建

1.1.1.1、選中指定的單元格 -> 點擊頭部工具欄中的”插入“ -> 選擇 ”文檔部件“ -> 選擇 ”域“;

Office添加域

1.1.1.2、在左側的 “選擇域” 中找到 “Mergefield” -> 在功能變數名稱中填寫變數名(註:填寫的功能變數名稱需要和後臺中定義的欄位名數組中的欄位一樣,這樣才會填充對應的數據);

變數名

1.1.1.3、列表創建域

有列表區域的;需要進行迴圈插入。迴圈生成區域插入:輸入開始標識:TableStart:UserList,這裡的 UserList 要與 dt.TableName = "UserList"對應,這樣DataTable中的數據才會對應填充到表格中。
迴圈區域
再輸入其他DataTable中的欄位。
其他欄位列
最後記得同樣輸入一個結束標識:《《TableEnd:UserList》》《《最後的列名》》,把下方多餘的行刪除,在WORD模板生成時,會自動向下填充的。

自此,Word表格模板已創建完成!

1.1.2、Office中WPS域的創建

1.1.2.1、選中指定的單元格 -> 點擊頭部工具欄中的”插入“ -> 選擇 ”文檔部件“ -> 選擇 ”域“;

WPS域的創建

1.1.2.2、在左側的 “選擇域” 中找到 “郵件合併” -> 在域代碼填寫變數名:例如:(MERGEFIELD Textdwmc)(註:填寫的功能變數名稱需要和後臺中定義的欄位名數組中的欄位一樣,這樣才會填充對應的數據);

填充數據
自此,WPS中Word表格模板已創建完成!

二、添加相關的DLL文件

這裡的前提,你需要引用Aspose.Words.dll文件:using Aspose.Words;

2.1、添加相關的DLL文件

2.1.1、右鍵項目->管理NuGet程式包

管理NuGet程式包

2.1.2、在 管理NuGet程式包 中的瀏覽搜索:Aspose.Words(註:一定選擇21.8.0版本,這個版本能去水印,其餘高版本我暫沒試過( ̄▽ ̄)~*)點擊安裝即可!

安裝
自此,Aspose.Words就安裝成功!或者直接從網上下載指定的版本即可

三、編寫代碼(後臺.NET 代碼以VS 2019為例)

3.1、定義公共的欄位(註:定義的數組欄位要和Word模板中的功能變數名稱相同

/// <summary>
/// 公共欄位名字元串數組
/// </summary>
public static String[] fieldNames = new String[] { "Textdwmc", "Textdwdz", "Textfrdb", "Texthyxm", "Textmz", "Radioxb", "Textsfz", "Textdp", "Textlxdh", "Textwhcd", "Textgryx", "Texthyxz", "Textqyrs", "Textjxdz", "droprhxz", "Textrhsq", "Radiostate" };

/// <summary>
/// 文件名
/// </summary>
public static fileName="";

3.2、Word模板操作核心方法

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web;
using System.IO;
//這裡的前提,你需要引用Aspose.Words.dll文件
using Aspose.Words;
using System.Data;

namespace AsposeWord//類名,可根據實際情況而定
{
    /// <summary>
    /// 通過WORD模板導出文檔
    /// </summary>
    public class WordModelEvent
    {
        /// <summary>
        /// 根據Word模板進行數據的導出Word操作
        /// </summary>
        /// <param name="modelDoc">模板路徑</param>
        /// <param name="exptDoc">導出文件名</param>
        /// <param name="fieldNames">欄位名字元串數組</param>
        /// <param name="fieldValues">欄位值數組</param>
        /// <param name="dt">需要迴圈的數據DataTable</param>
        /// <returns>返回的文檔路徑</returns>
        public static string ExpertWordToModel(string modelDoc, string exptDoc, String[] fieldNames, Object[] fieldValues, DataTable dt)
        {
            try
            {
                removeWatermark();//載入監聽,用於去除水印
                //string tempPath = HttpContext.Current.Server.MapPath("~/Demos/" + modelDoc + ".docx");//word模板路徑
                string tempPath = "../" + modelDoc + ".docx";
                //導出的WORD存放的位置
                const string saveFold = "../word/";
                //string outputPath = HttpContext.Current.Server.MapPath("~/" + saveFold);
                string outputPath = "" + saveFold;
                if (!Directory.Exists(outputPath))
                {
                    Directory.CreateDirectory(outputPath);
                }
                //生成的WORD文件名
                string fileName = exptDoc + "信息.docx";
                outputPath += fileName;
                //載入模板
                Document doc = new Document(tempPath);
                doc.MailMerge.Execute(fieldNames, fieldValues);
                //將我們獲得的DataTable類型的數據:EduDataTable放入doc方法中做處理
                if (dt.Rows.Count > 0 && dt!=null)
                {
                    doc.MailMerge.ExecuteWithRegions(dt);
                }
                //獲取下載地址
                String StrVisitURL = saveFold + fileName;
                //合併模版,相當於頁面的渲染
                doc.MailMerge.Execute(new[] { "PageCount" }, new object[] { doc.PageCount });
                //保存合併後的文檔
                doc.Save(outputPath);
                return StrVisitURL;
            }
            catch (Exception er)
            {
                return er.Message;
            }
        }

        /// <summary>
        /// 載入監聽,用於去除水印
        /// </summary>
        public static void removeWatermark()
        {
            new Aspose.Words.License().SetLicense(new MemoryStream(Convert.FromBase64String("PExpY2Vuc2U+CiAgPERhdGE+CiAgICA8TGljZW5zZWRUbz5TdXpob3UgQXVuYm94IFNvZnR3YXJlIENvLiwgTHRkLjwvTGljZW5zZWRUbz4KICAgIDxFbWFpbFRvPnNhbGVzQGF1bnRlYy5jb208L0VtYWlsVG8+CiAgICA8TGljZW5zZVR5cGU+RGV2ZWxvcGVyIE9FTTwvTGljZW5zZVR5cGU+CiAgICA8TGljZW5zZU5vdGU+TGltaXRlZCB0byAxIGRldmVsb3BlciwgdW5saW1pdGVkIHBoeXNpY2FsIGxvY2F0aW9uczwvTGljZW5zZU5vdGU+CiAgICA8T3JkZXJJRD4yMDA2MDIwMTI2MzM8L09yZGVySUQ+CiAgICA8VXNlcklEPjEzNDk3NjAwNjwvVXNlcklEPgogICAgPE9FTT5UaGlzIGlzIGEgcmVkaXN0cmlidXRhYmxlIGxpY2Vuc2U8L09FTT4KICAgIDxQcm9kdWN0cz4KICAgICAgPFByb2R1Y3Q+QXNwb3NlLlRvdGFsIGZvciAuTkVUPC9Qcm9kdWN0PgogICAgPC9Qcm9kdWN0cz4KICAgIDxFZGl0aW9uVHlwZT5FbnRlcnByaXNlPC9FZGl0aW9uVHlwZT4KICAgIDxTZXJpYWxOdW1iZXI+OTM2ZTVmZDEtODY2Mi00YWJmLTk1YmQtYzhkYzBmNTNhZmE2PC9TZXJpYWxOdW1iZXI+CiAgICA8U3Vic2NyaXB0aW9uRXhwaXJ5PjIwMjEwODI3PC9TdWJzY3JpcHRpb25FeHBpcnk+CiAgICA8TGljZW5zZVZlcnNpb24+My4wPC9MaWNlbnNlVmVyc2lvbj4KICAgIDxMaWNlbnNlSW5zdHJ1Y3Rpb25zPmh0dHBzOi8vcHVyY2hhc2UuYXNwb3NlLmNvbS9wb2xpY2llcy91c2UtbGljZW5zZTwvTGljZW5zZUluc3RydWN0aW9ucz4KICA8L0RhdGE+CiAgPFNpZ25hdHVyZT5wSkpjQndRdnYxV1NxZ1kyOHFJYUFKSysvTFFVWWRrQ2x5THE2RUNLU0xDQ3dMNkEwMkJFTnh5L3JzQ1V3UExXbjV2bTl0TDRQRXE1aFAzY2s0WnhEejFiK1JIWTBuQkh1SEhBY01TL1BSeEJES0NGbWg1QVFZRTlrT0FxSzM5NVBSWmJRSGowOUNGTElVUzBMdnRmVkp5cUhjblJvU3dPQnVqT1oyeDc4WFE9PC9TaWduYXR1cmU+CjwvTGljZW5zZT4=")));
        }
    }
}

3.3、通過Word模板生成新文件

/// <summary>
        /// 根據WORD模板基本信息
        /// </summary>
        /// <param name="id">需要迴圈的子數據的所屬上級ID</param>
        /// <returns>返回完成的文件下載路徑</returns>
        public static string GetWordEvent(string id)
        {
            try
            {
            //這裡是實例化Model,如果項目已有封裝的查詢資料庫信息的方法,直接使用參數“id”進行動態數據查詢即可
                memberUnit member = new memberUnit();
                member.id = "202204291157458529";
                member.Textdwmc = "長沙傑術有限公司";
                member.Textdwdz = "湖南省長";
                member.Textfrdb =null;
                member.Texthyxm = "gows";
                member.Textmz = "漢";
                member.Radioxb = "男";
                member.Textsfz = "4302685556951366";
                member.Textdp = "黨員";
                member.Textlxdh = "175125956569";
                member.Textwhcd = "高中";
                member.Textgryx = "[email protected]";
                member.Texthyxz = "wu";
                member.Textqyrs = "1444";
                member.Textjxdz = "湖南啊";
                member.droprhxz = "副會長";
                member.Textrhsq = "呃呃呃呃呃呃呃呃呃呃";
                member.Radiostate = "已處理";

                Object[] fieldValues = new object[fieldNames.Length];
                fieldValues[0] = member.Textdwmc;
                fieldValues[1] = member.Textdwdz;
                fieldValues[2] = member.Textfrdb;
                fieldValues[3] = member.Texthyxm;
                fieldValues[4] = member.Textmz;
                fieldValues[5] = member.Radioxb;
                fieldValues[6] = member.Textsfz;
                fieldValues[7] = member.Textdp;
                fieldValues[8] = member.Textlxdh;
                fieldValues[9] = member.Textwhcd;
                fieldValues[10] = member.Textgryx;
                fieldValues[11] = member.Texthyxz;
                fieldValues[12] = member.Textqyrs;
                fieldValues[13] = member.Textjxdz;
                fieldValues[14] = member.droprhxz;
                fieldValues[15] = member.Textrhsq;
                fieldValues[16] = member.Radiostate;
                DataTable dt = new DataTable();
                
            	#region /// 註意:如果在Word中沒有類似表格或者列表的數據,此處則不需要,刪除即可

                if (!string.IsNullOrEmpty(id))
                {
                    string sql = " SELECT * FROM TABLE WHERE id='' ORDER BY id DESC ";
                    dt = getDataTable(sql);
                    //這裡的UserList很關鍵,要與WORD模板的域設置對應,不是隨便寫的,後面還會用到
                    dt.TableName = "UserList";
                }

            	#endregion
            	
                string StrVisitURL = WordModelEvent.ExpertWordToModel("template", member.Textdwmc, fieldNames, fieldValues, dt);
                dt.Dispose();
                return StrVisitURL;
            }
            catch (Exception er)
            {
                return er.Message;
            }
        }

        /// <summary>
        /// 通過SQL獲得 DataTable
        /// </summary>
        /// <param name="sql">sql查詢語句</param>
        /// <param name="ConnectionString">你的數據鏈接字元串</param>
        /// <returns></returns>
        private static DataTable getDataTable(string sql, string ConnectionString = "")
        {
            SqlConnection cn = new SqlConnection(ConnectionString);
            SqlDataAdapter da = new SqlDataAdapter(sql, cn);
            DataTable ds = new DataTable();
            da.Fill(ds);
            cn.Dispose();
            return ds;
        }

3.4、調用方法

string url=  GetWordEvent("");

3.5、.NET 文件下載

3.5.1、ASP.NET 文件下載

/// <summary>
       ///字元流下載方法
       /// </summary>
       /// <param name="fileName">下載文件生成的名稱</param>
       /// <param name="fPath">下載文件路徑</param>
       /// <returns></returns>
        public void DownloadFile(string fileName, string fPath)
        {
            string filePath = Server.MapPath(fPath);//路徑
            //以字元流的形式下載文件
            FileStream fs = new FileStream(filePath, FileMode.Open);
            byte[] bytes = new byte[(int)fs.Length];
            fs.Read(bytes, 0, bytes.Length);
            fs.Close();
            Response.ContentType = "application/octet-stream";
            //通知瀏覽器下載文件而不是打開
            Response.AddHeader("Content-Disposition", "attachment;   filename=" + HttpUtility.UrlEncode(fileName, System.Text.Encoding.UTF8));
            Response.BinaryWrite(bytes);
            Response.Flush();
            if (!string.IsNullOrEmpty(filePath)&& filePath!=".")
            {
               System.IO.File.Delete(filePath+"/"+fileName);//在文件下載之後刪除其生成的文件
            }
            Response.End();
        }

3.5.2、ASP.NET MVC 的下載方法

/// <summary>
        /// 下載文件的方法
        /// </summary>
        /// <param name="path">文件絕對路徑</param>
        /// <param name="fileName">客戶端接收的文件名</param>
        /// <returns></returns>
        public static HttpResponseMessage Download(string path, string fileName)
        {
            var stream = File.OpenRead(path);
            HttpResponseMessage httpResponseMessage = new HttpResponseMessage(HttpStatusCode.OK);
            try
            {
                httpResponseMessage.Content = new StreamContent(stream);
                httpResponseMessage.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
                if (!string.IsNullOrEmpty(fileName))
                {
                    httpResponseMessage.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
                    {
                        FileName = HttpUtility.UrlEncode(fileName, Encoding.UTF8),
                    };
                }
                if (!string.IsNullOrEmpty(filePath)&& filePath!=".")
                {
                   System.IO.File.Delete(filePath+"/"+fileName);//在文件下載之後刪除其生成的文件
                }
                return httpResponseMessage;
            }
            catch
            {
                stream.Dispose();
                httpResponseMessage.Dispose();
                throw;
            }
        }

本文來自博客園,作者:TomLucas,轉載請註明原文鏈接:https://www.cnblogs.com/lucasDC/p/17255910.html


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 之前瞭解到通過UFUN函數UF_UGMGR_invoke_pdm_server可以調用Teamcenter ITK函數,從而可以獲取及編輯Teamcenter對象。UFUN中有樣例代碼,但是就是不知道怎麼使用,今天下午看了幫助文檔,想到需要把ITK的USER_invoke_pdm_server函數進 ...
  • 開發了一個Java庫的Google Bard API,可以自動化與AI對話了 Google Bard是Google提供的還在實驗階段的人工智慧對話服務。這明顯是對標ChatGPT來的,它可以提供更實時的答案,會基於Google強大的網頁數據。 為了更方便的使用並實現自動化,我寫了一個Java類庫,G ...
  • 信號槽連接 信號槽的連接,其實內部本質還是一個回調函數,主要是維護了信號發送Object的元對象里一個連接的列表。調用connect函數時,將槽的一系列信息,封裝成一個Connection,在發送信號時,通過這個列表,去回調槽函數。 1. 信號的連接 下麵列舉一種信號的連接方式,來大致講解一下信號的 ...
  • 零基礎 OpenGL ES 學習路線推薦 : OpenGL ES 學習目錄 >> OpenGL ES 基礎 零基礎 OpenGL ES 學習路線推薦 : OpenGL ES 學習目錄 >> OpenGL ES 特效 零基礎 OpenGL ES 學習路線推薦 : OpenGL ES 學習目錄 >> O ...
  • 原文地址: Java/Kotlin 使用Redis模擬發送郵件驗證碼 - Stars-One的雜貨小窩 Java中常用語連接Redis的庫有lettuce和jredis,一般是推薦lettuce,其具有非同步性,下麵兩種都簡單來使用如何實現功能 jredis 1.引入依賴 <dependency> < ...
  • 原文鏈接:https://www.zhoubotong.site/post/91.html 通常樹形菜單的實現基本就是遞歸調用,大部分場景畢竟這種數據不多,性能倒是並不突出, 下麵給個demo,有興趣的朋友可以看看: 新建一個city表: CREATE TABLE `city` ( `id` int ...
  • What is static and dynamic libraries 他們有什麼相同點嗎? 都是庫文件。對於調用庫文件的使用者來說,不管是靜態庫還是動態庫,調用的方式都是一樣的,沒什麼區別。 Differences between static and dynamic libraries 動態庫 ...
  • [NOIP2002 普及組] 選數 洛谷傳送門 點擊查看題目 題目描述 已知 n 個整數 x1,x2,.....,xn,以及 1 個整數 k(k<n)。從 n 個整數中任選 k 個整數相加,可分別得到一系列的和。例如當 n=4,k=3,4 個整數分別為 3,7,12,19 時,可得全部的組合與它們的 ...
一周排行
    -Advertisement-
    Play Games
  • C#TMS系統代碼-基礎頁面BaseCity學習 本人純新手,剛進公司跟領導報道,我說我是java全棧,他問我會不會C#,我說大學學過,他說這個TMS系統就給你來管了。外包已經把代碼給我了,這幾天先把增刪改查的代碼背一下,說不定後面就要趕鴨子上架了 Service頁面 //using => impo ...
  • 委托與事件 委托 委托的定義 委托是C#中的一種類型,用於存儲對方法的引用。它允許將方法作為參數傳遞給其他方法,實現回調、事件處理和動態調用等功能。通俗來講,就是委托包含方法的記憶體地址,方法匹配與委托相同的簽名,因此通過使用正確的參數類型來調用方法。 委托的特性 引用方法:委托允許存儲對方法的引用, ...
  • 前言 這幾天閑來沒事看看ABP vNext的文檔和源碼,關於關於依賴註入(屬性註入)這塊兒產生了興趣。 我們都知道。Volo.ABP 依賴註入容器使用了第三方組件Autofac實現的。有三種註入方式,構造函數註入和方法註入和屬性註入。 ABP的屬性註入原則參考如下: 這時候我就開始疑惑了,因為我知道 ...
  • C#TMS系統代碼-業務頁面ShippingNotice學習 學一個業務頁面,ok,領導開完會就被裁掉了,很突然啊,他收拾東西的時候我還以為他要旅游提前請假了,還在尋思為什麼回家連自己買的幾箱飲料都要叫跑腿帶走,怕被偷嗎?還好我在他開會之前拿了兩瓶芬達 感覺感覺前面的BaseCity差不太多,這邊的 ...
  • 概述:在C#中,通過`Expression`類、`AndAlso`和`OrElse`方法可組合兩個`Expression<Func<T, bool>>`,實現多條件動態查詢。通過創建表達式樹,可輕鬆構建複雜的查詢條件。 在C#中,可以使用AndAlso和OrElse方法組合兩個Expression< ...
  • 閑來無聊在我的Biwen.QuickApi中實現一下極簡的事件匯流排,其實代碼還是蠻簡單的,對於初學者可能有些幫助 就貼出來,有什麼不足的地方也歡迎板磚交流~ 首先定義一個事件約定的空介面 public interface IEvent{} 然後定義事件訂閱者介面 public interface I ...
  • 1. 案例 成某三甲醫預約系統, 該項目在2024年初進行上線測試,在正常運行了兩天後,業務系統報錯:The connection pool has been exhausted, either raise MaxPoolSize (currently 800) or Timeout (curren ...
  • 背景 我們有些工具在 Web 版中已經有了很好的實踐,而在 WPF 中重新開發也是一種費時費力的操作,那麼直接集成則是最省事省力的方法了。 思路解釋 為什麼要使用 WPF?莫問為什麼,老 C# 開發的堅持,另外因為 Windows 上已經裝了 Webview2/edge 整體打包比 electron ...
  • EDP是一套集組織架構,許可權框架【功能許可權,操作許可權,數據訪問許可權,WebApi許可權】,自動化日誌,動態Interface,WebApi管理等基礎功能於一體的,基於.net的企業應用開發框架。通過友好的編碼方式實現數據行、列許可權的管控。 ...
  • .Net8.0 Blazor Hybird 桌面端 (WPF/Winform) 實測可以完整運行在 win7sp1/win10/win11. 如果用其他工具打包,還可以運行在mac/linux下, 傳送門BlazorHybrid 發佈為無依賴包方式 安裝 WebView2Runtime 1.57 M ...