I have a function in Excel that calculates the average of some numbers
=AVERAGE(I1:I36) for example.
The thing is, I need to paste this function every 49 rows, instead of counting the rows manually then copying and pasting.
To do this in VBA (avoiding blank formulae) you could try this:
Enters formulas from A1 to A50000 every 9 rows
Dim rng1 As Range
Set rng1 = Range([a1], Cells(50000, "A"))
rng1.FormulaR1C1 = Application.Evaluate("=IF(MOD(ROW(A1:A50000),49)=0,""=AVERAGE(RC9:R[35]C9)"","""")")
=IF(MOD(ROW(),49)=0,AVERAGE($I$1:$I$36),"")
If you save in c1 the starting row and in c2 the frequency of the formula, it should look like
=IF(MOD(ROW()-$c$1+$c$2,$c$2)=0,AVERAGE($I$1:$I$36),"")
Decision 1
Use =IF(MOD((ROW()-ROW($I$1)),49)=0;AVERAGE(I1:I36);"")
Pro: pure formula, without macros.
Cons: you have to use entire column for it, excessive calculations (btw ROW() function is not efficient, so it would be better to spend another column for row number).
Decision 2
Just select cell with a formula and 48 empty cells, press "Copy", then select entire range and press "Paste".
Related
I have this formula:
IF(ROWS($Q$27:Q27)<=$P$25,INDEX(DataTable[[#All],[Time]],$P27),"")
and if I drag it to the right, it should automatically read each column respectively; example:
=IF(ROWS($Q$27:R27)<=$P$25,INDEX(DataTable[[#All],[Name]],$P27),"")
^Notice that the first Q27 is fixed, the second Q27 is variable.
I drag this formula to the right by 15 columns, and down to 50 rows. that's 750 formulas in total.
I want to do this in vba, but if I did this, it will be 750 lines of code for each cell representing each row/column.
example: .Range("G17").Formula=IF(ROWS($Q$27:R27)<=$P$25,INDEX(DataTable[[#All],[Name]],$P27),"""")
and if I drag it down, it will automatically pick up what I exactly want, example:
=IF(ROWS($Q$27:Q28)<=$P$25,INDEX(DataTable[[#All],[Time]],$P28),"")
so this formula should be written 750 times in total for the cell range [ A27:N76 ]
Any faster / more dynamic approach? and if possible, can I make it depend on more than 50 lines based on a cell value inside the sheet?
Example:
This should do it all in one line:
Range("A27:N76").FormulaR1C1 = "=IF(ROWS(R27C17:RC[16])<=R25C16,INDEX((DataTable[[#All],[Name]],RC16),"""")"
EDIT: Seems a more that one line of code required after all 😊
The code below will do what you want (this time fully tested)
Sub FillFormulas()
Dim inC%, rgHead As Range
''' Assumes the target sheet is Active.
''' o If that's not the case, change this With statement to reference the target sheet
With ActiveSheet
''' Set rgHead to the Table's header row
Set rgHead = .ListObjects("DataTable").Range.Rows(1)
''' Add the formulas to the target range, column by column updating the table header on the fly
With .Range("A27:N76")
For inC = 1 To .Columns.Count
.Columns(inC).FormulaR1C1 = _
"=IF(ROWS(R27C17:RC[16])<=R25C16,INDEX(DataTable[[#All],[" & rgHead.Cells(inC) & "]],RC16),"""")"
Next inC
End With
End With
End Sub
so this formula should be written 750 times in total for the cell range [A27:N76]
You don't need to do that. If you specify range.Formula, it will fill the proper formulas all the way across and down. Just give it the formula of the top/left most cell.
So, in your case
Range("A27:N76").Formula = "=IF(ROWS($Q$27:R27)<=$P$25 ... "
EDIT: This response had some obvious errors
This has an obvious error (as tested part and then merged to the full thing).
Range(A27:N76).FormulaR1C1 = "=IF(ROWS(R27C17:RC[16])<=R25C16,INDEX((DataTable[[#All],[Name]],$P27),"""")"
Currently I have a couple of SUM functions setup in my worksheet.
Lets use H2:H34 for my example: If I add a row within that range, the sum function will automatically adjust. The problem is when I add new rows, it is below the range (below H:33). In this case, I would just have to highlight the column and expand/drag the range to where it needs to be. There are a total of 8 columns that are doing a sum function. Is this only possible by using a macro?
=SUBTOTAL(3,H2:H34)
With your formula being the extent of the range minus one row we can use this:
=SUBTOTAL(3,H2:INDEX(H:H,ROW()-1))
Now as rows are added or deleted the reference will remain intact.
If there is a chance that row 2 would be deleted you will get #Ref errors. To avoid that you can use this formula:
=SUBTOTAL(3,INDEX(H:H,2):INDEX(H:H,ROW()-1))
Now there are no specific cell references and adding or deleting will not effect the formula and the range will be dynamic.
you could use a named range like =sum(range1) and something like;
Select first empty cell in column F starting from row 1. (without using offset )
to find the first empty cell to change the reference for the named range.
Triggering it would be difficult... potentially could use on_save?
or option 2.... bit of a dodge, but can work....
you say your sum is in cell H35... maybe move it to h36, and create a dummy hidden row in 35 (0.1 row height). that way when you add a row, it is always above 35. Use sum H1:H35 and it will always auto update? its not a neat solution, but should work
Use the following code, you need to adjust column "H" to whatever column you need.
Dim sumtest As Variant
sumstest = Application.WorksheetFunction.Subtotal(9, Range("H2:H" & ActiveSheet.Cells(ActiveSheet.Rows.Count, "H").End(xlUp).Row))
I am trying to create a large spreadsheet(10,000 rows of formulas) that takes information in from two other sheets. The basic layout that I want is:
Row1
=Sheet1!A7
=Sheet2!M7
=Sheet1!A8
=Sheet2!M8
=Sheet1!A9
=Sheet2!M9
...etc.
When I try to use to formula auto fill, excel picks up on the wrong pattern and I end up with something like this:
=Sheet1!A7
=Sheet2!M7
...
=Sheet1!A11
=Sheet2!M11
=Sheet1!A17
=Sheet2!M17
I gave excel 10 cells to base the pattern off of, and have not been able to get it to work. Can anyone help me figure out how to do this (hopefully without VBA)?
Try to avoid the volatile¹ OFFSET function or INDIRECT / ADDRESS function pairs in favor of the INDEX function and a little maths.
In the first two cells use these two formulas.
=INDEX(Sheet1!A:A, 7+ROW(1:1)/2)
=INDEX(Sheet2!M:M, 7+ROW(1:1)/2)
Select the two cells and drag the Fill Handle down.
¹ Volatile functions recalculate whenever anything in the entire workbook changes, not just when something that affects their outcome changes. Examples of volatile functions are INDIRECT, OFFSET, TODAY, NOW, RAND and RANDBETWEEN. Some sub-functions of the CELL and INFO worksheet functions will make them volatile as well.
Here is a simple VBA macro that sets up your links. Use it until a non-VBA solution is presented:
Sub propagator()
Dim i As Long, k As Long
k = 1
For i = 7 To 99
Cells(k, 1).Formula = "=Sheet1!A" & i
k = k + 1
Cells(k, 1).Formula = "=Sheet2!M" & i
k = k + 1
Next i
End Sub
Just select the destination worksheet and run the macro.
Adjust the 99 to meet your needs.
You can solve this without VBA with some =INDIRECT trickery -- the following is located in "Sheet3":
You can type out Sheet1!A and Sheet2!M in cells A1 and A2 respectively and fill down. Then, type a 7 in B1 and the formula in B2 -- again fill down. This first formula is effectively incrementing the count by two. Finally, you can type the formula in C1 and fill down.
Use the INDIRECT function to build this, and you can make the pattern work based on your current row number. Assuming your first cell is in Row 2:
=INDIRECT("Sheet1!A" & 7+(ROUNDDOWN(ROW()/2,0)-1))
=INDIRECT("Sheet2!M" & 7+(ROUNDDOWN(ROW()/2,0)-1))
ROW() returns the current row, which is then divided by 2 (since you only increase one row reference for every two cells), and then subtracted 1 (since we want the first adjustment to be 0).
Try in row 2:
=INDIRECT("Sheet1!A" & 7 +QUOTIENT(ROW()-2,2))
And in row 3:
=INDIRECT("Sheet2!M" & 7 +QUOTIENT(ROW()-2,2))
Highlight both and copy down.
I want to make a series of tables that each contain 25 values, that come from a set of 30 values. How can I quickly, and randomly, produce these tables? I'm wondering if there is a way in excel, or will I need to program something, myself? If so, which language would be the easiest (Python, C, Java)?
Edit: The 25 values would include no repeats. In other words, I'm looking for random combinations (30C25) of the values.
You can eventually add the following custom User-Defined function and then use it as an array formula. Add the code to code module Module1:
Public Function RandUnique(src As Range) As Variant
Dim v As Variant: v = src
Randomize
Dim i As Integer, j As Integer, temp As Variant
For i = 1 To src.Rows.count
j = 1 + Int(Rnd * src.Rows.count)
temp = v(i, 1): v(i, 1) = v(j, 1): v(j, 1) = temp
Next
RandUnique = v
End Function
Once you have added this UDF,
Select the destination range, enter in the formula bar the following formula
=RandUnique($A$1:$A$30) ' <~~ set it to your source range of 30 values
Then press Ctrl+Shift+Enter
Please note that the randomization procedure used is rather basic, so that not all the combinations have really equal probability, but it is fair enough, unless you are using it for some deep statistical analysis, in which case you might need a perfect randomizer.
Name a list of your thirty values in Excel in rows greater than 25 (say List30), then in A1 copied down to A25 and all copied across to suit:
=INDEX(List30,RANDBETWEEN(1,30))
To exclude repetitions (so not random choices) you might enter your list in A1:A30 and in B1 copied down to suit:
=RAND()
then sort A:B on ColumnB and copy A1:A25 to paste say to D1. This way only one set is generated at a time (the sort/copy/paste would have to be repeated after each paste).
Here is an interesting way that requires no VBA nor any manual sorting.
Enter your source list in the range A1:A30.
In cell B1 enter this formula:
=CHOOSE(RANDBETWEEN(1,7),7,11,13,17,19,23,29)
In the range C1:C30 enter this formula:
=INDEX(A$1:A$30,MOD(ROWS(A$1:J1)*B$1,30))
In cell D1 enter this formula:
=RANDBETWEEN(1,30)
Now select any 25 contiguous vertical and empty cells and enter this formula:
=INDEX($C$1:$C$30,MOD(D$1+ROWS($A$1:$J1),30)+1)
Now copy the 25 cells and paste as values somewhere for your 1st table. Press F9 on the keyboard to get a fresh 25; copy and paste as values somewhere for your 2nd table. Press F9 on the keyboard to get a fresh 25; copy and paste as values somewhere for your 3rd table. Keep repeating for as many tables as you need.
.
Please note that while this will look very random (with no repeats) it is not random at all. It's a complex interference pattern that will appear completely random unless you are the Rain Man.
This time, I have a cell holding a natural number, let's say 10. Starting from another cell and for the 9 columns to the right of it, I want to display the numbers 1 through 10. If my reference cell held 20, however, I want to start at the other cell and display the numbers 1 through 20 in 20 columns. I hope you get the gist.
Is there a good way to do this, first of all, without VBA? If not, is there a good way to do this with VBA? Is there some event I should catch on a cell which would allow me to then manually insert the values I want? My knowledge of Excel and VBA is not very good, so sorry if the question is an easy one.
Thank you all in advance!
Let's say that the cell with the number is A3 and the you want to start the series in F3. In F3, put this formula
=IF(COLUMN()-5<=$A$3,COLUMN()-5,"")
Copy F3 and paste to the right (or fill right) for as many columns as you may ever need. If A3 will never be more than 100, then fill right for 106 columns. If you want to start in a column other than F, you'll need to change the -5 parts of the formula.
You won't be able to use a UDF since values are changed in more than one cell. So the easiest way (with VBA) is probably with the Change event. If the value is in the named range "holdvalue" and you want to start the numbers at range "valueStart" then this will work:
Private Sub Worksheet_Change(ByVal Target As Range)
Dim i As Integer
If Target.Cells.Count > 1 Or IsEmpty(Target) Then Exit Sub
If Target.Address = Range("holdvalue").Address Then
For i = 1 To Range("holdvalue")
Range("valueStart").Offset(0, i - 1) = i
Next i
End If
End Sub
Note: This doesn't deal with clearing the values.
You can do this with formulas:
=IF(COLUMN()<$A$35+2,COLUMN()-1,"")
Where $A$35 is the reference cell and I started the "another cell" in column B. If you start at a later column you would need to adjust the +2 and -1 in the formula accordingly. Just drag out the formula to where you would expect the max number would be, you can also do a validation on the reference cell to make sure it is below the max number and a whole number.