VBA Rows.count and FormulaR1C1 - vba

I've got some VBA scirpt in excel that copies unique values from Column A, to column E then should total values from column B into column F for each. I found the snippet below online and have been editing it to fit my spreadsheet.
Original snippet that works in the example workbook to copy values from column B to column K and sums column I into column L.
Columns("B:B").AdvancedFilter Action:=xlFilterCopy, CriteriaRange:=Columns( _
"B:B"), CopyToRange:=Range("'Example1'!K1"), Unique:=True
For i = 2 To Cells(Rows.Count, 11).End(xlUp).Row
Cells(i, "L").FormulaR1C1 = "=SUMIF(C[-10],RC[-1],C[-3])"
Next i
My edited code that does copy the unique value from A into E, but does not perform the sum:
Range("A5:A30").AdvancedFilter Action:=xlFilterCopy, CopyToRange:=Range("'Sheet1'!E7"), Unique:=True
For i = 2 To Cells(Rows.Count, 11).End(xlUp).Row
Cells(i, "F6").FormulaR1C1 = "=SUMIF(C[-4],RC[-1],C[-4])"
Next i
The part I think is wrong is the
For i = 2 To Cells(Rows.Count, 11).End(x1Up).Row
but I'm sure sure the meaning of this line, especially where it has 11. Anyone have any idea why this isn't working?
#Jarom
Edit: My spreadsheet looks like this when I run the edited code, its not totaling properly and giving 0 value.
{Part Quantity Order Number Part Needed Scanned
6116022-42ID 28 041981
6116022-42ID 13 041981 Part Number 0
6116126-01 42 041981 6116022-42ID 0
6116784-15 42 041981 6116126-01 0
6116022-42ID 1 041981 6116784-15 0 }

The cells function references a cell based on row and column numbers like this cells(row reference,column reference). So cells(1,2) references the cell B1.
It does look like the problem is in your loop. With a for loop you run an operation a certain amount of times based on the number of a variable.
The first line identifies how many iterations of the loop it will do. i is the variable the sets the loop. i starts at 7 and goes to cells(7,5).end(xldown).Rows. The cells(7,5).end(xldown).Rows code goes to cell E7 and gets the row number of the bottom of the group of populated cells (it does the equivalent of the ctrl + down arrow and gets the row number). That way the loop iterates starting at cell E7 and goes to the lowest of the populated group cells in the column E. Notice that the code in the loop has a reference to i in the row part of the cells function. i increases with every iteration of the loop, so the input to the cells function increases every loop, which is how the loop goes down one row for every iteration.
Sub test()
Range("A5:A30").AdvancedFilter Action:=xlFilterCopy, CopyToRange:=Range("'Sheet1'!E7"), Unique:=True
For i = 7 To Cells(7, 5).End(xlDown).Row
Cells(i, 6).Value = Application.WorksheetFunction.SumIf(Range("A:A"), Cells(i, 5),Range("B:B"))
Next i
End Sub
I hope that this helps you understand what the code is doing.

Related

Showing Numbers inbetween two numbers on the same row

What I'm trying to achieve is there are 2 whole numbers in column A & B on the same row. I want to fill the row from Column C to show the whole numbers increments of one between the two numbers.
i.e.
A B C D E F G H I J K L
1 10 1 2 3 4 5 6 7 8 9 10
any help would be appreciated.
Assuming this is Excel and you can open the VBE Editor to use VBA
Here's a macro you can run or call via a button
See the comments in the code to understand what it's doing with the Dataseries fill function
Sub FillData()
Dim intStopAt As Integer
' Set to cell indicated low end of range
Cells(1, 1).Select
' Fill in "Start At" Number
ActiveCell.Offset(0, 2).Value = ActiveCell.Value
' Retrieve and use stop number to fill in series
intStopAt = ActiveCell.Offset(0, 1).Value
ActiveCell.Offset(0, 2).DataSeries Rowcol:=xlRows, Type:=xlLinear, Date:=xlDay, Step:=1, Stop:=intStopAt
End Sub
The below code assumes you have no header and that your value in A1 is always 1, and your value in B1 is the number you want to count to.
This can be modified to be more dynamic, but taking your question as is, this should work for you.
1) Check number to count to (CountTo)
2) Run loop for 1 to CountTo and auto-populate your column headers
To run: Open VBE and paste this code on the sheet where you wish to run it.
Sub Counter()
Dim CountTo As Integer
CountTo = Range("B1").Value
For i = 1 To CountTo
Cells(1, i + 2) = i
Next i
End Sub
This can be done without VBA, perhaps not as neat initially as #dbmitch's answer because the formula has to go across to the maximum possible number.
A1 is start number, > 0
B1 is end number (> A1)
In Cell C1 enter =A1
In Cell D1 enter =IF(AND(C1<$B1,C1>=$A1),C1+1,"") and then
drag/fill right as far as you need to.
I have formulated the code so that you can now select the filled rows (A through to wherever) and fill down.
A simple explanation:
C1 sets the start of the list
The AND formula in D1 onwards checks that the immediate left cell (for D1 this is C1, for E1 this is D1 etc.) is less than the end number and greater than the start number.
If the conditions are true, use the immediate left cell value + 1 as the result.
If the conditions are false, insert a blank.
Further checking can be done, I have assumed in the above solution that the numbers are positive and increasing.
You can use helper columns to indicate if you should increase or decrease (i.e. +1 or -1 as required.
Using a blank as the other answer falls down if the numbers go from -ve to +ve. In this case, you could use another symbol (e.g. x) and check for that in the AND function as well.
you could use this:
Sub main()
Dim cell As Range
With Range("A1", Cells(Rows.Count, 1).End(xlUp)).SpecialCells(xlCellTypeConstants, xlNumbers) ' reference column A cells from row 1 down to last not empty one with a "constant" (i.e. not a formula result) numeric content
For Each cell In .Cells 'loop through referenced range
cell.Offset(, 2).Resize(, cell.Offset(, 1).Value - cell.Value + 1).FormulaR1C1 = "=COLUMN()-COLUMN(C3)+RC1" 'write proper formula in current cell adjacent cells
Next
.CurrentRegion.Value = .CurrentRegion.Value ' get rid of formulas and leave values only
End With
End Sub

Excel VBA deleting certain rows with certain conditions

I found a code online which works but I am failing to change it for my purpose. Each entry in my spreadsheet contains different formulas as well as an Iferror function with the aim of making cells with error messages appear as blank. For example lets say a cell E3 is dependent on cell F3 with a certain formula (for clarification lets say F3/2.5). It is obvious if there is no entry in cell F3 then an error message would display in cell E3. For this reason, I use the IFERROR function to display the cell as blank. The difficulty arises when I want to delete blank rows after a click on the macro button. However, since that cell does have an entry (a formula which in turn returns an error message), that cell does not delete. Also I need to run this code over 3 different selection ranges. Please can someone help! The code I found was from a different thread on this forum and is:
`sub foo()
dim r As Range, rows As Long, i As Long
Set r = ActiveSheet.Range("A1:Z50")
rows = r.rows.Count
For i = rows To 1 Step (-1)
If WorksheetFunction.CountA(r.rows(i)) = 0 Then r.rows(i).Delete
Next
End Sub`
Thanks Alot!
EDIT: If statement added to the autofilter as it was deleting a row when there were no blanks
You will want to set up a column in the spreadsheet with the following sumproduct:
=SUMPRODUCT((LEN(A1:F1)>0)*1)
This is calculating how many cells' values have a length more than 0 hence are not blank, you will need to adjust cell references accordingly as I tested on a small sample of fake data.
Following this you can just loop:
For i = rows To 1 Step (-1)
If Cells(i,"G") = 0 Then r.rows(i).Delete 'My formula is in column "G"
Next
Or set up an auto-filter and delete entire rows of the visible cells:
Dim lrow As Integer
If Not WorksheetFunction.CountIf(Range("G:G"), "0") = 0 Then
Range("A1:G1").AutoFilter
Range("A1:G1").AutoFilter Field:=7, Criteria1:="0"
lrow = Cells(rows.Count, 7).End(xlUp).Row + 1
Range("G2:G" & lrow).SpecialCells(xlCellTypeVisible).EntireRow.Delete
Range("A1:G1").AutoFilter
End If
The only problem with using a leading column to calculate for this is if you have a lot of data coming and going as you will need to replenish the formula, though you could use auto complete in the code i guess.

Adjust criteria to depend on multiple values

I have been working on a code to copy the data from one specific range(always the same) and paste in another spreadsheet always in the row below. So basically, it starts pasting on row 11, but if I run again it will paste on the row 12 and there it goes.. The code has been working fine, but there is only one problem. It identifies the next empty row(to paste) based on the value of the column AP, but i want it to identify based on the values of all the columns between AP:BA. Thus, if there is any value on those cells, it should copy on the row below, not only if there is a value on AP. Does someone know how to change my code in order to solve this problem? Thank You very much
Sub Copy_Shanghai()
Dim count As Integer
count = 11
Do While Worksheets("Time Evolution").Range("AP" & count).Value <> ""
'<>"" means "is not empty", as long as this happens we go down looking for empty cell
count = count + 1
Loop
'Now count is row with first empty cell outside of top 10 rows in column C
Worksheets("Fill").Range("E5:P5").Copy
Worksheets("Time Evolution").Range("AP" & count).PasteSpecial xlPasteValues
End Sub

Excel macro generates Subscript out of Range error

All three sheets will have the same column headings in row 1. On the first and second sheets in the workbook (titled "Monthly" and "Annual" respectively), I am using conditional formatting to color cells in columns Y and AC based upon there values as determined by a formula (Yellow if the calculation returns a value less than 90, Red if the value returned is 0 or a negative number). What I would like a macro to do is to copy the entire row from column A through column AD to a third sheet (titled "Maint Due"). It would also be nice if this process were automated so that anytime the values in columns Y and AC changed in the "Monthly" or "Annual" sheets, the information in the "Maint Due" sheet was automatically updated (but if I have to rerun the macro manually for that to happen it's not a big deal).
I've never used the Macro recorder and I can only figure out how to create a macro to copy and paste, so I had no luck there. After doing some more searching and watching some videos I cobbled this together:
Sub Show_on_Maint()
x = 2
'Sets the starting row
Do While Cells(x, 2) <> ""
'Continue to evaluate until a blank cell is reached
If Cells(x, 25) <= 90 Then
'Evaluates the cell in column Y to determine if the value
' is less than or equal to 90
Sheets("Monthly").Rows(x).Copy Sheets("Maint Due").Range("A2")
'Copies the row to the Maint Due sheet
Else
If Cells(x, 29) <= 90 Then
'Evaluates the cell in column AC to determine if the value
' is less than or equal to 90
Sheets("Monthly").Rows(x).Copy Sheets("Maint Due").Range("A2")
'Copies the row to the Maint Due sheet
End If
End If
x = x + 1
Loop
End Sub
When I run/debug it I get a Loop without Do error. I think my logic is sound but I don't have enough experience to figure out why I'm getting that error.
EDIT: Fixed the missing End If before x = x + 1
Now I receive a runtime error 9 "Subscript out of range" at: Sheets("Sheet1").Rows(x).Copy Sheets("Sheet6").Range("A2")
EDIT: Fixed sheet names. Macro now runs without errors but doesn't appear to do anything. Also edited main post for brevity.
You code snippet contains multiple error. The first 'Loop without Do error' has been fixed in comments. The second one, 'Subscript out of range' is self-descriptive, so check the maximum value of x+1 by adding
Debug.Print x = x + 1
to your loop. Also, make sure that you are not referencing a non-existing Worksheet (i.e. Sheets("Sheet6")) in your copy statement.
Hope this will help.

Collect numbers from a column containing empty cells using Excel VBA

I have a little problem, I occasionally bump into this kind of problem, but I haven’t found a fast solution so far.
So, imagine we have an Excel worksheet and let's suppose that we have a couple of numbers in column ’A’ with some empty cells in it. Altogether (just to make it simple) we have the first 10 cells in column 'A' to observe. For example:
3
(empty cell)
(empty cell)
6
(empty cell)
4
(empty cell)
23
(empty cell)
2
Now in the next step I would like to collect these numbers into another column (for example, column ’B’) using VBA. Obviously I just want to collect those cells which contain a number and I want to ignore the empty cells. So I would like to get a column something like this:
3
6
4
23
2
I have already written the following code, but I’m stuck at this point.
Sub collect()
For i = 1 To 10
if cells(i,1)<>"" then...
Next i
End Sub
Is there an easy way to solve this problem?
Probably the quickest and easiest way is to use Excel's Advanced Filter - the only amendment you'll need to make is it add a field name and criteria. You can even list unique items only:
The VBA equivalent is
Sub test()
With Sheet1
.Range("B1:B8").AdvancedFilter Action:=xlFilterCopy, CriteriaRange:=.Range( _
"D1:D2"), CopyToRange:=.Range("F1"), Unique:=False
End With
End Sub
You should be able to use the method in the post int the comments, but you could also use SpecialCells like Range("A:A").SpecialCells(xlCellTypeConstants,xlNumbers).Copy to get all of the filled cells.
Edit: needed constants not formulas.
This will work for any number of rows that you select. It will always output in the next column at the start of your selection e.g. if data starts in B10 it will ooutput in C10
Sub RemoveBlanks()
Dim cl As Range, cnt As Long
cnt = 0
For Each cl In Selection
If Not cl = vbNullString Then
Cells(Selection.Cells(1, 1).Row, Selection.Cells(1, 1).Column).Offset(cnt, 1) = cl
cnt = cnt + 1
End If
Next cl
End Sub
If you wish to loop manually and don't mind specifying the maximum row limit;
Dim i As long, values As long
For i = 1 To 10
If cells(i, 1).Value <> "" Then
values = (values + 1)
' // Adjacent column target
cells(values, 2).value = cells(i, 1).value
End If
Next i