Browse Source

feat(exporter): 增加数据导入导出功能

pull/1013/head
colin 1 year ago
parent
commit
a5b2b09393
  1. 3
      aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.Application.Contracts/FodyWeavers.xml
  2. 30
      aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.Application.Contracts/FodyWeavers.xsd
  3. 20
      aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.Application.Contracts/LINGYUN.Abp.Exporter.Application.Contracts.csproj
  4. 9
      aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.Application.Contracts/LINGYUN/Abp/Exporter/AbpExporterApplicationContractsModule.cs
  5. 19
      aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.Application.Contracts/LINGYUN/Abp/Exporter/IExporterAppService.cs
  6. 17
      aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.Application.Contracts/LINGYUN/Abp/Exporter/IImporterAppService.cs
  7. 103
      aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.Application.Contracts/README.md
  8. 3
      aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.Application/FodyWeavers.xml
  9. 30
      aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.Application/FodyWeavers.xsd
  10. 25
      aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.Application/LINGYUN.Abp.Exporter.Application.csproj
  11. 12
      aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.Application/LINGYUN/Abp/Exporter/AbpExporterApplicationModule.cs
  12. 50
      aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.Application/LINGYUN/Abp/Exporter/ExporterAppService.cs
  13. 47
      aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.Application/LINGYUN/Abp/Exporter/ImporterAppService.cs
  14. 3
      aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.Core/FodyWeavers.xml
  15. 30
      aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.Core/FodyWeavers.xsd
  16. 30
      aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.Core/LINGYUN.Abp.Exporter.Core.csproj
  17. 31
      aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.Core/LINGYUN/Abp/Exporter/AbpExporterCoreModule.cs
  18. 9
      aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.Core/LINGYUN/Abp/Exporter/ExporterErrorCodes.cs
  19. 20
      aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.Core/LINGYUN/Abp/Exporter/IExporterProvider.cs
  20. 19
      aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.Core/LINGYUN/Abp/Exporter/IImporterProvider.cs
  21. 8
      aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.Core/LINGYUN/Abp/Exporter/Localization/AbpExporterResource.cs
  22. 6
      aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.Core/LINGYUN/Abp/Exporter/Localization/Resources/en.json
  23. 6
      aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.Core/LINGYUN/Abp/Exporter/Localization/Resources/zh-Hans.json
  24. 17
      aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.Core/LINGYUN/Abp/Exporter/NullExporterProvider.cs
  25. 18
      aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.Core/LINGYUN/Abp/Exporter/NullImporterProvider.cs
  26. 76
      aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.Core/README.md
  27. 3
      aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.HttpApi/FodyWeavers.xml
  28. 24
      aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.HttpApi/LINGYUN.Abp.Exporter.HttpApi.csproj
  29. 12
      aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.HttpApi/LINGYUN/Abp/Exporter/AbpExporterHttpApiModule.cs
  30. 22
      aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.HttpApi/LINGYUN/Abp/Exporter/ExporterController.cs
  31. 24
      aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.HttpApi/LINGYUN/Abp/Exporter/ImporterController.cs
  32. 3
      aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.MagicodesIE.Excel/FodyWeavers.xml
  33. 26
      aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.MagicodesIE.Excel/LINGYUN.Abp.Exporter.MagicodesIE.Excel.csproj
  34. 30
      aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.MagicodesIE.Excel/LINGYUN/Abp/Exporter/AbpExporterMagicodesIEExcelModule.cs
  35. 31
      aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.MagicodesIE.Excel/LINGYUN/Abp/Exporter/AbpExporterMagicodesIEExcelOptions.cs
  36. 23
      aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.MagicodesIE.Excel/LINGYUN/Abp/Exporter/AbpImportHelper.cs
  37. 62
      aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.MagicodesIE.Excel/LINGYUN/Abp/Exporter/MagicodesIEExcelExporterProvider.cs
  38. 74
      aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.MagicodesIE.Excel/LINGYUN/Abp/Exporter/MagicodesIEExcelImporterProvider.cs
  39. 41
      aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.MagicodesIE.Excel/README.md
  40. 3
      aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.MiniExcel/FodyWeavers.xml
  41. 30
      aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.MiniExcel/FodyWeavers.xsd
  42. 25
      aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.MiniExcel/LINGYUN.Abp.Exporter.MiniExcel.csproj
  43. 22
      aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.MiniExcel/LINGYUN/Abp/Exporter/AbpExporterMiniExcelModule.cs
  44. 25
      aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.MiniExcel/LINGYUN/Abp/Exporter/AbpExporterMiniExcelOptions.cs
  45. 41
      aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.MiniExcel/LINGYUN/Abp/Exporter/MiniExcelExporterProvider.cs
  46. 35
      aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.MiniExcel/LINGYUN/Abp/Exporter/MiniExcelImporterProvider.cs
  47. 46
      aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.MiniExcel/README.md

3
aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.Application.Contracts/FodyWeavers.xml

@ -0,0 +1,3 @@
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
<ConfigureAwait ContinueOnCapturedContext="false" />
</Weavers>

30
aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.Application.Contracts/FodyWeavers.xsd

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. -->
<xs:element name="Weavers">
<xs:complexType>
<xs:all>
<xs:element name="ConfigureAwait" minOccurs="0" maxOccurs="1">
<xs:complexType>
<xs:attribute name="ContinueOnCapturedContext" type="xs:boolean" />
</xs:complexType>
</xs:element>
</xs:all>
<xs:attribute name="VerifyAssembly" type="xs:boolean">
<xs:annotation>
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="VerifyIgnoreCodes" type="xs:string">
<xs:annotation>
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="GenerateXsd" type="xs:boolean">
<xs:annotation>
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:complexType>
</xs:element>
</xs:schema>

20
aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.Application.Contracts/LINGYUN.Abp.Exporter.Application.Contracts.csproj

@ -0,0 +1,20 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\..\..\configureawait.props" />
<Import Project="..\..\..\..\common.props" />
<PropertyGroup>
<TargetFrameworks>netstandard2.0;netstandard2.1;net8.0</TargetFrameworks>
<AssemblyName>LINGYUN.Abp.Exporter.Application.Contracts</AssemblyName>
<PackageId>LINGYUN.Abp.Exporter.Application.Contracts</PackageId>
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
<RootNamespace />
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Volo.Abp.Ddd.Application.Contracts" />
</ItemGroup>
</Project>

9
aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.Application.Contracts/LINGYUN/Abp/Exporter/AbpExporterApplicationContractsModule.cs

@ -0,0 +1,9 @@
using Volo.Abp.Application;
using Volo.Abp.Modularity;
namespace LINGYUN.Abp.Exporter;
[DependsOn(typeof(AbpDddApplicationContractsModule))]
public class AbpExporterApplicationContractsModule : AbpModule
{
}

19
aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.Application.Contracts/LINGYUN/Abp/Exporter/IExporterAppService.cs

@ -0,0 +1,19 @@
using System.Threading.Tasks;
using Volo.Abp.Content;
namespace LINGYUN.Abp.Exporter;
/// <summary>
/// 数据导出服务接口
/// </summary>
/// <typeparam name="TEntityExportDto">导出的实体数据传输对象</typeparam>
/// <typeparam name="TEntityListGetInput">实体数据过滤数据对象</typeparam>
public interface IExporterAppService<TEntityExportDto, TEntityListGetInput>
where TEntityExportDto : class, new()
{
/// <summary>
/// 导出数据(默认实现Excel)
/// </summary>
/// <param name="input">数据过滤条件</param>
/// <returns></returns>
Task<IRemoteStreamContent> ExportAsync(TEntityListGetInput input);
}

17
aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.Application.Contracts/LINGYUN/Abp/Exporter/IImporterAppService.cs

@ -0,0 +1,17 @@
using System.Threading.Tasks;
namespace LINGYUN.Abp.Exporter;
/// <summary>
/// 数据导入服务接口
/// </summary>
/// <typeparam name="TEntityImportDto"></typeparam>
public interface IImporterAppService<TEntityImportDto>
where TEntityImportDto: class, new()
{
/// <summary>
/// 导入数据(默认从Excel)
/// </summary>
/// <param name="input">导入的数据文件流</param>
/// <returns></returns>
Task ImportAsync(TEntityImportDto input);
}

103
aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.Application.Contracts/README.md

@ -0,0 +1,103 @@
# LINGYUN.Abp.Exporter.Application.Contracts
数据导出/导入接口契约层,定义通用的数据导入/导入服务接口
## 配置使用
> 配置模块依赖
```csharp
[DependsOn(
typeof(AbpExporterApplicationContractsModule)
)]
public class YouProjectModule : AbpModule
{
}
```
> 定义导出类型
```csharp
public class DemoClassDto
{
public string Name { get; set; }
public string Remarks { get; set; }
public DemoClassDto()
{
}
}
```
> 定义导入类型
```csharp
public class DemoClassImportInput
{
[Required]
public IRemoteStreamContent Content { get; set; }
public DemoClassImportInput()
{
}
}
```
> 定义数据过滤类型
```csharp
public class DemoClassExportListInput
{
public string Filter { get; set; }
[Required]
public string FileName { get; set; }
public DemoClassExportListInput()
{
}
}
```
> 导出数据
```csharp
public class ExportDemoClassExportAppService : IExporterAppService<DemoClassDto, DemoClassExportListInput>
{
private readonly IExporterProvider _exporterProvider;
public ExportDemoClassExportAppService(IExporterProvider exporterProvider)
{
_exporterProvider = exporterProvider;
}
public async virtual Task<IRemoteStreamContent> ExportAsync(DemoClassExportListInput input)
{
var dtos = 通过仓储接口查询数据列表;
var stream = await _exporterProvider.ExportAsync(dtos);
return new RemoteStreamContent(stream, input.FileName);
}
}
```
> 导入数据
```csharp
public class ExportDemoClassImportAppService : IImporterAppService<DemoClassImportInput>
{
private readonly IImporterProvider _importerProvider;
public ExportDemoClassImportAppService(IImporterProvider importerProvider)
{
_importerProvider = importerProvider;
}
public async virtual Task ImportAsync(DemoClassImportInput input)
{
var stream = input.Content.GetStream();
var demos = await _importerProvider.ImportAsync<DemoClass>(stream);
// 其他操作
}
}
```

3
aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.Application/FodyWeavers.xml

@ -0,0 +1,3 @@
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
<ConfigureAwait ContinueOnCapturedContext="false" />
</Weavers>

30
aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.Application/FodyWeavers.xsd

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. -->
<xs:element name="Weavers">
<xs:complexType>
<xs:all>
<xs:element name="ConfigureAwait" minOccurs="0" maxOccurs="1">
<xs:complexType>
<xs:attribute name="ContinueOnCapturedContext" type="xs:boolean" />
</xs:complexType>
</xs:element>
</xs:all>
<xs:attribute name="VerifyAssembly" type="xs:boolean">
<xs:annotation>
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="VerifyIgnoreCodes" type="xs:string">
<xs:annotation>
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="GenerateXsd" type="xs:boolean">
<xs:annotation>
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:complexType>
</xs:element>
</xs:schema>

25
aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.Application/LINGYUN.Abp.Exporter.Application.csproj

@ -0,0 +1,25 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\..\..\configureawait.props" />
<Import Project="..\..\..\..\common.props" />
<PropertyGroup>
<TargetFrameworks>netstandard2.0;netstandard2.1;net8.0</TargetFrameworks>
<AssemblyName>LINGYUN.Abp.Exporter.Application</AssemblyName>
<PackageId>LINGYUN.Abp.Exporter.Application</PackageId>
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
<RootNamespace />
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Volo.Abp.Ddd.Application" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\LINGYUN.Abp.Exporter.Application.Contracts\LINGYUN.Abp.Exporter.Application.Contracts.csproj" />
<ProjectReference Include="..\LINGYUN.Abp.Exporter.Core\LINGYUN.Abp.Exporter.Core.csproj" />
</ItemGroup>
</Project>

12
aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.Application/LINGYUN/Abp/Exporter/AbpExporterApplicationModule.cs

@ -0,0 +1,12 @@
using Volo.Abp.Application;
using Volo.Abp.Modularity;
namespace LINGYUN.Abp.Exporter;
[DependsOn(
typeof(AbpDddApplicationModule),
typeof(AbpExporterCoreModule),
typeof(AbpExporterApplicationContractsModule))]
public class AbpExporterApplicationModule : AbpModule
{
}

50
aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.Application/LINGYUN/Abp/Exporter/ExporterAppService.cs

@ -0,0 +1,50 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using Volo.Abp.Application.Services;
using Volo.Abp.Content;
namespace LINGYUN.Abp.Exporter;
public abstract class ExporterAppService<TEntity, TEntityExportDto, TEntityListGetInput> : ApplicationService, IExporterAppService<TEntityExportDto, TEntityListGetInput>
where TEntityExportDto : class, new()
{
private readonly IExporterProvider _exporterProvider;
protected ExporterAppService(IExporterProvider exporterProvider)
{
_exporterProvider = exporterProvider;
}
public async virtual Task<IRemoteStreamContent> ExportAsync(TEntityListGetInput input)
{
var fileName = GetExportFileName(input);
var entities = await GetListAsync(input);
var entitieDtoList = MapEntitiesToDto(entities);
var stream = await _exporterProvider.ExportAsync(entitieDtoList);
return new RemoteStreamContent(stream, fileName);
}
/// <summary>
/// 实现方法用以返回导出文件名
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
protected abstract string GetExportFileName(TEntityListGetInput input);
/// <summary>
/// 实现方法用以查询需要导出的实体列表
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
protected abstract Task<List<TEntity>> GetListAsync(TEntityListGetInput input);
/// <summary>
/// 实现方法用以实体数据传输对象映射
/// </summary>
/// <param name="entities"></param>
/// <returns></returns>
protected virtual List<TEntityExportDto> MapEntitiesToDto(List<TEntity> entities)
{
return ObjectMapper.Map<List<TEntity>, List<TEntityExportDto>>(entities);
}
}

47
aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.Application/LINGYUN/Abp/Exporter/ImporterAppService.cs

@ -0,0 +1,47 @@
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
using Volo.Abp.Application.Services;
namespace LINGYUN.Abp.Exporter;
public abstract class ImporterAppService<TEntity, TEntityImportDto> : ApplicationService, IImporterAppService<TEntityImportDto>
where TEntityImportDto : class, new()
{
private readonly IImporterProvider _importerProvider;
protected ImporterAppService(IImporterProvider importerProvider)
{
_importerProvider = importerProvider;
}
public async virtual Task ImportAsync(TEntityImportDto input)
{
var stream = await GetImportStream(input);
var entitieDtoList = await _importerProvider.ImportAsync<TEntityImportDto>(stream);
var entities = MapDtoToEntities([.. entitieDtoList]);
await SaveManyEntities(entities);
}
/// <summary>
/// 实现方法用以从导入数据中提取文件流
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
protected abstract Task<Stream> GetImportStream(TEntityImportDto input);
/// <summary>
/// 实现方法用以保存实体列表到持久化设施
/// </summary>
/// <param name="entities"></param>
/// <returns></returns>
protected abstract Task SaveManyEntities(ICollection<TEntity> entities);
/// <summary>
/// 实现方法用以实体数据传输对象映射
/// </summary>
/// <param name="entitieDtoList"></param>
/// <returns></returns>
protected virtual List<TEntity> MapDtoToEntities(List<TEntityImportDto> entitieDtoList)
{
return ObjectMapper.Map<List<TEntityImportDto>, List<TEntity>>(entitieDtoList);
}
}

3
aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.Core/FodyWeavers.xml

@ -0,0 +1,3 @@
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
<ConfigureAwait />
</Weavers>

30
aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.Core/FodyWeavers.xsd

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. -->
<xs:element name="Weavers">
<xs:complexType>
<xs:all>
<xs:element name="ConfigureAwait" minOccurs="0" maxOccurs="1">
<xs:complexType>
<xs:attribute name="ContinueOnCapturedContext" type="xs:boolean" />
</xs:complexType>
</xs:element>
</xs:all>
<xs:attribute name="VerifyAssembly" type="xs:boolean">
<xs:annotation>
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="VerifyIgnoreCodes" type="xs:string">
<xs:annotation>
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="GenerateXsd" type="xs:boolean">
<xs:annotation>
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:complexType>
</xs:element>
</xs:schema>

30
aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.Core/LINGYUN.Abp.Exporter.Core.csproj

@ -0,0 +1,30 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\..\..\configureawait.props" />
<Import Project="..\..\..\..\common.props" />
<PropertyGroup>
<TargetFrameworks>netstandard2.0;netstandard2.1;net8.0</TargetFrameworks>
<AssemblyName>LINGYUN.Abp.Exporter.Core</AssemblyName>
<PackageId>LINGYUN.Abp.Exporter.Core</PackageId>
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
<Nullable>enable</Nullable>
<RootNamespace />
</PropertyGroup>
<ItemGroup>
<None Remove="LINGYUN\Abp\Exporter\Localization\Resources\zh-Hans.json" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="LINGYUN\Abp\Exporter\Localization\Resources\en.json" />
<EmbeddedResource Include="LINGYUN\Abp\Exporter\Localization\Resources\zh-Hans.json" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Volo.Abp.Localization" />
</ItemGroup>
</Project>

31
aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.Core/LINGYUN/Abp/Exporter/AbpExporterCoreModule.cs

@ -0,0 +1,31 @@
using LINGYUN.Abp.Exporter.Localization;
using Volo.Abp.Localization;
using Volo.Abp.Localization.ExceptionHandling;
using Volo.Abp.Modularity;
using Volo.Abp.VirtualFileSystem;
namespace LINGYUN.Abp.Exporter;
[DependsOn(typeof(AbpLocalizationModule))]
public class AbpExporterCoreModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
Configure<AbpVirtualFileSystemOptions>(options =>
{
options.FileSets.AddEmbedded<AbpExporterCoreModule>();
});
Configure<AbpLocalizationOptions>(options =>
{
options.Resources
.Add<AbpExporterResource>("en")
.AddVirtualJson("/LINGYUN/Abp/Exporter/Localization/Resources");
});
Configure<AbpExceptionLocalizationOptions>(options =>
{
options.MapCodeNamespace(ExporterErrorCodes.Namespace, typeof(AbpExporterResource));
});
}
}

9
aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.Core/LINGYUN/Abp/Exporter/ExporterErrorCodes.cs

@ -0,0 +1,9 @@
namespace LINGYUN.Abp.Exporter;
public static class ExporterErrorCodes
{
public const string Namespace = "AbpExporter";
/// <summary>
/// 导入数据过程中出现一些错误,请检查数据有效性!
/// </summary>
public const string ImportDataError = Namespace + ":010001";
}

20
aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.Core/LINGYUN/Abp/Exporter/IExporterProvider.cs

@ -0,0 +1,20 @@
using System.Collections.Generic;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
namespace LINGYUN.Abp.Exporter;
/// <summary>
/// 数据导出提供者
/// </summary>
public interface IExporterProvider
{
/// <summary>
/// 数据导出
/// </summary>
/// <param name="data">导出数据</param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task<Stream> ExportAsync<T>(ICollection<T> data, CancellationToken cancellationToken = default)
where T : class, new();
}

19
aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.Core/LINGYUN/Abp/Exporter/IImporterProvider.cs

@ -0,0 +1,19 @@
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
namespace LINGYUN.Abp.Exporter;
/// <summary>
/// 数据导入提供者
/// </summary>
public interface IImporterProvider
{
/// <summary>
/// 数据导入
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="stream"></param>
/// <returns></returns>
Task<IReadOnlyCollection<T>> ImportAsync<T>(Stream stream)
where T : class, new();
}

8
aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.Core/LINGYUN/Abp/Exporter/Localization/AbpExporterResource.cs

@ -0,0 +1,8 @@
using Volo.Abp.Localization;
namespace LINGYUN.Abp.Exporter.Localization;
[LocalizationResourceName("AbpExporter")]
public class AbpExporterResource
{
}

6
aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.Core/LINGYUN/Abp/Exporter/Localization/Resources/en.json

@ -0,0 +1,6 @@
{
"culture": "en",
"texts": {
"AbpExporter:010001": "There were some errors during the data import process. Please check the validity of the data!"
}
}

6
aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.Core/LINGYUN/Abp/Exporter/Localization/Resources/zh-Hans.json

@ -0,0 +1,6 @@
{
"culture": "zh-Hans",
"texts": {
"AbpExporter:010001": "导入数据过程中出现一些错误,请检查数据有效性!"
}
}

17
aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.Core/LINGYUN/Abp/Exporter/NullExporterProvider.cs

@ -0,0 +1,17 @@
using System.Collections.Generic;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using Volo.Abp.DependencyInjection;
namespace LINGYUN.Abp.Exporter;
[Dependency(TryRegister = true)]
public class NullExporterProvider : IExporterProvider, ISingletonDependency
{
private readonly static Stream _nullStreamCache = Stream.Null;
public Task<Stream> ExportAsync<T>(ICollection<T> data, CancellationToken cancellationToken = default) where T : class, new()
{
return Task.FromResult(_nullStreamCache);
}
}

18
aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.Core/LINGYUN/Abp/Exporter/NullImporterProvider.cs

@ -0,0 +1,18 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
using Volo.Abp.DependencyInjection;
namespace LINGYUN.Abp.Exporter;
[Dependency(TryRegister = true)]
public class NullImporterProvider : IImporterProvider, ISingletonDependency
{
public Task<IReadOnlyCollection<T>> ImportAsync<T>(Stream stream) where T : class, new()
{
IReadOnlyCollection<T> empty = Array.Empty<T>();
return Task.FromResult(empty);
}
}

76
aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.Core/README.md

@ -0,0 +1,76 @@
# LINGYUN.Abp.Exporter.Core
数据导出/导入核心层
## 配置使用
```csharp
[DependsOn(
typeof(AbpExporterCoreModule)
)]
public class YouProjectModule : AbpModule
{
}
```
> 导出数据
```csharp
public class ExportDemoClass
{
private readonly IExporterProvider _exporterProvider;
public ExportDemoClass(IExporterProvider exporterProvider)
{
_exporterProvider = exporterProvider;
}
public async virtual Task<IRemoteStreamContent> ExportAsync()
{
var dataItems = new object[]
{
new
{
Name = "name1",
Remakrs = "remarks1"
}
};
var stream = await _exporterProvider.ExportAsync(dataItems);
return new RemoteStreamContent(stream, "demo.xlsx");
}
}
```
> 导入数据
```csharp
public class ImportDemoClass
{
private readonly IImporterProvider _importerProvider;
public ImportDemoClass(IImporterProvider importerProvider)
{
_importerProvider = importerProvider;
}
public async virtual Task ImportAsync(Stream stream)
{
var demos = await _importerProvider.ImportAsync<DemoClass>(stream);
// 其他操作
}
}
public class DemoClass
{
public string Name { get; set; }
public string Remarks { get; set; }
public DemoClass()
{
}
}
```

3
aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.HttpApi/FodyWeavers.xml

@ -0,0 +1,3 @@
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
<ConfigureAwait ContinueOnCapturedContext="false" />
</Weavers>

24
aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.HttpApi/LINGYUN.Abp.Exporter.HttpApi.csproj

@ -0,0 +1,24 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\..\..\configureawait.props" />
<Import Project="..\..\..\..\common.props" />
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<AssemblyName>LINGYUN.Abp.Exporter.HttpApi</AssemblyName>
<PackageId>LINGYUN.Abp.Exporter.HttpApi</PackageId>
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
<RootNamespace />
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Volo.Abp.AspNetCore.Mvc" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\LINGYUN.Abp.Exporter.Application.Contracts\LINGYUN.Abp.Exporter.Application.Contracts.csproj" />
</ItemGroup>
</Project>

12
aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.HttpApi/LINGYUN/Abp/Exporter/AbpExporterHttpApiModule.cs

@ -0,0 +1,12 @@
using Volo.Abp.Application;
using Volo.Abp.Modularity;
namespace LINGYUN.Abp.Exporter;
[DependsOn(
typeof(AbpDddApplicationModule),
typeof(AbpExporterApplicationContractsModule))]
public class AbpExporterHttpApiModule : AbpModule
{
}

22
aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.HttpApi/LINGYUN/Abp/Exporter/ExporterController.cs

@ -0,0 +1,22 @@
using Microsoft.AspNetCore.Mvc;
using System.Threading.Tasks;
using Volo.Abp.AspNetCore.Mvc;
using Volo.Abp.Content;
namespace LINGYUN.Abp.Exporter;
public abstract class ExporterController<TEntityExportDto, TEntityListGetInput> : AbpControllerBase, IExporterAppService<TEntityExportDto, TEntityListGetInput>
where TEntityExportDto : class, new()
{
private readonly IExporterAppService<TEntityExportDto, TEntityListGetInput> _exportService;
protected ExporterController(IExporterAppService<TEntityExportDto, TEntityListGetInput> exportService)
{
_exportService = exportService;
}
[HttpGet]
[Route("export")]
public virtual Task<IRemoteStreamContent> ExportAsync(TEntityListGetInput input)
{
return _exportService.ExportAsync(input);
}
}

24
aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.HttpApi/LINGYUN/Abp/Exporter/ImporterController.cs

@ -0,0 +1,24 @@
using Microsoft.AspNetCore.Mvc;
using System.Threading.Tasks;
using Volo.Abp.AspNetCore.Mvc;
using Volo.Abp.Content;
namespace LINGYUN.Abp.Exporter;
public abstract class ImporterController<TEntityImportDto> : AbpControllerBase, IImporterAppService<TEntityImportDto>
where TEntityImportDto : class, new()
{
private readonly IImporterAppService<TEntityImportDto> _importService;
protected ImporterController(IImporterAppService<TEntityImportDto> importService)
{
_importService = importService;
}
[HttpPost]
[Route("import")]
public virtual Task ImportAsync(IRemoteStreamContent input)
{
return _importService.ImportAsync(input);
}
}

3
aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.MagicodesIE.Excel/FodyWeavers.xml

@ -0,0 +1,3 @@
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
<ConfigureAwait ContinueOnCapturedContext="false" />
</Weavers>

26
aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.MagicodesIE.Excel/LINGYUN.Abp.Exporter.MagicodesIE.Excel.csproj

@ -0,0 +1,26 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\..\..\configureawait.props" />
<Import Project="..\..\..\..\common.props" />
<PropertyGroup>
<TargetFrameworks>netstandard2.0;netstandard2.1;net8.0</TargetFrameworks>
<AssemblyName>LINGYUN.Abp.Exporter.MagicodesIE.Excel</AssemblyName>
<PackageId>LINGYUN.Abp.Exporter.MagicodesIE.Excel</PackageId>
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
<Nullable>enable</Nullable>
<RootNamespace />
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Volo.Abp.Json" />
<PackageReference Include="Magicodes.IE.Excel" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\LINGYUN.Abp.Exporter.Core\LINGYUN.Abp.Exporter.Core.csproj" />
</ItemGroup>
</Project>

30
aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.MagicodesIE.Excel/LINGYUN/Abp/Exporter/AbpExporterMagicodesIEExcelModule.cs

@ -0,0 +1,30 @@
using Magicodes.ExporterAndImporter.Core;
using Magicodes.ExporterAndImporter.Excel;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Volo.Abp.Modularity;
namespace LINGYUN.Abp.Exporter.MiniExcel;
[DependsOn(typeof(AbpExporterCoreModule))]
public class AbpExporterMagicodesIEExcelModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
context.Services.AddScoped<IExcelExporter, ExcelExporter>();
context.Services.AddScoped<IExcelImporter, ExcelImporter>();
context.Services.AddScoped<IExportFileByTemplate, ExcelExporter>();
context.Services.Replace(
ServiceDescriptor.Transient(
typeof(IExporterProvider),
typeof(MagicodesIEExcelExporterProvider)));
context.Services.Replace(
ServiceDescriptor.Transient(
typeof(IImporterProvider),
typeof(MagicodesIEExcelImporterProvider)));
}
}

31
aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.MagicodesIE.Excel/LINGYUN/Abp/Exporter/AbpExporterMagicodesIEExcelOptions.cs

@ -0,0 +1,31 @@
using Magicodes.ExporterAndImporter.Excel;
using System;
using System.Collections.Generic;
namespace LINGYUN.Abp.Exporter;
public class AbpExporterMagicodesIEExcelOptions
{
/// <summary>
/// 数据导出设置
/// </summary>
public IDictionary<Type, Action<ExcelExporterAttribute>> ExportSettingMapping { get; }
/// <summary>
/// 数据导入设置
/// </summary>
public IDictionary<Type, Action<ExcelImporterAttribute>> ImportSettingMapping { get; }
public AbpExporterMagicodesIEExcelOptions()
{
ExportSettingMapping = new Dictionary<Type, Action<ExcelExporterAttribute>>();
ImportSettingMapping = new Dictionary<Type, Action<ExcelImporterAttribute>>();
}
public void MapExportSetting(Type dataType, Action<ExcelExporterAttribute> exportSettingsSetup)
{
ExportSettingMapping[dataType] = exportSettingsSetup;
}
public void MapImportSetting(Type dataType, Action<ExcelImporterAttribute> importSettingsSetup)
{
ImportSettingMapping[dataType] = importSettingsSetup;
}
}

23
aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.MagicodesIE.Excel/LINGYUN/Abp/Exporter/AbpImportHelper.cs

@ -0,0 +1,23 @@
using Magicodes.ExporterAndImporter.Excel;
using Magicodes.ExporterAndImporter.Excel.Utility;
using System;
using System.IO;
namespace LINGYUN.Abp.Exporter;
public class AbpImportHelper<T> : ImportHelper<T> where T : class, new()
{
public AbpImportHelper(string? filePath = null, string? labelingFilePath = null)
: base(filePath, labelingFilePath)
{
}
public AbpImportHelper(Stream stream, Stream? labelingFileStream)
: base(stream, labelingFileStream)
{
}
internal void ConfigureExcelImportSettings(Action<ExcelImporterAttribute>? excelImportSettingsConfig)
{
excelImportSettingsConfig?.Invoke(ExcelImporterSettings);
}
}

62
aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.MagicodesIE.Excel/LINGYUN/Abp/Exporter/MagicodesIEExcelExporterProvider.cs

@ -0,0 +1,62 @@
using Magicodes.ExporterAndImporter.Excel;
using Magicodes.ExporterAndImporter.Excel.Utility;
using Microsoft.Extensions.Options;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Volo.Abp.DependencyInjection;
namespace LINGYUN.Abp.Exporter;
public class MagicodesIEExcelExporterProvider : IExporterProvider, ITransientDependency
{
private readonly AbpExporterMagicodesIEExcelOptions _options;
private readonly IExcelExporter _excelExporter;
public MagicodesIEExcelExporterProvider(IOptions<AbpExporterMagicodesIEExcelOptions> options)
{
_options = options.Value;
}
public async virtual Task<Stream> ExportAsync<T>(ICollection<T> data, CancellationToken cancellationToken = default)
where T : class, new()
{
var fileBytes = new List<byte>();
var exportHelper = new ExportHelper<T>();
// 由于Microsoft.IE.Excel官方此接口未暴露用户配置,做一次转换
if (_options.ExportSettingMapping.TryGetValue(typeof(T), out var exportSetting))
{
exportSetting?.Invoke(exportHelper.ExcelExporterSettings);
}
if (exportHelper.ExcelExporterSettings.MaxRowNumberOnASheet > 0 && data.Count > exportHelper.ExcelExporterSettings.MaxRowNumberOnASheet)
{
using (exportHelper.CurrentExcelPackage)
{
var num = data.Count / exportHelper.ExcelExporterSettings.MaxRowNumberOnASheet + ((data.Count % exportHelper.ExcelExporterSettings.MaxRowNumberOnASheet > 0) ? 1 : 0);
for (var i = 0; i < num; i++)
{
var dataItems2 = data.Skip(i * exportHelper.ExcelExporterSettings.MaxRowNumberOnASheet).Take(exportHelper.ExcelExporterSettings.MaxRowNumberOnASheet).ToList();
exportHelper.AddExcelWorksheet();
exportHelper.Export(dataItems2);
}
fileBytes.AddRange(await exportHelper.CurrentExcelPackage.GetAsByteArrayAsync());
}
}
else
{
using var excelPackage2 = exportHelper.Export(data);
fileBytes.AddRange(await excelPackage2.GetAsByteArrayAsync());
}
var memoryStream = new MemoryStream([.. fileBytes]);
memoryStream.Seek(0, SeekOrigin.Begin);
return memoryStream;
}
}

74
aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.MagicodesIE.Excel/LINGYUN/Abp/Exporter/MagicodesIEExcelImporterProvider.cs

@ -0,0 +1,74 @@
using Magicodes.ExporterAndImporter.Core.Models;
using Magicodes.ExporterAndImporter.Excel;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using Microsoft.Extensions.Options;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.IO;
using System.Threading.Tasks;
using Volo.Abp;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Json;
namespace LINGYUN.Abp.Exporter;
public class MagicodesIEExcelImporterProvider : IImporterProvider, ITransientDependency
{
public ILogger<MagicodesIEExcelImporterProvider> Logger { protected get; set; }
private readonly AbpExporterMagicodesIEExcelOptions _options;
private readonly IJsonSerializer _jsonSerializer;
private readonly IExcelImporter _excelImporter;
public MagicodesIEExcelImporterProvider(
IJsonSerializer jsonSerializer,
IExcelImporter excelImporter,
IOptions<AbpExporterMagicodesIEExcelOptions> options)
{
_jsonSerializer = jsonSerializer;
_excelImporter = excelImporter;
_options = options.Value;
Logger = NullLogger<MagicodesIEExcelImporterProvider>.Instance;
}
public async virtual Task<IReadOnlyCollection<T>> ImportAsync<T>(Stream stream) where T : class, new()
{
using var importHelper = new AbpImportHelper<T>(stream, null);
// 由于Microsoft.IE.Excel官方此接口未暴露用户配置,做一次转换
if (_options.ImportSettingMapping.TryGetValue(typeof(T), out var importSetting))
{
importHelper.ConfigureExcelImportSettings(importSetting);
}
var importResult = await importHelper.Import(null, null);
ThrowImportException(importResult);
return importResult.Data.ToImmutableList();
}
protected virtual void ThrowImportException<T>(ImportResult<T> importResult) where T : class, new()
{
if (importResult.HasError)
{
if (importResult.RowErrors.Count > 0)
{
var errorJson = _jsonSerializer.Serialize(importResult.RowErrors);
Logger.LogWarning("Row validation error occurred during data import process, details: {errorJson}", errorJson);
}
if (importResult.TemplateErrors.Count > 0)
{
var errorJson = _jsonSerializer.Serialize(importResult.TemplateErrors);
Logger.LogWarning("Template validation error occurred during data import process, details: {errorJson}", errorJson);
}
throw new BusinessException(
code: ExporterErrorCodes.ImportDataError,
innerException: importResult.Exception);
}
}
}

41
aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.MagicodesIE.Excel/README.md

@ -0,0 +1,41 @@
# LINGYUN.Abp.Exporter.MagicodesIE.Excel
数据导出接口的 [Magicodes.IE.Excel](https://github.com/dotnetcore/Magicodes.IE) 实现
Import and export general library, support Dto import and export, template export, fancy export and dynamic export, support Excel, Csv, Word, Pdf and Html.
详情请参考 [Magicodes.IE.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)
## 配置使用
```csharp
[DependsOn(
typeof(AbpExporterMagicodesIEExcelModule)
)]
public class YouProjectModule : AbpModule
{
Configure<AbpExporterMagicodesIEExcelOptions>(options =>
{
// 配置类型数据导出
options.MapExportSetting(typeof(DemoClass), config =>
{
// 表头位置从第二行开始
config.HeaderRowIndex = 2;
// 其他配置
});
});
}
public class DemoClass
{
public string Name { get; set; }
public string Remarks { get; set; }
public DemoClass()
{
}
}
```

3
aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.MiniExcel/FodyWeavers.xml

@ -0,0 +1,3 @@
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
<ConfigureAwait ContinueOnCapturedContext="false" />
</Weavers>

30
aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.MiniExcel/FodyWeavers.xsd

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. -->
<xs:element name="Weavers">
<xs:complexType>
<xs:all>
<xs:element name="ConfigureAwait" minOccurs="0" maxOccurs="1">
<xs:complexType>
<xs:attribute name="ContinueOnCapturedContext" type="xs:boolean" />
</xs:complexType>
</xs:element>
</xs:all>
<xs:attribute name="VerifyAssembly" type="xs:boolean">
<xs:annotation>
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="VerifyIgnoreCodes" type="xs:string">
<xs:annotation>
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="GenerateXsd" type="xs:boolean">
<xs:annotation>
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:complexType>
</xs:element>
</xs:schema>

25
aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.MiniExcel/LINGYUN.Abp.Exporter.MiniExcel.csproj

@ -0,0 +1,25 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\..\..\configureawait.props" />
<Import Project="..\..\..\..\common.props" />
<PropertyGroup>
<TargetFrameworks>netstandard2.0;netstandard2.1;net8.0</TargetFrameworks>
<AssemblyName>LINGYUN.Abp.Exporter.MiniExcel</AssemblyName>
<PackageId>LINGYUN.Abp.Exporter.MiniExcel</PackageId>
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
<Nullable>enable</Nullable>
<RootNamespace />
</PropertyGroup>
<ItemGroup>
<PackageReference Include="MiniExcel" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\LINGYUN.Abp.Exporter.Core\LINGYUN.Abp.Exporter.Core.csproj" />
</ItemGroup>
</Project>

22
aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.MiniExcel/LINGYUN/Abp/Exporter/AbpExporterMiniExcelModule.cs

@ -0,0 +1,22 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Volo.Abp.Modularity;
namespace LINGYUN.Abp.Exporter.MiniExcel;
[DependsOn(typeof(AbpExporterCoreModule))]
public class AbpExporterMiniExcelModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
context.Services.Replace(
ServiceDescriptor.Transient(
typeof(IExporterProvider),
typeof(MiniExcelExporterProvider)));
context.Services.Replace(
ServiceDescriptor.Transient(
typeof(IImporterProvider),
typeof(MiniExcelImporterProvider)));
}
}

25
aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.MiniExcel/LINGYUN/Abp/Exporter/AbpExporterMiniExcelOptions.cs

@ -0,0 +1,25 @@
using MiniExcelLibs.OpenXml;
using System;
using System.Collections.Generic;
namespace LINGYUN.Abp.Exporter;
public class AbpExporterMiniExcelOptions
{
public IDictionary<Type, Action<OpenXmlConfiguration>> ExportSettingMapping { get; }
public IDictionary<Type, Action<OpenXmlConfiguration>> ImportSettingMapping { get; }
public AbpExporterMiniExcelOptions()
{
ExportSettingMapping = new Dictionary<Type, Action<OpenXmlConfiguration>>();
ImportSettingMapping = new Dictionary<Type, Action<OpenXmlConfiguration>>();
}
public void MapExportSetting(Type dataType, Action<OpenXmlConfiguration> settingMapping)
{
ExportSettingMapping[dataType] = settingMapping;
}
public void MapImportSetting(Type dataType, Action<OpenXmlConfiguration> settingMapping)
{
ImportSettingMapping[dataType] = settingMapping;
}
}

41
aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.MiniExcel/LINGYUN/Abp/Exporter/MiniExcelExporterProvider.cs

@ -0,0 +1,41 @@
using Microsoft.Extensions.Options;
using MiniExcelLibs;
using MiniExcelLibs.OpenXml;
using System.Collections.Generic;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using Volo.Abp.DependencyInjection;
namespace LINGYUN.Abp.Exporter;
public class MiniExcelExporterProvider : IExporterProvider, ITransientDependency
{
private readonly AbpExporterMiniExcelOptions _options;
public MiniExcelExporterProvider(IOptions<AbpExporterMiniExcelOptions> options)
{
_options = options.Value;
}
public async virtual Task<Stream> ExportAsync<T>(ICollection<T> data, CancellationToken cancellationToken = default)
where T : class, new()
{
var memoryStream = new MemoryStream();
var xmlConfig = new OpenXmlConfiguration();
if (_options.ExportSettingMapping.TryGetValue(typeof(T), out var exportSetting))
{
exportSetting?.Invoke(xmlConfig);
}
await memoryStream.SaveAsAsync(
value: data,
excelType: ExcelType.XLSX,
configuration: xmlConfig,
cancellationToken: cancellationToken);
memoryStream.Seek(0, SeekOrigin.Begin);
return memoryStream;
}
}

35
aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.MiniExcel/LINGYUN/Abp/Exporter/MiniExcelImporterProvider.cs

@ -0,0 +1,35 @@
using Microsoft.Extensions.Options;
using MiniExcelLibs;
using MiniExcelLibs.OpenXml;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.IO;
using System.Threading.Tasks;
using Volo.Abp.DependencyInjection;
namespace LINGYUN.Abp.Exporter;
public class MiniExcelImporterProvider : IImporterProvider, ITransientDependency
{
private readonly AbpExporterMiniExcelOptions _options;
public MiniExcelImporterProvider(IOptions<AbpExporterMiniExcelOptions> options)
{
_options = options.Value;
}
public async virtual Task<IReadOnlyCollection<T>> ImportAsync<T>(Stream stream) where T : class, new()
{
var xmlConfig = new OpenXmlConfiguration();
if (_options.ExportSettingMapping.TryGetValue(typeof(T), out var exportSetting))
{
exportSetting?.Invoke(xmlConfig);
}
var dataList = await stream.QueryAsync<T>(
excelType: ExcelType.XLSX,
configuration: xmlConfig);
return dataList.ToImmutableList();
}
}

46
aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.MiniExcel/README.md

@ -0,0 +1,46 @@
# LINGYUN.Abp.Exporter.MiniExcel
数据导出接口的 [MiniExcel](https://github.com/mini-software/MiniExcel) 实现
MiniExcel简单、高效避免OOM的.NET处理Excel查、写、填充数据工具。
目前主流框架大多需要将数据全载入到内存方便操作,但这会导致内存消耗问题,MiniExcel 尝试以 Stream 角度写底层算法逻辑,能让原本1000多MB占用降低到几MB,避免内存不够情况。
详情请参考 [MiniExcel 文档](https://github.com/mini-software/MiniExcel/blob/master/README.md)
## 配置使用
```csharp
[DependsOn(
typeof(AbpExporterMiniExcelModule)
)]
public class YouProjectModule : AbpModule
{
Configure<AbpExporterMiniExcelOptions>(options =>
{
// 配置类型数据导出
options.MapExportSetting(typeof(DemoClass), config =>
{
config.DynamicColumns = new[]
{
// 忽略Name字段
new DynamicExcelColumn(nameof(DemoClass.Name)){ Ignore = true },
// 其他配置
};
});
});
}
public class DemoClass
{
public string Name { get; set; }
public string Remarks { get; set; }
public DemoClass()
{
}
}
```
Loading…
Cancel
Save