using Microsoft.Office.Interop.Excel;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using XYY.Core.Standard.AliYun;
namespace XYY.Core.Standard.ExcelHelper.MSExcelHelper
{
///
/// 默认值配置
///
public struct ExcelMappingConfig
{
///
/// 列最长宽度
///
public int CoulmnMaxWidht => 50;
}
public class MSExcelHelper : IExcelHelper
{
[DllImport("User32.dll", CharSet = CharSet.Auto)]
public static extern int GetWindowThreadProcessId(IntPtr hwnd, out int ID);
public static void Kill(Microsoft.Office.Interop.Excel.Application excel)
{
IntPtr t = new IntPtr(excel.Hwnd); //得到这个句柄,具体作用是得到这块内存入口
int k = 0;
GetWindowThreadProcessId(t, out k); //得到本进程唯一标志k
System.Diagnostics.Process p = System.Diagnostics.Process.GetProcessById(k); //得到对进程k的引用
p.Kill(); //关闭进程k
}
IAliYunPostFileSerivce _aliYunPostFileSerivce;
public MSExcelHelper(IAliYunPostFileSerivce aliYunPostFileSerivce)
{
_aliYunPostFileSerivce = aliYunPostFileSerivce;
}
public MSExcelHelper()
{
}
public string OutData(List data) where Mapping : MSExcelClassMapping
{
string filename = OutLocalData(data);
string url = _aliYunPostFileSerivce.GetPublicCDN(_aliYunPostFileSerivce.PostMd5File(filename, "temp\\" + Guid.NewGuid().ToString()));
//清理临时文件
System.IO.File.Delete(filename);
return url;
}
public string OutData(List data, string fileName) where Mapping : MSExcelClassMapping
{
string filename = OutLocalData(data);
string url = _aliYunPostFileSerivce.GetPublicCDN(_aliYunPostFileSerivce.PostMd5File(filename, fileName));
//清理临时文件
System.IO.File.Delete(filename);
return url;
}
public int GetRowCount(Worksheet worksheet)
{
return worksheet.Cells.Find("*", System.Reflection.Missing.Value,
System.Reflection.Missing.Value, System.Reflection.Missing.Value,
Microsoft.Office.Interop.Excel.XlSearchOrder.xlByRows, Microsoft.Office.Interop.Excel.XlSearchDirection.xlPrevious,
false, System.Reflection.Missing.Value, System.Reflection.Missing.Value).Row;
}
public List LoadData(string fileName) where Mapping : MSExcelClassMapping
{
Microsoft.Office.Interop.Excel.Application app = new Microsoft.Office.Interop.Excel.Application();
try
{
app.Visible = false; //不显示EXCEL
app.DisplayAlerts = false; //不提示信息
app.ScreenUpdating = false; //停止更新屏幕,加快速度
Workbooks wbs = app.Workbooks; //获取工作薄
_Workbook wb = wbs.Add(fileName);
Microsoft.Office.Interop.Excel.Range range;
List list = new List();
var mapping = CreateT();
List sheetNames = new List();
foreach (Microsoft.Office.Interop.Excel.Worksheet item in wb.Sheets)
{
if (item.Rows.Row > 0)
{
sheetNames.Add(item.Name);
}
}
var sheetsIndex = mapping.SheetIndexs(sheetNames);
foreach (var si in sheetsIndex)
{
Worksheet sh = (Worksheet)wb.Sheets[si];
range = sh.get_Range("A1", Missing.Value);
var rowCount = GetRowCount(sh);
var colCount = range.get_End(XlDirection.xlToRight).Column;
if (rowCount > 0)
{
range = range.get_Resize(rowCount, colCount);
object[,] value22 = (object[,])range.Value2;
///获取Map与列序号的映射关系
Dictionary keyValuePairs = new Dictionary();
for (int i = 0; i < mapping.Items.Count; i++)
{
for (int j = 0; j < colCount; j++)
{
if (mapping.Items[i].ColumnName == value22[1, j + 1].ToString())
{
keyValuePairs.Add(i, j + 1);
continue;
}
}
}
for (int iRow = 1; iRow < rowCount; iRow++)
{
var item = CreateT();
for (int iCol = 0; iCol < mapping.Items.Count; iCol++)
{
try
{
if (keyValuePairs.ContainsKey(iCol))
{
var value = value22[iRow + 1, keyValuePairs[iCol]];
if (value != null)
{
var c = mapping.Items[iCol].PropertyInfo;
if (c.PropertyType == typeof(int))
{
c.SetValue(item, Convert.ToInt32(Convert.ToDecimal(value.ToString())));
}
else if (c.PropertyType == typeof(DateTime) || c.PropertyType == typeof(DateTime?))
{
c.SetValue(item, DateTime.FromOADate((double)value));
}
else if (c.PropertyType == typeof(decimal))
{
c.SetValue(item, Convert.ToDecimal(value.ToString()));
}
else if (c.PropertyType == typeof(string))
{
c.SetValue(item, value.ToString());
}
else
{
c.SetValue(item, value);
}
}
}
}
catch (Exception ex)
{
Console.WriteLine(mapping.Items[iCol].PropertyInfo.Name + ex.Message);
}
}
list.Add(item);
}
}
}
wb.Close();
return list;
}
catch (Exception ex)
{
throw ex;
}
finally
{
app.Quit();
}
}
public List LoadDataByUrl(string url) where Mapping : MSExcelClassMapping
{
var client = new System.Net.WebClient();
var data = client.DownloadData(url);
return LoadDataByByte(data);
}
public List LoadDataByByte(byte[] data) where Mapping : MSExcelClassMapping
{
string file = getTempFilePath();
System.IO.File.WriteAllBytes(file, data);
var result = LoadData(file);
System.IO.File.Delete(file);
return result;
}
public List LoadDataAsStream(Stream stream) where Mapping : MSExcelClassMapping
{
byte[] data = new byte[stream.Length];
stream.Read(data, 0, data.Length);
return LoadDataByByte(data);
}
public string getTempFilePath()
{
string basePath = System.IO.Path.Combine(System.AppContext.BaseDirectory, "temp");
if (!System.IO.Directory.Exists(basePath))
System.IO.Directory.CreateDirectory(basePath);
return System.IO.Path.Combine(basePath, Guid.NewGuid().ToString() + ".xlsx");
}
private Mapping CreateT()
{
var type = typeof(Mapping);
var ass = type.Assembly;
Mapping mapping = (Mapping)ass.CreateInstance(type.FullName);
return mapping;
}
public byte[] OutDataAsByte(List data) where Mapping : MSExcelClassMapping
{
string file = OutLocalData(data);
byte[] bytes = System.IO.File.ReadAllBytes(file);
System.IO.File.Delete(file);
return bytes;
}
public byte[] OutDataAsByte(List data, List> list)
{
string file = OutLocalData(data, list);
byte[] bytes = System.IO.File.ReadAllBytes(file);
System.IO.File.Delete(file);
return bytes;
}
public byte[] OutDataAsByte(List data, Mapping mapping) where Mapping : MSExcelClassMapping
{
string file = OutLocalData(data, mapping);
byte[] bytes = System.IO.File.ReadAllBytes(file);
System.IO.File.Delete(file);
return bytes;
}
public byte[] OutLocalTableDataByte(System.Data.DataTable data)
{
string file = OutLocalTableData(data);
byte[] bytes = System.IO.File.ReadAllBytes(file);
System.IO.File.Delete(file);
return bytes;
}
public string OutLocalTableData(System.Data.DataTable data)
{
Microsoft.Office.Interop.Excel.Application app = new Microsoft.Office.Interop.Excel.Application();
try
{
string filename = getTempFilePath();
//System.IO.File.Create(filename);
app.Visible = false; //不显示EXCEL
app.DisplayAlerts = false; //不提示信息
app.ScreenUpdating = false; //停止更新屏幕,加快速度
Workbooks wbs = app.Workbooks; //获取工作薄
_Workbook wb = wbs.Add(Missing.Value);
Microsoft.Office.Interop.Excel.Worksheet Sheet = (Microsoft.Office.Interop.Excel.Worksheet)wb.Sheets[1];
OutLocalTableData(data, Sheet);
app.Columns.AutoFit();
wb.SaveCopyAs(filename);
wb.Close(); //关闭工作薄
//wb._SaveAs(filename); //保存
return filename;
}
catch (Exception ex)
{
throw new Exception(ex.Message + " ");
}
finally
{
app.Quit(); //关闭EXCEL
}
}
public void OutLocalTableData(System.Data.DataTable data, Microsoft.Office.Interop.Excel.Worksheet Sheet, string Start = "A1",
System.Drawing.Color? _color = null, bool hasHeader = true)
{
Microsoft.Office.Interop.Excel.Application app = new Microsoft.Office.Interop.Excel.Application();
//string filename = getTempFilePath();
////System.IO.File.Create(filename);
//app.Visible = false; //不显示EXCEL
//app.DisplayAlerts = false; //不提示信息
//app.ScreenUpdating = false; //停止更新屏幕,加快速度
//Workbooks wbs = app.Workbooks; //获取工作薄
//_Workbook wb = wbs.Add(Missing.Value);
System.Text.RegularExpressions.Regex regex = new System.Text.RegularExpressions.Regex(@"([A-Z]?)(\d+)");
//Microsoft.Office.Interop.Excel.Worksheet Sheet = (Microsoft.Office.Interop.Excel.Worksheet)wb.Sheets[1];
//Sheet.Activate();
//Sheet.Application.ActiveWindow.SplitRow = 1;
//Sheet.Application.ActiveWindow.FreezePanes = true;
int startQty = 1;
if (regex.IsMatch(Start))
{
startQty = (int.Parse(regex.Match(Start).Groups[2].Value)) + 1;
}
else
{
Start = "A1";
}
int colCount, rowCount;
colCount = data.Columns.Count;
rowCount = data.Rows.Count;
//写入标题行
Microsoft.Office.Interop.Excel.Range range;
if (hasHeader)
{
range = Sheet.get_Range(Start, Missing.Value);
range = range.get_Resize(1, colCount);
if (_color == null)
range.Interior.Color = System.Drawing.Color.FromArgb(204, 255, 255);
else
range.Interior.Color = _color;
range.Font.Bold = true;
range.HorizontalAlignment = XlHAlign.xlHAlignLeft;
range.VerticalAlignment = XlVAlign.xlVAlignCenter;
range.Borders.LineStyle = XlLineStyle.xlContinuous;
range.RowHeight = 30;
object[,] headerData = new object[1, colCount];
for (int iCol = 0; iCol < colCount; iCol++)
{
headerData[0, iCol] = data.Columns[iCol].ColumnName;
//var column= Sheet.Columns[iCol] as
string ColumnFormattext = ExcelFormattextHelper.GetColumnFormattext(data.Columns[iCol].DataType);
if (!string.IsNullOrEmpty(ColumnFormattext))
{
var r2 = Sheet.Range[Sheet.Cells[startQty, iCol + 1], Sheet.Cells[data.Rows.Count + startQty, iCol + 1]];
r2.NumberFormat = ColumnFormattext;
}
}
range.set_Value(Missing.Value, headerData);
}
if (rowCount > 0)
{
if (regex.IsMatch(Start))
{
Start = regex.Match(Start).Groups[1].Value + (int.Parse(regex.Match(Start).Groups[2].Value) + 1);
}
else
{
Start = "A2";
}
range = Sheet.get_Range(Start, Missing.Value);
range = range.get_Resize(rowCount, colCount);
range.Borders.LineStyle = Microsoft.Office.Interop.Excel.XlLineStyle.xlContinuous;
range.RowHeight = 20;
object[,] cellData = new object[rowCount, colCount];
for (int iRow = 0; iRow < rowCount; iRow++)
{
for (int iCol = 0; iCol < colCount; iCol++)
{
cellData[iRow, iCol] = data.Rows[iRow][iCol];
}
}
range.set_Value(Missing.Value, cellData);
//设置单元格格式
}
}
public void SetSheet(List data, MSExcelClassMapping mapping, Microsoft.Office.Interop.Excel.Worksheet Sheet, List repeat = null) where Mapping : MSExcelClassMapping
{
int colCount, rowCount;
colCount = mapping.Items.Count;
rowCount = data.Count;
//写入标题行
Microsoft.Office.Interop.Excel.Range range;
range = Sheet.get_Range("A1", Missing.Value);
range = range.get_Resize(1, colCount);
range.Interior.Color = System.Drawing.Color.FromArgb(191, 191, 191);
range.Font.Bold = true;
range.HorizontalAlignment = Microsoft.Office.Interop.Excel.XlHAlign.xlHAlignLeft;
range.VerticalAlignment = Microsoft.Office.Interop.Excel.XlVAlign.xlVAlignCenter;
range.Borders.LineStyle = Microsoft.Office.Interop.Excel.XlLineStyle.xlContinuous;
range.RowHeight = 30;
object[,] headerData = new object[1, colCount];
for (int iCol = 0; iCol < colCount; iCol++)
{
if (!string.IsNullOrEmpty(mapping.Items[iCol].ColumnName))
{
headerData[0, iCol] = mapping.Items[iCol].ColumnName;
}
else
{
headerData[0, iCol] = mapping.Items[iCol].PropertyInfo.Name;
}
if (!string.IsNullOrEmpty(mapping.Items[iCol].ColumnAnnotation))
{
//批注
var r = Sheet.Range[Sheet.Cells[1, iCol + 1], Sheet.Cells[1, iCol + 1]];
if (r.Comment != null)
{
r.Comment.Delete();
}
r.AddComment(mapping.Items[iCol].ColumnAnnotation);
}
//var column= Sheet.Columns[iCol] as
if (!string.IsNullOrEmpty(mapping.Items[iCol].ColumnFormattext))
{
var r2 = Sheet.Range[Sheet.Cells[2, iCol + 1], Sheet.Cells[data.Count + 1, iCol + 1]];
r2.NumberFormat = mapping.Items[iCol].ColumnFormattext;
}
}
range.set_Value(Missing.Value, headerData);
decimal sum = 0;
int sumIndex = mapping.RemarkIndex();
if (rowCount > 0)
{
range = Sheet.get_Range("A2", Missing.Value);
range = range.get_Resize(rowCount, colCount);
range.Borders.LineStyle = Microsoft.Office.Interop.Excel.XlLineStyle.xlContinuous;
range.RowHeight = 20;
object[,] cellData = new object[rowCount, colCount];
for (int iRow = 0; iRow < rowCount; iRow++)
{
for (int iCol = 0; iCol < colCount; iCol++)
{
var item = data[iRow];
cellData[iRow, iCol] = mapping.Items[iCol].PropertyInfo.GetValue(item, null);
}
if (sumIndex > 0)
{
var item = data[iRow];
sum += (decimal)mapping.Items[sumIndex + 1].PropertyInfo.GetValue(item, null);
}
}
range.set_Value(Missing.Value, cellData);
//设置单元格格式
if (repeat != null)
{
foreach (var i in repeat)
{
var ranges = (Microsoft.Office.Interop.Excel.Range)Sheet.Rows[2+i, Missing.Value];
ranges.Interior.Color = System.Drawing.Color.FromArgb(255, 0, 0);
}
}
if (sumIndex > 0)
{
//汇总
int rows = data.Count + 1;
var rangeS = Sheet.get_Range("A" + (rows + 1), Missing.Value);
rangeS = rangeS.get_Resize(1, colCount);
rangeS.Borders.LineStyle = Microsoft.Office.Interop.Excel.XlLineStyle.xlContinuous;
rangeS.RowHeight = 20;
object[,] sumData = new object[1, colCount];
sumData[0, sumIndex] = "合计";
sumData[0, sumIndex + 1] = sum;
rangeS.set_Value(Missing.Value, sumData);
}
}
}
public string OutLocalData(List data, List> mapping)
{
string filename = getTempFilePath();
Microsoft.Office.Interop.Excel.Application app = new Microsoft.Office.Interop.Excel.Application();
try
{
//System.IO.File.Create(filename);
app.Visible = false; //不显示EXCEL
app.DisplayAlerts = false; //不提示信息
app.ScreenUpdating = false; //停止更新屏幕,加快速度
app.DefaultSaveFormat = XlFileFormat.xlWorkbookDefault;
Workbooks wbs = app.Workbooks; //获取工作薄
_Workbook wb = wbs.Add(Missing.Value);
for (int i = 1; i <= mapping.Count; i++)
{
Microsoft.Office.Interop.Excel.Worksheet Sheet;
if (i > 1)
{
Sheet = (Worksheet)wb.Sheets.Add(Type.Missing, wb.ActiveSheet, 1, XlSheetType.xlWorksheet);
}
else
{
Sheet = (Worksheet)wb.Sheets[i];
}
SetSheet>(data, mapping[i - 1], Sheet);
}
//Sheet.Activate();
//Sheet.Application.ActiveWindow.SplitRow = 1;
//Sheet.Application.ActiveWindow.FreezePanes = true;
app.Columns.AutoFit();
wb.SaveCopyAs(filename);
wb.Close(); //关闭工作薄
//wb._SaveAs(filename); //保存
return filename;
}
catch (Exception ex)
{
throw new Exception(ex.Message + " " + " filename" + filename + " " + ex.StackTrace);
}
finally
{
app.Quit(); //关闭EXCEL
}
}
public string OutLocalData(List data, Mapping mapping) where Mapping : MSExcelClassMapping
{
return OutLocalData(data, new List> { mapping });
}
///
/// 导出数据并返回本地链接
///
///
///
///
///
public string OutLocalData(List data) where Mapping : MSExcelClassMapping
{
var mapping = CreateT();
return OutLocalData(data, mapping);
}
}
}