VSTO之旅系列(六):实现Office的自动化,使你办公更容易

写在前面:本博客所有VSTO之旅系列均来自于网络,一切权益归原作者所有,由于原文价值较高,受到多次转载,此处转载仅为学习之用,转载时对原文部分进行了简要修改,向原作者致敬。

引言

在我们日常办公中,我们经常可能遇到一些重复性的工作,如果手工去做即繁琐又费时,比如在我们论文的写作中经常会遇到文中存在很多空白的段落,可以利用传统手工的方式重新审阅一遍,再手动删除这些空白行,如果大量的论文、报告都需要这样手工去处理,其繁琐程度可想而知。又如人事工作中有一项工作设定是每个月末给本月的寿星员工发送邮件来通知参加生日会,又比如员工信息位于Exce之l中,那么我们就需要手动从这些表格中去查找本月寿星的邮箱,然后用Outlook一个一个添加邮件地址来给本月寿星发送邮件。诸如此类的工作,能否运用VSTO技术来实现Office自动化呢?回答是肯定的。下面就上面那项工作运用VSTO编程来做个示例。

1、自动删除Word中的空白行和页

在引言部分,我们已经提出了这个需求的。记得当时在写毕业论文的时候,我也做过这些重复的事情,经常写完之后会再去审阅一遍毕业论文中的所有文档,然后手动把一些空白行删除掉,由于当时并不知道可以对Word来进行自动化编程,所以只能傻傻地做这样一些重复的事情。但是现在不一样了,自从接触了VSTO之后,才知道Office一系列产品都是提供了一些公开的API的,我们可以利用这些对象使我们自定义Office程序和使Office自动化地工作,下面就具体讲讲如何实现这个小的工具的。
首先,我们先明确下这个工具需要实现的功能——自动移除Word文档中的空白行。然后向大家解释下实现该工具的思路:

==我们打开一个Word文档,该Word文档就是一个Word.Document对象
Word文档中内容都是段落组成的,然而段落在Word对象模型中是Word.Paragraph对象
空白行或空白页也就是段落的内容为空。
明白了这点,我们就可以在程序中对段落对象的文本进行判断。
如果段落内容为空,我们就删除该段落,这样也就实现了移除空白行的功能了。==

有了上面的思路之后,然后大家只需要了解Word中对象模型,然后通过对象模型找到段落对象,然后再判断它的文本是否为空,为空就删除段落,不为空就什么都不做。所以思路有了之后,就是要了解Word对象模型了,对于这部分内容,大家可以参考我博客的中的——创建Word解决方案。由于代码中都有注释,这里就直接看实现该工具的核心代码:

    string[] wordPatharray = null;
    // 打开需要操作的Word文档
    privatevoid btnOpen_Click(object sender, EventArgs e)
           {
    using (OpenFileDialog openFileDialog = new OpenFileDialog())
               {
                   openFileDialog.Filter = "Word document(*.doc;*.docx)|*.dox;**.docx|All Files(*.*)|*.*";
    // 设置允许选择多个文件,该属性默认为false的,即只允许选择一个文件
                   openFileDialog.Multiselect = true;
    if (openFileDialog.ShowDialog() == DialogResult.OK)
                   {
                       txtWordPath.Text = openFileDialog.FileName;
    // 获得所有选定文件的文件名
                       wordPatharray = openFileDialog.FileNames;
                   }
               }
           }
    // 移除Word中的所有空页
    privatevoid btnRemove_Click(object sender, EventArgs e)
           {
               Word.Application wordapp = null;
               Word.Document doc = null;
    try
               {
    // 启动Word应用程序并设置不可见
                   wordapp = new Word.Application();
    // 如果不设置该属性,就可以看到Word程序的启动过程,这个和我们手动启动Word是一样的
                   wordapp.Visible = false;
    // 遍历每个文件名
    foreach (var wordpath in wordPatharray)
                   {
                       doc = wordapp.Documents.Open(wordpath);
    // 删除所有空白页面
                       Word.Paragraph paragraph;
                       Word.Paragraphs paragraphs = doc.Paragraphs;
    for (int i = paragraphs.Count; i > 0; i--)
                       {
                           paragraph = paragraphs[i];
    //  如果段落的文本为空的话,首先选择该段落,然后再调用Word中Selection对象的Delete方法来删除
    // 不为空什么都不做
    if (paragraph.Range.Text.Trim() == string.Empty)
                           {
                               paragraph.Range.Select();
                               wordapp.Selection.Delete();
                           }
                       }
    if (doc != null)
                      {

    // 先保存所有修改再关闭Word文档
                           doc.Save();
                           ((Word._Document)doc).Close();
                       }
                   }
                   MessageBox.Show("删除空白行成功");
               }
    catch (Exception ex)
               {
                   MessageBox.Show("异常发生,异常信息为:" + ex.Message);
               }
    finally
               {
    // 释放资源
    // 退出Word程序
    if (wordapp != null)
                   {
                       ((Word._Application)wordapp).Quit();
                   }
                   doc = null;
                   wordapp = null;
               }
           }

为了测试该程序的正确性,这里我建立了两个测试文档,为了测试,我故意在文档中删除了空白行和空白页面,下面是两个测试文档的截图:
在这里插入图片描述

2、自动给本月寿星员工发送邮件提醒

为了帮助大家更好地理解该程序,还是像之前一样,首先说说实现该程序的思路:

(1)打开员工信息表,此时我们可以利用Excel对象模型中的Excel.Application.Workbooks.Open方法来获得一个工作簿对象。
(2)通过遍历工作簿中的激活表,即表格一(Sheet1),我们可以通过workbook.ActiveSheet来获得表格一对象。
遍历表格一中的所有行来找到生日信息中的月份,如果月份等于当前月份,就给该员工的邮箱进行发邮件。
(3)自动发送邮件与手动发送原理一样,手动操作发送邮件过程是打开Outlook(在程序中就是创建Outlook应用程序对象),然后点击新建邮件(在程序中就是通过Applicatin对象的CreateItem(Outlook.OlItemType.olMailItem)方法来创建一个邮件项目),在新建邮件窗口中指定收件人,主题,邮件内容之后,点击Outlook中的发送邮件按钮(在程序中就是通过指定 Outlook.MailItem对象(即代表一个邮件窗体)的To(收件人)、Subject(主题)、Body(邮件内容)属性,然后再调用Send方法来发送邮件)

明白了思路之后,我们理解代码会更加容易了,具体实现代码为:

sing System;
using System.IO;
using System.Runtime.InteropServices;
using System.Windows.Forms;
// 引用Excel和Outlook的命名空间
using Excel = Microsoft.Office.Interop.Excel;
using Outlook = Microsoft.Office.Interop.Outlook;
string excelpath = string.Empty;
// 打开员工表格
privatevoid btnOpen_Click(object sender, EventArgs e)
       {
using (OpenFileDialog openFileDialog = new OpenFileDialog())
           {
               openFileDialog.Filter = "Excel File(*.xls;*.xlsx)|*.xls;**.xlsx|All Files(*.*)|*.*";
if (openFileDialog.ShowDialog() == DialogResult.OK)
               {
                   txtExcelPath.Text = openFileDialog.FileName;
                   excelpath = openFileDialog.FileName;
               }
           }
       }
// 自动给本月寿星发邮件通知
privatevoid btnSendEmail_Click(object sender, EventArgs e)
       {
if (!File.Exists(txtExcelPath.Text))
           {
               MessageBox.Show("员工表路径不存在,请确保输入正确的文件路径");
return;
           }
if (txbBirthday.Text.Trim() == string.Empty || txbEmail.Text.Trim() == string.Empty)
           {
               MessageBox.Show("请先输入员工表中生日信息所在的列和邮箱信息所在的列!");
return;
           }
// 输入信息都正确时开始发送邮件
           SendEmail(int.Parse(txbBirthday.Text.Trim()), int.Parse(txbEmail.Text.Trim()));
       }
// 发送邮件方法
privatevoid SendEmail(int birthDayColumn,int emailColumn)
       {
// 获得当前月份
int nowmonth = DateTime.Now.Month;
// 发送邮件地址字符串
string toEmailString = string.Empty;
string emailBody="请收到邮件的员工,请本月28号到休闲室来参加生日Party";
           Excel.Application excelApp = null;
           Excel.Workbook workbook =null;
           Excel.Worksheet worksheet = null;
           Excel.Range range = null;
try
           {
// 新建Excel应用程序被设置它不可见
               excelApp = new Excel.Application();
               excelApp.Visible = false;
               workbook = excelApp.Workbooks.Open(excelpath);
// 获得打开文件的激活表格
              worksheet= workbook.ActiveSheet;
// 遍历表格中的所有行
for (int row = 2; row < worksheet.UsedRange.Rows.Count + 1; row++)
               {
// 因为我的测试表格中第四列是生日信息,在Excel中第一行的下标是从1开始的
// 这里本来需要在页面设置一个文本框让用户填写生日信息是在那一列的
// 这里为了测试就直接在程序中指定
// 下面的Range就代表生日列中每一个单元格
                   range = worksheet.Cells[row, birthDayColumn];
// 我们可以通过Range.Value来获得单元格中的生日信息
// 因为我生日单元格中为日期格式,所以获得的是日期类型,所以直接通过Month属性来获得月份
int month = range.Value.Month;
// 如果我们的Excel文档中生日时间设置为文本格式的话,这时候就需要通过分割字符串的方式来获得月份
// 通过Split函数来把生日信息以'/'符号分隔,分隔的数组的第二个就是月份
//int month = Int32.Parse(birthday.Split('/')[1]);
// 如果月份等于当前月的话,就给这个人发邮件
if (month == nowmonth)
                   {
// 获得本月生日员工的邮件地址
                       toEmailString += ";" + ((Excel.Range)worksheet.Cells[row, emailColumn]).Value;
                   }
               }
           }
catch (Exception ex)
           {
               MessageBox.Show("读取员工表格时出错,异常信息为:" + ex.Message);
return;
           }
finally
           {
               workbook.Close(Excel.XlSaveAction.xlDoNotSaveChanges);
               excelApp.Quit();
if (workbook != null)
               {
                   Marshal.FinalReleaseComObject(workbook);
                   workbook = null;
               }
if (excelApp != null)
               {
                   Marshal.FinalReleaseComObject(excelApp);
                   excelApp = null;
               }
           }
if (CreateEmailItem("生日提醒", toEmailString, emailBody))
           {
               MessageBox.Show("成功给本月寿星发送邮件提醒");
           }
       }
// 创建邮件项
privatebool CreateEmailItem(string subjectEmail,string toEmail,string bodyEmail)
       {
           Outlook.Application outlookapp = null;
           Outlook.MailItem email =null;
try
           {
// 创建邮件项,就如你手动点新建邮件一样
               outlookapp = new Outlook.Application();
               email = outlookapp.CreateItem(Outlook.OlItemType.olMailItem);
// 指定邮件的主题,收件人和内容,就如你在新建邮件窗体中输入收件人,主题和内容一样
               email.Subject = subjectEmail;
               email.To = toEmail;
               email.Body = bodyEmail;
               email.Importance = Outlook.OlImportance.olImportanceHigh;
// 发送邮件,就如你点界面上的发送邮件操作一样
               ((Outlook._MailItem)email).Send();
           }
catch(Exception ex)
           {
               MessageBox.Show("发送邮件的时候失败,异常信息为:" + ex.Message);
returnfalse;
           }
finally
           {
// 释放资源
               ((Outlook._Application)outlookapp).Quit();
if (email != null)
               {
                   Marshal.FinalReleaseComObject(email);
                   email = null;
               }
if (outlookapp != null)
               {
                   Marshal.FinalReleaseComObject(outlookapp);
                   outlookapp = null;
               }
           }
returntrue;
       }

为了测试程序,我新建了一个员工信息表,表格的格式如下(你当然可以根据自己的需要更改格式):
在这里插入图片描述

发布了7 篇原创文章 · 获赞 24 · 访问量 458

猜你喜欢

转载自blog.csdn.net/CVSTO/article/details/104223160