From 5c0e07ab494d0bc3e454fcb78c90c409b5eb3807 Mon Sep 17 00:00:00 2001 From: xiaochanghai Date: Tue, 21 May 2024 15:29:50 +0800 Subject: [PATCH] =?UTF-8?q?2.=E4=BF=AE=E5=A4=8D=E9=A2=98=E5=BA=93=E6=8F=90?= =?UTF-8?q?=E4=BA=A4=E7=BC=BA=E9=99=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Tiobon.Core.Common/Attribute/QueryFilter.cs | 3 + Tiobon.Core.DataAccess/ReportHelper.cs | 457 +++++++++++++++++- .../Tiobon.Core.DataAccess.csproj | 1 + .../Tiobon.Core.PublishHelper.csproj | 4 +- Tiobon.Core.Services/CommonServices.cs | 85 +++- .../Ghre/Ghre_QuestionServices.cs | 7 +- Tiobon.Core/Tiobon.Core.xml | 7 + 7 files changed, 541 insertions(+), 23 deletions(-) diff --git a/Tiobon.Core.Common/Attribute/QueryFilter.cs b/Tiobon.Core.Common/Attribute/QueryFilter.cs index 5fcddc66..0fee06e0 100644 --- a/Tiobon.Core.Common/Attribute/QueryFilter.cs +++ b/Tiobon.Core.Common/Attribute/QueryFilter.cs @@ -178,6 +178,9 @@ public class QueryExportColumn public string dataType { get; set; } public string elementType { get; set; } + public string commentText { get; set; } + + } public class QueryExportReturn diff --git a/Tiobon.Core.DataAccess/ReportHelper.cs b/Tiobon.Core.DataAccess/ReportHelper.cs index 34dca1a3..dffe7c38 100644 --- a/Tiobon.Core.DataAccess/ReportHelper.cs +++ b/Tiobon.Core.DataAccess/ReportHelper.cs @@ -1,15 +1,24 @@ 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; +using Tiobon.Core.Common.DB.Dapper; using Tiobon.Core.Common.Extensions; using Tiobon.Core.Model.Models; + namespace Tiobon.Core.DataAccess; /// @@ -65,7 +74,7 @@ public static class ReportHelper 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) + 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) @@ -98,4 +107,448 @@ public static class ReportHelper } #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 } \ No newline at end of file diff --git a/Tiobon.Core.DataAccess/Tiobon.Core.DataAccess.csproj b/Tiobon.Core.DataAccess/Tiobon.Core.DataAccess.csproj index e93aad94..0e7e6858 100644 --- a/Tiobon.Core.DataAccess/Tiobon.Core.DataAccess.csproj +++ b/Tiobon.Core.DataAccess/Tiobon.Core.DataAccess.csproj @@ -28,6 +28,7 @@ + diff --git a/Tiobon.Core.PublishHelper/Tiobon.Core.PublishHelper.csproj b/Tiobon.Core.PublishHelper/Tiobon.Core.PublishHelper.csproj index 37835400..ba3b599e 100644 --- a/Tiobon.Core.PublishHelper/Tiobon.Core.PublishHelper.csproj +++ b/Tiobon.Core.PublishHelper/Tiobon.Core.PublishHelper.csproj @@ -48,9 +48,7 @@ Form - - Form - + Form diff --git a/Tiobon.Core.Services/CommonServices.cs b/Tiobon.Core.Services/CommonServices.cs index 33d2ec10..1c90a8bd 100644 --- a/Tiobon.Core.Services/CommonServices.cs +++ b/Tiobon.Core.Services/CommonServices.cs @@ -1,5 +1,4 @@ using System.Data; -using System.Drawing; using AgileObjects.AgileMapper; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; @@ -924,11 +923,11 @@ public partial class CommonServices : BaseServices>, ICommon } #endregion - #region 获取模块信息 + #region 获取通用列表下拉 /// - /// 获取模块信息 + /// 获取通用列表下拉 /// - /// + /// /// public async Task> GetSelectAsync(string type) { @@ -1139,7 +1138,12 @@ public partial class CommonServices : BaseServices>, ICommon } #endregion - #region Export + #region Excel导出 + /// + /// Excel导出 + /// + /// + /// public async Task> ExportExcelAsync(QueryExport param) { var result = new QueryExportReturn(); @@ -1183,8 +1187,6 @@ public partial class CommonServices : BaseServices>, ICommon AND dataType ! = ''"; var columns = await Db.Ado.SqlQueryAsync(sql); - - columns = columns.WhereIF(param.exportSet.ExFields.Any(), x => param.exportSet.ExFields.Contains(x.field)).ToList(); dt = await Db.Ado.GetDataTableAsync("SELECT * FROM " + tableNmae + " WHERE IsEnable=1"); @@ -1206,22 +1208,73 @@ public partial class CommonServices : BaseServices>, ICommon foreach (DataColumn column in dtColumns) { if (column.ColumnName == convertColumns[i].field) - { - //column.DataType = typeof(string); - //dt.AcceptChanges(); for (int j = 0; j < dt.Rows.Count; j++) - { dt.Rows[j][column.ColumnName + "1"] = dtSelect.FirstOrDefault(x => x.value == dt.Rows[j][column.ColumnName].ToString())?.label; - } - } - } - } var fieldDescs = columns.ToDictionary(item => item.label, item => convertColumns.Any(x => x.field == item.field) ? item.field + "1" : item.field); - var fileId = await ReportHelper.SendFile(dt, $"测试测试", fieldDescs, null, null, null); + var fileId = await ReportHelper.SendFile(dt, param.exportSet.TitleName, fieldDescs, null, null, null); + + return new ServiceResult() { Success = true, Message = "查询成功", Data = result, }; + } + #endregion + + #region Excel导入模板 + /// + /// Excel导入模板 + /// + /// + /// + public async Task> ImportTemplateAsync(QueryExport param) + { + var result = new QueryExportReturn(); + + var tableNmae = string.Empty; + string sql = "select QueryProcedure, EditProcedure, IUDProcedure from Ghrs_Menu where MenuNo='{0}'"; + sql = string.Format(sql, param.menuName); + var dt = await Db.Ado.GetDataTableAsync(sql); + if (dt.Rows.Count > 0) + { + string queryProcedure = dt.Rows[0]["QueryProcedure"].ToString(); + + string[] aaa = queryProcedure.Split('/'); + tableNmae = aaa[1]; + } + + sql = $@"SELECT Row_Number () + OVER (ORDER BY CONVERT (INT, rowNum), CONVERT (INT, colNum)) + sortNum, + field, + [dbo].[FLangKeyToValue] (mkey, 1, label) + label, + dbo.FS_GetdataSourceBySet + (dataSource, APIDataSourceType, Ghrs_PageSettingEdit.APIDataSourceID) + dataSource, + required, + dataType, + CONVERT (NVARCHAR (1000), '') + commentText -- StaffWith + , + elementType + + CASE WHEN multipleSelect = 'true' THEN '_multiple' ELSE '' END + elementType -- 增加多选判断 + FROM Ghrs_PageSettingEdit + WHERE IsEnable = 1 + AND elementType NOT IN ('FnKey', 'PageGroup') + AND pageNo = 'F_Training_Course' + --and editable = 'true' + AND defaultHidden ! = 'true' + AND elementType ! = 'FileUpload' + AND dataType ! = ''"; + + var columns = await Db.Ado.SqlQueryAsync(sql); + columns = columns.WhereIF(param.exportSet.ExFields.Any(), x => param.exportSet.ExFields.Contains(x.field)).ToList(); + + dt = await Db.Ado.GetDataTableAsync("SELECT * FROM " + tableNmae + " WHERE IsEnable=1"); + ReportHelper.ExportExcel(Db, columns, dt); + return new ServiceResult() { Success = true, Message = "查询成功", Data = result, }; } diff --git a/Tiobon.Core.Services/Ghre/Ghre_QuestionServices.cs b/Tiobon.Core.Services/Ghre/Ghre_QuestionServices.cs index da168cc8..20ea091d 100644 --- a/Tiobon.Core.Services/Ghre/Ghre_QuestionServices.cs +++ b/Tiobon.Core.Services/Ghre/Ghre_QuestionServices.cs @@ -648,9 +648,12 @@ public class Ghre_QuestionServices : BaseServices + + + 导出Excel + + + + 构造函数