diff --git a/README.md b/README.md index bb98cea0b2c98a9cfb2e99b8f50213a8ba06e644..bf2ee53be88500f25bb8c51bf6dd1db6d930189a 100644 --- a/README.md +++ b/README.md @@ -1,474 +1,40 @@ -
-

NuGet -GitHub stars -version -Ask DeepWiki -

-
+# miniword中添加html支持 ---- +## 说明 -

version version version version version version version version version version version version version version version version version

+在**miniword**项目中引用**htmlToOpenXml**添加html支持 ---- +## 环境 -
- Your Star and dotnate can make MiniWord better -
+**.Net Framework 4.6.2**, **.NET Standard 2.0** ---- +## 相关依赖 -## Introduction +**miniword**:https://gitee.com/dotnetchina/MiniWord -MiniWord is an easy and effective .NET Word Template library. +**htmlToOpenXml**:https://github.com/onizet/html2openxml -![image](https://user-images.githubusercontent.com/12729184/190835307-6cd87982-b5f3-4a79-9682-bdd1cc02a4ea.png) +## 使用手册 +1. 引入MiniWordWithHtml.dll + https://gitee.com/tangdou89/MiniWord/releases -## Getting Started +2. nuget安装依赖 -### Installation + ```cmd + dotnet add package DocumentFormat.OpenXml --version 3.4.1 + dotnet add package HtmlToOpenXml --version 3.3.1 + dotnet add package System.Text.Encoding.CodePages --version 10.0.3 + ``` -- nuget link : https://www.nuget.org/packages/MiniWord +3. html解析 -### Quick Start + ```c# + new MiniWordHtml + { + HtmlText = File.ReadAllText(@"TestData\sample2.html") + } + ``` -Template follow "WHAT you see is what you get" design,and the template tag styles are completely preserved. -```csharp -var value = new Dictionary(){["title"] = "Hello MiniWord"}; -MiniSoftware.MiniWord.SaveAsByTemplate(outputPath, templatePath, value); -``` - -![image](https://user-images.githubusercontent.com/12729184/190875707-6c5639ab-9518-4dc1-85d8-81e20af465e8.png) - -### Input, Output - -- Input support file path, byte[] -- Output support file path, byte[], stream - -```csharp -SaveAsByTemplate(string path, string templatePath, Dictionary value) -SaveAsByTemplate(string path, byte[] templateBytes, Dictionary value) -SaveAsByTemplate(this Stream stream, string templatePath, Dictionary value) -SaveAsByTemplate(this Stream stream, byte[] templateBytes, Dictionary value) -``` - - - -## Tags - -MiniWord template format string like Vue, React `{{tag}}`,users only need to make sure tag and value parameter key same then system will replace them automatically. - -### Text - -```csharp -{{tag}} -``` - -##### Example - -```csharp -var value = new Dictionary() -{ - ["Name"] = "Jack", - ["Department"] = "IT Department", - ["Purpose"] = "Shanghai site needs a new system to control HR system.", - ["StartDate"] = DateTime.Parse("2022-09-07 08:30:00"), - ["EndDate"] = DateTime.Parse("2022-09-15 15:30:00"), - ["Approved"] = true, - ["Total_Amount"] = 123456, -}; -MiniWord.SaveAsByTemplate(path, templatePath, value); -``` - -##### Template - -![image](https://user-images.githubusercontent.com/12729184/190834360-39b4b799-d523-4b7e-9331-047a61fd5eb9.png) - -##### Result - -![image](https://user-images.githubusercontent.com/12729184/190834455-ba065211-0f9d-41d1-9b7a-5d9e96ac2eff.png) - -### Image - -Value type is `MiniWordPicture` - -##### Example - -```csharp -var value = new Dictionary() -{ - ["Logo"] = new MiniWordPicture() { Path= PathHelper.GetFile("DemoLogo.png"), Width= 180, Height= 180 } -}; -MiniWord.SaveAsByTemplate(path, templatePath, value); -``` - - - -##### Template - -![image](https://user-images.githubusercontent.com/12729184/190647953-6f9da393-e666-4658-a56d-b3a7f13c0ea1.png) - -##### Result - -![image](https://user-images.githubusercontent.com/12729184/190648179-30258d82-723d-4266-b711-43f132d1842d.png) - -### List - -tag value is `string[]` or `IList` type - -##### Example - -```csharp -var value = new Dictionary() -{ - ["managers"] = new[] { "Jack" ,"Alan"}, - ["employees"] = new[] { "Mike" ,"Henry"}, -}; -MiniWord.SaveAsByTemplate(path, templatePath, value); -``` - -Template - -![image](https://user-images.githubusercontent.com/12729184/190645513-230c54f3-d38f-47af-b844-0c8c1eff2f52.png) - -##### Result - -![image](https://user-images.githubusercontent.com/12729184/190645704-1f6405e9-71e3-45b9-aa99-2ba52e5e1519.png) - -### Table - -Tag value is `IEmerable>` type - -##### Example - -```csharp -var value = new Dictionary() -{ - ["TripHs"] = new List> - { - new Dictionary - { - { "sDate",DateTime.Parse("2022-09-08 08:30:00")}, - { "eDate",DateTime.Parse("2022-09-08 15:00:00")}, - { "How","Discussion requirement part1"}, - { "Photo",new MiniWordPicture() { Path = PathHelper.GetFile("DemoExpenseMeeting02.png"), Width = 160, Height = 90 }}, - }, - new Dictionary - { - { "sDate",DateTime.Parse("2022-09-09 08:30:00")}, - { "eDate",DateTime.Parse("2022-09-09 17:00:00")}, - { "How","Discussion requirement part2 and development"}, - { "Photo",new MiniWordPicture() { Path = PathHelper.GetFile("DemoExpenseMeeting01.png"), Width = 160, Height = 90 }}, - }, - } -}; -MiniWord.SaveAsByTemplate(path, templatePath, value); -``` - -##### Template - -![image](https://user-images.githubusercontent.com/12729184/190843632-05bb6459-f1c1-4bdc-a79b-54889afdfeea.png) - - -##### Result - -![image](https://user-images.githubusercontent.com/12729184/190843663-c00baf16-21f2-4579-9d08-996a2c8c549b.png) - -### List inside list - -Tag value is `IEnumerable` type. Adding `{{foreach` and `endforeach}}` tags to template is required. - -##### Example - -```csharp -var value = new Dictionary() -{ - ["TripHs"] = new List> - { - new Dictionary - { - { "sDate", DateTime.Parse("2022-09-08 08:30:00") }, - { "eDate", DateTime.Parse("2022-09-08 15:00:00") }, - { "How", "Discussion requirement part1" }, - { - "Details", new List() - { - new MiniWordForeach() - { - Value = new Dictionary() - { - {"Text", "Air"}, - {"Value", "Airplane"} - }, - Separator = " | " - }, - new MiniWordForeach() - { - Value = new Dictionary() - { - {"Text", "Parking"}, - {"Value", "Car"} - }, - Separator = " / " - } - } - } - } - } -}; -MiniWord.SaveAsByTemplate(path, templatePath, value); -``` - -##### Template - -![before_foreach](https://user-images.githubusercontent.com/38832863/220123955-063c9345-3998-4fd7-982c-8d1e3b48bbf8.PNG) - -Screenshot 2023-08-08 at 17 59 37 - -##### Result - -![after_foreach](https://user-images.githubusercontent.com/38832863/220123960-913a7140-2fa2-415e-bb3e-456e04167382.PNG) - -Screenshot 2023-08-08 at 18 00 15 - -### If statement inside template - -For multip paragraph, use @if and @endif tags. -For single paragraph and inside foreach, use `{{if` and `endif}}` tags to template is required. - -##### Example - -```csharp -var value = new Dictionary() -{ - ["Name"] = new List(){ - new MiniWordHyperLink(){ - Url = "https://google.com", - Text = "測試連結22!!" - }, - new MiniWordHyperLink(){ - Url = "https://google1.com", - Text = "測試連結11!!" - } - }, - ["Company_Name"] = "MiniSofteware", - ["CreateDate"] = new DateTime(2021, 01, 01), - ["VIP"] = true, - ["Points"] = 123, - ["APP"] = "Demo APP", -}; -MiniWord.SaveAsByTemplate(path, templatePath, value); -``` - -##### Template For Multi Paragraph - -![before_if](https://user-images.githubusercontent.com/38832863/220125429-7dd6ce94-35c6-478e-8903-064f9cf9361a.PNG) - -##### Result Of Multi Paragraph - -![after_if](https://user-images.githubusercontent.com/38832863/220125435-72ea24b4-2412-45de-961a-ad4b2134417b.PNG) - -##### Template For Single Paragraph - -Screenshot 2023-08-08 at 17 55 46 - -##### Result Of Single Paragraph - -Screenshot 2023-08-08 at 17 56 47 - -### ColorText - -##### Example - -```csharp -var value = new -{ - Company_Name = new MiniWordColorText { Text = "MiniSofteware", FontColor = "#eb70AB", }, - Name = new[] { - new MiniWordColorText { Text = "Ja", HighlightColor = "#eb70AB" }, - new MiniWordColorText { Text = "ck", HighlightColor = "#a56abe" } - }, - CreateDate = new MiniWordColorText - { - Text = new DateTime(2021, 01, 01).ToString(), - HighlightColor = "#eb70AB", - FontColor = "#ffffff", - }, - VIP = true, - Points = 123, - APP = "Demo APP", -}; -MiniWord.SaveAsByTemplate(path, templatePath, value); -``` - - -## Other - -### POCO or dynamic parameter - -v0.5.0 support POCO or dynamic parameter - -```csharp -var value = new { title = "Hello MiniWord" }; -MiniWord.SaveAsByTemplate(outputPath, templatePath, value); -``` - -### FontColor and HighlightColor -```csharp -var value = new -{ - Company_Name = new MiniWordColorText { Text = "MiniSofteware", FontColor = "#eb70AB" }, - Name = new MiniWordColorText { Text = "Jack", HighlightColor = "#eb70AB" }, - CreateDate = new MiniWordColorText { Text = new DateTime(2021, 01, 01).ToString(), HighlightColor = "#eb70AB", FontColor = "#ffffff" }, - VIP = true, - Points = 123, - APP = "Demo APP", -}; -``` - -### HyperLink - -If value type is `MiniWordHyperLink` system will replace template string by hyperlink. - -* Url: HyperLink URI target path -* Text:Description - -```csharp -var value = new -{ - ["Name"] = new MiniWordHyperLink(){ - Url = "https://google.com", - Text = "Test Link!!" - }, - ["Company_Name"] = "MiniSofteware", - ["CreateDate"] = new DateTime(2021, 01, 01), - ["VIP"] = true, - ["Points"] = 123, - ["APP"] = "Demo APP", -}; -MiniWord.SaveAsByTemplate(path, templatePath, value); -``` - - - -## Examples - - - -#### ASP.NET Core 3.1 API Export - -```cs -using Microsoft.AspNetCore.Builder; -using Microsoft.AspNetCore.Hosting; -using Microsoft.AspNetCore.Mvc; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Hosting; -using System; -using System.Collections.Generic; -using System.IO; -using System.Net; -using MiniSoftware; - -public class Program -{ - public static void Main(string[] args) => CreateHostBuilder(args).Build().Run(); - - public static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args).ConfigureWebHostDefaults(webBuilder => webBuilder.UseStartup()); -} - -public class Startup -{ - public void ConfigureServices(IServiceCollection services) => services.AddMvc(); - public void Configure(IApplicationBuilder app, IWebHostEnvironment env) - { - app.UseStaticFiles(); - app.UseRouting(); - app.UseEndpoints(endpoints => - { - endpoints.MapControllerRoute( - name: "default", - pattern: "{controller=api}/{action=Index}/{id?}"); - }); - } -} - -public class ApiController : Controller -{ - public IActionResult Index() - { - return new ContentResult - { - ContentType = "text/html", - StatusCode = (int)HttpStatusCode.OK, - Content = @" -DownloadWordFromTemplatePath
-DownloadWordFromTemplateBytes
-" - }; - } - - static Dictionary defaultValue = new Dictionary() - { - ["title"] = "FooCompany", - ["managers"] = new List> { - new Dictionary{{"name","Jack"},{ "department", "HR" } }, - new Dictionary {{ "name", "Loan"},{ "department", "IT" } } - }, - ["employees"] = new List> { - new Dictionary{{ "name", "Wade" },{ "department", "HR" } }, - new Dictionary {{ "name", "Felix" },{ "department", "HR" } }, - new Dictionary{{ "name", "Eric" },{ "department", "IT" } }, - new Dictionary {{ "name", "Keaton" },{ "department", "IT" } } - } - }; - - public IActionResult DownloadWordFromTemplatePath() - { - string templatePath = "TestTemplateComplex.docx"; - - Dictionary value = defaultValue; - - MemoryStream memoryStream = new MemoryStream(); - MiniWord.SaveAsByTemplate(memoryStream, templatePath, value); - memoryStream.Seek(0, SeekOrigin.Begin); - return new FileStreamResult(memoryStream, "application/vnd.openxmlformats-officedocument.wordprocessingml.document") - { - FileDownloadName = "demo.docx" - }; - } - - private static Dictionary TemplateBytesCache = new Dictionary(); - - static ApiController() - { - string templatePath = "TestTemplateComplex.docx"; - byte[] bytes = System.IO.File.ReadAllBytes(templatePath); - TemplateBytesCache.Add(templatePath, bytes); - } - - public IActionResult DownloadWordFromTemplateBytes() - { - byte[] bytes = TemplateBytesCache["TestTemplateComplex.docx"]; - - Dictionary value = defaultValue; - - MemoryStream memoryStream = new MemoryStream(); - MiniWord.SaveAsByTemplate(memoryStream, bytes, value); - memoryStream.Seek(0, SeekOrigin.Begin); - return new FileStreamResult(memoryStream, "application/vnd.openxmlformats-officedocument.wordprocessingml.document") - { - FileDownloadName = "demo.docx" - }; - } -} -``` - - - - - - -## Support : [Donate Link](https://miniexcel.github.io/) diff --git a/README.zh-CN.md b/README.zh-CN.md deleted file mode 100644 index 5d0e1a28add62d5e56c9cfca1b00a84dd0e4d8bb..0000000000000000000000000000000000000000 --- a/README.zh-CN.md +++ /dev/null @@ -1,525 +0,0 @@ -
-

NuGet -GitHub stars -version -Ask DeepWiki -

-
- ---- - - - ---- - -
- 您的 Star赞助 可以让 MiniWord 走更远 -
- ---- - -## QQ群(1群) : [813100564](https://qm.qq.com/cgi-bin/qm/qr?k=3OkxuL14sXhJsUimWK8wx_Hf28Wl49QE&jump_from=webapi) / QQ群(2群) : [579033769](https://jq.qq.com/?_wv=1027&k=UxTdB8pR) - ----- - -## 介绍 - -MiniWord .NET Word模板引擎,藉由Word模板和数据简单、快速生成文件。 - -![image](https://user-images.githubusercontent.com/12729184/190835307-6cd87982-b5f3-4a79-9682-bdd1cc02a4ea.png) - - - -## Getting Started - -### 安装 - -- nuget link : https://www.nuget.org/packages/MiniWord - -### 快速入门 - -模板遵循“所见即所得”的设计,模板和标签的样式会被完全保留 - -```csharp -var value = new Dictionary(){["title"] = "Hello MiniWord"}; -MiniSoftware.MiniWord.SaveAsByTemplate(outputPath, templatePath, value); -``` - -![image](https://user-images.githubusercontent.com/12729184/190875707-6c5639ab-9518-4dc1-85d8-81e20af465e8.png) - -### 输入、输出 - -- 输入系统支持模版路径或是Byte[] -- 输出支持文件路径、Byte[]、Stream - -```csharp -SaveAsByTemplate(string path, string templatePath, Dictionary value) -SaveAsByTemplate(string path, byte[] templateBytes, Dictionary value) -SaveAsByTemplate(this Stream stream, string templatePath, Dictionary value) -SaveAsByTemplate(this Stream stream, byte[] templateBytes, Dictionary value) -``` - - - -## 标签 - -MiniWord 使用类似 Vue, React 的模版字串 `{{tag}}`,只需要确保 tag 与 value 参数的 key 一样`(大小写敏感)`,系统会自动替换字串。 - -### 文本 - -```csharp -{{tag}} -``` - - - -##### 代码例子 - -```csharp -var value = new Dictionary() -{ - ["Name"] = "Jack", - ["Department"] = "IT Department", - ["Purpose"] = "Shanghai site needs a new system to control HR system.", - ["StartDate"] = DateTime.Parse("2022-09-07 08:30:00"), - ["EndDate"] = DateTime.Parse("2022-09-15 15:30:00"), - ["Approved"] = true, - ["Total_Amount"] = 123456, -}; -MiniWord.SaveAsByTemplate(path, templatePath, value); -``` - -##### 模版 - -![image](https://user-images.githubusercontent.com/12729184/190834360-39b4b799-d523-4b7e-9331-047a61fd5eb9.png) - -##### 导出 - -![image](https://user-images.githubusercontent.com/12729184/190834455-ba065211-0f9d-41d1-9b7a-5d9e96ac2eff.png) - -### 图片 - -标签值为 `MiniWordPicture` 类别 - -##### 代码例子 - -```csharp -var value = new Dictionary() -{ - ["Logo"] = new MiniWordPicture() { Path= PathHelper.GetFile("DemoLogo.png"), Width= 180, Height= 180 } -}; -MiniWord.SaveAsByTemplate(path, templatePath, value); -``` - - - -##### 模版 - -![image](https://user-images.githubusercontent.com/12729184/190647953-6f9da393-e666-4658-a56d-b3a7f13c0ea1.png) - -##### 导出 - -![image](https://user-images.githubusercontent.com/12729184/190648179-30258d82-723d-4266-b711-43f132d1842d.png) - -### 列表 - -标签值为 `string[]` 或是 `IList`类别 - -##### 代码例子 - -```csharp -var value = new Dictionary() -{ - ["managers"] = new[] { "Jack" ,"Alan"}, - ["employees"] = new[] { "Mike" ,"Henry"}, -}; -MiniWord.SaveAsByTemplate(path, templatePath, value); -``` - -##### 模版 - -![image](https://user-images.githubusercontent.com/12729184/190645513-230c54f3-d38f-47af-b844-0c8c1eff2f52.png) - -##### 导出 - -![image](https://user-images.githubusercontent.com/12729184/190645704-1f6405e9-71e3-45b9-aa99-2ba52e5e1519.png) - -### 表格 - -标签值为 `IEmerable>`类别 - -##### 代码例子 - -```csharp -var value = new Dictionary() -{ - ["TripHs"] = new List> - { - new Dictionary - { - { "sDate",DateTime.Parse("2022-09-08 08:30:00")}, - { "eDate",DateTime.Parse("2022-09-08 15:00:00")}, - { "How","Discussion requirement part1"}, - { "Photo",new MiniWordPicture() { Path = PathHelper.GetFile("DemoExpenseMeeting02.png"), Width = 160, Height = 90 }}, - }, - new Dictionary - { - { "sDate",DateTime.Parse("2022-09-09 08:30:00")}, - { "eDate",DateTime.Parse("2022-09-09 17:00:00")}, - { "How","Discussion requirement part2 and development"}, - { "Photo",new MiniWordPicture() { Path = PathHelper.GetFile("DemoExpenseMeeting01.png"), Width = 160, Height = 90 }}, - }, - } -}; -MiniWord.SaveAsByTemplate(path, templatePath, value); -``` - -##### 模版 - -![image](https://user-images.githubusercontent.com/12729184/190843632-05bb6459-f1c1-4bdc-a79b-54889afdfeea.png) - - -##### 导出 - -![image](https://user-images.githubusercontent.com/12729184/190843663-c00baf16-21f2-4579-9d08-996a2c8c549b.png) - -### 二级列表 - -Tag 是 `IEnumerable` 类别. 使用方式`{{foreach` 和 `endforeach}}`. - -##### Example - -```csharp -var value = new Dictionary() -{ - ["TripHs"] = new List> - { - new Dictionary - { - { "sDate", DateTime.Parse("2022-09-08 08:30:00") }, - { "eDate", DateTime.Parse("2022-09-08 15:00:00") }, - { "How", "Discussion requirement part1" }, - { - "Details", new List() - { - new MiniWordForeach() - { - Value = new Dictionary() - { - {"Text", "Air"}, - {"Value", "Airplane"} - }, - Separator = " | " - }, - new MiniWordForeach() - { - Value = new Dictionary() - { - {"Text", "Parking"}, - {"Value", "Car"} - }, - Separator = " / " - } - } - } - } - } -}; -MiniWord.SaveAsByTemplate(path, templatePath, value); -``` - -##### Template - -![before_foreach](https://user-images.githubusercontent.com/38832863/220123955-063c9345-3998-4fd7-982c-8d1e3b48bbf8.PNG) - -##### Result - -![after_foreach](https://user-images.githubusercontent.com/38832863/220123960-913a7140-2fa2-415e-bb3e-456e04167382.PNG) - -### 条件判断 - - `@if` 和 `@endif` tags . - -##### Example - -```csharp -var value = new Dictionary() -{ - ["Name"] = new List(){ - new MiniWordHyperLink(){ - Url = "https://google.com", - Text = "測試連結22!!" - }, - new MiniWordHyperLink(){ - Url = "https://google1.com", - Text = "測試連結11!!" - } - }, - ["Company_Name"] = "MiniSofteware", - ["CreateDate"] = new DateTime(2021, 01, 01), - ["VIP"] = true, - ["Points"] = 123, - ["APP"] = "Demo APP", -}; -MiniWord.SaveAsByTemplate(path, templatePath, value); -``` - -##### Template - -![before_if](https://user-images.githubusercontent.com/38832863/220125429-7dd6ce94-35c6-478e-8903-064f9cf9361a.PNG) - -##### Result - -![after_if](https://user-images.githubusercontent.com/38832863/220125435-72ea24b4-2412-45de-961a-ad4b2134417b.PNG) - -### 循环 - - `@foreach` 和 `@endforeach` tags . - -##### Example - -```csharp -var value = new -{ - LoopData = new List() - { - new { - Type="类型A", - Items = new List() {new {Name = "A-1"}, new {Name = "A-2"},} - }, - new - { - Type="类型B", - Items = new List() {new {Name = "B-1"}, new {Name = "B-2"}, new {Name = "B-3"},} - }, - } -}; -MiniWord.SaveAsByTemplate(path, templatePath, value); -``` - -##### Template - -![1](https://github.com/user-attachments/assets/5d32241d-3977-46e7-b3de-cae130e5a653) - -##### Result - -![2](https://github.com/user-attachments/assets/69daa15e-4864-483e-b132-d8e867b6d1d1) - -### 多彩字体 - -##### 代码例子 - -```csharp -var value = new -{ - Company_Name = new MiniWordColorText { Text = "MiniSofteware", FontColor = "#eb70AB", }, - Name = new[] { - new MiniWordColorText { Text = "Ja", HighlightColor = "#eb70AB" }, - new MiniWordColorText { Text = "ck", HighlightColor = "#a56abe" } - }, - CreateDate = new MiniWordColorText - { - Text = new DateTime(2021, 01, 01).ToString(), - HighlightColor = "#eb70AB", - FontColor = "#ffffff", - }, - VIP = true, - Points = 123, - APP = "Demo APP", -}; -MiniWord.SaveAsByTemplate(path, templatePath, value); -``` - - - - - -## 其他 - -### POCO or dynamic 参数 - -v0.5.0 支持 POCO 或 dynamic parameter - -```csharp -var value = new { title = "Hello MiniWord" }; -MiniWord.SaveAsByTemplate(outputPath, templatePath, value); -``` - -### 字体FontColor和HighlightColor -```csharp -var value = new -{ - Company_Name = new MiniWordColorText { Text = "MiniSofteware", FontColor = "#eb70AB" }, - Name = new MiniWordColorText { Text = "Jack", HighlightColor = "#eb70AB" }, - CreateDate = new MiniWordColorText { Text = new DateTime(2021, 01, 01).ToString(), HighlightColor = "#eb70AB", FontColor = "#ffffff" }, - VIP = true, - Points = 123, - APP = "Demo APP", -}; -``` - -### HyperLink - -我们可以尝试使用 `MiniWodrHyperLink` 类,用模板测试替换为超链接。 - -`MiniWordHyperLink` 提供了两个主要参数。 - -* Url: HyperLink URI 目标路径 -* 文字:超链接文字 - -```csharp -var value = new -{ - ["Name"] = new MiniWordHyperLink(){ - Url = "https://google.com", - Text = "測試連結!!" - }, - ["Company_Name"] = "MiniSofteware", - ["CreateDate"] = new DateTime(2021, 01, 01), - ["VIP"] = true, - ["Points"] = 123, - ["APP"] = "Demo APP", -}; -MiniWord.SaveAsByTemplate(path, templatePath, value); -``` - -### 浮动图像 - -可以通过MiniWordPicture扩展参数配置图片悬浮环绕在文字上或文字下 -`MiniWordPicture` 扩展参数。 -* WrappingType: MiniWordPictureWrappingType.Anchor 浮动图像 -* HorizontalPositionOffset: 设置图片相对于锚点的水平偏移量(以像素为单位) -* VerticalPositionOffset:设置图片相对于锚点的垂直偏移量(以像素为单位) -* BehindDoc: 控制图片是否显示在文档文字的后方 -* AllowOverlap: 控制图片是否允许与其他图片或对象重叠 - - -## 例子 - - - -#### ASP.NET Core 3.1 API Export - -```cs -using Microsoft.AspNetCore.Builder; -using Microsoft.AspNetCore.Hosting; -using Microsoft.AspNetCore.Mvc; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Hosting; -using System; -using System.Collections.Generic; -using System.IO; -using System.Net; -using MiniSoftware; - -public class Program -{ - public static void Main(string[] args) => CreateHostBuilder(args).Build().Run(); - - public static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args).ConfigureWebHostDefaults(webBuilder => webBuilder.UseStartup()); -} - -public class Startup -{ - public void ConfigureServices(IServiceCollection services) => services.AddMvc(); - public void Configure(IApplicationBuilder app, IWebHostEnvironment env) - { - app.UseStaticFiles(); - app.UseRouting(); - app.UseEndpoints(endpoints => - { - endpoints.MapControllerRoute( - name: "default", - pattern: "{controller=api}/{action=Index}/{id?}"); - }); - } -} - -public class ApiController : Controller -{ - public IActionResult Index() - { - return new ContentResult - { - ContentType = "text/html", - StatusCode = (int)HttpStatusCode.OK, - Content = @" -DownloadWordFromTemplatePath
-DownloadWordFromTemplateBytes
-" - }; - } - - static Dictionary defaultValue = new Dictionary() - { - ["title"] = "FooCompany", - ["managers"] = new List> { - new Dictionary{{"name","Jack"},{ "department", "HR" } }, - new Dictionary {{ "name", "Loan"},{ "department", "IT" } } - }, - ["employees"] = new List> { - new Dictionary{{ "name", "Wade" },{ "department", "HR" } }, - new Dictionary {{ "name", "Felix" },{ "department", "HR" } }, - new Dictionary{{ "name", "Eric" },{ "department", "IT" } }, - new Dictionary {{ "name", "Keaton" },{ "department", "IT" } } - } - }; - - public IActionResult DownloadWordFromTemplatePath() - { - string templatePath = "TestTemplateComplex.docx"; - - Dictionary value = defaultValue; - - MemoryStream memoryStream = new MemoryStream(); - MiniWord.SaveAsByTemplate(memoryStream, templatePath, value); - memoryStream.Seek(0, SeekOrigin.Begin); - return new FileStreamResult(memoryStream, "application/vnd.openxmlformats-officedocument.wordprocessingml.document") - { - FileDownloadName = "demo.docx" - }; - } - - private static Dictionary TemplateBytesCache = new Dictionary(); - - static ApiController() - { - string templatePath = "TestTemplateComplex.docx"; - byte[] bytes = System.IO.File.ReadAllBytes(templatePath); - TemplateBytesCache.Add(templatePath, bytes); - } - - public IActionResult DownloadWordFromTemplateBytes() - { - byte[] bytes = TemplateBytesCache["TestTemplateComplex.docx"]; - - Dictionary value = defaultValue; - - MemoryStream memoryStream = new MemoryStream(); - MiniWord.SaveAsByTemplate(memoryStream, bytes, value); - memoryStream.Seek(0, SeekOrigin.Begin); - return new FileStreamResult(memoryStream, "application/vnd.openxmlformats-officedocument.wordprocessingml.document") - { - FileDownloadName = "demo.docx" - }; - } -} -``` - - - - - - - -## 支持 : [Donate Link](https://miniexcel.github.io/) - -wechat - - - alipay - - - diff --git a/README.zh-Hant.md b/README.zh-Hant.md deleted file mode 100644 index ce3cab161536841263f8ca12c75d26b6f538f9a3..0000000000000000000000000000000000000000 --- a/README.zh-Hant.md +++ /dev/null @@ -1,477 +0,0 @@ -
-

NuGet -GitHub stars -version -Ask DeepWiki -

-
- - ---- - - - ---- - -
- 您的 Star贊助 可以讓 MiniWord 走更遠 -
- ---- - - -## 介紹 - -MiniWord .NET Word模板引擎,藉由Word模板和數據簡單、快速生成文件。 - -![image](https://user-images.githubusercontent.com/12729184/190835307-6cd87982-b5f3-4a79-9682-bdd1cc02a4ea.png) - - - -## Getting Started - -### 安裝 - -- nuget link : https://www.nuget.org/packages/MiniWord - -### 快速入門 - -模板遵循“所見即所得”的設計,模板和標籤的樣式會被完全保留 - -```csharp -var value = new Dictionary(){["title"] = "Hello MiniWord"}; -MiniSoftware.MiniWord.SaveAsByTemplate(outputPath, templatePath, value); -``` - -![image](https://user-images.githubusercontent.com/12729184/190875707-6c5639ab-9518-4dc1-85d8-81e20af465e8.png) - -### 輸入、輸出 - -- 輸入系統支持模版路徑或是Byte[] -- 輸出支持文件路徑、Byte[]、Stream - -```csharp -SaveAsByTemplate(string path, string templatePath, Dictionary value) -SaveAsByTemplate(string path, byte[] templateBytes, Dictionary value) -SaveAsByTemplate(this Stream stream, string templatePath, Dictionary value) -SaveAsByTemplate(this Stream stream, byte[] templateBytes, Dictionary value) -``` - - - -## 標籤 - -MiniWord 使用類似 Vue, React 的模版字串 `{{tag}}`,只需要確保 tag 與 value 參數的 key 一樣`(大小寫敏感)`,系統會自動替換字串。 - -### 文本 - -```csharp -{{tag}} -``` - -##### 代碼例子 - -```csharp -var value = new Dictionary() -{ - ["Name"] = "Jack", - ["Department"] = "IT Department", - ["Purpose"] = "Shanghai site needs a new system to control HR system.", - ["StartDate"] = DateTime.Parse("2022-09-07 08:30:00"), - ["EndDate"] = DateTime.Parse("2022-09-15 15:30:00"), - ["Approved"] = true, - ["Total_Amount"] = 123456, -}; -MiniWord.SaveAsByTemplate(path, templatePath, value); -``` - -##### 模版 - -![image](https://user-images.githubusercontent.com/12729184/190834360-39b4b799-d523-4b7e-9331-047a61fd5eb9.png) - -##### 導出 - -![image](https://user-images.githubusercontent.com/12729184/190834455-ba065211-0f9d-41d1-9b7a-5d9e96ac2eff.png) - - - -### 圖片 - -標籤值為 `MiniWordPicture` 類別 - -##### 代碼例子 - -```csharp -var value = new Dictionary() -{ - ["Logo"] = new MiniWordPicture() { Path= PathHelper.GetFile("DemoLogo.png"), Width= 180, Height= 180 } -}; -MiniWord.SaveAsByTemplate(path, templatePath, value); -``` - - - -##### 模版 - -![image](https://user-images.githubusercontent.com/12729184/190647953-6f9da393-e666-4658-a56d-b3a7f13c0ea1.png) - -##### 導出 - -![image](https://user-images.githubusercontent.com/12729184/190648179-30258d82-723d-4266-b711-43f132d1842d.png) - -### 列表 - -標籤值為 `string[]` 或是 `IList`類別 - -##### 代碼例子 - -```csharp -var value = new Dictionary() -{ - ["managers"] = new[] { "Jack" ,"Alan"}, - ["employees"] = new[] { "Mike" ,"Henry"}, -}; -MiniWord.SaveAsByTemplate(path, templatePath, value); -``` - -##### 模版 - -![image](https://user-images.githubusercontent.com/12729184/190645513-230c54f3-d38f-47af-b844-0c8c1eff2f52.png) - -##### 導出 - -![image](https://user-images.githubusercontent.com/12729184/190645704-1f6405e9-71e3-45b9-aa99-2ba52e5e1519.png) - -### 表格 - -標籤值為 `IEmerable>`類別 - -##### 代碼例子 - -```csharp -var value = new Dictionary() -{ - ["TripHs"] = new List> - { - new Dictionary - { - { "sDate",DateTime.Parse("2022-09-08 08:30:00")}, - { "eDate",DateTime.Parse("2022-09-08 15:00:00")}, - { "How","Discussion requirement part1"}, - { "Photo",new MiniWordPicture() { Path = PathHelper.GetFile("DemoExpenseMeeting02.png"), Width = 160, Height = 90 }}, - }, - new Dictionary - { - { "sDate",DateTime.Parse("2022-09-09 08:30:00")}, - { "eDate",DateTime.Parse("2022-09-09 17:00:00")}, - { "How","Discussion requirement part2 and development"}, - { "Photo",new MiniWordPicture() { Path = PathHelper.GetFile("DemoExpenseMeeting01.png"), Width = 160, Height = 90 }}, - }, - } -}; -MiniWord.SaveAsByTemplate(path, templatePath, value); -``` - -##### 模版 - -![image](https://user-images.githubusercontent.com/12729184/190843632-05bb6459-f1c1-4bdc-a79b-54889afdfeea.png) - - -##### 導出 - -![image](https://user-images.githubusercontent.com/12729184/190843663-c00baf16-21f2-4579-9d08-996a2c8c549b.png) - - - -### 二级列表 - -Tag 是 `IEnumerable` 类别. 使用方式`{{foreach` 和 `endforeach}}`. - -##### Example - -```csharp -var value = new Dictionary() -{ - ["TripHs"] = new List> - { - new Dictionary - { - { "sDate", DateTime.Parse("2022-09-08 08:30:00") }, - { "eDate", DateTime.Parse("2022-09-08 15:00:00") }, - { "How", "Discussion requirement part1" }, - { - "Details", new List() - { - new MiniWordForeach() - { - Value = new Dictionary() - { - {"Text", "Air"}, - {"Value", "Airplane"} - }, - Separator = " | " - }, - new MiniWordForeach() - { - Value = new Dictionary() - { - {"Text", "Parking"}, - {"Value", "Car"} - }, - Separator = " / " - } - } - } - } - } -}; -MiniWord.SaveAsByTemplate(path, templatePath, value); -``` - -##### Template - -![before_foreach](https://user-images.githubusercontent.com/38832863/220123955-063c9345-3998-4fd7-982c-8d1e3b48bbf8.PNG) - -##### Result - -![after_foreach](https://user-images.githubusercontent.com/38832863/220123960-913a7140-2fa2-415e-bb3e-456e04167382.PNG) - -### 条件判断 - - `@if` 和 `@endif` tags . - -##### Example - -```csharp -var value = new Dictionary() -{ - ["Name"] = new List(){ - new MiniWordHyperLink(){ - Url = "https://google.com", - Text = "測試連結22!!" - }, - new MiniWordHyperLink(){ - Url = "https://google1.com", - Text = "測試連結11!!" - } - }, - ["Company_Name"] = "MiniSofteware", - ["CreateDate"] = new DateTime(2021, 01, 01), - ["VIP"] = true, - ["Points"] = 123, - ["APP"] = "Demo APP", -}; -MiniWord.SaveAsByTemplate(path, templatePath, value); -``` - -##### Template - -![before_if](https://user-images.githubusercontent.com/38832863/220125429-7dd6ce94-35c6-478e-8903-064f9cf9361a.PNG) - -##### Result - -![after_if](https://user-images.githubusercontent.com/38832863/220125435-72ea24b4-2412-45de-961a-ad4b2134417b.PNG) - -### 多彩字體 - -##### 例子 - -```csharp -var value = new -{ - Company_Name = new MiniWordColorText { Text = "MiniSofteware", FontColor = "#eb70AB", }, - Name = new[] { - new MiniWordColorText { Text = "Ja", HighlightColor = "#eb70AB" }, - new MiniWordColorText { Text = "ck", HighlightColor = "#a56abe" } - }, - CreateDate = new MiniWordColorText - { - Text = new DateTime(2021, 01, 01).ToString(), - HighlightColor = "#eb70AB", - FontColor = "#ffffff", - }, - VIP = true, - Points = 123, - APP = "Demo APP", -}; -MiniWord.SaveAsByTemplate(path, templatePath, value); -``` - - - -## 其他 - -### POCO or dynamic 參數 - -v0.5.0 支持 POCO 或 dynamic parameter - -```csharp -var value = new { title = "Hello MiniWord" }; -MiniWord.SaveAsByTemplate(outputPath, templatePath, value); -``` - -### 字体FontColor和HighlightColor -```csharp -var value = new -{ - Company_Name = new MiniWordColorText { Text = "MiniSofteware", FontColor = "#eb70AB" }, - Name = new MiniWordColorText { Text = "Jack", HighlightColor = "#eb70AB" }, - CreateDate = new MiniWordColorText { Text = new DateTime(2021, 01, 01).ToString(), HighlightColor = "#eb70AB", FontColor = "#ffffff" }, - VIP = true, - Points = 123, - APP = "Demo APP", -}; -``` - -### HyperLink - -我們可以嘗試使用 `MiniWordHyperLink` 類,它將模板文本替換為超鏈接。 - -`MiniWordHyperLink` 提供了兩個主要參數。 - -* Url: HyperLink URI 目標路徑 -* 文字:超鏈接文字 - -```csharp -var value = new -{ - ["Name"] = new MiniWordHyperLink(){ - Url = "https://google.com", - Text = "測試連結!!" - }, - ["Company_Name"] = "MiniSofteware", - ["CreateDate"] = new DateTime(2021, 01, 01), - ["VIP"] = true, - ["Points"] = 123, - ["APP"] = "Demo APP", -}; -MiniWord.SaveAsByTemplate(path, templatePath, value); -``` - -## 例子 - - - -#### ASP.NET Core 3.1 API Export - -``` -using Microsoft.AspNetCore.Builder; -using Microsoft.AspNetCore.Hosting; -using Microsoft.AspNetCore.Mvc; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Hosting; -using System; -using System.Collections.Generic; -using System.IO; -using System.Net; -using MiniSoftware; - -public class Program -{ - public static void Main(string[] args) => CreateHostBuilder(args).Build().Run(); - - public static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args).ConfigureWebHostDefaults(webBuilder => webBuilder.UseStartup()); -} - -public class Startup -{ - public void ConfigureServices(IServiceCollection services) => services.AddMvc(); - public void Configure(IApplicationBuilder app, IWebHostEnvironment env) - { - app.UseStaticFiles(); - app.UseRouting(); - app.UseEndpoints(endpoints => - { - endpoints.MapControllerRoute( - name: "default", - pattern: "{controller=api}/{action=Index}/{id?}"); - }); - } -} - -public class ApiController : Controller -{ - public IActionResult Index() - { - return new ContentResult - { - ContentType = "text/html", - StatusCode = (int)HttpStatusCode.OK, - Content = @" -DownloadWordFromTemplatePath
-DownloadWordFromTemplateBytes
-" - }; - } - - static Dictionary defaultValue = new Dictionary() - { - ["title"] = "FooCompany", - ["managers"] = new List> { - new Dictionary{{"name","Jack"},{ "department", "HR" } }, - new Dictionary {{ "name", "Loan"},{ "department", "IT" } } - }, - ["employees"] = new List> { - new Dictionary{{ "name", "Wade" },{ "department", "HR" } }, - new Dictionary {{ "name", "Felix" },{ "department", "HR" } }, - new Dictionary{{ "name", "Eric" },{ "department", "IT" } }, - new Dictionary {{ "name", "Keaton" },{ "department", "IT" } } - } - }; - - public IActionResult DownloadWordFromTemplatePath() - { - string templatePath = "TestTemplateComplex.docx"; - - Dictionary value = defaultValue; - - MemoryStream memoryStream = new MemoryStream(); - MiniWord.SaveAsByTemplate(memoryStream, templatePath, value); - memoryStream.Seek(0, SeekOrigin.Begin); - return new FileStreamResult(memoryStream, "application/vnd.openxmlformats-officedocument.wordprocessingml.document") - { - FileDownloadName = "demo.docx" - }; - } - - private static Dictionary TemplateBytesCache = new Dictionary(); - - static ApiController() - { - string templatePath = "TestTemplateComplex.docx"; - byte[] bytes = System.IO.File.ReadAllBytes(templatePath); - TemplateBytesCache.Add(templatePath, bytes); - } - - public IActionResult DownloadWordFromTemplateBytes() - { - byte[] bytes = TemplateBytesCache["TestTemplateComplex.docx"]; - - Dictionary value = defaultValue; - - MemoryStream memoryStream = new MemoryStream(); - MiniWord.SaveAsByTemplate(memoryStream, bytes, value); - memoryStream.Seek(0, SeekOrigin.Begin); - return new FileStreamResult(memoryStream, "application/vnd.openxmlformats-officedocument.wordprocessingml.document") - { - FileDownloadName = "demo.docx" - }; - } -} -``` - - - - - -## 支持 : [Donate Link](https://miniexcel.github.io/) - -wechat - - - alipay - - - diff --git a/package.bat b/package.bat new file mode 100644 index 0000000000000000000000000000000000000000..32fe19ef5982529367b79a8193b2675bca47b8d0 --- /dev/null +++ b/package.bat @@ -0,0 +1,3 @@ +echo off +dotnet pack -c Release +pause \ No newline at end of file diff --git a/src/MiniWord/Extensions/NumberExtension.cs b/src/MiniWord/Extensions/NumberExtension.cs new file mode 100644 index 0000000000000000000000000000000000000000..40828bc532be3ae11aa2166efcb9aa3117079501 --- /dev/null +++ b/src/MiniWord/Extensions/NumberExtension.cs @@ -0,0 +1,24 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace MiniSoftware.Extensions +{ + public static class NumberExtension + { + /// + /// int值 + /// + /// + /// + public static int? IntValue(this long longVal) + { + if(int.TryParse(longVal.ToString(), out var val)) + return val; + return null; + } + + } +} diff --git a/src/MiniWord/Extensions/StringExtension.cs b/src/MiniWord/Extensions/StringExtension.cs index 0ece7cb91ffc7709e9784535fda26c406c94acde..3cdde50a95e87263bce96a5f459ec34b8e942d08 100644 --- a/src/MiniWord/Extensions/StringExtension.cs +++ b/src/MiniWord/Extensions/StringExtension.cs @@ -1,4 +1,6 @@ -namespace MiniSoftware.Extensions +using System.Linq; + +namespace MiniSoftware.Extensions { public static class StringExtension { @@ -6,5 +8,11 @@ public static string FirstCharacterToLower(this string str) { return string.IsNullOrWhiteSpace(str) ? str : char.ToLowerInvariant(str[0]) + str.Substring(1); } + + public static string[] SplitRemoveEmptyEntries(this string str, char split) + { + return str.Split(split).Where(x => !string.IsNullOrEmpty(x)).ToArray(); + } + } } \ No newline at end of file diff --git a/src/MiniWord/MiniWord.Implment.cs b/src/MiniWord/MiniWord.Implment.cs index 6e48862a5c3f2c22a4018e666e9914c6bfc7100d..4a3b356ee9d0078addb574a245958c7000946a1a 100644 --- a/src/MiniWord/MiniWord.Implment.cs +++ b/src/MiniWord/MiniWord.Implment.cs @@ -1,10 +1,11 @@ -namespace MiniSoftware +namespace MiniSoftware { using DocumentFormat.OpenXml; + using DocumentFormat.OpenXml.Drawing.Charts; using DocumentFormat.OpenXml.Packaging; using DocumentFormat.OpenXml.Wordprocessing; using Extensions; - using Utility; + using HtmlToOpenXml; using System; using System.Collections; using System.Collections.Generic; @@ -12,20 +13,20 @@ namespace MiniSoftware using System.Linq; using System.Text; using System.Text.RegularExpressions; + using System.Threading; + using System.Threading.Tasks; + using System.Xml; + using System.Xml.Linq; + using Utility; using A = DocumentFormat.OpenXml.Drawing; using DW = DocumentFormat.OpenXml.Drawing.Wordprocessing; using PIC = DocumentFormat.OpenXml.Drawing.Pictures; - using System.Xml; - using System.Xml.Linq; - using DocumentFormat.OpenXml.Drawing.Charts; - using System.Threading.Tasks; - using System.Threading; public static partial class MiniWord { private static void SaveAsByTemplateImpl(Stream stream, byte[] template, Dictionary data) { - SaveAsByTemplateImplAsync(stream,template,data).GetAwaiter().GetResult(); + SaveAsByTemplateImplAsync(stream, template, data).GetAwaiter().GetResult(); } private static async Task SaveAsByTemplateImplAsync(Stream stream, byte[] template, Dictionary data, CancellationToken token = default(CancellationToken)) @@ -500,10 +501,10 @@ private static void ReplaceText(Paragraph p, WordprocessingDocument docx, Dictio if (!isFullMatch && tag.Value is List forTags) { if (forTags.Any(forTag => forTag.Value.Keys.Any(dictKey => - { - var innerTag = "{{" + tag.Key + "." + dictKey + "}}"; - return t.Text.Contains(innerTag); - }))) + { + var innerTag = "{{" + tag.Key + "." + dictKey + "}}"; + return t.Text.Contains(innerTag); + }))) { isFullMatch = true; } @@ -648,11 +649,21 @@ private static void ReplaceText(Paragraph p, WordprocessingDocument docx, Dictio { AddPicture(run, mainPart.GetIdOfPart(imagePart), pic); } - + } t.Remove(); } + else if (value is MiniWordHtml html) + { + AddHtmls(docx, run, new[] { html }); + t.Remove(); + } + else if (value is IEnumerable htmlList) + { + AddHtmls(docx, run, htmlList); + t.Remove(); + } else { var newText = value is DateTime @@ -1023,9 +1034,9 @@ private static void AddPicture(OpenXmlElement appendElement, string relationship new A.PresetGeometry( new A.AdjustValueList() ) - { Preset = A.ShapeTypeValues.Rectangle })) + { Preset = A.ShapeTypeValues.Rectangle })) ) - { Uri = "http://schemas.openxmlformats.org/drawingml/2006/picture" }) + { Uri = "http://schemas.openxmlformats.org/drawingml/2006/picture" }) ) { DistanceFromTop = (UInt32Value)0U, @@ -1043,22 +1054,30 @@ private static void AddPictureAnchor(OpenXmlElement appendElement, string relati DW.Anchor anchor3 = new DW.Anchor() { - DistanceFromTop = (UInt32Value)0U, DistanceFromBottom = (UInt32Value)0U, - DistanceFromLeft = (UInt32Value)114300U, DistanceFromRight = (UInt32Value)114300U, - SimplePos = false, RelativeHeight = (UInt32Value)0U, BehindDoc = pic.BehindDoc, Locked = false, - LayoutInCell = true, AllowOverlap = pic.AllowOverlap, EditId = "1EACBECC", AnchorId = "5AF073F3" + DistanceFromTop = (UInt32Value)0U, + DistanceFromBottom = (UInt32Value)0U, + DistanceFromLeft = (UInt32Value)114300U, + DistanceFromRight = (UInt32Value)114300U, + SimplePos = false, + RelativeHeight = (UInt32Value)0U, + BehindDoc = pic.BehindDoc, + Locked = false, + LayoutInCell = true, + AllowOverlap = pic.AllowOverlap, + EditId = "1EACBECC", + AnchorId = "5AF073F3" }; DW.SimplePosition simplePosition3 = new DW.SimplePosition() { X = 0L, Y = 0L }; DW.HorizontalPosition horizontalPosition3 = new DW.HorizontalPosition() - { RelativeFrom = DW.HorizontalRelativePositionValues.Column }; + { RelativeFrom = DW.HorizontalRelativePositionValues.Column }; DW.PositionOffset positionOffset5 = new DW.PositionOffset(); positionOffset5.Text = $"{pic.HorizontalPositionOffset * 9525}"; horizontalPosition3.Append(positionOffset5); DW.VerticalPosition verticalPosition3 = new DW.VerticalPosition() - { RelativeFrom = DW.VerticalRelativePositionValues.Paragraph }; + { RelativeFrom = DW.VerticalRelativePositionValues.Paragraph }; DW.PositionOffset positionOffset6 = new DW.PositionOffset(); positionOffset6.Text = $"{pic.VerticalPositionOffset * 9525}"; @@ -1067,12 +1086,12 @@ private static void AddPictureAnchor(OpenXmlElement appendElement, string relati DW.EffectExtent effectExtent13 = new DW.EffectExtent() - { LeftEdge = 0L, TopEdge = 0L, RightEdge = 0L, BottomEdge = 0L }; + { LeftEdge = 0L, TopEdge = 0L, RightEdge = 0L, BottomEdge = 0L }; DW.WrapNone wrapNone3 = new DW.WrapNone(); DW.DocProperties docProperties13 = new DW.DocProperties() - { Id = (UInt32Value)774829591U, Name = $"Picture {Guid.NewGuid().ToString()}" }; + { Id = (UInt32Value)774829591U, Name = $"Picture {Guid.NewGuid().ToString()}" }; DW.NonVisualGraphicFrameDrawingProperties nonVisualGraphicFrameDrawingProperties13 = new DW.NonVisualGraphicFrameDrawingProperties(); @@ -1087,14 +1106,14 @@ private static void AddPictureAnchor(OpenXmlElement appendElement, string relati graphic13.AddNamespaceDeclaration("a", "http://schemas.openxmlformats.org/drawingml/2006/main"); A.GraphicData graphicData13 = new A.GraphicData() - { Uri = "http://schemas.openxmlformats.org/drawingml/2006/picture" }; + { Uri = "http://schemas.openxmlformats.org/drawingml/2006/picture" }; PIC.Picture picture13 = new PIC.Picture(); picture13.AddNamespaceDeclaration("pic", "http://schemas.openxmlformats.org/drawingml/2006/picture"); PIC.NonVisualPictureProperties nonVisualPictureProperties13 = new PIC.NonVisualPictureProperties(); PIC.NonVisualDrawingProperties nonVisualDrawingProperties13 = new PIC.NonVisualDrawingProperties() - { Id = (UInt32Value)0U, Name = $"Image {Guid.NewGuid().ToString()}.{pic.Extension}" }; + { Id = (UInt32Value)0U, Name = $"Image {Guid.NewGuid().ToString()}.{pic.Extension}" }; PIC.NonVisualPictureDrawingProperties nonVisualPictureDrawingProperties13 = new PIC.NonVisualPictureDrawingProperties(); @@ -1104,7 +1123,7 @@ private static void AddPictureAnchor(OpenXmlElement appendElement, string relati PIC.BlipFill blipFill13 = new PIC.BlipFill(); A.Blip blip13 = new A.Blip() - { Embed = relationshipId, CompressionState = A.BlipCompressionValues.Print }; + { Embed = relationshipId, CompressionState = A.BlipCompressionValues.Print }; A.BlipExtensionList blipExtensionList11 = new A.BlipExtensionList(); A.BlipExtension blipExtension11 = new A.BlipExtension() { Uri = $"{{{Guid.NewGuid().ToString("n")}}}" }; @@ -1175,5 +1194,57 @@ private static byte[] GetBytes(string path) return ms.ToArray(); } } + + #region html支持 + + /// + /// 填充htmls + /// + /// + /// + private static void AddHtmls(WordprocessingDocument docx, Run run, IEnumerable miniWordHtmls) + { + //找到当前顶级段落(body)添加,html中的表格不能直接放在run或者段落里 + Paragraph topPara = FindTopPara(run); + if (topPara == null) return; + foreach (var miniWordHtml in miniWordHtmls) + { + try + { + //实例化转换对象 + HtmlConverter converter = new HtmlConverter(docx.MainDocumentPart); + //解析 + var paras = converter.Parse(miniWordHtml.HtmlText); + //倒排插入(因为都是插入到标记位置后面所以需要倒排) + for (var i = paras.Count - 1; i >= 0; i--) + { + var item = paras[i]; + topPara.Parent.InsertAfter(item, topPara); + } + } + catch (Exception) + { } + } + } + + /// + /// 找到当前顶级段落(body)添加 + /// + /// + /// + private static Paragraph FindTopPara(Run run) + { + for (var pnode = run.Parent; pnode != null; pnode = pnode.Parent) + { + if (pnode is Paragraph para && pnode.Parent != null && pnode.Parent is Body) + { + return para; + } + } + return null; + } + + #endregion + } } diff --git a/src/MiniWord/MiniWord.csproj b/src/MiniWord/MiniWord.csproj index 34c6deb83ef294cb93da467d89756024d8237415..64ff08d7eb193ffbb3dbb6b8c6d3161a319f81c8 100644 --- a/src/MiniWord/MiniWord.csproj +++ b/src/MiniWord/MiniWord.csproj @@ -1,26 +1,26 @@  - net45;netstandard2.0; + net462;netstandard2.0; 0.9.1 MiniWord - MiniWord + MiniWordWithHtml MiniWord word;template;micro-helper;mini;openxml;helper; .NET Word(docx) exporting template engine without COM+ and interop (support Linux and Mac) mini-software, Wei Lin, eynarhaji - MiniWord + MiniWordWithHtml mini-software, Wei Lin, 2022 onwards en https://raw.githubusercontent.com/mini-software/MiniWord/main/LICENSE MiniSoftware Apache-2.0 - https://github.com/mini-software/MiniWord - https://github.com/mini-software/MiniWord + https://gitee.com/tangdou89/MiniWord/tree/htmlToOpenxml/ + https://gitee.com/tangdou89/MiniWord/tree/htmlToOpenxml/ icon.png - Please Check [Release Notes](https://github.com/mini-software/MiniWord/tree/main/release-note) + Please Check [Release Notes](https://gitee.com/tangdou89/MiniWord/tree/htmlToOpenxml/) Github @@ -33,6 +33,10 @@ - + + true + + + diff --git a/src/MiniWord/MiniWordHtml.cs b/src/MiniWord/MiniWordHtml.cs new file mode 100644 index 0000000000000000000000000000000000000000..d0943cdb9da530fe01c3c4027f5d1c145fcd83ce --- /dev/null +++ b/src/MiniWord/MiniWordHtml.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace MiniSoftware +{ + public class MiniWordHtml + { + public string HtmlText { get; set; } + } +} diff --git a/src/MiniWord/Properties/PublishProfiles/FolderProfile.pubxml b/src/MiniWord/Properties/PublishProfiles/FolderProfile.pubxml new file mode 100644 index 0000000000000000000000000000000000000000..10dbb4ab9196bd822bd3d50f44e22f33d2a7fd4a --- /dev/null +++ b/src/MiniWord/Properties/PublishProfiles/FolderProfile.pubxml @@ -0,0 +1,12 @@ + + + + + Release + Any CPU + bin\Release\net462\publish\ + FileSystem + <_TargetId>Folder + netstandard2.0 + + \ No newline at end of file diff --git a/tests/MiniWordTests/HtmlTest.cs b/tests/MiniWordTests/HtmlTest.cs new file mode 100644 index 0000000000000000000000000000000000000000..216062ee2baff56f50386ad93e480db5d4b5941b --- /dev/null +++ b/tests/MiniWordTests/HtmlTest.cs @@ -0,0 +1,279 @@ +using MiniSoftware; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Xunit; + +namespace MiniWordTests +{ + public class HtmlTest + { + [Fact] + public async Task Test() + { + //定义导出文件名称 + string fileName = $"{DateTime.Now.ToString("yyyyMMddHHmmss")}.docx"; + //构建测试数据 + var data = BuildTestData(); + var outFile = new FileInfo($"TestData/out/{fileName}"); + if (outFile?.Directory?.Exists != true) + outFile?.Directory?.Create(); + //导出文件 + await MiniWord.SaveAsByTemplateAsync(outFile.FullName, "TestData/testTmplate.docx", data); + Console.WriteLine($"文件生成成功:{outFile.FullName}"); + //using var stream = new MemoryStream(); + //await MiniWord.SaveAsByTemplateAsync(stream, data.template, data.data); + //var bytes = stream.ToArray(); + //return File(bytes, FileContentType.DOCX, fileName); + } + + /// + /// 构建测试数据 + /// + /// + private object BuildTestData() + { + var data = new TestData + { + title = "你好 MiniWord", + username = "林婉晴", + userage = 22, + userdept = "软件开发部", + userremark = "她没有备注", + userroles = new[] { "开发", "项目经理" }, + userimgPath = @"TestData\test.png", + HtmlContents = new MiniWordHtml + { + HtmlText = File.ReadAllText(@"TestData\sample.html") + }, + dept = new TestDataDept + { + code = "D001", + name = "软件开发部", + manager = "林婉晴" + }, + cl = new List + { + new TestDataCl + { + start="2025-01-02", + end="2025-01-03", + address="成都", + sx="讨论需求", + }, + new TestDataCl + { + start="2025-01-02", + end="2025-01-03", + address="北京", + sx="考察项目", + }, + new TestDataCl + { + start="2025-01-02", + end="2025-01-03", + address="南京", + sx="拜访客户", + }, + new TestDataCl + { + start="2025-01-02", + end="2025-01-03", + address="广东", + sx="看海", + }, + new TestDataCl + { + start="2025-01-02", + end="2025-01-03", + address="山东", + sx="旅游", + } + }, + gzjls = new List + { + new TestDataGzjl + { + name="星瀚未来科技有限公司", + start="2018年3月", + end="2020年6月", + xms=new []{ + "AI语音助手“星语”开发:主导跨团队协作,完成从需求分析到上线的全流程,用户量突破500万", + "为商业卫星公司定制数据分析工具,客户复购率提升30%。" + } + }, + new TestDataGzjl + { + name="锐驰国际物流供应链有限公司", + start="2020年7月", + end="2021年12月", + xms=new []{ + "东南亚跨境物流系统优化:设计智能路由算法,运输时效缩短20%,成本降低15%。", + "冷链仓储自动化试点:引入AGV机器人,实现仓储效率提升40%。" + } + }, + new TestDataGzjl + { + name="绿野生态农业集团", + start="2022年1月", + end="2022年9月", + xms=new []{ + "有机蔬菜订阅制改革:因传统渠道阻力未能落地,仅完成试点用户调研。" + } + }, + } + + }; + return data; + } + + /// + /// 构建测试数据 + /// + /// + private object BuildTestDict() + { + Dictionary data = new Dictionary + { + { "title","你好 MiniWord"}, + { "username","林婉晴" }, + { "userage","22" }, + { "userdept","软件开发部" }, + { "userremark","她没有备注" }, + { "userroles",new[]{"开发","项目经理"} }, + { "userimg",new MiniWordPicture( + @"TestData\test.png",180,180 + ) }, + { "cl",new List> + { + new Dictionary + { + { "start","2025-01-02" }, + { "end","2025-01-03" }, + { "address","成都" }, + { "sx","讨论需求" }, + }, + new Dictionary + { + { "start","2025-01-02" }, + { "end","2025-01-03" }, + { "address","北京" }, + { "sx","考察项目" }, + }, + new Dictionary + { + { "start","2025-01-02" }, + { "end","2025-01-03" }, + { "address","南京" }, + { "sx","拜访客户" }, + }, + new Dictionary + { + { "start","2025-01-02" }, + { "end","2025-01-03" }, + { "address","广东" }, + { "sx","看海" }, + }, + new Dictionary + { + { "start","2025-01-02" }, + { "end","2025-01-03" }, + { "address","山东" }, + { "sx","旅游" }, + } + } }, + { "gzjls",new List> + { + new Dictionary + { + { "name","星瀚未来科技有限公司" }, + { "start","2018年3月" }, + { "end","2020年6月" }, + { "xms",new []{ + "AI语音助手“星语”开发:主导跨团队协作,完成从需求分析到上线的全流程,用户量突破500万", + "为商业卫星公司定制数据分析工具,客户复购率提升30%。" + } }, + }, + new Dictionary + { + { "name","锐驰国际物流供应链有限公司" }, + { "start","2020年7月" }, + { "end"," 2021年12月" }, + { "xms",new []{ + "东南亚跨境物流系统优化:设计智能路由算法,运输时效缩短20%,成本降低15%。", + "冷链仓储自动化试点:引入AGV机器人,实现仓储效率提升40%。" + } }, + }, + new Dictionary + { + { "name","绿野生态农业集团" }, + { "start","2022年1月" }, + { "end"," 2022年9月" }, + { "xms",new []{ + "有机蔬菜订阅制改革:因传统渠道阻力未能落地,仅完成试点用户调研。" + } }, + } + + } } + }; + return data; + } + + } + + + public class TestData + { + public string title { get; set; } + public string username { get; set; } + public int userage { get; set; } + public string userdept { get; set; } + public string userremark { get; set; } + public string[] userroles { get; set; } + public string userimgPath { get; set; } + public object HtmlContents { get; set; } + + public MiniWordPicture? userimg + { + get + { + return userimgPath == null || userimgPath == "" ? null : + new MiniWordPicture + ( + //Bytes=ReadFileToByteArray(@"TestData\test.png"), + @"TestData\test.png", + 180, + 180 + ); + } + } + public TestDataDept dept { get; set; } + public List cl { get; set; } + public List gzjls { get; set; } + } + + public class TestDataDept + { + public string code { get; set; } + public string name { get; set; } + public string manager { get; set; } + } + + public class TestDataCl + { + public string start { get; set; } + public string end { get; set; } + public string address { get; set; } + public string sx { get; set; } + } + public class TestDataGzjl + { + public string start { get; set; } + public string end { get; set; } + public string name { get; set; } + public string[] xms { get; set; } + } +} diff --git a/tests/MiniWordTests/MiniWordTests.csproj b/tests/MiniWordTests/MiniWordTests.csproj index 6b0cb5b4b66570b597d3c324ca7b11e8d45e7d5a..4844595912801d1e0e3936cce60f35801817abf1 100644 --- a/tests/MiniWordTests/MiniWordTests.csproj +++ b/tests/MiniWordTests/MiniWordTests.csproj @@ -23,4 +23,25 @@ + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + diff --git a/tests/MiniWordTests/TestData/sample.html b/tests/MiniWordTests/TestData/sample.html new file mode 100644 index 0000000000000000000000000000000000000000..a40416514a322bbc6a97ce74a2cd400017c92ee3 --- /dev/null +++ b/tests/MiniWordTests/TestData/sample.html @@ -0,0 +1,162 @@ +

产品介绍

+

这是一个重要的产品描述,包含斜体下划线文本。

+

这是红色的大号文字。

+

产品特点:

+

产品图片(居中)

+

+ +

+ +

产品图片(左对齐)

+

+ +

+
产品图片(右对齐)
+

+ +

+

产品图片(居中)

+

+ +

+

技术规格

+

支持 WindowsLinux 和国产操作系统。

+
    +
  • 高性能
  • +
  • 易于使用
  • +
  • 跨平台支持
  • +
+
    +
  1. a
  2. +
  3. b
  4. +
  5. c
  6. +
+
    +
  1. + 1班 +
      +
    1. 张三
    2. +
    3. 里斯
    4. +
    5. 王五
    6. +
    +
  2. +
  3. 2班
  4. +
  5. 3班
  6. +
  7. 4班
  8. +
+
居中文字
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
班级姓名年龄
一班张三16
里斯16
王武16
二班王五16
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
表1
123123123123     
         
         
         
         
         
         
+ + + diff --git a/tests/MiniWordTests/TestData/test.png b/tests/MiniWordTests/TestData/test.png new file mode 100644 index 0000000000000000000000000000000000000000..301a18d1eca63933e9bacc54a8fb194305b8badd Binary files /dev/null and b/tests/MiniWordTests/TestData/test.png differ diff --git a/tests/MiniWordTests/TestData/testTmplate.docx b/tests/MiniWordTests/TestData/testTmplate.docx new file mode 100644 index 0000000000000000000000000000000000000000..c4ee11488bbf4826a8ef90df1123cb9e1234ddd2 Binary files /dev/null and b/tests/MiniWordTests/TestData/testTmplate.docx differ