using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Data; using System.IO; using System.Linq; using System.Linq.Dynamic.Core; using System.Text; using System.Threading.Tasks; using Google.Protobuf.Collections; using NPOI.HSSF.UserModel; using NPOI.OpenXmlFormats.Spreadsheet; using NPOI.SS.UserModel; using NPOI.SS.Util; using NPOI.XSSF.UserModel; using SqlSugar; using Tiobon.Core.Common; using Tiobon.Core.Common.DB.Dapper; using Tiobon.Core.Common.Extensions; using Tiobon.Core.Model.Models; namespace Tiobon.Core.DataAccess; /// /// 报表辅助类 /// public static class ReportHelper { #region 文件下载 /// /// 生成文件,并通知用户下载(IQueryable) /// /// /// /// 导出模块名称(JobSetting.xxx) /// /// /// /// /// /// /// public static async Task SendFile(IQueryable list, string modelName, List exportFields, List exportFieldsWidth, string sort = null, string headText = "", string totalText = "", bool isNeedItemNo = false) where T : class { if (list == null) throw new Exception("生成文件失败"); //生成文件至文件服务器 var fid = SnowFlakeSingle.Instance.NextId(); var path = $"{$"{Environment.CurrentDirectory}{Path.DirectorySeparatorChar}wwwroot{Path.DirectorySeparatorChar}files{Path.DirectorySeparatorChar}export{Path.DirectorySeparatorChar}{fid}{Path.DirectorySeparatorChar}"}"; if (!Directory.Exists(path)) Directory.CreateDirectory(path); var fname = $"{modelName}.xlsx"; list = string.IsNullOrEmpty(sort) ? list : list.OrderBy(sort); list.IntoFileFromLinqExcel(path + fname, ",", exportFields, exportFieldsWidth, headText, totalText, isNeedItemNo); using var _context = ContextFactory.CreateContext(); Ghre_Attachment fileAttachment = new Ghre_Attachment(); fileAttachment.Id = fid; fileAttachment.AttachFileName = fname; fileAttachment.CreateBy = App.User.ID; fileAttachment.CreateTime = DateTime.Now; fileAttachment.AttachmentName = fname; fileAttachment.AttachFileExtension = "xlsx"; fileAttachment.AttachFileSize = 0; fileAttachment.PhysicsPath = $"/files/export/{fid}/" + fname; fileAttachment.AttachmentType = "xlsx"; await _context.Ghre_Attachment.AddAsync(fileAttachment); await _context.SaveChangesAsync(); return fid; } public static async Task SendFile(DataTable list, string modelName, Dictionary fieldDescs, List exportFieldsWidth, string sort = null, string headText = "", string totalText = "", bool isNeedItemNo = false) { if (list == null) throw new Exception("生成文件失败"); //生成文件至文件服务器 var fid = SnowFlakeSingle.Instance.NextId(); var path = $"{$"{Environment.CurrentDirectory}{Path.DirectorySeparatorChar}wwwroot{Path.DirectorySeparatorChar}files{Path.DirectorySeparatorChar}export{Path.DirectorySeparatorChar}{fid}{Path.DirectorySeparatorChar}"}"; if (!Directory.Exists(path)) Directory.CreateDirectory(path); var fname = $"{modelName}.xlsx"; list.IntoFileFromLinqExcel(path + fname, ",", fieldDescs, exportFieldsWidth, headText, totalText, isNeedItemNo); using var _context = ContextFactory.CreateContext(); Ghre_Attachment fileAttachment = new Ghre_Attachment(); fileAttachment.Id = fid; fileAttachment.AttachFileName = fname; fileAttachment.CreateBy = App.User.ID; fileAttachment.CreateTime = DateTime.Now; fileAttachment.AttachmentName = fname; fileAttachment.AttachFileExtension = "xlsx"; fileAttachment.AttachFileSize = 0; fileAttachment.PhysicsPath = $"/files/export/{fid}/" + fname; fileAttachment.AttachmentType = "xlsx"; await _context.Ghre_Attachment.AddAsync(fileAttachment); await _context.SaveChangesAsync(); return fid; } #endregion public static async Task ExportExcel(ISqlSugarClient Db, List tableColumn, DataTable dt) { string filepath = ""; //生成表格 try { IWorkbook fileWorkbook; bool IsHSSF = true; if (Path.GetExtension(filepath) == ".xls") { IsHSSF = true; fileWorkbook = new HSSFWorkbook(); } else { IsHSSF = false; fileWorkbook = new XSSFWorkbook(); } int index = 0; //创建Sheet; ISheet sheet = fileWorkbook.CreateSheet("导入数据"); ISheet sheet2 = fileWorkbook.CreateSheet("下拉数据"); //隐藏下拉数据Sheet //fileWorkbook.SetSheetHidden(fileWorkbook.GetSheetIndex("下拉数据"), SheetState.Hidden); IRow erow_1 = sheet.CreateRow(0); //ID行 IRow erow_2 = sheet.CreateRow(1); //文本行 erow_1.CreateCell(0).SetCellValue("ExcelNums"); erow_2.CreateCell(0).SetCellValue("序号"); //必填颜色 var CellRed = fileWorkbook.CreateCellStyle(); // 创建单元格样式 IFont Font = fileWorkbook.CreateFont(); // 创建字体 Font.Color = IndexedColors.Red.Index; // 选择字体颜色 CellRed.SetFont(Font); // 把字体赋给样式 erow_2.GetCell(0).CellStyle = CellRed; //文本类型 ICellStyle cellString = fileWorkbook.CreateCellStyle(); IDataFormat cellFormat = fileWorkbook.CreateDataFormat(); cellString.DataFormat = cellFormat.GetFormat("@"); //下拉数据列ID int listColIndex = 0; int ColNums = 0; foreach (var drow in tableColumn) { int SortNum = Convert.ToInt32(drow.sortNum); ICell cell = erow_1.CreateCell(SortNum); ICell cel2 = erow_2.CreateCell(SortNum); string field = drow.field; ; string label = drow.label; // 批注 string commentText = string.Empty; try { commentText = drow.commentText; } catch (Exception) { } cell.SetCellValue(field); cel2.SetCellValue(label); // 设置批注 if (!string.IsNullOrEmpty(commentText)) { cel2.CellComment = GetComment(sheet, null, ColNums, commentText); } //是否必填 if (drow.required == "true") { cel2.CellStyle = CellRed; } string dataSource = drow.dataSource; //是否下拉 if (!string.IsNullOrEmpty(dataSource) && !dataSource.StartsWith("OrgTreeWith") && !dataSource.StartsWith("StaffWith") ) { List dataSourceLists = GetDataSourceLists(Db, field, dataSource); //下拉数据行ID int listRowIndex = 1; //写入下拉值区域 IRow rowTitle = sheet2.GetRow(0); if (rowTitle == null) rowTitle = sheet2.CreateRow(0); rowTitle.CreateCell(listColIndex).SetCellValue(label); foreach (var data in dataSourceLists)//将下拉列表中的数据循环赋给sheet页 { IRow row = sheet2.GetRow(listRowIndex); if (row == null) row = sheet2.CreateRow(listRowIndex); listRowIndex = listRowIndex + 1; row.CreateCell(listColIndex).SetCellValue(data.name); } // 定义一个名称,指向刚才创建的下拉项的区域: var rangeName = field + "Range"; IName range = fileWorkbook.CreateName(); string ABC = Other.Num2ABCletter((listColIndex + 1)); //range.RefersToFormula = "下拉数据" + "!$"+ ABC + "$2:$"+ ABC + "$" + (listRowIndex == 0 ? 2 : listRowIndex); //Excel 正常引用 string a1 = "下拉数据" + "!$" + ABC + "$2:$" + ABC + "$" + (listRowIndex == 0 ? 2 : listRowIndex); // Excel R1C1引用样式 string a2 = "下拉数据" + "!$R2C" + listColIndex.ToString() + ":R" + listRowIndex.ToString() + "C" + listColIndex.ToString(); listColIndex = listColIndex + 1; range.RefersToFormula = a1; range.NameName = rangeName; //-----------------分割线以上是用来创建一个sheet页赋值,然后将sheet页中的内容定义成一个名称,后面用来当作数组传入方法的过程 CellRangeAddressList cellRegions = new CellRangeAddressList(1, 65535, SortNum, SortNum);// DVConstraint constraint = DVConstraint.CreateFormulaListConstraint(rangeName); //HSSFDataValidation dataValidate = new HSSFDataValidation(cellRegions, constraint); //IDataValidationConstraint constraint; IDataValidation dataValidate; if (Path.GetExtension(filepath) == ".xls") { constraint = DVConstraint.CreateFormulaListConstraint(rangeName); dataValidate = new HSSFDataValidation(cellRegions, constraint); } else { CT_DataValidation cdv = new CT_DataValidation(); cdv.allowBlank = true; //constraint = CT_DataValidation dataValidate = new XSSFDataValidation(cellRegions, cdv); } // 多选 ,自行输入不报错 if (drow.elementType.ToString().LastIndexOf("multiple") == -1) { dataValidate.CreateErrorBox("输入不合法", "请输入或选择下拉列表中的值。"); dataValidate.ShowPromptBox = true; } else { dataValidate.ShowErrorBox = false; } sheet.AddValidationData(dataValidate); } //是否文本格式 if (drow.dataType != "int" && drow.dataType != "decimal" && drow.dataType != "number" ) { sheet.SetDefaultColumnStyle(ColNums, cellString); } ColNums = ColNums + 1; } erow_1.HeightInPoints = 1; // 如果导出模板存在默认数据 //if (ds.Tables[1] != null && ds.Tables[1].Rows.Count > 0) for (int i = 0; i < dt.Rows.Count; i++) { IRow row1 = sheet.CreateRow(i + 2); for (int j = 0; j < dt.Columns.Count; j++) { ICell cell = row1.CreateCell(j); cell.SetCellValue(dt.Rows[i][j].ToString()); } } ////月排班维护写入下拉数据 //if (menuName == "F_SchedulePeriodSetup") //{ // string listSql = @" select ParaDetailNo 日期类别编号,ParaDetailName 日期类别名称 from Ghrs_ParaDetail where ParaMasterNo = 'DateType' and IsEnable = 1; // select ShiftNo 班次编号,ShiftName 班次名称 from Ghrb_Shift where IsEnable = 1; // select ShiftGroupNo 班组编号,ShiftGroupName 班组名称 from Ghrb_ShiftGroup where IsEnable = 1; "; // InsertExcelList(sheet2, listSql); //} //// 生成部门Sheet //if (tableColumn.Rows.Cast().Any(x => x["dataSource"].ToString().StartsWith("OrgTreeWith"))) //{ // ISheet sheetDept = fileWorkbook.CreateSheet("部门数据"); // string listSql = @" select DeptNo 部门编号,DeptName 部门名称 from Ghro_Dept where IsEnable = 1 and convert(date,getdate()) between BeginDate and ISNULL(EndDate,'2099-12-31') "; // InsertExcelList(sheetDept, listSql); //} // Sheet 更改列为自适应宽度 for (int col = 0; col <= ColNums; col++) { try { sheet.AutoSizeColumn(col);//自适应宽度,但是其实还是比实际文本要宽 var columnWidth = sheet.GetColumnWidth(col) / 256;//获取当前列宽度 for (int rowIndex = 1; rowIndex <= sheet.LastRowNum; rowIndex++) { IRow row = sheet.GetRow(rowIndex); ICell cell = row.GetCell(col); int contextLength = Encoding.UTF8.GetBytes(cell.ToString()).Length;//获取当前单元格的内容宽度 columnWidth = columnWidth < contextLength ? contextLength : columnWidth; } sheet.SetColumnWidth(col, columnWidth * 256);// } catch (Exception) { } } // Sheet2 更改列为自适应宽度 //if (listColIndex > 0) //{ // for (int col = 0; col <= listColIndex - 1; col++) // { // sheet2.AutoSizeColumn(col);//自适应宽度,但是其实还是比实际文本要宽 // int columnWidth = sheet2.GetColumnWidth(col) / 256;//获取当前列宽度 // for (int rowIndex = 1; rowIndex <= sheet2.LastRowNum; rowIndex++) // { // IRow row = sheet2.GetRow(rowIndex); // ICell cell = row.GetCell(col); // int contextLength = Encoding.UTF8.GetBytes(cell.ToString()).Length;//获取当前单元格的内容宽度 // columnWidth = columnWidth < contextLength ? contextLength : columnWidth; // } // sheet2.SetColumnWidth(col, columnWidth * 256);// // } //} //转为字节数组 MemoryStream stream = new MemoryStream(); fileWorkbook.Write(stream); var buf = stream.ToArray(); //保存为Excel文件 using (FileStream fs = new FileStream(filepath, FileMode.Create, FileAccess.Write)) { fs.Write(buf, 0, buf.Length); fs.Flush(); } } catch (Exception ex) { } return default(long); } /// /// Excel字段下拉 /// public class DataSourceList { public string field { get; set; } public string id { get; set; } public string no { get; set; } public string name { get; set; } } /// /// 设置Excel批注 /// /// sheet /// comment /// 列 /// 文本 /// private static IComment GetComment(ISheet sheet, IComment comment, int cellnum, string text) { IWorkbook workbook = sheet.Workbook; bool exportXlsx = workbook is XSSFWorkbook; if (comment == null) { IDrawing draw = sheet.CreateDrawingPatriarch(); IClientAnchor clientAnchor = null; if (exportXlsx) { clientAnchor = new XSSFClientAnchor(0, 0, 0, 0, cellnum, 0, cellnum + 2, 6); } else { clientAnchor = new HSSFClientAnchor(0, 0, 0, 0, cellnum, 0, cellnum + 2, 6); } comment = draw.CreateCellComment(clientAnchor); } IRichTextString richText = null; if (exportXlsx) { richText = new XSSFRichTextString(string.Format("{0}", text)); } else { richText = new HSSFRichTextString(string.Format("{0}", text)); } //richText.ApplyFont(GetDefaultFont(workbook, true));// 设置批注中文本的字体 comment.String = richText; comment.Visible = false; comment.Author = "Tiobon"; return comment; } /// /// 获取数据下拉 /// /// /// public static List GetDataSourceLists(ISqlSugarClient Db, string field, string dataSource) { List dataSourceList = new List(); try { ////Dept //if (dataSource.StartsWith("OrgTreeWith")) //{ //} ////Staff //else if (dataSource.StartsWith("StaffWith")) //{ //} //else { string listSQL = string.Format(@"exec[dbo].[PRI_ListValue] '{0}','GetEnableList','',1,63,'',9999,1,2", dataSource); DataSet listds = Db.Ado.GetDataSetAll(listSQL); if (listds.Tables.Count > 3) { DataTable listdt = new DataTable(); listdt = listds.Tables[2]; foreach (DataRow row in listdt.Rows) { DataSourceList _dataSource = new DataSourceList(); _dataSource.field = field; try { _dataSource.id = row["value"].ToString(); _dataSource.name = row["label"].ToString(); } catch (Exception) { _dataSource.id = row[0].ToString(); _dataSource.name = row[1].ToString(); try { _dataSource.name = _dataSource.name + " " + row[2].ToString(); } catch (Exception) { } } dataSourceList.Add(_dataSource); } } } } catch (Exception) { } return dataSourceList; } /// /// /// /// /// 需要写入的查询的SQL /// 开始行 /// 开始列 /// public static bool InsertExcelList(ISqlSugarClient Db, ISheet sheet, string sql) { bool IsBool = false; DataSet ds = Db.Ado.GetDataSetAll(sql); //写入下拉值区域 int cols = 0; foreach (DataTable dt in ds.Tables) { int col = 0; //表头 IRow row = sheet.GetRow(0); if (row == null) row = sheet.CreateRow(0); for (int i = 0; i < dt.Columns.Count; i++) { ICell cell = row.CreateCell(i + cols); cell.SetCellValue(dt.Columns[i].ColumnName); col++; } //数据 for (int i = 0; i < dt.Rows.Count; i++) { IRow row1 = sheet.GetRow(i + 1); if (row1 == null) row1 = sheet.CreateRow(i + 1); for (int j = 0; j < dt.Columns.Count; j++) { ICell cell = row1.CreateCell(j + cols); cell.SetCellValue(dt.Rows[i][j].ToString()); } } cols = cols + col + 1; } return IsBool; } #region 其他 public class Other { /// /// 数字转ADC字母 /// /// /// public static string Num2ABCletter([Range(1, 300)] int value) { List Level = new List { "A","B","C","D","E","F","G","H","I","J", "K","L","M","N","O","P","Q","R","S","T", "U","V","W","X","Y","Z", }; value = value - 1; System.Text.ASCIIEncoding asciiEncoding = new System.Text.ASCIIEncoding(); int remainder = value % 26;//余数 int front = (value - remainder) / 26;// if (front == 0) { return Level[remainder]; } else if (front < 26) { return Level[front - 1] + Level[remainder]; } else { return Num2ABCletter(front) + Level[remainder]; } } } #endregion }