Excel: возвращение выбранных строк - PullRequest
5 голосов
/ 21 января 2010

Я использую Microsoft.Office.Interop.Excel и не могу найти способ вернуть выбранные строки. Под «выбранным» я подразумеваю сами номера строк, когда вы щелкаете по желобу слева и выбираете одну или несколько смежных или несмежных строк (которые выделяют всю строку). Это отличается от выбора региона область на самом листе.

До сих пор я смотрел на app.Selection, app.Cells, app.Rows, и ни один из них не дает мне строк. app.Selection дает мне фактическое содержимое ячейки, а это НЕ то, что я хочу.

Есть идеи? Спасибо!

Ответы [ 3 ]

9 голосов
/ 21 января 2010

Для этого вам нужно перечислить каждую область в диапазоне, а затем перечислить строки в каждой области. Несколько странно, что свойство 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());
}

Вы можете даже использовать Linq, если хотите.

Использование синтаксиса запроса:

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

Использование синтаксиса метода:

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

Обновление: как вернуть Отличительные Номера строк:

Чтобы вернуть отдельные номера строк (что может произойти, если выбран диапазон из нескольких областей, если области не содержат целых строк).

(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();

Использование синтаксиса метода:

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

(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());
}

(3) Возможно, самый интуитивный подход - сначала преобразовать исходный диапазон во все строки, а затем выполнить итерацию строк. В этом случае строки уже гарантированно будут уникальными, поэтому нам не нужно использовать оператор HashSet или оператор Distinct .

В этих примерах обратите внимание на использование 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);
    }
}

Linq с использованием синтаксиса запроса:

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

Linq с использованием синтаксиса метода:

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

Обратите внимание, что Range.EntireRow может возвращать неверный результат , но, если я правильно понимаю, это относится только к Excel '95 и ниже, который полностью устарел. (Я бы не стал беспокоиться о любой версии Excel ниже Excel '97.) Если, однако, вас беспокоят какие-либо проблемы с версиями, и вы не можете позволить себе роскошь тестирования во всех версиях Excel, вы можете использовать HashSet. или используйте Linq вместе с оператором Distinct, чтобы обеспечить уникальность номеров строк.

Надеюсь, это поможет!

Mike

0 голосов
/ 29 января 2018

Я помешиваю мамонта и добавляю немного актуальной информации:
теперь мы можем использовать только xlApp.ActiveCell.Row для этого:)

0 голосов
/ 10 мая 2017

Не нужно перечислять строки, только области:

var rows = new SortedSet<int>();                 // distinct and sorted

foreach (Excel.Range a in app.Selection.Areas)
    foreach (int r in Enumerable.Range(a.Row, a.Rows.Count))
        rows.Add(r);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...