[C# 开发技巧系列]使用C#操作Word和Excel程序

简介:

一、引言

  在我们日常办公中,我们经常可能遇到一些重复性的工作的,比如,我们在写毕业设计的时候,有时候我们写的过程中不注意,当整篇毕业论文写完之后,发现在毕业论文中存在很多空白的段落,这是我们就需要人工重新审阅一遍论文,再手动删除一些空白行,由于毕业论文也不是一篇,有开题报告啊,文献翻译等等,这样就可能需要我们人工都去审阅一篇把一些空白行删除,这样既花时间,我们也看的累。然后还有一个例子就是——我们人事部门的MM们,一到月末的时候就需要给本月的寿星员工发送邮件来通知参加生日会,如果员工信息是在Excel中的话,这时候人事的MM就要手动地从中查找本月寿星的邮箱,然后用Outlook一个一个添加邮件地址来给本月寿星发送邮件的,为了让人事MM们不再那么累,所以就想能不能用程序自动化地完成这一系列的过程呢?答案是肯定的,下面就让我来实现上面的两个需求的,使我们(尤其是人事MM们)的办公更加Easy。


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

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

首先,我们先明确下这个工具需要实现的功能——自动移除Word文档中的空白行。然后向大家解释下实现该工具的思路:

  • 我们打开一个Word文档,该Word文档就是一个Word.Document对象

  • Word文档中内容都是段落组成的,然而段落在Word对象模型中是Word.Paragraph对象

  • 空白行或空白页也就是段落的内容为空,明白了这点,我们就可以在程序中对段落对象的文本进行判断,如果段落内容为空,我们就删除该段落,这样也就实现了移除空白行的功能了。

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


 
 
  1. string[] wordPatharray = null;

  2. // 打开需要操作的Word文档

  3. privatevoid btnOpen_Click(object sender, EventArgs e)

  4.        {

  5. using (OpenFileDialog openFileDialog = new OpenFileDialog())

  6.            {

  7.                openFileDialog.Filter = "Word document(*.doc;*.docx)|*.dox;**.docx|All Files(*.*)|*.*";

  8. // 设置允许选择多个文件,该属性默认为false的,即只允许选择一个文件

  9.                openFileDialog.Multiselect = true;

  10. if (openFileDialog.ShowDialog() == DialogResult.OK)

  11.                {

  12.                    txtWordPath.Text = openFileDialog.FileName;

  13. // 获得所有选定文件的文件名

  14.                    wordPatharray = openFileDialog.FileNames;

  15.                }

  16.            }

  17.        }

  18. // 移除Word中的所有空页

  19. privatevoid btnRemove_Click(object sender, EventArgs e)

  20.        {

  21.            Word.Application wordapp = null;

  22.            Word.Document doc = null;

  23. try

  24.            {

  25. // 启动Word应用程序并设置不可见

  26.                wordapp = new Word.Application();

  27. // 如果不设置该属性,就可以看到Word程序的启动过程,这个和我们手动启动Word是一样的

  28.                wordapp.Visible = false;

  29. // 遍历每个文件名

  30. foreach (var wordpath in wordPatharray)

  31.                {

  32.                    doc = wordapp.Documents.Open(wordpath);

  33. // 删除所有空白页面

  34.                    Word.Paragraph paragraph;

  35.                    Word.Paragraphs paragraphs = doc.Paragraphs;

  36. for (int i = paragraphs.Count; i > 0; i--)

  37.                    {

  38.                        paragraph = paragraphs[i];

  39. //  如果段落的文本为空的话,首先选择该段落,然后再调用Word中Selection对象的Delete方法来删除

  40. // 不为空什么都不做

  41. if (paragraph.Range.Text.Trim() == string.Empty)

  42.                        {

  43.                            paragraph.Range.Select();

  44.                            wordapp.Selection.Delete();

  45.                        }

  46.                    }

  47. if (doc != null)

  48.                    {

  49. // 先保存所有修改再关闭Word文档

  50.                        doc.Save();

  51.                        ((Word._Document)doc).Close();

  52.                    }

  53.                }

  54.                MessageBox.Show("删除空白行成功");

  55.            }

  56. catch (Exception ex)

  57.            {

  58.                MessageBox.Show("异常发生,异常信息为:" + ex.Message);

  59.            }

  60. finally

  61.            {

  62. // 释放资源

  63. // 退出Word程序

  64. if (wordapp != null)

  65.                {

  66.                    ((Word._Application)wordapp).Quit();

  67.                }

  68.                doc = null;

  69.                wordapp = null;

  70.            }

  71.        }


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

下面就看看该工具的运行效果(效果图是一段动画,认为这样可以更加说明运行效果)


三、人事部门的福音——自动给本月寿星员工发送邮件提醒

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

  • 我们首先需要打开员工信息表,此时我们可以利用Excel对象模型中的Excel.Application.Workbooks.Open方法来获得一个工作簿对象,关于更多Excel对象模型的内容可以转向——创建Excel解决方案

  • 通过第一步我们已经获得了工作簿对象了,然后通过遍历工作簿中的激活表,即表格一(Sheet1),我们可以通过workbook.ActiveSheet来获得表格一对象。

  • 遍历表格一中的所有行来找到生日信息中的月份,如果月份等于当前月份,就给该员工的邮箱进行发邮件。

  • 对于自动发送邮件的实现,该实现和我们手动操作Outlook过程是一样,手动操作时,我们需要手动打开Outlook(在程序中就是创建Outlook应用程序对象),然后点击新建邮件(在程序中就是通过Applicatin对象的CreateItem(Outlook.OlItemType.olMailItem)方法来创建一个邮件项目),在新建邮件窗口中指定收件人,主题,邮件内容之后,点击Outlook中的发送邮件按钮(在程序中就是通过指定 Outlook.MailItem对象(即代表一个邮件窗体)的To(收件人)、Subject(主题)、Body(邮件内容)属性,然后再调用Send方法来发送邮件)

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


 
 
  1. using System;

  2. using System.IO;

  3. using System.Runtime.InteropServices;

  4. using System.Windows.Forms;

  5. // 引用Excel和Outlook的命名空间

  6. using Excel = Microsoft.Office.Interop.Excel;

  7. using Outlook = Microsoft.Office.Interop.Outlook;

  8. string excelpath = string.Empty;

  9. // 打开员工表格

  10. privatevoid btnOpen_Click(object sender, EventArgs e)

  11.        {

  12. using (OpenFileDialog openFileDialog = new OpenFileDialog())

  13.            {

  14.                openFileDialog.Filter = "Excel File(*.xls;*.xlsx)|*.xls;**.xlsx|All Files(*.*)|*.*";

  15. if (openFileDialog.ShowDialog() == DialogResult.OK)

  16.                {

  17.                    txtExcelPath.Text = openFileDialog.FileName;

  18.                    excelpath = openFileDialog.FileName;

  19.                }

  20.            }

  21.        }

  22. // 自动给本月寿星发邮件通知

  23. privatevoid btnSendEmail_Click(object sender, EventArgs e)

  24.        {

  25. if (!File.Exists(txtExcelPath.Text))

  26.            {

  27.                MessageBox.Show("员工表路径不存在,请确保输入正确的文件路径");

  28. return;

  29.            }

  30. if (txbBirthday.Text.Trim() == string.Empty || txbEmail.Text.Trim() == string.Empty)

  31.            {

  32.                MessageBox.Show("请先输入员工表中生日信息所在的列和邮箱信息所在的列!");

  33. return;

  34.            }

  35. // 输入信息都正确时开始发送邮件

  36.            SendEmail(int.Parse(txbBirthday.Text.Trim()), int.Parse(txbEmail.Text.Trim()));

  37.        }

  38. // 发送邮件方法

  39. privatevoid SendEmail(int birthDayColumn,int emailColumn)

  40.        {

  41. // 获得当前月份

  42. int nowmonth = DateTime.Now.Month;

  43. // 发送邮件地址字符串

  44. string toEmailString = string.Empty;

  45. string emailBody="请收到邮件的员工,请本月28号到休闲室来参加生日Party";

  46.            Excel.Application excelApp = null;

  47.            Excel.Workbook workbook =null;

  48.            Excel.Worksheet worksheet = null;

  49.            Excel.Range range = null;

  50. try

  51.            {

  52. // 新建Excel应用程序被设置它不可见

  53.                excelApp = new Excel.Application();

  54.                excelApp.Visible = false;

  55.                workbook = excelApp.Workbooks.Open(excelpath);

  56. // 获得打开文件的激活表格

  57.               worksheet= workbook.ActiveSheet;

  58. // 遍历表格中的所有行

  59. for (int row = 2; row < worksheet.UsedRange.Rows.Count + 1; row++)

  60.                {

  61. // 因为我的测试表格中第四列是生日信息,在Excel中第一行的下标是从1开始的

  62. // 这里本来需要在页面设置一个文本框让用户填写生日信息是在那一列的

  63. // 这里为了测试就直接在程序中指定

  64. // 下面的Range就代表生日列中每一个单元格

  65.                    range = worksheet.Cells[row, birthDayColumn];

  66. // 我们可以通过Range.Value来获得单元格中的生日信息

  67. // 因为我生日单元格中为日期格式,所以获得的是日期类型,所以直接通过Month属性来获得月份

  68. int month = range.Value.Month;

  69. // 如果我们的Excel文档中生日时间设置为文本格式的话,这时候就需要通过分割字符串的方式来获得月份

  70. // 通过Split函数来把生日信息以'/'符号分隔,分隔的数组的第二个就是月份

  71. //int month = Int32.Parse(birthday.Split('/')[1]);

  72. // 如果月份等于当前月的话,就给这个人发邮件

  73. if (month == nowmonth)

  74.                    {

  75. // 获得本月生日员工的邮件地址

  76.                        toEmailString += ";" + ((Excel.Range)worksheet.Cells[row, emailColumn]).Value;

  77.                    }

  78.                }

  79.            }

  80. catch (Exception ex)

  81.            {

  82.                MessageBox.Show("读取员工表格时出错,异常信息为:" + ex.Message);

  83. return;

  84.            }

  85. finally

  86.            {

  87.                workbook.Close(Excel.XlSaveAction.xlDoNotSaveChanges);

  88.                excelApp.Quit();

  89. if (workbook != null)

  90.                {

  91.                    Marshal.FinalReleaseComObject(workbook);

  92.                    workbook = null;

  93.                }

  94. if (excelApp != null)

  95.                {

  96.                    Marshal.FinalReleaseComObject(excelApp);

  97.                    excelApp = null;

  98.                }

  99.            }

  100. if (CreateEmailItem("生日提醒", toEmailString, emailBody))

  101.            {

  102.                MessageBox.Show("成功给本月寿星发送邮件提醒");

  103.            }

  104.        }

  105. // 创建邮件项

  106. privatebool CreateEmailItem(string subjectEmail,string toEmail,string bodyEmail)

  107.        {

  108.            Outlook.Application outlookapp = null;

  109.            Outlook.MailItem email =null;

  110. try

  111.            {

  112. // 创建邮件项,就如你手动点新建邮件一样

  113.                outlookapp = new Outlook.Application();

  114.                email = outlookapp.CreateItem(Outlook.OlItemType.olMailItem);

  115. // 指定邮件的主题,收件人和内容,就如你在新建邮件窗体中输入收件人,主题和内容一样

  116.                email.Subject = subjectEmail;

  117.                email.To = toEmail;

  118.                email.Body = bodyEmail;

  119.                email.Importance = Outlook.OlImportance.olImportanceHigh;

  120. // 发送邮件,就如你点界面上的发送邮件操作一样

  121.                ((Outlook._MailItem)email).Send();

  122.            }

  123. catch(Exception ex)

  124.            {

  125.                MessageBox.Show("发送邮件的时候失败,异常信息为:" + ex.Message);

  126. returnfalse;

  127.            }

  128. finally

  129.            {

  130. // 释放资源

  131.                ((Outlook._Application)outlookapp).Quit();

  132. if (email != null)

  133.                {

  134.                    Marshal.FinalReleaseComObject(email);

  135.                    email = null;

  136.                }

  137. if (outlookapp != null)

  138.                {

  139.                    Marshal.FinalReleaseComObject(outlookapp);

  140.                    outlookapp = null;

  141.                }

  142.            }

  143. returntrue;

  144.        }



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

现在就让我们看看该程序的运行效果:


四、 小结

  到这里,本专题的内容就和大家介绍完了,在下一个专题中将向大家介绍下如何通过Office提供的API的来遥控幻灯片。如果大家对本专题中两个工具的实现源码有任何的疑问,都可以在下面留言给我。觉得不错的话,帮忙赞下,感谢大家的支持。






     本文转自LearningHard 51CTO博客,原文链接:http://blog.51cto.com/learninghard/1156852,如需转载请自行联系原作者



相关文章
|
1月前
|
Java API Apache
Java编程如何读取Word文档里的Excel表格,并在保存文本内容时保留表格的样式?
【10月更文挑战第29天】Java编程如何读取Word文档里的Excel表格,并在保存文本内容时保留表格的样式?
117 5
|
2月前
|
缓存 C# Windows
C#程序如何编译成Native代码
【10月更文挑战第15天】在C#中,可以通过.NET Native和第三方工具(如Ngen.exe)将程序编译成Native代码,以提升性能和启动速度。.NET Native适用于UWP应用,而Ngen.exe则通过预编译托管程序集为本地机器代码来加速启动。不过,这些方法也可能增加编译时间和部署复杂度。
136 2
|
1月前
|
XML C# 开发工具
C# 删除Word文档中的段落
【11月更文挑战第3天】本文介绍了两种方法来操作 Word 文档:一是使用 `Microsoft.Office.Interop.Word` 库,适用于 Windows 环境下操作 Word 文档,需引用相应库并在代码中引入命名空间;二是使用 Open XML SDK,适用于处理 .docx 格式的文档,通过引用 `DocumentFormat.OpenXml` 库实现。文中提供了示例代码,展示了如何打开、删除段落并保存文档。
|
2月前
|
设计模式 程序员 C#
C# 使用 WinForm MDI 模式管理多个子窗体程序的详细步骤
WinForm MDI 模式就像是有超能力一般,让多个子窗体井然有序地排列在一个主窗体之下,既美观又实用。不过,也要小心管理好子窗体们的生命周期哦,否则一不小心就会出现一些意想不到的小bug
167 0
|
2月前
|
XML 存储 安全
C#开发的程序如何良好的防止反编译被破解?ConfuserEx .NET混淆工具使用介绍
C#开发的程序如何良好的防止反编译被破解?ConfuserEx .NET混淆工具使用介绍
77 0
|
2月前
|
安全 API C#
C# 如何让程序后台进程不被Windows任务管理器强制结束
C# 如何让程序后台进程不被Windows任务管理器强制结束
66 0
|
3月前
|
C# 容器
C#中的命名空间与程序集管理
在C#编程中,`命名空间`和`程序集`是组织代码的关键概念,有助于提高代码的可维护性和复用性。本文从基础入手,详细解释了命名空间的逻辑组织方式及其基本语法,展示了如何使用`using`指令访问其他命名空间中的类型,并提供了常见问题的解决方案。接着介绍了程序集这一.NET框架的基本单位,包括其创建、引用及高级特性如强名称和延迟加载等。通过具体示例,展示了如何创建和使用自定义程序集,并提出了针对版本不匹配和性能问题的有效策略。理解并善用这些概念,能显著提升开发效率和代码质量。
119 4
|
2月前
|
API C#
C#实现Winform程序右下角弹窗消息提示
C#实现Winform程序右下角弹窗消息提示
108 0
|
8天前
|
数据采集 数据可视化 数据挖掘
利用Python自动化处理Excel数据:从基础到进阶####
本文旨在为读者提供一个全面的指南,通过Python编程语言实现Excel数据的自动化处理。无论你是初学者还是有经验的开发者,本文都将帮助你掌握Pandas和openpyxl这两个强大的库,从而提升数据处理的效率和准确性。我们将从环境设置开始,逐步深入到数据读取、清洗、分析和可视化等各个环节,最终实现一个实际的自动化项目案例。 ####
|
2月前
|
数据采集 存储 JavaScript
自动化数据处理:使用Selenium与Excel打造的数据爬取管道
本文介绍了一种使用Selenium和Excel结合代理IP技术从WIPO品牌数据库(branddb.wipo.int)自动化爬取专利信息的方法。通过Selenium模拟用户操作,处理JavaScript动态加载页面,利用代理IP避免IP封禁,确保数据爬取稳定性和隐私性。爬取的数据将存储在Excel中,便于后续分析。此外,文章还详细介绍了Selenium的基本设置、代理IP配置及使用技巧,并探讨了未来可能采用的更多防反爬策略,以提升爬虫效率和稳定性。
111 4