【问题标题】:Search entire workbook and fetch out values搜索整个工作簿并获取值
【发布时间】:2013-08-19 18:02:36
【问题描述】:

在我的 Excel 工作簿中

第一个工作表标签包含

Number Name Code    Subject
100    Mark ABC Mathematics
101    John XYZ Physics

The second sheet tab contains

Number Name Code    Subject
103    Mark DEF Chemistry
104    John GHI Biology

我想将代码(将是唯一的)作为参数传递并搜索整个 excel 工作簿

并获取名称和主题..

ie..select name,subject from myexcelworkbook where code='ABC'

我能够获取工作表名称、列数等,但无法搜索整个 Excel 工作簿并获取所需的值

        const string fileName="C:\\FileName.xls";

        OleDbConnectionStringBuilder connectionStringBuilder = new OleDbConnectionStringBuilder();
        connectionStringBuilder.Provider = "Microsoft.ACE.OLEDB.12.0";
        connectionStringBuilder.DataSource = fileName;
        connectionStringBuilder.Add("Mode", "Read");

        const string extendedProperties = "Excel 12.0;IMEX=1;HDR=YES";
        connectionStringBuilder.Add("Extended Properties", extendedProperties);
        using (OleDbConnection objConn = new OleDbConnection(connectionStringBuilder.ConnectionString))
       {
            objConn.Open();

            Microsoft.Office.Interop.Excel.Application xlsApp = new Microsoft.Office.Interop.Excel.Application();
            Workbook wb = xlsApp.Workbooks.Open(fileName, 0, true, 5, "", "", true, XlPlatform.xlWindows, "\t", false, false, 0, true);

            Sheets sheets = wb.Worksheets;

            for (int i =1 ; i <= wb.Worksheets.Count; i++)
            {

                MessageBox.Show(wb.Sheets[i].Name.ToString()); - gives sheet names inside the workbook
            }

          Worksheet ws = (Worksheet)sheets.get_Item(1); - gives the elements of specified sheet tab
      }

  //To get elements inside a specific sheet of an excel workbook/get column names

        OleDbCommand objCmdSelect = new OleDbCommand("SELECT * FROM [" + "Sheet1" + "$]", objConn); 

        OleDbDataAdapter objAdapter1 = new OleDbDataAdapter(); 

        objAdapter1.SelectCommand = objCmdSelect; 

        DataSet objDataset1 = new DataSet(); 

        objAdapter1.Fill(objDataset1);

        string columnNames = string.Empty;
        // For each DataTable, print the ColumnName. use dataset.Rows to iterate row data...
        foreach (System.Data.DataTable table in objDataset1.Tables)
        {
            foreach (DataColumn column in table.Columns)
            {
                if (columnNames.Length > 0)
                {
                    columnNames = columnNames + Environment.NewLine + column.ColumnName;
                }
                else
                {
                    columnNames = column.ColumnName;
                }

            }
        } 

有人可以分享一些想法,以便我可以找出 excel 工作簿中的唯一数据并据此获取所需的值吗?提前致谢。

【问题讨论】:

  • 你尝试了什么?您的代码从 COM 互操作开始以打开工作簿,但随后切换到使用 OleDb 填充数据集。在同一个代码块中同时执行这两种操作是不寻常的。您将使用哪种方法来找到所需的值?如果您正在填充 DataSet,那么 Interop 似乎是不必要的,您可以搜索或过滤 DataTable。

标签: c# .net vb.net excel c#-4.0


【解决方案1】:

如果工作簿的结构如您所指,并且您将查询多个学生,那么正如@Andy G 建议的那样,您可能会发现将数据放入某种形式的记录集中然后在其上运行查询是最简单的通过 Linq 或 SQL 或任何你喜欢的。由于您根本不希望修改 Excel 工作簿,这可能是一种更好的方法。

或者,您可以使用 Excel API,就像您尝试使用的一样。您可以枚举工作表,在每个工作表上运行 Find。啊啦:

internal void GetYourData()
{
    //... code to get the relevant Workbook and relevant/new Excel Application

    Tuple<string, string> pupil;
    string searchTerm = "ABC";

    //Get the cell of the match
    Range match = FindFirstOccurrenceInWorkbook(workbook, searchTerm);
    if (match != null)
    {
        //Do whatever - per your data structure, it is probably easiest to just use .Offset(row, column) property
        pupil = new Tuple<string, string>((string)match.Offset(0, -1).Value, (string)match.Offset(0, 1).Value);
    }

    //... code to do whatever with your results
}

internal static Range FindFirstOccurrenceInWorkbook(Workbook workbook, string searchTerm)
{
    if (workbook == null) throw new ArgumentNullException("workbook");
    if (searchTerm == null) throw new ArgumentNullException("searchTerm");

    Sheets wss = workbook.Worksheets;
    Range match = null;

    foreach (Worksheet ws in wss)
    {
        Range cells = ws.Cells;
        //Add more args as needed - this is just an example
        match = cells.Find(
                what: searchTerm,
                after: Type.Missing,
                lookIn: XlFindLookIn.xlFormulas,
                lookAt: XlLookAt.xlPart);
        System.Runtime.InteropServices.Marshal.ReleaseComObject(cells);
        System.Runtime.InteropServices.Marshal.ReleaseComObject(ws);
        if (match != null)
        {
            break;
        }
    }
    System.Runtime.InteropServices.Marshal.ReleaseComObject(wss);
    GC.Collect();
    GC.WaitForPendingFinalizers();
    GC.Collect();

    return match;
}

此外,如果不生成孤立引用,则不能像使用的那样使用 COM 对象 -> 这将阻止 Excel 应用程序关闭。您需要将要使用的所有对象属性(如 Workbook.Worksheets)显式分配给变量,然后在变量即将超出范围时调用 System.Runtime.InteropServices.Marshal.ReleaseCOMObject(object)。

【讨论】:

  • 谢谢。 .Offset(-1, 0).Value 抛出错误,我使用 get_Offset new Tuple((string)match.get_Offset(-1, 0).Value, (string)match.get_Offset(1, 0 )。价值);但是输出结果不正确,让我再检查一下。
  • @Sharpeye500 哎呀——我把应该是列偏移的内容作为行偏移,反之亦然。 (只需将 Offset(-1,0) 更改为 Offset(0,-1) 等)。此外,我使用 NetOffice 而不是 Microsoft PIA,因此 get_Offset 可能是您需要的。 .Offset 当然对我有用。
  • 谢谢,而不是 Offset(0, 1).Value,反正我可以传递列名,输出结果可以随时改变?
猜你喜欢
  • 2021-04-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-10-18
  • 1970-01-01
相关资源
最近更新 更多