文章目录
- 简介
- 开发环境
- 安装使用
- 特色功能示例代码
- 1. 检验字符串是否是Email、手机号、URL、IP地址、身份证号等
- 2.硬件监测(需要管理员权限,仅支持Windows,部分函数仅支持物理机模式)
- 3.html的防XSS处理:
- 4.整理Windows系统的内存:
- 5.任意进制转换/中文数字
- 6.纳秒级性能计时器
- 7.产生分布式唯一有序短id(雪花id)
- 8.农历转换
- 9.Linq表达式树扩展
- 10.模版引擎
- 11.List转Datatable
- 12.文件压缩解压
- 13.简易日志组件(又不是不能用.jpg)
- 14.多线程后台下载
- 15.加密解密/hash
- 16.实体校验
- 17.HTML操作
- 18.IP地址和URL
- 19.对象属性值合并
- 20.元素去重
- 21.枚举扩展
- 22.日期时间扩展
- 23简单的Excel导出
简介
库包含一些常用的操作类,大都是静态类,加密解密,反射操作,树结构,文件探测,权重随机筛选算法,分布式短id,表达式树,linq扩展,文件压缩,多线程下载,硬件信息,字符串扩展方法,日期时间扩展操作,中国农历,大文件拷贝,图像裁剪,验证码,断点续传,集合扩展、Excel导出等常用封装。
开发环境
操作系统:Windows 11 23H2及以上版本
开发工具:VisualStudio2022 v17.8及以上版本
SDK:.Net Core 2.1.0及以上所有版本
安装使用
基础功能包
.NET Framework ≥ 4.6.2
PM> Install-Package Masuit.Tools.Net
.NET Standard ≥ 2.1 或只想使用一些基本功能
通用项目推荐首选包
PM> Install-Package Masuit.Tools.Abstraction
.NET Core ≥ 2.1
.NET Core项目推荐首选包
PM> Install-Package Masuit.Tools.Core
.NET Framework 4.5特供版
请注意:这是.NET Framework 4.5的专用版本,相比4.6.2及.NET Core的版本,阉割了Redis、HTML、文件压缩、ASP.NET扩展、硬件监测、Session扩展等一些功能。如果你的项目版本高于4.6.2,请务必使用上述版本的包,以享受完整的功能体验!
PM> Install-Package Masuit.Tools.Net45
工具库注册配置
工具库需要用到外部配置节,.NET Framework项目配置在web.config/app.config的AppSettings配置节中,.NET Core项目配置在appsettings.json中:
EmailDomainWhiteList,邮箱校验需要用到的白名单域名,英文逗号分隔,每个元素支持正则表达式,若未配置,则不启用邮箱校验白名单,示例: “\w{1,5}@qq.com,\w{1,5}@163.com,\w{1,5}@gmail.com,\w{1,5}@outlook.com”
EmailDomainBlockList,邮箱校验需要用到的黑名单域名,英文逗号分隔,每个元素支持正则表达式,且黑名单优先级高于白名单,若未配置,则不启用邮箱校验黑白名单
public Startup(IConfiguration configuration)
{
configuration.AddToMasuitTools(); // 若未调用,则默认自动尝试加载appsettings.json
}
特色功能示例代码
1. 检验字符串是否是Email、手机号、URL、IP地址、身份证号等
var (isMatch, match) = "337845818@qq.com".MatchEmail(); // 可在appsetting.json中添加EmailDomainWhiteList和EmailDomainBlockList配置邮箱域名黑白名单,逗号分隔,如"EmailDomainBlockList": "^\\w{1,5}@qq.com,^\\w{1,5}@163.com,^\\w{1,5}@gmail.com,^\\w{1,5}@outlook.com",
bool isInetAddress = "114.114.114.114".MatchInetAddress(); // 匹配IP地址
bool isUrl = "http://masuit.org/20/history".MatchUrl(); // 匹配url
bool isPhoneNumber = "15205201520".MatchPhoneNumber(); // 匹配手机号
bool isLandline = "01088888888".MatchLandline(); // 匹配座机号
bool isIdentifyCard = "312000199502230660".MatchIdentifyCard();// 校验中国大陆身份证号
bool isCNPatentNumber = "200410018477.9".MatchCNPatentNumber(); // 校验中国专利申请号或专利号,是否带校验位,校验位前是否带“.”,都可以校验,待校验的号码前不要带CN、ZL字样的前缀
bool isUSCC = "200410018477.9".MatchUSCC(); // 校验企业统一社会信用代码
2.硬件监测(需要管理员权限,仅支持Windows,部分函数仅支持物理机模式)
float load = SystemInfo.CpuLoad;// 获取CPU占用率
long physicalMemory = SystemInfo.PhysicalMemory;// 获取物理内存总数
long memoryAvailable = SystemInfo.MemoryAvailable;// 获取物理内存可用率
double freePhysicalMemory = SystemInfo.GetFreePhysicalMemory();// 获取可用物理内存
double temperature = SystemInfo.GetCPUTemperature();// 获取CPU温度
int cpuCount = SystemInfo.GetCpuCount();// 获取CPU核心数
var ipAddress = SystemInfo.GetLocalIPs();// 获取本机所有IP地址
string localUsedIp = SystemInfo.GetLocalUsedIP();// 获取本机当前正在使用的IP地址
IList<string> macAddress = SystemInfo.GetMacAddress();// 获取本机所有网卡mac地址
string osVersion = Windows.GetOsVersion();// 获取操作系统版本
RamInfo ramInfo = SystemInfo.GetRamInfo();// 获取内存信息
var cpuSN=SystemInfo.GetCpuInfo()[0].SerialNumber; // CPU序列号
var driveSN=SystemInfo.GetDiskInfo()[0].SerialNumber; // 硬盘序列号
// 快速方法
var cpuInfos = CpuInfo.Locals; // 快速获取CPU的信息
var ramInfo = RamInfo.Local; // 快速获取内存的信息
var diskInfos = DiskInfo.Locals; // 快速获取硬盘的信息
var biosInfo = BiosInfo.Local; // 快速获取主板的信息
3.html的防XSS处理:
string html = @"<link href='/Content/font-awesome/css' rel='stylesheet'/>
<!--[if IE 7]>
<link href='/Content/font-awesome-ie7.min.css' rel='stylesheet'/>
<![endif]-->
<script src='/Scripts/modernizr'></script>
<div id='searchBox' role='search'>
<form action='/packages' method='get'>
<span class='user-actions'><a href='/users/account/LogOff'>退出</a></span>
<input name='q' id='searchBoxInput'/>
<input id='searchBoxSubmit' type='submit' value='Submit' />
</form>
</div>";
string s = html.HtmlSanitizerStandard();// 清理后:<div><span><a href="/users/account/LogOff">退出</a></span></div>
string s = html.HtmlSanitizerCustom(); // 自定义清理
4.整理Windows系统的内存:
类似于各大系统优化软件的加速球功能
Windows.ClearMemorySilent();
5.任意进制转换/中文数字
大写数字
var num=123.45.ToChineseMoney(); // 壹佰贰拾叁元肆角伍分
var num=123.45.ToChineseNumber(); // 一百二十三点四五
进制转换
可用于生成短id,短hash,随机字符串等操作,纯数学运算。
NumberFormater nf = new NumberFormater(36);//内置2-95进制的转换
//NumberFormater nf = new NumberFormater("0123456789abcdefghijklmnopqrstuvwxyz");// 自定义进制字符,可用于生成验证码,自定义字符可支持任意进制,你传1w个字符进去那就支持一万进制(手动狗头)
string s36 = nf.ToString(12345678);
long num = nf.FromString("7clzi");
Console.WriteLine("12345678的36进制是:" + s36); // 7clzi
Console.WriteLine("36进制的7clzi是:" + num); // 12345678
var s = new NumberFormater(91).ToString(new Random().Next(100000, int.MaxValue)); //配合随机数生成随机字符串
//扩展方法形式调用
var bin=12345678.ToBase(36);// 10进制转36进制:7clzi
var num="7clzi".FromBase(36);// 36进制转10进制:12345678
//超大数字的进制转换
var num = "e6186159d38cd50e0463a55e596336bd".FromBaseBig(16); // 大数字16进制转10进制
Console.WriteLine(num); // 十进制:305849028665645097422198928560410015421
Console.WriteLine(num.ToBase(64)); // 64进制:3C665pQUPl3whzFlVpoPqZ,22位长度
Console.WriteLine(num.ToBase(36)); // 36进制:dmed4dkd5bhcg4qdktklun0zh,25位长度
Console.WriteLine(num.ToBase(7)); // 7进制:2600240311641665565300424545154525131265221035,46位长度
Console.WriteLine(num.ToBase(12)); // 12进制:5217744842749978a756b22135b16a5998a5,36位长度
Console.WriteLine(num.ToBase(41)); // 41进制:opzeBda2aytcEeudEquuesbk,24位长度
如果你想让进制符支持emoji,NumberFormater是不支持的,不过如果你确实有这么骚的需求,我还准备了UnicodeFormater类,用于支持emoji,用法和NumberFormater一模一样,并且,UnicodeFormater的功能包含NumberFormater的功能,但是,性能比NumberFormater差了许多。
var formater = new UnicodeFormater("😀😁😂🤣😃😄😅😆😉😊😋😎😍😘🥰😗😙🥲😚🙂🤗🤩🤔🤨😑😶😶🌫🙄😏😣😥😮");
var s = formater.ToString(1234567890); // 😄🌫😶😋😋
var num = formater.FromString(s); // 1234567890
6.纳秒级性能计时器
HiPerfTimer timer = HiPerfTimer.StartNew();
for (int i = 0; i < 100000; i++)
{
//todo
}
timer.Stop();
Console.WriteLine("执行for循环100000次耗时"+timer.Duration+"s");
double time = HiPerfTimer.Execute(() =>
{
for (int i = 0; i < 100000; i++)
{
//todo
}
});
Console.WriteLine("执行for循环100000次耗时"+time+"s");
7.产生分布式唯一有序短id(雪花id)
// 实例调用
var sf = SnowFlake.GetInstance();
string id = sf.GetUniqueId();// rcofqodori0w
var sfn = SnowFlakeNew.GetInstance(); // 改良版雪花id,对时间回拨不敏感
string id = sfn.GetUniqueId();// vmbq8q3s3zul
// 静态调用
string id = SnowFlake.NewId;// rcofqodori0w
string shortId = sf.GetUniqueShortId(8);// qodw9728
string id = SnowFlakeNew.NewId;// 改良版雪花id,对时间回拨不敏感
// 全局设置
SnowFlake.SetMachienId(1); // 设置机器id
SnowFlake.SetInitialOffset(4219864516915105792); // 设置起始偏移量
SnowFlake.SetNumberFormater(new NumberFormater("0123456789abcdefghijklmnopqrstuvwxyz._-!")); // 设置数制格式化器
SnowFlakeNew.SetMachienId(1); // 设置机器id
SnowFlakeNew.SetInitialOffset(4219864516915105792); // 设置起始偏移量
SnowFlakeNew.SetNumberFormater(new NumberFormater("0123456789abcdefghijklmnopqrstuvwxyz._-!")); // 设置数制格式化器
var set = new HashSet<string>();
double time = HiPerfTimer.Execute(() =>
{
for (int i = 0; i < 1000000; i++)
{
set.Add(SnowFlake.NewId);
}
});
Console.WriteLine(set.Count == 1000000); //True
Console.WriteLine("产生100w个id耗时" + time + "s"); //2.6891495s
8.农历转换
ChineseCalendar.CustomHolidays.Add(DateTime.Parse("2018-12-31"),"元旦节");//自定义节假日
ChineseCalendar today = new ChineseCalendar(DateTime.Parse("2018-12-31"));
Console.WriteLine(today.ChineseDateString);// 二零一八年十一月廿五
Console.WriteLine(today.AnimalString);// 生肖:狗
Console.WriteLine(today.GanZhiDateString);// 干支:戊戌年甲子月丁酉日
Console.WriteLine(today.DateHoliday);// 获取按公历计算的节假日
9.Linq表达式树扩展
Expression<Func<string, bool>> where1 = s => s.StartsWith("a");
Expression<Func<string, bool>> where2 = s => s.Length > 10;
Func<string, bool> func = where1.And(where2)
.AndIf(!string.IsNullOrEmpty(name),s=>s==name)
.Compile(); // And和AndIf可供选择,满足条件再执行And
bool b=func("abcd12345678");//true
Expression<Func<string, bool>> where1 = s => s.StartsWith("a");
Expression<Func<string, bool>> where2 = s => s.Length > 10;
Func<string, bool> func = where1
.Or(where2)
.OrIf(!string.IsNullOrEmpty(name),s=>s==name)
.Compile(); // Or和OrIf可供选择,满足条件再执行Or
bool b=func("abc");// true
queryable.WhereIf(!string.IsNullOrEmpty(name),e=>e.Name==name)
.WhereIf(()=> age.HasValue,e=>e.Age>=age); // IQueryable的WhereIf扩展函数,满足条件再执行Where
10.模版引擎
var tmp = new Template("{{name}},你好!");
tmp.Set("name", "万金油");
string s = tmp.Render();//万金油,你好!
var tmp = new Template("{{one}},{{two}},{{three}}");
string s = tmp.Set("one", "1").Set("two", "2").Set("three", "3").Render();// 1,2,3
var tmp = new Template("{{name}},{{greet}}!");
tmp.Set("name", "万金油");
string s = tmp.Render();// throw 模版变量{{greet}}未被使用
11.List转Datatable
var list = new List<MyClass>()
{
new MyClass()
{
Name = "张三",
Age = 22
},
new MyClass()
{
Name = "李四",
Age = 21
},
new MyClass()
{
Name = "王五",
Age = 28
}
};
var table = list.Select(c => new{姓名=c.Name,年龄=c.Age}).ToDataTable();// 将自动填充列姓名和年龄
12.文件压缩解压
.NET Framework
MemoryStream ms = SevenZipCompressor.ZipStream(new List<string>()
{
@"D:\1.txt",
"http://ww3.sinaimg.cn/large/87c01ec7gy1fsq6rywto2j20je0d3td0.jpg",
});//压缩成内存流
SevenZipCompressor.Zip(new List<string>()
{
@"D:\1.txt",
"http://ww3.sinaimg.cn/large/87c01ec7gy1fsq6rywto2j20je0d3td0.jpg",
}, zip);//压缩成zip
SevenZipCompressor.UnRar(@"D:\Download\test.rar", @"D:\Download\");//解压rar
SevenZipCompressor.Decompress(@"D:\Download\test.tar", @"D:\Download\");//自动识别解压压缩包
SevenZipCompressor.Decompress(@"D:\Download\test.7z", @"D:\Download\");
ASP.NET Core
Startup.cs
services.AddSevenZipCompressor();
构造函数注入ISevenZipCompressor
private readonly ISevenZipCompressor _sevenZipCompressor;
public Test(ISevenZipCompressor sevenZipCompressor)
{
_sevenZipCompressor = sevenZipCompressor;
}
使用方式同.NET Framework版本
13.简易日志组件(又不是不能用.jpg)
LogManager.LogDirectory=AppDomain.CurrentDomain.BaseDirectory+"/logs";
LogManager.Event+=info =>
{
//todo:注册一些事件操作
};
LogManager.Info("记录一次消息");
LogManager.Error(new Exception("异常消息"));
14.多线程后台下载
var mtd = new MultiThreadDownloader("https://attachments-cdn.shimo.im/yXwC4kphjVQu06rH/KeyShot_Pro_7.3.37.7z",Environment.GetEnvironmentVariable("temp"),"E:\\Downloads\\KeyShot_Pro_7.3.37.7z",8);
mtd.Configure(req =>
{
req.Referer = "https://masuit.com";
req.Headers.Add("Origin", "https://baidu.com");
});
mtd.TotalProgressChanged+=(sender, e) =>
{
var downloader = sender as MultiThreadDownloader;
Console.WriteLine("下载进度:"+downloader.TotalProgress+"%");
Console.WriteLine("下载速度:"+downloader.TotalSpeedInBytes/1024/1024+"MBps");
};
mtd.FileMergeProgressChanged+=(sender, e) =>
{
Console.WriteLine("下载完成");
};
mtd.FileMergedComplete+=(sender,e)=>{
Console.WriteLine("文件合并完成");
};
mtd.Start();//开始下载
//mtd.Pause(); // 暂停下载
//mtd.Resume(); // 继续下载
15.加密解密/hash
var enc="123456".MDString();// MD5
var enc="123456".MDString("abc");// MD5加盐
var enc="123456".MDString2();// MD5两次
var enc="123456".MDString2("abc");// MD5两次加盐
var enc="123456".MDString3();// MD5三次
var enc="123456".MDString3("abc");// MD5三次加盐
string aes = "123456".AESEncrypt();// AES加密为密文
string s = aes.AESDecrypt(); //AES解密为明文
string aes = "123456".AESEncrypt("abc");// AES密钥加密为密文
string s = aes.AESDecrypt("abc"); //AES密钥解密为明文
string enc = "123456".DesEncrypt();// DES加密为密文
string s = enc.DesDecrypt(); //DES解密为明文
string enc = "123456".DesEncrypt("abcdefgh");// DES密钥加密为密文
string s = enc.DesDecrypt("abcdefgh"); //DES密钥解密为明文
RsaKey rsaKey = RsaCrypt.GenerateRsaKeys();// 生成RSA密钥对
string encrypt = "123456".RSAEncrypt(rsaKey.PublicKey);// 公钥加密
string s = encrypt.RSADecrypt(rsaKey.PrivateKey);// 私钥解密
string s = "123".Crc32();// 生成crc32摘要
string s = "123".Crc64();// 生成crc64摘要
string s = "123".SHA256();// 生成SHA256摘要
// 零宽字符串,通常用作文章暗水印,以一种看不见的字符插入到文本中,使攻击者无法直接识别文本内容,从而起到保护文章的作用,可通过代码把水印还原出来取证。
string pub="hello,world!";
string hidden="ldqk";
var str = pub.InjectZeroWidthString(hidden); // 扩展函数调用:将"ldqk"以零宽字符串的方式隐藏在"hello,world!"中
var str = ZeroWidthCodec.Encrypt(pub,hidden); // 类调用:将"ldqk"以零宽字符串的方式隐藏在"hello,world!"中
var dec = str.DecodeZeroWidthString(); // 扩展函数调用:将包含零宽字符串的密文解密出隐藏字符串"ldqk"
var dec = ZeroWidthCodec.Decrypt(str); // 类调用:将包含零宽字符串的密文解密出隐藏字符串"ldqk"
var enc = hidden.EncodeToZeroWidthText(); // 扩展函数调用:将字符串编码成零宽字符串
var enc = ZeroWidthCodec.Encode(str); // 类调用:将字符串编码成零宽字符串
16.实体校验
public class MyClass
{
[IsEmail] //可在appsetting.json中添加EmailDomainWhiteList配置邮箱域名白名单,逗号分隔
public string Email { get; set; }
[IsPhone]
public string PhoneNumber { get; set; }
[IsLandline]
public string Landline { get; set; }
[IsIPAddress]
public string IP { get; set; }
[MinValue(0, ErrorMessage = "年龄最小为0岁"), MaxValue(100, ErrorMessage = "年龄最大100岁")]
public int Age { get; set; }
[ComplexPassword]//密码复杂度校验,默认最小长度6,最大长度30,必须包含数字、字母、特殊符号
public string Password { get; set; }
[ComplexPassword(MustNumber=true,MustLetter=true,MustSymbol=true)]//密码复杂度校验,默认最小长度6,最大长度30,手动配置必须包含数字、字母、特殊符号
public string Password { get; set; }
[ComplexPassword(4,12)]//密码复杂度校验,配置最小长度4,最大长度12
public string Password { get; set; }
[EnumOf] // 检测是否是有效枚举值
public MyEnum MyEnum { get; set; }
[MinItemsCount(1)] // 检测集合元素最少1个
public List<string> Strs { get; set; }
[UnifiedSocialCreditCode] // 校验企业统一社会信用代码
public string USCC { get; set; }
}
17.HTML操作
List<string> srcs = "html".MatchImgSrcs().ToList();// 获取html字符串里所有的img标签的src属性
var imgTags = "html".MatchImgTags();//获取html字符串里的所有的img标签
var str="html".RemoveHtmlTag(); // 去除html标签
18.IP地址和URL
bool inRange = "192.168.2.2".IpAddressInRange("192.168.1.1","192.168.3.255");// 判断IP地址是否在这个地址段里
bool isPrivateIp = "172.16.23.25".IsPrivateIP();// 判断是否是私有地址
bool isExternalAddress = "http://baidu.com".IsExternalAddress();// 判断是否是外网的URL
//以下需要配置baiduAK
string isp = "114.114.114.114".GetISP(); // 获取ISP运营商信息
PhysicsAddress physicsAddress = "114.114.114.114".GetPhysicsAddressInfo().Result;// 获取详细地理信息对象
Tuple<string, List<string>> ipAddressInfo = "114.114.114.114".GetIPAddressInfo().Result;// 获取详细地理信息集合
uint number=ipAddress.ToUInt32(); // IP地址转10进制
uint number="114.114.114.114".IPToID(); // IP地址转10进制
19.对象属性值合并
public class MyClass
{
public string A { get; set; }
public bool? B { get; set; }
public int? C { get; set; }
}
var a = new MyClass()
{
A = "aa"
};
var b = new MyClass()
{
B = true
};
var c = new MyClass()
{
C = 3
};
var merge = a.Merge(b, c); // 合并后对象:A = "aa",B = true,C = 3
20.元素去重
var list = new List<MyClass>()
{
new MyClass()
{
Email = "1@1.cn"
},
new MyClass()
{
Email = "1@1.cn"
},
new MyClass()
{
Email = "1@1.cn"
}
};
List<MyClass> classes = list.DistinctBy(c => c.Email).ToList();
Console.WriteLine(classes.Count==1);//True
21.枚举扩展
[Flags]
public enum MyEnum
{
[Display(Name = "读")]
[Description("读")]
[EnumDescription("读取操作","读","zh-CN")] // 多语言枚举描述
[EnumDescription("Read","Read","en-US")]
Read=1,
[Display(Name = "写")]
[Description("写")]
Write=2,
Delete=4,
All=8
}
Dictionary<int, string> dic1 = typeof(MyEnum).GetDictionary();// 获取枚举值和字符串表示的字典映射
var dic2 = typeof(MyEnum).GetDescriptionAndValue();// 获取字符串表示和枚举值的字典映射
string desc = MyEnum.Read.GetDescription();// 获取Description标签
string display = MyEnum.Read.GetDisplay();// 获取Display标签的Name属性
var value = typeof(MyEnum).GetValue("Read");//获取字符串表示值对应的枚举值
var op=MyEnum.Read|MyEnum.Write|MyEnum.Delete;
var enums=op.Split(); // 拆分枚举值,得到枚举数组,这个函数建议使用在按位定值的枚举
22.日期时间扩展
double milliseconds = DateTime.Now.GetTotalMilliseconds();// 获取毫秒级时间戳
double microseconds = DateTime.Now.GetTotalMicroseconds();// 获取微秒级时间戳
double nanoseconds = DateTime.Now.GetTotalNanoseconds();// 获取纳秒级时间戳
double seconds = DateTime.Now.GetTotalSeconds();// 获取秒级时间戳
double minutes = DateTime.Now.GetTotalMinutes();// 获取分钟级时间戳
var indate=DateTime.Parse("2020-8-3").In(DateTime.Parse("2020-8-2"),DateTime.Parse("2020-8-4"));//true
DateTime time="2021-1-1 8:00:00".ToDateTime(); //字符串转DateTime
//时间段计算工具
var range = new DateTimeRange(DateTime.Parse("2020-8-3"), DateTime.Parse("2020-8-5"));
range.Union(DateTime.Parse("2020-8-4"), DateTime.Parse("2020-8-6")); //连接两个时间段,结果:2020-8-3~2020-8-6
range.In(DateTime.Parse("2020-8-3"), DateTime.Parse("2020-8-6"));//判断是否在某个时间段内,true
var (intersected,range2) = range.Intersect(DateTime.Parse("2020-8-4"), DateTime.Parse("2020-8-6"));//两个时间段是否相交,(true,2020-8-3~2020-8-4)
range.Contains(DateTime.Parse("2020-8-3"), DateTime.Parse("2020-8-4"));//判断是否包含某个时间段,true
range.GetUnionSet(List<DateTimeRange>); // 根据某个时间段查找在某批时间段中的最大并集
range.GetMaxTimePeriod(List<DateTimeRange>); // 获取一批时间段内存在相互重叠的最大时间段
23简单的Excel导出
需要额外依赖包:Masuit.Tools.Excel
var stream=list.Select(item=>new{
姓名=item.Name,
年龄=item.Age,
item.Gender,
Avatar=Image.FromStream(filestream) //图片列
}).ToDataTable().ToExcel("Sheet1"); //自定义列名导出
var stream=list.ToDataTable("Sheet1").ToExcel("文件密码");