У меня есть столбец, где почти каждая ячейка состоит из комбинации цифр и букв и символов ("ТС-403" или "ТСМ-7600"). Я хочу, чтобы каждый символ, который не является целым числом, был удален/заменен пустой строкой, чтобы у меня остались только числа ("403").
Я придумал два подхода:
Я думаю, что лучше всего создать массив целых чисел с числами 0-9, а затем выполнить итерацию по ячейкам с помощью цикла for, где, если строка в ячейке содержит символ, которого нет в массиве, тогда этот символ (не вся ячейка) должна быть стерта.
Sub fixRequestNmrs()
Dim intArr() as Integer
ReDim intArr(1 to 10)
For i = 0 to 9
intArr(i) = i
Next i
Dim bRange as Range
Set bRange = Sheets(1).Columns(2)
For Each cell in bRange.Cells
if cell.Value
// if cell includes char that is not in the intArr,
// then that char should be deleted/replaced.
...
End Sub()
Возможно, второй подход проще: использовать функцию Split()
, поскольку за «-» всегда следуют числа, а затем заменить первую подстроку на «». Я очень смущен тем, как использовать функцию Split() в сочетании с диапазоном и функцией замены...
For Each cell in bRange.Cells
Cells.Split(?, "-")
...
Функция
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' Purpose: Returns an integer composed from the digits of a string.
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Function DigitsToInteger(ByVal SearchString As String) As Long
Dim ResultString As String
Dim Char As String
Dim n As Long
For n = 1 To Len(SearchString)
Char = Mid(SearchString, n, 1)
If Char Like "[0-9]" Then ResultString = ResultString & Char
Next n
If Len(ResultString) = 0 Then Exit Function
DigitsToInteger = CLng(ResultString)
End Function
Пример рабочего листа
Sub DigitsToIntegerTEST()
Const FIRST_ROW As Long = 2
' Read: Reference the (single-column) range.
Dim wb As Workbook: Set wb = ThisWorkbook ' workbook containing this code
Dim ws As Worksheet: Set ws = wb.Worksheets("Sheet1")
Dim LastRow As Long: LastRow = ws.Cells(ws.Rows.Count, "B").End(xlUp).Row
If LastRow < FIRST_ROW Then Exit Sub ' no data
Dim rg As Range: Set rg = ws.Range("B2", ws.Cells(LastRow, "B"))
Dim rCount As Long: rCount = rg.Rows.Count
' Read: Return the values from the range in an array.
Dim Data() As Variant
If rCount = 1 Then
ReDim Data(1 To 1, 1 To 1): Data(1, 1) = rg.Value
Else
Data = rg.Value
End If
' Modify: Use the function to replace the values with integers.
Dim r As Long
For r = 1 To rCount
Data(r, 1) = DigitsToInteger(CStr(Data(r, 1)))
Next r
' Write: Return the modifed values in the range.
rg.Value = Data
' To test the results in the column adjacent to the right, instead use:
'rg.Offset(, 1).Value = Data
End Sub
В VBA (простой)
Sub DigitsToIntegerSimpleTest()
Const S As String = "TSM-7600sdf"
Debug.Print DigitsToInteger(S) ' Result 7600
End Sub
В Excel
=DigitsToInteger(A1)
Полезный подход + :) ... К вашему сведению, вам может быть интересна моя альтернатива через хитрое совпадение @VBasic
Если у вас есть функция CONCAT
, вы можете сделать это с помощью относительно простой формулы — VBA не требуется:
=CONCAT(IFERROR(--MID(A1,SEQUENCE(LEN(A1)),1),""))
Если вы предпочитаете решение, отличное от VBA, в более ранней версии Excel, доступна более сложная формула, но мне придется вернуться к своим файлам, чтобы найти ее.
Элегантный и полезный способ +:)
Сложная функция GetVal()
Следующая функция
arr
с помощью функции справки String2Arr()
Application.Match
(здесь без третьего аргумента, который в основном используется для точного поиска, и путем сравнения двух массивов)Instr()
Val()
(~> см. примечание).Function GetVal(ByVal s As String) As Double
Dim arr: arr = String2Arr(s): Debug.Print Join(arr, "|")
Dim chars: chars = Split(" ,',+,-,.,0,A", ",")
Dim catCodes: catCodes = Application.Match(arr, chars) 'No 3rd zero-argument!!
Dim tmp$: tmp = Join(catCodes, ""): Debug.Print Join(catCodes, "|")
Dim pos&: pos = InStr(tmp, 6) ' Pos 6: Digits; pos 1-5,7: other symbols/chars
GetVal = Val(Mid(s, pos)) ' calculate value of right substring
End Function
Ноты
Функция Val
может преобразовать (под)строку с начальными цифрами в число, даже если за ней следуют нечисловые символы.
Функция помощи String2Arr()
Разбивает строку на один массив символов:
Function String2Arr(ByVal s As String)
s = StrConv(s, vbUnicode)
String2Arr = Split(s, vbNullChar, Len(s) \ 2)
End Function
Пример вызова
Dim s As String
s = "aA+*&$%(y#,'/\)!-12034.56blabla"
Debug.Print GetVal(s) ' ~~> 12034.56
Если бы я использовал первый подход, я бы использовал ключи scripting.dictionary или arraylist для хранения чисел от 0 до 9. Это позволило бы мне проверить, является ли символ числом, используя метод .exists или .Contains. соответственно.