From 3d42f0a058aa103918d41f1adc4f181d29770dbd Mon Sep 17 00:00:00 2001 From: just42 Date: Wed, 24 Mar 2021 15:31:42 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E8=8B=B1=E8=AF=AD=E7=BF=BB?= =?UTF-8?q?=E8=AF=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...asic tutorial of importing student data.md | 445 +++++++++++++++ docs/2.Basic tutorial of export Excel.md | 348 +++++++++++ ...3.Basic tutorial of export Pdf receipts.md | 538 ++++++++++++++++++ docs/4.Use in Docker.md | 213 +++++++ docs/5.Dynamic Export.md | 56 ++ 5 files changed, 1600 insertions(+) create mode 100644 docs/1.Basic tutorial of importing student data.md create mode 100644 docs/2.Basic tutorial of export Excel.md create mode 100644 docs/3.Basic tutorial of export Pdf receipts.md create mode 100644 docs/4.Use in Docker.md create mode 100644 docs/5.Dynamic Export.md diff --git a/docs/1.Basic tutorial of importing student data.md b/docs/1.Basic tutorial of importing student data.md new file mode 100644 index 00000000..c332f66c --- /dev/null +++ b/docs/1.Basic tutorial of importing student data.md @@ -0,0 +1,445 @@ +# Basic tutorial of importing student data + +## Description + +This tutorial explains how to use Magicodes.IE.Excel to complete the Excel import of student data. + +## Main points + +- Uses Magicodes.IE.Excel to complete the Excel data import +- Creating a Dto for import data. +- Magicodes.IE.Excel can automatically generate imported Excel templates, data validation (including duplicate validation), template validation, read settings, value constraints and mapping, and output Excel validation markup based on Dto and feature settings. + +## Main steps + +### 1.Installation package - Magicodes.IE.Excel + +In this tutorial, we will only demonstrate the use of Excel to complete the import of student data. We need to install the following packages in the prepared project with the following reference commands: + +```powershell +Install-Package Magicodes.IE.Excel +``` + + + +### 2.Create Import Dto + +The main code is shown below: + +- Student Data Dto + + ```c# + /// + /// Importing Student Data Dto + /// IsLabelingError:Whether to mark data errors + /// + [ExcelImporter(IsLabelingError = true)] + public class ImportStudentDto + { + /// + /// Serial No. + /// + [ImporterHeader(Name = "Serial No.")] + public long SerialNumber { get; set; } + + /// + /// Student Registration No. + /// + [ImporterHeader(Name = "Student Registration No.")] + [MaxLength(30, ErrorMessage = "The number of words exceeds the maximum limit, please modify!")] + public string StudentCode { get; set; } + + /// + /// Name + /// + [ImporterHeader(Name = "Name")] + [Required(ErrorMessage = "Name cannot be empty")] + [MaxLength(50, ErrorMessage = "The number of words exceeds the maximum limit, please modify!")] + public string Name { get; set; } + + /// + /// ID number + /// + [ImporterHeader(Name = "ID number", IsAllowRepeat = false)] + [Required(ErrorMessage = "ID number cannot be empty")] + [MaxLength(18, ErrorMessage = "The number of words exceeds the maximum limit, please modify!")] + public string IdCard { get; set; } + + /// + /// Gender + /// + [ImporterHeader(Name = "Gender")] + [Required(ErrorMessage = "Gender cannot be empty")] + [ValueMapping("Male", 0)] + [ValueMapping("Female", 1)] + public Genders Gender { get; set; } + + /// + /// Home Address + /// + [ImporterHeader(Name = "Home Address")] + [Required(ErrorMessage = "Home Address cannot be empty")] + [MaxLength(200, ErrorMessage = "The number of words exceeds the maximum limit, please modify!")] + public string Address { get; set; } + + /// + /// Parent's name + /// + [ImporterHeader(Name = "Parent's name")] + [Required(ErrorMessage = "Parent's name cannot be empty")] + [MaxLength(50, ErrorMessage = "The number of words exceeds the maximum limit, please modify!")] + public string Guardian { get; set; } + + /// + /// Parental contact number + /// + [ImporterHeader(Name = "Parental contact number")] + [MaxLength(20, ErrorMessage = "The number of words exceeds the maximum limit, please modify!")] + public string GuardianPhone { get; set; } + + /// + /// Student ID + /// + [ImporterHeader(Name = "Student ID")] + [MaxLength(30, ErrorMessage = "The number of words exceeds the maximum limit, please modify!")] + public string StudentNub { get; set; } + + /// + /// Dormitory number + /// + [ImporterHeader(Name = "Dormitory number")] + [MaxLength(20, ErrorMessage = "The number of words exceeds the maximum limit, please modify!")] + public string DormitoryNo { get; set; } + + /// + /// QQ + /// + [ImporterHeader(Name = "QQ number")] + [MaxLength(30, ErrorMessage = "The number of words exceeds the maximum limit, please modify!")] + public string QQ { get; set; } + + /// + /// Ethnic + /// + [ImporterHeader(Name = "Ethnic")] + [MaxLength(2, ErrorMessage = "The number of words exceeds the maximum limit, please modify!")] + public string Nation { get; set; } + + /// + /// Household + /// + [ImporterHeader(Name = "Household")] + [MaxLength(10, ErrorMessage = "The number of words exceeds the maximum limit, please modify!")] + public string HouseholdType { get; set; } + + /// + /// Contact number + /// + [ImporterHeader(Name = "Contact number")] + [MaxLength(20, ErrorMessage = "The number of words exceeds the maximum limit, please modify!")] + public string Phone { get; set; } + + /// + /// Status + /// Test for nullable enumeration types + /// + [ImporterHeader(Name = "Status")] + public StudentStatus? Status { get; set; } + + /// + /// Remarks + /// + [ImporterHeader(Name = "Remarks")] + [MaxLength(200, ErrorMessage = "The number of words exceeds the maximum limit, please modify!")] + public string Remark { get; set; } + + /// + /// Whether live on campus (dormitory) + /// + [ImporterHeader(IsIgnore = true)] + public bool? IsBoarding { get; set; } + + /// + /// Class id + /// + [ImporterHeader(IsIgnore = true)] + public Guid ClassId { get; set; } + + /// + /// School Id + /// + [ImporterHeader(IsIgnore = true)] + public Guid? SchoolId { get; set; } + + /// + /// Campus Id + /// + [ImporterHeader(IsIgnore = true)] + public Guid? CampusId { get; set; } + + /// + /// MajorsId + /// + [ImporterHeader(IsIgnore = true)] + public Guid? MajorsId { get; set; } + + /// + /// GradeId + /// + [ImporterHeader(IsIgnore = true)] + public Guid? GradeId { get; set; } + } + ``` + As shown in the above code, we defined the above student data Dto with the following main considerations : + + 1. ExcelImporterfeature allows you to set some global settings for importing, such as whether to mark errors, the name of the imported Sheet (if not set, the first one is automatically obtained), the number of columns to be read, and the position of the sheet header. + 2. Support common data validation settings, such as required and maximum length. + 3. Support data duplicate verification, such as ID numbers. Refer ImporterHeader features of IsAllowRepeat setting. + 4. Supports column header settings,For example ImporterHeader - Name Properties。Other than that,ImporterHeader also supports automatic space filtering (enabled by default), disposing off all spaces, column indexing, etc.。 + 5. Ignore setting is enabled for data columns,For example SchoolId "[ImporterHeader(IsIgnore = true)]"。 + 6. Value mapping is used, For example “Gender” attribute. When value mapping is enabled, the value mapping will not be retrieved from the enumeration definition。 + 7. Enumeration support, support for enumeration from the Display、Description Get value mapping。See below for enumeration definitions。 + +- Gender Enumeration + + The definition is as follows: + + ```c# + /// + /// Gender + /// + public enum Genders + { + /// + /// 男 + /// + Man = 0, + + /// + /// 女 + /// + Female = 1 + } + ``` + Note point 7 above. + +- Student Status Enumeration + + ```c# + /// + /// Student Status: Normal, Attrition, Suspended, Work-Study, Internship, Graduation, Military + /// + public enum StudentStatus + { + /// + /// Normal + /// + [Display(Name = "Normal")] Normal = 0, + + /// + /// Attrition + /// + [Description("Attrition")] PupilsAway = 1, + + /// + /// Suspended + /// + [Display(Name = "Suspended")] Suspension = 2, + + /// + /// Work-Study + /// + [Display(Name = "Work-Study")] WorkStudy = 3, + + /// + /// Internship + /// + [Display(Name = "Internship")] PostPractice = 4, + + /// + /// Graduation + /// + [Display(Name = "Graduation")] Graduation = 5, + + /// + /// Military + /// + [Display(Name = "Military")] JoinTheArmy = 6 + } + ``` + Note point 7 above + + + +### 3.Generate import templates and populate them with data + +Do you have to prepare a template before importing? handwritten template?Not required! Magicodes.IE.Excel Provided the basis for DTO Automatic generation Excel Methods of importing templates,We can call it directly. Here we look at the relevant methods for importing: + +```c# +/// +/// Import +/// +public interface IImporter +{ + /// + /// 生成Excel导入模板 + /// + /// + /// + Task GenerateTemplate(string fileName) where T : class, new(); + + /// + /// 生成Excel导入模板 + /// + /// + /// 二进制字节 + Task GenerateTemplateBytes() where T : class, new(); + + /// + /// 导入模型验证数据 + /// + /// + /// + /// + Task> Import(string filePath) where T : class, new(); +} +``` + +By using GenerateTemplate in the above method, we can get the required import template. The specific use can be found in the following unit tests. + +```c# + public IImporter Importer = new ExcelImporter(); + + [Fact(DisplayName = "生成学生数据导入模板(测试枚举生成模板)")] + public async Task GenerateStudentImportTemplate_Test() + { + var filePath = Path.Combine(Directory.GetCurrentDirectory(), + nameof(GenerateStudentImportTemplate_Test) + ".xlsx"); + if (File.Exists(filePath)) File.Delete(filePath); + + var result = await Importer.GenerateTemplate(filePath); + result.ShouldNotBeNull(); + File.Exists(filePath).ShouldBeTrue(); + + //TODO:读取Excel检查表头和格式 + } +``` + +The above DTO gets the template and populates the data as shown below: + +![Excel导入模板](../res/1574832770808.png) + +**Note: The enumeration will automatically generate a drop-down selection, and the required column headers will be marked in red** + +### 4. Get student import verification errors and data + +After populating the data according to the template, we are ready to perform the data import. Typically, we have the following steps. + +1. Validate imported data + + Importing data through Magicodes.IE.Excel will automatically perform validation and output the validation results for frontend display. Specifically, we can look through its imported result classes to see. + + ```c# + /// + /// Import Results + /// + public class ImportResult where T : class + { + /// + /// + public ImportResult() + { + RowErrors = new List(); + } + + /// + /// Importing Data + /// + public virtual ICollection Data { get; set; } + + /// + /// Validation error + /// + public virtual IList RowErrors { get; set; } + + /// + /// Template error + /// + public virtual IList TemplateErrors { get; set; } + + /// + /// Import exception information + /// + public virtual Exception Exception { get; set; } + + /// + /// Is there an import error + /// + public virtual bool HasError => Exception != null || + (TemplateErrors?.Count(p => p.ErrorLevel == ErrorLevels.Error) ?? 0) > 0 || + (RowErrors?.Count ?? 0) > 0; + } + ``` + Among them: + + - Data is the data result + + - RowErrors is validation errors, such as required, duplicate validation, text length, etc. will give the line number, field and the set of field errors + + ![](../res/数据错误统一返回.png "数据错误") + + - TemplateErrors is template errors, such as missing mandatory columns and other error messages. Support error level (warning, error) + + - Exception is import exception information + + - HasError is existence of errors (without warnings) + + Through ImportResult, we can easily get the import validation error without writing additional code. Usually, we need to determine the HasError property during import and return a specific error result to the frontend. + + The data import reference code is shown below: + + ```c# + [Fact(DisplayName = "Student base data import")] + public async Task StudentInfoImporter_Test() + { + var filePath = Path.Combine(Directory.GetCurrentDirectory(), "TestFiles", "Import", "学生基础数据导入.xlsx"); + var import = await Importer.Import(filePath); + import.ShouldNotBeNull(); + if (import.Exception != null) _testOutputHelper.WriteLine(import.Exception.ToString()); + + if (import.RowErrors.Count > 0) _testOutputHelper.WriteLine(JsonConvert.SerializeObject(import.RowErrors)); + import.HasError.ShouldBeFalse(); + import.Data.ShouldNotBeNull(); + import.Data.Count.ShouldBe(16); + } + ``` + +2. Get verification markup + + The customer said although you hinted, but I still do not know what is wrong! What to do?!!! + + ![](../res/f1536893905558.jpg) + + We have thoughtfully prepared for you the markup of the Excel file for importing data: + + ![](../res/数据错误.png "数据错误标注") + ![](../res/多个错误.png "多个错误") + + How to open this [Epic Plot]? Simply by one step: + + + ```c# + [ExcelImporter(IsLabelingError = true)] + ``` + + Once turned on, we will automatically save the markup file "{target file name}_.xlsx" to the target location. + +3. Get imported data + + No more errors? That is, HasError is false, then we can just get the Data and do whatever we want! + + + +## Finally + +This concludes the entire tutorial on importing student data. ** Related libraries will be updated all the time, and there may be slight differences in functional experience with this tutorial, please refer to the relevant specific code, version logs, and unit test examples. ** \ No newline at end of file diff --git a/docs/2.Basic tutorial of export Excel.md b/docs/2.Basic tutorial of export Excel.md new file mode 100644 index 00000000..3fe7c6ff --- /dev/null +++ b/docs/2.Basic tutorial of export Excel.md @@ -0,0 +1,348 @@ +# Basic tutorial of export Excel + +## Description + +This tutorial explains how to complete the Excel export of student data using Magicodes. + +## Main points + +- Export Features +- How to export Excel table headers +- How to export data、cut data、use filters +- Support dynamic/ExpandoObject type of dynamic export + +## Export Features + +### ExporterAttribute + ++ **Name**: Name (current Sheet name) ++ **HeaderFontSize**:Header font size ++ **FontSize**:Body font size ++ **MaxRowNumberOnASheet**:The maximum number of rows allowed for a Sheet, after setting it, multiple Sheets will be output. ++ **TableStyle**:Form Style ++ **AutoFitAllColumn**:***bool*** Adaptive all columns ++ **Author**:Author ++ **ExporterHeaderFilter**:Head Screener ++ **AutoCenter**:Set to center the entire table + +### ExporterHeaderAttribute + ++ **DisplayName**: Display Name ++ **FontSize**: Font Size ++ **IsBold**: Bolded or not ++ **Format**: Formatting ++ **IsAutoFit**: Adaptive or not ++ **IsIgnore**: Whether or not to ignore ++ **AutoCenterColumn**: Set column centering + +### IEIgnoreAttribute + +Works on properties and enumeration members. + ++ **IsImportIgnore**:Whether to ignore the import, default true ++ **IsExportIgnore**:Whether to ignore export, default true + +### DescriptionAttribute + ++ **Description**: Sheet Import Export Annotation + +### DisplayFormatAttribute + ++ **DataFormatString**:Data display format + +### DisplayAttribute + ++ **Name** + + **Import exported display column names (properties)** ++ **Order** + + **列索引** ++ **Description** + + **列描述** + +## Main steps + +### 1.Installation package Magicodes.IE.Excel + +```powershell +Install-Package Magicodes.IE.Excel +``` + +### 2.Exporting Excel table headers + +- Exporting through arrays + +```csharp + public async Task ExportHeader() + { + IExcelExporter exporter = new ExcelExporter(); + + var filePath = "h.xlsx"; + var arr = new[] { "Name1", "Name2", "Name3", "Name4", "Name5", "Name6" }; + var sheetName = "Test"; + var result = await exporter.ExportHeaderAsByteArray(arr, sheetName); + result.ToExcelExportFileInfo(filePath); + + } +``` + +- Export via DTO + +```csharp + public async Task ExportHeader() + { + IExporter exporter = new ExcelExporter(); + + var filePath = "h.xlsx"; + var result = await exporter.ExportHeaderAsByteArray( new Student()); + result.ToExcelExportFileInfo(filePath); + + } +``` + +![基础教程导出Excel-2](../res/2.基础教程导出Excel-3.png) + + +### 3.Export Excel + +- Basic Export + +```csharp + + public class Student + { + /// + /// 姓名 + /// + public string Name { get; set; } + /// + /// 年龄 + /// + public int Age { get; set; } + } + + public async Task Export() + { + IExporter exporter = new ExcelExporter(); + var result = await exporter.Export("a.xlsx", new List() + { + new Student + { + Name = "MR.A", + Age = 18 + }, + new Student + { + Name = "MR.B", + Age = 19 + }, + new Student + { + Name = "MR.B", + Age = 20 + } + }); + } + + +``` + +With the code as above we can export Excel as shown below + +![基础教程导出Excel-1](../res/2.基础教程导出Excel-1.png) + +- Example of feature export + +```csharp + + public async Task Export() + { + IExporter exporter = new ExcelExporter(); + var result = await exporter.Export("test.xlsx", new List() + { + new Student + { + Name = "MR.A", + Age = 18, + Remarks = "我叫MR.A,今年18岁", + Birthday=DateTime.Now + }, + new Student + { + Name = "MR.B", + Age = 19, + Remarks = "我叫MR.B,今年19岁", + Birthday=DateTime.Now + }, + new Student + { + Name = "MR.C", + Age = 20, + Remarks = "我叫MR.C,今年20岁", + Birthday=DateTime.Now + } + }); + } + /// + /// 学生信息 + /// + [ExcelExporter(Name = "学生信息", TableStyle = "Light10", AutoFitAllColumn = true, MaxRowNumberOnASheet = 2)] + public class Student + { + /// + /// 姓名 + /// + [ExporterHeader(DisplayName = "姓名")] + public string Name { get; set; } + /// + /// 年龄 + /// + [ExporterHeader(DisplayName = "年龄")] + public int Age { get; set; } + /// + /// 备注 + /// + public string Remarks { get; set; } + /// + /// 出生日期 + /// + [ExporterHeader(DisplayName = "出生日期", Format = "yyyy-mm-DD")] + public DateTime Birthday { get; set; } + } + + +``` + +With the code as above we can export Excel as shown below + +![基础教程导出Excel-2](../res/2.基础教程导出Excel-2.png) + + 1. ExcelExporter can set the export layout settings, table format, SheetName, adaptive columns, etc. Refer to **导出特性** + 2. ExporterHeader can set the table header name, style, etc. For details, refer to **导出特性** + 3. ExcelExporter MaxRowNumberOnASheet can split the data, specify the length of the Sheet data by this property to achieve automatic cutting + + +- Table Header Filter + +```csharp + /// + /// 学生信息 + /// + [ExcelExporter(Name = "学生信息", TableStyle = "Light10", AutoFitAllColumn = true, MaxRowNumberOnASheet = 2,ExporterHeaderFilter = typeof(ExporterStudentHeaderFilter))] + public class Student + { + /// + /// 姓名 + /// + [ExporterHeader(DisplayName = "姓名")] + public string Name { get; set; } + /// + /// 年龄 + /// + [ExporterHeader(DisplayName = "年龄",Format = "#,##0")] + public int Age { get; set; } + /// + /// 备注 + /// + public string Remarks { get; set; } + } + + + public class ExporterStudentHeaderFilter : IExporterHeaderFilter + { + /// + /// 表头筛选器(修改名称) + /// + /// + /// + public ExporterHeaderInfo Filter(ExporterHeaderInfo exporterHeaderInfo) + { + if (exporterHeaderInfo.DisplayName.Equals("姓名")) + { + exporterHeaderInfo.DisplayName = "name"; + } + return exporterHeaderInfo; + } + } +``` + +With the above code snippet we implement **IExporterHeaderFilter** interface, IExporterHeaderFilter to support multi-language, dynamic control column display and other scenarios + +### 4.Dynamic Export + +```csharp + class Program + { + static async Task Main(string[] args) + { + IExporter exporter = new ExcelExporter(); + // 生成测试数据 + var personList = GenFu.GenFu.ListOf(); + + // 导出一个只包含"FirstName", "LastName"列的excel + string fields = "FirstName,LastName"; // 可自定义导出想要的字段 + var expandoObjectList = new List(personList.Count); + var propertyInfoList = new List(); + var fieldsAfterSplit = fields.Split(','); + foreach (var field in fieldsAfterSplit) + { + var propertyName = field.Trim(); + var propertyInfo = typeof(Person).GetProperty(propertyName); + + if (propertyInfo == null) + { + throw new Exception($"Property: {propertyName} 没有找到:{typeof(Person)}"); + } + + propertyInfoList.Add(propertyInfo); + } + + foreach (var person in personList) + { + var shapedObj = new ExpandoObject(); + + foreach (var propertyInfo in propertyInfoList) + { + var propertyValue = propertyInfo.GetValue(person); + ((IDictionary)shapedObj).Add(propertyInfo.Name, propertyValue); + } + + expandoObjectList.Add(shapedObj); + } + + string filePath = Path.Combine(Directory.GetCurrentDirectory(), "dynamicExportExcel.xlsx"); + var result = await exporter.ExportAsByteArray(expandoObjectList); + File.WriteAllBytes(filePath, result); + } + } + + + class Person + { + public string FirstName { get; set; } + public string LastName { get; set; } + public string Title { get; set; } + public int Age { get; set; } + public int NumberOfKids { get; set; } + } +``` + +With the code as above we can export Excel as shown below +![基础教程导出Excel-支持动态类型](../res/2.基础教程导出Excel-支持动态类型.png) + +### 5.Enum&bool类型指定显示的值 + +``` +[ValueMapping(text: "yes", true)] +[ValueMapping(text: "no", false)] +[ValueMapping(text: "小微客户", 0)] +``` + + + + + + + + + + diff --git a/docs/3.Basic tutorial of export Pdf receipts.md b/docs/3.Basic tutorial of export Pdf receipts.md new file mode 100644 index 00000000..cc0b8897 --- /dev/null +++ b/docs/3.Basic tutorial of export Pdf receipts.md @@ -0,0 +1,538 @@ +# Basic tutorial of export Pdf receipts + +## Description + +This tutorial mainly explains how to use Magicodes. + +## Main points + +- Export PDF data +- Customize PDF templates +- Export documents +- How to export documents in bulk + +## Export feature description + +### PdfExporterAttribute +PdfExporterAttribute feature used to set the overall settings for Pdf export, such as direction, paper, etc.. Mainly contains the following settings. + ++ **Name**:Document Title ++ **FontSize**:Font Size ++ **Orientation**: Orientation (horizontal or vertical) ++ **PaperKind**: Paper type (default A4) ++ **IsWriteHtml**: Whether to output HTML templates ++ **IsEnablePagesCount**:Whether paging is enabled ++ **Encoding**:Encoding, default utf-8 ++ **HeaderSettings**:Export header settings ++ **FooterSettings**:Export bottom setting + +### ExporterHeaderAttribute + +ExporterHeaderAttribute feature used to set the column header information, in the Pdf form, can be used to set the display name. +**DisplayName**: Display Name + +## Steps to use + +### 1.Installation package Magicodes.IE.Pdf + +```powershell +Install-Package Magicodes.IE.Pdf +``` + +### 2.Exporting PDF data + +- Create Dto class + +```csharp + public class Student + { + /// + /// 姓名 + /// + public string Name { get; set; } + /// + /// 年龄 + /// + public int Age { get; set; } + } +``` + +```csharp + public async Task ExportPdf() + { + var exporter = new PdfExporter(); + var result = await exporter.ExportListByTemplate("test.pdf", new List() + { + new Student + { + Name = "MR.A", + Age = 18 + }, + new Student + { + Name = "MR.B", + Age = 19 + }, + new Student + { + Name = "MR.B", + Age = 20 + } + }); + } +``` + +Export PDF currently also supports the passing of feature classes in the form of parameters, as follows: + +```csharp + /// + /// 导出Pdf + /// + /// + /// Pdf导出设置 + /// 模板 + /// + Task ExportListBytesByTemplate(ICollection data, PdfExporterAttribute pdfExporterAttribute, + string template) where T : class; + + /// + /// 导出Pdf + /// + /// + /// + /// + /// + /// + Task ExportBytesByTemplate(T data, PdfExporterAttribute pdfExporterAttribute, string template) + where T : class; +``` + +The exported content is shown below. + +![3.基础教程之导出Pdf收据-1](../res/3.基础教程之导出Pdf收据-1.png) + +The above code exports a simple Pdf table, using the built-in table template in Magicodes. If we need to customize the title, you can set through the [ExporterHeader] feature to. + +```csharp + [PdfExporter(Name = "学生信息")] + public class Student + { + /// + /// 姓名 + /// + [ExporterHeader(DisplayName = "姓名")] + [Display(Name = "Display姓名")] + public string Name { get; set; } + /// + /// 年龄 + /// + [ExporterHeader(DisplayName = "年龄")] + public int Age { get; set; } + } +``` +1. PdfExporter through the Name property to define the title of the document +2. ExporterHeader DisplayName is used to define the attribute name +3. DDisplay also defines the attribute name, but with less priority than ExporterHeader + +The result of the execution by modifying the above code is shown below. + +![3.基础教程之导出Pdf收据-2](../res/3.基础教程之导出Pdf收据-2.png) + +### 3.Export PDF receipts via templates + +- Create export templates + +```html + + + + + + + + + + + +

+ @Model.Title +

+

+ NO:@Model.Data.Code + 交易时间:@Model.Data.TradeTime.ToString("yyyy-MM-dd HH:mm:ss") +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
交款姓名@Model.Data.Name身份证号码@Model.Data.IdNo
交易金额 + ¥:@Model.Data.Amount + 人民币(大写): + @Model.Data.UppercaseAmount +
收款方式@Model.Data.PaymentMethod交易状态@Model.Data.TradeStatus
收款事由@Model.Data.Remark入学年级@Model.Data.Grade专业@Model.Data.Profession
+ + +``` +IE supports HTML template writing for ease of template writing, as shown in the code above. + +- Create Dto class + + ```csharp + [Exporter(Name = "湖南心莱信息科技有限公司电子收款凭证")] + public class ReceiptInfo + { + /// + /// 交易时间 + /// + public DateTime TradeTime { get; set; } + + /// + /// 姓名 + /// + public string Name { get; set; } + + /// + /// 身份证 + /// + public string IdNo { get; set; } + + /// + /// 金额 + /// + public decimal Amount { get; set; } + + /// + /// 支付方式 + /// + public string PaymentMethod { get; set; } + + /// + /// 交易状态 + /// + public string TradeStatus { get; set; } + + /// + /// 备注 + /// + public string Remark { get; set; } + + /// + /// 年级 + /// + public string Grade { get; set; } + + /// + /// 专业 + /// + public string Profession { get; set; } + + /// + /// 收款人 + /// + public string Payee { get; set; } + + /// + /// 大写金额 + /// + public string UppercaseAmount { get; set; } + + /// + /// 编号 + /// + public string Code { get; set; } + } + ``` + + 1. You can specify the Title in the template through the Exporter feature, and you can also work without the attribute to do so, after all, this piece is also fully customizable + +- How to use custom template export? The code is shown below. + + ```csharp + public async Task ExportReceipt() + { + var tplPath = Path.Combine(Directory.GetCurrentDirectory(), "TestFiles", "ExportTemplates", + "receipt.cshtml"); + var tpl = File.ReadAllText(tplPath); + var exporter = new PdfExporter(); + //此处使用默认模板导出 + var result = await exporter.ExportByTemplate("test.pdf", + new ReceiptInfo + { + Amount = 22939.43M, + Grade = "2019秋", + IdNo = "43062619890622xxxx", + Name = "张三", + Payee = "湖南心莱信息科技有限公司", + PaymentMethod = "微信支付", + Profession = "运动训练", + Remark = "学费", + TradeStatus = "已完成", + TradeTime = DateTime.Now, + UppercaseAmount = "贰万贰仟玖佰叁拾玖圆肆角叁分", + Code = "19071800001" + }, tpl); + } + ``` + + With the above code we need to specify the passing of the template content and the final export effect is as follows. + + ![3.基础教程之导出Pdf收据-3](../res/3.基础教程之导出Pdf收据-3.png) + +### 4.Export PDF receipts in batch + +In some cases, we need to export multiple data to a Pdf, such as the bank to provide bulk receipts. IE, through Magicodes, can also be very simple to achieve similar needs. The main steps are shown below: + +- Create Template + + ```html + + + + + + + + + + + + @for (var i = 0; i < Model.Data.ReceiptInfoInputs.Count; i++) + { +
+

+ @Model.Data.Title +

+

+ NO:@Model.Data.ReceiptInfoInputs[i].Code + 交易时间:@Model.Data.ReceiptInfoInputs[i].TradeTime.ToString("yyyy-MM-dd HH:mm:ss") +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
交款姓名@Model.Data.ReceiptInfoInputs[i].Name身份证号码@Model.Data.ReceiptInfoInputs[i].IdNo
交易金额 + ¥:@Model.Data.ReceiptInfoInputs[i].Amount + 人民币(大写): + @Model.Data.ReceiptInfoInputs[i].UppercaseAmount +
收款方式@Model.Data.ReceiptInfoInputs[i].PaymentMethod交易状态@Model.Data.ReceiptInfoInputs[i].TradeStatus
收款事由@Model.Data.ReceiptInfoInputs[i].Remark入学年级@Model.Data.ReceiptInfoInputs[i].Grade专业@Model.Data.ReceiptInfoInputs[i].Profession
+
+ } + + + ``` + +- Create Dto class + + ```csharp + /// + /// 批量导出Dto + /// + [PdfExporter(Orientation = Orientation.Portrait, PaperKind = PaperKind.A5)] + public class BatchReceiptInfoDto + { + /// + /// 交易时间 + /// + public DateTime TradeTime { get; set; } + + /// + /// 姓名 + /// + public string Name { get; set; } + + /// + /// 身份证 + /// + public string IdNo { get; set; } + + /// + /// 金额 + /// + public decimal Amount { get; set; } + + /// + /// 支付方式 + /// + public string PaymentMethod { get; set; } + + /// + /// 交易状态 + /// + public string TradeStatus { get; set; } + + /// + /// 备注 + /// + public string Remark { get; set; } + + /// + /// 年级 + /// + public string Grade { get; set; } + + /// + /// 专业 + /// + public string Profession { get; set; } + + /// + /// 大写金额 + /// + public string UppercaseAmount { get; set; } + + /// + /// 编号 + /// + public string Code { get; set; } + } + ``` + +- How to use + + ```csharp + public async Task BathExportReceipt() + { + var tplPath = Path.Combine(Directory.GetCurrentDirectory(), "TestFiles", "ExportTemplates", + "batchReceipt.cshtml"); + var tpl = File.ReadAllText(tplPath); + var exporter = new PdfExporter(); + + var input = new BatchReceiptInfoInput + { + Payee = "湖南心莱信息科技有限公司", + ReceiptInfoInputs = new List() + }; + + for (var i = 0; i < 20; i++) + input.ReceiptInfoInputs.Add(new BatchReceiptInfoDto + { + Amount = 22939.43M, + Grade = "2019秋", + IdNo = "43062619890622xxxx", + Name = "张三", + PaymentMethod = "微信支付", + Profession = "运动训练", + Remark = "学费", + TradeStatus = "已完成", + TradeTime = DateTime.Now, + UppercaseAmount = "贰万贰仟玖佰叁拾玖圆肆角叁分", + Code = "1907180000" + i + }); + + //此处使用默认模板导出 + var result = await exporter.ExportByTemplate("test.pdf", input, tpl); + } + ``` + + + +With the above code we need to specify the passing of the template content and the final export effect is as follows: + +![3.基础教程之导出Pdf收据-4](../res/3.基础教程之导出Pdf收据-4.png) + +## Cautions + +At this point, the entire tutorial ends here. However, there are still the following things to note: + +- Pdf export supports all platforms, including Windows and Linux, x86 and x64 +- Pdf export underlying based on the wkhtmltopdf library package, has included wkhtmltopdf package for each platform, no need to install again +- In the Linux container, Pdf export requires the installation of relevant font files, see the container tutorial + diff --git a/docs/4.Use in Docker.md b/docs/4.Use in Docker.md new file mode 100644 index 00000000..919b2739 --- /dev/null +++ b/docs/4.Use in Docker.md @@ -0,0 +1,213 @@ +# Magicodes.IE for use in Docker + +## Description + +This chapter mainly explains the use of Magicodes.IE, configuration in a Docker environment. + +## Main points + +- Excel export via Dto +- Exporting PDF +- Docker Configuration + +## Example + +### Example of export. + + +```powershell +Install-Package Magicodes.IE.Excel +Install-Package Magicodes.IE.Pdf +``` + +- Export Excel + +```csharp + [ExcelExporter(Name = "学生信息", TableStyle = "Light10", AutoFitAllColumn = true, + MaxRowNumberOnASheet = 2)] + public class StudentExcel + { + + /// + /// 姓名 + /// + [ExporterHeader(DisplayName = "姓名")] + public string Name { get; set; } + /// + /// 年龄 + /// + [ExporterHeader(DisplayName = "年龄")] + public int Age { get; set; } + /// + /// 备注 + /// + public string Remarks { get; set; } + /// + /// 出生日期 + /// + [ExporterHeader(DisplayName = "出生日期", Format = "yyyy-mm-DD")] + public DateTime Birthday { get; set; } + } + +``` + + +```csharp + + public async Task ExporterExcel() { + IExporter exporter = new ExcelExporter(); + + var result = await exporter.Export(Path.Combine("wwwroot","test.xlsx"), new List() + { + new StudentExcel + { + Name = "MR.A", + Age = 18, + Remarks = "我叫MR.A,今年18岁", + Birthday=DateTime.Now + }, + new StudentExcel + { + Name = "MR.B", + Age = 19, + Remarks = "我叫MR.B,今年19岁", + Birthday=DateTime.Now + }, + new StudentExcel + { + Name = "MR.C", + Age = 20, + Remarks = "我叫MR.C,今年20岁", + Birthday=DateTime.Now + } + }); + return File("test.xlsx", "application/ms-excel", result.FileName); + } + +``` + + +- 导出PDF + +```csharp + + [PdfExporter(Name = "学生信息")] + public class StudentPdf + { + /// + /// 姓名 + /// + [ExporterHeader(DisplayName = "姓名")] + public string Name { get; set; } + /// + /// 年龄 + /// + [ExporterHeader(DisplayName = "年龄")] + public int Age { get; set; } + /// + /// 备注 + /// + public string Remarks { get; set; } + /// + /// 出生日期 + /// + [ExporterHeader(DisplayName = "出生日期", Format = "yyyy-mm-DD")] + public DateTime Birthday { get; set; } + } +``` + +```csharp + + public async Task ExporterPdf() { + var exporter = new PdfExporter(); + var result = await exporter.ExportListByTemplate(Path.Combine("wwwroot", "test.pdf"), new List() + { + new StudentPdf + { + Name = "MR.A", + Age = 18, + Remarks = "我叫MR.A,今年18岁", + Birthday=DateTime.Now + }, + new StudentPdf + { + Name = "MR.B", + Age = 19, + Remarks = "我叫MR.B,今年19岁", + Birthday=DateTime.Now + }, + new StudentPdf + { + Name = "MR.C", + Age = 20, + Remarks = "我叫MR.C,今年20岁", + Birthday=DateTime.Now + } + }); + return File("test.pdf", "application/pdf", result.FileName); + } + +``` + +With the above code we have created an export demo, +The specific characteristics and properties can be seen in the previous two articles. [基础教程之导出Excel](https://github.com/dotnetcore/Magicodes.IE/blob/master/docs/2.%E5%9F%BA%E7%A1%80%E6%95%99%E7%A8%8B%E4%B9%8B%E5%AF%BC%E5%87%BAExcel.md) 、[基础教程之导出Pdf收据](https://github.com/dotnetcore/Magicodes.IE/blob/master/docs/3.%E5%9F%BA%E7%A1%80%E6%95%99%E7%A8%8B%E4%B9%8B%E5%AF%BC%E5%87%BAPdf%E6%94%B6%E6%8D%AE.md) + +## Dockerfile Configuration + +```dockerfile +#It is recommended that you build with this base image for the reasons given below. This image build has the libgdiplus library installed. +FROM ccr.ccs.tencentyun.com/magicodes/aspnetcore-runtime:latest AS base + +WORKDIR /src +RUN ls +COPY /src/Magicodes.IE.Exporter/simsun.ttc /usr/share/fonts/simsun.ttc + +WORKDIR /app +EXPOSE 80 +EXPOSE 443 + +FROM mcr.microsoft.com/dotnet/core/sdk:latest AS build +WORKDIR /src +COPY ["Magicodes.IE.Exporter.csproj", "src/Magicodes.IE.Exporter/"] +RUN dotnet restore "src/Magicodes.IE.Exporter/Magicodes.IE.Exporter.csproj" +COPY . . +WORKDIR "src/Magicodes.IE.Exporter" +RUN dotnet build "Magicodes.IE.Exporter.csproj" -c Release -o /app/build + +FROM build AS publish +RUN dotnet publish "Magicodes.IE.Exporter.csproj" -c Release -o /app/publish + +FROM base AS final +WORKDIR /app +COPY --from= publish /app/publish . +ENTRYPOINT ["dotnet", "Magicodes.IE.Exporter.dll"] +``` + +```dockerfile +# If you do not use the above base image, then you need to add the following command to install the libgdiplus library for Excel export +RUN apt-get update && apt-get install -y libgdiplus libc6-dev +RUN ln -s /usr/lib/libgdiplus.so /usr/lib/gdiplus.dll +``` + +```dockerfile +# Install fontconfig library for Pdf export +RUN apt-get update && apt-get install -y fontconfig +# Copy font file +COPY /simsun.ttc /usr/share/fonts/simsun.ttc +``` +Note that the above base image uses:(ccr.ccs.tencentyun.com/magicodes/aspnetcore-runtime:latest) ,该镜像GitHub地址:(https://github.com/xin-lai/aspnetcore-docker)。 + + +Reasons for Recommendation. + +- Speed up image building and pulling, accelerate CI/CD building and improve development experience +- Time zone is set to East 8 by default, see "ENV TZ=Asia/Shanghai" +- By default, libgdiplus and other libraries are installed to support Excel import and export +- At present, we provide Tencent Cloud public mirror and hub.docker public mirror, you can use them as needed. + + +## Reference + +- [https://github.com/dotnetcore/Magicodes.IE](https://github.com/dotnetcore/Magicodes.IE) +- [https://github.com/hueifeng/BlogSample/tree/master/src/Magicodes.IE.Exporter](https://github.com/hueifeng/BlogSample/tree/master/src/Magicodes.IE.Exporter) +- [https://github.com/xin-lai/aspnetcore-docker](https://github.com/xin-lai/aspnetcore-docker) \ No newline at end of file diff --git a/docs/5.Dynamic Export.md b/docs/5.Dynamic Export.md new file mode 100644 index 00000000..b67ee96b --- /dev/null +++ b/docs/5.Dynamic Export.md @@ -0,0 +1,56 @@ +## Dynamic export of table headers + +The following code snippet allows us to export the Excel table header, we can pass it as an array to generate our dynamic table header, and at the same time call it as `exporter.ExportHeaderAsByteArray` and export our `result` of type `byte[]` to the specified filepath(path ). + +``` +public async Task ExportHeaderAsByteArrayWithItems_Test() +{ + IExcelExporter exporter = new ExcelExporter(); + var arr = new[] { "Name1", "Name2", "Name3", "Name4", "Name5", "Name6" }; + var sheetName = "Test"; + var result = await exporter.ExportHeaderAsByteArray(arr, sheetName); + + result.ToExcelExportFileInfo(filePath); +} +``` + + +## DDataTable Dynamic Export + +In this export `exportDatas` is a List, but in the following code snippet we have converted it to a DataTable and exported it, `maxRowNumberOnASheet` is the number of rows each sheet holds. + +``` +public async Task LargeDataDynamicExport_Test() +{ + IExcelExporter exporter = new ExcelExporter(); + + var dt = new DataTable(); + //Create columns with column names and type names + dt.Columns.Add("Text", Type.GetType("System.String")); + dt.Columns.Add("Name", Type.GetType("System.String")); + dt.Columns.Add("Number", Type.GetType("System.Decimal")); + dt = EntityToDataTable(dt, exportDatas); + + var result = await exporter.Export(filePath, dt, maxRowNumberOnASheet: 100000); +} +``` + +## ExpandoObject Export + +`ExpandoObject` is a dynamic object that is part of the Dynamic Language (DLR). With `ExpandoObject` we can add and remove members of its instances at runtime, and of course set and get these values. In IE we support `ExpandoObject` objects, so here we can use `ExpandoObject` to implement our dynamic export behavior. + +``` +public async Task ExportAsByteArraySupportDynamicType_Test() +{ + IExporter exporter = new ExcelExporter(); + + var source = GenFu.GenFu.ListOf(); + string fields = "text,number,name"; + var shapedData = source.ShapeData(fields) as ICollection; + + var result = await exporter.ExportAsByteArray(shapedData); + File.WriteAllBytes(filePath, result); +} +``` + +In addition, for ExpandoObject export process for table headers and other information, you can use filters to achieve, please refer to the tutorial article on the use of filters for details. \ No newline at end of file