65.9K
CodeProject 正在变化。 阅读更多。
Home

使用 Visual Studio .NET 自动化 MS Excel

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.46/5 (58投票s)

2005年5月2日

6分钟阅读

viewsIcon

801649

downloadIcon

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` 对象。

  1. 创建一个 `VkExcel` 类型的对象:`VkExcel excel = new VkExcel(false);。请记住,`VkExcel(...)` 接受一个用于应用程序可见性的参数。
  2. 打开 Excel 文件:`string status = excel.OpenFile( filename, password );,传入文件名,或者如果您正在使用 `OpenFileDialog`,则传入 *完整名称*。如果文件没有密码保护,请将密码设置为 `null`。
  3. 检查文件是否已成功打开:`if( status.equal("OK")) ...
  4. 检索 Excel 工作表:`excel.GetExcelSheets();` 将在对象内部获取所有工作表。
  5. 搜索特定工作表:`excel.FindExcelWorksheet(worksheetName);` 将在给定文件中查找任何工作表。将 `worksheetName` 作为参数传递。
  6. 根据范围检索数据:`string[] A4D4 = excel.GetRange("A4:D4"); 这将以 `string[]` 的形式返回范围内的值。

就是这样!

© . All rights reserved.