如何以编程方式在多个工作表之间的Excel单元格中查找重复值
本文关键字:单元格 Excel 查找 之间 编程 方式 工作 | 更新日期: 2023-09-27 18:14:43
例如,我有一个名为EmployeeSheet的表,它只是公司中每个员工姓名的首列和尾列。假设此列表格式完美,没有重复,因此工作表中的每个单元格都是唯一的。
现在我有了公司每个部门的表格,例如 financiesheet 、ITSheet和SalesSheet。每张表格都在某个地方(因为每张表格的布局不同)列出了每个部门的员工名单。但是,任何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); } } } }
这是我拼凑的一个小例子-注释应该逐行解释发生了什么。
您可以声明要检查名称的工作表的名称,以及在"工作表"字典中从哪里开始查找名称。
我假设您不知道每个列表中有多少个名字-它将继续沿着每个列表向下查找,直到遇到空白单元格。
// 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!
}
- 您可以使用
.Range
定义多个单元格(即.Range["A1", "F500"]
)
- 然后您可以使用
.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的索引。