47 changed files with 1243 additions and 0 deletions
@ -0,0 +1,3 @@ |
|||||
|
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd"> |
||||
|
<ConfigureAwait ContinueOnCapturedContext="false" /> |
||||
|
</Weavers> |
||||
@ -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> |
||||
@ -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> |
||||
@ -0,0 +1,9 @@ |
|||||
|
using Volo.Abp.Application; |
||||
|
using Volo.Abp.Modularity; |
||||
|
|
||||
|
namespace LINGYUN.Abp.Exporter; |
||||
|
|
||||
|
[DependsOn(typeof(AbpDddApplicationContractsModule))] |
||||
|
public class AbpExporterApplicationContractsModule : AbpModule |
||||
|
{ |
||||
|
} |
||||
@ -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); |
||||
|
} |
||||
@ -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); |
||||
|
} |
||||
@ -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); |
||||
|
|
||||
|
// 其他操作 |
||||
|
} |
||||
|
} |
||||
|
``` |
||||
@ -0,0 +1,3 @@ |
|||||
|
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd"> |
||||
|
<ConfigureAwait ContinueOnCapturedContext="false" /> |
||||
|
</Weavers> |
||||
@ -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> |
||||
@ -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> |
||||
@ -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 |
||||
|
{ |
||||
|
} |
||||
@ -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); |
||||
|
} |
||||
|
} |
||||
@ -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); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,3 @@ |
|||||
|
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd"> |
||||
|
<ConfigureAwait /> |
||||
|
</Weavers> |
||||
@ -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> |
||||
@ -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> |
||||
@ -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)); |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
@ -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"; |
||||
|
} |
||||
@ -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(); |
||||
|
} |
||||
@ -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(); |
||||
|
} |
||||
@ -0,0 +1,8 @@ |
|||||
|
using Volo.Abp.Localization; |
||||
|
|
||||
|
namespace LINGYUN.Abp.Exporter.Localization; |
||||
|
|
||||
|
[LocalizationResourceName("AbpExporter")] |
||||
|
public class AbpExporterResource |
||||
|
{ |
||||
|
} |
||||
@ -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!" |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,6 @@ |
|||||
|
{ |
||||
|
"culture": "zh-Hans", |
||||
|
"texts": { |
||||
|
"AbpExporter:010001": "导入数据过程中出现一些错误,请检查数据有效性!" |
||||
|
} |
||||
|
} |
||||
@ -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); |
||||
|
} |
||||
|
} |
||||
@ -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); |
||||
|
} |
||||
|
} |
||||
@ -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() |
||||
|
{ |
||||
|
} |
||||
|
} |
||||
|
``` |
||||
@ -0,0 +1,3 @@ |
|||||
|
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd"> |
||||
|
<ConfigureAwait ContinueOnCapturedContext="false" /> |
||||
|
</Weavers> |
||||
@ -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> |
||||
@ -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 |
||||
|
{ |
||||
|
|
||||
|
} |
||||
@ -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); |
||||
|
} |
||||
|
} |
||||
@ -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); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,3 @@ |
|||||
|
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd"> |
||||
|
<ConfigureAwait ContinueOnCapturedContext="false" /> |
||||
|
</Weavers> |
||||
@ -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> |
||||
@ -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))); |
||||
|
} |
||||
|
} |
||||
@ -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; |
||||
|
} |
||||
|
} |
||||
@ -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); |
||||
|
} |
||||
|
} |
||||
@ -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; |
||||
|
} |
||||
|
} |
||||
@ -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); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -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() |
||||
|
{ |
||||
|
} |
||||
|
} |
||||
|
``` |
||||
|
|
||||
@ -0,0 +1,3 @@ |
|||||
|
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd"> |
||||
|
<ConfigureAwait ContinueOnCapturedContext="false" /> |
||||
|
</Weavers> |
||||
@ -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> |
||||
@ -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> |
||||
@ -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))); |
||||
|
} |
||||
|
} |
||||
@ -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; |
||||
|
} |
||||
|
} |
||||
@ -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; |
||||
|
} |
||||
|
} |
||||
@ -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(); |
||||
|
} |
||||
|
} |
||||
@ -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…
Reference in new issue