2010-02-27 7 views
7

Ich frage mich, ob jemand wusste, wie schnell zu erkennen ist, ob Daten in einem bestimmten Arbeitsblatt vorhanden sind oder nicht, ohne dass tatsächlich alle Zeilen/Spalten des Arbeitsblatts durchlaufen werden, um dies herauszufinden.Wie erkennt man in VSTO Excel Daten in Zellen?

Ich schreibe ein Importprogramm, das Daten direkt in das aktive Arbeitsblatt importiert (wenn es nicht geändert wurde), oder ein neues Arbeitsblatt erstellen und stattdessen in es importieren. Ich durchlaufe gerade das gesamte Blatt und es gibt eine merkliche Verzögerung in meinem Import.

Ich würde jede Hilfe in der Angelegenheit schätzen. Vielen Dank!

+2

Ich weiß, das alt ist, aber zusätzlich zu den Antworten machen diese Ereignisse aus, Arbeitsblatt füllen und sie dann wieder einschalten: 'currentInstance.EnableEvents = false/true; currentInstance.ScreenUpdating = false/true; ' –

Antwort

12

Looping zu vermeiden und nahezu sofortige Ausführungsgeschwindigkeit ausnutzen, können Sie die Excel.WorksheetFunction.CountA Methode verwenden, die das gleiche Ergebnis wie die = COUNTA() Tabellenfunktion zurückgibt.

Unter der Annahme, dass Ihre Excel.Application Referenz wird der Namen 'excelApp' und Ihre Excel.Worksheet Referenz ist 'Arbeitsblatt' genannt, können Sie Code wie die folgenden in C# 4.0 verwenden können:

// 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 und unten, ist es ein bisschen ausführlicher, weil Sie explizit müssen die fehlenden optionale Argumente liefern:

// 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. 
} 

ich denke, das es für Sie tun sollten!

Mike

+0

Die Besetzung in int nicht funktioniert, weil [COUNTA] (http://msdn.microsoft.com/en-us/library/ Microsoft.office.interop.excel.worksheetfunction.counta (v = office.14) .aspx) gibt ein double zurück. – Maxence

-1

Dies sollte ziemlich schnell sein:

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

auswählen und kopieren sind nie schnell;) –

0

fand ich die folgende Lösung, die auch augenblicklich ist, aber ich bin mir nicht sicher, wie genau es ist ... es bisher alle meine Tests bestanden hat.

Hier ist es für jeden, der wissen will:

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 
} 

Ich nehme an, das viel einfacher ist als die Zwischenablage ich den Scheck zu tun jedes Mal, Sprengung oder Zählen alle nicht leeren Zellen in dem Arbeitsblatt . Danke Mikael und Mike, ich schätze deine Antworten.

+0

momad, Ihr Ansatz ist nicht schlecht, aber es ist (a) mehr Arbeit, und (b) meldet fälschlicherweise einige Arbeitsblätter als Daten enthalten, wenn dies nicht der Fall, weil die Usedrange durch solche Dinge wie die Formatierung in den Zellen beeinflusst werden kann, nicht nur Werte. Wenn Sie stattdessen die 'Application.WorksheetFunction.CountA'-Methode verwenden, würden Sie alle Daten und * only * -Daten in einer Zeile statt in fünf auflesen. –

+0

Beide sind viel besser als die Verwendung der Zwischenablage sicher. Die Zwischenablage Art und Weise wird auch zu berücksichtigen, Zellen mit „white space“, die die anderen Wege nicht, aber das ist ein besonderer Fall :) –

+0

Mike, ich wusste nicht, über die Formatierung. Wenn das der Fall ist, stimme ich definitiv zu, dass die Arbeitsblattfunktion CountA ein besserer Ansatz ist. In meinem speziellen Szenario möchte ich jedoch keine Zelle überschreiben wollen, auch wenn die Änderung nur eine Formatierungsänderung ist. Danke für die Klarstellung! –

4

Ich arbeite mit VSTO und Excel seit einiger Zeit auf einem sehr intensiven Niveau, so hoffe ich, dass ich Dinge, die ich im Laufe der Zeit gelernt habe, mit Ihnen teilen kann.

Basierend auf den Informationen, die Sie bereitgestellt haben, würde ich empfehlen, auf ein Objektarray zu übertragen und stattdessen mit diesen Informationen zu arbeiten. Grundsätzlich würden Sie auf die Werte wie zugreifen:

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

ArrayValues ​​ist ein 2D-Array ([Zeile, Spalte]). Excel bevölkert das Array blitzschnell, und natürlich sind Operationen auf dem Array sehr performant (mach dir keine Sorgen über die Leistung des Boxens, es ist KEIN Problem, glaub mir).

HTH, James

+0

Dank James gewesen, ich auf einem VSTO arbeite Add-in für Excel und oft auf Probleme stoßen, die von jemandem, der Bescheid weiß, aber zeitaufwendig im Internet gefunden werden kann. Ich werde sicher mehr Stackoverflow nutzen, da es so viele VSTO-Experten gibt! –

+0

@ coder4life, wissen Sie, ob es ein Weg, um das gleiche „bulk“ für Eigenschaften wie Zellfarbe holen zu tun? Ich habe eine Methode verwendet, wie Sie Werte für Monate beschrieben jetzt, aber ich habe noch einen Weg zu finden, ohne Zeile-für-Zeile gehen alle Farben (range.Interior.Color) in der Lage sein zu holen, col -nach Kol. Und es ist schmerzhaft langsam! Vielen Dank! –

+0

Eigentlich habe ich einen neuen Thread für diese Frage geöffnet, nur so ist es leichter für andere Leute zu finden, als durch Kommentare zu schauen. Die URL ist [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

über Wie?

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

Beispielaufruf

bool isFirstEmpty = IsSheetEmpty(1);