Excel VBA - Macro Runs but has no effect - vba

I'm new to Excel VBA and this is my first macro, so please forgive me if I've made a very obvious mistake. I have the following code to compare to worksheets and, if a match is found, to make a note on one of the sheets. It runs with no errors, but the changes are not being made. I can't see where I've gone wrong. Thanks in advance for the help.
Sub invalid()
Dim i As Integer
Dim j As Integer
Dim main As Worksheet
Dim invalid As Worksheet
i = 2
Set main = ThisWorkbook.Worksheets(1)
Set invalid = ThisWorkbook.Worksheets(2)
Do
j = 2
Do
If LCase$(invalid.Cells(i, 1).Value) = LCase$(main.Cells(j, 13).Value) Then
main.Cells(j, 14).Value = "Invalid Email"
End If
j = j + 1
Loop While main.Cells(j, 2) = Not Null
i = i + 1
Loop While invalid.Cells(i, 2) = Not Null
End Sub

Try this, it removes one of the loops:
Sub invalid()
Dim i As Long
Dim j As Long
Dim lRow As Long
Dim main As Worksheet
Dim invalid As Worksheet
Set main = ThisWorkbook.Worksheets(1)
Set invalid = ThisWorkbook.Worksheets(2)
lRow = main.Cells(main.Rows.Count, 13).End(xlUp).Row
For i = 2 To lRow
j = 0
On Error Resume Next
j = Application.WorksheetFunction.Match(main.Cells(i, 13), invalid.Range("A:A"), 0)
On Error GoTo 0
If j > 0 Then main.Cells(i, 14) = "Invalid Email"
Next i
End Sub

Related

Excel VBA copying specific columns

I have the following VBA code for excel
Dim k As Integer, z As Integer
Dim sourceSht As Worksheet
Dim destSht As Worksheet
z = 0
Set sourceSht = Sheets("sheet1")
Set destSht = Sheets("sheet2")
DoEvents
For k = 1 To 5000
If k < 3 Or (k - 1) Mod 3 <> 0 Then
z = z + 1
sourceSht.Columns(k).Copy destSht.Columns(z)
End If
Next
This code was working perfectly for rows (changed this part"sourceSht.Columns(k).Copy destSht.Columns(z)").
but I can not make it work for columns. I want excel to copy the first 2 columns then skip the third one, then copy 2 again, skip one and etc... can somebody help me and explain what am I doing wrong?
I'm going to ignore the use of mod and do a Step 3 with the loop:
Dim i as Long, j as Long
For i = 1 to 5000 Step 3
With sourceSht
If j = 0 Then
j = 1
Else
j = j + 2 'Copying 2 columns over, so adding 2 each time
End If
.Range(.Columns(i),.Columns(i+1)).Copy destSht.Range( destSht.Columns(j), destSht.Column(j+1))
End With
Next i
Something like that should do it for you
Alternate:
Sub tgr()
Dim wsSource As Worksheet
Dim wsDest As Worksheet
Dim rCopy As Range
Dim rLast As Range
Dim LastCol As Long
Dim i As Long
Set wsSource = ActiveWorkbook.Sheets("Sheet1")
Set wsDest = ActiveWorkbook.Sheets("Sheet2")
On Error Resume Next
Set rLast = wsSource.Cells.Find("*", wsSource.Range("A1"), xlFormulas, , xlByColumns, xlPrevious)
On Error GoTo 0
If rLast Is Nothing Then Exit Sub 'No data
LastCol = rLast.Column
Set rCopy = wsSource.Range("A:B")
For i = 4 To LastCol Step 3
Set rCopy = Union(rCopy, wsSource.Columns(i).Resize(, 2))
Next i
rCopy.Copy wsDest.Range("A1")
End Sub
Try this (use count for the number of time you need to copy columns, t for the first columns you need to copy):
Sub copy_columns()
t = 1
Count = 1
Do Until Count = 10
Range(Columns(t), Columns(t + 1)).Copy
Cells(1, t + 3).Select
Selection.PasteSpecial Paste:=xlPasteValues
t = t + 3
Count = Count + 1
Loop
End Sub

Excel: VBA to delete group of rows

I have an excel file with one column with data. Something like:
21/07/2017
DEF
GHI
Field 7
SOMETHING HERE
MORE TEXT
21/07/2017
DEF
GHI
Field 7
This is repeated a few thousand times. What I am looking for is all rows between and including 21/07/2017 and Field 7 to be deleted and for the rows to be moved up.
I've tried a few things but now back to a blank canvas! Any hints?
Thanks
CODE I TRIED
I get an Overflow error
Sub deleteRows()
Dim sh As Worksheet
Dim rw As Range
Dim RowCount As Integer
RowCount = 1
Application.DisplayAlerts = False
Set sh = ActiveSheet
For Each rw In sh.Rows
If sh.Cells(rw.Row, 1).Value = "21/07/2017" Then
a = RowCount
End If
If sh.Cells(rw.Row, 1).Value = "Field 7" Then
b = RowCount
Rows(a & ":" & b).Delete
End If
RowCount = RowCount + 1
Next rw
End Sub
This will only loop as many times as the pair exists and delete each block as a whole.
The loop ends the first time that both are not found in the remaining values.
Sub myDelete()
Dim str1 As string
Dim str2 As String
Dim rng As Range
Dim ws As Worksheet
Dim i As Long
Dim j As Long
str1 = "21/07/2017"
str2 = "Field 7"
Set ws = Worksheets("Sheet18") 'change to your worksheet
Set rng = ws.Range("A:A")
Do
i = 0: j = 0
On Error Resume Next
i = Application.WorksheetFunction.Match(str1, rng, 0)
j = Application.WorksheetFunction.Match(str2, rng, 0)
On Error GoTo 0
If i > 0 And j > 0 Then
ws.Rows(i & ":" & j).Delete
End If
Loop Until i = 0 Or j = 0
End Sub
If your date is a true date then change str1 to Double:
Dim str1 As Double
and then assign it as such:
str1 = CDbl(DateSerial(2017, 7, 21))

Delete entire Row with zeroes apply to all worksheets

I have VBA code that works to delete entire row when there is an absolute zero value in one a cell column but, I am not able to figure out how to update code to apply to all worksheets (there are 20 Sheets in my workbook):
Can someone help with syntax how to update this code to apply to all worksheets in the workbook.
Sub IfandthenDelete_Button3_Click()
Dim lRow As Long
Dim i As Long
lRow = 3000
Application.ScreenUpdating = False
For i = lRow To 1 Step -1
If Cells(i, 1) = 0 Then
Rows(i).Delete
End If
Next
Application.ScreenUpdating = False
End Sub
You need one more for loop for that.
Sub WorksheetLoop()
Dim wsCount As Integer
Dim j As Integer
Dim lRow As Long
Dim i As Long
lRow = 3000
wsCount = ActiveWorkbook.Worksheets.Count
For j = 1 To wsCount
For i = lRow To 1 Step -1
If ActiveWorkbook.Worksheets(j).Cells(i, 1) = 0 Then
ActiveWorkbook.Worksheets(j).Rows(i).Delete
End If
Next
Next j
End Sub

Issue with Do...Until Function VBA

I have an issue with my VBA code. I try to go through a whole table that has a lot of data. I go through a first column with a first condition required. Once this condition is complete, I go through the column next to the first one but starting at the same position I stopped the previous one. Once the second condition is complete, I try to do a copy paste. But for some reasons I got the error "Subscript out of Range" Could you please help me?
Here is the code:
Sub Match()
Dim i As Integer
i = 0
Dim j As Integer
Do
i = i + 1
Loop Until Sheets("Sheet1").Range("A1").Offset(i, 0).Text = Sheets("Sheet2").Range("I5").Text
j = i
Do
j = j + 1
Loop Until Sheets("Sheet1").Range("B1").Offset(j, 0).Value = Sheets("Sheet2").Range("I11").Value
Sheets("Sheet1").Range("C1").Offset(j, 0).Copy
Sheets("Sheet2").Range("N11").Paste
End Sub
Thanks guys
This should do the same thing without any loops:
Sub Match()
Dim lastA As Long, lastB As Long
Dim i As Long, j As Long
With Sheets("Sheet1")
last a = .Cells(.Rows.count, 1).End(xlUp).Row
last b = .Cells(.Rows.count, 2).End(xlUp).Row
End With
i = WorksheetFunction.Match(Sheets("Sheet2").Range("I5").Text, Sheets("Sheet1").Range("A:A"), 0)
j = WorksheetFunction.Match(Sheets("Sheet2").Range("I11").value, Sheets("Sheet1").Range("B" & i & ":B" & lastB), 0)
Sheets("Sheet2").Range("N11").value = Sheets("Sheet1").Cells(j, 3).value
End Sub
I didn't get the same error as you but I changed the last line and it seems to work.
Sub Match()
Dim i As Integer
i = 0
Dim j As Integer
Do
i = i + 1
Loop Until Sheets("Sheet1").Range("A1").Offset(i, 0).Text = Sheets("Sheet2").Range("I5").Text
j = i
Do
j = j + 1
Loop Until Sheets("Sheet1").Range("B1").Offset(j, 0).Value = Sheets("Sheet2").Range("I11").Value
Sheets("Sheet1").Range("C1").Offset(j, 0).Copy Destination:=Sheets("Sheet2").Range("N11")
End Sub
I did notice that your code runs for ever if you do not get a match which is not good. You may want to add a solution to this. It can be as easy as adding
Or i > 10000 on the Loop Until lines.
I modified your code slightly:
Sub Match()
Dim i As Integer
i = 0
Dim j As Integer
Do
i = i + 1
Loop Until Sheets("Sheet1").Range("A1").Offset(i, 0).Text = Sheets("Sheet2").Range("I5").Text
j = i
Do
j = j + 1
Loop Until Sheets("Sheet1").Range("B1").Offset(j, 0).Value = Sheets("Sheet2").Range("I11").Value
Sheets("Sheet1").Range("C1").Offset(j, 0).Copy Sheets("Sheet2").Range("N11")
End Sub
and it worked fine with data like:
In Sheet1.
Note the B match must be below the A match.

Using VBA to copy data from one worksheet into another worksheet

I have a slight problem in Excel. I need to sync up the values in the curly braces {} found in column C and put them against the user id in column F. I would like this data to be copied across to a new worksheet in the same workbook. Any ideas how I could accomplish this? You don't have to provide any code but a nudge in the right direction would be great.
E.g. on the Emails sheet
becomes this on a new sheet
In case anyone needs help, this is the solution:
Sub CopyConditional()
Dim wshS As Worksheet
Dim WhichName As String
Set wshS = ActiveWorkbook.Sheets("Emails")
WhichName = "NewSheet"
Const NameCol = "C"
Const FirstRow = 1
Dim LastRow As Long
Dim SrcRow As Long
Dim TrgRow As Long
Dim wshT As Worksheet
Dim cpt As String
Dim user As String
Dim computers() As String
Dim computer As String
On Error Resume Next
Set wshT = Worksheets(WhichName)
If wshT Is Nothing Then
Set wshT = Worksheets.Add(After:=wshS)
wshT.Name = WhichName
End If
On Error GoTo 0
If wshT.Cells(1, NameCol).value = "" Then
TrgRow = 1
Else
TrgRow = wshT.Cells(wshT.Rows.Count, NameCol).End(xlUp).Row + 1
End If
LastRow = wshS.Cells(wshS.Rows.Count, NameCol).End(xlUp).Row
For SrcRow = FirstRow To LastRow
cpt = wshS.Range("C" & SrcRow).value
user = wshS.Range("F" & SrcRow).value
If InStr(cpt, ":") Then
cpt = Mid(cpt, InStr(1, cpt, ":") + 1, Len(cpt))
End If
If InStr(cpt, ";") Then
computers = Split(cpt, ";")
For i = 0 To UBound(computers)
If computers(i) <> "" Then
wshT.Range("A" & TrgRow).value = user
wshT.Range("B" & TrgRow).value = Mid(Left(computers(i), Len(computers(i)) - 1), 2)
TrgRow = TrgRow + 1
End If
Next
Else
computer = cpt
If computer <> "" Then
wshT.Range("A" & TrgRow).value = user
wshT.Range("B" & TrgRow).value = Mid(Left(computer, Len(computer) - 1), 2)
TrgRow = TrgRow + 1
End If
End If
Next SrcRow
End Sub
You didn't ask a question. Basically what you would do is
loop through the values in column F
for each value, get the value in column C
loop through all braced values in column C
let braceValue = parse column C searching for {value}
create a row in new worksheet with column F value, braceValue