Страницы: 1
RSS
VBA проверка на число (по заданному региональному стандарту)
 
Привет всем.
Немного туплю, порыл форум, но никак не найду подходящего решения, или не могу протестировать... а VBA основательно приподзабыл уже :)

Есть три ячейки, в которых может быть написано число с десятичным знаком или без десятичного знака, причем может быть сохранено как текст или как число:
0.5true
0,5false
1true
нужен кусочек кода VBA для проверки содержимого ячейки
Если в ячейке записано целое число, без десятичного знака, то это не ошибка. Неважно, как оно сохранено - как текст или как число
Если в ячейке записано число со знаками после запятой, то если разделитель не точка - это ошибка.
Если в ячейке записано число со знаками после запятой, то если разделитель точка - это не ошибка.

Макрос должен работать в системе с любыми региональными стандартами. Иными словами, хороши только целые числа, и то, что может быть преобразовано в число, но при этом обязательно в нем разделитель - точка.

вот такой код не дает нормального результата, увы :(
Код
Sub tezt()
With Application
       .DecimalSeparator = "."
       .ThousandsSeparator = ","
       .UseSystemSeparators = False
End With

Debug.Print "0.5", IsNumeric("0.5")     ' false, должно быть true
Debug.Print "0,5", IsNumeric("0,5")     ' true, должно быть false
Debug.Print "1", IsNumeric("1")           ' true, всё в порядке

Application.UseSystemSeparators = True
End Sub


Идеи?
F1 творит чудеса
 
Здравствуйте, Максим! Вопросы:

  • Такой текст допустим "123,456.78" (числа в локализации en_US)?
  • Что должна возвращать функция: True / False или число / False?
  • В Excel логические значения ячеек - самостоятельный базовый тип (не числа и не текст). Для них что возвращать?
  • Для пустых ячеек что возвращать?
В макросе из #1 изменение свойств объекта (Excel.)Application не влияет на поведение функции (VBA.)IsNumeric, которая руководствуется исключительно региональными настройками.
Изменено: sokol92 - 13.10.2021 20:33:25
Владимир
 
а мне кажется присутсвует подвох
Цитата
Максим Зеленский написал:
сохранено как текст или как число:
тут сразу говорим о невозможности сравнить что там за разделитель.
По вопросам из тем форума, личку не читаю.
 
sokol92, спасибо за вопросы, навело на кучу мыслей :)

Цитата
sokol92 написал:
Такой текст допустим "123,456.78" (числа в локализации en_US)?
с таким пока не знаю, что делать. По идее, тысячные разделители вряд ли встретятся, но надо допилить будет код. Текст в формате "123.45" как раз то, что должно считаться числом.
Цитата
sokol92 написал:
Что должна возвращать функция: True / False или число / False?
достаточно true/false
Цитата
sokol92 написал:
В Excel логические значения ячеек - самостоятельный базовый тип (не числа и не текст). Для них что возвращать?
false
Цитата
sokol92 написал:
Для пустых ячеек что возвращать?
false

Вроде решил я, как-то так (не оптимально для Empty, но не страшно)
Код
Function IsNumberDotSeparated(ByRef MyVal) As Boolean

If CStr(MyVal) = Replace(CStr(MyVal), Application.International(xlDecimalSeparator), ".") Then
    'Debug.Print MyVal, "Number with Dot separator"
    IsNumberDotSeparated = True
Else
    'Debug.Print MyVal, "Number with other separator"
    IsNumberDotSeparated = False
End If

End Function

Sub tezt()
Dim st
st = Empty
'st = 0.5
'st = "0.5"
'st = 1
'st = "2"
'st = True
If IsNumeric(CStr(st)) Then
        If Not IsNumberDotSeparated(st) Then
            Debug.Print CStr(st), "false"
        Else
            Debug.Print CStr(st), "true"
        End If
    Else
        'non-number branch
        Debug.Print CStr(st), IsNumeric(Replace(st, ".", Application.International(xlDecimalSeparator)))
    End If
End Sub


БМВ, у меня получилось :) если не сложно, посмотрите, может, я какой-то кейс (кроме тысячных разделителей) упустил
F1 творит чудеса
 
С той же идеей (надо еще погонять как следует):
Код
Option Explicit
' Возвращает True для чисел и текстов, представимых как число (разделитель дробной доли - точка).
' False в иных случаях
Function IsNumberUS(ByVal arg) As Boolean
  If IsObject(arg) Then
    arg = arg.Value        ' параметр является объектом - ячейка (???)
  End If
  If Not IsArray(arg) Then ' массивы не обрабатываем (пока ???)
    Select Case VarType(arg)
      Case vbEmpty, vbBoolean, vbNull, vbError, vbUserDefinedType:
      Case vbString:
        arg = Trim(arg) ' пробелы слева и справа отбрасываем (???)
        If Not (arg Like "*[ ,]*") Then ' нет запятых и пробелов между цифрами
          IsNumberUS = IsNumeric(Replace(arg, ".", Mid(1.5, 2, 1)))
        End If
      Case Else ' числовые типы
        IsNumberUS = True
    End Select
  End If
End Function

Sub Test()
  Dim v
  For Each v In Array("0.5", "0,5", "  123.45 ", " -1e-14", Now, 25, "Hello!", "1 2")
    Debug.Print v, IsNumberUS(v)
  Next v
End Sub
Изменено: sokol92 - 13.10.2021 21:18:34
Владимир
 
допилил на проверку тысячных разделителей американских
В моем случае они ошибка, поэтому для них false. Для проверки сначала их чищу от "," и заменяю разделитель, он думает, что это число, а дальше не проходит проверку.
Код
Sub tezt()
Dim st
'st = Empty
'st = "0,5"
'st = 0.5
'st = "0.5"
'st = 1
'st = True
st = "12,345.67"

If IsNumeric(CStr(st)) Or IsNumeric(Replace(Replace(Cstr(st), ",", ""), ".", Application.International(xlDecimalSeparator))) Then
        If Not IsNumberDotSeparated(st) Then
            Debug.Print CStr(st), False
        Else
            Debug.Print CStr(st), True
        End If
    Else
        'non-number branch
        Debug.Print CStr(st), False
 
    End If
End Sub

sokol92, на значении 0.5 (как число) ломается, похоже. Если брать из ячейки его, например.

UPD
блин, нет, хромая логика. Изменил разделитель в системе, неправильно работает :(
F1 творит чудеса
 
Макрос из #5 с разделителями Excel не общается. Если в ячейке число (или дата), то при передаче ячейки как параметра (или ее значения (value или value2) как параметра) он должен вернуть True.
Я проверял в системе Excel 2019 (64-), Win 10, windows-1252 (en-US).
Изменено: sokol92 - 13.10.2021 21:54:50
Владимир
 
Максим Зеленский вчера не хотела голова думать а сегодня времени не будет.

Максим, если записано в ячейке  число, как число, то проверять нет смысла, ибо формат задает что видно и если это важно , то нужно брать текст и уже его обрабатывать, типа там число но видеть вы должны его по особому.
Если там текст, то вопрос может быть только к одному варианту 123,456  не понятно это дробная или разделитель разрядов и там целое число. в остальных случаях - проверка на преобразование с заменой и без с предварительным удалением пробелов, даст результат.
По вопросам из тем форума, личку не читаю.
 
Максим, а нет возможности приложить файл с возможными вариантами значений в ячейках и напротив записать, которое должно вернуть True, а какое False? А то мне тоже неясен момент с настройками Excel и ОС. Что делать, если в ячейке число, но я в параметрах Excel поставил свои разделители, игнорируя системные?
Даже самый простой вопрос можно превратить в огромную проблему. Достаточно не уметь формулировать вопросы...
 
Коллеги, спасибо за вопросы - подготовлю файл, приложу. Там еще маленькие нюансы выяснились, уточню их по ходу дела
F1 творит чудеса
Страницы: 1
Наверх