I need a way to replace values in my primary worksheet (main) with values from my secondary worksheet (update).
my main worksheet has these column names: EmpName, EmpID, EmpSupervisor, Emp Director.
and my secondary worksheet: EmpName, EmpID, New Sup, NewDir, Status.
if an entry in the 2nd worksheet has STATUS listed as "mismatch", it will automatically pass the "new sup" and/or "new dir" data with the corresponding EmpID and overwrite "empsupervisor" and/or "empdirector" in the primary sheet.
something like this, i just can't put it in a correct syntax that vba can understand.
for each STATUS = Mismatch in worksheet2
update worksheet1.column("Empsupervisor") with worksheet2.column("New Sup").value
where worksheet1.column("EmpID") = worksheet2.column("EmpID")
next
This method loops through all rows, checks for mismatch, finds the employee ID row, then moves the new supervisor and new director into the first sheet:
Sub TestIt()
Dim LastRow As Long, CurRow As Long, DestRow As Long, DestLast As Long
Dim ws1 As Worksheet, ws2 As Worksheet
Set ws1 = Sheets("Name of main worksheet")
Set ws2 = Sheets("Name of secondary worksheet")
LastRow = ws2.Range("B" & Rows.Count).End(xlUp).Row
DestLast = ws1.Range("B" & Rows.Count).End(xlUp).Row
For CurRow = 2 To LastRow 'Assumes first row has headers
If ws2.Range("E" & CurRow) = "mismatch" Then 'Assumes mismatch is in column E
If Not ws1.Range("B2:B" & DestLast).Find(ws2.Range("B" & CurRow).Value, LookIn:=xlValues, LookAt:=xlWhole) Is Nothing Then
DestRow = ws1.Range("B2:B" & DestLast).Find(ws2.Range("B" & CurRow).Value, LookIn:=xlValues, LookAt:=xlWhole).Row
End If
ws1.Range("C" & DestRow).Value = ws2.Range("C" & CurRow).Value 'assumes supervisor is in column C in both sheets
ws1.Range("D" & DestRow).Value = ws2.Range("D" & CurRow).Value 'assumes director is in column D in both sheets
End If
Next CurRow
End Sub
Explanation of LastRow:
Range("B" & Rows.Count) goes to the last row on the sheet which is Row 1,048,576 in Excel '07, '10, and '13. So imagine Range("B1048576"). Then it performs End(xlUp) which is "Equivalent to pressing END+UP ARROW" according to MSDN. This will go to the first cell in column B that is non-blank above B1048576. The last command .Row returns that row number of the cell.
Explanation of DestRow:
We are using a Range.Find() method to identify if the employeeID exists in the first worksheet and on what row it exists. Range.Find() returns a range which is why I use Range.Find().Row because when found, we want to know the row we are going to. However, if Find() doesn't find anything, it returns Nothing and Nothing.Row would error. Therefore I do a quick If Not Find() Nothing to make sure the value is found.
Related
In my scenario I have four columns, columns A-D. If column B contains any value whatsoever then the matching row in column A must be updated to contain a predetermined value. The same macro is applied for columns C and D. I have code right now that achieves that result:
Sub Update_Column_Based_On_Column_Value1()
On Error Resume Next
Dim ws As Worksheet
Dim lRow As Long
Set ws = ThisWorkbook.Sheets("Sheet1")
With ws
lRow = .Range("B" & .Rows.Count).End(xlUp).Row
.Range("A1:A" & lRow).SpecialCells(xlCellTypeBlanks).Formula = "=If(B1<>"""",""PREDETERMINED VALUE"","""")"
.Range("A1:A" & lRow).Value = .Range("A1:A" & lRow).Value
End With
End Sub
When column B contains a value the macro will write "PREDETERMINED VALUE" in the corresponding cell in column A.
An issue occurs when a column does not contain any values at all. What happens is the macro will write my new value to nearly all of the blank cells in the entire data-set.
Thank you in advance for your time! I apologize if my question is noobish, I am still very new to VBA.
The use of If WorksheetFunction.CountA(ws.Range("B:B")) = 1 in the comment section to avoid the problem is a good attempt but there can be exceptions as discussed below. Test it several times using various scenarios (especially using blank range) to see if you are getting the desired result every single time.
.SpecialCells attempts to simplify the codes, however sometime the .SpecialCells(xlCellTypeBlanks) VBA function does not work as expected in Excel.
Also, the statement On Error Resume Next shouldn't be used as far as practicable. But if you must, be sure to insert the On Error GoTo 0 statement ASAP as you don't want to mask other errors.
Instead of .SpecialCells, you may use For Each loop to avoid this problem. So let's see how it looks:
Sub Update_Column_Based_On_Column_Value1()
Dim ws As Worksheet, lRow As Long, r As Range
Set ws = ThisWorkbook.Sheets("Sheet1")
With ws
lRow = .Range("B" & .Rows.Count).End(xlUp).Row
For Each r In .Range("A1:A" & lRow)
If IsEmpty(r) Then
r.Formula = "=If(B" & r.Row & "<>"""",""PREDETERMINED VALUE"","""")"
r = r.Value
End If
Next
End With
End Sub
Here is the answer everyone!
Sub Update_Column_Based_On_Column_Value_1()
On Error Resume Next
Dim ws As Worksheet
Dim lRow As Long
Set ws = ThisWorkbook.Sheets("Sheet1")
If WorksheetFunction.CountA(ws.Range("B:B")) = 1 Then
Else
With ws
lRow = .Range("B" & .Rows.Count).End(xlUp).Row
.Range("A1:A" & lRow).SpecialCells(xlCellTypeBlanks).FormulaR1C1 = "=If(LEN(RC2),""NEW TEXT HERE"", TEXT(,))"
.Range("A1:A" & lRow).Value = .Range("A1:A" & lRow).Value
End With
End If
End Sub
The title of the question might be a little confusing but essentially what I am trying to do is write a value to column A if Column B is not empty. This must be repeated for C through Q. The code I have now produces the desired result IF there is value in the B column. However, if there is no value for B then my replacement text will fill in all sorts of blank cells outside of the target range of A1:A. Here is the code I have:
Sub Update_Column_Based_On_Column_Value_1()
On Error Resume Next
Dim ws As Worksheet
Dim lRow As Long
Set ws = ThisWorkbook.Sheets("Sheet1")
With ws
lRow = .Range("B" & .Rows.Count).End(xlUp).Row
.Range("A1:A" & lRow).SpecialCells(xlCellTypeBlanks).Formula = "=If(B1<>"""",""NEW VALUE"","""")"
.Range("A1:A" & lRow).Value = .Range("A1:A" & lRow).Value
End With
End Sub
I am fairly new to VBA so please forgive any vagueness in my post.
Instead of inserting formulas and getting their values afterwards, you can do the same logic by using pure VBA:
Sub Update_Column_Based_On_Column_Value_1()
Dim ws As Worksheet
Dim lRow As Long
Set ws = ThisWorkbook.Sheets("Sheet1")
With ws
lRow = .Range("B" & .Rows.Count).End(xlUp).Row
For i = 1 To lRow
If .Cells(i, 2) <> "" Then
.Cells(i, 1) = "NEW VALUE"
End If
Next i
End With
End Sub
This formula will only work if A1 is the first blank.
.Range("A1:A" & lRow).SpecialCells(xlCellTypeBlanks).Formula = "=If(B1<>"""",""NEW VALUE"","""")"
.SpecialCells(xlCellTypeBlanks) may be a discontiguous range of areas that may or may not start in row 1. You need to convert it to an xlR1C1 style formula in order to have it correctly identify the first blank row.
.Range("A1:A" & lRow).SpecialCells(xlCellTypeBlanks).FormulaR1C1 = "=If(LEN(RC2),""NEW VALUE"", TEXT(,))"
TEXT(,) is the same as "" and you do not have to double-up the quotes within a quoted string; similarly, any positive number representing the length of a value in column B is the same as <>"".
So I have a macro which takes an invoice I have copied into a worksheet, and copies the premium amount and pastes it onto the summary tab in the cell that corresponds with the same social security number on both sheets. Here is the macro:
Sub Eyemed2()
Dim rw, LastRow, LastRRow As Long
Dim rng As Range, Found As Range, SheetEnd3 As Range
Dim ws1 As Worksheet, ws2 As Worksheet
Set ws1 = Sheets("Eyemed 2")
Set ws2 = Sheets("Raw")
LastRow = ws2.Cells(Rows.Count, "A").End(xlUp).Offset(1, 0).Row
Set rng = ws2.Range("A2:B" & LastRow)
LastRRow = ws1.Cells(Rows.Count, "R").End(xlUp).Row
For rw = 14 To LastRRow 'Begin in row 14 of Eyemed 2
If Not ws1.Range("R" & rw) Is Nothing Then
is blank
Set Found = rng.Find(What:=ws1.Range("A" & rw).Value,
LookIn:=xlValues)
If Not Found Is Nothing Then
ws2.Range("N" & Found.Row) = ws1.Cells(rw, "J").Value
Else
Set SheetEnd3 = rng.Find(What:=ws1.Range("A" & rw).Value,
LookIn:=xlValues)
LastRow = ws2.Cells(Rows.Count, "B").End(xlUp).Offset(1, 0).Row
ws1.Range("A" & rw).Copy ws2.Range("B" & LastRow)
ws2.Range("N" & SheetEnd3.Row) = ws1.Cells(rw, "J").Value
End If
End If
Next rw
End Sub
So it looks at column R in 'Eyemed 2' and if it isn't blank, then copy over the cell in column N into the summary tab, column J. It finds the appropriate row to paste in the summary tab by searching for the social security number in column A of 'Eyemed 2' in column A:B in the summary tab.
My issue is that in 'Eyemed 2', some of the social security numbers are listed more than once with two different amounts. So I need to edit the macro to sum all amounts with the same social security number and then search and paste into one entry in the summary tab as opposed to now where it just copies and pastes one amount.
Thank you very much
If there are multiple matches then this just leaves you with the last value found:
ws2.Range("N" & Found.Row) = ws1.Cells(rw, "J").Value
...but this will add each value to any previous value
With ws2.Range("N" & Found.Row)
.Value = .Value + ws1.Cells(rw, "J").Value
End with
I have sheet 1 with Column name: Main task
MainTask
And, I have Sheet 2 where the Sub-tasks are given based on the characters between 1st and 2nd hyphen(-) of the Data in Main Task for eg: Under the main task column there is "Pyramid - IoT Forecast - Latin America - Argentina - 2017". So, based on the string " IoT Forecast" the sub tasks are given as in the below image.
Out Put:
Now In sheet 3 I need every title from the main task should be copied and pasted from the Sheet 1 and look for relevant sub tasks and pasted in the next column like the below image.
I have used, Wild cards, partial V-look up with Mid Function but only single sub task is populating. Please help me provide code in VBA.
Your Sheet 3 is identical to Sheet 2 but with the full main task in it instead of just the extract. I suggest the following method.
Create a column in Sheet 1 in which you write only the extract. This column would be identical in contents to column A of sheet 2. Use this formula to populate that column (where A2 contains the full main task).
=TRIM(LEFT(MID($A2,FIND("-",$A2)+1,100),FIND("-",MID($A2,FIND("-",$A2)+1,100))-1))
Make a copy of Sheet 2 as Sheet 3 and add a blank column B in it. Populate this column with this formula (where A:A is the column containing the full task, and C:C the column you added in step 1.
=INDEX('Sheet 1'!A:A,MATCH(A2,'Sheet 1'!C:C,0))
Replace the formulas in Sheet 3 with values (Copy / Paste values) and Remove column A from that sheet. Sort this sheet on what is now column A.
Remove the column you added in Sheet 1 to restore Sheet 1 to its original state.
You will need to do an array formula, something similar to the below where the sub category is in C1
=INDEX($A$2:$A$6,SMALL(IF(NOT(ISERROR(SEARCH("-" & $C$1 & "-",$A$2:$A$6))),ROW($A$2:$A$6)-1),ROWS($D$1:D1)))
If you are open to a VBA solution, you may try something like this.
The following code assumes that there are three sheets in the workbook named as "Sheet1", "Sheet2" and "Sheet3".
If the sheet names are different in your original workbook, please change them in the code in following lines before testing the code.
Set ws1 = Sheets("Sheet1")
Set ws2 = Sheets("Sheet2")
Set ws3 = Sheets("Sheet3")
Place the following code on a Standard Module and run the code to get the desired output on Sheet3.
Sub LookupData()
Dim ws1 As Worksheet, ws2 As Worksheet, ws3 As Worksheet
Dim rng As Range, cell As Range, MainTask As Range
Dim lr2 As Long, lr3 As Long
Dim MainTaskStr As String, wht As String
Application.ScreenUpdating = False
Set ws1 = Sheets("Sheet1")
Set ws2 = Sheets("Sheet2")
Set ws3 = Sheets("Sheet3")
lr2 = ws2.Cells(Rows.Count, 1).End(xlUp).Row
Set rng = ws2.Range("A2:A" & lr2)
ws3.Cells.Clear
ws3.Range("A1:B1").Value = Array("Main Task", "Sub-Task")
If ws2.FilterMode Then ws2.ShowAllData
For Each cell In rng
If cell.Value <> MainTaskStr Then
MainTaskStr = cell.Value
lr3 = ws3.Cells.Find("*", SearchOrder:=xlByRows, SearchDirection:=xlPrevious).Row + 1
wht = "- " & cell.Value & " -"
Set MainTask = ws1.Range("A:A").Find(what:=wht, LookIn:=xlValues, lookat:=xlPart, MatchCase:=False)
If Not MainTask Is Nothing Then
With ws2.Rows(1)
.AutoFilter field:=1, Criteria1:=MainTaskStr
ws3.Range("A" & lr3) = MainTask.Value
ws2.Range("B2:B" & lr2).SpecialCells(xlCellTypeVisible).Copy ws3.Range("B" & lr3)
End With
End If
End If
Next cell
If ws2.FilterMode Then ws2.AutoFilterMode = False
ws3.UsedRange.Columns.AutoFit
Application.ScreenUpdating = True
End Sub
I am attempting to copy and paste Rows from an original sheet (Ticket Sales) to a new Sheet (Rachel) based on the value in a specific Column for each Row (Column U). I want all the sales from Rachel to be copied over to another sheet, pretty much. No change in the formatting for the second sheet. This is what I have so far:
Sub CopyRachelDataPaste()
Dim i, LastRow
'Get Last Row
LasRow = Sheets("Ticket Sales").Range("A" & Rows.Count).End(xlUp).Row
'Clear Contents
Sheets("Rachel").Range("A2:AB3000").ClearContents
For i = 2 To LastRow
If Sheets("Ticket Sales").Cells(i, "U").Value = "Rachel" Then
Sheets("Ticket Sales").Cells(i, "U").EntireRow.Copy Destination:=Sheets("Rachel").Range("A" & Rows.Count).End(xlUp).Offset(1)
End If
Next i
End Sub
you must properly reference worksheet in all range definitions
like follows:
Option Explicit
Sub CopyRachelDataPaste()
Dim i As Long, lastRow As Long
Worksheets("Rachel").Range("A2:AB3000").ClearContents 'Clear Contents
With Worksheets("Ticket Sales") '<--| reference ticket worksheet
lastRow = .Range("A" & .Rows.Count).End(xlUp).Row '<--| get referenced worksheet column "A" last non empty row
For i = 2 To lastRow
If .Cells(i, "U").Value = "Rachel" Then .Cells(i, "U").EntireRow.Copy Destination:=Worksheets("Rachel").Range("A" & Worksheets("Rachel").Rows.Count).End(xlUp).Offset(1)
Next i
End With
End Sub