2010-01-21 14 views
5

Używam Microsoft.Office.Interop.Excel i nie mogę znaleźć sposobu na zwrócenie zaznaczonych wierszy. To, co mam na myśli przez "wybrane", to same numery wierszy po kliknięciu na rynnę po lewej stronie i wybrania jednego lub więcej ciągłych lub niesąsiadujących wierszy (co powoduje zaznaczenie całego wiersza). Różni się to od wyboru regionu lub obszar na samym arkuszu.Excel: pobieranie zaznaczonych wierszy powrotem

Do tej pory przyjrzałem się aplikacji. Selekcja, app.Cells, app.Rows i żadne z nich nie wydają mi się wiersze. app.Selection daje mi rzeczywistą zawartość komórki, która NIE jest tym, czego chcę.

Wszelkie pomysły? Dzięki!

Odpowiedz

8

Aby to zrobić, należy wyliczyć każdy obszar w zakresie, a następnie wyliczyć wiersze w każdym obszarze. Nieco mylące, właściwość Excel.Range.Rows zwraca zbiór zakresów (każdy reprezentuje wiersz), podczas gdy właściwość Excel.Range.Row zwraca numer wiersza lewej górnej komórki w zakresie.

Dlatego, aby uzyskać numery wierszy, należy wyliczyć kolekcje Obszary i rzędy, a następnie uzyskać dostęp do Range.Row. Na przykład:

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

Możesz nawet użyć Linq, jeśli chcesz.

Korzystanie Składnia zapytania:

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

Korzystanie Metoda Składnia:

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

Update: Jak Powrót różne numery rzędu:

Aby powrócić odrębne numery wierszy (co może wystąpić, gdy wybrany jest zakres wielu obszarów, w którym obszary nie obejmują całych rzędów).

(1) Najprostszym sposobem jest użycie Linq i skorzystanie z operatora Distinct. Na przykład:

Korzystanie Składnia zapytania:

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

stosując metodę Składnia:

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

(2) Jeżeli nie wykorzystując Linq, a następnie można użyć HashSet. Na przykład:

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) Być może najbardziej intuicyjne podejście jest zamienić oryginalny asortyment do całych wierszy, a potem iteracyjne wierszy. W tym przypadku wiersze są już gwarantowane jako unikatowe, więc nie musimy używać operatora HashSet ani operatora Distinct.

W tych przykładów należy zwrócić uwagę na stosowanie Excel.Range.EntireRow, który jest stosowany do pierwotnego zakresu przed wyliczanie powierzchni i rzędach

wylicza bez 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 w składni zapytania:

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

Linq stosując metodę Składnia

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

Zauważ, że Range.EntireRow May Return Incorrect Result, ale jeśli rozumiem to poprawnie, dotyczy to tylko Excel '95 i poniżej, co jest całkowicie przestarzałe. (Nie martwiłbym się żadną wersją Excela poniżej Excela 97). Jeśli jednak obawiasz się problemów związanych z wersjami i nie masz luksusu testowania we wszystkich wersjach Excela, możesz chcieć trzymać się za pomocą HashSet lub użyj Linq razem z operatorem Distinct, aby upewnić się, że numery wierszy są unikalne.

Mam nadzieję, że to pomoże!

Mike

+0

Proponuję dodać dodatkowy test, aby uniknąć duplikatów wpisów w wierszach. –

+0

Dobra uwaga, Doc Brown! Teraz dodane powyżej ... :-) –

+0

Mike, to było fantastyczne! Dziękuję bardzo!!! –

0

Nie ma potrzeby, aby wyliczyć wiersze, po prostu obszarach:

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

mam mieszanie mamuta i dodając tutaj trochę rzeczywistej INFO:
teraz możemy używać tylko dla xlApp.ActiveCell.Row że :)

Powiązane problemy