Эта статья будет близка тем, кому приходится часто работать с отчетами, выгруженными в Excel из программ вроде 1С, SAP и им подобных. Хотя, справедливости ради, надо отметить, что и в обычных файлах Excel такая проблема может так же встречаться, особенно, если в файле использовались различные формулы.
Вводные данные: есть отчет который выкачивается из сторонней программы. В нем есть ячейки, с виду пустые: в них нет пробелов, нет переносов на строки, никаких символов, нет объектов, условного форматирования, в настройках не стоит скрывать нули(Файл -Параметры -Дополнительно -Показывать нули в ячейках, которые содержат нулевые значения). Даже если перейти в режим редактирования ячейки - там пусто.
Если попробовать найти такие "пустые" ячейки(выделить все ячейки листа -F5 -Выделить -Пустые ячейки) - они не выделяются. Но фильтр при этом их видит как пустые и фильтрует как пустые.
Любые математические действия(умножение на ячейку, сложение, деление и т.п.) внутри формул с такими ячейками выдают ошибку #ЗНАЧ!(#VALUE!), а функция ЕПУСТО(ISBLANK) считает ячейку не пустой. Формулы вроде СУММ(SUM) и СЧЁТ(COUNT) игнорируют такие ячейки, а СЧЁТЗ(COUNTA) считает их заполненными.

И самое удивительное - если выделить такую ячейку вручную и нажать Delete (или вкладка Главная -группа Редактирование -Очистить содержимое) - то ячейка становится действительно пустой и с ней начинают работать формулы и другие функции Excel как с реально пустой.
Здесь возникает главный вопрос: что с этой ячейкой не так, если там и до Delete ничего не было?
А не так с ней вот что: практически во всех программах есть такое понятие строковых(текстовых) данных, как строка нулевой длины(еще её часто называют нулевая строка. В Visual Basic for Application такая строка обозначается константой vbNullString, в ячейках её можно встретить как сочетание двух кавычек подряд - ""). Визуально такой текст себя никак не проявляет, однако это все же текст. А любой текст это уже не пусто, но и не число.
Откуда может появится такой текст в ячейках? Здесь несколько вариантов:

  1. Он есть в ячейках изначально, потому что именно так настроена выгрузка и создание файлов в сторонней программе(вроде 1С). В некоторых случаях такие выгрузки настроены таким образом, что как таковых пустых ячеек нет - они просто заполняются строкой нулевой длины.
  2. в ячейке была записана формула, результатом которой стал текст нулевой длины. Самый простой пример такой формулы:
    =ЕСЛИ(A1=1;10;"")
    =IF(A1=1,10,"")

    в итоге, если в ячейке A1 записано любое значение, отличное от 1 формула вернет строку нулевой длины. И если впоследствии формулу заменять значением(Как удалить в ячейке формулу, оставив значения?), то получим нашу псевдо пустую ячейку.
    Если формулы создаются Вами и в дальнейшем планируются производить с этими ячейками математические действия, то лучше вместо "" ставить 0. Тогда проблем не будет. Нули всегда можно заменить или скрыть: Файл -Параметры -Дополнительно -Показывать нули в ячейках, которые содержат нулевые значения

А если такой файл делали не Вы - он достался "по наследству" или это выгрузка из другой программы, что делать тогда? Я предлагаю такой вот нехитрый код, который во всех выделенных ячейках заменит строки нулевой длины на нормальные пустые ячейки:

Sub ReplaceNullString()
    Dim rR As Range, rF As Range, ra As Range
    Dim avR, lr As Long, lc As Long
 
    Set rR = Intersect(ActiveSheet.UsedRange, Selection)
    On Error Resume Next
    Set rR = rR.SpecialCells(xlCellTypeConstants)
    On Error GoTo 0
    If rR Is Nothing Then
        MsgBox "В выделенных ячейках нет значений!", vbInformation, "www.excel-vba.ru"
        Exit Sub
    End If
    Set rF = rR.Find(vbNullString, , xlFormulas, xlWhole)
    If Not rF Is Nothing Then
        For Each ra In rR.Areas
            avR = ra.Value
            If Not IsArray(avR) Then
                ReDim avR(1 To 1, 1 To 1)
                avR(1, 1) = ra.Value
            End If
            For lr = 1 To UBound(avR, 1)
                For lc = 1 To UBound(avR, 2)
                    If avR(lr, lc) = "" Then
                        ra.Item(lr, lc).Value = Empty
                    End If
                Next lc
            Next lr
        Next
        MsgBox "Строки нулевой длины заменены", vbInformation, "www.excel-vba.ru"
        Exit Sub
    End If
    MsgBox "Строк нулевой длины на листе нет или лист защищен", vbInformation, "www.excel-vba.ru"
End Sub

Как это работает:
если раньше никогда не работали с макросами, то рекомендую ознакомиться со статьями:
Что такое макрос и где его искать?
Что такое модуль? Какие бывают модули?

  1. создаем в книге новый стандартный модуль: Alt+F11 -Insert -Module()
  2. копируем в созданный модуль приведенный выше код
  3. выделяем нужный диапазон(если надо заменить на всем листе - то можно выделить все ячейки листа или целиком нужные столбцы - программа сама определить нужные данные)
  4. нажимаем Alt+F8 и в появившемся окне выбираем ReplaceNullString
  5. Короткая видеоинструкция:
    Вставка кода в файл и его выполнение

7 комментариев

    1. Олег, скорее всего на листе всего одна ячейка со значением, без формул.
      По идее можно вот эти строки

      If Not rF Is Nothing Then
              avR = rR.Value

      заменить на такие:

      If Not rF Is Nothing Then
         avR = rR.Value
         If Not IsArray(avR) Then
             Redim avR(1 to 1, 1 to 1)
             avR(1,1) = rR.Value
         end if

      Это должно решить проблему

  1. А есть какое то ограничение по количеству выделенных столбцов? Выделил около 200 - макрос после запуска сразу выдал, что заменено, но по факту ничего не поменялось. Выделил 5 столбцов - все хорошо. Excel 2010.

  2. К сожалению не помогло. Пытался и с первоначальным кодом и с поправкой к нему. И макросы включил в параметрах безопасности и книгу сохранил с поддержкой макросов. Жаль. Программа видит эти якобы пустые ячейки. Мне нужно было обработать данные в программе SPSS. Она их видит и считает :(

Добавить комментарий

Этот сайт использует Akismet для борьбы со спамом. Узнайте, как обрабатываются ваши данные комментариев.