Excel VBA: End(xlUp) и End(xlDown) заканчиваются строкой 244, которая пуста?

Я заполнил B2: GQ244 формулами, скопировал диапазон и вставил по значению перед сортировкой столбца диапазона за столбцом. Все ячейки в B8:GQ244 были пустыми. Затем я хотел объединить непустые ячейки столбец за столбцом, начиная со строки 2. Для этого мне нужно было найти последнюю непустую ячейку в каждом столбце.

По какой-то причине и End(xlUp), и End(xlDown) дали строку 244, которая была пустой. Я не могу понять, почему. Я думал, что файл может быть поврежден. Итак, я безрезультатно скопировал два листа и модуль во вновь созданную книгу. Любое объяснение, почему и End(xlUp), и End(xlDown) дали строку 244?

.Range("B2:GQ244").Formula = "=IF(ISERROR(FIND( B$1,Sheet9!$H34)),"""",Sheet9!$I34)"

'paste by value to get rid of formulae

.Range("B2:GQ244").Copy
.Range("B2").PasteSpecial Paste:=xlPasteValues

'sort by column

Dim last_row As Long
Dim j As Long

For i = 2 To 200 Step 1

Range(.Cells(2, i), .Cells(245, i)).Sort key1:=.Cells(2, i), order1:=xlAscending

Next i

For i = 2 To 200 Step 1

last_row = .Cells(65536, i).End(xlUp).Row
last_row = .Cells(1, i).End(xlDown).Row

Ячейка, содержащая формулу, не пуста. Он просто ничего не отображает, но содержит формулу.

Variatus 24.12.2020 14:36

@Variatus да, но после вставки по значению все формулы исчезли.

joehua 25.12.2020 00:25

Да, формулы заменяются созданными ими значениями. Я объяснил это в моем официальном ответе ниже.

Variatus 25.12.2020 01:13
Преобразование HTML-таблицы в профессиональный документ Excel
Преобразование HTML-таблицы в профессиональный документ Excel
Это самый простой способ создания Excel из HTML-таблицы.
Импорт excel в laravel в базу данных
Импорт excel в laravel в базу данных
Здравствуйте, дорогой читатель, в этой статье я расскажу практическим и быстрым способом, как импортировать файл Excel в вашу базу данных с помощью...
0
3
2 056
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Я не могу подтвердить ваши выводы. Имея пустой ActiveSheet и пустой Sheet9, приведенный ниже код заполнил ActiveSheet нулями B2:GQ244. Затем он считывает последнюю строку xlUp как 244 и xlDown как 2. Оба этих значения соответствуют ожидаемым. Возможно, у вас есть настройка, подавляющая отображение нулей. Однако, как объяснялось в моем комментарии выше, ячейка, которая выглядит пустой, не обязательно является пустой, и это также применимо к ячейке, содержащей NullString, вставленную вашей формулой, даже если формула была впоследствии удалена, оставив нулевую строку на своем месте.

Sub Examine()
    
    Dim last_row As Long
    Dim i As Long

    With ActiveSheet
        .Range("B2:GQ244").Formula = "=IF(ISERROR(FIND( B$1,Sheet9!$H34)),"""",Sheet9!$I34)"
        
        'paste by value to get rid of formulae
        
        .Range("B2:GQ244").Copy
        .Range("B2").PasteSpecial Paste:=xlPasteValues
        
        'sort by column
        
        For i = 2 To 200 Step 1
            Range(.Cells(2, i), .Cells(245, i)).Sort Key1:=.Cells(2, i), Order1:=xlAscending
            last_row = .Cells(.Rows.Count, i).End(xlUp).Row
            Debug.Print last_row            ' returns 244
            last_row = .Cells(1, i).End(xlDown).Row
            Debug.Print last_row            ' returns 2
        Next i
    End With
End Sub

Таким образом, остается единственная загадка, почему .Cells(1, i).End(xlDown).Row дает вам значение 244. Это не так. Поэтому решение должно быть в проведении вашего теста, а не в его результате. Сравните свой метод тестирования с тем, который я использовал выше.

Странно, что код заполнил ячейки нулями. Разве ячейки не должны содержать нуль, учитывая, что формула вставляет "" (пустую строку)? Я проверил File/Options/Advanced и подтвердил, что должны отображаться нули. Я также ввел «=B243=0» в B246 и получил ЛОЖЬ, подтверждая, что пустые ячейки не содержат нуля. Интересно, что если бы я изменил формулу, чтобы заполнить vbNullString вместо «»», все ранее пустые ячейки теперь были нулями. Результат сортировки также отличается. При «»» после сортировки числа начинались со 2-й строки и вниз. С vbNullString числа были внизу.

joehua 25.12.2020 01:14

Если B1 ничего не содержит, функция НАЙТИ будет успешной, и результат, импортированный из Sheet9, будет равен нулю, если указанная ячейка также пуста. Если B1 имеет содержимое, это значение может не быть найдено на Sheet9, что приведет к ошибке FIND, которую формула преобразует в «». Обратите внимание, что "" = NullString. Результат сортировки может отличаться в зависимости от того, сортируете ли вы формулы или значения.

Variatus 25.12.2020 01:22

Я только что запустил ваш код на своем листе и получил два числа — 244, 244. Это точно то же самое, что дал мой код.

joehua 25.12.2020 03:09

Это потому, что в вашем тесте B1 не пуст. Имейте в виду, что xlDown просматривает заданную ячейку вниз, тогда как xlUp просматривает заданную ячейку вверх. Поэтому в случае xlDown результат должен быть таким же, как и для xlUp, если перед концом столбца нет пустых ячеек.

Variatus 25.12.2020 08:38

Спасибо за объяснение, но это восходит к моему первоначальному вопросу. Что такого особенного в строке 244? B3 вниз до конца столбца все пустые. На самом деле все столбцы со 2 по 199, начиная с строки 10 и ниже, пусты, а End(xlUp) и End(xlDown) дают 244.

joehua 25.12.2020 13:06

B244 — последняя непустая (используемая) ячейка в столбце B. Пожалуйста, поймите, что Excel предназначен для отображения вещей в ячейках, которых там нет. В этом случае то, что отображается, является нулевой строкой, и вы пытаетесь утверждать, что ее не может быть, потому что она не существует и не видна. Это потому, что ваша собственная формула поместила это туда. Это не видно, потому что пустые строки невидимы. Код, который мы обсуждаем, доказывает оба факта.

Variatus 25.12.2020 13:17

Спасибо. Теперь это начинает обретать смысл. Есть ли способ удалить нулевые строки или различать ячейки, содержащие нулевую строку, и те, которые пусты?

joehua 26.12.2020 00:24
Ответ принят как подходящий

Приведенный ниже код удалит все нулевые строки в нижней части столбцов, а также те, которые содержат нули.

Sub ClearBlankCells()
    ' 146
    
    Dim Rng         As Range            ' working range
    Dim R           As Long             ' intermediate: row
    Dim C           As Long             ' loop counter: columns

    Application.ScreenUpdating = False
    With ActiveSheet
        With .Range("B2:GQ244")
            .Formula = "=IF(ISERROR(FIND( B$1,Sheet9!$H34)),"""",Sheet9!$I34)"
            ' replace formulas with their values
            .Copy
            .PasteSpecial Paste:=xlPasteValues
        End With
        Application.CutCopyMode = False

        For C = 2 To 200 Step 1
            Set Rng = .Columns(C)
            R = Application.Evaluate("SUMPRODUCT((" & Rng.Address & "<>"""")*(" & _
                                                      Rng.Address & "<>0)*1)")
            If R > 0 Then
                Set Rng = Range(.Cells(R + 1, C), .Cells(Rows.Count, C))
                Rng.ClearContents
            End If
            ' sort by column
'            Range(.Cells(2, C), .Cells(245, C)).Sort Key1:=.Cells(2, C), Order1:=xlAscending
        Next C
    End With
    Application.ScreenUpdating = True
End Sub

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

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

Код работает очень медленно, что приводит к двум наблюдениям.

  1. Он тратит 99% своего времени на устранение ущерба, нанесенного в первой линии.
  2. Он рассматривает диапазон данных, который значительно больше, чем на самом деле требуется. Никто не хочет смотреть на лист из 200 столбцов и 244 строк.

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

Спасибо за ответ. Мне нужно отсортировать столбец по отдельности. B1:GQ1 содержат имена, а строки после них содержат нулевой номер страницы. Я сортирую столбцы по отдельности, чтобы увидеть, какое имя появляется на каких страницах. Это индекс для публикации. Возможно, есть лучший способ сделать это, но я не предвижу, что буду делать эту работу снова в будущем. Так что, пока у меня есть рабочий метод, все в порядке. Если мне нужно сделать это много раз, я буду исследовать, как сделать это лучше.

joehua 26.12.2020 19:08

Другие вопросы по теме