zhaoxinyu
5 months ago
13 changed files with 730 additions and 136 deletions
@ -1,13 +1,187 @@ |
|||||
using System; |
using System; |
||||
|
using System.Collections.Concurrent; |
||||
using System.Collections.Generic; |
using System.Collections.Generic; |
||||
|
using System.ComponentModel.DataAnnotations; |
||||
|
using System.IO.Compression; |
||||
|
using System.IO; |
||||
using System.Linq; |
using System.Linq; |
||||
|
using System.Reflection; |
||||
using System.Text; |
using System.Text; |
||||
|
using System.Threading; |
||||
using System.Threading.Tasks; |
using System.Threading.Tasks; |
||||
|
using Magicodes.ExporterAndImporter.Core; |
||||
|
using Minio; |
||||
|
using NPOI.SS.UserModel; |
||||
|
using NPOI.XSSF.UserModel; |
||||
|
using SettleAccount.Bases; |
||||
|
using System.Diagnostics; |
||||
|
using Magicodes.ExporterAndImporter.Core.Extension; |
||||
|
|
||||
namespace Win.Sfs.SettleAccount.Entities.BQ |
namespace Win.Sfs.SettleAccount.Entities.BQ |
||||
{ |
{ |
||||
public class NopiDataToExcel |
public class NopiExtendExcel<T> where T : class, new() |
||||
{ |
{ |
||||
|
|
||||
|
static ConcurrentBag<FileInfoGroup> excelFiles = new ConcurrentBag<FileInfoGroup>(); |
||||
|
public static string EndPoint { get; set; } |
||||
|
public static string AccessKey { get; set; } |
||||
|
public static string SecretKey { get; set; } |
||||
|
public static string BucketName { get; set; } |
||||
|
public static bool WithSSL { get; set; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
///
|
||||
|
/// </summary>
|
||||
|
/// <param name="sheetName">页签名称</param>
|
||||
|
/// <param name="data">数据</param>
|
||||
|
/// <param name="chunkSize">缓存文件行数</param>
|
||||
|
public static async Task<string> WriteDataToExcelInParallel(string sheetName, List<T> data, int chunkSize) |
||||
|
{ |
||||
|
Stopwatch sw = Stopwatch.StartNew(); |
||||
|
var count = data.Count / 1000000 + ((data.Count % 1000000) > 0 ? 1 : 0); |
||||
|
for (var i = 1; i <= count; i++) |
||||
|
{ |
||||
|
var datas = data.Skip((i - 1) * 1000000).Take(1000000).ToList(); |
||||
|
var chunks = datas.ChunkBy(chunkSize); |
||||
|
Parallel.ForEach(chunks, chunk => |
||||
|
{ |
||||
|
var fileName = $"{sheetName}_{i - 1}_{Guid.NewGuid()}.xlsx"; |
||||
|
var fileinfogroup = new FileInfoGroup((fileName), $"{sheetName}_{i - 1}"); |
||||
|
WriteDataToExcel(chunk.ToList(), fileName); |
||||
|
excelFiles.Add(fileinfogroup); |
||||
|
}); |
||||
|
} |
||||
|
string[] filePaths = excelFiles.Select(x => x.FileName).ToArray(); |
||||
|
string zipPath = $"{sheetName}_{Guid.NewGuid()}.zip"; |
||||
|
using (var archive = ZipFile.Open(zipPath, ZipArchiveMode.Create)) |
||||
|
{ |
||||
|
foreach (var file in filePaths) |
||||
|
{ |
||||
|
archive.CreateEntryFromFile(file, Path.GetFileName(file)); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
//for (var i = 0; i < count; i++)
|
||||
|
//{
|
||||
|
// var filelist = excelFiles.Where(p => p.Grpup == $"{sheetName}_{i}").Select(p => p.FileName).ToList();
|
||||
|
// //MergeExcelFiles(filelist.ToArray(), $"{sheetName}.xlsx",filelist.First());
|
||||
|
// //foreach (var file in filelist)
|
||||
|
// //{
|
||||
|
// // File.Delete(file);
|
||||
|
// //}
|
||||
|
//}
|
||||
|
sw.Stop(); |
||||
|
|
||||
|
|
||||
|
using (FileStream fileStream = new FileStream(zipPath, FileMode.Open)) |
||||
|
{ |
||||
|
var minioClient = new MinioClient(EndPoint, AccessKey, SecretKey, ""); |
||||
|
try |
||||
|
{ |
||||
|
await minioClient.PutObjectAsync(BucketName, zipPath, fileStream, fileStream.Length, "application/zip").ConfigureAwait(false); |
||||
|
} |
||||
|
catch (Exception ex) |
||||
|
{ |
||||
|
// Console.WriteLine($"上传文件到 MinIO 时发生错误: {ex.Message}");
|
||||
|
} |
||||
|
|
||||
|
} |
||||
|
Thread.Sleep(10000); |
||||
|
|
||||
|
return zipPath; |
||||
|
//using (FileStream fileStream = new FileStream(zipPath, FileMode.Open))
|
||||
|
//{
|
||||
|
// return fileStream.GetAllBytes();
|
||||
|
//}
|
||||
|
|
||||
|
} |
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
public static void WriteDataToExcel(List<T> data, string fileName) |
||||
|
{ |
||||
|
IWorkbook workbook = new XSSFWorkbook(); |
||||
|
ISheet sheet = workbook.CreateSheet("Sheet1"); |
||||
|
var firist = data.FirstOrDefault(); |
||||
|
var properties = typeof(T).GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.GetProperty) |
||||
|
.Where(o => o.GetAttributes<ExporterHeaderAttribute>().Any() || o.GetAttributes<DisplayAttribute>().Any()) |
||||
|
.ToDictionary(o => o.GetAttribute<ExporterHeaderAttribute>()?.DisplayName ?? o.GetAttribute<DisplayAttribute>()?.Name, o => o); |
||||
|
int columnCellIndex = 0; |
||||
|
int rowIndex = 1; |
||||
|
IRow headerRow = sheet.CreateRow(0); |
||||
|
foreach (var property in properties) |
||||
|
{ |
||||
|
headerRow.CreateCell(columnCellIndex).SetCellValue(property.Key); |
||||
|
columnCellIndex++; |
||||
|
} |
||||
|
foreach (var item in data) |
||||
|
{ |
||||
|
IRow row = sheet.CreateRow(rowIndex++); |
||||
|
int cellIndex = 0; |
||||
|
foreach (var property in item.GetType().GetProperties()) |
||||
|
{ |
||||
|
ICell cell = row.CreateCell(cellIndex++); |
||||
|
cell.SetCellValue(property.GetValue(item)?.ToString()); |
||||
|
} |
||||
|
} |
||||
|
using (FileStream fileStream = new FileStream(fileName, FileMode.Create)) |
||||
|
{ |
||||
|
workbook.Write(fileStream); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public static void MergeExcelFiles(string[] filePaths, string outputFilePath, string sheetName) |
||||
|
{ |
||||
|
|
||||
|
IWorkbook workbook = new XSSFWorkbook(); |
||||
|
ISheet sheet = workbook.CreateSheet(sheetName); |
||||
|
|
||||
|
int rowIndex = 0; |
||||
|
foreach (string filePath in filePaths) |
||||
|
{ |
||||
|
using (FileStream fileStream = new FileStream(filePath, FileMode.Open)) |
||||
|
{ |
||||
|
IWorkbook sourceWorkbook = new XSSFWorkbook(fileStream); |
||||
|
ISheet sourceSheet = sourceWorkbook.GetSheetAt(0); |
||||
|
|
||||
|
int sourceRowCount = sourceSheet.LastRowNum; |
||||
|
for (int i = 0; i <= sourceRowCount; i++) |
||||
|
{ |
||||
|
IRow sourceRow = sourceSheet.GetRow(i); |
||||
|
if (sourceRow != null) |
||||
|
{ |
||||
|
IRow targetRow = sheet.CreateRow(rowIndex++); |
||||
|
int cellCount = sourceRow.LastCellNum; |
||||
|
for (int j = 0; j < cellCount; j++) |
||||
|
{ |
||||
|
ICell sourceCell = sourceRow.GetCell(j); |
||||
|
if (sourceCell != null) |
||||
|
{ |
||||
|
ICell targetCell = targetRow.CreateCell(j); |
||||
|
targetCell.SetCellValue(sourceCell.ToString()); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
if (File.Exists(outputFilePath)) |
||||
|
{ |
||||
|
using (FileStream fileStream = new FileStream(outputFilePath, FileMode.Open, FileAccess.ReadWrite)) |
||||
|
{ |
||||
|
workbook.Write(fileStream); |
||||
|
} |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
using (FileStream fileStream = new FileStream(outputFilePath, FileMode.Create)) |
||||
|
{ |
||||
|
workbook.Write(fileStream); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
} |
} |
||||
|
|
||||
} |
} |
||||
|
@ -0,0 +1,313 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Concurrent; |
||||
|
using System.Collections.Generic; |
||||
|
using System.ComponentModel.DataAnnotations; |
||||
|
using System.Diagnostics; |
||||
|
using System.IO.Compression; |
||||
|
using System.IO; |
||||
|
using System.Linq; |
||||
|
using System.Reflection; |
||||
|
using System.Text; |
||||
|
using System.Threading; |
||||
|
using System.Threading.Tasks; |
||||
|
using Magicodes.ExporterAndImporter.Core.Extension; |
||||
|
using Magicodes.ExporterAndImporter.Core; |
||||
|
using NPOI.SS.UserModel; |
||||
|
using NPOI.XSSF.UserModel; |
||||
|
using SettleAccount.Bases; |
||||
|
using Minio; |
||||
|
using Win.Sfs.SettleAccount.Reports; |
||||
|
using NPOI.XWPF.UserModel; |
||||
|
|
||||
|
namespace SettleAccount.Job.Services.Report |
||||
|
{ |
||||
|
public class NopiExtendExcel<T> where T : class, new() |
||||
|
{ |
||||
|
|
||||
|
ConcurrentBag<FileInfoGroup> excelFiles = new ConcurrentBag<FileInfoGroup>(); |
||||
|
public string EndPoint { get; set; } |
||||
|
public string AccessKey { get; set; } |
||||
|
public string SecretKey { get; set; } |
||||
|
public string BucketName { get; set; } |
||||
|
public bool WithSSL { get; set; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
///
|
||||
|
/// </summary>
|
||||
|
/// <param name="sheetName">页签名称</param>
|
||||
|
/// <param name="data">数据</param>
|
||||
|
/// <param name="chunkSize">缓存文件行数</param>
|
||||
|
public async Task<string> WriteDataToExcelInParallel(string sheetName, List<T> data, int chunkSize,string zipFileName, List<SaSeEdiCompareSumReport> sumdata) |
||||
|
{ |
||||
|
var count = data.Count / 1000000 + ((data.Count % 1000000) > 0 ? 1 : 0); |
||||
|
for (var i = 1; i <= count; i++) |
||||
|
{ |
||||
|
var datas = data.Skip((i - 1) * 1000000).Take(1000000).ToList(); |
||||
|
var chunks = datas.ChunkBy(chunkSize); |
||||
|
Parallel.ForEach(chunks, chunk => |
||||
|
{ |
||||
|
var fileName = $"{sheetName}_{Guid.NewGuid()}.xlsx"; |
||||
|
var fileinfogroup = new FileInfoGroup((fileName), $"{sheetName}_{i}"); |
||||
|
WriteDataToExcel(chunk.ToList(), fileName); |
||||
|
excelFiles.Add(fileinfogroup); |
||||
|
}); |
||||
|
} |
||||
|
if(sumdata!=null) |
||||
|
{ |
||||
|
var sumFileName = $"{sheetName}_汇总_{Guid.NewGuid()}.xlsx"; |
||||
|
var fileinfogroup = new FileInfoGroup((sumFileName), $"{sheetName}_汇总"); |
||||
|
WriteSumDataToExcel(sumdata, sumFileName); |
||||
|
excelFiles.Add(fileinfogroup); |
||||
|
|
||||
|
} |
||||
|
|
||||
|
string[] filePaths = excelFiles.Select(x => x.FileName).ToArray(); |
||||
|
string zipPath = zipFileName; |
||||
|
using (var archive = ZipFile.Open(zipPath, ZipArchiveMode.Create)) |
||||
|
{ |
||||
|
foreach (var file in filePaths) |
||||
|
{ |
||||
|
archive.CreateEntryFromFile(file, Path.GetFileName(file)); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
for (var i = 0; i < count; i++) |
||||
|
{ |
||||
|
var filelist = excelFiles.Select(p => p.FileName).ToList(); |
||||
|
|
||||
|
foreach (var file in filelist) |
||||
|
{ |
||||
|
File.Delete(file); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
using (FileStream fileStream = new FileStream(zipPath, FileMode.Open)) |
||||
|
{ |
||||
|
var minioClient = new MinioClient(EndPoint, AccessKey, SecretKey, ""); |
||||
|
try |
||||
|
{ |
||||
|
await minioClient.PutObjectAsync(BucketName, "host/"+zipPath, fileStream, fileStream.Length, "application/zip").ConfigureAwait(false); |
||||
|
|
||||
|
|
||||
|
} |
||||
|
catch (Exception ex) |
||||
|
{ |
||||
|
Console.WriteLine($"上传文件到 MinIO 时发生错误: {ex.Message}"); |
||||
|
} |
||||
|
finally |
||||
|
{ |
||||
|
if (fileStream != null) |
||||
|
{ |
||||
|
fileStream.Close(); |
||||
|
File.Delete(zipPath); |
||||
|
} |
||||
|
|
||||
|
} |
||||
|
|
||||
|
} |
||||
|
//using (FileStream fileStream = new FileStream(zipPath, FileMode.Open))
|
||||
|
//{
|
||||
|
// return fileStream.GetAllBytes();
|
||||
|
//}
|
||||
|
return zipFileName; |
||||
|
} |
||||
|
|
||||
|
public void WriteDataToExcel(List<T> data, string fileName) |
||||
|
{ |
||||
|
// 每列列宽字典
|
||||
|
var dic = new Dictionary<int, int>(); |
||||
|
|
||||
|
IWorkbook workbook = new XSSFWorkbook(); |
||||
|
ISheet sheet = workbook.CreateSheet("数据"); |
||||
|
var firist = data.FirstOrDefault(); |
||||
|
var properties = typeof(T).GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.GetProperty) |
||||
|
.Where(o => o.GetAttributes<ExporterHeaderAttribute>().Any() || o.GetAttributes<DisplayAttribute>().Any()) |
||||
|
.ToDictionary(o => o.GetAttribute<ExporterHeaderAttribute>()?.DisplayName ?? o.GetAttribute<DisplayAttribute>()?.Name, o => o); |
||||
|
int columnCellIndex = 0; |
||||
|
int rowIndex = 1; |
||||
|
IRow headerRow = sheet.CreateRow(0); |
||||
|
foreach (var property in properties) |
||||
|
{ |
||||
|
headerRow.CreateCell(columnCellIndex).SetCellValue(property.Key); |
||||
|
//sheet.AutoSizeColumn(columnCellIndex);
|
||||
|
dic.Add(columnCellIndex, Encoding.Default.GetBytes(headerRow.GetCell(columnCellIndex).StringCellValue).Length * 256 + 200); |
||||
|
columnCellIndex++; |
||||
|
|
||||
|
} |
||||
|
foreach (var item in data) |
||||
|
{ |
||||
|
IRow row = sheet.CreateRow(rowIndex++); |
||||
|
int cellIndex = 0; |
||||
|
foreach (var property in item.GetType().GetProperties()) |
||||
|
{ |
||||
|
NPOI.SS.UserModel.ICell cell = row.CreateCell(cellIndex); |
||||
|
|
||||
|
var propertyType = property.PropertyType; |
||||
|
if (propertyType == typeof(bool)) |
||||
|
{ |
||||
|
cell.SetCellValue((bool)property.GetValue(item)! ? "是" : "否"); |
||||
|
} |
||||
|
else if (propertyType.IsEnum) |
||||
|
{ |
||||
|
var value = property.GetValue(item)?.ToString()?.Trim(); |
||||
|
var enumValue = (System.Enum.Parse(propertyType, value) as System.Enum); |
||||
|
var type = enumValue.GetType(); |
||||
|
var field = type.GetField(enumValue.ToString()); |
||||
|
|
||||
|
cell.SetCellValue(field.GetCustomAttribute<DisplayAttribute>()?.Name ?? field.Name); |
||||
|
|
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
cell.SetCellValue(property.GetValue(item)?.ToString()); |
||||
|
} |
||||
|
|
||||
|
int length = Encoding.Default.GetBytes(cell.StringCellValue).Length * 256 + 200; |
||||
|
length = length > 15000 ? 15000 : length; |
||||
|
|
||||
|
// 若比已存在列宽更宽则替换,Excel限制最大宽度为15000
|
||||
|
try |
||||
|
{ |
||||
|
if (dic[cellIndex] < length) |
||||
|
{ |
||||
|
dic[cellIndex] = length; |
||||
|
} |
||||
|
} |
||||
|
catch(Exception ex) |
||||
|
{ |
||||
|
} |
||||
|
|
||||
|
cellIndex++; |
||||
|
|
||||
|
} |
||||
|
} |
||||
|
|
||||
|
for (int i = 0; i < dic.Count; i++) |
||||
|
{ |
||||
|
sheet.SetColumnWidth(i, dic[i]); |
||||
|
} |
||||
|
|
||||
|
using (FileStream fileStream = new FileStream(fileName, FileMode.Create)) |
||||
|
{ |
||||
|
workbook.Write(fileStream); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public void WriteSumDataToExcel(List<SaSeEdiCompareSumReport> data, string fileName) |
||||
|
{ |
||||
|
try |
||||
|
{ |
||||
|
// 每列列宽字典
|
||||
|
var dic = new Dictionary<int, int>(); |
||||
|
|
||||
|
IWorkbook workbook = new XSSFWorkbook(); |
||||
|
ISheet sheet = workbook.CreateSheet("数据"); |
||||
|
var firist = data.FirstOrDefault(); |
||||
|
var properties = typeof(SaSeEdiCompareSumReport).GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.GetProperty) |
||||
|
.Where(o => o.GetAttributes<ExporterHeaderAttribute>().Any() || o.GetAttributes<DisplayAttribute>().Any()) |
||||
|
.ToDictionary(o => o.GetAttribute<ExporterHeaderAttribute>()?.DisplayName ?? o.GetAttribute<DisplayAttribute>()?.Name, o => o); |
||||
|
int columnCellIndex = 0; |
||||
|
int rowIndex = 1; |
||||
|
IRow headerRow = sheet.CreateRow(0); |
||||
|
foreach (var property in properties) |
||||
|
{ |
||||
|
headerRow.CreateCell(columnCellIndex).SetCellValue(property.Key); |
||||
|
//sheet.AutoSizeColumn(columnCellIndex);
|
||||
|
dic.Add(columnCellIndex, Encoding.Default.GetBytes(headerRow.GetCell(columnCellIndex).StringCellValue).Length * 256 + 200); |
||||
|
columnCellIndex++; |
||||
|
|
||||
|
} |
||||
|
foreach (var item in data) |
||||
|
{ |
||||
|
IRow row = sheet.CreateRow(rowIndex++); |
||||
|
int cellIndex = 0; |
||||
|
foreach (var property in item.GetType().GetProperties()) |
||||
|
{ |
||||
|
NPOI.SS.UserModel.ICell cell = row.CreateCell(cellIndex); |
||||
|
|
||||
|
var propertyType = property.PropertyType; |
||||
|
if (propertyType == typeof(bool)) |
||||
|
{ |
||||
|
cell.SetCellValue((bool)property.GetValue(item)! ? "是" : "否"); |
||||
|
} |
||||
|
else if (propertyType.IsEnum) |
||||
|
{ |
||||
|
var value = property.GetValue(item)?.ToString()?.Trim(); |
||||
|
var enumValue = (System.Enum.Parse(propertyType, value) as System.Enum); |
||||
|
var type = enumValue.GetType(); |
||||
|
var field = type.GetField(enumValue.ToString()); |
||||
|
|
||||
|
cell.SetCellValue(field.GetCustomAttribute<DisplayAttribute>()?.Name ?? field.Name); |
||||
|
|
||||
|
} |
||||
|
else if (propertyType.IsValueType) |
||||
|
{ |
||||
|
try |
||||
|
{ |
||||
|
cell.SetCellValue(double.Parse(property.GetValue(item)?.ToString())); |
||||
|
} |
||||
|
catch |
||||
|
{ |
||||
|
cell.SetCellValue(property.GetValue(item)?.ToString()); |
||||
|
} |
||||
|
|
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
cell.SetCellValue(property.GetValue(item)?.ToString()); |
||||
|
} |
||||
|
|
||||
|
try |
||||
|
{ |
||||
|
int length = Encoding.Default.GetBytes(cell.StringCellValue).Length * 256 + 200; |
||||
|
length = length > 15000 ? 15000 : length; |
||||
|
|
||||
|
// 若比已存在列宽更宽则替换,Excel限制最大宽度为15000
|
||||
|
|
||||
|
if (dic[cellIndex] < length) |
||||
|
{ |
||||
|
dic[cellIndex] = length; |
||||
|
} |
||||
|
} |
||||
|
catch (Exception ex) |
||||
|
{ |
||||
|
} |
||||
|
|
||||
|
cellIndex++; |
||||
|
|
||||
|
} |
||||
|
} |
||||
|
|
||||
|
for (int i = 0; i < dic.Count; i++) |
||||
|
{ |
||||
|
sheet.SetColumnWidth(i, dic[i]); |
||||
|
} |
||||
|
|
||||
|
using (FileStream fileStream = new FileStream(fileName, FileMode.Create)) |
||||
|
{ |
||||
|
workbook.Write(fileStream); |
||||
|
} |
||||
|
|
||||
|
} |
||||
|
catch(Exception ex) |
||||
|
{ |
||||
|
|
||||
|
} |
||||
|
|
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public class FileInfoGroup |
||||
|
{ |
||||
|
public FileInfoGroup(string fileName, string grpup) |
||||
|
{ |
||||
|
FileName = fileName; |
||||
|
Grpup = grpup; |
||||
|
} |
||||
|
|
||||
|
public string FileName { get; set; } |
||||
|
public string Grpup { get; set; } |
||||
|
} |
||||
|
|
||||
|
|
||||
|
} |
Loading…
Reference in new issue