You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
554 lines
22 KiB
554 lines
22 KiB
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;
|
|
|
|
/// <summary>
|
|
/// 报表辅助类
|
|
/// </summary>
|
|
public static class ReportHelper
|
|
{
|
|
|
|
#region 文件下载
|
|
/// <summary>
|
|
/// 生成文件,并通知用户下载(IQueryable)
|
|
/// </summary>
|
|
/// <typeparam name="T"></typeparam>
|
|
/// <param name="list"></param>
|
|
/// <param name="modelName">导出模块名称(JobSetting.xxx)</param>
|
|
/// <param name="exportFields"></param>
|
|
/// <param name="exportFieldsWidth"></param>
|
|
/// <param name="user"></param>
|
|
/// <param name="sort"></param>
|
|
/// <param name="headText"></param>
|
|
/// <param name="totalText"></param>
|
|
/// <param name="isNeedItemNo"></param>
|
|
public static async Task<long> SendFile<T>(IQueryable<T> list, string modelName, List<string> exportFields, List<int> 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<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
|
|
|
|
|
|
public static async Task<long> ExportExcel(ISqlSugarClient Db, List<QueryExportColumn> 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<DataSourceList> 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<DataRow>().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);
|
|
}
|
|
/// <summary>
|
|
/// Excel字段下拉
|
|
/// </summary>
|
|
public class DataSourceList
|
|
{
|
|
public string field { get; set; }
|
|
public string id { get; set; }
|
|
public string no { get; set; }
|
|
public string name { get; set; }
|
|
} /// <summary>
|
|
/// 设置Excel批注
|
|
/// </summary>
|
|
/// <param name="sheet"> sheet</param>
|
|
/// <param name="comment"> comment </param>
|
|
/// <param name="cellnum"> 列 </param>
|
|
/// <param name="text">文本</param>
|
|
/// <returns></returns>
|
|
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;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 获取数据下拉
|
|
/// </summary>
|
|
/// <param name="dataSource"></param>
|
|
/// <returns></returns>
|
|
public static List<DataSourceList> GetDataSourceLists(ISqlSugarClient Db, string field, string dataSource)
|
|
{
|
|
List<DataSourceList> dataSourceList = new List<DataSourceList>();
|
|
|
|
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;
|
|
}
|
|
|
|
/// <summary>
|
|
///
|
|
/// </summary>
|
|
/// <param name="sheet"></param>
|
|
/// <param name="sql">需要写入的查询的SQL</param>
|
|
/// <param name="rows">开始行</param>
|
|
/// <param name="cols">开始列</param>
|
|
/// <returns></returns>
|
|
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
|
|
{
|
|
/// <summary>
|
|
/// 数字转ADC字母
|
|
/// </summary>
|
|
/// <param name="value"></param>
|
|
/// <returns></returns>
|
|
public static string Num2ABCletter([Range(1, 300)] int value)
|
|
{
|
|
List<string> Level = new List<string>
|
|
{
|
|
"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
|
|
} |