Summing by active column vba - excel

'Find & Copy Column for Actual Curtailed
Dim ws As Worksheet
Set ws = Worksheets("Report")
Range("A2:AC2").Find(What:="Actual Curtailed").ActiveCell.Select
Range("S20") = Application.WorksheetFunction.Sum(ws.Range(Column(ActiveCell.Column))).Copy
This code brings a compile error, I am presuming that I am doing some wrong by summing the column with where the active cell is.
I am trying to fine "actual curtailed", get the column number, and put the summation of that column in row S20.
Thanks

This code will do what you intend.
Dim SumClm As Variant
Dim SumRng As Range
With Worksheets("Report")
SumClm = Application.Match("Actual Curtailed", .Rows(2), 0)
If Not IsError(SumClm) Then
' from row 3 to the end of the column
Set SumRng = .Range(.Cells(3, SumClm), .Cells(.Rows.Count, SumClm).End(xlUp))
.Cells(20, "S").Value = WorksheetFunction.Sum(SumRng)
End If
End With
If the column isn't found S20 will remain blank.

I just did few edits to your code
Dim ws As Worksheet
Set ws = Worksheets("Report")
Range("A2:AC2").Find(What:="Actual Curtailed").Activate
Range("S20") = WorksheetFunction.Sum(Columns(ActiveCell.Column))

Related

Replace Existing Values on one Tab With Values From a Table on Another tab

I am trying to find a way to replace all values on the second tab of an Excel workbook with values from a table in a different tab 1 cell to the right of the corresponding value. On Sheet1 there are 2 columns. 1 is called ID and the second is called New ID. On Sheet2 there is a column called ID. I am looking for a way so that when I run a macro the values on Sheet2 will be replaced by the corresponding New ID from Sheet1. For example, on Sheet2 the first ID is ABC. On Sheet1 the corresponding New ID value for ABC is 123. I'd like the VBA script to replace all ABCs on Sheet2 with 123. I need this for varying amounts of data.
Sheet1
Sheet2
So far I've tried the following but it won't change the cells
Sub Test1()
Dim N As Long, L As Long
Dim rLook As Range
Sheets("Sheet1").Select
N = Cells(Rows.Count, "A").End(xlUp).Row
aryA = Range("A2:A" & N)
aryB = Range("B2:B" & N)
Sheets("Sheet2").Select
Set rLook = Range("A2:A" & N)
For L = 1 To N
rLook.Replace aryA(L, 1), aryB(L, 1)
Next L
End Sub
When I run the macro it only changes the same number of rows as Sheet1 so I am left with the following:
Result
After I run this I get an error that says subscript is out of range.
Your error is basically that you reuse N, which is the number of rows from sheet1 to define the range on sheet2.
So my advise is to use more explicit names for variables that explain what the variable "contains".
Furthermore if you don't use the implicit Cells(xxx) but the explicit one Thisworkbook.Worksheets("Sheet1") you can omit the selection of the sheets (and by that reduce the possibility for errors referencing the wrong range).
Plus: you can read both columns of sheet1 into one array
Option Explicit
Public Sub updateSheet2IDs()
Dim wsSource As Worksheet
Set wsSource = ThisWorkbook.Worksheets("Sheet1")
Dim wsTarget As Worksheet
Set wsTarget = ThisWorkbook.Worksheets("Sheet2")
Dim cntRowsSheet1 As Long
Dim arrSource As Variant
With wsSource
cntRowsSheet1 = .Cells(.Rows.Count, "A").End(xlUp).Row
'array includes both columns: arrsource(1,1) = A2, arrsource(1,2) = B2
arrSource = .Range("A2:B" & cntRowsSheet1)
End With
Dim cntRowsSheet2 As Long, rgTarget As Range
With wsTarget
cntRowsSheet2 = .Cells(.Rows.Count, "A").End(xlUp).Row
Set rgTarget = .Range("A2:A" & cntRowsSheet2)
Dim i As Long
For i = 1 To UBound(arrSource, 1) 'ubound gives you the upper bound of the array
rgTarget.Replace arrSource(i, 1), arrSource(i, 2)
Next
End With
End Sub
You could omit the whole "cntRows"-stuff by using currentregion - which returns the area around one cell that is surrounded by empty rows and columns (see https://learn.microsoft.com/en-us/office/vba/api/excel.range.currentregion).
That means that wsSource.Range("A1").CurrentRegionwill return all cells until the first empty row and until the first empty column - I assume this is exactly what your are looking for. The same for sheet2 as well.
To omit the first row, you can use offset:
set rgTarget = wsTarget.Range("A1").CurrentRegion.Offset(1)
The code then looks like
Option Explicit
Public Sub updateSheet2IDs()
Dim wsSource As Worksheet
Set wsSource = ThisWorkbook.Worksheets("Sheet1")
Dim wsTarget As Worksheet
Set wsTarget = ThisWorkbook.Worksheets("Sheet2")
'array includes both columns: arrsource(1,1) = A2, arrsource(1,2) = B2
Dim arrSource As Variant
arrSource = wsSource.Range("A1").CurrentRegion.Offset(1)
Dim rgTarget As Range
Set rgTarget = wsTarget.Range("A1").CurrentRegion.Offset(1)
Dim i As Long
For i = 1 To UBound(arrSource, 1) 'ubound gives you the upper bound of the array
rgTarget.Replace arrSource(i, 1), arrSource(i, 2)
Next
End Sub

Find matching value on another sheet and paste into next empty cell on that row

I've been struggling with this all day and I'm sure there's a really simple answer that I'm just not finding so hoping someone can point me in the right direction!
What I want to achieve is:
see if a value (R.BName) from sheet1 (wsResults) can be found in column c of sheet2 (wsSchedule);
if found, paste a value from sheet1 (that I've already copied) into
the next empty cell of that row;
if not found, insert a value into a specific cell in sheet1
The 2 issues I'm having are that:
If there is a match - the paste location is the last cell in row1 - yes, I know that this be because my code has (1,columns.count) but I don't know how to get it to select the cell of the match!
"broker name not found on review schedule" is being added to wsResults even if a match was on wsSchedule
Here is my defective code:
'copy result from wsresults
wsResults.range("R.Result").Copy
'find broker & add result to review schedule sheet
Dim wsSchedule As Worksheet
Dim rSearch As range
Dim c As range
Set wsSchedule = Worksheets("Review Schedule")
Set rSearch = wsSchedule.range("C5:C400")
For Each c In rSearch
If c.Value = wsResults.range("R.BName").Value Then
wsSchedule.Cells(1, Columns.count).End(xlToLeft).Offset(0, 1).PasteSpecial xlPasteValues
Else
With wsResults
.range("AP2:AP2").Value = "Broker name not found on review schedule"
End With
End If
Next c
Any assistance that can be offered would be greatly appreciated!
I believe this is what you had in mind. Please try it.
Sub Test()
' 009
Dim wsSchedule As Worksheet
Dim wsResults As Worksheet
Dim searchCrit As Variant
Dim lastR As Long
Dim R As Long
Set wsSchedule = Worksheets("Review Schedule")
Set wsResults = Worksheets("Results")
' try to access sheet values as little as possible: it's slow
' here, once is enough. No need to do it on every loop
searchCrit = wsResults.Range("R.BName").Value
With wsSchedule
lastR = .Cells(.Rows.Count, "C").End(xlUp).Row
For R = 5 To lastR
If .Cells(R, "c").Value = searchCrit Then
.Cells(R, Columns.Count).End(xlToLeft).Offset(0, 1) = wsResults.Range("R.Result")
Exit For
End If
Next R
End With
' R will be <=lastR if a match was found
If R > lastR Then
wsResults.Cells(2, "AP").Value = "Broker name not found on review schedule"
End If
End Sub
However, #SJR is right: using Find in place of the loop would be more efficient.

Stack different columns into one column on a different worksheet

I want to copy all filled cells starting from C5 to column F of a different worksheet.
I referred to another post: Excel - Combine multiple columns into one column
Modified the code based on my needs.
Sub CombineColumns()
Dim Range1 As Range, iCol As Long, Range2 As Range, Check As Range, wks As Worksheets
Set Range1 = wks("T(M)").Range(Cells(5, 3), Cells(Cells(5, 3).End(xlDown).Row, Cells(5, 3).End(xlToRight).Column))
Set Check = wks("csv").Range("F1")
If IsEmpty(Check.Value) = True Then
Set Range2 = Check
Else
LastRow = wks("csv").Range("F" & Rows.Count).End(xlUp).Row
Set Range2 = wks("csv").Cells(LastRow, 6).Offset(1, 0)
End If
For iCol = 3 To Range1.Columns.Count
wks("T(M)").Range(Cells(5, iCol), Cells(Range1.Columns(iCol).Rows.Count, iCol)).Copy
wks("csv").Range2.PasteSpecial Paste:=xlPasteValuesAndNumberFormats
Next iCol
End Sub
But I kept getting the error message
"object doesn't support this method or property"
at the step of pasting. After I tried to qualify all the ranges, It says I didn't set the object variable.
Thank you so much for the help!
How about this?
Sub Transposes()
' Example just for hardcoded data
Dim inputRange As Range
Set inputRange = Sheets("Sheet1").Range("C5:F10").SpecialCells(xlCellTypeConstants)
Dim outputCell As Range
Set outputCell = Sheets("Sheet2").Range("A1")
Dim cell As Range
For Each cell In inputRange
Dim offset As Long
outputCell.offset(offset).Value = cell.Value
offset = offset + 1
Next cell
End Sub
Set the last row in ColumnF to be whatever you want, and if that changes dynamically, just use any one of the multiple techniques out there to find the last cell you need to copy/paste.

How to copy range from multiple sheets to one sheet (one range under another) if a condition is met?

I have and excel workbook with multiple sheets and I need a range from each one to be copied into one "Main" sheet (one under another) if a condition is met.
Each sheet is different and the number of rows and cells may vary.
In all of the sheets (except the main sheet which is blank) cell B1 is a check cell that contains "yes" or is blank.
If cell B1 ="yes" the macro must migrate the range (from row 2 to the lat filled in row) into the main sheet.
The selected ranges must be copied one under another in the main sheet (so that it's like a list)
I am still a beginner in VBA and if anyone could help me a little with the code I would very much appreciate it :).
I tried to build in the code using "For Each - Next" but perhaps it would be better to make it with a Loop cicle or something else.
Sub Migrate_Sheets()
Dim wksh As Worksheet, DB_range As Range, end_row As Long, con_cell As Variant
con_cell = Range("B1")
'end_row = Range("1048576" & Rows.Count).End(xlUp).Rows
For Each wksh In Worksheets
If con_cell = "Yes" Then
Set DB_range = Range("2" & Rows.Count).End(xlDown).Rows
DB_range.Copy
wksh("Main").Activate
'row_end = Range("2" & Rows.Count).End(xlUp).Rows
Range("A1").End(xlDown).Offset(1, 0).Paste
End If
Next wksh
End Sub
There are quite a few issues here - I suggest you do some reading on VBA basics - syntax, objects, methods etc.
I've assumed you are only copying column B.
Sub Migrate_Sheets()
Dim wksh As Worksheet, DB_range As Range
For Each wksh In Worksheets
If wksh.Name <> "Main" Then 'want to exclude this sheet from the check
If wksh.Range("B1").Value = "Yes" Then 'refer to the worksheet in the loop
Set DB_range = wksh.Range("B2", wksh.Range("B" & Rows.Count).End(xlUp)) 'you need Set when assigning object variables
DB_range.Copy Worksheets("Main").Range("A" & Rows.Count).End(xlUp).Offset(1, 0) 'better to work up from the bottom and then go down 1
End If
End If
Next wksh
End Sub
See if this helps, though you might need to make some minor changes to match your data sets..
Sub Migrate_Sheets()
Dim wksh As Worksheet, mainWS As Worksheet
Dim DB_range As Range, con_cell As String
Dim lRow As Long, lCol As Long, lRowMain As Long
Set mainWS = ThisWorkbook.Worksheets("Main")
For Each wksh In Worksheets
con_cell = wksh.Range("B1").Value 'You want to use this variable within the loop
If wksh.Name <> "Main" And con_cell = "Yes" Then
lRowMain = lastRC(mainWS, "row", 1) + 1 'Add 1 to the last value to get first empty row
lRow = lastRC(wksh, "row", 1) 'Get the last row at column 1 - adjust to a different column if no values in column 1
lCol = lastRC(wksh, "col", 2) 'Get the last column at row 2 - adjust to a different row if no values in row 2
With mainWS
.Range(.Cells(lRowMain, 1), .Cells(lRowMain + lRow - 1, lCol)).Value = wksh.Range(wksh.Cells(2, 1), wksh.Cells(lRow, lCol)).Value
End With
End If
Next wksh
End Sub
Function lastRC(sht As Worksheet, RC As String, Optional RCpos As Long = 1) As Long
If RC = "row" Then
lastRC = sht.Cells(sht.Rows.Count, RCpos).End(xlUp).row
ElseIf RC = "col" Then
lastRC = sht.Cells(RCpos, sht.Columns.Count).End(xlToLeft).Column
Else
lastRC = 0
End If
End Function

Loop throug column and paste values to an existing workbook

Hi this is my first post and i am newbie when it comes to VBA.
So i tried the last 6 hours to accomplish one task.
I already managed to get the code for the For each loop and it works and copies the value to the existing workbook. But i couldnt find out why it always copies the value to A2 and not further to A3/A4/A5 and so on .
I tried these piece of code " range = range + 1 " but i keep getting runtime errors and it still copies the values to A2 and overwrites it when it gets a new value from the loop.
I think its only a litte change needed but i cant figure it out. :(
Sub copie1()
Dim ws As Worksheet
Dim cell As Range
Dim targetsheet As Worksheet
Dim target As Range
Dim rngTemp As Range
Set wkba = ActiveWorkbook
Worksheets("cop1").Activate
LR = Cells(Rows.Count, "A").End(xlUp).Row
LT = Cells(Rows.Count, "X").End(xlUp).Row
Set rngTemp = Range("X2:X" & LT)
Workbooks.Open Filename:="C:\Users\path......."
Set targetsheet = Worksheets("Data")
Set target= targetsheet.Range("A1")
For Each cell In rngTemp
If cell > 0 Then
target.Offset(1, 0) = cell.Value
End If
target = target+1 '// is this right?
Next cell
End Sub
my goal is the loop through column X in a Workbook and copy every single data that is bigger than 0 ( because there are empty cells & cells with value 0)
and paste it in an existing workbook in range A2/A3/A4 and so on
You can't add the number one to a Range object.
Try replacing target = target+1 '// is this right? with:
Set target = target.Offset(1)
Does this resolve the problem?
SibSib1903, I have added below a simple example that you can easily adapt to your own requirements. It looks at all cell values in column A and any numeric value greater than zero is copied to column C starting in row 1. For example, if column A contains 45 rows with data, and only three of these rows have a numeric value greater than zero, these three values will copied in column C in the first three rows.
Public Sub copieTest()
Dim ws As Worksheet, cell As Range, rngX As Range
Dim tmpVal As Variant, counter As Long
Set ws = ThisWorkbook.Worksheets("cop1")
Set rngX = ws.Range("A1:A" & ws.Cells(ws.Rows.count, 1).End(xlUp).Row)
counter = 1
For Each cell In rngX
tmpVal = Val(Trim(cell.Value))
If tmpVal > 0 Then
ws.Range("C" & counter).Value = tmpVal
counter = counter + 1
End If
Next cell
Set rngX = Nothing: Set ws = Nothing
End Sub

Resources