2010-02-27 9 views
7

Je me demandais si quelqu'un savait comment détecter rapidement s'il y a des données dans une feuille de travail donnée ou pas, sans boucler réellement toutes les lignes/colonnes de la feuille de calcul pour comprendre cela.Dans VSTO Excel, comment détecter des données dans des cellules?

J'écris un importateur qui va importer des données directement dans la feuille active (si elle n'a pas été modifiée), ou créer une nouvelle feuille de travail et l'importer à la place. Je suis en train de boucler toute la feuille, et il y a un décalage dans mon importation.

J'apprécierais toute aide à ce sujet. Je vous remercie!

+2

Je sais que c'est vieux, mais en plus des réponses éteins ces événements, remplir feuille de calcul, puis les rallume: 'currentInstance.EnableEvents = false/true; currentInstance.ScreenUpdating = false/true; ' –

Répondre

12

Pour éviter les boucles et profiter de la vitesse d'exécution quasi-instantanée, vous pouvez utiliser la méthode Excel.WorksheetFunction.CountA, qui renvoie le même résultat que la fonction = feuille de calcul NBVAL().

En supposant que votre référence Excel.Application est nommé 'excelApp' et votre référence Excel.Worksheet est nommé 'feuille de calcul', vous pouvez utiliser le code comme suit dans 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. 
} 

En C# 3.0 et ci-dessous, il est un peu plus bavard, parce que vous devez fournir explicitement les arguments optionnels manquants:

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

Je pense que cela devrait le faire pour vous!

Mike

+0

La conversion en int ne fonctionne pas, car [CountA] (http://msdn.microsoft.com/fr-fr/library/ microsoft.office.interop.excel.worksheetfunction.counta (v = office.14) .aspx) renvoie un double. – Maxence

-1

Cela devrait être assez rapide:

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

sélectionner et copier ne sont jamais rapides;) –

0

J'ai trouvé la solution suivante, qui est aussi instantanée, mais je ne sais pas comment il est précis ... il a passé tous mes tests jusqu'à présent.

Ici, il est pour tous ceux qui veulent savoir:

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 
} 

Je suppose que cela est beaucoup plus simple que sauter le presse-papier chaque fois que je fais le chèque ou comptant toutes les cellules non vides dans la feuille de calcul . Merci Mikael et Mike, j'apprécie vos deux réponses.

+0

momad, votre approche n'est pas mauvaise, mais c'est (a) plus de travail, et (b) indiquera incorrectement que certaines feuilles de travail contiennent des données quand elles ne le font pas, car UsedRange peut être affecté par des choses telles que le formatage dans les cellules, pas seulement des valeurs. Si vous utilisez la méthode 'Application.WorksheetFunction.CountA', vous récupérerez toutes les données et * seulement * les données sur une ligne au lieu de cinq. –

+0

Les deux sont beaucoup mieux que d'utiliser le presse-papiers à coup sûr. Le chemin du presse-papiers prendra également en compte les cellules avec "espace blanc", ce qui ne sera pas le cas autrement, mais c'est un cas particulier :) –

+0

Mike, je ne connaissais pas le formatage. Si c'est le cas, alors je suis tout à fait d'accord que la fonction de feuille de calcul CountA est une meilleure approche. Toutefois, dans mon scénario spécifique, je ne souhaite pas remplacer une cellule même si le changement est uniquement un changement de format. Merci pour la clarification! –

4

Je travaille avec VSTO et Excel depuis un certain temps, à un niveau très intense, alors j'espère pouvoir partager avec vous des choses que j'ai apprises au fil du temps. Sur la base des informations que vous avez fournies, je recommanderais plutôt de lancer un tableau d'objets et de travailler avec ces informations. Fondamentalement, vous souhaitez accéder aux valeurs:

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

ArrayValues ​​est un tableau 2D ([ligne, colonne]). Excel remplit le tableau très rapidement, et bien sûr les opérations sur le tableau seront très performantes (ne vous inquiétez pas de la performance de la boxe, ce n'est pas un problème, croyez-moi).

HTH, James

+0

Merci James, Je travaille sur un complément VSTO pour exceller et souvent se heurter à des problèmes qui peuvent être rapidement résolus par quelqu'un de savoir, mais prend du temps à trouver sur Internet. Je serai sûr de faire plus usage de stackoverflow car il y a tellement d'experts VSTO ici! –

+0

@ coder4life, savez-vous s'il existe un moyen de faire la même recherche en masse pour des propriétés comme la couleur des cellules? J'ai utilisé une méthode comme celle que vous avez décrite pour les valeurs depuis des mois, mais je n'ai pas encore trouvé le moyen de pouvoir récupérer toutes les couleurs (range.Interior.Color) sans aller ligne par ligne, col -par-col. Et c'est douloureusement lent! Merci! –

+0

En fait, j'ai ouvert un nouveau sujet pour cette question de recherche de couleur, juste pour qu'il soit plus facile à trouver pour d'autres personnes, plutôt que de regarder à travers les commentaires. L'URL est [http://stackoverflow.com/questions/8451511/vsto-getting-excel-cell-properties-in-bulk](http://stackoverflow.com/questions/8451511/vsto-getting-excel-cell -propriétés-en-vrac) –

0

Que diriez-vous?

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

Exemple d'appel

bool isFirstEmpty = IsSheetEmpty(1); 
Questions connexes