




全文预览已结束
下载本文档
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
Excel、Exchange 和 C#Eric GunnersonMicrosoft Corporation 2003年4月21日 摘要:Eric Gunnerson 将向您介绍如何使用 Outlook、Excel 和 C# 创建自定义的日历,该日历可以提供适用于短期项目和长期项目的清晰明了的版式。 下载 csharp05152003_sample.exe 示例文件(英文)。虽然一月份已经过去了,我还是决定为您介绍这个迟到的新年解决方案。我决定不再谈论我的下一个专栏要说什么,因为每提到一个主题似乎就预示着我将来不会说到它。所以,这个月我将不谈论 DirectX。( 下次谈到它,就是违背诺言了。)在开始之前,先简短回顾一下上月专栏的内容。虽然我使用了 NUnit 来完成我的单元测试,但您也可以使用 csunit 或 .NETUnit 来完成您的单元测试。有关详细信息,请参阅 C# 工具页面(英文)。C# 程序管理组最近开始使用 Microsoft Outlook 的日历,来安排我们各项活动的日程,所以我们全都知道下一次讨论安排在什么时间、小组成员何时休假以及要召开的会议安排在什么时间。查看短期日程安排时,这个日历非常好用,但要查看未来几个月的日程安排时,它就不那么管用了。我查找了适用于查看长期日程安排的实用程序,但是没找到。看来,应该好好利用 MSDN 了。我写了一些用于访问电子邮件的代码,这些代码看起来相当简单,但是我需要一种方法来创建并打印日程安排网格。网格很容易画,但是要实现跨多个页面打印并不容易,所以我开始寻找可以打印矩形网格的程序,并了解如何跨页打印。看起来 Microsoft Excel 是比较理想的选择。要从 C# 访问 Outlook 和 Excel,需要使用 COM 互操作。要使用 COM 互操作,需要具备互操作程序集以从 C# 端进行引用。您可以从 C# 项目中引用适当的 COM 组件来生成程序集,也可以下载适用于所有 Microsoft Office 组件的互操作程序集。 如果需要将程序集安装到 GAC 中,则不能引用任何未签名的程序集,因此如果您的程序集需要使用 Office,就需要下载已签名的程序集(英文)。下载程序集之后,需要向已签名的程序集添加引用。我将从在 Excel 中创建工作表并设置单元格开始。使用 Excel创建项目后,我找到项目中的引用节点,浏览到 PIA 所在目录,然后添加对 Excel 的引用。 现在我已准备好使用 Excel 开始工作,但要这样做,还需要了解 Excel 对象模型。遗憾的是,很难找到正确的信息,所以我尝试了两种方法。第一种方法是使用对象浏览器,浏览互操作程序集中可用对象。要了解可以使用哪些方法和属性,这是一个不错的方法。第二个方法是在 Excel 中录制宏,让宏完成我需要的操作,然后将 VBA 代码作为要编写的 C# 代码的参考。通常这很容易完成,但是 C# 中的代码与 VBA 中的有些不同,所以我想简单介绍一下这种方法。Excel 宏我打算写一个“探测”应用程序,以了解如何完成我要在 Excel 中进行的操作。首先,启动 Excel 并使其可见,创建一个新的工作表,在其中一个单元格中放入值,然后设置单元格的背景颜色。 但在操作之前,我想简单介绍一下 Excel 对象模型。Excel 是最早提供对象模型的 Microsoft 应用程序之一,当时提供的几种选项现在仍在使用。这意味着有时用起来会不太方便。遇到这些情况时,我会指出。启动 Excel 很容易,使其可见也是如此:using Microsoft.Office.Interop.Excel;using ExcelApplication = Microsoft.Office.Interop.Excel.Application;ExcelApplication excel = new ExcelApplication();excel.Visible = true;第一个 using 语句引用 Excel 对象和方法。但在 Windows 窗体应用程序中使用这个语句时,我发现 Excel 和 Windows 窗体都有 Application 对象。我为 Excel 的 Application 定义了别名,而没有使用完全限定名称。在第二个 using 语句中,我将 ExcelApplication 作为 Excel Application 对象,然后我就可以使用它而不必使用完全限定名称。 我将需要的操作录制为 Excel 宏,如下所示: Workbooks.AddRange(C6).SelectActiveCell.FormulaR1C1 = HelloRange(C6).SelectWith Selection.Interior .ColorIndex = 6 .Pattern = xlSolidEnd With这看起来不太象 C# 代码。在 Excel 宏中,有一些特定的假设值和结果,因此我们必须进行一些转换。例如: Workbooks.Add转换为: Workbook workbook = excel.Workbooks.Add(Missing.Value);我怎么知道要这样转换呢?我首先查看 Application 对象,发现它有一个名为 Workbooks 的属性可以返回 Workbooks 对象(这并不奇怪)。所以,在 VBA 代码中有一个假设的“excel.”。我键入 Workbooks.Add( 时,IntelliSense 提示我 Add 方法接受一个名为 template 的参数。 但在 VBA 代码中并没有参数,显然,这是一个可选参数。我们使用的包装类仅定义了函数的一个版本,因此我们必须传递一个表示“使用默认值”的值,该值就是 System.Reflection 命名空间中的 Missing.Value。下一步,在单元格 C6 中设置值。由于 VBA 代码中的 Workbooks 表示 C# 代码中的 excel.Workbooks,因此我们可以尝试使用 excel.Range 来获取区域。遗憾的是,我们的尝试失败了。实际上,在 Excel VBA 中编程时,根据您编写的内容,会有多个假设的前缀。如果您使用 Range,那么实际上就是在使用 excel.ActiveSheet.Range。因此,我们编写以下代码:excel.ActiveSheet.Range(C4).Select();至少我们可以尝试这样写,但是会发现这样不能编译。原来,excel.ActiveSheet 是某种类型的对象。我不能确定这是为什么,只能推测,它可能是工作表或其他对象,也可能只是最初设定的类型的对象。所以,我们尝试:(Worksheet) excel.ActiveSheet).Range(C4).Select();这样会好一些,但在 Worksheet 类中没有 Range 函数。Range 在 VBA 领域里是一个属性,但是在 C# 中,它只是一个接受两个参数的方法。所以,我们得到以下代码:(Worksheet) excel.ActiveSheet).get_Range(C4, Missing.Value).Select();excel.ActiveCell.Value2 = Hello;为什么是 Value2 而不是 FormulaR1C1?这也是我尚未查明的问题。有两种方法可以使代码更简洁一些。第一种方法是将 Worksheet 对象存储在变量中,这样就可以避免类型转换;第二种方法是对 Range 对象执行操作,而不是选择它并使用活动的单元格。最后一步是保存工作表,可以通过调用 Worksheet.SaveAs() 来完成。此方法接受十个参数,因此可以将其余参数作为 Missing.Value 传递。以下是最终的代码: ExcelApplication excel = new ExcelApplication();excel.Visible = true;excel.Workbooks.Add(Missing.Value);Worksheet worksheet = (Worksheet) excel.ActiveSheet;Range r = worksheet.get_Range(C6, Missing.Value);r.Value2 = Hello;r.Interior.ColorIndex = 6;worksheet.SaveAs(c:ExcelExample.xls, Missing.Value, Missing.Value, Missing.Value, Missing.Value, Missing.Value, Missing.Value, Missing.Value, Missing.Value, Missing.Value); excel.Quit();创建一个工作表,设置一些值,然后保存并退出,共九行代码。真是好极了。这些代码保存在 ExcelExample 项目中。使用电子邮件要访问 Exchange 电子邮件,可以使用 Outlook 对象模型,也可以使用 CDO(协作数据对象,以前称为 MAPI)模型。因为我不关心图形的显示,所以我要使用 CDO。CDO 不是 Office 的一部分,所以没有 PIA。我创建一个新项目,并添加对 COM 对象 Microsoft CDO 1.21 Library 的引用。然后编写以下代码,以获取收件箱中邮件的数量: using MAPI; using System.Reflection; Session session = new Session(); session.Logon(Default Outlook Profile, Missing.Value, Missing.Value, Missing.Value, Missing.Value, Missing.Value, Missing.Value ); Folder folder = (Folder) session.Inbox; Messages messages = (Messages) folder.Messages; int messageCount = (int) messages.Count;与 Excel 一样,MAPI/CDO 对象模型出现的很早,其中的每项内容都被定义为对象,甚至象文件夹中邮件数量都是如此。通常,我会编写 MAPI 对象的包装对象,这样就可以不进行类型转换就直接使用它们。我为文件夹和 Messages 集合编写了两个包装程序,您可以使用 foreach 对它们进行遍历。上述准备工作完成后,我可以编写以下代码来查看收件箱中的所有邮件: MapiFolder inbox = new MapiFolder(session.Inbox); int size = 0; int count = 0; foreach (MAPI.Message message in inbox.Messages) size += (int) message.Size; count+; 当我运行这段代码时,发现我的 Exchange 收件箱中有 2982 封邮件,占用的空间超过了 33 MB。 如果我要查看所有文件夹,我可以编写一个递归函数: public int TraverseFolder(MapiFolder folder) int size = 0; foreach (MapiFolder subFolder in folder) size += TraverseFolder(subFolder); foreach (MAPI.Message message in folder.Messages) size += (int) message.Size; return size; 如果我运行这段代码,大约一分多钟以后,它就会告诉我,我的整个收件箱树占用了大约 88 MB 空间。我想我需要做些清理工作。处理约会起初,MAPI 只是处理邮件。添加了其他类型的项后,它出现了一个问题。如果我的代码用于取回 Message 项,而意外地取回了 Appointment 项,代码将会中断。所以,如果我打开一个邮箱并找到 Calendar 子文件夹,我将取回由邮件而不是由约会组成的文件夹。如果我要查找一个约会的主题,这样很有效,但是如果我要获取开始日期和结束日期,就比较困难了。为解决这个问题,MAPI 添加了一个名为 GetDefaultFolder() 的新函数,我可以通过调用它来指定我真正需要的 AppointmentItems 集合,而不是 Messages 集合。因此,我可以编写以下代码: public void TraverseCalendar(Session session) Folder calendar = (Folder) session.GetDefaultFolder(ActMsgDefaultFolderTypes.ActMsgDefaultFolderCalendar); Messages messages = (Messages) calendar.Messages; AppointmentItem message = (AppointmentItem) messages.GetFirst(Missing.Value); while (message != null) string subject = (string) message.Subject; message = (AppointmentItem) messages.GetNext(); 我没有编写 Appointments 集合的包装程序,这就是我编写的没有包装程序的代码。 这段代码运行良好,但还有一个缺点。我只能获取我的邮箱的默认文件夹,而不能获取其他人的邮箱的文件夹。您可能还记得,我的目标是查看其他人邮箱中的约会,而这个方法没有解决问题。所以,我又回到 Google 进行更多的研究。结果是,除了邮件中特定的项外,还有一个包含此类型所有字段的 Fields 项,这些字段按编号存储。因此,如果我知道正确的编号,我就可以获取特定字段的值。下面是我最后编写的代码: InfoStore infoStore = FindInfoStore(session, mailbox); MapiFolder rootFolder = new MapiFolder(Folder) infoStore.RootFolder); MapiFolder calendar = rootFolder.FindSubFolder(Calendar); DateTime graphEndDate = graphStartDate + new TimeSpan(days, 0, 0, 0); foreach (MAPI.Message message in calendar.Messages) DateTime startDate = (DateTime) GetFieldValue(message, 6291520); DateTime endDate = (DateTime) GetFieldValue(message, 6357056); if (endDate graphEndDate) continue; if (startDate graphEndDate) endDate = graphEndDate; int labelIndex = 0; try labelIndex = (int) GetFieldValue(message, -2093678589); catch (Exception e) string s = e.Message; Appointment appointment = new Appointment(string) message.Subjec
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 玉米原材料采购合同范本
- 村委建设补偿协议书范本
- 禁止学生喝酒安全协议书
- 浦东同城厂房出租协议书
- 材料商玻璃采购合同范本
- 自建房套间出售合同范本
- 防晒服定制采购合同范本
- 注册人员聘用协议书范本
- 空压机节能方案合同范本
- 股东协议书与代持协议书
- 猪场生猪销售管理制度
- 初中教师坐班管理制度
- 2025贵州省水利投资(集团)有限责任公司招聘84人笔试备考题库附答案详解(综合题)
- 页岩气储层表征评价技术进展及其未来发展趋势分析
- 统编版高中政治必修三《政治与法治》期末复习:选择题刷题练习题(含答案解析)
- 四人合伙养猪合同协议
- 保险公司考核工作方案
- 2024年辽阳职业技术学院单招职业倾向性测试题库附答案
- 配电网建设知识培训课件
- 护理实习生安全教育
- 医德医风警示教育
评论
0/150
提交评论