2010-02-27 42 views
7

Me preguntaba si alguien sabía cómo detectar rápidamente si hay datos en una hoja de trabajo determinada o no, sin realmente recorrer todas las filas/columnas de la hoja de trabajo para resolver esto.En VSTO Excel, ¿cómo detectar datos en las celdas?

Escribo un importador que importará los datos directamente a la hoja de trabajo activa (si no se ha modificado), o crea una nueva hoja de cálculo y la importa en su lugar. Actualmente estoy revisando toda la hoja, y hay un retraso notable en mi importación.

Agradeceria cualquier ayuda en la materia. ¡Gracias!

+2

Sé que esto es viejo, pero además de las respuestas desactivar estos eventos, rellenar la hoja de cálculo, a continuación, volver a activarlos: 'currentInstance.EnableEvents = false/true; currentInstance.ScreenUpdating = false/true; ' –

Respuesta

12

Para evitar bucles y tomar ventaja de la velocidad de ejecución casi instantánea, puede utilizar el método Excel.WorksheetFunction.CountA, que devuelve el mismo resultado que la función de hoja = CONTARA().

Suponiendo que su referencia Excel.Application se llama 'excelApp' y su referencia Excel.Worksheet se llama 'hoja', puede utilizar código como el siguiente en 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 y a continuación, es un poco más detallado, ya que hay que prever explícitamente los argumentos opcionales que faltan:

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

creo que esto debería hacerlo por usted!

Mike

+0

El molde en int no funciona, porque [CountA] (http://msdn.microsoft.com/en-us/library/ microsoft.office.interop.excel.worksheetfunction.counta (v = office.14) .aspx) devuelve un doble. – Maxence

-1

Esto debería ser bastante rápido:

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

seleccionar y copiar nunca son rápidos;) –

0

me encontré con la siguiente solución, que también es instantánea, pero no estoy seguro de cómo es exacta ... que ha pasado todos mis pruebas hasta el momento.

aquí está para cualquier persona que quiera saber:

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 
} 

supongo que esto es mucho más simple que la voladura del portapapeles cada vez que hago el cheque o contar todas las celdas no vacías en la hoja de trabajo . Gracias Mikael y Mike, aprecio sus respuestas.

+0

momad, su enfoque no es malo, pero es (a) más trabajo, y (b) informará incorrectamente que algunas hojas de cálculo contienen datos cuando no lo hace, porque el UsedRange puede verse afectado por cuestiones como el formateo en las celdas, no solo valores Si utiliza el método 'Application.WorksheetFunction.CountA', en su lugar, recogería todos los datos y * solo * datos en una línea, en lugar de cinco. –

+0

Ambos son mucho mejores que usar el portapapeles seguro. La forma del portapapeles también tendrá en cuenta las celdas con "espacio en blanco", que las otras formas no, pero ese es un caso especial :) –

+0

Mike, no sabía sobre el formato. Si ese es el caso, definitivamente estoy de acuerdo en que la función de la hoja de trabajo CountA es un mejor enfoque. Sin embargo, en mi caso específico, no quiero querer anular una celda, incluso si el cambio es solo un cambio de formato. ¡Gracias por la aclaración! –

4

Trabajo con VSTO y Excel por un tiempo, a un nivel muy intenso, así que espero poder compartir cosas que he aprendido con el paso del tiempo con usted.

Según la información que ha proporcionado, le recomiendo que realice una conversión a una matriz de objetos y trabaje con esa información. Básicamente es posible acceder a los valores como:

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

arrayValues ​​es una matriz 2D ([fila, columna]). Excel rellena la matriz sorprendentemente rápido y, por supuesto, las operaciones en la matriz serán muy efectivas (no se preocupe por el rendimiento del boxeo, NO es un problema, créanme).

HTH, James

+0

Gracias James, Estoy trabajando en un complemento de VSTO para sobresalir y, a menudo, se topan con problemas que pueden ser respondidos rápidamente por alguien que los conoce, pero que consumen mucho tiempo en Internet. ¡Me aseguraré de hacer un mayor uso de stackoverflow ya que hay tantos expertos de VSTO aquí! –

+0

@ coder4life, ¿sabes si hay una forma de hacer la misma obtención "masiva" de propiedades como el color de la celda? He usado un método como el que describió para los valores desde hace meses, pero todavía tengo que encontrar una manera de poder buscar todos los colores (rango.Interior.Color) sin ir a filas, col. por col. ¡Y es dolorosamente lento! ¡Gracias! –

+0

En realidad, abrí un hilo nuevo para esta pregunta de captación de colores, solo para que sea más fácil de encontrar para otras personas, en lugar de mirar a través de los comentarios. La URL es [http://stackoverflow.com/questions/8451511/vsto-getting-excel-cell-properties-in-bulk](http://stackoverflow.com/questions/8451511/vsto-getting-excel-cell -propiedades-en-bulto) –

0

¿Qué tal?

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

Ejemplo llamada

bool isFirstEmpty = IsSheetEmpty(1); 
Cuestiones relacionadas