如何以编程方式在多个工作表之间的Excel单元格中查找重复值

本文关键字:单元格 Excel 查找 之间 编程 方式 工作 | 更新日期: 2023-09-27 18:14:43

例如,我有一个名为EmployeeSheet的表,它只是公司中每个员工姓名的首列和尾列。假设此列表格式完美,没有重复,因此工作表中的每个单元格都是唯一的。

现在我有了公司每个部门的表格,例如 financiesheet ITSheetSalesSheet。每张表格都在某个地方(因为每张表格的布局不同)列出了每个部门的员工名单。但是,任何1个员工名应该只在所有部门表(不包括EmployeeSheet)中出现一次。

这是我能想到的解决方案,但不知道如何实现,将是做一个多维数组(在学校里学了一点关于他们,模糊地记得如何使用)。

伪代码,例如:

 arrEmployees = {"Tom Hanks", "Burt Reynolds", "Your Mom"}
 arrFinance = {"Tom Hanks"}
 arrIT = {"Burt Reynolds"}
 arrSales = {"Your Mom"}
 arrSheets = {arrEmployees, arrFinance, arrIT, arrSales}

虽然我已经能够通过使用

获得单个单元格值和范围作为字符串
Sheets shts = app.Worksheets;
Worksheet ws = (Worksheet)sheets.get_Item("EmployeeSheet");
Excel.Range empRange = (Excel.Range)worksheet.get_range("B2");
string empVal = empRange.Value2.ToString();  

但是通过这个过程将单个单元格值转换为字符串,我不知道如何将其放入数组的元素中,更不用说值的范围了。

我确信我的方法不是最有效的,甚至可能不可能,但这就是我在这里寻求帮助的原因,所以任何建议都很感激。


编辑:这是解决方案,最终为我工作。多亏了Ian Edwards的解决方案。

Dictionary<string, List<Point>> fields = new Dictionary<string, List<Point>>();
fields["Finance"] = new List<Point>() { new Point(2,20)};
fields["Sales"] = new List<Point>();
for (int row = 5; row <= 185; row += 20) {fields["Sales"].Add(new Point(2,row));}
List<string> names = new List<string>();
List<string> duplicates = new List<string>();
foreach (KeyValuePair<string, List<Point>> kp in fields)
{ 
   Excel.Worksheet xlSheet = (Excel.Worksheet)workbook.Worksheets[kp.Key];
   foreach (Point p in kp.Value)
   {
     if ((xlSheet.Cells[p.Y, p.X] as Excel.Range.Value != null)
     {
       string cellVal = ((xlSheet.Cells[p.Y,p.X] as Excel.Range).Value).ToString();
       if (!names.Contains(cellVal))
       { names.Add(cellVal)) }
       else { duplicates.Add(cellVal); } } } }

如何以编程方式在多个工作表之间的Excel单元格中查找重复值

这是我拼凑的一个小例子-注释应该逐行解释发生了什么。

您可以声明要检查名称的工作表的名称,以及在"工作表"字典中从哪里开始查找名称。

我假设您不知道每个列表中有多少个名字-它将继续沿着每个列表向下查找,直到遇到空白单元格。

        // Load the Excel app
        Microsoft.Office.Interop.Excel.Application xlApp = new Microsoft.Office.Interop.Excel.Application();
        // Open the workbook
        var xlWorkbook = xlApp.Workbooks.Open("XLTEST.xlsx");
        // Delcare the sheets and locations to look for names
        Dictionary<string, Tuple<int, int>> worksheets = new Dictionary<string, Tuple<int, int>>()
        {
            // Declare the name of the sheets to look in and the 1 base X,Y index of where to start looking for names on each sheet (i.e. 1,1, = A1)
            { "Sheet1", new Tuple<int, int>(1, 1) },
            { "Sheet2", new Tuple<int, int>(2, 3) },
            { "Sheet3", new Tuple<int, int>(4, 5) },
            { "Sheet4", new Tuple<int, int>(2, 3) },
        };
        // List to keep track of all names in all sheets
        List<string> names = new List<string>();
        // Iterate over every sheet we need to look at
        foreach(var worksheet in worksheets)
        {
            string workSheetName = worksheet.Key;
            // Get this excel worksheet object
            var xlWorksheet = (Microsoft.Office.Interop.Excel.Worksheet)xlWorkbook.Worksheets[workSheetName];
            // Get the 1 based X,Y cell index
            int row = worksheet.Value.Item1;
            int column = worksheet.Value.Item2;
            // Get the string contained in this cell
            string name = (string)(xlWorksheet.Cells[row, column] as Microsoft.Office.Interop.Excel.Range).Value;
            // name is null when the cell is empty - stop looking in this sheet and move on to the next one
            while(name != null)
            {
                // Add the current name to the list
                names.Add(name);
                // Get the next name in the cell below this one
                name = (string)(xlWorksheet.Cells[++row, column] as Microsoft.Office.Interop.Excel.Range).Value;
            }
        }
        // Compare the number of names to the number of unique names
        if (names.Count() != names.Distinct().Count())
        {
            // You have duplicate names!
        }
  1. 您可以使用.Range定义多个单元格(即.Range["A1", "F500"])
https://msdn.microsoft.com/en-us/library/microsoft.office.tools.excel.worksheet.range.aspx

  • 然后您可以使用.get_Value来获取该范围内所有单元格的内容/值。根据dotnetperls.com, get_Value()比get_Range()快得多(见"性能"部分)。使用多个range + get_value的组合将绝对在使用get_range的大量单范围调用中执行得更好。

    https://msdn.microsoft.com/en-us/library/microsoft.office.tools.excel.namedrange.get_value (v = vs.120) . aspx

    我将它们存储在一个对象数组中。

    (object[,])yourexcelRange.get_Value(Excel.XlRangeValueDataType.xlRangeValueDefault);
    

    从那里你可以编写自己的比较方法来比较多个数组。一个奇怪的地方是,这样做返回一个以1为索引的数组,而不是标准的基于0的索引。