Browse Source

更新包

懒得勤快 2 years ago
parent
commit
3c886d764f

+ 2 - 2
Masuit.Tools.Abstractions/Masuit.Tools.Abstractions.csproj

@@ -3,7 +3,7 @@
         <TargetFrameworks>netstandard2.0;netstandard2.1;net461;net5;net6;net7</TargetFrameworks>
         <TargetFrameworks>netstandard2.0;netstandard2.1;net461;net5;net6;net7</TargetFrameworks>
         <LangVersion>latest</LangVersion>
         <LangVersion>latest</LangVersion>
         <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
         <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
-        <Version>2.5.9.1</Version>
+        <Version>2.5.9.2</Version>
         <Authors>懒得勤快</Authors>
         <Authors>懒得勤快</Authors>
         <Description>Masuit.Tools基础公共库,包含一些常用的操作类,大都是静态类,加密解密,反射操作,Excel简单导出,权重随机筛选算法,分布式短id,表达式树,linq扩展,文件压缩,多线程下载和FTP客户端,硬件信息,字符串扩展方法,日期时间扩展操作,中国农历,大文件拷贝,图像裁剪,验证码,断点续传,集合扩展等常用封装。</Description>
         <Description>Masuit.Tools基础公共库,包含一些常用的操作类,大都是静态类,加密解密,反射操作,Excel简单导出,权重随机筛选算法,分布式短id,表达式树,linq扩展,文件压缩,多线程下载和FTP客户端,硬件信息,字符串扩展方法,日期时间扩展操作,中国农历,大文件拷贝,图像裁剪,验证码,断点续传,集合扩展等常用封装。</Description>
         <Copyright>懒得勤快,长空X</Copyright>
         <Copyright>懒得勤快,长空X</Copyright>
@@ -44,7 +44,7 @@
 
 
     <ItemGroup>
     <ItemGroup>
         <PackageReference Include="DnsClient" Version="1.7.0" />
         <PackageReference Include="DnsClient" Version="1.7.0" />
-        <PackageReference Include="HtmlSanitizer" Version="8.0.601" />
+        <PackageReference Include="HtmlSanitizer" Version="8.0.645" />
         <PackageReference Include="Microsoft.CSharp" Version="4.7.0" />
         <PackageReference Include="Microsoft.CSharp" Version="4.7.0" />
         <PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="7.0.0" />
         <PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="7.0.0" />
         <PackageReference Include="Newtonsoft.Json" Version="13.0.2" />
         <PackageReference Include="Newtonsoft.Json" Version="13.0.2" />

+ 1 - 1
Masuit.Tools.AspNetCore/Masuit.Tools.AspNetCore.csproj

@@ -17,7 +17,7 @@
         <Product>Masuit.Tools.AspNetCore</Product>
         <Product>Masuit.Tools.AspNetCore</Product>
         <PackageId>Masuit.Tools.AspNetCore</PackageId>
         <PackageId>Masuit.Tools.AspNetCore</PackageId>
         <LangVersion>latest</LangVersion>
         <LangVersion>latest</LangVersion>
-        <Version>1.1.9.1</Version>
+        <Version>1.1.9.2</Version>
         <RepositoryType></RepositoryType>
         <RepositoryType></RepositoryType>
         <GeneratePackageOnBuild>True</GeneratePackageOnBuild>
         <GeneratePackageOnBuild>True</GeneratePackageOnBuild>
         <FileVersion>1.1.9</FileVersion>
         <FileVersion>1.1.9</FileVersion>

+ 3 - 3
Masuit.Tools.Core/Masuit.Tools.Core.csproj

@@ -6,7 +6,7 @@
 官网教程:https://ldqk.org/55
 官网教程:https://ldqk.org/55
 github:https://github.com/ldqk/Masuit.Tools
 github:https://github.com/ldqk/Masuit.Tools
         </Description>
         </Description>
-        <Version>2.5.9.1</Version>
+        <Version>2.5.9.2</Version>
         <Copyright>Copyright © 懒得勤快</Copyright>
         <Copyright>Copyright © 懒得勤快</Copyright>
         <PackageProjectUrl>https://github.com/ldqk/Masuit.Tools</PackageProjectUrl>
         <PackageProjectUrl>https://github.com/ldqk/Masuit.Tools</PackageProjectUrl>
         <PackageTags>Masuit.Tools,工具库,Utility,Crypt,Extensions</PackageTags>
         <PackageTags>Masuit.Tools,工具库,Utility,Crypt,Extensions</PackageTags>
@@ -35,7 +35,7 @@ github:https://github.com/ldqk/Masuit.Tools
     </PropertyGroup>
     </PropertyGroup>
 
 
     <ItemGroup>
     <ItemGroup>
-        <PackageReference Include="FastExpressionCompiler" Version="3.3.3" />
+        <PackageReference Include="FastExpressionCompiler" Version="3.3.4" />
         <PackageReference Include="Microsoft.AspNetCore.Mvc" Version="2.2.0" />
         <PackageReference Include="Microsoft.AspNetCore.Mvc" Version="2.2.0" />
         <PackageReference Include="Microsoft.Extensions.Http" Version="7.0.0" />
         <PackageReference Include="Microsoft.Extensions.Http" Version="7.0.0" />
         <PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.1.1" PrivateAssets="All" />
         <PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.1.1" PrivateAssets="All" />
@@ -54,7 +54,7 @@ github:https://github.com/ldqk/Masuit.Tools
         <PackageReference Include="Microsoft.EntityFrameworkCore" Version="6.0.10" />
         <PackageReference Include="Microsoft.EntityFrameworkCore" Version="6.0.10" />
     </ItemGroup>
     </ItemGroup>
     <ItemGroup Condition=" '$(TargetFramework)' == 'net7'">
     <ItemGroup Condition=" '$(TargetFramework)' == 'net7'">
-        <PackageReference Include="Microsoft.EntityFrameworkCore" Version="7.0.1" />
+        <PackageReference Include="Microsoft.EntityFrameworkCore" Version="7.0.2" />
     </ItemGroup>
     </ItemGroup>
     <ItemGroup>
     <ItemGroup>
       <Compile Remove="..\Masuit.Tools.Abstractions\Mapping\**" />
       <Compile Remove="..\Masuit.Tools.Abstractions\Mapping\**" />

+ 608 - 608
Masuit.Tools.Excel/ExcelExtension.cs

@@ -15,616 +15,616 @@ namespace Masuit.Tools.Excel;
 
 
 public static class ExcelExtension
 public static class ExcelExtension
 {
 {
-    static ExcelExtension()
-    {
-        ExcelPackage.LicenseContext = LicenseContext.NonCommercial;
-    }
+	static ExcelExtension()
+	{
+		ExcelPackage.LicenseContext = LicenseContext.NonCommercial;
+	}
 
 
 #if NET5_0_OR_GREATER
 #if NET5_0_OR_GREATER
-    [System.Runtime.CompilerServices.ModuleInitializer]
-    internal static void Init()
-    {
-        ExcelPackage.LicenseContext = LicenseContext.NonCommercial;
-    }
+	[System.Runtime.CompilerServices.ModuleInitializer]
+	internal static void Init()
+	{
+		ExcelPackage.LicenseContext = LicenseContext.NonCommercial;
+	}
 #endif
 #endif
 
 
-    /// <summary>
-    /// 将内存表自动填充到Excel
-    /// </summary>
-    /// <param name="sheetTables">sheet名和内存表的映射</param>
-    /// <param name="password">密码</param>
-    /// <param name="settings">列设置</param>
-    /// <returns>内存流</returns>
-    public static PooledMemoryStream ToExcel(this Dictionary<string, DataTable> sheetTables, string password = null, ColumnSettings settings = null)
-    {
-        using var pkg = new ExcelPackage();
-        foreach (var pair in sheetTables)
-        {
-            pair.Value.TableName = pair.Key;
-            CreateWorksheet(pkg, pair.Value, settings);
-        }
-
-        return SaveAsStream(pkg, password);
-    }
-
-    /// <summary>
-    /// 将内存表自动填充到Excel
-    /// </summary>
-    /// <param name="sheetTables">sheet名和内存表的映射</param>
-    /// <param name="password">密码</param>
-    /// <param name="settings">列设置</param>
-    /// <returns>内存流</returns>
-    public static PooledMemoryStream ToExcel<T>(this Dictionary<string, IEnumerable<T>> sheetTables, string password = null, ColumnSettings settings = null)
-    {
-        using var pkg = new ExcelPackage();
-        foreach (var pair in sheetTables)
-        {
-            CreateWorksheet(pkg, pair, settings);
-        }
-
-        return SaveAsStream(pkg, password);
-    }
-
-    /// <summary>
-    /// 将内存表自动填充到Excel
-    /// </summary>
-    /// <param name="tables">内存表</param>
-    /// <param name="password">密码</param>
-    /// <returns>内存流</returns>
-    public static PooledMemoryStream ToExcel(this List<DataTable> tables, string password = null, ColumnSettings settings = null)
-    {
-        using var pkg = new ExcelPackage();
-        foreach (var table in tables)
-        {
-            CreateWorksheet(pkg, table, settings);
-        }
-
-        return SaveAsStream(pkg, password);
-    }
-
-    /// <summary>
-    /// 将内存表自动填充到Excel
-    /// </summary>
-    /// <param name="table">内存表</param>
-    /// <param name="password">密码</param>
-    /// <returns>内存流</returns>
-    public static PooledMemoryStream ToExcel(this DataTable table, string password = null, ColumnSettings settings = null)
-    {
-        using var pkg = new ExcelPackage();
-        CreateWorksheet(pkg, table, settings);
-        return SaveAsStream(pkg, password);
-    }
-
-    /// <summary>
-    /// 将内存表自动填充到Excel
-    /// </summary>
-    /// <param name="table">内存表</param>
-    /// <param name="password">密码</param>
-    /// <returns>内存流</returns>
-    public static PooledMemoryStream ToExcel<T>(this IEnumerable<T> table, string password = null, ColumnSettings settings = null)
-    {
-        using var pkg = new ExcelPackage();
-        CreateWorksheet(pkg, new KeyValuePair<string, IEnumerable<T>>("Sheet1", table), settings);
-        return SaveAsStream(pkg, password);
-    }
-
-    private static PooledMemoryStream SaveAsStream(ExcelPackage pkg, string password)
-    {
-        var ms = new PooledMemoryStream();
-        if (!string.IsNullOrEmpty(password))
-        {
-            pkg.SaveAs(ms, password);
-        }
-        else
-        {
-            pkg.SaveAs(ms);
-        }
-
-        return ms;
-    }
-
-    public static void CreateWorksheet(this ExcelPackage pkg, DataTable table, ColumnSettings settings = null)
-    {
-        if (string.IsNullOrEmpty(table.TableName))
-        {
-            table.TableName = "Sheet1";
-        }
-
-        var sheet = pkg.Workbook.Worksheets.Add(table.TableName);
-        sheet.Cells.Style.Font.Name = "微软雅黑";
-
-        FillWorksheet(sheet, table, settings);
-
-        sheet.Cells.Style.VerticalAlignment = ExcelVerticalAlignment.Center;
-
-        //打印方向:纵向
-        sheet.PrinterSettings.Orientation = eOrientation.Landscape;
-
-        //集中在一页里打印
-        sheet.PrinterSettings.FitToPage = true;
-
-        //使用A4纸
-        sheet.PrinterSettings.PaperSize = ePaperSize.A4;
-    }
-
-    public static void CreateWorksheet<T>(this ExcelPackage pkg, KeyValuePair<string, IEnumerable<T>> table, ColumnSettings settings = null)
-    {
-        var sheet = pkg.Workbook.Worksheets.Add(table.Key);
-        sheet.Cells.Style.Font.Name = "微软雅黑";
-
-        FillWorksheet(sheet, table.Value, settings);
-
-        sheet.Cells.Style.VerticalAlignment = ExcelVerticalAlignment.Center;
-
-        //打印方向:纵向
-        sheet.PrinterSettings.Orientation = eOrientation.Landscape;
-
-        //集中在一页里打印
-        sheet.PrinterSettings.FitToPage = true;
-
-        //使用A4纸
-        sheet.PrinterSettings.PaperSize = ePaperSize.A4;
-    }
-
-    /// <summary>
-    /// 从datatable填充工作簿
-    /// </summary>
-    /// <param name="sheet">工作簿</param>
-    /// <param name="table">数据</param>
-    /// <param name="settings">列设置</param>
-    /// <param name="startRow">起始行,默认第一行</param>
-    /// <param name="startColumn">起始列,默认第一列A列</param>
-    public static void FillWorksheet(this ExcelWorksheet sheet, DataTable table, ColumnSettings settings = null, int startRow = 1, int startColumn = 1)
-    {
-        var hasPicColumn = false;
-        if (table.Rows.Count > 0)
-        {
-            for (int i = 0; i < table.Columns.Count; i++)
-            {
-                switch (table.Rows[0][i])
-                {
-                    case Stream:
-                    case IEnumerable<Stream>:
-                    case IDictionary<string, Stream>:
-                    case IDictionary<string, MemoryStream>:
-                        hasPicColumn = true;
-                        break;
-                }
-            }
-
-            if (hasPicColumn)
-            {
-                // 填充表头
-                var maxWidth = new int[table.Columns.Count];
-                for (var j = 0; j < table.Columns.Count; j++)
-                {
-                    sheet.SetValue(startRow, j + startColumn, table.Columns[j].ColumnName);
-                    maxWidth[j] = Encoding.UTF8.GetBytes(table.Columns[j].ColumnName).Length;
-                }
-
-                sheet.Row(startRow).Style.Font.Bold = true; // 表头设置为粗体
-                sheet.Row(startRow).Style.Font.Size = sheet.Row(startRow).Style.Font.Size * 1.11f; // 表头字号放大1.11倍
-                sheet.Row(startRow).Style.HorizontalAlignment = ExcelHorizontalAlignment.Center;
-                sheet.Row(startRow).CustomHeight = true; // 自动调整行高
-                if (settings != null)
-                {
-                    foreach (var x in settings.ColumnTypes)
-                    {
-                        sheet.Column(x.Key).Style.Numberformat.Format = x.Value;
-                    }
-                }
-                sheet.Cells.AutoFitColumns(); // 表头自适应列宽
-
-                // 填充内容
-                for (int i = 0; i < table.Rows.Count; i++)
-                {
-                    sheet.Row(i + startRow + 1).CustomHeight = true; // 自动调整行高
-                    for (int j = 0; j < table.Columns.Count; j++)
-                    {
-                        switch (table.Rows[i][j])
-                        {
-                            case Stream s:
-                                {
-                                    if (s.Length > 2)
-                                    {
-                                        try
-                                        {
-                                            var picture = sheet.Drawings.AddPicture(Guid.NewGuid().ToString(), s);
-                                            picture.SetPosition(i + startRow, 3, j + startColumn - 1, 5); //设置图片显示位置
-                                            var percent = Math.Round(Math.Min(120f / picture.Image.Bounds.Height * picture.Image.Bounds.VerticalResolution, 100));
-                                            sheet.Row(i + startRow + 1).Height = 90;
-                                            sheet.Column(j + startColumn).Width = Math.Max(sheet.Column(j + startColumn).Width, picture.Image.Bounds.Width / picture.Image.Bounds.HorizontalResolution * percent / 6.4);
-                                            picture.SetSize((int)percent);
-                                        }
-                                        catch
-                                        {
-                                            throw new ArgumentException($"{i + startRow}行{j}列图像格式不受支持");
-                                        }
-                                    }
-
-                                    sheet.SetValue(i + startRow + 1, j + startColumn, "");
-
-                                    break;
-                                }
-
-                            case IEnumerable<Stream> streams:
-                                {
-                                    double sumWidth = 0;
-                                    int index = 0;
-                                    foreach (var stream in streams.Where(stream => stream.Length > 2))
-                                    {
-                                        try
-                                        {
-                                            var picture = sheet.Drawings.AddPicture(Guid.NewGuid().ToString(), stream);
-                                            var percent = Math.Round(Math.Min(120f / picture.Image.Bounds.Height * picture.Image.Bounds.VerticalResolution, 100));
-                                            picture.SetPosition(i + startRow, 3, j + startColumn - 1, (int)Math.Ceiling(picture.Image.Bounds.Width / picture.Image.Bounds.HorizontalResolution * percent * index++)); //设置图片显示位置
-                                            sheet.Row(i + startRow + 1).Height = 90;
-                                            sumWidth += picture.Image.Bounds.Width / picture.Image.Bounds.HorizontalResolution * percent / 6.4;
-                                            sheet.Column(j + startColumn).Width = Math.Max(sheet.Column(j + startColumn).Width, sumWidth);
-                                            picture.SetSize((int)percent);
-                                        }
-                                        catch
-                                        {
-                                            throw new ArgumentException($"{i + startRow}行{j}列第{index}张图像格式不受支持");
-                                        }
-                                    }
-
-                                    sheet.SetValue(i + startRow + 1, j + startColumn, "");
-                                    break;
-                                }
-
-                            case IDictionary<string, Stream> dic:
-                                {
-                                    double sumWidth = 0;
-                                    int index = 0;
-                                    foreach (var kv in dic.Where(kv => kv.Value.Length > 2))
-                                    {
-                                        try
-                                        {
-                                            var picture = sheet.Drawings.AddPicture(Guid.NewGuid().ToString(), kv.Value, new Uri(kv.Key));
-                                            var percent = Math.Round(Math.Min(120f / picture.Image.Bounds.Height * picture.Image.Bounds.VerticalResolution, 100));
-                                            picture.SetPosition(i + startRow, 3, j + startColumn - 1, (int)Math.Ceiling(picture.Image.Bounds.Width / picture.Image.Bounds.HorizontalResolution * percent * index++)); //设置图片显示位置
-                                            sheet.Row(i + startRow + 1).Height = 90;
-                                            sumWidth += picture.Image.Bounds.Width / picture.Image.Bounds.HorizontalResolution * percent / 6.4;
-                                            sheet.Column(j + startColumn).Width = Math.Max(sheet.Column(j + startColumn).Width, sumWidth);
-                                            picture.SetSize((int)percent);
-                                        }
-                                        catch
-                                        {
-                                            throw new ArgumentException($"{i + startRow}行{j}列第{index}张图像格式不受支持,图片链接:{kv.Key}");
-                                        }
-                                    }
-
-                                    sheet.SetValue(i + startRow + 1, j + startColumn, "");
-                                    break;
-                                }
-
-                            case IDictionary<string, MemoryStream> dic:
-                                {
-                                    double sumWidth = 0;
-                                    int index = 0;
-                                    foreach (var kv in dic.Where(kv => kv.Value.Length > 2))
-                                    {
-                                        try
-                                        {
-                                            var picture = sheet.Drawings.AddPicture(Guid.NewGuid().ToString(), kv.Value, new Uri(kv.Key));
-                                            var percent = Math.Round(Math.Min(120f / picture.Image.Bounds.Height * picture.Image.Bounds.VerticalResolution, 100));
-                                            picture.SetPosition(i + startRow, 3, j + startColumn - 1, (int)Math.Ceiling(picture.Image.Bounds.Width / picture.Image.Bounds.HorizontalResolution * percent * index++)); //设置图片显示位置
-                                            sheet.Row(i + startRow + 1).Height = 90;
-                                            sumWidth += picture.Image.Bounds.Width / picture.Image.Bounds.HorizontalResolution * percent / 6.4;
-                                            sheet.Column(j + startColumn).Width = Math.Max(sheet.Column(j + startColumn).Width, sumWidth);
-                                            picture.SetSize((int)percent);
-                                        }
-                                        catch
-                                        {
-                                            throw new ArgumentException($"{i + startRow}行{j}列第{index}张图像格式不受支持,图片链接:{kv.Key}");
-                                        }
-                                    }
-
-                                    sheet.SetValue(i + startRow + 1, j + startColumn, "");
-                                    break;
-                                }
-
-                            case IDictionary<string, PooledMemoryStream> dic:
-                                {
-                                    double sumWidth = 0;
-                                    int index = 0;
-                                    foreach (var kv in dic.Where(kv => kv.Value.Length > 2))
-                                    {
-                                        try
-                                        {
-                                            var picture = sheet.Drawings.AddPicture(Guid.NewGuid().ToString(), kv.Value, new Uri(kv.Key));
-                                            var percent = Math.Round(Math.Min(120f / picture.Image.Bounds.Height * picture.Image.Bounds.VerticalResolution, 100));
-                                            picture.SetPosition(i + startRow, 3, j + startColumn - 1, (int)Math.Ceiling(picture.Image.Bounds.Width / picture.Image.Bounds.HorizontalResolution * percent * index++)); //设置图片显示位置
-                                            sheet.Row(i + startRow + 1).Height = 90;
-                                            sumWidth += picture.Image.Bounds.Width / picture.Image.Bounds.HorizontalResolution * percent / 6.4;
-                                            sheet.Column(j + startColumn).Width = Math.Max(sheet.Column(j + startColumn).Width, sumWidth);
-                                            picture.SetSize((int)percent);
-                                        }
-                                        catch
-                                        {
-                                            throw new ArgumentException($"{i + startRow}行{j}列第{index}张图像格式不受支持,图片链接:{kv.Key}");
-                                        }
-                                    }
-
-                                    sheet.SetValue(i + startRow + 1, j + startColumn, "");
-                                    break;
-                                }
-
-                            default:
-                                {
-                                    sheet.SetValue(i + startRow + 1, j + startColumn, table.Rows[i][j] ?? "");
-                                    if (table.Rows[i][j] is ValueType)
-                                    {
-                                        sheet.Column(j + startColumn).AutoFit();
-                                    }
-                                    else
-                                    {
-                                        // 根据单元格内容长度来自适应调整列宽
-                                        var fontFamily = SystemFonts.Families.FirstOrDefault(f => f.Name == sheet.Cells[i + startRow + 1, j + startColumn].Style.Font.Name);
-                                        int measureSize = 1;
-                                        if (fontFamily == default)
-                                        {
-                                            fontFamily = SystemFonts.Families.FirstOrDefault();
-                                            measureSize++;
-                                        }
-
-                                        var width = TextMeasurer.Measure(table.Rows[i][j].ToString(), new TextOptions(fontFamily.CreateFont(measureSize))).Width;
-                                        sheet.Column(j + startColumn).Width = Math.Min(110, Math.Max(width, sheet.Column(j + startColumn).Width));
-                                    }
-
-                                    break;
-                                }
-                        }
-                    }
-                }
-
-                sheet.Cells.Style.WrapText = true;
-            }
-            else
-            {
-                sheet.Cells[startRow, startColumn].LoadFromDataTable(table, true, TableStyles.Light15).AutoFitColumns(12, 90);
-                sheet.Cells.Style.WrapText = true;
-            }
-        }
-    }
-
-    /// <summary>
-    /// 从datatable填充工作簿
-    /// </summary>
-    /// <param name="sheet">工作簿</param>
-    /// <param name="table">数据</param>
-    /// <param name="settings">列设置</param>
-    /// <param name="startRow">起始行,默认第一行</param>
-    /// <param name="startColumn">起始列,默认第一列A列</param>
-    public static void FillWorksheet<T>(this ExcelWorksheet sheet, IEnumerable<T> source, ColumnSettings settings = null, int startRow = 1, int startColumn = 1)
-    {
-        var hasPicColumn = false;
-        var properties = typeof(T).GetProperties();
-        if (source is ICollection<T> table)
-        {
-        }
-        else
-        {
-            table = source.ToList();
-        }
-
-        if (table.Any())
-        {
-            if (properties.Any(t => t.PropertyType.IsSubclassOf(typeof(Stream)) || typeof(IEnumerable<Stream>).IsAssignableFrom(t.PropertyType) || (typeof(IDictionary).IsAssignableFrom(t.PropertyType) && t.PropertyType.GenericTypeArguments[1].IsSubclassOf(typeof(Stream)))))
-            {
-                hasPicColumn = true;
-            }
-
-            if (hasPicColumn)
-            {
-                // 填充表头
-                var maxWidth = new int[properties.Length];
-                for (var j = 0; j < properties.Length; j++)
-                {
-                    sheet.SetValue(startRow, j + startColumn, properties[j].Name);
-                    maxWidth[j] = Encoding.UTF8.GetBytes(properties[j].Name).Length;
-                }
-
-                sheet.Row(startRow).Style.Font.Bold = true; // 表头设置为粗体
-                sheet.Row(startRow).Style.Font.Size = sheet.Row(startRow).Style.Font.Size * 1.11f; // 表头字号放大1.11倍
-                sheet.Row(startRow).Style.HorizontalAlignment = ExcelHorizontalAlignment.Center;
-                sheet.Row(startRow).CustomHeight = true; // 自动调整行高
-                if (settings != null)
-                {
-                    foreach (var x in settings.ColumnTypes)
-                    {
-                        sheet.Column(x.Key).Style.Numberformat.Format = x.Value;
-                    }
-                }
-                sheet.Cells.AutoFitColumns(); // 表头自适应列宽
-
-                // 填充内容
-                int current = 0;
-                foreach (var item in table)
-                {
-                    sheet.Row(current + startRow + 1).CustomHeight = true; // 自动调整行高
-                    for (int j = 0; j < properties.Length; j++)
-                    {
-                        switch (properties[j].GetValue(item))
-                        {
-                            case Stream s:
-                                {
-                                    if (s.Length > 2)
-                                    {
-                                        try
-                                        {
-                                            var picture = sheet.Drawings.AddPicture(Guid.NewGuid().ToString(), s);
-                                            picture.SetPosition(current + startRow, 3, j + startColumn - 1, 5); //设置图片显示位置
-                                            var percent = Math.Round(Math.Min(120f / picture.Image.Bounds.Height * picture.Image.Bounds.VerticalResolution, 100));
-                                            sheet.Row(current + startRow + 1).Height = 90;
-                                            sheet.Column(j + startColumn).Width = Math.Max(sheet.Column(j + startColumn).Width, picture.Image.Bounds.Width / picture.Image.Bounds.HorizontalResolution * percent / 6.4);
-                                            picture.SetSize((int)percent);
-                                        }
-                                        catch
-                                        {
-                                            throw new ArgumentException($"{current + startRow}行{j}列图像格式不受支持");
-                                        }
-                                    }
-
-                                    sheet.SetValue(current + startRow + 1, j + startColumn, "");
-
-                                    break;
-                                }
-
-                            case IEnumerable<Stream> streams:
-                                {
-                                    double sumWidth = 0;
-                                    int index = 0;
-                                    foreach (var stream in streams.Where(stream => stream.Length > 2))
-                                    {
-                                        try
-                                        {
-                                            var picture = sheet.Drawings.AddPicture(Guid.NewGuid().ToString(), stream);
-                                            var percent = Math.Round(Math.Min(120f / picture.Image.Bounds.Height * picture.Image.Bounds.VerticalResolution, 100));
-                                            picture.SetPosition(current + startRow, 3, j + startColumn - 1, (int)Math.Ceiling(picture.Image.Bounds.Width / picture.Image.Bounds.HorizontalResolution * percent * index++)); //设置图片显示位置
-                                            sheet.Row(current + startRow + 1).Height = 90;
-                                            sumWidth += picture.Image.Bounds.Width / picture.Image.Bounds.HorizontalResolution * percent / 6.4;
-                                            sheet.Column(j + startColumn).Width = Math.Max(sheet.Column(j + startColumn).Width, sumWidth);
-                                            picture.SetSize((int)percent);
-                                        }
-                                        catch
-                                        {
-                                            throw new ArgumentException($"{current + startRow}行{j}列第{index}张图像格式不受支持");
-                                        }
-                                    }
-
-                                    sheet.SetValue(current + startRow + 1, j + startColumn, "");
-                                    break;
-                                }
-
-                            case IDictionary<string, Stream> dic:
-                                {
-                                    double sumWidth = 0;
-                                    int index = 0;
-                                    foreach (var kv in dic.Where(kv => kv.Value.Length > 2))
-                                    {
-                                        try
-                                        {
-                                            var picture = sheet.Drawings.AddPicture(Guid.NewGuid().ToString(), kv.Value, new Uri(kv.Key));
-                                            var percent = Math.Round(Math.Min(120f / picture.Image.Bounds.Height * picture.Image.Bounds.VerticalResolution, 100));
-                                            picture.SetPosition(current + startRow, 3, j + startColumn - 1, (int)Math.Ceiling(picture.Image.Bounds.Width / picture.Image.Bounds.HorizontalResolution * percent * index++)); //设置图片显示位置
-                                            sheet.Row(current + startRow + 1).Height = 90;
-                                            sumWidth += picture.Image.Bounds.Width / picture.Image.Bounds.HorizontalResolution * percent / 6.4;
-                                            sheet.Column(j + startColumn).Width = Math.Max(sheet.Column(j + startColumn).Width, sumWidth);
-                                            picture.SetSize((int)percent);
-                                        }
-                                        catch
-                                        {
-                                            throw new ArgumentException($"{current + startRow}行{j}列第{index}张图像格式不受支持,图片链接:{kv.Key}");
-                                        }
-                                    }
-
-                                    sheet.SetValue(current + startRow + 1, j + startColumn, "");
-                                    break;
-                                }
-
-                            case IDictionary<string, MemoryStream> dic:
-                                {
-                                    double sumWidth = 0;
-                                    int index = 0;
-                                    foreach (var kv in dic.Where(kv => kv.Value.Length > 2))
-                                    {
-                                        try
-                                        {
-                                            var picture = sheet.Drawings.AddPicture(Guid.NewGuid().ToString(), kv.Value, new Uri(kv.Key));
-                                            var percent = Math.Round(Math.Min(120f / picture.Image.Bounds.Height * picture.Image.Bounds.VerticalResolution, 100));
-                                            picture.SetPosition(current + startRow, 3, j + startColumn - 1, (int)Math.Ceiling(picture.Image.Bounds.Width / picture.Image.Bounds.HorizontalResolution * percent * index++)); //设置图片显示位置
-                                            sheet.Row(current + startRow + 1).Height = 90;
-                                            sumWidth += picture.Image.Bounds.Width / picture.Image.Bounds.HorizontalResolution * percent / 6.4;
-                                            sheet.Column(j + startColumn).Width = Math.Max(sheet.Column(j + startColumn).Width, sumWidth);
-                                            picture.SetSize((int)percent);
-                                        }
-                                        catch
-                                        {
-                                            throw new ArgumentException($"{current + startRow}行{j}列第{index}张图像格式不受支持,图片链接: {kv.Key}");
-                                        }
-                                    }
-
-                                    sheet.SetValue(current + startRow + 1, j + startColumn, "");
-                                    break;
-                                }
-
-                            case IDictionary<string, PooledMemoryStream> dic:
-                                {
-                                    double sumWidth = 0;
-                                    int index = 0;
-                                    foreach (var kv in dic.Where(kv => kv.Value.Length > 2))
-                                    {
-                                        try
-                                        {
-                                            var picture = sheet.Drawings.AddPicture(Guid.NewGuid().ToString(), kv.Value, new Uri(kv.Key));
-                                            var percent = Math.Round(Math.Min(120f / picture.Image.Bounds.Height * picture.Image.Bounds.VerticalResolution, 100));
-                                            picture.SetPosition(current + startRow, 3, j + startColumn - 1, (int)Math.Ceiling(picture.Image.Bounds.Width / picture.Image.Bounds.HorizontalResolution * percent * index++)); //设置图片显示位置
-                                            sheet.Row(current + startRow + 1).Height = 90;
-                                            sumWidth += picture.Image.Bounds.Width / picture.Image.Bounds.HorizontalResolution * percent / 6.4;
-                                            sheet.Column(j + startColumn).Width = Math.Max(sheet.Column(j + startColumn).Width, sumWidth);
-                                            picture.SetSize((int)percent);
-                                        }
-                                        catch
-                                        {
-                                            throw new ArgumentException($"{current + startRow}行{j}列第{index}张图像格式不受支持,图片链接: {kv.Key}");
-                                        }
-                                    }
-
-                                    sheet.SetValue(current + startRow + 1, j + startColumn, "");
-                                    break;
-                                }
-
-                            default:
-                                {
-                                    sheet.SetValue(current + startRow + 1, j + startColumn, properties[j].GetValue(item) ?? "");
-                                    if (properties[j].GetValue(item) is ValueType)
-                                    {
-                                        sheet.Column(j + startColumn).AutoFit();
-                                    }
-                                    else
-                                    {
-                                        // 根据单元格内容长度来自适应调整列宽
-                                        var fontFamily = SystemFonts.Families.FirstOrDefault(f => f.Name == sheet.Cells[current + startRow + 1, j + startColumn].Style.Font.Name);
-                                        int measureSize = 1;
-                                        if (fontFamily == default)
-                                        {
-                                            fontFamily = SystemFonts.Families.FirstOrDefault();
-                                            measureSize++;
-                                        }
-
-                                        var width = TextMeasurer.Measure(properties[j].GetValue(item).ToString(), new TextOptions(fontFamily.CreateFont(measureSize))).Width;
-                                        sheet.Column(j + startColumn).Width = Math.Min(110, Math.Max(width, sheet.Column(j + startColumn).Width));
-                                    }
-
-                                    break;
-                                }
-                        }
-                    }
-                    current++;
-                }
-
-                sheet.Cells.Style.WrapText = true;
-            }
-            else
-            {
-                sheet.Cells[startRow, startColumn].LoadFromCollection(table, true, TableStyles.Light15).AutoFitColumns(12, 90);
-                sheet.Cells.Style.WrapText = true;
-            }
-        }
-    }
-
-    private static readonly NumberFormater NumberFormater = new("ABCDEFGHIJKLMNOPQRSTUVWXYZ", 1);
-
-    /// <summary>
-    /// 获取字母列
-    /// </summary>
-    /// <param name="sheet"></param>
-    /// <param name="index"></param>
-    /// <returns></returns>
-    public static ExcelColumn Column(this ExcelWorksheet sheet, string index)
-    {
-        return sheet.Column((int)NumberFormater.FromString(index));
-    }
+	/// <summary>
+	/// 将内存表自动填充到Excel
+	/// </summary>
+	/// <param name="sheetTables">sheet名和内存表的映射</param>
+	/// <param name="password">密码</param>
+	/// <param name="settings">列设置</param>
+	/// <returns>内存流</returns>
+	public static PooledMemoryStream ToExcel(this Dictionary<string, DataTable> sheetTables, string password = null, ColumnSettings settings = null)
+	{
+		using var pkg = new ExcelPackage();
+		foreach (var pair in sheetTables)
+		{
+			pair.Value.TableName = pair.Key;
+			CreateWorksheet(pkg, pair.Value, settings);
+		}
+
+		return SaveAsStream(pkg, password);
+	}
+
+	/// <summary>
+	/// 将内存表自动填充到Excel
+	/// </summary>
+	/// <param name="sheetTables">sheet名和内存表的映射</param>
+	/// <param name="password">密码</param>
+	/// <param name="settings">列设置</param>
+	/// <returns>内存流</returns>
+	public static PooledMemoryStream ToExcel<T>(this Dictionary<string, IEnumerable<T>> sheetTables, string password = null, ColumnSettings settings = null)
+	{
+		using var pkg = new ExcelPackage();
+		foreach (var pair in sheetTables)
+		{
+			CreateWorksheet(pkg, pair, settings);
+		}
+
+		return SaveAsStream(pkg, password);
+	}
+
+	/// <summary>
+	/// 将内存表自动填充到Excel
+	/// </summary>
+	/// <param name="tables">内存表</param>
+	/// <param name="password">密码</param>
+	/// <returns>内存流</returns>
+	public static PooledMemoryStream ToExcel(this List<DataTable> tables, string password = null, ColumnSettings settings = null)
+	{
+		using var pkg = new ExcelPackage();
+		foreach (var table in tables)
+		{
+			CreateWorksheet(pkg, table, settings);
+		}
+
+		return SaveAsStream(pkg, password);
+	}
+
+	/// <summary>
+	/// 将内存表自动填充到Excel
+	/// </summary>
+	/// <param name="table">内存表</param>
+	/// <param name="password">密码</param>
+	/// <returns>内存流</returns>
+	public static PooledMemoryStream ToExcel(this DataTable table, string password = null, ColumnSettings settings = null)
+	{
+		using var pkg = new ExcelPackage();
+		CreateWorksheet(pkg, table, settings);
+		return SaveAsStream(pkg, password);
+	}
+
+	/// <summary>
+	/// 将内存表自动填充到Excel
+	/// </summary>
+	/// <param name="table">内存表</param>
+	/// <param name="password">密码</param>
+	/// <returns>内存流</returns>
+	public static PooledMemoryStream ToExcel<T>(this IEnumerable<T> table, string password = null, ColumnSettings settings = null)
+	{
+		using var pkg = new ExcelPackage();
+		CreateWorksheet(pkg, new KeyValuePair<string, IEnumerable<T>>("Sheet1", table), settings);
+		return SaveAsStream(pkg, password);
+	}
+
+	private static PooledMemoryStream SaveAsStream(ExcelPackage pkg, string password)
+	{
+		var ms = new PooledMemoryStream();
+		if (!string.IsNullOrEmpty(password))
+		{
+			pkg.SaveAs(ms, password);
+		}
+		else
+		{
+			pkg.SaveAs(ms);
+		}
+
+		return ms;
+	}
+
+	public static void CreateWorksheet(this ExcelPackage pkg, DataTable table, ColumnSettings settings = null)
+	{
+		if (string.IsNullOrEmpty(table.TableName))
+		{
+			table.TableName = "Sheet1";
+		}
+
+		var sheet = pkg.Workbook.Worksheets.Add(table.TableName);
+		sheet.Cells.Style.Font.Name = "微软雅黑";
+
+		FillWorksheet(sheet, table, settings);
+
+		sheet.Cells.Style.VerticalAlignment = ExcelVerticalAlignment.Center;
+
+		//打印方向:纵向
+		sheet.PrinterSettings.Orientation = eOrientation.Landscape;
+
+		//集中在一页里打印
+		sheet.PrinterSettings.FitToPage = true;
+
+		//使用A4纸
+		sheet.PrinterSettings.PaperSize = ePaperSize.A4;
+	}
+
+	public static void CreateWorksheet<T>(this ExcelPackage pkg, KeyValuePair<string, IEnumerable<T>> table, ColumnSettings settings = null)
+	{
+		var sheet = pkg.Workbook.Worksheets.Add(table.Key);
+		sheet.Cells.Style.Font.Name = "微软雅黑";
+
+		FillWorksheet(sheet, table.Value, settings);
+
+		sheet.Cells.Style.VerticalAlignment = ExcelVerticalAlignment.Center;
+
+		//打印方向:纵向
+		sheet.PrinterSettings.Orientation = eOrientation.Landscape;
+
+		//集中在一页里打印
+		sheet.PrinterSettings.FitToPage = true;
+
+		//使用A4纸
+		sheet.PrinterSettings.PaperSize = ePaperSize.A4;
+	}
+
+	/// <summary>
+	/// 从datatable填充工作簿
+	/// </summary>
+	/// <param name="sheet">工作簿</param>
+	/// <param name="table">数据</param>
+	/// <param name="settings">列设置</param>
+	/// <param name="startRow">起始行,默认第一行</param>
+	/// <param name="startColumn">起始列,默认第一列A列</param>
+	public static void FillWorksheet(this ExcelWorksheet sheet, DataTable table, ColumnSettings settings = null, int startRow = 1, int startColumn = 1)
+	{
+		var hasPicColumn = false;
+		if (table.Rows.Count > 0)
+		{
+			for (int i = 0; i < table.Columns.Count; i++)
+			{
+				switch (table.Rows[0][i])
+				{
+					case Stream:
+					case IEnumerable<Stream>:
+					case IDictionary<string, Stream>:
+					case IDictionary<string, MemoryStream>:
+						hasPicColumn = true;
+						break;
+				}
+			}
+
+			if (hasPicColumn)
+			{
+				// 填充表头
+				var maxWidth = new int[table.Columns.Count];
+				for (var j = 0; j < table.Columns.Count; j++)
+				{
+					sheet.SetValue(startRow, j + startColumn, table.Columns[j].ColumnName);
+					maxWidth[j] = Encoding.UTF8.GetBytes(table.Columns[j].ColumnName).Length;
+				}
+
+				sheet.Row(startRow).Style.Font.Bold = true; // 表头设置为粗体
+				sheet.Row(startRow).Style.Font.Size = sheet.Row(startRow).Style.Font.Size * 1.11f; // 表头字号放大1.11倍
+				sheet.Row(startRow).Style.HorizontalAlignment = ExcelHorizontalAlignment.Center;
+				sheet.Row(startRow).CustomHeight = true; // 自动调整行高
+				if (settings != null)
+				{
+					foreach (var x in settings.ColumnTypes)
+					{
+						sheet.Column(x.Key).Style.Numberformat.Format = x.Value;
+					}
+				}
+				sheet.Cells.AutoFitColumns(); // 表头自适应列宽
+
+				// 填充内容
+				for (int i = 0; i < table.Rows.Count; i++)
+				{
+					sheet.Row(i + startRow + 1).CustomHeight = true; // 自动调整行高
+					for (int j = 0; j < table.Columns.Count; j++)
+					{
+						switch (table.Rows[i][j])
+						{
+							case Stream s:
+								{
+									if (s.Length > 2)
+									{
+										try
+										{
+											var picture = sheet.Drawings.AddPicture(Guid.NewGuid().ToString(), s);
+											picture.SetPosition(i + startRow, 3, j + startColumn - 1, 5); //设置图片显示位置
+											var percent = Math.Round(Math.Min(120f / picture.Image.Bounds.Height * picture.Image.Bounds.VerticalResolution, 100));
+											sheet.Row(i + startRow + 1).Height = 90;
+											sheet.Column(j + startColumn).Width = Math.Max(sheet.Column(j + startColumn).Width, picture.Image.Bounds.Width / picture.Image.Bounds.HorizontalResolution * percent / 6.4);
+											picture.SetSize((int)percent);
+										}
+										catch
+										{
+											throw new ArgumentException($"{i + startRow}行{j}列图像格式不受支持");
+										}
+									}
+
+									sheet.SetValue(i + startRow + 1, j + startColumn, "");
+
+									break;
+								}
+
+							case IEnumerable<Stream> streams:
+								{
+									double sumWidth = 0;
+									int index = 0;
+									foreach (var stream in streams.Where(stream => stream.Length > 2))
+									{
+										try
+										{
+											var picture = sheet.Drawings.AddPicture(Guid.NewGuid().ToString(), stream);
+											var percent = Math.Round(Math.Min(120f / picture.Image.Bounds.Height * picture.Image.Bounds.VerticalResolution, 100));
+											picture.SetPosition(i + startRow, 3, j + startColumn - 1, (int)Math.Ceiling(picture.Image.Bounds.Width / picture.Image.Bounds.HorizontalResolution * percent * index++)); //设置图片显示位置
+											sheet.Row(i + startRow + 1).Height = 90;
+											sumWidth += picture.Image.Bounds.Width / picture.Image.Bounds.HorizontalResolution * percent / 6.4;
+											sheet.Column(j + startColumn).Width = Math.Max(sheet.Column(j + startColumn).Width, sumWidth);
+											picture.SetSize((int)percent);
+										}
+										catch
+										{
+											throw new ArgumentException($"{i + startRow}行{j}列第{index}张图像格式不受支持");
+										}
+									}
+
+									sheet.SetValue(i + startRow + 1, j + startColumn, "");
+									break;
+								}
+
+							case IDictionary<string, Stream> dic:
+								{
+									double sumWidth = 0;
+									int index = 0;
+									foreach (var kv in dic.Where(kv => kv.Value.Length > 2))
+									{
+										try
+										{
+											var picture = sheet.Drawings.AddPicture(Guid.NewGuid().ToString(), kv.Value, new Uri(kv.Key));
+											var percent = Math.Round(Math.Min(120f / picture.Image.Bounds.Height * picture.Image.Bounds.VerticalResolution, 100));
+											picture.SetPosition(i + startRow, 3, j + startColumn - 1, (int)Math.Ceiling(picture.Image.Bounds.Width / picture.Image.Bounds.HorizontalResolution * percent * index++)); //设置图片显示位置
+											sheet.Row(i + startRow + 1).Height = 90;
+											sumWidth += picture.Image.Bounds.Width / picture.Image.Bounds.HorizontalResolution * percent / 6.4;
+											sheet.Column(j + startColumn).Width = Math.Max(sheet.Column(j + startColumn).Width, sumWidth);
+											picture.SetSize((int)percent);
+										}
+										catch
+										{
+											throw new ArgumentException($"{i + startRow}行{j}列第{index}张图像格式不受支持,图片链接:{kv.Key}");
+										}
+									}
+
+									sheet.SetValue(i + startRow + 1, j + startColumn, "");
+									break;
+								}
+
+							case IDictionary<string, MemoryStream> dic:
+								{
+									double sumWidth = 0;
+									int index = 0;
+									foreach (var kv in dic.Where(kv => kv.Value.Length > 2))
+									{
+										try
+										{
+											var picture = sheet.Drawings.AddPicture(Guid.NewGuid().ToString(), kv.Value, new Uri(kv.Key));
+											var percent = Math.Round(Math.Min(120f / picture.Image.Bounds.Height * picture.Image.Bounds.VerticalResolution, 100));
+											picture.SetPosition(i + startRow, 3, j + startColumn - 1, (int)Math.Ceiling(picture.Image.Bounds.Width / picture.Image.Bounds.HorizontalResolution * percent * index++)); //设置图片显示位置
+											sheet.Row(i + startRow + 1).Height = 90;
+											sumWidth += picture.Image.Bounds.Width / picture.Image.Bounds.HorizontalResolution * percent / 6.4;
+											sheet.Column(j + startColumn).Width = Math.Max(sheet.Column(j + startColumn).Width, sumWidth);
+											picture.SetSize((int)percent);
+										}
+										catch
+										{
+											throw new ArgumentException($"{i + startRow}行{j}列第{index}张图像格式不受支持,图片链接:{kv.Key}");
+										}
+									}
+
+									sheet.SetValue(i + startRow + 1, j + startColumn, "");
+									break;
+								}
+
+							case IDictionary<string, PooledMemoryStream> dic:
+								{
+									double sumWidth = 0;
+									int index = 0;
+									foreach (var kv in dic.Where(kv => kv.Value.Length > 2))
+									{
+										try
+										{
+											var picture = sheet.Drawings.AddPicture(Guid.NewGuid().ToString(), kv.Value, new Uri(kv.Key));
+											var percent = Math.Round(Math.Min(120f / picture.Image.Bounds.Height * picture.Image.Bounds.VerticalResolution, 100));
+											picture.SetPosition(i + startRow, 3, j + startColumn - 1, (int)Math.Ceiling(picture.Image.Bounds.Width / picture.Image.Bounds.HorizontalResolution * percent * index++)); //设置图片显示位置
+											sheet.Row(i + startRow + 1).Height = 90;
+											sumWidth += picture.Image.Bounds.Width / picture.Image.Bounds.HorizontalResolution * percent / 6.4;
+											sheet.Column(j + startColumn).Width = Math.Max(sheet.Column(j + startColumn).Width, sumWidth);
+											picture.SetSize((int)percent);
+										}
+										catch
+										{
+											throw new ArgumentException($"{i + startRow}行{j}列第{index}张图像格式不受支持,图片链接:{kv.Key}");
+										}
+									}
+
+									sheet.SetValue(i + startRow + 1, j + startColumn, "");
+									break;
+								}
+
+							default:
+								{
+									sheet.SetValue(i + startRow + 1, j + startColumn, table.Rows[i][j] ?? "");
+									if (table.Rows[i][j] is ValueType)
+									{
+										sheet.Column(j + startColumn).AutoFit();
+									}
+									else
+									{
+										// 根据单元格内容长度来自适应调整列宽
+										var fontFamily = SystemFonts.Families.FirstOrDefault(f => f.Name == sheet.Cells[i + startRow + 1, j + startColumn].Style.Font.Name);
+										int measureSize = 1;
+										if (fontFamily == default)
+										{
+											fontFamily = SystemFonts.Families.FirstOrDefault();
+											measureSize++;
+										}
+
+										var width = TextMeasurer.Measure(table.Rows[i][j].ToString(), new TextOptions(fontFamily.CreateFont(measureSize))).Width;
+										sheet.Column(j + startColumn).Width = Math.Min(110, Math.Max(width, sheet.Column(j + startColumn).Width));
+									}
+
+									break;
+								}
+						}
+					}
+				}
+
+				sheet.Cells.Style.WrapText = true;
+			}
+			else
+			{
+				sheet.Cells[startRow, startColumn].LoadFromDataTable(table, true, TableStyles.Light15).AutoFitColumns(12, 90);
+				sheet.Cells.Style.WrapText = true;
+			}
+		}
+	}
+
+	/// <summary>
+	/// 从datatable填充工作簿
+	/// </summary>
+	/// <param name="sheet">工作簿</param>
+	/// <param name="table">数据</param>
+	/// <param name="settings">列设置</param>
+	/// <param name="startRow">起始行,默认第一行</param>
+	/// <param name="startColumn">起始列,默认第一列A列</param>
+	public static void FillWorksheet<T>(this ExcelWorksheet sheet, IEnumerable<T> source, ColumnSettings settings = null, int startRow = 1, int startColumn = 1)
+	{
+		var hasPicColumn = false;
+		var properties = typeof(T).GetProperties();
+		if (source is ICollection<T> table)
+		{
+		}
+		else
+		{
+			table = source.ToList();
+		}
+
+		if (table.Any())
+		{
+			if (properties.Any(t => t.PropertyType.IsSubclassOf(typeof(Stream)) || typeof(IEnumerable<Stream>).IsAssignableFrom(t.PropertyType) || (typeof(IDictionary).IsAssignableFrom(t.PropertyType) && t.PropertyType.GenericTypeArguments[1].IsSubclassOf(typeof(Stream)))))
+			{
+				hasPicColumn = true;
+			}
+
+			if (hasPicColumn)
+			{
+				// 填充表头
+				var maxWidth = new int[properties.Length];
+				for (var j = 0; j < properties.Length; j++)
+				{
+					sheet.SetValue(startRow, j + startColumn, properties[j].Name);
+					maxWidth[j] = Encoding.UTF8.GetBytes(properties[j].Name).Length;
+				}
+
+				sheet.Row(startRow).Style.Font.Bold = true; // 表头设置为粗体
+				sheet.Row(startRow).Style.Font.Size = sheet.Row(startRow).Style.Font.Size * 1.11f; // 表头字号放大1.11倍
+				sheet.Row(startRow).Style.HorizontalAlignment = ExcelHorizontalAlignment.Center;
+				sheet.Row(startRow).CustomHeight = true; // 自动调整行高
+				if (settings != null)
+				{
+					foreach (var x in settings.ColumnTypes)
+					{
+						sheet.Column(x.Key).Style.Numberformat.Format = x.Value;
+					}
+				}
+				sheet.Cells.AutoFitColumns(); // 表头自适应列宽
+
+				// 填充内容
+				int current = 0;
+				foreach (var item in table)
+				{
+					sheet.Row(current + startRow + 1).CustomHeight = true; // 自动调整行高
+					for (int j = 0; j < properties.Length; j++)
+					{
+						switch (properties[j].GetValue(item))
+						{
+							case Stream s:
+								{
+									if (s.Length > 2)
+									{
+										try
+										{
+											var picture = sheet.Drawings.AddPicture(Guid.NewGuid().ToString(), s);
+											picture.SetPosition(current + startRow, 3, j + startColumn - 1, 5); //设置图片显示位置
+											var percent = Math.Round(Math.Min(120f / picture.Image.Bounds.Height * picture.Image.Bounds.VerticalResolution, 100));
+											sheet.Row(current + startRow + 1).Height = 90;
+											sheet.Column(j + startColumn).Width = Math.Max(sheet.Column(j + startColumn).Width, picture.Image.Bounds.Width / picture.Image.Bounds.HorizontalResolution * percent / 6.4);
+											picture.SetSize((int)percent);
+										}
+										catch
+										{
+											throw new ArgumentException($"{current + startRow}行{j}列图像格式不受支持");
+										}
+									}
+
+									sheet.SetValue(current + startRow + 1, j + startColumn, "");
+
+									break;
+								}
+
+							case IEnumerable<Stream> streams:
+								{
+									double sumWidth = 0;
+									int index = 0;
+									foreach (var stream in streams.Where(stream => stream.Length > 2))
+									{
+										try
+										{
+											var picture = sheet.Drawings.AddPicture(Guid.NewGuid().ToString(), stream);
+											var percent = Math.Round(Math.Min(120f / picture.Image.Bounds.Height * picture.Image.Bounds.VerticalResolution, 100));
+											picture.SetPosition(current + startRow, 3, j + startColumn - 1, (int)Math.Ceiling(picture.Image.Bounds.Width / picture.Image.Bounds.HorizontalResolution * percent * index++)); //设置图片显示位置
+											sheet.Row(current + startRow + 1).Height = 90;
+											sumWidth += picture.Image.Bounds.Width / picture.Image.Bounds.HorizontalResolution * percent / 6.4;
+											sheet.Column(j + startColumn).Width = Math.Max(sheet.Column(j + startColumn).Width, sumWidth);
+											picture.SetSize((int)percent);
+										}
+										catch
+										{
+											throw new ArgumentException($"{current + startRow}行{j}列第{index}张图像格式不受支持");
+										}
+									}
+
+									sheet.SetValue(current + startRow + 1, j + startColumn, "");
+									break;
+								}
+
+							case IDictionary<string, Stream> dic:
+								{
+									double sumWidth = 0;
+									int index = 0;
+									foreach (var kv in dic.Where(kv => kv.Value.Length > 2))
+									{
+										try
+										{
+											var picture = sheet.Drawings.AddPicture(Guid.NewGuid().ToString(), kv.Value, new Uri(kv.Key));
+											var percent = Math.Round(Math.Min(120f / picture.Image.Bounds.Height * picture.Image.Bounds.VerticalResolution, 100));
+											picture.SetPosition(current + startRow, 3, j + startColumn - 1, (int)Math.Ceiling(picture.Image.Bounds.Width / picture.Image.Bounds.HorizontalResolution * percent * index++)); //设置图片显示位置
+											sheet.Row(current + startRow + 1).Height = 90;
+											sumWidth += picture.Image.Bounds.Width / picture.Image.Bounds.HorizontalResolution * percent / 6.4;
+											sheet.Column(j + startColumn).Width = Math.Max(sheet.Column(j + startColumn).Width, sumWidth);
+											picture.SetSize((int)percent);
+										}
+										catch
+										{
+											throw new ArgumentException($"{current + startRow}行{j}列第{index}张图像格式不受支持,图片链接:{kv.Key}");
+										}
+									}
+
+									sheet.SetValue(current + startRow + 1, j + startColumn, "");
+									break;
+								}
+
+							case IDictionary<string, MemoryStream> dic:
+								{
+									double sumWidth = 0;
+									int index = 0;
+									foreach (var kv in dic.Where(kv => kv.Value.Length > 2))
+									{
+										try
+										{
+											var picture = sheet.Drawings.AddPicture(Guid.NewGuid().ToString(), kv.Value, new Uri(kv.Key));
+											var percent = Math.Round(Math.Min(120f / picture.Image.Bounds.Height * picture.Image.Bounds.VerticalResolution, 100));
+											picture.SetPosition(current + startRow, 3, j + startColumn - 1, (int)Math.Ceiling(picture.Image.Bounds.Width / picture.Image.Bounds.HorizontalResolution * percent * index++)); //设置图片显示位置
+											sheet.Row(current + startRow + 1).Height = 90;
+											sumWidth += picture.Image.Bounds.Width / picture.Image.Bounds.HorizontalResolution * percent / 6.4;
+											sheet.Column(j + startColumn).Width = Math.Max(sheet.Column(j + startColumn).Width, sumWidth);
+											picture.SetSize((int)percent);
+										}
+										catch
+										{
+											throw new ArgumentException($"{current + startRow}行{j}列第{index}张图像格式不受支持,图片链接: {kv.Key}");
+										}
+									}
+
+									sheet.SetValue(current + startRow + 1, j + startColumn, "");
+									break;
+								}
+
+							case IDictionary<string, PooledMemoryStream> dic:
+								{
+									double sumWidth = 0;
+									int index = 0;
+									foreach (var kv in dic.Where(kv => kv.Value.Length > 2))
+									{
+										try
+										{
+											var picture = sheet.Drawings.AddPicture(Guid.NewGuid().ToString(), kv.Value, new Uri(kv.Key));
+											var percent = Math.Round(Math.Min(120f / picture.Image.Bounds.Height * picture.Image.Bounds.VerticalResolution, 100));
+											picture.SetPosition(current + startRow, 3, j + startColumn - 1, (int)Math.Ceiling(picture.Image.Bounds.Width / picture.Image.Bounds.HorizontalResolution * percent * index++)); //设置图片显示位置
+											sheet.Row(current + startRow + 1).Height = 90;
+											sumWidth += picture.Image.Bounds.Width / picture.Image.Bounds.HorizontalResolution * percent / 6.4;
+											sheet.Column(j + startColumn).Width = Math.Max(sheet.Column(j + startColumn).Width, sumWidth);
+											picture.SetSize((int)percent);
+										}
+										catch
+										{
+											throw new ArgumentException($"{current + startRow}行{j}列第{index}张图像格式不受支持,图片链接: {kv.Key}");
+										}
+									}
+
+									sheet.SetValue(current + startRow + 1, j + startColumn, "");
+									break;
+								}
+
+							default:
+								{
+									sheet.SetValue(current + startRow + 1, j + startColumn, properties[j].GetValue(item) ?? "");
+									if (properties[j].GetValue(item) is ValueType)
+									{
+										sheet.Column(j + startColumn).AutoFit();
+									}
+									else
+									{
+										// 根据单元格内容长度来自适应调整列宽
+										var fontFamily = SystemFonts.Families.FirstOrDefault(f => f.Name == sheet.Cells[current + startRow + 1, j + startColumn].Style.Font.Name);
+										int measureSize = 1;
+										if (fontFamily == default)
+										{
+											fontFamily = SystemFonts.Families.FirstOrDefault();
+											measureSize++;
+										}
+
+										var width = TextMeasurer.Measure(properties[j].GetValue(item).ToString(), new TextOptions(fontFamily.CreateFont(measureSize))).Width;
+										sheet.Column(j + startColumn).Width = Math.Min(110, Math.Max(width, sheet.Column(j + startColumn).Width));
+									}
+
+									break;
+								}
+						}
+					}
+					current++;
+				}
+
+				sheet.Cells.Style.WrapText = true;
+			}
+			else
+			{
+				sheet.Cells[startRow, startColumn].LoadFromCollection(table, true, TableStyles.Light15).AutoFitColumns(12, 90);
+				sheet.Cells.Style.WrapText = true;
+			}
+		}
+	}
+
+	private static readonly NumberFormater NumberFormater = new("ABCDEFGHIJKLMNOPQRSTUVWXYZ", 1);
+
+	/// <summary>
+	/// 获取字母列
+	/// </summary>
+	/// <param name="sheet"></param>
+	/// <param name="index"></param>
+	/// <returns></returns>
+	public static ExcelColumn Column(this ExcelWorksheet sheet, string index)
+	{
+		return sheet.Column((int)NumberFormater.FromString(index));
+	}
 }
 }

+ 2 - 2
Masuit.Tools.Excel/Masuit.Tools.Excel.csproj

@@ -3,7 +3,7 @@
         <TargetFramework>netstandard2.0</TargetFramework>
         <TargetFramework>netstandard2.0</TargetFramework>
         <LangVersion>latest</LangVersion>
         <LangVersion>latest</LangVersion>
         <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
         <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
-        <Version>1.2.5.1</Version>
+        <Version>1.2.5.2</Version>
         <Authors>懒得勤快</Authors>
         <Authors>懒得勤快</Authors>
         <Description>Masuit.Tools.Excel导出库,支持一些简单数据的导出,支持图片列</Description>
         <Description>Masuit.Tools.Excel导出库,支持一些简单数据的导出,支持图片列</Description>
         <Copyright>懒得勤快</Copyright>
         <Copyright>懒得勤快</Copyright>
@@ -38,7 +38,7 @@
       </None>
       </None>
     </ItemGroup>
     </ItemGroup>
     <ItemGroup>
     <ItemGroup>
-        <PackageReference Include="EPPlus" Version="6.1.1" />
+        <PackageReference Include="EPPlus" Version="6.1.2" />
         <PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.1.1" PrivateAssets="All" />
         <PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.1.1" PrivateAssets="All" />
     </ItemGroup>
     </ItemGroup>
     <ItemGroup>
     <ItemGroup>

+ 1 - 1
Masuit.Tools.Net45/package.nuspec

@@ -2,7 +2,7 @@
 <package>
 <package>
   <metadata>
   <metadata>
     <id>Masuit.Tools.Net45</id>
     <id>Masuit.Tools.Net45</id>
-    <version>2.5.8.1</version>
+    <version>2.5.9.2</version>
     <title>Masuit.Tools</title>
     <title>Masuit.Tools</title>
     <authors>懒得勤快</authors>
     <authors>懒得勤快</authors>
     <owners>masuit.com</owners>
     <owners>masuit.com</owners>

+ 1 - 1
Masuit.Tools.NoSQL.MongoDBClient/Masuit.Tools.NoSQL.MongoDBClient.csproj

@@ -38,7 +38,7 @@
   </PropertyGroup>
   </PropertyGroup>
 
 
   <ItemGroup>
   <ItemGroup>
-    <PackageReference Include="MongoDB.Driver" Version="2.18.0" />
+    <PackageReference Include="MongoDB.Driver" Version="2.19.0" />
   </ItemGroup>
   </ItemGroup>
 
 
 </Project>
 </Project>

+ 2 - 2
Masuit.Tools/Masuit.Tools.csproj

@@ -177,7 +177,7 @@
       <Version>1.7.0</Version>
       <Version>1.7.0</Version>
     </PackageReference>
     </PackageReference>
     <PackageReference Include="HtmlSanitizer">
     <PackageReference Include="HtmlSanitizer">
-      <Version>8.0.601</Version>
+      <Version>8.0.645</Version>
     </PackageReference>
     </PackageReference>
     <PackageReference Include="Microsoft.AspNet.Mvc">
     <PackageReference Include="Microsoft.AspNet.Mvc">
       <Version>5.2.9</Version>
       <Version>5.2.9</Version>
@@ -195,7 +195,7 @@
       <Version>1.0.0-beta14</Version>
       <Version>1.0.0-beta14</Version>
     </PackageReference>
     </PackageReference>
     <PackageReference Include="StackExchange.Redis">
     <PackageReference Include="StackExchange.Redis">
-      <Version>2.6.80</Version>
+      <Version>2.6.90</Version>
     </PackageReference>
     </PackageReference>
     <PackageReference Include="System.ValueTuple">
     <PackageReference Include="System.ValueTuple">
       <Version>4.5.0</Version>
       <Version>4.5.0</Version>

+ 1 - 1
Masuit.Tools/package.nuspec

@@ -2,7 +2,7 @@
 <package>
 <package>
   <metadata>
   <metadata>
     <id>Masuit.Tools.Net</id>
     <id>Masuit.Tools.Net</id>
-    <version>2.5.8.1</version>
+    <version>2.5.9.2</version>
     <title>Masuit.Tools</title>
     <title>Masuit.Tools</title>
     <authors>懒得勤快</authors>
     <authors>懒得勤快</authors>
     <owners>masuit.com</owners>
     <owners>masuit.com</owners>

+ 1 - 1
NetCoreTest/NetCoreTest.csproj

@@ -8,7 +8,7 @@
     </PropertyGroup>
     </PropertyGroup>
 
 
     <ItemGroup>
     <ItemGroup>
-        <PackageReference Include="Swashbuckle.AspNetCore" Version="6.4.0" />
+        <PackageReference Include="Swashbuckle.AspNetCore" Version="6.5.0" />
     </ItemGroup>
     </ItemGroup>
 
 
     <ItemGroup>
     <ItemGroup>

+ 1 - 1
Test/Masuit.Tools.Abstractions.Test/Masuit.Tools.Abstractions.Test.csproj

@@ -13,7 +13,7 @@
   </ItemGroup>
   </ItemGroup>
 
 
   <ItemGroup>
   <ItemGroup>
-    <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.4.0" />
+    <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.4.1" />
     <PackageReference Include="xunit" Version="2.4.2" />
     <PackageReference Include="xunit" Version="2.4.2" />
     <PackageReference Include="xunit.runner.visualstudio" Version="2.4.5">
     <PackageReference Include="xunit.runner.visualstudio" Version="2.4.5">
       <PrivateAssets>all</PrivateAssets>
       <PrivateAssets>all</PrivateAssets>

+ 1 - 1
Test/Masuit.Tools.AspNetCore.ResumeFileResults.WebTest/Masuit.Tools.AspNetCore.ResumeFileResults.WebTest.csproj

@@ -23,7 +23,7 @@
   </ItemGroup>
   </ItemGroup>
 
 
   <ItemGroup>
   <ItemGroup>
-    <PackageReference Include="Swashbuckle.AspNetCore" Version="6.4.0" />
+    <PackageReference Include="Swashbuckle.AspNetCore" Version="6.5.0" />
   </ItemGroup>
   </ItemGroup>
 
 
   <ItemGroup>
   <ItemGroup>

+ 2 - 2
Test/Masuit.Tools.Core.Test/Masuit.Tools.Core.Test.csproj

@@ -9,9 +9,9 @@
   </PropertyGroup>
   </PropertyGroup>
 
 
   <ItemGroup>
   <ItemGroup>
-    <PackageReference Include="Microsoft.AspNetCore.TestHost" Version="7.0.1" />
+    <PackageReference Include="Microsoft.AspNetCore.TestHost" Version="7.0.2" />
     <PackageReference Include="Microsoft.Extensions.Hosting" Version="7.0.0" />
     <PackageReference Include="Microsoft.Extensions.Hosting" Version="7.0.0" />
-    <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.4.0" />
+    <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.4.1" />
     <PackageReference Include="xunit" Version="2.4.2" />
     <PackageReference Include="xunit" Version="2.4.2" />
     <PackageReference Include="xunit.runner.visualstudio" Version="2.4.5">
     <PackageReference Include="xunit.runner.visualstudio" Version="2.4.5">
       <PrivateAssets>all</PrivateAssets>
       <PrivateAssets>all</PrivateAssets>

+ 4 - 4
Test/Masuit.Tools.Test/Masuit.Tools.Test.csproj

@@ -79,7 +79,7 @@
   </ItemGroup>
   </ItemGroup>
   <ItemGroup>
   <ItemGroup>
     <PackageReference Include="Castle.Core">
     <PackageReference Include="Castle.Core">
-      <Version>5.1.0</Version>
+      <Version>5.1.1</Version>
     </PackageReference>
     </PackageReference>
     <PackageReference Include="Microsoft.AspNet.Mvc">
     <PackageReference Include="Microsoft.AspNet.Mvc">
       <Version>5.2.9</Version>
       <Version>5.2.9</Version>
@@ -94,13 +94,13 @@
       <Version>2.0.0</Version>
       <Version>2.0.0</Version>
     </PackageReference>
     </PackageReference>
     <PackageReference Include="Moq">
     <PackageReference Include="Moq">
-      <Version>4.18.3</Version>
+      <Version>4.18.4</Version>
     </PackageReference>
     </PackageReference>
     <PackageReference Include="MSTest.TestAdapter">
     <PackageReference Include="MSTest.TestAdapter">
-      <Version>3.0.0</Version>
+      <Version>3.0.2</Version>
     </PackageReference>
     </PackageReference>
     <PackageReference Include="MSTest.TestFramework">
     <PackageReference Include="MSTest.TestFramework">
-      <Version>3.0.0</Version>
+      <Version>3.0.2</Version>
     </PackageReference>
     </PackageReference>
     <PackageReference Include="NUnit">
     <PackageReference Include="NUnit">
       <Version>3.13.3</Version>
       <Version>3.13.3</Version>