使用 Visual Studio .NET 自动化 MS Excel






4.46/5 (58投票s)
2005年5月2日
6分钟阅读

801649

5363
这段代码将演示如何自动化 MS Excel 文档并从中获取内容。
引言
我撰写本文是为了回应我通过电子邮件收到的关于如何自动化 MS Excel 的请求。大多数对此文章感兴趣的人可能也对以下自动化 MS Word 文档的文章感兴趣。这是指向“使用 C# 自动化 MS Word”的链接:使用 C# 自动化 MS Word,这是指向“使用 C++ 自动化 MS Word”的链接:使用 C++ 自动化 MS Word。
回到正题,商业世界中有大量的电子表格,而且越来越多地被创建,有时甚至以 Excel 最初未设计的方式使用,例如存储实验室等敏感和关键数据……
首先,本文不会深入探讨 Excel 中提供的非常高级的自动化功能,但它将提供一个框架,希望其他人可以以此为基础进行改进并使其更具可扩展性。该框架允许您创建一个 Excel 对象并控制一些基本功能,例如获取工作表信息以及根据给定范围从工作表中提取数据。
我开发的程序范围更广,我将只专注于 Excel 部分。但我开发了一些用于使用线程进行文件系统导航的精妙类。如果对此类文章的需求足够多,或者我能有机会撰写,我会继续发布。在此期间,我希望以下文章能对您有所帮助。
背景
具备足够的面向对象编程 (OOP) 理解和熟悉 C# 语言。
使用代码
我将提供可用于您的项目中的 Excel 包装器类。代码将在下方讨论。我不会深入过多地讨论 Excel 对象模型,首先因为它是一项艰巨的任务,其次因为 Microsoft 已经有相关的文档。在我们开始之前,这里为需要了解如何设置 Office 自动化项目的初学者提供一个快速入门。
创建一个新项目,为简单起见,创建一个 Windows 应用程序,然后右键单击 **解决方案资源管理器** 中的“引用”,然后选择 **添加引用…**。当“添加引用”窗口出现时,选择 **COM** 选项卡。这将列出您计算机上可用的所有组件名称。由于我们将使用 MS Excel,您需要向下滚动直到找到:**Microsoft Excel 11.0 对象库**。
注意:您的版本可能因您计算机上安装的 Office 版本而异。这是针对 **MS Excel 2003** 的。
using System;
using System.IO;
using System.Collections;
using System.Threading;
using Office = Microsoft.Office.Core;
using Excel = Microsoft.Office.Interop.Excel;
using System.Diagnostics;
namespace ATPMain
{
/// <summary>
/// Project: Code Project Demo
/// Author: Vahe Karamian
/// Date: 03/01/2005
/// Version: 1.0
/// </summary>
public class VkExcel
{
private Excel.Application excelApp = null;
private Excel.Workbook excelWorkbook = null;
private Excel.Sheets excelSheets = null;
private Excel.Worksheet excelWorksheet = null;
...
using Office = Microsoft.Office.Core;
using Excel = Microsoft.Office.Interop.Excel;
您需要包含这两个,以便在代码中使用 `Excel` 对象。因此,我们需要一个 `Excel.Application` 对象、`Excel.Workbook` 对象、`Excel.Sheets` 对象和 `Excel.Worksheet` 对象。这些对象将用于控制 Excel 并从中提取数据。因此,我们声明以下变量来表示这些对象:`excelApp`、`excelWorkbook`、`excelSheets` 和 `excelWorksheet`。
....
private static object vk_missing = System.Reflection.Missing.Value;
private static object vk_visible = true;
private static object vk_false = false;
private static object vk_true = true;
private bool vk_app_visible = false;
private object vk_filename;
#region OPEN WORKBOOK VARIABLES
private object vk_update_links = 0;
private object vk_read_only = vk_true;
private object vk_format = 1;
private object vk_password = vk_missing;
private object vk_write_res_password = vk_missing;
private object vk_ignore_read_only_recommend = vk_true;
private object vk_origin = vk_missing;
private object vk_delimiter = vk_missing;
private object vk_editable = vk_false;
private object vk_notify = vk_false;
private object vk_converter = vk_missing;
private object vk_add_to_mru = vk_false;
private object vk_local = vk_false;
private object vk_corrupt_load = vk_false;
#endregion
#region CLOSE WORKBOOK VARIABLES
private object vk_save_changes = vk_false;
private object vk_route_workbook = vk_false;
#endregion
/// <summary>
/// Vahe Karamian - 03/04/2005 - Excel Object Constructor.
/// </summary>
public VkExcel()
{
this.startExcel();
}
/// <summary>
/// Vahe Karamian - 03/04/2005 - Excel Object Constructor
/// visible is a parameter, either TRUE or FALSE, of type object.
/// </summary>
/// Visible parameter, true for visible, false for non-visible
public VkExcel(bool visible)
{
this.vk_app_visible = visible;
this.startExcel();
}
...
在上面的代码块中,我们预定义了一些常量,这些常量将用于打开给定的 Excel 文件。要了解每个参数的含义或作用,您应该查阅 Excel 附带的文档。
我们有两个构造函数:`VkExcel()`,它默认会隐藏启动 Excel;另一个是 `VkExcel(bool visible)
`,它允许您指定是否希望看到 Excel 应用程序。
... /// <summary> /// Vahe Karamian - 03/04/2005 - Start Excel Application /// </summary> #region START EXCEL private void startExcel() { if( this.excelApp == null ) { this.excelApp = new Excel.ApplicationClass(); } // Make Excel Visible this.excelApp.Visible = this.vk_app_visible; } #endregion /// <summary> /// Vahe Karamian - 03/23/2005 - Kill the current Excel Process /// </summary> #region STOP EXCEL public void stopExcel() { if( this.excelApp != null ) { Process[] pProcess; pProcess = System.Diagnostics.Process.GetProcessesByName("Excel"); pProcess[0].Kill(); } } #endregion ...
上面的代码启动和停止 Excel 应用程序。`startExcel()` 检查 `excelApp` 对象是否已初始化。如果已初始化,它会确保其可见性设置为 `visible` 属性。如果未初始化,它会继续为我们初始化该对象。`stopExcel()` 还会检查该对象当前是否正在使用,如果是,它将继续终止该进程。
注意:`pProcess[0].Kill()` 将确保 Excel 被彻底关闭!一些进行 Excel 自动化的人总是抱怨,在他们退出应用程序后,Excel 消失了,但 Excel 进程仍在任务管理器中,此代码将为您解决这个问题!
...
/// <summary>
/// Vahe Karamian - 03/09/2005 - Open File function for Excel 2003
/// The following function will take in a filename, and a password
/// associated, if needed, to open the file.
/// </summary>
#region OPEN FILE FOR EXCEL
public string OpenFile(string fileName, string password)
{
vk_filename = fileName;
if( password.Length > 0 )
{
vk_password = password;
}
try
{
// Open a workbook in Excel
this.excelWorkbook = this.excelApp.Workbooks.Open(
fileName, vk_update_links, vk_read_only,
vk_format, vk_password,
vk_write_res_password,
vk_ignore_read_only_recommend, vk_origin,
vk_delimiter, vk_editable, vk_notify,
vk_converter, vk_add_to_mru,
vk_local, vk_corrupt_load);
}
catch(Exception e)
{
this.CloseFile();
return e.Message;
}
return "OK";
}
#endregion
public void CloseFile()
{
excelWorkbook.Close( vk_save_changes,
vk_filename, vk_route_workbook );
}
...
好了,上面的代码允许您打开 Excel 文件。`OpenFile(string fileName, string password)
` 接受两个参数:文件名,或者(如果使用 `OpenFileDialog`)是 *完整名称*(即 *路径 + 文件名*),以及一个密码参数,用于受保护的工作表。请注意,open 函数接受许多参数,这些参数已在类中定义。`CloseFile()` 将继续关闭文件。
注意:提供的代码适用于 MS Excel 2003。对于早期版本,参数略有不同,您需要查阅文档。如果您需要这方面的帮助,请给我发电子邮件,我会尽力帮助您。
...
/// <summary>
/// Vahe Karamian - 03/20/2005 - Get Excel Sheets
/// Get the collection of sheets in the workbook
/// </summary>
#region GET EXCEL SHEETS
public void GetExcelSheets()
{
if( this.excelWorkbook != null )
{
excelSheets = excelWorkbook.Worksheets;
}
}
#endregion
/// <summary>
/// Vahe Karamian - 03/21/2005 - Find Excel ATP Worksheet
/// Search for ATP worksheet, if found return TRUE
/// </summary>
/// <returns>bool</returns>
#region FIND EXCEL ATP WORKSHEET
public bool FindExcelATPWorksheet(string worksheetName)
{
bool ATP_SHEET_FOUND = false;
if( this.excelSheets != null )
{
// Step thru the worksheet collection and see if ATP sheet is
// available. If found return true;
for( int i=1; i<=this.excelSheets.Count; i++ )
{
this.excelWorksheet =
(Excel.Worksheet)excelSheets.get_Item((object)i);
if( this.excelWorksheet.Name.Equals(worksheetName) )
{
this.excelWorksheet.Activate();
ATP_SHEET_FOUND = true;
return ATP_SHEET_FOUND;
}
}
}
return ATP_SHEET_FOUND;
}
#endregion
...
上面的代码演示了如何获取工作簿中的所有工作表,以及如何获取特定工作表来提取数据。`GetExcelSheets()` 获取所有工作表。`FindExcelATPWorkSheet(string worksheetName)
` 搜索名称为 `worksheetName` 的工作表。
... /// <summary> /// Vahe Karamian - 03/22/2005 - Get Range from Worksheet /// Return content of range from the selected range /// </summary> /// Range parameter: Example, GetRange("A1:D10") #region GET RANGE public string[] GetRange(string range) { Excel.Range workingRangeCells = excelWorksheet.get_Range(range,Type.Missing); //workingRangeCells.Select(); System.Array array = (System.Array)workingRangeCells.Cells.Value2; string[] arrayS = this.ConvertToStringArray(array); return arrayS; } #endregion ...
`GetRange(string range)` 是实际从 Excel 工作表中检索数据的函数,我们将返回的值转换为 `string[]
`。这是通过下一个函数调用完成的:`this.ConvertToStringArray(array)
`。然后将 `string[]
` 传递回调用者,调用者可以以任何他们想要的方式使用它。
...
/// <summary>
/// Vahe Karamian - 03/22/2005 - Convert To String Array
/// Convert System.Array into string[]
/// </summary>
/// Values from range object
/// <returns>String[]</returns>
#region CONVERT TO STRING ARRAY
private string[] ConvertToStringArray(System.Array values)
{
string[] newArray = new string[values.Length];
int index = 0;
for ( int i = values.GetLowerBound(0);
i <= values.GetUpperBound(0); i++ )
{
for ( int j = values.GetLowerBound(1);
j <= values.GetUpperBound(1); j++ )
{
if(values.GetValue(i,j)==null)
{
newArray[index]="";
}
else
{
newArray[index]=(string)values.GetValue(i,j).ToString();
}
index++;
}
}
return newArray;
}
#endregion
}
最后一部分代码:`ConvertToStringArray(System.Array values)` 将获取 `GetRange(...)` 传递过来的数组,将其放入一个字符串数组并返回。
我们已经到达了对象的末尾。正如您所见,这是一个非常简单的对象,功能非常有限,但对于任何需要快速入门的人来说,它都是一个很好的起点,而且您可以非常轻松地将其扩展为一个更复杂的对象。
我没有包含演示项目。原因是使用该对象极其简单。您只需按照以下步骤初始化和使用 `VkExcel` 对象。
- 创建一个 `VkExcel` 类型的对象:`
VkExcel excel = new VkExcel(false);
。请记住,`VkExcel(...)` 接受一个用于应用程序可见性的参数。 - 打开 Excel 文件:`
string status = excel.OpenFile( filename, password );
,传入文件名,或者如果您正在使用 `OpenFileDialog`,则传入 *完整名称*。如果文件没有密码保护,请将密码设置为 `null
`。 - 检查文件是否已成功打开:`
if( status.equal("OK"))
... - 检索 Excel 工作表:`excel.GetExcelSheets();` 将在对象内部获取所有工作表。
- 搜索特定工作表:`excel.FindExcelWorksheet(worksheetName);` 将在给定文件中查找任何工作表。将 `worksheetName` 作为参数传递。
- 根据范围检索数据:`
string[] A4D4 = excel.GetRange("A4:D4");
这将以 `string[]
` 的形式返回范围内的值。
就是这样!