Excel:获取所选行

Mar*_*ton 5 c# excel automation

我正在使用Microsoft.Office.Interop.Excel,我找不到返回所选行的方法.我所说的"选择"是指,当您单击左侧的行排水沟并选择一个或多个连续或不连续的行(突出显示整行)时,行号本身.这与选择区域或纸张本身的区域.

到目前为止,我已经看过app.Selection,app.Cells,app.Rows,但这些似乎都没有给我行.app.Selection给我实际的细胞内容,这不是我想要的.

有任何想法吗?谢谢!

Mik*_*lum 10

为此,您需要枚举Range中的每个Area,然后枚举每个区域内的Rows.有点令人困惑的是,Excel.Range.Rows属性返回一个范围集合(每个表示一行),而Excel.Range.Row属性返回范围中左上角单元格的行号.

因此,要获取行号,您应该枚举区域和行集合,然后访问Range.Row.例如:

Excel.Range range = (Excel.Range)excelApp.Selection;

List<int> rowNumbers = new List<int>();

// Enumerate the Rows within each Area of the Range.
foreach (Excel.Range area in range.Areas)
{
    foreach (Excel.Range row in area.Rows)
    {
        rowNumbers.Add(row.Row);
    }
}

// Report the results.
foreach (int rowNumber in rowNumbers)
{
    MessageBox.Show(rowNumber.ToString());
}
Run Code Online (Sandbox Code Playgroud)

如果你愿意,你甚至可以使用Linq.

使用查询语法:

IEnumerable<int> rowNumbers =
    from area in range.Areas.Cast<Excel.Range>()
    from row in area.Rows.Cast<Excel.Range>()
    select row.Row;
Run Code Online (Sandbox Code Playgroud)

使用方法语法:

IEnumerable<int> rowNumbers =
    range.Areas.Cast<Excel.Range>()
    .SelectMany(area => area.Rows.Cast<Excel.Range>()
                        .Select(row => row.Row));
Run Code Online (Sandbox Code Playgroud)

更新:如何返回不同的行号:

返回不同的行号(当选择区域不包括整行的多区域范围时,可能会出现这种情况).

(1)最简单的方法是使用Linq并使用Distinct运算符.例如:

使用查询语法:

IEnumerable<int> distinctRowNumbers =
    (from area in range.Areas.Cast<Excel.Range>()
     from row in area.Rows.Cast<Excel.Range>()
     select row.Row)
    .Distinct();
Run Code Online (Sandbox Code Playgroud)

使用方法语法:

IEnumerable<int> distinctRowNumbers =
    range.Areas.Cast<Excel.Range>()
    .SelectMany(area => area.Rows.Cast<Excel.Range>()
                        .Select(row => row.Row))
    .Distinct();
Run Code Online (Sandbox Code Playgroud)

(2)如果没有使用Linq,那么你可以使用HashSet.例如:

Excel.Range range = (Excel.Range)excelApp.Selection;

HashSet<int> distinctRowNumbers = new HashSet<int>();

// Enumerate the Rows within each Area of the Range.
foreach (Excel.Range area in range.Areas)
{
    foreach (Excel.Range row in area.Rows)
    {
        distinctRowNumbers.Add(row.Row);
    }
}

// Report the results.
foreach (int rowNumber in distinctRowNumbers)
{
    MessageBox.Show(rowNumber.ToString());
}
Run Code Online (Sandbox Code Playgroud)

(3)也许最直观的方法是首先将原始范围转换为整行,然后迭代行.在这种情况下,行已经保证是唯一的,因此我们不需要使用HashSetDistinct运算符.

在这些示例中,请注意使用Excel.Range.EntireRow,它在枚举区域和行之前应用于原始范围:

不使用Linq进行枚举:

List<int> distinctRowNumbers = new List<int>();

foreach (Excel.Range area in range.EntireRow.Areas)
{
    foreach (Excel.Range row in area.Rows)
    {
        distinctRowNumbers.Add(row.Row);
    }
}
Run Code Online (Sandbox Code Playgroud)

Linq使用查询语法:

IEnumerable<int> distinctRowNumbers =
    from area in range.EntireRow.Areas.Cast<Excel.Range>()
    from row in area.Rows.Cast<Excel.Range>()
    select row.Row;
Run Code Online (Sandbox Code Playgroud)

Linq使用方法语法:

IEnumerable<int> distinctRowNumbers =
    range.EntireRow.Areas.Cast<Excel.Range>()
    .SelectMany(area => area.Rows.Cast<Excel.Range>()
                        .Select(row => row.Row));
Run Code Online (Sandbox Code Playgroud)

请注意,Range.EntireRow可能会返回不正确的结果,但是,如果我理解正确,这仅适用于Excel '95及更低版本,这已完全过时.(我不担心Excel '97下面的任何版本的Excel.)但是,如果您担心任何版本问题,并且没有在所有Excel版本中进行测试,那么您可能希望坚持使用HashSet ,或使用Linq和Distinct运算符,以确保您的行号是唯一的.

希望这可以帮助!

麦克风