Changing a value of a cell based on another cell - excel

What I want to do is if column O contains "weekend" then change the value of column M cells to "3".
Sub weekly_weekend()
lastrow = Sheet1.Cells(Rows.Count, 1).End(xlUp).Row
Application.ScreenUpdating = False
For x = 2 To lastrow
If InStr(1, Sheet1.Range("O" & x).Value, UCase("weekend"), 1) > 0 Then
Sheet1.Range("M" & x).Value = "3"
Next x
Application.ScreenUpdating = True
End Sub

The problem with your code is that you're getting the last row of the column A, and this will prevent the For to be executed. To fix your code, you can proceed in multiple ways.
Using Range
One is to use the Range property, so you can explicitly write your column name, like this:
Sub weekly_weekend()
lastrow = Sheet1.Range("O" & Sheet1.Rows.Count).End(xlUp).Row
Application.ScreenUpdating = False
For x = 2 To lastrow
If InStr(1, Sheet1.Range("O" & x).Value, UCase("weekend"), 1) > 0 Then Sheet1.Range("M" & x).Value = "3"
Next x
Application.ScreenUpdating = True
End Sub
Picking up the right column
Or you can simply pick the right number of the column you want (in this case column O is 15), like this:
Sub weekly_weekend()
lastrow = Sheet1.Cells(Sheet1.Rows.Count, 15).End(xlUp).Row
Application.ScreenUpdating = False
For x = 2 To lastrow
If InStr(1, Sheet1.Range("O" & x).Value, UCase("weekend"), 1) > 0 Then Sheet1.Range("M" & x).Value = "3"
Next x
Application.ScreenUpdating = True
End Sub
Note: Please note that if you add or remove columns, with the second method you'll need to remember to change the column index in your code accordingly.
Hope this helps.

Related

Remove Row(s) Based on Duplicate Values When Comparing 2 Row Cells To Below Row Cells in Same Column in Spreadsheet

I am attempting to remove (mostly) duplicate rows from a very large spreadsheet.
I can tell that the row is duplicate if the values in two cells per row are the same.
Here is an example:
1 a ewq
1 e weq
1 h ewq
2 b ddsfa
2 b as
2 i d
3 c fdsa
3 f ads
4 d fd
4 g as
In this example, the fourth and fifth rows would be duplicate because the values in column "A" and column "B" are the same. The deciding values will always be found in the same columns.
I would like to get rid of either the fourth or fifth row based on the duplicate status and shift the rows up.
I'm not even sure if this is close, but this is what I have so far (I'm getting a mismatch error):
Sub MasterRemoveDuplicates()
Dim Master As Worksheet
Application.ScreenUpdating = False
Application.DisplayAlerts = False
Set Master = Workbooks("Master.csv").Worksheets("Master")
Last = 1
For i = 1 To 18211
If Range("A" & i) And Range("B" & i) <> Range("A" & (i + 1)) And Range("B" & (i + 1)) Then
Worksheets("Master").Rows(Last).Delete Shift:=xlShiftUp
Last = i + 1
Master.Activate
End If
Next i
MsgBox "Completed!", vbInformation, ""
reset_settings:
Application.ScreenUpdating = True
Application.DisplayAlerts = True
End Sub
Any thoughts on how I could achieve this would be greatly appreciated!
P.S. Everything is in the same worksheet.
You're trying to reinvent the wheel. There is a ready-made RemoveDuplicates command.
Sub MasterRemoveDuplicates()
Application.ScreenUpdating = False
Application.DisplayAlerts = False
With Workbooks("Master.csv").Worksheets("Master")
With .Range(.Cells(1, "A"), .Cells(.Rows.Count, "A").End(xlUp).Offset(0, 2))
.RemoveDuplicates Columns:=Array(1, 2), Header:=xlNo
End With
End With
MsgBox "Completed!", vbInformation, ""
reset_settings:
Application.ScreenUpdating = True
Application.DisplayAlerts = True
End Sub
You have a mistake in if statement
try this:
If Range("A" & i) <> Range("A" & (i + 1)) And Range("B" & i) <> Range("B" & (i + 1)) Then

Index/Match in VBA

I tried several ways, but I still have a problem in my code.
What I want to do (this example in Q2 on Sheet4):
=INDEX('Sheet8'!K:K,MATCH('Sheet4'!P2,'Sheet8'!A:A,0))
I'd like to do it for all rows with content in column K on Sheet 4 so I'll probably need "For i = 1..."
What I tried:
For i = 1 To LastRowShort
row_mtch = Application.WorksheetFunction.Match(Sheet4.Cells("Q????").Value, Sheet8.Range("A1:A"), 0)
Sheet4.Range("R" & i).Value = Application.WorksheetFunction.Index(Sheet8.Range("K1:K" & LastRowShort), row_mtch)
Next i
Thanks a lot!
Andy
Entire Module:
Sub MissingBoth()
Application.ScreenUpdating = False
Dim MyRange, CopyRange As Range
Dim LastRow As Long
Dim LastRowSheet4 As Long
Dim LastRowSheet8 As Long
Set src4 = Sheet2
Set dst4 = Sheet4
LastRow = src4.Cells(Cells.Rows.Count, "D").End(xlUp).Row
LastRowSheet8 = Worksheets("Sheet8").Cells(Cells.Rows.Count, "B").End(xlUp).Row
LastRowSheet4 = Worksheets("Sheet4").Cells(Cells.Rows.Count, "K").End(xlUp).Row
src4.Unprotect
dst4.Unprotect
If src4.FilterMode = True Then
src4.ShowAllData
End If
dst4.Cells.ClearFormats
dst4.Cells.Clear
'Find content in the "Type of Rack" cells
j = 3
For i = 10 To LastRow
If src4.Cells(i, "CL").Value = "" And src4.Cells(i, "GV").Value = "" Then
src4.Cells(i, "CL").EntireRow.Copy dst4.Cells(j, 1)
j = j + 1
End If
Next i
src4.Range("A6:GW7").Copy Destination:=dst4.Range("A1:GW2")
'Copy every column EXCEPT the following
dst4.Range("GW1,CM1:GU1, U1:CK1,R1:S1,P1,J1:M1").EntireColumn.Delete
For i = 1 To LastRowSheet4
For i2 = 1 To LastRowSheet8
If Worksheets("Sheet4").Range("P" & i).Value = Worksheets("Sheet8").Range("A" & i2).Value Then
Worksheets("Sheet4").Range("Q" & i).Value = Worksheets("Sheet8").Range("K" & i2).Value
End If
Next i2
Next i
dst4.Columns("A:AX").EntireColumn.AutoFit
dst4.Rows("1:500").RowHeight = 15
dst4.Columns("N:O").Interior.Color = vbYellow
dst4.Rows("1:2").Interior.ColorIndex = 15
dst4.Range("B:I").EntireColumn.Hidden = True
Application.ScreenUpdating = True
End Sub
Have you tried something like the following code:
For i = 1 To LastRowSheet4
For i2 = 1 To LastRowSheet8
If Worksheets("Sheet4").Range("P" & i).Value = Worksheets("Sheet8").Range("A" & i2).Value Then
Worksheets("Sheet4").Range("Q" & i).Value = Worksheets("Sheet8").Range("K" & i2).Value
End If
Next i2
Next i
You will just need to define the upper ends of both sheets (LastRowSheet4 and LastRowSheet8) and this should work.
Thanks for your help. I solved the problem with recording a macro and modifying it:
Sheet4.Cells(3, 17).FormulaR1C1 = _
"=INDEX('TS-48 Matrix'!C[-7],MATCH('Missing Both'!RC[-1],'TS-48 Matrix'!C[-16],0))"
Range("Q3").AutoFill Destination:=Range("Q3:Q" & lastRowSheet4)

Excel VBA - Adding 'If 0 in First Row' To Existing Macro

I have the following VBA Macro -
Sub CopyData()
Application.ScreenUpdating = False
Dim CRow As Integer
Dim CColBRange As String
Dim PColBRange As String
Dim Continue As Boolean
'Select Sheet1
With Sheets("KG9New")
.Select
'Initialize variables
Continue = True
CRow = 1
While Continue = True
CRow = CRow + 1
'Test B2:
If CRow = 2 And Cells(CRow, 2).Value = 0 Then
Range("A" & CStr(CRow) & ":C" & CStr(CRow)).Copy
Sheets("Sheet2").Cells(Rows.Count, 1).End(xlUp).Offset(1, 0).PasteSpecial xlPasteValues
CRow = CRow + 1
End If
CColBRange = "B" & CStr(CRow)
PColBRange = "B" & CStr(CRow - 1)
'Break loop upon finding blank cell.
If Len(Range(CColBRange).Value) = 0 Then
Continue = False
End If
'Copy first instance of each changing Value in MachineRunning.
If Range(CColBRange).Value <> Range(PColBRange).Value Then
Range("A" & CStr(CRow) & ":C" & CStr(CRow)).Copy
Sheets("Sheet2").Cells(Rows.Count, 1).End(xlUp).Offset(1, 0).PasteSpecial xlPasteValues
End If
Wend
End With
Application.ScreenUpdating = True
End Sub
Basically, This scans through Column B of my table and copies values across to a new sheet when the value changes from a 1 to a 0 or 0 to 1.
My issue is that this assumes that the first value (in B2) will be a 1. I would like it to return Row 2 values if B2=0.
I tried changing the initialized CRow to 1, but this returns row 2 whether it is a 1 or 2 (due to it being different from the header, I guess).
Could somebody help me out please?
Change your CRow to 1, like you thought. You can't test B2 if you are never at that cell. Then you just need to do an IF statement.
Sub CopyData()
Application.ScreenUpdating = False
Dim CRow As Integer
Dim CColBRange As String
Dim PColBRange As String
Dim Continue As Boolean
'Select Sheet1
Sheets("KG9New").Select
'Initialize variables
Continue = True
CRow = 1
While Continue = True
CRow = CRow + 1
'Test B2:
If CRow=2 and Cells(CRow, 2).value = 0 Then
CRow = 3
End if
CColBRange = "B" & CStr(CRow)
PColBRange = "B" & CStr(CRow - 1)
'Break loop upon finding blank cell.
If Len(Range(CColBRange).Value) = 0 Then
Continue = False
End If
'Copy first instance of each changing Value in MachineRunning.
If Range(CColBRange).Value <> Range(PColBRange).Value Then
Range("A" & CStr(CRow) & ":C" & CStr(CRow)).Copy
Sheets("Sheet2").Cells(Rows.Count, 1).End(xlUp).Offset(1, 0).PasteSpecial xlPasteValues
End If
Wend
Application.ScreenUpdating = True
End Sub
The additional If statement just tests to see if we are on row 2 and if that value is 0. If it is, then change CRow to 3 and it will continue on.
I also removed the superfluous With block. I couldn't see anywhere else in the Macro where that format was being used.

How to optimize Macro Code That Looks into 2 Worksheets

Problem:
I have 1 Excel Sheet with 2 tabs
Tab 1 = Shipment Package
Tab 2 = Mass Update Steps
I want to go through all the values in column B of Tab 2 one by one.
As I go through each row in Tab 2, I will select and copy the values in column C and D of Tab 2.
After selecting and copying, I want to find Tab 2-column B's corresponding values in Tab 1 column G.
If a match is found, I will select column E of Tab 1 (in row where the match was found), and paste there the values copied from Tab 2.
So far this is the code I have which works. However the values from being searched are hard coded. With the values growing in number in Tab 2, the code is hard to maintain. I would like to optimize it. I have googled several possible solutions. But I keep on getting these run-time errors when declaring or setting the range for the 2 sheets. Here is my code.
Private Sub btn_Updt_Steps_Click()
Dim lastRow As Long
With Sheets("Shipment Package")
.Activate
lastRow = .Range("G65000").End(xlUp).Row
For i = 1 To lastRow
If (InStr(1, .Range("G" & i).Value, "Code 001", vbTextCompare) > 0) Then
Sheets("Mass Update Steps").Activate
ActiveSheet.Range("C4:D4").Select
Selection.Copy
Sheets("Shipment Package").Activate
.Range("E" & i).Select
ActiveSheet.Paste
ElseIf (InStr(1, .Range("G" & i).Value, "Code 002", vbTextCompare) > 0) Then
Sheets("Mass Update Steps").Activate
ActiveSheet.Range("C5:D5").Select
Selection.Copy
Sheets("Shipment Package").Activate
.Range("E" & i).Select
ActiveSheet.Paste
ElseIf (InStr(1, .Range("G" & i).Value, "Code 003", vbTextCompare) > 0) Then
Sheets("Mass Update Steps").Activate
ActiveSheet.Range("C6:D6").Select
Selection.Copy
Sheets("Shipment Package").Activate
.Range("E" & i).Select
ActiveSheet.Paste
End If
Next
End With
NotFoundErr:
Debug.Print "value not found"
End Sub
Solution:
Private Sub btn_Updt_Steps_Click()
Dim i As Long
Dim j As Long
Dim Tab2ColC As String
Dim Tab2ColD As String
Dim Tab1ColE As String
Dim Tab1ColF As String
Tab1 = "Shipment Package"
Tab2 = "Mass Update Steps"
With Worksheets(Tab1)
LastRowTab1 = .Cells(.Rows.Count, "G").End(xlUp).Row 'LastRowInColumn(2, Tab1)
End With
With Worksheets(Tab2)
LastRowTab2 = .Cells(.Rows.Count, "B").End(xlUp).Row 'LastRowInColumn(2, Tab2)
End With
For i = 4 To LastRowTab2
Tab2ColumnB = Trim(Sheets(Tab2).Range("B" & i).Value)
Sheets(Tab2).Activate
If Tab2ColumnB <> "" Then
Tab2ColC = "C" & i
Tab2ColD = "D" & i
ActiveSheet.Range(Tab2ColC, Tab2ColD).Copy
For j = 16 To LastRowTab1
Tab1ColumnG = Trim(Sheets(Tab1).Range("G" & j).Value)
If Tab1ColumnG = Tab2ColumnB Then
Sheets(Tab1).Activate
Tab1ColE = "E" & j
Tab1ColF = "F" & j
Sheets(Tab1).Range(Tab1ColE, Tab1ColF).Select
ActiveSheet.Paste
End If
Next
End If
Next
End Sub
For optimization, you can avoid select statements, activate statements etc. Check the code below.
For i = 1 To lastRow
Application.ScreenUpdating = False
If YourCondn1 Then
Sheets("Mass Update Steps").Range("C4:D4").Copy
Sheets("Shipment Package").Range("E" & i).PasteSpecial xlPasteAll
ElseIf YourCondn2 Then
Sheets("Mass Update Steps").Range("C5:D5").Copy
Sheets("Shipment Package").Range("E" & i).PasteSpecial xlPasteAll
ElseIf YourCondn3 Then
Sheets("Mass Update Steps").Range("C6:D6").Copy
Sheets("Shipment Package").Range("E" & i).PasteSpecial xlPasteAll
End If
Application.ScreenUpdating = True
Next
Adding the code that you require. Hope this will work. I haven't tested it. Please check.
Private Sub btn_Updt_Steps_Click()
'Finding LastRow in Tab 2
Tab1 = "Shipment Package"
Tab2 = "Mass Update Steps"
With Worksheets(Tab2)
LastRowTab2 = .Cells(.Rows.Count, 2).End(xlUp).Row 'LastRowInColumn(2, Tab2)
End With
MatchFound = 0
For i = 1 To LastRowTab2
'checking whether value in tab2 column b is same as tab1 column g
Tab2ColumnB = Trim(Sheets(Tab2).Range("B" & i).Value)
Tab1ColumnG = Trim(Sheets(Tab1).Range("G" & i).Value)
If Tab2ColumnB = Tab1ColumnG Then
Tab2ColumnC = Trim(Sheets(Tab2).Range("C" & i).Value)
Tab2ColumnD = Trim(Sheets(Tab2).Range("D" & i).Value)
Sheets(Tab1).Range("E" & i).Value = Tab2ColumnC
Sheets(Tab1).Range("F" & i).Value = Tab2ColumnD
MatchFound = MatchFound + 1
End If
Next
If MatchFound = 0 Then
MsgBox "No matches found"
ElseIf MatchFound > 0 Then
MsgBox MatchFound & " matches were found."
End If
End Sub
I think you can achieve what you want with simple Excel formulas.
In Shipment Package, type the following into E1 and F1 and then drag formula down:
E1 = VLOOKUP(G1,'Mass Update Steps'!$B$1:$D$20,2,0)
F1 = VLOOKUP(G1,'Mass Update Steps'!$B$1:$D$20,3,0)
NB - you'll need to amend $B$1:$D$20 depending on how much data you have in Mass Update
Finally, this assumes that there is always a match. If not, and you want to get rid of those pesky #N/A values, then update the formuals with ISNA e.g.
E1 = IF(ISNA(VLOOKUP(G1,'Mass Update Steps'!$B$1:$D$4,2,0)),"",VLOOKUP(G1,'Mass Update Steps'!$B$1:$D$4,2,0))
Hope that helps.

Excel macro - unable to call cell value

In my worksheet some cells values are based on other cells
Info worksheet
A1: 5
B1: =A1
Design worksheet
A1:
Is there a way to copy and read the value in B1? I'm trying to use the value in a for loop, with no luck.
Sheets("Info").Select
For i = 1 to 5
If Range("B" & i).Value <> 0 Then
Range("B" & i).Copy Destination:=Sheets("Design").Range("A" & x)
'Sheets("Design").Range("A" & x).Value = Sheets("Offerte").Range("B" & i).Value
x = x + 1
End If
Next i
Your example doesn't seem to match the code well. The line
If Range("B" & i).Value = 1 Then
means that nothing will be copied in your example. It's looking for a cell with 1 in it. Why do you need that If statement at all?
EDIT I am guessing you're just checking that there's something in the cell to copy? I would probably do it this way:
If Trim(Range("B" & i).Value) <> "" Then
Also - did you miss out setting x=1?
There is more than one way to do it. One of them is using 'offset', which is a function that really worth understand. It basically points to a amount of rows / columns from the original cell.
Sub test()
Dim oCell As Excel.Range
Dim i As Integer
Dim x As Integer
Set oCell = Sheets("Info").Range("B1")
x = 1
For i = 1 To 5
If oCell.Offset(i, 0).Value = 1 Then
oCell.Offset(i, 0).Copy Destination:=Sheets("Design").Range("A" & x)
x = x + 1
End If
Next i
End Sub
Besides, you can assert the value instead of using the copy property. Notice it won't work unless x is an integer > 0.
Sub test2()
Sheets(3).Select
x = 1
For i = 1 To 5
If Range("B" & i).Value = 1 Then
Sheets(4).Range("A" & x).Value = Range("B" & i).Value
'Sheets("Design").Range("A" & x).Value = Sheets("Offerte").Range("B" & i).Value
x = x + 1
End If
Next i
End Sub

Resources