В VSTO Excel, как обнаружить данные в ячейках? - PullRequest
7 голосов
/ 27 февраля 2010

Мне было интересно, знает ли кто-нибудь, как быстро определить, есть ли данные в данном рабочем листе или нет, фактически не просматривая все строки / столбцы рабочего листа, чтобы выяснить это.

Я пишу импортер, который будет импортировать данные прямо в активную рабочую таблицу (если она не была изменена) или создать новую рабочую таблицу и импортировать в нее. В настоящее время я перебираю весь лист, и в моем импорте есть заметное время задержки.

Буду признателен за любую помощь в этом вопросе. Спасибо!

Ответы [ 5 ]

13 голосов
/ 27 февраля 2010

Чтобы избежать зацикливания и воспользоваться почти мгновенной скоростью выполнения, вы можете использовать метод Excel.WorksheetFunction.CountA, который возвращает тот же результат, что и функция листа = CountA ().

Предполагая, что ваша ссылка на Excel.Application называется «excelApp», а ваша ссылка на Excel.Worksheet - «рабочая таблица», вы можете использовать код, подобный следующему в 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.
}

В C # 3.0 и ниже он более многословен, потому что вы должны явно указать отсутствующие необязательные аргументы:

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

Я думаю, что это должно сделать это для вас!

Mike

4 голосов
/ 03 марта 2010

Я работаю с VSTO и Excel в течение некоторого времени, на очень интенсивном уровне, поэтому я надеюсь, что смогу поделиться с вами тем, чему научился за время.

Исходя из предоставленной вами информации, я бы рекомендовал привести к массиву объектов и вместо этого работать с этой информацией. По сути, вы получите доступ к значениям как:

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

arrayValues ​​- это двумерный массив ([строка, столбец]). Excel заполняет массив невероятно быстро, и, конечно, операции над массивом будут очень производительными (не беспокойтесь о производительности бокса, это НЕ проблема, поверьте мне).

НТН, Джеймс

0 голосов
/ 12 мая 2014

Как насчет?

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

Пример вызова

bool isFirstEmpty = IsSheetEmpty(1);
0 голосов
/ 28 февраля 2010

Я нашел следующее решение, которое также является мгновенным, но я не уверен, насколько оно точное ... оно уже прошло все мои испытания.

Вот для тех, кто хочет знать:

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
}

Полагаю, это намного проще, чем взрывать буфер обмена каждый раз, когда я проверяю или подсчитываю все непустые ячейки на листе. Спасибо, Микаэль и Майк, я ценю оба ваших ответа.

0 голосов
/ 27 февраля 2010

Это должно быть довольно быстро:

    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;
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...