2010-01-21 25 views
5

Utilizzo Microsoft.Office.Interop.Excel e non riesco a trovare un modo per restituire le righe selezionate. Ciò che intendo per "selezionato" è, i numeri delle righe stessi quando si fa clic sul margine di rilegatura sulla sinistra e si seleziona una o più righe contigue o non contigue (che evidenzia l'intera riga). Ciò è diverso dalla selezione di una regione o area sul foglio stesso.Excel: recupero delle righe selezionate

Finora, ho guardato l'app.Selezione, app.Cells, app.Rows, e nessuna di queste sembra darmi le righe. app.Selection mi fornisce il contenuto effettivo della cella, che NON è quello che voglio.

Qualche idea? Grazie!

risposta

8

Per fare ciò, è necessario enumerare ciascuna area nell'intervallo e quindi elencare le righe all'interno di ciascuna area. Un po 'di confusione, la proprietà Excel.Range.Rows restituisce una raccolta di intervalli (ognuno che rappresenta una riga), mentre la proprietà Excel.Range.Row restituisce il numero di riga della cella in alto a sinistra dell'intervallo.

Pertanto, per ottenere i numeri di riga, è necessario enumerare le raccolte Aree e righe e quindi accedere a Range.Row. Ad esempio:

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

Si potrebbe anche usare Linq se si desidera.

Utilizzando Query Syntax:

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

Usando metodo Sintassi:

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

Aggiornamento: Come restituire distinti Numbers Row:

Per tornare numeri di riga distinte (che può verificarsi quando viene selezionata una gamma multi-area in cui le aree non comprendono intere righe).

(1) Il modo più semplice è utilizzare Linq e utilizzare l'operatore Distinct. Per esempio:

Utilizzando Query Syntax:

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

Usando metodo Sintassi:

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

(2) Se non fare uso di LINQ, allora si potrebbe utilizzare un HashSet. Per esempio:

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) Forse l'approccio più intuitivo è quello di convertire la vostra gamma originale per intere righe prima, e poi scorrere le righe. In questo caso, le righe sono già garantite come uniche, quindi non è necessario utilizzare un operatore HashSet o Distinct.

In questi esempi, si noti l'uso Excel.Range.EntireRow, che viene applicato alla gamma originale prima enumerazione dei settori e delle righe:

enumerazione senza utilizzare 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 utilizzando la sintassi di query:

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

Linq con il metodo sintassi:

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

Si noti che il Range.EntireRow May Return Incorrect Result, ma, se ho capito bene, questo vale solo per Excel '95 e sotto, che è completamente obsoleto. (Non mi preoccuperei di nessuna versione di Excel sotto Excel '97.) Se sei preoccupato per eventuali problemi di versioning, tuttavia, e non hai il lusso di provare in tutte le versioni di Excel, allora potresti voler usare un HashSet oppure utilizzare Linq insieme all'operatore Distinto per garantire che i numeri di riga siano univoci.

Spero che questo aiuti!

Mike

+0

Suggerisco di aggiungere un test aggiuntivo per evitare voci duplicate in rowNumbers. –

+0

Buon punto, Doc Brown! Ora aggiunto sopra ... :-) –

+0

Mike, è stato fantastico! Grazie mille!!! –

0

Non c'è bisogno di elencare le righe, solo le aree:

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

sto mescolando il mammut e l'aggiunta di qui un po 'di informazioni attuale:
Ora possiamo usare solo per xlApp.ActiveCell.Row che :)

Problemi correlati