copy selected columns in a row to another sheet if a cell meets a condition - excel

(not in a range, not adjacent columns)
(in given order)
I have many rows on Sheet1. I would like to copy some columns of a row (not the entire row and not a range of columns) to Sheet2 (to the first empty row of Sheet2) if a cell satisfies a condition (the cell in the current row and A column has a value of y)
I would like to copy not the entire row from Sheet1 only the row with those columns that are given on Sheet3 (Column A), and the new column number (on Sheet2) is also given on Sheet3 (column B)
It would be simple if my task would be to copy the entire row, or the selected column would be in a range...but i would need to copy those columns that are specialized on Sheet3. I would be grateful for any help. Thanks in advance.
Sheet1 shows an example data sheet. The criteria is if Cells(Rows, 1).Value = "y"
Sheet2 shows the desired result.
Sheet3 shows the selected column number on Sheet1 and the new column number on Sheet2

Whilst this probably should be done using arrays more, here's some basic VBA code that loops the first sheet checking for "y" in the first column. When it finds it, it then loops the column mappings in the third sheet that have been saved into arrays to set the values on the second sheet:
Sub sTranasferData()
On Error GoTo E_Handle
Dim aOld() As Variant
Dim aNew() As Variant
Dim wsIn As Worksheet
Dim wsOut As Worksheet
Dim wsTrack As Worksheet
Dim lngLastRow As Long
Dim lngLoop1 As Long
Dim lngLoop2 As Long
Dim lngRow As Long
Dim lngTrack As Long
Set wsIn = Worksheets("Sheet1")
Set wsOut = Worksheets("Sheet2")
Set wsTrack = Worksheets("Sheet3")
lngLastRow = wsIn.Cells(wsIn.Rows.Count, "A").End(xlUp).Row
lngTrack = wsTrack.Cells(wsTrack.Rows.Count, "A").End(xlUp).Row
aOld() = wsTrack.Range("A2:A" & lngTrack).Value
aNew() = wsTrack.Range("B2:B" & lngTrack).Value
lngRow = 1
For lngLoop1 = 2 To lngLastRow
If wsIn.Cells(lngLoop1, 1) = "y" Then
For lngLoop2 = LBound(aOld) To UBound(aOld)
wsOut.Cells(lngRow, aNew(lngLoop2, 1)) = wsIn.Cells(lngLoop1, aOld(lngLoop2, 1))
Next lngLoop2
lngRow = lngRow + 1
End If
Next lngLoop1
sExit:
On Error Resume Next
Set wsIn = Nothing
Set wsOut = Nothing
Set wsTrack = Nothing
Exit Sub
E_Handle:
MsgBox Err.Description & vbCrLf & vbCrLf & "sTransferData", vbOKOnly + vbCritical, "Error: " & Err.Number
Resume sExit
End Sub
Regards,

Related

VBA execute Sumif function across sheets for all rows in a column, then duplicate the task for different columns and sumranges

I have a worksheet (named RsOut) with 235 columns. I need to overwrite the values in only certain columns with data from another sheet(named rsTrans). Both sheets have a unique identifier that I am using to match.
I decided to use the Sumif function to populate the rsOut worksheet. Where I ran into a snag is I cannot figure out how to run the script for all rows in the column that have data.
Once we figure this out, I need to repeat this process for roughly 15 other columns.
My over-arching question is even after we get the sumif to work properly, what is the most efficient way to execute the code so that it repeats 15 more times?
The Criteria list and the CriteriaRange will always have the same location. But the Sum Range and the column where the results are inserted will change for each of the 15 columns.
So, Thoughts on the most efficient way to proceed...maybe separate the sumif code as it's own block and call upon it instead of repeating the steps over and over, and/or list out all the sum ranges and all the insert ranges, so the script just loops through them..Would love your insight VBA masters.
Issue:
I think my main issue is that I tried to use a rngList as the criteria.
I also tried to separate the sumif as a separate block of code, to call on. I may have screwed something up there as well.
The error highlights on the Set sumRange row. (Runtime error 1004 - Method 'Range' of Object '_Worksheet' Failed.
Any help you can provide would be greatly appreciated!!
Sub SumifmovewsTransdatatowsOut()
Dim wb As Workbook, wsOut As Worksheet
Dim wsTrans As Worksheet, rngList As Range
Dim sumRange As Range
Dim criteriaRange As Range
Dim criteria As Long 'Setting as long because the IDs (criteria) are at least 20 characters. Should this be a range??
Set wb = ThisWorkbook
Set wsTrans = Worksheets("DEL SOURCE_Translator") 'Worksheet that contains analysis and results that need to be inserted into wsOut
Set wsOut = Worksheets("FID GDMR - Output_2") 'Worksheet where you are pasting results from wsTrans
Set rngList = wsOut.Range("B2:B" & wsOut.Cells(Rows.Count, "B").End(xlUp).Row) 'this range of IDs will be different every run, thus adding in the count to find last row...or do I not need the rnglist at all? Just run the sumif for all criteria B2:b
Set sumRange = wsTrans.Range("ag21:ag") 'Values in wsTrans that need to be added to wsOut
Set criteriaRange = wsTrans.Range("AA21:AA") 'Range of IDs found on wsTrans
criteria = rngList
Sumif
End Sub
'Standard Sumif formula
Sub Sumif()
wsOut.Range("AT2:AT") = WorksheetFunction.SumIfs(sumRange, criteriaRange, criteria)
End Sub
'OR should the Sumif formula be: rng.Formula = "=SUMIF(criteriaRange,rngList,sumRange)"
SUBSEQUENT TESTING after receiving recommendations:
I tested using the second recommendation only because a future user could easily change out the array values if the columns shifted on the wsout template. Below is the code that I used and the resulting error.
Result issues:
the result in each changed cell is #NAME?
a pop up box shows up for each request. It is looking for the translater. See screenshot below. If I x out of each pop up box, the script completes and each cell has the #NAME?
enter image description here
Thoughts on what went wrong?
Code:
Sub test2()
Dim wsTrans As Worksheet: Dim wsOut As Worksheet
Dim rgCrit As String: Dim rgSum As String
Dim rgR As Range: Dim i As Integer: Dim arr
arr = Array("AG:AT", "AJ:BB", "AM:BJ", "AT:BR", "AZ:CA", "BP:DE", "BW:DO") 'change as needed
Set wsTrans = Sheets("DEL SOURCE_Translator") 'change as needed
Set wsOut = Sheets("FID GDMR - Output_2") 'change as needed
rgCrit = wsTrans.Name & "!" & wsTrans.Columns(27).Address 'Column 27 is AA in wsTrans which contains the criteria range
Set rgR = wsOut.Range("B2", wsOut.Range("B2").End(xlDown)) 'change as needed
startCell = "$" & Replace(rgR(1, 1).Address, "$", "")
For i = LBound(arr) To UBound(arr)
rgSum = wsTrans.Name & "!" & Split(arr(i), ":")(0) & ":" & Split(arr(i), ":")(0)
With rgR.Offset(0, Range(Split(arr(i), ":")(1) & 1).Column - rgR.Column)
.Value = "=SUMIF(" & rgCrit & "," & startCell & "," & rgSum & ")"
.Value = .Value
End With
Next
End Sub
'Sum Ranges in wsTrans: AG, AJ, AM, AT, AZ, BP, BW
'Result Columns in wsOut: AT, BB, BJ, BR, CA, DE, DO
Additional Review:
Also, to test, instead of x'ing out of the pop up, I selected my file in the pop up. when I did, a second pop up below showed up. Interestingly, the sheet name is missing the DEL on the front. When I select the correct sheet, I still get the #Name? error.
enter image description here
Okay, so your question is a little too broad for this website. The general rule is each question should address one specific issue.
That being said, I think I can help you with a few easy to solve points.
1) Making Sumif Work:
Using Sumif() function inside a Sub is the same as using it in an Excel formula. First you need two full ranges, next you need a value to lookup.
Full ranges: wsTrans.Range("ag21:ag") is not going to work because it doesn't have an end row. Instead, it needs to be wsTrans.Range("AG21:AG100"). Now since you don't seem to know your last row, I would suggest you find that first and then integrate it into all your ranges. I'm using the variable lRow below.
Option Explicit
Sub TestSum2()
Dim WB As Workbook
Dim wsTrans As Worksheet
Dim wsOut As Worksheet
Dim criteriaRange As Range
Dim sumRange As Range
Dim rngList As Range
Dim aCriteria 'Array
Dim lRow As Long
Set WB = ThisWorkbook
Set wsTrans = WB.Worksheets("DEL SOURCE_Translator")
Set wsOut = WB.Worksheets("FID GDMR - Output_2")
lRow = wsOut.Range("B" & Rows.Count).End(xlUp).Row
Set rngList = wsOut.Range("B2:B" & lRow)
aCriteria = rngList 'Transfer Range to array
lRow = wsTrans.Range("AA" & Rows.Count).End(xlUp).Row
Set sumRange = wsTrans.Range("AG21:AG" & lRow)
Set criteriaRange = wsTrans.Range("AA21:AA" & lRow)
Debug.Print Application.WorksheetFunction.SumIf(criteriaRange, aCriteria(1, 1), sumRange)
End Sub
The above sub returns:
Which is correct considering the following sheets:
2) Making it loop through the criteria list
You've already made a great start on looping through this criteria list by importing rngList into an array. Next we just need to loop that array like so:
Option Explicit
Sub TestSum2()
Dim WB As Workbook
Dim wsTrans As Worksheet
Dim wsOut As Worksheet
Dim criteriaRange As Range
Dim sumRange As Range
Dim rngList As Range
Dim aCriteria 'Array
Dim lRow As Long
Dim I As Long
Set WB = ThisWorkbook
Set wsTrans = WB.Worksheets("DEL SOURCE_Translator")
Set wsOut = WB.Worksheets("FID GDMR - Output_2")
lRow = wsOut.Range("B" & Rows.Count).End(xlUp).Row
Set rngList = wsOut.Range("B2:B" & lRow)
aCriteria = rngList 'Transfer Range to array
lRow = wsTrans.Range("AA" & Rows.Count).End(xlUp).Row
Set sumRange = wsTrans.Range("AG21:AG" & lRow)
Set criteriaRange = wsTrans.Range("AA21:AA" & lRow)
For I = 1 To UBound(aCriteria, 1)
Debug.Print "Sum of " & aCriteria(I, 1) & "=" & _
Application.WorksheetFunction. _
SumIf(criteriaRange, aCriteria(I, 1), sumRange)
Next I
End Sub
This results in an output of:
Then to finish it off, you'll need to check which column to put it in, maybe with a .Find or maybe with a Match() of the column headers, but I don't know what your data looks like. But, if you just want to output that range to your output sheet here's how to do that:
Sub TestSum2()
Dim WB As Workbook
Dim wsTrans As Worksheet
Dim wsOut As Worksheet
Dim criteriaRange As Range
Dim sumRange As Range
Dim rngList As Range
Dim aCriteria 'Array
Dim OutputSums
Dim lRow As Long
Dim I As Long
Set WB = ThisWorkbook
Set wsTrans = WB.Worksheets("DEL SOURCE_Translator")
Set wsOut = WB.Worksheets("FID GDMR - Output_2")
lRow = wsOut.Range("B" & Rows.Count).End(xlUp).Row
Set rngList = wsOut.Range("B2:B" & lRow)
aCriteria = rngList 'Transfer Range to array
lRow = wsTrans.Range("AA" & Rows.Count).End(xlUp).Row
Set sumRange = wsTrans.Range("AG21:AG" & lRow)
Set criteriaRange = wsTrans.Range("AA21:AA" & lRow)
ReDim OutputSums(1 To UBound(aCriteria, 1), 1 To 1)
For I = 1 To UBound(aCriteria, 1)
OutputSums(I, 1) = Application.WorksheetFunction. _
SumIf(criteriaRange, aCriteria(I, 1), sumRange)
Next I
wsOut.Range("C2").Resize(UBound(OutputSums, 1), 1) = OutputSums
End Sub
Resulting in:
If I understand you correctly, besides Mr. Cameron's answers, another way maybe you can have the VBA using formula.
Before running the sub is something like this :
After running the sub (expected result) is something like this:
Please ignore the fill color, the sorting and the value, as they are used is just to be easier to calculate manually for the expected result.
The Criteria list and the CriteriaRange will always have the same
location. But the Sum Range and the column where the results are
inserted will change for each of the 15 columns.
Since you don't mention where are the columns for the Sum Range will be, this code assume that it will be in a consecutive column to the right of column ID, as seen in the image of sheet1 ---> rgSUM1, rgSUM2, rgSUM3.
And because you also don't mention in what column in sheet2 the result is, this code assume that it will be in a consecutive column to the right of column ID, as seen in the image of sheet2 ---> SUM1, SUM2, SUM3.
If your Sum Range columns are random and/or your Sum Result columns are random, then you can't use this code. For example : your rgSum1 is in column D sheet1 - rgSum1Result sheet2 column Z, rgSum2 is in column AZ sheet1 - rgSum2Result sheet2 column F, rgSum3 is in column Q sheet1 - rgSum3Result sheet2 column DK, and so on until 15 columns. I think it will need an array of column letter for both rgSum and rgSumResult if they are random.
Sub test()
Dim sh1 As Worksheet: Dim sh2 As Worksheet
Dim rgCrit As String: Dim rgSum As String
Dim rgR As Range: Dim col As Integer
col = 3 'change as needed
Set sh1 = Sheets("Sheet1") 'change as needed
Set sh2 = Sheets("Sheet2") 'change as needed
rgCrit = sh1.Name & "!" & sh1.Columns(1).Address 'change as needed
rgSum = sh1.Name & "!" & Replace(sh1.Columns(2).Address, "$", "") 'change as needed
Set rgR = sh2.Range("A2", sh2.Range("A2").End(xlDown)) 'change as needed
startCell = "$" & Replace(rgR(1, 1).Address, "$", "")
With rgR.Resize(rgR.Rows.Count, col).Offset(0, 1)
.Value = "=SUMIF(" & rgCrit & "," & startCell & "," & rgSum & ")"
.Value = .Value
End With
End Sub
Basically the code just fill the range of the expected result with SUMIF formula.
col = how many columns are there as the sum range
sh1 (wsTrans in your case) is the sheet where the ID and the multiple sum range are.
sh2 (wsOut in your case) is the sheet where the ID to sum and the multiple sum result are.
rgCrit is the sh1 name with the column of the range of criteria (column A, (ID) in this case)
rgSum is the sh1 name with the first column of Sum Range (column B in this case)
rgR is the range of the unique ID in sheet2 (column A in this case, must have no blank cell in between, because it use xldown) and finally, startCell is the first cell address of rgR
Below if the SumRange and ResultRange are random column.
Sub test2()
Dim sh1 As Worksheet: Dim sh2 As Worksheet
Dim rgCrit As String: Dim rgSum As String
Dim rgR As Range: Dim i As Integer: Dim arr
arr = Array("B:G", "F:E", "D:B") 'change as needed
Set sh1 = Sheets("Sheet13") 'change as needed
Set sh2 = Sheets("Sheet14") 'change as needed
rgCrit = sh1.Name & "!" & sh1.Columns(1).Address 'change as needed
Set rgR = sh2.Range("A2", sh2.Range("A2").End(xlDown)) 'change as needed
startCell = "$" & Replace(rgR(1, 1).Address, "$", "")
For i = LBound(arr) To UBound(arr)
rgSum = sh1.Name & "!" & Split(arr(i), ":")(0) & ":" & Split(arr(i), ":")(0)
With rgR.Offset(0, Range(Split(arr(i), ":")(1) & 1).Column - rgR.Column)
.Value = "=SUMIF(" & rgCrit & "," & startCell & "," & rgSum & ")"
.Value = .Value
End With
Next
End Sub
The arr value is in pair : sum range column - sum result column.
Example arr in code :
First loop : sum range column is B (sheet1) where the result will be in column G (sheet2).
Second loop: sum range column is F (sheet1) where the result will be in column E (sheet2).
Third loop: sum range column is D (sheet1) where the result will be in column B (sheet2).

VBA Vlookup from different worksheet

I am trying to write a vlookup code that uses the lookups tab as the array (A:B) and the revenue tab where the vlookup is in cell Y2. I need it to fill all the way through column Y.
Sub VLOOKUP()
Dim LookupsLastRow As Long
Dim RevenueLastRow As Long
Dim LookupsSheet As Worksheet
Dim RevenueSheet As Worksheet
'What are the names of our worksheets?
Set LookupsSheet = Worksheets("Lookups")
Set RevenueSheet = Worksheets("Revenue")
'Determine last row of source
With LookupsSheet
LookupsLastRow = .Cells(.Rows.Count, "A").End(xlUp).Row
End With
With RevenueSheet
'Determine last row in col P
RevenueLastRow = .Cells(.Rows.Count, "X").End(xlUp).Row
'Apply our formula
.Range("Y2:Y" & RevenueLastRow).Formula = _
"=VLOOKUP(V2,"Lookups"!$A$2:$B$" & LookupsLastRow & ",2,0)"
End With
End Sub

How to copy data from 2 cells from workbook A and copy to workbook B in a cell and how do I start a for loop until last row/column

I have two questions
How to combine data using two of the cells from workbookA and copy to workbookB on the same cell?
How do I start using for loop to copy it until the last row/column?
I have no clue on how to combine the data and I do not know where to place the variable inside the code for it to loop until its last column.
Dim Tlastrow As Integer
Tlastrow = Cells(1, Columns.Count).End(xlToLeft).Column
For r = 1 To Tlastrow
Workbooks("InputB.xls").Worksheets("HC_MODULAR_BOARD_20180112").Range("F3:G3").Copy _
Workbooks("Output.xls").Worksheets("Sheet1").Range("I3")
Next
Try this:
Option Explicit
Sub Paste()
Dim wsInput As Worksheet, wsOutput As Worksheet, LastRow As Long, C As Range
Set wsInput = Workbooks("InputB.xls").Worksheets("HC_MODULAR_BOARD_20180112")
Set wsOutput = Workbooks("Output.xls").Worksheets("Sheet1")
With wsInput
LastRow = .Cells(.Rows.Count, "E").End(xlUp).Row 'Last Row with data
For Each C In .Range("F3:F" & LastRow) 'loop for every row with data
wsOutput.Cells(C.Row, "I").Value = C & " " & C.Offset(0, 1)
Next C
End With
End Sub
This code is assuming you want to paste every row from your input workbook to the output workbook on the same rows, but merging F and G columns. It's just pasting the values, not formulas or formats.

VLOOKUP from another sheet, apply formula every nth row

I'm working on the below formula to Vlookup data from another sheet. The formula must be placed on the 14th column, and every 7 rows, vlookuping the first column value.
Sub test3()
'Vlookuping on Column N
Dim lastRow As Long
lastRow = Cells(Rows.Count, 14).End(xlUp).Row 'Checks last row with data
Dim cel As Range, rng As Range
Dim sheetName, lookupFrom, myRange 'variables
sheetName = "Plan2" 'the worksheet i want to get data from
lookupFrom = ActiveCell.Offset(0, -14).Address '
myRange = "'" & sheetName & "'!1:1048576"
For i = 3 To lastRow Step 7 '
Cells(i, 14).Select 'i= first value; step= lines to jump
ActiveCell.Formula = "=VLOOKUP(" & lookupFrom & ";" & myRange & "; 14; FALSE)"
Next i
End Sub
Example Sheet
I want to place the formula on the pink cells (column N), vlookuping the pink value from the first cell on another worksheet. My actual formula isn't even executing.
Try the code below, with 2 exceptions:
1.Modify "VlookRes" to your Sheet name - where you want to results to be.
2.You have Merged Cells in Column A (according to your image uploaded), you are merging Rows 2 untill 6 in column A, this means that the value of Cell A3 will be 0. If you want the values to read from the third row, start the merging from row 3 (and soon for the next values in Column A).
Option Explicit
Sub test3()
'Vlookuping on Column N
Dim ShtPlan As Worksheet
Dim ActSht As Worksheet
Dim lastRow As Long
Dim sheetName As String
Dim lookupFrom As String
Dim myRange As String
Dim i As Long
' modify this Sheet Name to your sheet name (where you want to keep your results)
Set ActSht = Sheets("VlookRes")
lastRow = ActSht.Cells(ActSht.Rows.Count, 14).End(xlUp).Row ' Checks last row with data
sheetName = "Plan2" 'the worksheet i want to get data from
Set ShtPlan = Sheets(sheetName)
myRange = "'" & sheetName & "'!1:1048576"
For i = 3 To lastRow Step 7
lookupFrom = ActSht.Cells(i, 1).Address ' ActiveCell.Offset(0, -14).Address '
Cells(i, 14).Formula = "=VLOOKUP(" & lookupFrom & "," & myRange & ", 14, FALSE)"
Next i
End Sub

Vba comparing then copying two different Sheets

I realize there are a few different similar ideas on here. But I need help with this simple compare function.
My goal is to compare two different cells and if they are the same, replace it with its full non-abbreviated name.
Thank you for your time!!!
I.E
Sheet1 Sheet2
Column H Column A Column B
Dept Dept Department
This is what I have (Yes simple), but the cell H is not updating to the non-abbreviation:
Sub updateDeptNames()
'Format user ID from the email column
Dim ws As Worksheet, ws2 As Worksheet
Dim LastRow As Long, i As Long
Dim tmpArray() As String, tempDept As String
Set ws = ActiveWorkbook.Sheets("Student_Travel_DB") '--> This is the relevant sheet
Set ws2 = ActiveWorkbook.Sheets("gokoutd") '--> This is the relevant sheet
LastRow = 1000 ''Bug finding the last row, had to hard code it
For i = 2 To LastRow 'Iterate through all the rows in the sheet
For j = 2 To 112
tempDept = ws2.Range("A" & j).Value
If ws.Range("H" & i).Value = tempDept Then
ws.Range("H" & i) = ws2.Range("B" & j).Value
End If
Next j
Next i
End Sub
You can more easily use VLOOKUP either on your worksheet or with VBA:
Sub GetFullName()
Dim cl As Range, data As Range, lookUpRng As Range
Set data = Worksheets("Student_Travel_DB").Range("A1:A10")
Set lookUpRng = Worksheets("gokoutd").Range("A1:B10")
On Error Resume Next
For Each cl In data
cl = WorksheetFunction.VLookup(cl, lookUpRng, 2, False)
Next cl
End Sub
You'll need to change your range references.

Resources