Итерация через все ячейки в Excel VBA или VSTO 2005

Что такое NullPointerException?

Хорошим местом для начала является JavaDocs . Они охватывают это:

Брошено, когда приложение пытается использовать null в случае, когда требуется объект. К ним относятся:

  • Вызов метода экземпляра нулевого объекта.
  • Доступ или изменение поля нулевого объекта.
  • Выполнение длины null, как если бы это был массив.
  • Доступ или изменение слотов с нулевым значением, как если бы это был массив.
  • Бросать нуль, как если бы это было значение Throwable.

Приложения должны бросать экземпляры этого класса для указания других незаконных видов использования нулевого объекта.

blockquote>

Также, если вы попытаетесь использовать нулевую ссылку с synchronized, который также выдаст это исключение, за JLS :

SynchronizedStatement:
    synchronized ( Expression ) Block
  • В противном случае, если значение выражения равно null, NullPointerException.
blockquote>

Как это исправить?

Итак, у вас есть NullPointerException. Как вы это исправите? Возьмем простой пример, который выдает NullPointerException:

public class Printer {
    private String name;

    public void setName(String name) {
        this.name = name;
    }

    public void print() {
        printString(name);
    }

    private void printString(String s) {
        System.out.println(s + " (" + s.length() + ")");
    }

    public static void main(String[] args) {
        Printer printer = new Printer();
        printer.print();
    }
}

Идентифицирует нулевые значения

. Первый шаг - точно определить , значения которого вызывают исключение . Для этого нам нужно выполнить некоторую отладку. Важно научиться читать stacktrace . Это покажет вам, где было выбрано исключение:

Exception in thread "main" java.lang.NullPointerException
    at Printer.printString(Printer.java:13)
    at Printer.print(Printer.java:9)
    at Printer.main(Printer.java:19)

Здесь мы видим, что исключение выбрано в строке 13 (в методе printString). Посмотрите на строку и проверьте, какие значения равны нулю, добавив протоколирующие операторы или используя отладчик . Мы обнаруживаем, что s имеет значение null, а вызов метода length на него вызывает исключение. Мы видим, что программа перестает бросать исключение, когда s.length() удаляется из метода.

Трассировка, где эти значения взяты из

Затем проверьте, откуда это значение. Следуя вызовам метода, мы видим, что s передается с printString(name) в методе print(), а this.name - null.

Трассировка, где эти значения должны быть установлены

Где установлен this.name? В методе setName(String). С некоторой дополнительной отладкой мы видим, что этот метод вообще не вызывается. Если этот метод был вызван, обязательно проверьте порядок , что эти методы вызывают, а метод set не будет называться после методом печати. ​​

Этого достаточно, чтобы дать нам решение: добавить вызов printer.setName() перед вызовом printer.print().

Другие исправления

Переменная может иметь значение по умолчанию setName может помешать ему установить значение null):

private String name = "";

Либо метод print, либо printString может проверить значение null например:

printString((name == null) ? "" : name);

Или вы можете создать класс, чтобы name всегда имел ненулевое значение :

public class Printer {
    private final String name;

    public Printer(String name) {
        this.name = Objects.requireNonNull(name);
    }

    public void print() {
        printString(name);
    }

    private void printString(String s) {
        System.out.println(s + " (" + s.length() + ")");
    }

    public static void main(String[] args) {
        Printer printer = new Printer("123");
        printer.print();
    }
}

См. также:

Я все еще не могу найти проблему

Если вы попытались отладить проблему и до сих пор не имеете решения, вы можете отправить вопрос для получения дополнительной справки, но не забудьте включить то, что вы пробовали до сих пор. Как минимум, включите stacktrace в вопрос и отметьте важные номера строк в коде. Также попробуйте сначала упростить код (см. SSCCE ).

23
задан braX 29 May 2018 в 19:01
поделиться

9 ответов

Sub CheckValues1()
    Dim rwIndex As Integer
    Dim colIndex As Integer
    For rwIndex = 1 To 10
            For colIndex = 1 To 5
                If Cells(rwIndex, colIndex).Value <> 0 Then _
                    Cells(rwIndex, colIndex).Value = 0
            Next colIndex
    Next rwIndex
End Sub

Найденный этим отрывком на http://www.java2s.com/Code/VBA-Excel-Access-Word/Excel/Checksvaluesinarange10rowsby5columns.htm Это, кажется, довольно полезно как функция проиллюстрировать средства для контрольных чисел в ячейках заказанным способом.

Просто воображают его как являющийся 2-м своего рода Массивом и применяют ту же логику для цикличного выполнения через ячейки.

7
ответ дан betelgeuce 29 November 2019 в 00:50
поделиться

Если только необходимо посмотреть на ячейки, которые используются, можно использовать:

sub IterateCells()

   For Each Cell in ActiveSheet.UsedRange.Cells
      'do some stuff
   Next

End Sub

, который поразит все в диапазоне от A1 до последней ячейки с данными (нижняя часть самая правая ячейка)

57
ответ дан cori 29 November 2019 в 00:50
поделиться

Если Вы просто смотрите на значения ячеек, можно сохранить значения в массиве различного типа. Кажется, что получение значения элемента в массиве может быть намного быстрее, чем взаимодействие с Excel, таким образом, Вы видите, что некоторая разница в производительности использует массив всех значений ячеек по сравнению с повторным получением отдельных ячеек.

Dim ValArray as Variant
ValArray = Range("A1:IV" & Rows.Count).Value

Тогда можно получить значение ячейки только путем проверки ValArray (строка, столбец)

5
ответ дан JimmyPena 29 November 2019 в 00:50
поделиться

Можно использовать Для Каждого для итерации через все ячейки в определенном диапазоне.

Public Sub IterateThroughRange()

Dim wb As Workbook
Dim ws As Worksheet
Dim rng As Range
Dim cell As Range

Set wb = Application.Workbooks(1)
Set ws = wb.Sheets(1)
Set rng = ws.Range("A1", "C3")

For Each cell In rng.Cells
    cell.Value = cell.Address
Next cell

End Sub
3
ответ дан theo 29 November 2019 в 00:50
поделиться

Для VB или приложения C#, один способ сделать это - при помощи Office Interop. Это зависит, на которой версии Excel Вы работаете с.

For Excel 2003, эта статья MSDN является хорошим местом для запуска. Понимание Excel Object Model из Visual Studio 2005 Перспектива Разработчика

необходимо будет в основном сделать следующее:

  • Запускают приложение Excel.
  • Открывают рабочую книгу Excel.
  • Получают рабочий лист от рабочей книги по имени или индекса.
  • Выполняют итерации через все Ячейки в рабочем листе, которые были получены как диапазон.
  • Образец (непротестированная) выборка кода ниже для последнего шага.

    Excel.Range allCellsRng;
    string lowerRightCell = "IV65536";
    allCellsRng = ws.get_Range("A1", lowerRightCell).Cells;
    foreach (Range cell in allCellsRng)
    {
        if (null == cell.Value2 || isBlank(cell.Value2))
        {
          // Do something.
        }
        else if (isText(cell.Value2))
        {
          // Do something.
        }
        else if (isNumeric(cell.Value2))
        {
          // Do something.
        }
    }

For Excel 2007, попробуйте эта ссылка MSDN .

2
ответ дан Cory Engebretson 29 November 2019 в 00:50
поделиться

Существует несколько методов для выполнения этого, каждый из которых имеет преимущества и недостатки; Прежде всего Вы собираетесь должны иметь экземпляр объекта Рабочего листа, Приложения. ActiveSheet работает, если Вы просто хотите тот, пользователь смотрит на.

объект Рабочего листа имеет три свойства, которые могут привыкнуть к данным ячейки доступа (Ячейки, строки, Столбцы) и метод, который может использоваться для получения блока данных ячейки, (get_Range).

Диапазоны могут быть изменены и такой, но Вы, возможно, должны использовать свойства, упомянутые выше для обнаружения, где границы данных. Преимущество для Диапазона становится очевидным, когда Вы работаете с большими объемами данных, потому что дополнения VSTO размещаются вне границ самого приложения Excel, таким образом, все вызовы к Excel должны быть переданы через слой с издержками; получение Диапазона позволяет Вам получать/устанавливать все данные, которые Вы хотите в одном вызове, который может иметь огромные выигрыши в производительности, но это требует, чтобы Вы использовали явные детали вместо того, чтобы выполнить итерации посредством каждой записи.

Это сообщение форума MSDN шоу разработчик VB.Net, задающий вопрос о получении результатов Диапазона как массив

1
ответ дан TheXenocide 29 November 2019 в 00:50
поделиться

В основном можно циклично выполниться по Диапазону

, Добираются, лист

myWs = (Worksheet)MyWb.Worksheets[1];

Получают Диапазон, Вы интересуетесь тем, Если Вы действительно хотите проверить, что каждая ячейка использует пределы Excel

, Excel 2007 "Большая Сетка" увеличивает максимальное число строк на рабочий лист от 65 536 до более чем 1 миллиона и числа столбцов от 256 (IV) к 16 384 (XFD). отсюда http://msdn.microsoft.com/en-us/library/aa730921.aspx#Office2007excelPerf_BigGridIncreasedLimitsExcel

и затем цикл по диапазону

        Range myBigRange = myWs.get_Range("A1", "A256");

        string myValue;

        foreach(Range myCell in myBigRange )
        {
            myValue = myCell.Value2.ToString();
        }
1
ответ дан w4ik 29 November 2019 в 00:50
поделиться

В Excel VBA эта функция даст Вам содержание любой ячейки в любом рабочем листе.

Function getCellContent(Byref ws As Worksheet, ByVal rowindex As Integer, ByVal colindex As Integer) as String
    getCellContent = CStr(ws.Cells(rowindex, colindex))
End Function

Поэтому, если Вы хотите проверить значение ячеек, просто поместите функцию в цикл, дайте ему ссылку на рабочий лист, который Вы хотите и индекс строки и индекс столбца ячейки. Индекс строки и индекс столбца оба запускаются от 1, означая, что ячейка A1 будет ws. Ячейки (1,1) и так далее.

0
ответ дан Martin08 29 November 2019 в 00:50
поделиться

Мои навыки VBA немного ржавы, но это - общее представление о том, что я сделал бы.
самый легкий способ сделать это должно было бы выполнить итерации через цикл для каждого столбца:

public sub CellProcessing()
on error goto errHandler

    dim MAX_ROW as Integer   'how many rows in the spreadsheet
    dim i as Integer
    dim cols as String

    for i = 1 to MAX_ROW
        'perform checks on the cell here
        'access the cell with Range("A" & i) to get cell A1 where i = 1
    next i

exitHandler:
    exit sub
errHandler:
    msgbox "Error " & err.Number & ": " & err.Description
    resume exitHandler
end sub

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

  • Brisketeer
0
ответ дан 29 November 2019 в 00:50
поделиться
Другие вопросы по тегам:

Похожие вопросы: