2010-02-27 15 views
7

Mi chiedevo se qualcuno fosse in grado di rilevare rapidamente se ci sono dati in un dato foglio di lavoro o meno, senza effettivamente scorrere tutte le righe/colonne del foglio di lavoro per capirlo.In VSTO Excel, come rilevare i dati nelle celle?

Sto scrivendo un importatore che importa i dati direttamente nel foglio di lavoro attivo (se non è stato modificato), oppure crea un nuovo foglio di lavoro e importa invece in esso. Attualmente sto eseguendo il ciclo di tutto il foglio e ci sono alcuni ritardi notevoli nella mia importazione.

Apprezzerei qualsiasi aiuto in merito. Grazie!

+2

So che questo è vecchio, ma in aggiunta alle risposte spegnere questi eventi, compilare foglio di lavoro, poi girare di nuovo su: 'currentInstance.EnableEvents = false/true; currentInstance.ScreenUpdating = false/true; ' –

risposta

12

Per evitare loop e sfruttare la velocità di esecuzione quasi istantanea, è possibile utilizzare il metodo Excel.WorksheetFunction.CountA, che restituisce lo stesso risultato della funzione del foglio di lavoro = CONTA.VALORI().

Supponendo che il vostro riferimento Excel.Application si chiama 'excelApp' e il vostro riferimento Excel.Worksheet si chiama 'foglio', è possibile utilizzare il codice simile al seguente in C# 4.0:

// C# 4.0 
int dataCount = (int)excelApp.WorksheetFunction.CountA(worksheet.Cells); 

if (dataCount == 0) 
{ 
    // All cells on the worksheet are empty. 
} 
else 
{ 
    // There is at least one cell on the worksheet that has non-empty contents. 
} 

In C# 3.0 e qui di seguito, è un po 'più prolisso, perché è necessario fornire esplicitamente gli argomenti opzionali mancanti:

// C# 3.0 and below 
int dataCount = (int)excelApp.WorksheetFunction.CountA(
    worksheet.Cells, 
    Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, 
    Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, 
    Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, 
    Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, 
    Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing); 

if (dataCount == 0) 
{ 
    // All cells on the worksheet are empty. 
} 
else 
{ 
    // There is at least one cell on the worksheet that has non-empty contents. 
} 

penso che questo dovrebbe farlo per voi!

Mike

+0

Il cast in int non funziona, perché [CountA] (http://msdn.microsoft.com/en-us/library/ microsoft.office.interop.excel.worksheetfunction.counta (v = office.14) .aspx) restituisce un doppio. – Maxence

-1

Questo dovrebbe essere piuttosto veloce:

private void CheckForContent() 
    { 
     Worksheet activeSheet = ActiveSheet; 
     var range = activeSheet.get_Range("A1", GetExcelColumnName(activeSheet.Columns.Count)+activeSheet.Rows.Count.ToString()); 
     range.Select(); 
     range.Copy(); 
     string text = Clipboard.GetText().Trim(); 
     if(string.IsNullOrEmpty(text)) 
     { 
      MessageBox.Show("No text"); 
     } 
    } 

    private string GetExcelColumnName(int columnNumber) 
    { 
     int dividend = columnNumber; 
     string columnName = String.Empty; 
     int modulo; 

     while (dividend > 0) 
     { 
      modulo = (dividend - 1) % 26; 
      columnName = Convert.ToChar(65 + modulo).ToString() + columnName; 
      dividend = (int)((dividend - modulo)/26); 
     } 
     return columnName; 
    } 
+0

selezionare e copiare non sono mai veloci;) –

0

ho trovato la soluzione seguente, che è anche istantanea, ma non sono sicuro come precisa che è ... ha superato tutte le mie prove finora.

Qui è per chi vuole sapere:

Worksheet sheet = (Worksheet)this.Application.ActiveSheet; 
Range usedRange = sheet.UsedRange; 
bool isUsed = (usedRange.Count > 1); 
if (usedRange.Count == 1) 
{ 
    isUsed = (usedRange.Value2 != null) && 
      (!string.IsNullOrEmpty(usedRange.Value2.ToString())); 
} 

if(isUsed) 
{ 
    // worksheet cells not empty 
} 

Suppongo che questo sia molto più semplice di far saltare in aria negli appunti ogni volta che faccio l'assegno o contare tutte le celle non vuote nel foglio di lavoro . Grazie a Mikael e Mike, apprezzo entrambe le vostre risposte.

+0

momad, il tuo approccio non è male, ma è (a) più lavoro, e (b) segnalerà erroneamente alcuni fogli di lavoro come contenenti dati quando non lo fa, perché il UsedRange può essere influenzato da cose come la formattazione nelle celle, non solo valori. Se utilizzi il metodo 'Application.WorksheetFunction.CountA', invece, raccogli tutti i dati e * solo * i dati in una riga anziché in cinque. –

+0

Entrambi sono molto meglio che usare gli appunti di sicuro. Il modo negli Appunti prenderà in considerazione anche le celle con "spazio bianco", che gli altri modi non saranno, ma è un caso speciale :) –

+0

Mike, non sapevo della formattazione. In questo caso, sono assolutamente d'accordo sul fatto che la funzione del foglio di lavoro CountA sia un approccio migliore. Tuttavia, nel mio scenario specifico, non voglio voler ignorare una cella anche se la modifica è solo una modifica della formattazione. Grazie per il chiarimento! –

4

Lavoro con VSTO ed Excel per un po 'di tempo, ad un livello molto intenso, quindi spero di poter condividere con voi le cose che ho imparato nel corso del tempo.

In base alle informazioni fornite, consigliamo di eseguire il casting su un array di oggetti e utilizzare invece tali informazioni. Fondamentalmente dovresti accedere ai valori come:

object[,] arrayValues = (object[,])ExcelRange.Value2; 

arrayValues ​​è un array 2D ([riga, colonna]). Excel popola l'array incredibilmente veloce e, naturalmente, le operazioni sull'array saranno molto performanti (non preoccuparti delle prestazioni della boxe, NON è un problema, credimi).

HTH, James

+0

Grazie James, Sto lavorando su un componente aggiuntivo VSTO per eccellere e spesso incappare in problemi che possono essere rapidamente risolti da qualcuno che sa, ma richiede tempo per trovare su internet. Sarò sicuro di utilizzare maggiormente lo stackoverflow poiché ci sono così tanti esperti VSTO qui fuori! –

+0

@ coder4life, sai se c'è un modo per fare lo stesso recupero "alla rinfusa" di proprietà come il colore della cella? Ho usato un metodo proprio come hai descritto per i valori per mesi, ma devo ancora trovare un modo per essere in grado di recuperare tutti i colori (range.Interior.Color) senza andare riga per fila, col -da-col. Ed è dolorosamente lento! Grazie! –

+0

In realtà, ho aperto una nuova discussione per questa domanda di recupero colore, solo che è più facile trovarla per altre persone, piuttosto che guardare attraverso i commenti. L'URL è [http://stackoverflow.com/questions/8451511/vsto-getting-excel-cell-properties-in-bulk](http://stackoverflow.com/questions/8451511/vsto-getting-excel-cell -properties-in-bulk) –

0

ne dite?

public static bool IsSheetEmpty(int sheetNo) 
{ 
    bool isEmpty = false; 

    if (sheetNo <= Globals.ThisAddIn.Application.Worksheets.Count) 
    { 
     Worksheet ws = Globals.ThisAddIn.Application.Worksheets[sheetNo]; 

     if (ws.UsedRange.Address.ToString() == "$A$1" && String.IsNullOrWhiteSpace(ws.get_Range("A1").Value2)) 
     { 
      isEmpty = true; 
     } 
    } 
    else 
    { 
     // or add your own error handling when sheetNo is not found 
    } 

    return isEmpty; 
} 

chiamata Esempio

bool isFirstEmpty = IsSheetEmpty(1); 
Problemi correlati