1.新增通用导出excel接口,与表单编辑页数据关联

master
xiaochanghai 1 year ago
parent 2955072dfe
commit e22a28ec92
  1. 13
      Tiobon.Core.Api/Controllers/CommonController.cs
  2. 7
      Tiobon.Core.Api/Tiobon.Core.xml
  3. 60
      Tiobon.Core.Common/Attribute/QueryFilter.cs
  4. 206
      Tiobon.Core.Common/Extensions/IQueryableExtensions.cs
  5. 33
      Tiobon.Core.DataAccess/ReportHelper.cs
  6. 3
      Tiobon.Core.IServices/ICommonServices.cs
  7. 8
      Tiobon.Core.Model/ViewModels/Extend/CommonSelectItem.cs
  8. 20
      Tiobon.Core.Services/BASE/BaseServices.cs
  9. 89
      Tiobon.Core.Services/CommonServices.cs

@ -61,4 +61,17 @@ public class CommonController : BaseApiController
return await _commonServices.GetSelectAsync(type); return await _commonServices.GetSelectAsync(type);
} }
#endregion #endregion
#region 导出Excel
/// <summary>
/// 导出Excel
/// </summary>
/// <param name="param"></param>
/// <returns></returns>
[HttpPost, Route("ExportExcel")]
public async Task<ServiceResult<QueryExportReturn>> ExportExcelAsync([FromBody] QueryExport param)
{
return await _commonServices.ExportExcelAsync(param);
}
#endregion
} }

@ -258,6 +258,13 @@
<param name="type"></param> <param name="type"></param>
<returns></returns> <returns></returns>
</member> </member>
<member name="M:Tiobon.Core.Controllers.CommonController.ExportExcelAsync(Tiobon.Core.Common.QueryExport)">
<summary>
导出Excel
</summary>
<param name="param"></param>
<returns></returns>
</member>
<member name="M:Tiobon.Core.Controllers.DbFirstController.#ctor(SqlSugar.ISqlSugarClient,Microsoft.AspNetCore.Hosting.IWebHostEnvironment)"> <member name="M:Tiobon.Core.Controllers.DbFirstController.#ctor(SqlSugar.ISqlSugarClient,Microsoft.AspNetCore.Hosting.IWebHostEnvironment)">
<summary> <summary>
构造函数 构造函数

@ -1,5 +1,6 @@
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
using Newtonsoft.Json.Linq; using Newtonsoft.Json.Linq;
using Tiobon.Core.Model;
namespace Tiobon.Core.Common; namespace Tiobon.Core.Common;
@ -117,9 +118,45 @@ public class QueryForm
public string timestamp { get; set; } public string timestamp { get; set; }
public string userId { get; set; } public string userId { get; set; }
private JObject _jsonParam; private JObject _jsonParam;
public JObject jsonParam
{
get { return _jsonParam; }
set
{
_jsonParam = value;
}
}
}
public class QueryExportField
{
public List<string> ExFields { get; set; }
public string IsTitle { get; set; }
public string TitleName { get; set; }
}
/// <summary> /// <summary>
/// 查询条件( 例如:id = 1 and name = 小明) /// 动态查询条件
/// </summary> /// </summary>
public class QueryExport
{
public string commonType { get; set; }
public QueryExportField exportSet { get; set; }
public string getDataType { get; set; }
private JObject _jsonParam;
public int langId { get; set; }
public string menuName { get; set; }
public string orderBy { get; set; }
public int pageNum { get; set; }
public int pageSize { get; set; }
public string token { get; set; }
public string procName { get; set; }
public string timestamp { get; set; }
public string userId { get; set; }
public JObject jsonParam public JObject jsonParam
{ {
get { return _jsonParam; } get { return _jsonParam; }
@ -130,3 +167,24 @@ public class QueryForm
} }
} }
public class QueryExportColumn
{
public int sortNum { get; set; }
public string label { get; set; }
public string field { get; set; }
public string dataSource { get; set; }
public string required { get; set; }
public string dataType { get; set; }
public string elementType { get; set; }
}
public class QueryExportReturn
{
public JM_PageControlT1 JM_PageControlT1 { get; set; } = new JM_PageControlT1();
public JM_TableColumnT1 JM_TableColumnT1 { get; set; } = new JM_TableColumnT1();
public List<DT_PageMutiMsg> DT_PageMutiMsg { get; set; }
public DT_Procedure DT_Procedure { get; set; } = new DT_Procedure();
}

@ -1,5 +1,7 @@
using System.Collections; using System.Collections;
using System.Collections.Generic;
using System.ComponentModel; using System.ComponentModel;
using System.Data;
using System.Reflection; using System.Reflection;
using OfficeOpenXml; using OfficeOpenXml;
using OfficeOpenXml.Style; using OfficeOpenXml.Style;
@ -169,6 +171,143 @@ public static class IQueryableExtensions
} }
LoggerHelper.SendLog("生成文件 " + fname + " 完毕 " + dbCount + " 耗时 " + (int)(DateTime.Now - dt_start).TotalSeconds); LoggerHelper.SendLog("生成文件 " + fname + " 完毕 " + dbCount + " 耗时 " + (int)(DateTime.Now - dt_start).TotalSeconds);
} }
public static void IntoFileFromLinqExcel(this DataTable db, string fname, string splitstr, Dictionary<string, string> fieldDescs, List<int> exportFieldsWidth, string headText = "", string totalText = "", bool isNeedItemNo = false)
{
if (db.IsNull())
return;
//查询文件状态
if (File.Exists(fname))
{
LoggerHelper.SendLog("文件已生成 " + fname);
return;
}
LoggerHelper.SendLog("正在生成文件 " + fname);
DateTime dt_start = DateTime.Now;
if (!File.Exists(fname))
File.Create(fname).Close();
//获取需要导出的字段
int dbCount = db.Rows.Count;
//列名排序,返回有序列表
var (fields, colunms) = Sort(fieldDescs, null);
using (FileStream stream = File.Create(fname))
{
using (ExcelPackage package = new ExcelPackage(stream))
{
ExcelWorksheet worksheet = package.Workbook.Worksheets.Add("sheet1");
var colunmsCount = colunms.Count;
var startCol = 0;
var startRow = 1; // 初始行数
if (isNeedItemNo)
startCol = 1;
if (!string.IsNullOrEmpty(headText))
{
worksheet.Cells[startRow, 1].Value = headText;
worksheet.Cells[startRow, 1, 1, colunmsCount + startCol].Merge = true;
worksheet.Cells[startRow, 1, 1, colunmsCount + startCol].Style.Font.Bold = true;
worksheet.Cells[startRow, 1, 1, colunmsCount + startCol].Style.HorizontalAlignment = ExcelHorizontalAlignment.Center; // Alignment is center
worksheet.Cells[startRow, 1, 1, colunmsCount + startCol].Style.Font.Size = 14;
startRow++;
}
if (isNeedItemNo)
{
worksheet.Cells[startRow, 1].Value = "序号";
worksheet.Cells[startRow, 1, startRow, 1].Style.Font.Bold = true;
worksheet.Cells[startRow, 1, startRow, 1].Style.VerticalAlignment = OfficeOpenXml.Style.ExcelVerticalAlignment.Center;
worksheet.Cells[startRow, 1, startRow, 1].Style.HorizontalAlignment = OfficeOpenXml.Style.ExcelHorizontalAlignment.Center;
}
//写入列名
for (int i = 0; i < fields.Count; ++i)
{
worksheet.Cells[startRow, i + 1 + startCol].Value = fields[i];
worksheet.Cells[startRow, i + 1 + startCol, startRow, i + 1 + startCol].Style.Font.Bold = true;
worksheet.Cells[startRow, i + 1 + startCol, startRow, i + 1 + startCol].Style.VerticalAlignment = OfficeOpenXml.Style.ExcelVerticalAlignment.Center;
worksheet.Cells[startRow, i + 1 + startCol, startRow, i + 1 + startCol].Style.HorizontalAlignment = OfficeOpenXml.Style.ExcelHorizontalAlignment.Center;
}
startRow++;
for (int row = 0; row < dbCount; ++row)
{
if (isNeedItemNo)
{
worksheet.Cells[row + startRow, 1].Value = row + 1;
worksheet.Cells[row + startRow, 1, row + startRow, 1].Style.VerticalAlignment = OfficeOpenXml.Style.ExcelVerticalAlignment.Center;
worksheet.Cells[row + startRow, 1, row + startRow, 1].Style.HorizontalAlignment = OfficeOpenXml.Style.ExcelHorizontalAlignment.Center;
}
//遍历需要写入文件的字段
for (int i = 0; i < colunms.Count; ++i)
{
worksheet.Cells[row + startRow, i + 1 + startCol].Value = db.Rows[row][colunms[i]].ToString();
worksheet.Cells[row + startRow, i + 1 + startCol, row + startRow, i + 1 + startCol].Style.VerticalAlignment = OfficeOpenXml.Style.ExcelVerticalAlignment.Center;
worksheet.Cells[row + startRow, i + 1 + startCol, row + startRow, i + 1 + startCol].Style.HorizontalAlignment = OfficeOpenXml.Style.ExcelHorizontalAlignment.Center;
}
}
if (!string.IsNullOrEmpty(totalText))
{
worksheet.Cells[dbCount + startRow, 1].Value = "总计:";
worksheet.Cells[dbCount + startRow, 1, dbCount + startRow, 1].Style.VerticalAlignment = OfficeOpenXml.Style.ExcelVerticalAlignment.Center;
worksheet.Cells[dbCount + startRow, 1, dbCount + startRow, 1].Style.HorizontalAlignment = OfficeOpenXml.Style.ExcelHorizontalAlignment.Center;
worksheet.Cells[dbCount + startRow, 2, dbCount + startRow, colunms.Count + startCol].Value = totalText;
worksheet.Cells[dbCount + startRow, 2, dbCount + startRow, colunms.Count + startCol].Merge = true;
startRow++;
}
using (ExcelRange r = worksheet.Cells[1, 1, dbCount + startRow - 1, fields.Count + startCol])
{
r.Style.Border.Top.Style = ExcelBorderStyle.Thin;
r.Style.Border.Left.Style = ExcelBorderStyle.Thin;
r.Style.Border.Right.Style = ExcelBorderStyle.Thin;
r.Style.Border.Bottom.Style = ExcelBorderStyle.Thin;
r.Style.Border.Top.Color.SetColor(Color.Black);
r.Style.Border.Left.Color.SetColor(Color.Black);
r.Style.Border.Right.Color.SetColor(Color.Black);
r.Style.Border.Bottom.Color.SetColor(Color.Black);
}
if (isNeedItemNo)
{
worksheet.Column(1).Width = 20;//设置列宽为默认值
}
//设置列宽
if (exportFieldsWidth == null || exportFieldsWidth.Count < fields.Count)
{
for (int i = 0; i < fields.Count; ++i)
{
worksheet.Column(i + 1 + startCol).Width = 20;//设置列宽为默认值
}
}
else
{
for (int i = 0; i < fields.Count; ++i)
{
worksheet.Column(i + 1 + startCol).Width = exportFieldsWidth[i];//设置列宽为前段配置的值
}
}
package.Workbook.Properties.Title = "数据导出";
package.Workbook.Properties.Author = "SUZHOUEU";
package.Workbook.Properties.Comments = "苏州一优信息技术有限公司提供技术支持!";
package.Workbook.Properties.Company = "苏州一优信息技术有限公司";
package.Workbook.Properties.SetCustomPropertyValue("Checked by", "SimonHsiao");
package.Workbook.Properties.SetCustomPropertyValue("AssemblyName", "SUZHOUEU");
package.Save();
}
}
LoggerHelper.SendLog("生成文件 " + fname + " 完毕 " + dbCount + " 耗时 " + (int)(DateTime.Now - dt_start).TotalSeconds);
}
private static string ConvertData2String<T>(T t, string field) where T : class private static string ConvertData2String<T>(T t, string field) where T : class
{ {
if (t.FieldTypeIsDateTime(field)) if (t.FieldTypeIsDateTime(field))
@ -225,73 +364,6 @@ public static class IQueryableExtensions
return (fields, colunms); return (fields, colunms);
} }
/// <summary>
/// 获取数据
/// </summary>
/// <param name="obj">对象</param>
/// <param name="colunms"></param>
/// <returns></returns>
public static List<string> GetPropertyData<T>(T obj, List<string> colunms) where T : class
{
List<string> data = new List<string>();
//声明obj的类型
Type type = obj.GetType();
// 获取obj类型的所有属性信息
System.Reflection.PropertyInfo[] PropertyList = type.GetProperties();
//循环每一个属性
foreach (var item in PropertyList)
{
// 获取自定义特性
object[] export = item.GetCustomAttributes(typeof(ExportDatatAttribute), true);
object[] descript = item.GetCustomAttributes(typeof(DescriptionAttribute), true);
//判断是否需要导出
if (export.Length > 0)
{
//取值
var exdesc = ((ExportDatatAttribute)export[0]);
// 是否嵌套
if (exdesc != null)
{
//是否是序列
if (exdesc.ExportDataFlag == "1")
{
var tmp = item.GetValue(obj) as IEnumerable; //List<ItemDetail>
if (tmp != null)
{
foreach (var o in tmp)
{
data.AddRange(GetPropertyData(o, colunms));
}
}
}
// 如果是嵌套model
else if (exdesc.ExportDataFlag == "2")
{
var tmp = item.GetValue(obj);
if (tmp != null)
{
data.AddRange(GetPropertyData(tmp, colunms));
}
}
else if (exdesc.ExportDataFlag == "3")
{
if (colunms.Contains(item.Name))
{
data.Add(item.GetValue(obj).ToString());
}
}
}
}
else if (descript.Length > 0)
{
if (colunms.Contains(item.Name))
{
data.Add(item.GetValue(obj).ToString());
}
}
}
return data;
}
#region 获取字段描述 #region 获取字段描述
/// <summary> /// <summary>

@ -1,5 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Data;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Linq.Dynamic.Core; using System.Linq.Dynamic.Core;
@ -63,6 +64,38 @@ public static class ReportHelper
await _context.SaveChangesAsync(); await _context.SaveChangesAsync();
return fid; return fid;
} }
public static async Task<long> SendFile (DataTable list, string modelName, Dictionary<string, string> fieldDescs, List<int> 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 #endregion
} }

@ -1,4 +1,5 @@
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Tiobon.Core.Common;
using Tiobon.Core.IServices.BASE; using Tiobon.Core.IServices.BASE;
using Tiobon.Core.Model; using Tiobon.Core.Model;
@ -21,4 +22,6 @@ public interface ICommonServices : IBaseServices<RootEntityTkey<int>>
Task<ServiceResult<ModuleReturn>> GetModuleInfoAsync([FromBody] ModuleParam param); Task<ServiceResult<ModuleReturn>> GetModuleInfoAsync([FromBody] ModuleParam param);
Task<ServiceResult<CommonSelect>> GetSelectAsync(string type); Task<ServiceResult<CommonSelect>> GetSelectAsync(string type);
Task<ServiceResult<QueryExportReturn>> ExportExcelAsync(QueryExport param);
} }

@ -0,0 +1,8 @@
namespace Tiobon.Core.Model;
public class CommonSelectItem
{
public string value { get; set; }
public string label { get; set; }
}

@ -686,6 +686,26 @@ public class BaseServices<TEntity, TEntityDto, TInsertDto, TEditDto> : IBaseServ
} }
public async Task<ServiceResult<long>> Export(QueryBody body) public async Task<ServiceResult<long>> Export(QueryBody body)
{ {
//sql = @$"SELECT field,
// [dbo].[FLangKeyToValue] (mkey, {body.langId}, label)
// label,
// required,
// editable,
// rowNum,
// colNum,
// elementType,
// dbo.FS_GetdataSourceBySet
// (dataSource, APIDataSourceType, Ghrs_PageSettingEdit.APIDataSourceID)
// dataSource,
// defaultHidden,
// isPrimaryKey,
// isSingleColumn
// FROM Ghrs_PageSettingEdit
// WHERE IsEnable = 1
// AND pageNo = '{body.menuName}'
// AND elementType NOT IN ('FnKey', 'PageGroup');";
//dt = await Db.Ado.GetDataTableAsync(sql);
var data = await BaseDal.QueryFilterPage(body); var data = await BaseDal.QueryFilterPage(body);
var fileId = await ReportHelper.SendFile(data.result.DT_TableDataT1.AsQueryable(), $"测试测试", null, null, null, null); var fileId = await ReportHelper.SendFile(data.result.DT_TableDataT1.AsQueryable(), $"测试测试", null, null, null, null);
return ServiceResult<long>.OprateSuccess("导出成功", fileId); return ServiceResult<long>.OprateSuccess("导出成功", fileId);

@ -9,6 +9,7 @@ using Newtonsoft.Json.Linq;
using SqlSugar; using SqlSugar;
using Tiobon.Core.Common; using Tiobon.Core.Common;
using Tiobon.Core.Common.DB.Dapper; using Tiobon.Core.Common.DB.Dapper;
using Tiobon.Core.DataAccess;
using Tiobon.Core.IServices; using Tiobon.Core.IServices;
using Tiobon.Core.Model; using Tiobon.Core.Model;
using Tiobon.Core.Services.BASE; using Tiobon.Core.Services.BASE;
@ -1138,4 +1139,92 @@ public partial class CommonServices : BaseServices<RootEntityTkey<int>>, ICommon
} }
#endregion #endregion
#region Export
public async Task<ServiceResult<QueryExportReturn>> ExportExcelAsync(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<QueryExportColumn>(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");
// 获取所有列名
var dtColumns = dt.Columns;
var convertColumns = columns.Where(x => !string.IsNullOrEmpty(x.dataSource) && !string.IsNullOrEmpty(x.elementType)).ToList();
for (int i = 0; i < convertColumns.Count; i++)
{
dt.Columns.Add(convertColumns[i].field + "1", typeof(string));
//var values = dt.AsEnumerable().Select(row => row.Field<string>(column.field)).Distinct().ToList();
sql = $@"SELECT SelectSql from Ghrs_ListCommonSql WHERE ListCommonSqlNo=REPLACE('{convertColumns[i].dataSource}','CommonList_','') and IsEnable=1 ";
sql = await Db.Ado.GetScalarAsync(sql) as string;
sql = sql.Replace("{@KeyWords}", null);
var dtSelect = await Db.Ado.SqlQueryAsync<CommonSelectItem>(sql);
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);
return new ServiceResult<QueryExportReturn>() { Success = true, Message = "查询成功", Data = result, };
}
#endregion
} }

Loading…
Cancel
Save