Excel催化剂开源第29波-在Winform上使用富文本编辑器控件

富文本编辑器,一般都是BS架构专利一般,好像百度有一个开源的比较出名,但无奈这些都只能用在JS上,在BS网页端开发上使用。像Winform开发的VSTO,只能羡慕的份。和一般Winform上用的RichText控件,别人BS的富文本编辑器就强大得多。

笔者找寻过程中,也总算找到一款很不错的开源控件,将它的dll编译后,还真能用了。

在Excel催化剂的批量邮件功能中, 为了得到最好的体验,不止是不用依赖OUTLOOK的组件来发邮件(好像VBA的方案只能用outlook组件,用户电脑没安装outlook就不能用),同时为了让用户可以在邮件正文编辑区的使用体验和outlookup或网页端的发邮件体验一样,用了一个第3方的富文本编辑器,不是RichText控件,所以对网页的支持特别友好,随便复杂网页上的内容,粘贴过来,渲染得非常出色。

Excel催化剂开源第29波-在Winform上使用富文本编辑器控件

邮件群发功能

这个第3方富文本编辑器控件,不单单可以在里面作一些格式的配置,还可以有打开html文件,直接从网页其他地方复杂内容直接粘贴和插入本地图片,有了这些能力,在发送邮件正文时,使用体验就非常棒,可以发送出去的邮件正文,不是纯文本的形式,毫无格式,同时可以发送本地图片,特别是有些时候,正文内容需要说明一切重要内容,无需点开附件查看,或者正文中有邮件签名时,签名位置有图片也是常有的事情,特别是放个二维码之类的。

同样地水平有限,具体技术细节也不懂,只是能用起来的程度。只需引用以下的dll即可。

有兴趣的可以看作者的github代码https://github.com/yahch/kwig

Excel催化剂开源第29波-在Winform上使用富文本编辑器控件

富文本控件dll

此控件是自定义控件,可以通过设计器拖拉出来。

群发邮件核心代码,用这个富文本控件,拿到其渲染后的html文件,发邮件当然有C#自己的轮子,也很好用。

string htmlBodyContent = this.kEditor1.Html;
 private async Task BatchSendingEmail()
 {
 SmtpClient client = GetSmtpClient();
 //string[] lisColNames = { "邮件标题", "收件人邮箱", "抄送邮箱", "密件抄送邮箱", "优先级", "附件路径" };
 int ColIndexOfsubject = this.SendInfoListObject.ListColumns["邮件标题"].Index;
 int ColIndexOfTo = this.SendInfoListObject.ListColumns["收件人邮箱"].Index;
 int ColIndexOfCC = this.SendInfoListObject.ListColumns["抄送邮箱"].Index;
 int ColIndexOfBCC = this.SendInfoListObject.ListColumns["密件抄送邮箱"].Index;
 int ColIndexOfPriority = this.SendInfoListObject.ListColumns["优先级"].Index;
 int ColIndexOfAttachments = this.SendInfoListObject.ListColumns["附件路径"].Index;
 int ColIndexOfAttachmentsSize = this.SendInfoListObject.ListColumns["附件最大限制(M)"].Index;
 int ColIndexOfStatus = this.SendInfoListObject.ListColumns["发送状态"].Index;
 string htmlBodyContent = this.kEditor1.Html;
 foreach (Excel.ListRow row in this.SendInfoListObject.ListRows)
 {
 if (isCancelSending == false)
 {
 try
 {
 string subject = row.Range[ColIndexOfsubject].Value2 != null ? row.Range[ColIndexOfsubject].Value2.ToString() : string.Empty;
 string to = row.Range[ColIndexOfTo].Value2 != null ? row.Range[ColIndexOfTo].Value2.ToString() : string.Empty;
 string cc = row.Range[ColIndexOfCC].Value2 != null ? row.Range[ColIndexOfCC].Value2.ToString() : string.Empty;
 string bcc = row.Range[ColIndexOfBCC].Value2 != null ? row.Range[ColIndexOfBCC].Value2.ToString() : string.Empty;
 string priority = row.Range[ColIndexOfPriority].Value2 != null ? row.Range[ColIndexOfPriority].Value2.ToString() : "正常";
 MailPriority mailPriority = priority == "高" ? MailPriority.High : priority == "低" ? MailPriority.Low : MailPriority.Normal;
 string attachments = row.Range[ColIndexOfAttachments].Value2 != null ? row.Range[ColIndexOfAttachments].Value2.ToString() : string.Empty;
 int attachmentsSize = int.Parse(row.Range[ColIndexOfAttachmentsSize].Value2 != null ? row.Range[ColIndexOfAttachmentsSize].Value2.ToString() : "0");
 long totalLength = 0;
 foreach (var filePath in attachments.Split(new char[] { ';', ';' }, StringSplitOptions.RemoveEmptyEntries))
 {
 FileInfo fileInfo = new FileInfo(filePath);
 totalLength = totalLength + fileInfo.Length;
 }
 if (totalLength / 1024.0 / 1024.0 > attachmentsSize)
 {
 row.Range[ColIndexOfStatus].Value2 = "发送失败,附件大小超出最大限制";
 continue;
 }
 if (!string.IsNullOrEmpty(subject) && !string.IsNullOrEmpty(to))
 {
 MailMessage mailMessage = GetMailMessage(row, subject, to, cc, bcc, mailPriority, attachments, htmlBodyContent);
 try
 {
 await client.SendTaskAsync(mailMessage);
 row.Range[ColIndexOfStatus].Value2 = "发送完成";
 }
 catch (Exception ex)
 {
 row.Range[ColIndexOfStatus].Value2 = "发送失败,原因为" + ex.Message;
 }
 }
 }
 catch (Exception ex)
 {
 row.Range[ColIndexOfStatus].Value2 = "发送失败,原因为" + ex.Message;
 }
 finally
 {
 await Task.Factory.StartNew(() => Thread.Sleep(int.Parse(Properties.Settings.Default.BatchMailSendStopSecond) * 1000));
 }
 }
 }
 //this.Close();
 this.Invoke(new Action(() => this.Close()));
 }

此控件,需要重写的方法,具体原理自己去看作者示例文档解释

 public void OnEditorErrorOccured(Exception ex)
 {
 //throw new NotImplementedException();
 }
 public void OnEditorLoadComplete()
 {
 //throw new NotImplementedException();
 }
 public void OnInsertImageClicked()
 {
 OpenFileDialog ofd = new OpenFileDialog();
 ofd.Filter = "图片|*.jpg;*.png;*.gif";
 if (ofd.ShowDialog() == DialogResult.OK)
 {
 string n = "";
 kEditor1.InsertNode(n);
 //把图片放到字典中,供之后清洗时取出来
 dicImageInfo.Add("t" + (dicImageInfo.Count + 1), "//img05.71396.com/ba/ua/1858745191f2db86.jpg" + ofd.FileName);
 }
 }
 public void OnOpenButtonClicked()
 {
 OpenFileDialog ofd = new OpenFileDialog();
 ofd.Filter = "*.html|*.html";
 if (ofd.ShowDialog() == DialogResult.OK)
 {
 string text = System.IO.File.ReadAllText(ofd.FileName);
 kEditor1.InsertNode(text);
 }
 }
 public void OnSaveButtonClicked()
 {
 SaveFileDialog sfd = new SaveFileDialog();
 sfd.Filter = "*.html|*.html";
 if (sfd.ShowDialog() == System.Windows.Forms.DialogResult.OK)
 {
 System.IO.File.WriteAllText(sfd.FileName, kEditor1.Html);
 }
 }

结语

接连的这几篇文章,大家都可以感受到,对于一个业务导向的业余开发者来说,如果找到好的轮子,也可以实现很多复杂场景,用户体验也可以做得很好。所以VSTO和VBA开发,真的有一个本质的区别,VBA大不了最多用下系统的API函数,OFFICE的对象模型,但在VSTO的世界里,只要用心找,可以尽性地用尽一切世界上优秀的代码轮子。

展开阅读全文

页面更新:2024-03-26

标签:编辑器   控件   密件   文本   收件人   优先级   轮子   能用   催化剂   附件   邮箱   邮件   代码   网页   数码   正文   图片

1 2 3 4 5

上滑加载更多 ↓
推荐阅读:
友情链接:
更多:

本站资料均由网友自行发布提供,仅用于学习交流。如有版权问题,请与我联系,QQ:4156828  

© CopyRight 2020-2024 All Rights Reserved. Powered By 71396.com 闽ICP备11008920号-4
闽公网安备35020302034903号

Top