Excel VBA: найти индексы строк пустых ячеек в заданном диапазоне - PullRequest
0 голосов
/ 02 декабря 2018

Можно ли написать макрос vba, который определяет, есть ли в данном диапазоне пустые ячейки и возвращает номер строки этой ячейки?

Я новичок в vba, и все, что мне удалось написать после поиска в Интернете, было что-то, что берет диапазон и окрашивает каждую пустую ячейку в нем красным:

Sub EmptyRed()
    If TypeName(Selection) <> "Range" Then Exit Sub
    For Each cell In Selection
        If IsEmpty(cell.Value) Then cell.Interior.Color = RGB(255, 0, 0)
    Next cell
End Sub 

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

Небольшая справочная информация: у меня очень большой файл (около 80 000 строк), который содержит много объединенных ячеек.Я хочу импортировать его в R с readxl.Readxl разделяет объединенные ячейки, помещает значение в первую ячейку разделения и NA во все остальные.Но совершенно пустой ячейке также будет присвоен NA, поэтому я подумал, что лучше всего выяснить, какие ячейки пусты в Excel, чтобы я знал, какие NA указывают на объединенную или пустую ячейку.Любые предложения о том, как решить эту проблему, очень приветствуются, спасибо!

Редактировать: Чтобы уточнить: В идеале я хочу объединить все ячейки в моем документе и заполнить каждую разделенную ячейку содержимым ранее объединенной ячейки.Но я нашел в сети макросы, которые должны были делать именно это, но они не работали с моим файлом, поэтому я подумал, что могу просто определить пустые ячейки и затем работать с ними в R. Обычно я не работаю с Excelпоэтому я очень мало знаю об этом, извините, если мой мыслительный процесс слишком сложен.

Ответы [ 5 ]

0 голосов
/ 02 декабря 2018

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

  • Циклически перебирая все ячейки в поле «Используемый диапазон» листа
  • Если объединено, удалите его и заполните заполненную область значением из ранее объединенной области.
  • Если не объединено, но пусто, соберитедля вывода адреса.

    Sub fillMerged()
    
        Dim r As Range, br As Range, mr As Range
    
        For Each r In ActiveSheet.UsedRange
            If r.Address <> r.MergeArea.Address Then
                'merged cells - unmerge and set value to all
                Set mr = r.MergeArea
                r.UnMerge
                mr.Value = mr.Cells(1).Value
            ElseIf IsEmpty(r) Then
                'unmerged blank cell
                If br Is Nothing Then
                    Set br = r
                Else
                    Set br = Union(br, r)
                End If
            End If
        Next r
    
        Debug.Print "blank cells: " & br.Address(0, 0)
    
    End Sub
    
0 голосов
/ 02 декабря 2018

Есть несколько способов:

Sub EmptyRed()

Dim rgn,targetrgn as range 
Dim ads as string ‘ return rgn address
Set targetrgn= ‘ your selection
For Each rgn In Targetrgn
    If IsEmpty(rgn.Value) Then 
        ‘1. Use address function, and from there you can stripe out the column and row
        Ads=application.worksheetfunction.addres(cell,1)’ the second input control the address format, w/o $
        ‘2. Range.row & range.column
       Ads=“row:” & rgn.row & “, col: “ & rgn.column

    End if
Next rgn

End Sub

Ps: я отредактировал код на своем телефоне и продолжу отладку, когда у меня будет компьютер.И я просто более привык использовать «диапазон», а не «клетка».

0 голосов
/ 02 декабря 2018

Прежде всего: с противоположного конца спектра вы можете использовать Range.MergeCells или Range.MergeArea, чтобы определить, является ли ячейка частью объединенной области.Но я отвлекся ...

Вы можете использовать Cell.Row, чтобы получить номер строки.То, как вы возвращаете или отображаете все, что вам нужно - это может быть окно сообщения, строка с разделителями, или массив, или даже диапазон из нескольких областей.

A Sub не может вернуть ничего после вызова, поэтомувместо этого вам может потребоваться Function, например Public Function EmptyRed() As String

(Кроме того, я бы порекомендовал вам привыкнуть явно объявлять все ваших переменных и, возможно, использовать Option ExplicitКроме того, прежде чем вы столкнетесь с ошибкой на основе опечатки. Просто добавьте Dim cell As Range в верхней части подпрограммы на данный момент)

0 голосов
/ 02 декабря 2018
Sub FF()
    Dim r, wksOutput As Worksheet
    Dim cell As Range, rng As Range, rngArea As Range
    With Selection
        .UnMerge
        '// Get only blank cells
        Set rng = .SpecialCells(xlCellTypeBlanks)
        '// Make blank cells red
        rng.Interior.Color = vbRed
    End With
    '// Create output worksheet
    Set wksOutput = Sheets.Add()
    With wksOutput
        For Each rngArea In rng.Areas
            For Each cell In rngArea
                r = r + 1
                '// Write down the row of blank cell
                .Cells(r, 1) = cell.Row
            Next
        Next
        '// Remove duplicates
        .Range("A:A").RemoveDuplicates Array(1), xlNo
    End With
End Sub
0 голосов
/ 02 декабря 2018

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

If IsEmpty(cell.Value) Then Debug.Print cell.Row

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

РЕДАКТИРОВАТЬ

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

Option Explicit
Sub EmptyRed()
    Dim myMergedRange As Range, myCell As Range, myMergedCell As Range
    Dim rngProcess As Range

With Application
    .ScreenUpdating = False
    .Calculation = xlCalculationManual
    .EnableEvents = False
End With

Set rngProcess = Range("A1:B10")
    For Each myCell In rngProcess
        If myCell.MergeCells = True Then
            Set myMergedRange = myCell.MergeArea
            With myMergedRange
                .MergeCells = False
                .Value = myCell(1, 1)
            End With
        End If
    Next myCell

With Application
    .ScreenUpdating = True
    .Calculation = xlCalculationAutomatic
    .EnableEvents = True
End With
End sub

Обратите внимание, что я явно объявляю все переменные, и я жестко запрограммировал диапазон для проверки.Существуют различные способы объявления диапазона, подлежащего проверке;использование «выделения» обычно редко бывает предпочтительным.

...