zhaoxinyu
5 months ago
13 changed files with 730 additions and 136 deletions
@ -1,13 +1,187 @@ |
|||
using System; |
|||
using System.Collections.Concurrent; |
|||
using System.Collections.Generic; |
|||
using System.ComponentModel.DataAnnotations; |
|||
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; |
|||
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 |
|||
{ |
|||
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