using MiniExcelLibs; using MiniExcelLibs.Attributes; using MiniExcelLibs.OpenXml; using MyCode.Project.Domain.Config; using MyCode.Project.Domain.Message.Act.Common; using MyCode.Project.Domain.Message.Response.LxmZHMDReport; using MyCode.Project.Domain.Message.Response.User; using MyCode.Project.Infrastructure; using MyCode.Project.Infrastructure.Cache; using MyCode.Project.Infrastructure.Common; using MyCode.Project.Infrastructure.Constant; using MyCode.Project.Infrastructure.Enumeration; using MyCode.Project.Infrastructure.Exceptions; using MyCode.Project.Infrastructure.UnityExtensions; using Newtonsoft.Json.Linq; using System; using System.Collections.Generic; using System.IO; using System.Linq; namespace MyCode.Project.Services.BLL.ReportExport { public abstract class BaseExport : MarshalByRefObject { private IMyCodeCacheService _myCodeCacheService { get { return UnityHelper.GetService(); } } /// /// 查询条件 /// public object Condition { get; set; } /// /// 当前操作用户 /// public LoginInfo CurrentUser { get; set; } /// /// 计算的id /// public long CalId { get; set; } //DotNetLib压缩 List PageZipFilePaths = new List(); public BaseExport() { } /// /// 报表id /// public long ReportId { get; set; } /// /// 多个的数据 /// private List ListData = new List(); /// /// 确定导出类型,根据导出类型,来决定导出模板 /// public int ReportType { get; set; } /// /// Excel文件类型 0:zip 1:xls /// public int ExcelFileType { get; set; } #region AddExcelProcess(增加EXCEL处理,可能有多个需要处理) /// /// 增加EXCEL处理,可能有多个需要处理 /// /// /// public void AddExcelProcess(string fileName, dynamic data) { ListData.Add(new ExcelData() { FileName = fileName, DyData = data }); } #endregion #region GetPageSearch(获取分页查询条件) /// /// 获取分页查询条件 /// /// 条件类型 /// 查询条件 /// 查询数量 /// public PagedSearch GetPageSearch(object condition, int pagesize = 100000, int pageIndex = 1) where TEntity : class, new() { var tCondition = ((JObject)condition).ToObject(); return new PagedSearch(pagesize, pageIndex, tCondition); } #endregion #region Execute(执行) /// /// 多个保存的实体,最后保存为一个压缩文件,返回压缩文件路径 /// /// /// public virtual string Execute() { if (ListData == null || ListData.Count == 0) { throw new BaseException("没有需要导出的数据"); } //DotNetLib压缩 var zipFilePaths = new List(); var zipFile = ""; //模板的路径 var filePath = SystemConfig.AppFilePath; //模板路径 var templatePath = Path.Combine(filePath, $"ExportTemplate/{ReportType}.xlsx"); //保存的excel目录 var savePathFolder = Path.Combine(filePath, $"download/exceltemp/{DateTime.Now.ToString("yyyyMM")}/"); //数据量 var listCount = ListData.Count; var resultData = new ReportCalRateResp() { Total = listCount }; var result = new Result() { Data = resultData, Code = ResultCode.Success }; int i = 1; //当前秒 int second = DateTime.Now.Second; //是否是导出excel格式 foreach (var item in ListData) { var saveFileName = $"{item.FileName }_{DateTime.Now.ToString("HHmmssfff")}.xlsx"; var savePath = Path.Combine(savePathFolder, saveFileName); if (!FileUtils.IsDirectoryExists(savePathFolder)) { Directory.CreateDirectory(savePathFolder); } //加入进度发送websocket MiniExcel.SaveAsByTemplate(savePath, templatePath, item.DyData); if (ExcelFileType == (int)ExportFileType.Xls) { return savePath; } zipFilePaths.Add(savePath); resultData.CurQty = i; var rate = Math.Round(resultData.CurQty * 1m / resultData.Total, 4); //这里因为前面已经用了2%了,比如获取数据什么的,所以这里不能低于2%;并且压缩也是需要时间的,所以最多就是99% if (rate < 0.02m) { rate = 0.02m; } else if (rate >= 1) { rate = 0.99m; } resultData.Rate = rate; //发送结果 var sendResult = WebSocketBLL.SendSocketMsg(ReportId, JsonHelper.ToJson(result, false, true)); //发送失败了 if (!sendResult) { throw new BaseException($"当前id={ReportId}不在线"); } //这里这么循环的话,当导出1000个的时候会有点问题,调用redis太频繁了;不同秒才需要 if (DateTime.Now.Second != second) { var existZipCacheFile = _myCodeCacheService.Exists($"{CacheKey.ReportZipFileCacheKey}{ReportId}"); if (!existZipCacheFile) { //移除正在下载 _myCodeCacheService.Delete($"{CacheKey.HasDownloadZipCacheKey}"); throw new BaseException($"用户已经取消id={ReportId}的导出"); } second = DateTime.Now.Second; } i++; } //这里判断如果只有一个文件,则直接导出为excel,不用压缩了 if (ExcelFileType == (int)ExportFileType.Zip) { //保存并压缩 zipFile = Path.Combine(savePathFolder, $"{EnumHelper.GetDescription(ReportType)}_{ReportId}.zip"); ZipHelper.Zip(zipFilePaths, zipFile); //将zip路径放到RedisCache中 _myCodeCacheService.Set($"{CacheKey.ReportZipFileCacheKey}{ReportId}", zipFile, new TimeSpan(7, 1, 0, 0)); resultData.CurQty = listCount; resultData.Rate = 1; WebSocketBLL.SendSocketMsg(ReportId, JsonHelper.ToJson(result, false, true)); //移除正在下载 _myCodeCacheService.Delete($"{CacheKey.HasDownloadZipCacheKey}"); } return zipFile; } #endregion #region PageListExecute(执行) /// /// 多个保存的实体,最后保存为一个压缩文件,返回压缩文件路径 /// /// /// public string PageListExecute(PageResult pageResult,int pageIndex,int pageSize,int totalCount,string fileName,string hasDownloadZipCacheKey) { var dataList = pageResult.DataList; if (dataList == null || dataList.Count == 0) { throw new BaseException("没有需要导出的数据"); } var zipFile = ""; //模板的路径 var filePath = SystemConfig.AppFilePath; if (!Directory.Exists(filePath)) { Directory.CreateDirectory(filePath); } //模板路径 var templatePath = Path.Combine(filePath, $"ExportTemplate/{ReportType}.xlsx"); //保存的excel目录 //string ServerMapPath = Environment.CurrentDirectory + @"/App_File/"; //string templatePath = Path.Combine(ServerMapPath, $"ExportTemplate/{ReportType}.xlsx"); var savePathFolder = Path.Combine(filePath, $"download/exceltemp/{DateTime.Now.ToString("yyyyMM")}/"); if (!FileUtils.IsDirectoryExists(savePathFolder)) { Directory.CreateDirectory(savePathFolder); } var resultData = new ReportCalRateResp() { Total = totalCount }; var result = new Result() { Data = resultData, Code = ResultCode.Success }; //当前秒 int second = DateTime.Now.Second; ListData = new List(); var dataResult = new { pro = dataList }; AddExcelProcess(fileName, dataResult); var saveFileName = $"{fileName }_{(pageIndex - 1) * pageSize+1}-{(pageIndex - 1) * pageSize + dataList.Count}_{DateTime.Now.ToString("HHmmssfff")}.xlsx"; var savePath = Path.Combine(savePathFolder, saveFileName); //是否是导出excel格式 //加入进度发送websocket MiniExcel.SaveAsByTemplate(savePath, templatePath, ListData.Select(t=>t.DyData).FirstOrDefault()); //这里判断如果只有一个文件,则直接导出为excel,不用压缩了 if (ExcelFileType == (int)ExportFileType.Xls) { return savePath; } PageZipFilePaths.Add(savePath); resultData.CurQty =(pageIndex-1)* pageSize+ dataList.Count; var rate = Math.Round(resultData.CurQty * 1m / resultData.Total, 4); //这里因为前面已经用了2%了,比如获取数据什么的,所以这里不能低于2%;并且压缩也是需要时间的,所以最多就是99% if (rate < 0.02m) { rate = 0.02m; } else if (rate >= 1) { rate = 0.99m; } resultData.Rate = rate; //发送结果 var sendResult = WebSocketBLL.SendSocketMsg(ReportId, JsonHelper.ToJson(result, false, true)); //发送失败了 if (!sendResult) { throw new BaseException($"当前id={ReportId}不在线"); } ////这里这么循环的话,当导出1000个的时候会有点问题,调用redis太频繁了;不同秒才需要 if (DateTime.Now.Second != second) { var existZipCacheFile = _myCodeCacheService.Exists($"{CacheKey.ReportZipFileCacheKey}{ReportId}"); if (!existZipCacheFile) { //移除正在下载 _myCodeCacheService.Delete($"{hasDownloadZipCacheKey}"); throw new BaseException($"用户已经取消id={ReportId}的导出"); } second = DateTime.Now.Second; } if (ExcelFileType == (int)ExportFileType.Zip && resultData.CurQty == totalCount) { //保存并压缩 zipFile = Path.Combine(savePathFolder, $"{fileName}_{ReportId}.zip"); ZipHelper.Zip(PageZipFilePaths, zipFile); PageZipFilePaths = new List(); //将zip路径放到RedisCache中 _myCodeCacheService.Set($"{CacheKey.ReportZipFileCacheKey}{ReportId}", zipFile, new TimeSpan(7, 1, 0, 0)); //resultData.CurQty = totalCount; resultData.Rate = 1; WebSocketBLL.SendSocketMsg(ReportId, JsonHelper.ToJson(result, false, true)); //移除正在下载 _myCodeCacheService.Delete($"{hasDownloadZipCacheKey}"); } return zipFile; } #endregion #region Execute(执行) /// /// 多个保存的实体,最后保存为一个压缩文件,返回压缩文件路径 /// /// /// public virtual string Execute(List columnNames) { if (ListData == null || ListData.Count == 0) { throw new BaseException("没有需要导出的数据"); } //DotNetLib压缩 var zipFilePaths = new List(); var zipFile = ""; //模板的路径 var filePath = SystemConfig.AppFilePath; //模板路径 var templatePath = Path.Combine(filePath, $"ExportTemplate/{ReportType}.xlsx"); //保存的excel目录 var savePathFolder = Path.Combine(filePath, $"download/exceltemp/{DateTime.Now.ToString("yyyyMM")}/"); //数据量 var listCount = ListData.Count; var resultData = new ReportCalRateResp() { Total = listCount }; var result = new Result() { Data = resultData, Code = ResultCode.Success }; int i = 1; //当前秒 int second = DateTime.Now.Second; List dynamicExcelColumns=new List(); int index = 0; columnNames.ForEach(name => { DynamicExcelColumn column=new DynamicExcelColumn(name) { Index=index, Name = name }; dynamicExcelColumns.Add(column); index++; }); var config = new OpenXmlConfiguration { DynamicColumns = dynamicExcelColumns.ToArray() //DynamicColumns = new DynamicExcelColumn[] { // new DynamicExcelColumn("id") { Ignore = true }, // new DynamicExcelColumn("name") { Index = 1, Width = 10 }, // new DynamicExcelColumn("createdate") { Index = 0, Format = "yyyy-MM-dd", Width = 15 }, // new DynamicExcelColumn("point") { Index = 2, Name = "Account Point" }, //} }; //config.FillMergedCells = true; //是否是导出excel格式 foreach (var item in ListData) { var saveFileName = $"{item.FileName}_{DateTime.Now.ToString("HHmmssfff")}.xlsx"; var savePath = Path.Combine(savePathFolder, saveFileName); if (!FileUtils.IsDirectoryExists(savePathFolder)) { Directory.CreateDirectory(savePathFolder); } ////加入进度发送websocket //MiniExcel.SaveAsByTemplate(savePath, templatePath, item.DyData); MiniExcel.SaveAs(savePath, item.DyData, configuration: config); if (ExcelFileType == (int)ExportFileType.Xls) { return savePath; } zipFilePaths.Add(savePath); resultData.CurQty = i; var rate = Math.Round(resultData.CurQty * 1m / resultData.Total, 4); //这里因为前面已经用了2%了,比如获取数据什么的,所以这里不能低于2%;并且压缩也是需要时间的,所以最多就是99% if (rate < 0.02m) { rate = 0.02m; } else if (rate >= 1) { rate = 0.99m; } resultData.Rate = rate; //发送结果 var sendResult = WebSocketBLL.SendSocketMsg(ReportId, JsonHelper.ToJson(result, false, true)); //发送失败了 if (!sendResult) { throw new BaseException($"当前id={ReportId}不在线"); } //这里这么循环的话,当导出1000个的时候会有点问题,调用redis太频繁了;不同秒才需要 if (DateTime.Now.Second != second) { var existZipCacheFile = _myCodeCacheService.Exists($"{CacheKey.ReportZipFileCacheKey}{ReportId}"); if (!existZipCacheFile) { //移除正在下载 _myCodeCacheService.Delete($"{CacheKey.HasDownloadZipCacheKey}"); throw new BaseException($"用户已经取消id={ReportId}的导出"); } second = DateTime.Now.Second; } i++; } //这里判断如果只有一个文件,则直接导出为excel,不用压缩了 if (ExcelFileType == (int)ExportFileType.Zip) { //保存并压缩 zipFile = Path.Combine(savePathFolder, $"{EnumHelper.GetDescription(ReportType)}_{ReportId}.zip"); ZipHelper.Zip(zipFilePaths, zipFile); //将zip路径放到RedisCache中 _myCodeCacheService.Set($"{CacheKey.ReportZipFileCacheKey}{ReportId}", zipFile, new TimeSpan(7, 1, 0, 0)); resultData.CurQty = listCount; resultData.Rate = 1; WebSocketBLL.SendSocketMsg(ReportId, JsonHelper.ToJson(result, false, true)); //移除正在下载 _myCodeCacheService.Delete($"{CacheKey.HasDownloadZipCacheKey}"); } return zipFile; } #endregion } }