【问题标题】:How to find duplicate values in Excel cells between multiple sheets programmatically如何以编程方式在多个工作表之间的 Excel 单元格中查找重复值
【发布时间】:2015-09-25 14:57:48
【问题描述】:

例如,我有一个名为 EmployeeSheet 的工作表,它只是公司中每个员工姓名的第一列和最后一位。让我们假设这个列表格式完美并且没有重复,所以每个单元格在这张表中都是唯一的。

现在我有一个公司每个部门的工作表,例如 FinanceSheetITSheetSalesSheet。每个工作表的某个地方都有一个每个部门的员工列表(因为每个工作表没有相同的布局)。但是,任何 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); } } } }

【问题讨论】:

    标签: c# arrays excel office-interop


    【解决方案1】:

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

    您可以声明要检查名称的工作表的名称,以及在“工作表”字典中从何处开始查找名称。

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

            // 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!
            }
    

    【讨论】:

    • 我有一个工作表,我想检查一列并且只检查该列中出现的任何重复项?
    【解决方案2】:
    1. 您可以使用.Range 定义多个单元格(即.Range["A1", "F500"]

    https://msdn.microsoft.com/en-us/library/microsoft.office.tools.excel.worksheet.range.aspx

    1. 然后您可以使用.get_Value 获取该范围内所有单元格的内容/值。根据 dotnetperls.com get_Value() is much faster than get_Range()(参见“性能”部分)。使用多个范围 + get_value 的组合肯定会比使用 get_range 的大量单范围调用执行得更好。

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

    我将它们存储在Object Array 中。

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

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

    【讨论】:

      猜你喜欢
      • 2014-11-30
      • 2013-01-11
      • 2011-11-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-11-14
      • 1970-01-01
      相关资源
      最近更新 更多