Excel VBA comparing variants in if statement - excel

let me explain my problem:
I have two excel sheets "data" and "output". In the first column of each sheet there are numbers that need to be compared. The numbers look like: 3081671
If I find a number in sheet output that matches the current iteration in the sheet data, I want that the value in the same line in sheet data is written right next to the number in sheet output. This actually works.
However, some of the numbers in sheet data look like this: V3081671A
When iterating and finding such a number in sheet data, I cut the V and A such that only the integer is left.
However, for those cases the if statement "If test = comp Then..." is false, even though test and comp should contain exactly the same strings. Why is this the case?
Any help to solve the problem is really appreciated. If I didn't describe it clear enough, feel free to ask.
Sub MatchNumbers()
Dim i As Integer
Dim j As Integer
Dim buffer As Variant
Dim comp As Variant
Dim test As Variant
Dim inp As Variant
j = 2
While IsEmpty(ActiveSheet.Cells(j, 1)) = False
ActiveSheet.Cells(j, 2) = "NV"
j = j + 1
Wend
i = 2
inp = Tabelle1.Cells(i, 1)
While IsEmpty(inp) = False
If Not IsNumeric(Left(inp, 1)) And Len(inp) >= 9 Then
comp = Mid(inp, Len(inp) - 7, 7)
Else
comp = inp
End If
j = 2
test = ActiveSheet.Cells(j, 1)
Do While IsEmpty(test) = False
If Left(inp, 1) = "V" Then
MsgBox ("Neue Zeile!")
ActiveSheet.Cells(j, 1).EntireRow.Insert Shift:=xlDown
j = j + 1
ActiveSheet.Cells(j, 1) = inp
End If
ActiveSheet.Cells(j, 2) = Tabelle1.Cells(i, 3)
Exit Do
End If
j = j + 1
test = ActiveSheet.Cells(j, 1)
Loop
i = i + 1
inp = Tabelle1.Cells(i, 1)
Wend
End Sub

Related

Speed up a VBA Replace-loop possible or use other method?

I have a small VBA Loop but it takes over 2-3 minute to finish, any idea how I can speed up/rewrite it that it will be faster?
The Range "Replace Names" is a List of 500 names of named areas in "Data".
The for loop searches for the one that matches the name in "Data" and replaces the one with the name from "Source". This also works fine, but it takes a while. Is there a faster method?
Application.Calculation = xlCalculationManual
Application.ScreenUpdating = False
For Each ID_name In wsSupport.Range("ReplaceNames")
wsCheck.Range("Data").Replace ID_name, wsSource.Range(ID_name), xlWhole
Next
Application.Calculation = xlCalculationAutomatic
Application.ScreenUpdating = True
You might benefit from this valuable piece of text:
https://www.microsoft.com/en-us/microsoft-365/blog/2009/03/12/excel-vba-performance-coding-best-practices/
So in your case the Code could somewhat look like this:
Dim arrData as Variant, arrSource as Variant, k as long
arrData = wsCheck.Range("Data").value2 'this creates a two-dimensional array with rows on the first and columns on the second index
arrSource = wsSource.Range(...).value2
'loop through rows I suppose
for k = LBound(arrData,1) to UBound(arrData,1)
if arrData(k, yourColumn) = ... then
arrData(k, yourColumn) = arrSource(rowhere, columnhere)
endif
next k
wscheck.range("Data") = arrData
Its working now!!!
If you see mistakes let me know!
Dim arrData As Variant, arrSource As Variant, arrNames As Variant, k As Long
arrData = wsChecklist.Range("Checklist").Value2 'this creates a two-dimensional array with rows on the first and columns on the second index
arrSource = wsSupport.Range("ReplaceNames").Value2
arrNames = wsNia.Range("D1:D1000").Value2
'loop through rows I suppose
For k = LBound(arrData, 1) To UBound(arrData, 1)
For j = LBound(arrData, 2) To UBound(arrData, 2)
' If UCase(arrData(k, j)) = UCase(arrSource(x, 1)) Then
If UCase(arrSource(x, 1)) = UCase(arrData(k, j)) Then
For i = 1 To 1000
Name1 = wsNia.Cells(i, 2)
Name2 = wsNia.Cells(i, 3)
Name = Name1 & "_" & Name2
If UCase(arrData(k, j)) = UCase(Name) Then
arrData(k, j) = arrNames(i, 1)
x = x + 1
k = 1
j = 1
i = 1
Exit For
End If
Next i
End If
If k > 2900 And x < 265 Then
x = x + 1
j = 1
k = 1
End If
Next j
Next k
wsChecklist.Range("Checklist").Value2 = arrData

Cut/copy/paste alternate cell rows onto the next column & delete empty rows after

I have challenges in highlighting/copying alternate rows in one column and pasting it to the next column and aligned.
Here's a screenshot:
Following code assumes you have two separate tabs, SRC and DST and the range of data starts in the first cell. Will do all in a single step:
Public Sub CopyAlternate()
Dim i As Long
i = 2
While Len(Sheets("SRC").Cells(i, 1).Value) > 0
Sheets("DST").Cells(i / 2 + 1, 1).Value = Sheets("SRC").Cells(i, 1).Value
Sheets("DST").Cells(i / 2 + 1, 2).Value = Sheets("SRC").Cells(i + 1, 1).Value
i = i + 2
Wend
End Sub
You can take this code and adjust it to taste:
Sub alternate()
Dim i As Integer
Dim j As Integer
Dim n As Integer
i = 0
j = 0
n = 0
With ActiveSheet
For Each c In .Range("A4:A16")
.Cells(20 + j, 1 + i).Value = c.Value
If n = 0 Or n Mod 2 = 0 Then
i = 1
j = j
Else
i = 0
j = j + 1
End If
n = n + 1
Next c
End With
End Sub
This worked for me when rebuilding your example with letters (for faster checking).

Extracting numbers from a string in each cell

I'm trying to write code that extracts X consecutive numbers from text.
For example, if I want to extract 5 consecutive numbers in my text:
Cell A1: dsuad28d2hr 22222222 11111 d33d11103
Cell B2: 11111 (wanted)
I could make it work for texts with only 5 numbers but the problem is if my text contains other consecutive numbers higher than 5.
Sub ExtractNum2()
Dim Caract() As String
Dim i As Integer
Dim j As Integer
Dim z As Integer
Dim cont As Integer
Dim goal As Integer
Dim Protocolo() As String
Dim cel As String
Dim lin As Long
lin = Range("A1", Range("A1").End(xlDown)).Rows.Count 'Repeat for each line
For z = 1 To lin
cel = Cells(z, 1)
ReDim Caract(Len(cel))
ReDim Protocolo(Len(cel))
cont = 0
For i = 1 To Len(cel)
Caract(i) = Left(Mid(cel, i), 1)
If IsNumeric(Caract(i)) Then 'Character check
cont = cont + 1
Protocolo(cont) = Caract(i)
'If Not IsNumeric(Caract(6)) And cont = 5 Then**
If cont = 5 '
Dim msg As String
For j = 1 To 5
msg = msg & Protocolo(j)
Next j
Cells(z, 2) = msg 'fills column B
msg = ""
End If
Else
cont = 0
End If
Next i
Next z 'end repeat
End Sub
I'm trying to use:
If Not IsNumeric(Caract(6)) And cont = 5 Then
But it is not working, my output is: B2: 22222 but I want 11111.
What am I missing?
EDIT
Sorry i wasnt clear. I want to extract X numbers with 6>x>4 (x=5). I dont want 22222 since it has 8 consecutive numbers and 11111 has 5 in my example.
UDF:
Function GetNum(cell)
With CreateObject("VBScript.RegExp")
.Pattern = "\b(\d{5})\b"
With .Execute(cell)
If .Count > 0 Then GetNum = .Item(0).SubMatches(0)
End With
End With
End Function
UPDATE:
If you want to return error (say, #N/A) instead of callee's default data type, you could write the following:
Function GetNum(cell)
With CreateObject("VBScript.RegExp")
.Pattern = "\b(\d{5})\b"
With .Execute(cell)
If .Count > 0 Then
GetNum = .Item(0).SubMatches(0)
Else
GetNum = CVErr(xlErrNA)
End If
End With
End With
End Function
I tried this with a Cell containing "Yjuj 525211111x5333332s5" to test whether 2 consecutive 5 characters get catch, and it worked great.
Sub Macro_Find_Five()
Dim str As String
Dim tmp As String
Dim cntr As Integer
Dim result As String
str = Sheet1.Cells(1, 1).Value
tmp = ""
cntr = 1
col = 2
result = ""
'For Loop for tracing each charater
For i = 1 To Len(str)
'Ignore first starting character
If i > 1 Then
'If the last character matches current character then
'enter the if condition
If tmp = Mid(str, i, 1) Then
'concatenate current character to a result variable
result = result + Mid(str, i, 1)
'increment the counter
cntr = cntr + 1
Else
'if the previous character does not match
'reset the cntr to 1
cntr = 1
'as well initialize the result string to "" (blank)
result = ""
End If
End If
'if cntr matches 5 i.e. 5 characters traced enter if condition
If cntr = 5 Then
'adding to next column the result found 5 characters same
Sheet1.Cells(1, col).Value = result
'increment the col (so next time it saves in next column)
col = col + 1
'initializing the variables for new search
cntr = 1
tmp = ""
result = ""
End If
'stores the last character
tmp = Mid(str, i, 1)
'if first character match concatenate.
If cntr = 1 Then
result = result + Mid(str, i, 1)
End If
Next i
End Sub

Compare each and every cell in a colum by custom macro (unhandy for loop)

i'm currently trying to compare each and every cell in a column with each other in order to find duplicates. I wrote below code, i know it as possible via default Excel functions, but i would like to write a macro with the above mentioned function. Excel currently doesn't respond when i run my code, my guess is that i run a double for loop with 14K cells to compare is each resulting in 14.000*14.000 loops, which is kinda unhandy. Any help will be appreciated :).
Sub findidentical()
Dim i As Integer
Dim j As Integer
Dim x As Integer
Dim ColumnG As Integer
x = 0
ColumnG = Application.WorksheetFunction.CountA(Range("G:G"))
'ColumnG is 14K cells long'
For i = 2 To ColumnG
For j = 1 + 1 To ColumnG
If Cells(i, 7).Value = Cells(j, 7).Value Then
x = x + 1 & Cells(i, 7).Font.Bold = True & Cells(j, 7).Font.Bold = True
End If
Next j
Next i
Range("L25").Text = "Amount of duplicates"
Range("L26").Value = x
End Sub
Try this:
Sub findidentical()
Dim i As Integer
Dim j As Integer
Dim x As Integer
Dim ColumnG As Integer
x = 0
ColumnG = Application.WorksheetFunction.CountA(Range("G:G"))
'ColumnG is 14K cells long'
For i = 2 To ColumnG
For j = i + 1 To ColumnG
If Cells(i, 7).Value = Cells(j, 7).Value Then
x = x + 1
Cells(i, 7).Font.Bold = True
Cells(j, 7).Font.Bold = True
End If
Next j
Next i
Range("L25").Text = "Amount of duplicates"
Range("L26").Value = x
End Sub
First you need to make each command in the if statement its own line or separate them with : instead of &. & is a string concatenation not a command separator.
Second there is no reason to start Loop j at 2 it has already been compared to everything above. So start it at i+1

in vba how to define array and compare them?

i have 2 sheets , i want to find the same rows in 2 sheets , so i put the first row in array , and by a for next i define the first array ...then i define another array from second sheet , then i compare them .... why it doesn't work?
Sub compare()
Dim n(4) As Variant
Dim o(4) As Variant
Dim i As Integer
For i = 3 To 20 'satrha
For j = 2 To 4 'por kardan
n(j) = Sheets("guys").Cells(i, j)
Next 'por kardan
k = 3
Do 'hhhh
For Z = 2 To 4 'por dovomi
o(Z) = Sheets("p").Cells(k, Z)
Next 'por dovomi
If n(j) = o(Z) Then
Sheets("guys").Cells(i, 1) = Sheets("p").Cells(k, 2)
flag = True
Else
flag = False
k = k + 1
End If
Loop Until flag = False 'hhhhh
Next 'satrha
End Sub
Guessing from your existing code, my following code will copy the value from sheet "p" column B into sheet "guys" column A when a match is found.
Sub compare()
Dim i As Integer
Dim j As Integer
Dim l As Integer
l = Sheets("p").Range("B65535").End(xlUp).Row
Debug.Print l
For i = 3 To 20
For j = 3 To l
If Sheets("guys").Cells(i, 2).Value = Sheets("p").Cells(j, 2).Value And _
Sheets("guys").Cells(i, 3).Value = Sheets("p").Cells(j, 3).Value And _
Sheets("guys").Cells(i, 4).Value = Sheets("p").Cells(j, 4).Value Then
Sheets("guys").Cells(i, 1).Value = Sheets("p").Cells(j, 2).Value
Exit For
End If
Next
Next
End Sub
Noted that I explicitly said Value in my code. That will copy the computed value (e.g. result of a formula) instead of the "original" content.

Resources