Excel vba цикл до первой пустой строки

 

Excel-Starter

Пользователь

Сообщений: 33
Регистрация: 21.09.2015

#1

29.10.2015 14:26:09

Добрый день.

Имеется следующий (записанный средствами Excel) макрос:

Скрытый текст

В нем записаны «проходы» для первых двух строк таблицы, по которым он работает (выполняет одни и те же действия для каждой из заданных строк). Как оптимизировать его таким образом, чтоб скрипт был по-короче (например с использованием FOR TO для подстановки номеров строк (отмечены красным)) и «обрабатывал» все строки, дойдя до первой пустой строки (строки постоянно дополняются, сейчас первыми пустыми явяются строки A270:F270).
(действия для всех строк одинаковы, единственное что меняется, если вбивать макрос вручную, это отмеченные красным ячейки (т.е. A1:F1 / A2:F2 / A3:F3 и т.п. и  G1/G2/G3 и т.п.).

Заранее спасибо!

Изменено: Excel-Starter29.10.2015 22:17:26

 

Hugo

Пользователь

Сообщений: 23249
Регистрация: 22.12.2012

Для начала уберите все строки с ActiveWindow.ScrollColumn- невозможно ведь читать код!…

 

Пытливый

Пользователь

Сообщений: 4586
Регистрация: 22.12.2012

#3

29.10.2015 14:35:37

сначала определяем номер последней заполненной строки на листе:

Код
I=cells(rows.count,1).end(xlUp).row

потом гоняем цикл для заполненных строк

Код
For J = 1 to I
'...какие-то действия
Next J

копирование и вставку можно без использования Select
например, копируем диапазон с переменной строкой и от А до F в G

Код
For J = 1 to I
Range(cells(J, "A"), cells(J, "F").Copy Cells(J, G)
Next J

Кому решение нужно — тот пример и рисует.

 

Excel-Starter

Пользователь

Сообщений: 33
Регистрация: 21.09.2015

#4

29.10.2015 15:35:07

Hugo, убрал

Пытливый, заменил:

Скрытый текст

выдается ошибка.

Изменено: Excel-Starter29.10.2015 16:34:57

 

Пытливый

Пользователь

Сообщений: 4586
Регистрация: 22.12.2012

1. На какой строке выдается ошибка?
2. Переменная для цикла j. В адресе ячеек используете J. Почему?

P.S. По-моему, гораздо проще было набросать файл-пример, описать свои хотелки и местные корифеи давно бы написали компактный макрос под ваши задачи.

Кому решение нужно — тот пример и рисует.

 

Excel-Starter

Пользователь

Сообщений: 33
Регистрация: 21.09.2015

#6

29.10.2015 15:53:12

Ошибка в строке:
Range(cells(J, «A»), cells(J, «F»).Copy Cells(J, G)
Брал ее из кода в Вашем сообщении

Код
For J = 1 to I
Range(cells(J, "A"), cells(J, "F").Copy Cells(J, G)
Next J
 

Hugo

Пользователь

Сообщений: 23249
Регистрация: 22.12.2012

ActiveWindow.SmallScroll Down:=-30
убрать, G взять в кавычки. Для начала, дальше не вникал.

 

Пытливый

Пользователь

Сообщений: 4586
Регистрация: 22.12.2012

Cells(J, «G») кавычки вокруг G поставьте.

Кому решение нужно — тот пример и рисует.

 

Не помогло:
Compile Error: Expected List Separator or )

Range(cells(J, «A»), cells(J, «F»).Copy Cells(j, «G»)

 

Пытливый

Пользователь

Сообщений: 4586
Регистрация: 22.12.2012

я уже написал, переменная для цикла = j (или, если хотите J)
Она потом используется для адресации ячейки.
НЕЛЬЗЯ в одном месте писать j, а в другом J — для программы это РАЗНЫЕ вещи.
Range(cells(J, «A»), cells(J, «F»)).Copy Cells(J, «G»)

p.s. Файл с внятным описанием что надо сделать не хотите показать? Давно б уж все решили…

Кому решение нужно — тот пример и рисует.

 

Hugo

Пользователь

Сообщений: 23249
Регистрация: 22.12.2012

#11

29.10.2015 16:59:05

Цитата
Excel-Starter написал: Expected List Separator or )

пишет ведь что скобки не хватает.

 

Прикладываю упрощенный пример

Прикрепленные файлы

  • primer.xlsm (13.31 КБ)

Изменено: Excel-Starter29.10.2015 17:29:57

 

Hugo
Скобку добавлял — не помогает…

 

Пытливый

Пользователь

Сообщений: 4586
Регистрация: 22.12.2012

в примере ОЧЕНЬ бы хорошо написать — вот есть, вот что надо, чтобы было.
А то — ну таблица. И?

Кому решение нужно — тот пример и рисует.

 

yoozhik

Пользователь

Сообщений: 239
Регистрация: 01.01.1970

записанный макрос по двум строкам в итоге проставляет в столбец G количество значений, больших 50. К чему такие сложности?…может просто протянуть формулу?

 

Hugo

Пользователь

Сообщений: 23249
Регистрация: 22.12.2012

#16

29.10.2015 18:22:35

Цитата
Excel-Starter написал: Скобку добавлял — не помогает…

Очевидно не туда добавляли. Всем помогает, Вам не помогает…

 
Пытливый

Надо чтоб после запуска макроса подтсавлялись значения из ячеек А1-F1 в ячейки ВJ1-ВJ6 , далее получившееся в результате этого значение из ячейки BK1 копировалось в ячейку G1,
далее все повторяется со второй строкой:
после запуска макроса подтсавлялись значения из ячеек А2-F2 в ячейки ВJ1-ВJ6 , далее получившееся в результате этого значение из ячейки BK1 копировалось в ячейку G2,
и так далее, до момента, когда следующая строка оказывается пустой.

yoozhik

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

 

Пытливый

Пользователь

Сообщений: 4586
Регистрация: 22.12.2012

#18

29.10.2015 18:53:59

Не обязательно переписывать все в другой диапазон, там считать количество значений = 0 и потом переписывать результат в нужное место.
Можно все делать в макросе:

Код
Sub t58()
Dim lngI As Long
    For lngI = 1 To Cells(Rows.Count, 1).End(xlUp).Row 'от первой строки до последней заполненной
'в ячейку G соответствующей строки пишем результат работы функции СЧЕТЕСЛИ соответствующего диапазона и условия.
        Range("G" & lngI) = Application.WorksheetFunction.CountIf(Range("A" & lngI & ":F" & lngI), 0) 
    Next lngI
End Sub

Кому решение нужно — тот пример и рисует.

 
Пытливый

В исходной таблице такое простое решение не годится, там обязательно нужно переписывать значения, иначе не посчитается результат в ячейке BK1

 

Пытливый

Пользователь

Сообщений: 4586
Регистрация: 22.12.2012

#20

29.10.2015 19:11:39

Ок. :)

Код
Sub t59()
Dim lngI As Long
    For lngI = 1 To Cells(Rows.Count, 1).End(xlUp).Row
'транспонируем значение диапазона А:F соответствующей строки
        Range("bj1:bj6").FormulaArray = "=TRANSPOSE(A" & lngI & ":F" & lngI & ")"
'тащим результат в G соответствующей строки
        Range("G" & lngI) = Range("BK1")
    Next lngI
End Sub

Изменено: Пытливый29.10.2015 19:11:52

Кому решение нужно — тот пример и рисует.

 

Excel-Starter

Пользователь

Сообщений: 33
Регистрация: 21.09.2015

#21

29.10.2015 19:56:15

Пытливый

Благодарю! Выглядет — оптимально, но не срабатывает. Прерывается на строке

Код
Range("G" & lngI) = Range("BK1")

Прерывается на заполнении то 48, то 40, то 34, то 15 строки (каждый раз по-разному)

Изменено: Excel-Starter29.10.2015 20:42:56

 

Вот версия таблицы, более похожая на финальную. Скрипт доходит до 15-60 строки и прерывается…

 

Excel-Starter

Пользователь

Сообщений: 33
Регистрация: 21.09.2015

#23

30.10.2015 12:07:31

Довел код до такого вида: все равно не работает, где-то ошибка.

Код
Sub Makro()
    Dim i As Long
    For i = 1 To Range("AM1")
        Range("bj1:bj6").FormulaArray = "=TRANSPOSE(A" & i & ":F" & i & ")"
        Range("G" & i) = Range("BK1")
    Next i
End Sub

Изменено: Excel-Starter30.10.2015 14:48:24

 

Пытливый

Пользователь

Сообщений: 4586
Регистрация: 22.12.2012

For i = 1 To Range(«AM1»)
Что в этой строке написано? От i = 1 до значения, содержащегося в AM1
Зачем? Бегать по циклу ж надо от первой строки до последней заполненной?

p.s. В примере с таблицей «более похожей на финальную» — 15 раз запускал макрос — все корректно отрабатывает, заполняет G до 260 строки без прерываний.
Может не в макросе проблема?

Изменено: Пытливый30.10.2015 14:52:45

Кому решение нужно — тот пример и рисует.

 
Пытливый

У меня вылазит ошибка

В финальной таблице каждый следующий подход требуется нажимать «Continue» для продолжения исполнения скрипта: для каждой строчки.

(B AM1 — ячейке находится номер последней заполненной строки)

Изменено: Excel-Starter30.10.2015 14:57:39

 

Пытливый

Пользователь

Сообщений: 4586
Регистрация: 22.12.2012

А вычисления на листе у вас в автоматическом режиме стоят?

Хотя… если нет — ну и что? тупо бы непересчитанные значения бы заполнялись…

Хм… даже не знаю пока в чем может быть причина…. думаю….

О!!!!!
А какие еще макросы есть в книге/на листе? Типа на изменение значения на листе?

Изменено: Пытливый30.10.2015 15:30:50

Кому решение нужно — тот пример и рисует.

 

Excel-Starter

Пользователь

Сообщений: 33
Регистрация: 21.09.2015

#27

30.10.2015 15:44:54

Пытливый

, больше никаких, без макросов.

Цикл Do While… Loop в VBA Excel, его синтаксис и описание отдельных компонентов. Примеры использования цикла Do While… Loop.

Цикл Do While… Loop в VBA Excel предназначен для повторения блока операторов пока выполняется заданное условие (возвращается значение True). Синтаксис этого цикла аналогичен синтаксису цикла Do Until… Loop, который повторяется до тех пор, пока условие не выполняется (возвращается значение False).

Синтаксис цикла Do While… Loop существует в двух вариантах, определяющих, когда проверяется условие.


Условие проверяется до выполнения операторов:

Do While condition

    [ statements ]

    [ Exit Do ]

    [ statements ]

Loop


Условие проверяется после выполнения операторов:

Do

    [ statements ]

    [ Exit Do ]

    [ statements ]

Loop While condition


В квадратных скобках указаны необязательные атрибуты цикла Do While… Loop.

Компоненты цикла Do While… Loop

Компонент Описание
condition Обязательный атрибут. Условие выполнения цикла. Выражение, возвращающее значение типа Boolean.
statements Необязательный* атрибут. Операторы вашего кода.
Exit Do Необязательный атрибут. Оператор выхода** из цикла до его окончания.

*Если не использовать в цикле свой код, смысл применения цикла теряется.

**Очень полезный оператор для цикла Do While… Loop, так как при некоторых обстоятельствах он может стать бесконечным. Если такой риск существует, следует предусмотреть возможность выхода из бесконечного цикла VBA с помощью оператора Exit Do.

Примеры циклов Do While… Loop

Простейшие циклы

Цикл Do While… Loop с условием до исполняемых операторов:

Sub test1()

Dim a As Byte

  Do While a < 10

    a = a + 1

  Loop

MsgBox a

End Sub

Цикл Do While… Loop с условием после исполняемых операторов:

Sub test2()

Dim a As Byte

  Do

    a = a + 1

  Loop While a < 10

MsgBox a

End Sub

В обоих случаях окно MsgBox выведет число 10. Когда значение переменной a будет равно 10, проверяемое условие выдаст значение False, и цикл будет остановлен.

Проход по строкам листа

У двух белок дупла расположены напротив друг друга. В каждом дупле по 100 шишек. В свободное время они бросают шишки в дупло напротив, попадают не всегда. Ниже, в таблице, указано количество шишек, брошенных каждой белкой, и сколько их попало в цель.

Дни Игрок Брошено Попало в цель
1 день Белка 1 15 6
1 день Белка 2 12 7
2 день Белка 1 14 8
2 день Белка 2 16 7
3 день Белка 1 20 9
3 день Белка 2 14 6
4 день Белка 1 26 10
4 день Белка 2 13 5
5 день Белка 1 17 4
5 день Белка 2 21 7

Исходя из этих данных необходимо узнать, сколько шишек осталось у Белки 1 в дупле. Для этого необходимо вычесть из 100 шишек количество выброшенных Белкой 1 и прибавить шишки, заброшенные в ее дупло Белкой 2. Вычисления начинаем со второй строки (в первой заголовки) и в условии для цикла Do While… Loop указываем «первая ячейка текущей строки не является пустой». Таблица должна начинаться с первой ячейки рабочего листа «A1», и под ней, как минимум, одна строка должна быть пустой, точнее, первая ячейка этой строки.

Sub test3()

Dim i As Long, n As Long

i = 2

n = 100

  Do While Cells(i, 1) <> «»

    If Cells(i, 2) = «Белка 1» Then

      n = n Cells(i, 3)

    Else

      n = n + Cells(i, 4)

    End If

    i = i + 1

  Loop

MsgBox n

End Sub

Результат, выведенный в информационном сообщении MsgBox, будет равен 40. Вы можете скопировать таблицу на рабочий лист книги Excel и поэкспериментировать с кодом VBA.

Бесконечный цикл и Exit Do

Пример бесконечного цикла:

Sub test4()

Dim a As Byte

  Do While a < 10

  a = a + 1

    If a = 9 Then

      a = 0

    End If

  Loop

End Sub

При запуске этой процедуры цикл Do While… Loop начинает выполняться бесконечно. Мне приходилось останавливать бесконечные циклы VBA в Excel 2000 и Excel 2016. В Excel 2000 помогло сочетание клавиш Ctrl+Break, а в Excel 2016 при закрытии редактора VBA крестиком появляется окно:

Информационное окно «Microsoft Excel не отвечает»

Информационное окно «Microsoft Excel не отвечает»

Ожидать отклика программы нет смысла, поэтому нажимаем «Перезапустить программу» или «Закрыть программу».

Совет: перед запуском процедуры с циклом Do While… Loop, который может стать бесконечным, обязательно сохраните книгу, иначе, при принудительном закрытии редактора VBA ваши изменения будут утеряны. Кроме того, при принудительном закрытии редактора VBA, Excel может отключить макросы. Включите их в окне «Центр управления безопасностью», открыть которое можно по ссылке «Безопасность макросов» на ленте в разделе «Разработчик». Подробнее о включении макросов в разных версиях Excel читайте в статье: Как разрешить выполнение макросов в Excel?.

Пример использования оператора Exit Do:

Sub test5()

Dim a As Byte, n As Long

  Do While a < 10

  a = a + 1

  n = n + 1

    If a = 9 Then

      a = 0

    End If

    If n = 1000 Then

      Exit Do

    End If

  Loop

MsgBox n

End Sub

Когда число итераций цикла дойдет до 1000, он будет завершен, и информационное сообщение MsgBox выведет на экран число повторений цикла Do While… Loop из этого примера.


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

Прокрутите строки до пустого с помощью VBA


стрелка синий правый пузырь Прокрутите строки до пустого с помощью VBA

1. Нажмите Alt + F11 ключи для включения Microsoft Visual Basic для приложений окно.

2. Нажмите Вставить > Модулии вставьте приведенный ниже код в пустой скрипт.

VBA: цикл до пустого

Sub Test1()
'UpdatebyExtendoffice20161222
      Dim x As Integer
      Application.ScreenUpdating = False
      ' Set numrows = number of rows of data.
      NumRows = Range("A1", Range("A1").End(xlDown)).Rows.Count
      ' Select cell a1.
      Range("A1").Select
      ' Establish "For" loop to loop "numrows" number of times.
      For x = 1 To NumRows
         ' Insert your code here.
         ' Selects cell down 1 row from active cell.
         ActiveCell.Offset(1, 0).Select
      Next
      Application.ScreenUpdating = True
End Sub

цикл документов до пустого 1

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

3. Нажмите F5 чтобы начать цикл по столбцу, курсор остановится на первой встреченной пустой ячейке.
цикл документов до пустого 2

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

Sub LoopThroughUntilBlanks()
'UpdatebyExtendoffice20161222
      ' Select cell A2, *first line of data*.
      Dim xrg As Range
      On Error Resume Next
      Set xrg = Application.InputBox _
        (Prompt:="first cell select..", Title:="Kutools for Excel", Type:=8)
      xrg.Cells(1, 1).Select
      ' Set Do loop to stop when two consecutive empty cells are reached.
      Application.ScreenUpdating = False
      Do Until IsEmpty(ActiveCell) And IsEmpty(ActiveCell.Offset(1, 0))
         ' Insert your code here.
         '
         ' Step down 2 rows from present location.
         ActiveCell.Offset(2, 0).Select
      Loop
      Application.ScreenUpdating = False
End Sub

Затем вам нужно выбрать первую ячейку, из которой вы хотите выполнить цикл в Kutools for Excel диалоговое окно, нажмите OK, затем курсор останавливается в первых непрерывных пустых ячейках.



Лучшие инструменты для работы в офисе

Kutools for Excel Решит большинство ваших проблем и повысит вашу производительность на 80%

  • Снова использовать: Быстро вставить сложные формулы, диаграммы и все, что вы использовали раньше; Зашифровать ячейки с паролем; Создать список рассылки и отправлять электронные письма …
  • Бар Супер Формулы (легко редактировать несколько строк текста и формул); Макет для чтения (легко читать и редактировать большое количество ячеек); Вставить в отфильтрованный диапазон
  • Объединить ячейки / строки / столбцы без потери данных; Разделить содержимое ячеек; Объединить повторяющиеся строки / столбцы… Предотвращение дублирования ячеек; Сравнить диапазоны
  • Выберите Дубликат или Уникальный Ряды; Выбрать пустые строки (все ячейки пустые); Супер находка и нечеткая находка во многих рабочих тетрадях; Случайный выбор …
  • Точная копия Несколько ячеек без изменения ссылки на формулу; Автоматическое создание ссылок на несколько листов; Вставить пули, Флажки и многое другое …
  • Извлечь текст, Добавить текст, Удалить по позиции, Удалить пробел; Создание и печать промежуточных итогов по страницам; Преобразование содержимого ячеек в комментарии
  • Суперфильтр (сохранять и применять схемы фильтров к другим листам); Расширенная сортировка по месяцам / неделям / дням, периодичности и др .; Специальный фильтр жирным, курсивом …
  • Комбинируйте книги и рабочие листы; Объединить таблицы на основе ключевых столбцов; Разделить данные на несколько листов; Пакетное преобразование xls, xlsx и PDF
  • Более 300 мощных функций. Поддерживает Office/Excel 2007-2021 и 365. Поддерживает все языки. Простое развертывание на вашем предприятии или в организации. Полнофункциональная 30-дневная бесплатная пробная версия. 60-дневная гарантия возврата денег.

вкладка kte 201905


Вкладка Office: интерфейс с вкладками в Office и упрощение работы

  • Включение редактирования и чтения с вкладками в Word, Excel, PowerPoint, Издатель, доступ, Visio и проект.
  • Открывайте и создавайте несколько документов на новых вкладках одного окна, а не в новых окнах.
  • Повышает вашу продуктивность на 50% и сокращает количество щелчков мышью на сотни каждый день!

офисный дно

Комментарии (7)


Оценок пока нет. Оцените первым!

I need to find the first blank row in a workbook and write information to (row, 1) and (row, 2). I think I’m currently pretty stuck…

Function WriteToMaster(num, path) As Boolean

'Declare variables
Dim xlApp As Excel.Application
Dim wb As Workbook
Dim ws As Worksheet
Dim infoLoc As Integer

Set xlApp = New Excel.Application

Set wb = xlApp.Workbooks.Open("PATH OF THE DOC")
Set ws = wb.Worksheets("Sheet1")

'Loop through cells, looking for an empty one, and set that to the Num
Cells(1, 1).Select
For Each Cell In ws.UsedRange.Cells
    If Cell.Value = "" Then Cell = Num
    MsgBox "Checking cell " & Cell & " for value."
Next


'Save, close, and quit
wb.Save
wb.Close
xlApp.Quit

'Resets the variables
Set ws = Nothing
Set wb = Nothing
Set xlApp = Nothing

Thanks so much for any help.

asked Sep 19, 2012 at 15:22

okapishomapi's user avatar

2

If you mean the row number after the last row that is used, you can find it with this:

Dim unusedRow As Long
unusedRow = Cells.SpecialCells(xlCellTypeLastCell).Offset(1, 0).Row

If you mean a row that happens to be blank with data after it… it gets more complicated.

Here’s a function I wrote which will give you the actual row number of the first row that is blank for the provided worksheet.

Function firstBlankRow(ws As Worksheet) As Long
'returns the row # of the row after the last used row
'Or the first row with no data in it
    Dim rw As Range
    For Each rw In ws.UsedRange.Rows
        If rw.Address = ws.Range(rw.Address).SpecialCells(xlCellTypeBlanks). _
            Address Then

                firstBlankRow = rw.Row
                Exit For
        End If
    Next
    If firstBlankRow = 0 Then
        firstBlankRow = ws.Cells.SpecialCells(xlCellTypeLastCell). _
                    Offset(1, 0).Row
    End If
End Function

Usage example: firstblankRow(thisworkbook.Sheets(1)) or pass any worksheet.

Edit: As ooo pointed out, this will error if there are no blank cells in your used range.

answered Sep 19, 2012 at 15:35

Daniel's user avatar

DanielDaniel

13k2 gold badges36 silver badges60 bronze badges

11

I would have done it like this. Short and sweet :)

Sub test()
Dim rngToSearch As Range
Dim FirstBlankCell As Range
Dim firstEmptyRow As Long

Set rngToSearch = Sheet1.Range("A:A")
    'Check first cell isn't empty
    If IsEmpty(rngToSearch.Cells(1, 1)) Then
        firstEmptyRow = rngToSearch.Cells(1, 1).Row
    Else
        Set FirstBlankCell = rngToSearch.FindNext(After:=rngToSearch.Cells(1, 1))
        If Not FirstBlankCell Is Nothing Then
            firstEmptyRow = FirstBlankCell.Row
        Else
            'no empty cell in range searched
        End If
    End If
End Sub

Updated to check if first row is empty.

Edit: Update to include check if entire row is empty

Option Explicit

Sub test()
Dim rngToSearch As Range
Dim firstblankrownumber As Long

    Set rngToSearch = Sheet1.Range("A1:C200")
    firstblankrownumber = FirstBlankRow(rngToSearch)
    Debug.Print firstblankrownumber

End Sub

Function FirstBlankRow(ByVal rngToSearch As Range, Optional activeCell As Range) As Long
Dim FirstBlankCell As Range

    If activeCell Is Nothing Then Set activeCell = rngToSearch.Cells(1, 1)
    'Check first cell isn't empty
    If WorksheetFunction.CountA(rngToSearch.Cells(1, 1).EntireRow) = 0 Then
        FirstBlankRow = rngToSearch.Cells(1, 1).Row
    Else

        Set FirstBlankCell = rngToSearch.FindNext(After:=activeCell)
        If Not FirstBlankCell Is Nothing Then

            If WorksheetFunction.CountA(FirstBlankCell.EntireRow) = 0 Then
                FirstBlankRow = FirstBlankCell.Row
            Else
                Set activeCell = FirstBlankCell
                FirstBlankRow = FirstBlankRow(rngToSearch, activeCell)

            End If
        Else
            'no empty cell in range searched
        End If
    End If
End Function

answered Sep 19, 2012 at 16:52

1

Update

Inspired by Daniel’s code above and the fact that this is WAY! more interesting to me now then the actual work I have to do, i created a hopefully full-proof function to find the first blank row in a sheet. Improvements welcome! Otherwise, this is going to my library :)
Hopefully others benefit as well.

    Function firstBlankRow(ws As Worksheet) As Long
'returns the row # of the row after the last used row
'Or the first row with no data in it

    Dim rngSearch As Range, cel As Range

    With ws

        Set rngSearch = .UsedRange.Columns(1).Find("") '-> does blank exist in the first column of usedRange

        If Not rngSearch Is Nothing Then

            Set rngSearch = .UsedRange.Columns(1).SpecialCells(xlCellTypeBlanks)

            For Each cel In rngSearch

                If Application.WorksheetFunction.CountA(cel.EntireRow) = 0 Then

                    firstBlankRow = cel.Row
                    Exit For

                End If

            Next

        Else '-> no blanks in first column of used range

            If Application.WorksheetFunction.CountA(Cells(.Rows.Count, 1).EntireRow) = 0 Then '-> is the last row of the sheet blank?

                '-> yeap!, then no blank rows!
                MsgBox "Whoa! All rows in sheet are used. No blank rows exist!"


            Else

                '-> okay, blank row exists
                firstBlankRow = .UsedRange.SpecialCells(xlCellTypeBlanks).Row + 1

            End If

        End If

    End With

End Function

Original Answer

To find the first blank in a sheet, replace this part of your code:

Cells(1, 1).Select
For Each Cell In ws.UsedRange.Cells
    If Cell.Value = "" Then Cell = Num
    MsgBox "Checking cell " & Cell & " for value."
Next

With this code:

With ws

    Dim rngBlanks As Range, cel As Range

    Set rngBlanks = Intersect(.UsedRange, .Columns(1)).Find("")

    If Not rngBlanks Is Nothing Then '-> make sure blank cell exists in first column of usedrange
        '-> find all blank rows in column A within the used range
        Set rngBlanks = Intersect(.UsedRange, .Columns(1)).SpecialCells(xlCellTypeBlanks)

        For Each cel In rngBlanks '-> loop through blanks in column A

            '-> do a countA on the entire row, if it's 0, there is nothing in the row
            If Application.WorksheetFunction.CountA(cel.EntireRow) = 0 Then
                num = cel.Row
                Exit For
            End If

        Next
    Else

        num = usedRange.SpecialCells(xlCellTypeLastCell).Offset(1).Row                 

    End If


End With

answered Sep 19, 2012 at 15:37

Scott Holtzman's user avatar

Scott HoltzmanScott Holtzman

27k5 gold badges36 silver badges72 bronze badges

11

I know this is an older thread however I needed to write a function that returned the first blank row WITHIN a range. All of the code I found online actually searches the entire row (even the cells outside of the range) for a blank row. Data in ranges outside the search range was triggering a used row. This seemed to me to be a simple solution:

Function FirstBlankRow(ByVal rngToSearch As Range) As Long
   Dim R As Range
   Dim C As Range
   Dim RowIsBlank As Boolean

   For Each R In rngToSearch.Rows
      RowIsBlank = True
      For Each C In R.Cells
         If IsEmpty(C.Value) = False Then RowIsBlank = False
      Next C
      If RowIsBlank Then
         FirstBlankRow = R.Row
         Exit For
      End If
   Next R
End Function

answered Mar 7, 2014 at 17:31

user3393711's user avatar

ActiveSheet.Range("A10000").End(xlup).offset(1,0).Select

SheetJS's user avatar

SheetJS

22.3k12 gold badges64 silver badges75 bronze badges

answered Oct 18, 2013 at 19:24

Josh Z's user avatar

very old thread but .. i was lookin for an «easier»… a smaller code

i honestly dont understand any of the answers above :D
— i´m a noob

but this should do the job. (for smaller sheets)

Set objExcel = CreateObject("Excel.Application")
objExcel.Workbooks.Add

reads every cell in col 1 from bottom up and stops at first empty cell

intRow = 1
Do until objExcel.Cells(intRow, 1).Value = ""
   intRow = intRow + 1
Loop

then you can write your info like this

objExcel.Cells(intRow, 1).Value = "first emtpy row, col 1"
objExcel.Cells(intRow, 2).Value = "first emtpy row, col 2"

etc…

and then i recognize its an vba thread … lol

answered Jul 3, 2014 at 15:43

ultr4low's user avatar

1

Very old thread but a simpler take :)

Sub firstBlank(c) 'as letter
    MsgBox (c & Split(Range(c & ":" & c).Find("", LookIn:=xlValues).address, "$")(2))
End Sub
Sub firstBlank(c) 'as number
    cLet = Split(Cells(1, c).address, "$")(1)
    MsgBox (cLet & Split(Range(cLet & ":" & cLet).Find("", LookIn:=xlValues).address, "$")(2))
End Sub

answered Feb 3, 2017 at 2:22

quantum285's user avatar

quantum285quantum285

1,0322 gold badges11 silver badges22 bronze badges

Function firstBlankRow() As Long
Dim emptyCells As Boolean

    For Each rowinC In Sheet7.Range("A" & currentEmptyRow & ":A5000")   ' (row,col)

        If rowinC.Value = "" Then
            currentEmptyRow = rowinC.row
            'firstBlankRow = rowinC.row 'define class variable to simplify computing complexity for other functions i.e. no need to call function again
            Exit Function   
        End If
    Next

End Function

answered Feb 1, 2018 at 22:15

user8453101's user avatar

На чтение 13 мин. Просмотров 26.4k.

VBA While Loop

Рамакришна, Источники индийской мудрости

Сейчас … мы идем по кругу

Эта статья содержит полное руководство по VBA Do While и VBA While Loops. (Если вы ищете информацию о циклах VBA For и For Each, перейдите сюда)

Цикл VBA While существует, чтобы сделать его совместимым со старым кодом. Однако Microsoft рекомендует использовать цикл Do Loop, поскольку он более «структурирован и гибок». Оба этих цикла рассматриваются в этом посте.

Для быстрого ознакомления с этими циклами перейдите к таблице быстрого руководства ниже.

Если вы ищете что-то конкретное, вы можете посмотреть содержание ниже.

Содержание

  1. Краткое руководство по VBA While Loops
  2. Введение
  3. Цикл For против цикла Do While
  4. Условия
  5. Формат цикла Do
  6. Цикл Exit Do
  7. While Wend
  8. Бесконечный цикл
  9. Использование функций Worksheet вместо циклов
  10. Резюме

Краткое руководство по VBA While Loops

Формат цикла Описание Пример
Do While … Loop Запускается 0 или более раз, пока условие выполняется Do While result = «Верно»
Loop
Do … Loop While Запускается 1 или более раз, пока условие выполняется Do 
Loop While result = «Верно»
Do Until … Loop Запускается 0 или более раз, пока условие не будет выполнено Do Until result <> «Верно»
Loop
Do … Until Loop Запускается 1 или более раз, пока условие не будет выполнено Do 
Loop Until result <> «Верно»
While … Wend
R
Запускается 0 или более раз, пока условие истинно.
Примечание: этот цикл считается устаревшим.
While result = «Верно»
Wend
Exit the Do Loop Завершает Do Do While i < 10
   i = GetTotal
   If i < 0 Then
      Exit Do
   End If
Loop

Введение

Если вы никогда ранее не использовали циклы, тогда вы можете прочитать «Что такое циклы и зачем они вам нужны» из моего поста в журнале For Loop.

Я собираюсь сосредоточиться в основном на Do Loop в этой статье. Как я упоминал выше, мы видели, что цикл While Wend считается устаревшим. Для полноты информации я все равно его включил в эту статью.

Итак, во-первых, зачем нам нужны циклы Do While, когда у нас уже есть циклы For?

Цикл For против цикла Do While

Когда мы используем цикл For Loop, мы заранее знаем, сколько раз мы хотим его запустить. Например, мы можем захотеть запустить цикл один раз для каждого элемента в коллекции, массиве или словаре.

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

' запускается 5 раз
For i = 1 To 5

' запускается один раз для каждого элемента коллекции
For i = 1 To coll.Count

' запускается один раз для каждого элемента в arr
For i = LBound(arr) To coll.lbound(arr)

' запускается один раз для каждого значения от 1 до значения в lastRow
For i = 1 To lastRow

' запускается один раз для каждого элемента в коллекции
For Each s In coll

Цикл Do другой. Он работает:

  • В то время как условие верно
  • Пока условие не будет выполнено

Другими словами, количество циклов в большинстве случаев не имеет значения.

Итак, что такое условие и как мы их используем?

Условия

Условие — это утверждение, которое оценивается как истинное или ложное. Они в основном используются с операторами Loops и If. При создании условия вы используете такие знаки, как >, <, <>,> =, =.

Ниже приведены примеры условий

Условие Истина, когда…
x < 5 x меньше 5
x <= 5 x меньше либо равен 5
x > 5 x больше 5
x >= 5 x больше либо равен 5
x = 5 x равен 5
x <> 5 x не равен 5
x > 5 And x < 10 x больше 5 И меньше 10
x = 2 Or x >10 x равен 2 ИЛИ больше 10
Range(«A1») = «Иван» Ячейка A1 содержит текст «Иван»
Range(«A1») <> «Иван» Ячейка A1 не содержит текст «Иван»

Вы могли заметить x = 5 как условие. Его следует путать с х = 5, при использовании в качестве назначения.

Например

' означает: значение 6 будет храниться в х
x = 6

' означает: х равен 6?
If x = 6

' означает: х равен 6?
Do While x = 6

В следующей таблице показано, как «=» используется в условиях и назначениях.

Использование «=» Тип Имеется в виду
Loop Until x = 5 Условие x равен 5?
Do While x = 5 Условие x равен 5?
If x = 5 Then Условие x равен 5?
For x = 1 To 5 Присваивание Установите значение x = 1, затем = 2 и т.д.
x = 5 Присваивание Установите значение x=5
b = 6 = 5 Присваивание и
условие
Присвойте b
результату условия
6 = 5
x = MyFunc(5,6) Присваивание Присвойте х
значение,
возвращаемое
функцией

Формат цикла Do

Цикл Do можно использовать четырьмя способами, и это часто вызывает путаницу. Однако в каждом из этих четырех способов есть только небольшая разница.

Do всегда в начале первой строки, а Loop всегда в конце последней строки.

Мы можем добавить условие после любой строки.

Do [условие]
Loop

Do 
Loop [условие]

Условию предшествует While или Until, которое дает нам эти четыре возможности

Do While [условие]
Loop

Do Until [условие]
Loop

Do 
Loop While [условие]

Do 
Loop Until [условие]

Давайте посмотрим на некоторые примеры, чтобы прояснить это.

Примеры цикла Do

Представьте, что вы хотите, чтобы пользователь ввел список элементов. Каждый раз, когда пользователь вводит элемент, вы печатаете его в «Immediate Window». Когда пользователь вводит пустую строку, вы хотите, чтобы приложение закрывалось.

В этом случае цикл For не подойдет, поскольку вы не знаете, сколько элементов будет вводить пользователь. Пользователь может ввести пустую строку первым или с сотой попытки. Для этого типа сценария вы бы использовали цикл Do.

Следующий код показывает это

 Dim sCommand As String

    Do
        ' Получить пользовательский ввод
        sCommand = InputBox("Пожалуйста, введите элемент")

        ' Печать в Immediate Window (Ctrl + G для просмотра)
        Debug.Print sCommand

    Loop While sCommand <> ""

Код входит в цикл и продолжается до тех пор, пока не достигнет строки «Loop While». На этом этапе он проверяет, оценивается ли условие как истинное или ложное.

Если условие оценивается как ложное, то код выходит из цикла и продолжается.
Если условие оценивается как истинное, то код возвращается к строке Do и снова проходит через цикл.
Разница между наличием условия на линии Do и на линии Loop очень проста.

Когда условие находится в строке Do, цикл может вообще не работать. Так что он будет работать ноль или более раз.
Когда условие находится на линии Loop, цикл всегда будет запущен хотя бы один раз. Так что он будет запущен один или несколько раз.

В нашем последнем примере условие находится в строке Loop, потому что мы всегда хотим получить хотя бы одно значение от пользователя. В следующем примере мы используем обе версии цикла. Цикл будет выполняться, пока пользователь не введет букву «н».

Sub GetInput()

    Dim sCommand As String

    ' Условие в начале
    Do While sCommand <> "н"
        sCommand = InputBox("Пожалуйста, введите элемент для цикла 1")
    Loop

    ' Условие в конце
    Do
        sCommand = InputBox("Пожалуйста, введите элемент для цикла 2")
    Loop While sCommand <> "н"

End Sub

В приведенном выше примере оба цикла будут вести себя одинаково.

Однако, если мы установим для sCommand значение «н» до запуска цикла «Do While», код не войдет в цикл.

Sub GetInput2()

    Dim sCommand As String
    sCommand = "н"

    ' Цикл не будет работать, поскольку команда "н"
    Do Whilel sCommand <> "н"
        sCommand = InputBox("Пожалуйста, введите элемент для цикла 1")
    Loop

    ' Цикл все равно будет запущен хотя бы один раз
    Do
        sCommand = InputBox("Пожалуйста, введите элемент для цикла 2")
    Loop While sCommand <> "н"

End Sub

Второй цикл в вышеприведенном примере (то есть Loop While) всегда будет запускаться хотя бы один раз.

While против Until

При использовании Do Loop условию должно предшествовать Until или While.

Until и While, по сути, противоположны друг другу. Они используются в VBA аналогично тому, как они используются в английском языке.

Например:

  • Оставьте одежду, пока не пойдет дождь
  • Оставь одежду, пока не идет дождь

Другой пример:

  • Оставайся в постели, пока не станет светло
  • Оставайся в постели, пока темно

Еще один пример:

  • повторять, пока число не станет больше или равно десяти
  • повторить пока счет меньше десяти

Как видите, использование Until и While — это просто противоположный способ написания одного и того же условия.

Примеры Until и While

Следующий код показывает циклы «While» и «Until» рядом. Как видите, единственная разница в том, что условие полностью изменено.

Примечание: знаки <> означают «не равно».

Sub GetInput()

    Dim sCommand As String

    ' Условие в начале
    Do Until sCommand = "н"
        sCommand = InputBox("Пожалуйста, введите элемент для цикла 1")
    Loop

    Do While sCommand <> "н"
        sCommand = InputBox("Пожалуйста, введите элемент для цикла 1")
    Loop

    ' Условие в конце
    Do
        sCommand = InputBox("Пожалуйста, введите элемент для цикла 2")
    Loop Until sCommand = "н"

    Do
        sCommand = InputBox("Пожалуйста, введите элемент для цикла 2")
    Loop While sCommand <> "н"

End Sub
  • Первый цикл: запускается только в том случае, если sCommand не равен ‘н’.
  • Второй цикл: запускается только в том случае, если sCommand не равен ‘н’.
  • Третий цикл: будет запущен хотя бы один раз перед проверкой sCommand.
  • Четвертый цикл: будет запущен хотя бы один раз перед проверкой sCommand.

Пример: проверка объектов

Примером использования Until и While является проверка объектов. Когда объект не был назначен, он имеет значение Nothing.

Поэтому, когда мы объявляем переменную книги в следующем примере, она имеет значение Nothing, пока мы не назначим ее Workbook.

Противоположностью Nothing не является Nothing, что может сбить с толку.

Представьте, что у нас есть две функции: GetFirstWorkbook и GetNextWorkbook, которые возвращают некоторые объекты книги. Код будет печатать имя рабочей книги до тех пор, пока функции больше не вернут действительную рабочую книгу.

Вы можете увидеть пример кода здесь:

Dim wrk As Workbook
    Set wrk = GetFirstWorkbook()

    Do Until wrk Is Nothing
        Debug.Print wrk.Name
        Set wrk = GetNextWorkbook()
    Loop

Написание этого кода с использованием Do While было бы более запутанным, так как условие Not Is Nothing

Dim wrk As Workbook
    Set wrk = GetFirstWorkbook()

    Do While Not wrk Is Nothing
        Debug.Print wrk.Name
        Set wrk = GetNextWorkbook()
    Loop

Это делает код более понятным, и наличие четких условий — всегда хорошо. Честно говоря, разница маленькая, и выбор между «While» и «Until» действительно сводится к личному выбору.

Цикл Exit Do

Мы можем выйти из любого цикла Do с помощью оператора Exit Do.

Следующий код показывает пример использования Exit Do

Do While i < 1000
     If Cells(i,1) = "Найдено" Then 
         Exit Do
     End If
     i = i + 1
Loop 

В этом случае мы выходим из цикла Do Loop, если ячейка содержит текст «Найдено».

While Wend

Этот цикл в VBA, чтобы сделать его совместимым со старым кодом. Microsoft рекомендует использовать циклы Do, поскольку они более структурированы.

Из MSDN: «Оператор Do… Loop обеспечивает более структурированный и гибкий способ выполнения циклов».

Формат цикла VBA While Wend

Цикл VBA While имеет следующий формат:

While <Условие>
Wend

While Wend против Do

Разница между циклами VBA While и VBA Do заключается в следующем:

  1. While может иметь условие только в начале цикла.
  2. While не имеет версии Until.
  3. Не существует оператора для выхода из цикла While, как Exit For или Exit Do.

Условие для цикла VBA While такое же, как и для цикла VBA Do While. Два цикла в приведенном ниже коде работают точно так же.

Sub GetInput()

    Dim sCommand As String

    Do While sCommand <> "н"
        sCommand = InputBox("Пожалуйста, введите элемент для цикла 1")
    Loop

    While sCommand <> "н"
        sCommand = InputBox("Пожалуйста, введите элемент для цикла 2")
    Wend

End Sub

Бесконечный цикл

Даже если вы никогда не писали код в своей жизни, я уверен, что вы слышали фразу «Бесконечный цикл». Это цикл, в котором условие никогда не будет выполнено. Обычно это происходит, когда вы забыли обновить счетчик.

Следующий код показывает бесконечный цикл

Dim cnt As Long
    cnt = 1

    'это бесконечный цикл
    Do While cnt <> 5

    Loop

В этом примере cnt установлен в 1, но он никогда не обновляется. Поэтому условие никогда не будет выполнено — cnt всегда будет меньше 5.

В следующем коде cnt обновляется каждый раз, поэтому условие будет выполнено.

Dim cnt As Long
    cnt = 1

    Do While cnt <> 5
        cnt = cnt + 1
    Loop

Как вы можете видеть, использование For Loop безопаснее для подсчета, поскольку оно автоматически обновляет счет в цикле. Ниже приведен тот же цикл с использованием For.

Dim i As Long
    For i = 1 To 4

    Next i

Это явно лучший способ сделать это. Цикл For устанавливает начальное значение, условие и счет в одну строку.

Конечно, можно использовать бесконечный цикл, используя For — это потребует немного больше усилий 🙂

 Dim i As Long
    ' Бесконечный цикл
    For i = 1 To 4
        ' i никогда не достигнет 4
        i = 1
    Next i

Работа с бесконечным циклом

Когда у вас бесконечный цикл — VBA не выдаст ошибку. Ваш код будет продолжать работать, а редактор Visual Basic не будет отвечать.

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

Вы также можете выйти из цикла, убив процесс. Нажмите Ctrl + Shift + Esc. На вкладке Процессы найдите Excel / Microsoft Excel. Щелкните правой кнопкой мыши по этому и выберите «Завершить процесс». Это закроет Excel, и вы можете потерять часть работы — так что гораздо лучше использовать Ctrl + Break или его эквивалент.

Использование функций Worksheet вместо циклов

Иногда вы можете использовать функцию листа вместо цикла.

Например, представьте, что вы хотите добавить значения в список ячеек. Вы можете сделать это с помощью цикла, но было бы более эффективно использовать функцию таблицы Sum. Это быстрее и экономит много кода.

Использовать функции рабочего листа очень просто. Ниже приведен пример использования Sum и Count.

Sub WorksheetFunctions()

    Debug.Print WorksheetFunction.Sum(Range("A1:A10"))

    Debug.Print WorksheetFunction.Count(Range("A1:A10"))

End Sub

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

Sub SumWithLoop()

    Dim total As Long, count As Long
    Dim rg As Range
    For Each rg In Range("A1:A10")
        ' Total
        total = total + rg
        ' Count
        If rg <> "" Then
            count = count + 1
        End If
    Next rg

    Debug.Print total
    Debug.Print count

End Sub

Резюме

Цикл Do While

  • Цикл Do можно использовать 4 способами.
  • Его можно использовать в начале или в конце, Do While .. Loop, Do … Loop While
  • Может использоваться с Until в начале или в конце, Do Until .. Loop, Do … Loop Until
  • While и Until используют противоположные условия друг к другу.
  • Бесконечный цикл происходит, если ваше условие выхода никогда не будет выполнено.
  • Иногда использование функции рабочего листа более эффективно, чем использование цикла.

Цикл While Wend

  • Цикл Wend Wend устарел, и вы можете вместо этого использовать цикл Do.

Понравилась статья? Поделить с друзьями:
  • Excel vba цикл row
  • Excel vba цикл for по ячейкам
  • Excel vba цикл for для массива
  • Excel vba цикл for exit
  • Excel vba цикл do loop