如何以编程方式在多个工作表之间的Excel单元格中查找重复值
例如,我有一张名为EmployeeSheet的工作表,它是公司中每个员工姓名的首个和最后一个列。 让我们假设这个列表是完全格式化的,没有重复,所以每个单元格在这张表中是唯一的。
现在,我为公司中的每个部门都有一个工作表,例如FinanceSheet , ITSheet和SalesSheet 。 每张表都有一个地方(如每张表中没有相同的布局),每个部门的雇员名单。 但是,任何一个员工名称只能在所有部门表单之间出现一次(不包括EmployeeSheet)。
这里是我能想到的解决scheme,但不知道如何实现,将是一个multidimensional array(在学校学习了一点,依稀记得如何使用)。
伪代码类似于:
arrEmployees = {"Tom Hanks", "Burt Reynolds", "Your Mom"} arrFinance = {"Tom Hanks"} arrIT = {"Burt Reynolds"} arrSales = {"Your Mom"} arrSheets = {arrEmployees, arrFinance, arrIT, arrSales}
虽然我已经能够通过使用单个单元格值和范围作为string
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();
但是,通过这个过程来获得一个string的单个单元格的值,我不知道如何将它放入我的数组元素,更不用说一系列的值。
我敢肯定,我的方法不是最有效的,也许是不可能的,但这就是为什么我在这里寻求帮助,所以任何提示都表示赞赏。
编辑:这是最终为我工作的解决scheme。 感谢Ian Edwards解决scheme。
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[pY, pX] as Excel.Range.Value != null) { string cellVal = ((xlSheet.Cells[pY,pX] as Excel.Range).Value).ToString(); if (!names.Contains(cellVal)) { names.Add(cellVal)) } else { duplicates.Add(cellVal); } } } }
这里有一个我敲的小例子 – 评论应该解释什么是逐行的。
您可以声明要检查名称的工作表名称,以及在“工作表”字典中开始查找名称的位置。
我假设你不知道每个列表中有多less个名字 – 它将继续沿着每个列表向下,直到它遇到一个空白单元格。
// 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 (ie 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! }
- 您可以使用
.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()快得多 (见“性能”部分)。 使用多个范围的组合+ 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的索引。