Reference cells with no gaps to fill table with gaps - excel

I have included 2 tables below to illustrate my problem.
Table 1
Table 2
I am trying to find a formula that fills rows 140, 143 & 146 (Table 2) from rows 15,16 & 17 (Table 1). There is over 100 so it is quite time consuming to input =B15 etc over and over again.
The offset method e.g. =OFFSET($B$15,(ROW()-1)*3,0) only works when I'm referencing gaps, not trying to fill them.
Essentially, where B140's formula is =B15, B143's will be =B140 + 1 row i.e. B16
Thanks for your help!

If you are trying find value for appropriate month you can use INDEX/MATCH entered as array formula:
=IFERROR(INDEX($B$1:$B$4,MATCH(TRUE,MONTH(A10)=MONTH($A$1:$A$4),0)),"")
Array formula after editing is confirmed by pressing ctrl + shift + enter
Edit
To find by month & year use:
=IFERROR(INDEX($B$1:$B$4,MATCH(1,(MONTH(A10)=MONTH($A$1:$A$4))*(YEAR(A10)=YEAR($A$1:$A$4)),0)),"")
it's also array formula

You can use modulo for this. With the Modulo function, you check if the remainder of the row you're on is divisible by a number (e.g. 3 if you want to copy a value every third row). IF(MOD(ROW(E1);3 = 0)
If that's the case, you can divide by 3 and use for example the Index function to copy the nth value of another location (or another worksheet). If that's not the case, you print "" to get an empty row.
=IF(MOD(ROW(E1);3)=0;INDEX($B$1:$B$4;ROW(E1)/3);"")
If you're working with offsets because the row numbers are not on numbers divisible by three, you could manually offset the rows (and do the same for the division that yields the index row). For example, if you want to have rows 2, 5, 8 etc:
=IF(MOD(ROW(E1)+1;3)=0;INDEX($B$1:$B$4;ROW(E2)+1/3);"")

Related

How to make Excel follow a formula algorithm on every 3 rows

I want to make Excel follow a formula pattern on every 3 rows, such that after an increase of three in the conditional if statement, there should be an increment of one on return value "TRUE". So that every time I drag it down, the algorithm gets applied to succeeding 3 rows that it follows. I have this simple formula of:
=IF(B11="RTR",RTR!G11:Z11,IF(B11="DHG2",'DHG2'!G11:Z11,IF(B11="JQV",JQV!G11:Z11,"")))
=IF(B12="RTR",RTR!G11:Z11,IF(B12="DHG2",'DHG2'!G11:Z11,IF(B12="JQV",JQV!G11:Z11,"")))
=IF(B13="RTR",RTR!G11:Z11,IF(B13="DHG2",'DHG2'!G11:Z11,IF(B13="JQV",JQV!G11:Z11,"")))
=IF(B14="RTR",RTR!G12:Z12,IF(B14="DHG2",'DHG2'!G12:Z12,IF(B14="JQV",JQV!G12:Z12,"")))
=IF(B15="RTR",RTR!G12:Z12,IF(B15="DHG2",'DHG2'!G12:Z12,IF(B15="JQV",JQV!G12:Z12,"")))
=IF(B16="RTR",RTR!G12:Z12,IF(B16="DHG2",'DHG2'!G12:Z12,IF(B16="JQV",JQV!G12:Z12,"")))
Following the formula I wanted, it's supposed to be followed by:
=IF(B17="RTR",RTR!G13:Z13,IF(B17="DHG2",'DHG2'!G13:Z13,IF(B17="JQV",JQV!G13:Z13,"")))
I tried dragging down the formula to apply it to below rows but the pattern doesn't follow to what I wanted. Instead, the row below goes into like:
=IF(B17="RTR",RTR!G17:Z17,IF(B17="DHG2",'DHG2'!G17:Z17,IF(B17="JQV",JQV!G17:Z17,"")))
Need a little bit of help here.
Thank you.
Here is a solution that doesn't require helper cells:
This formula will increment by 1 every 3 rows:
=CEILING.MATH(ROW()/3)
If you want the sequence to start on a different row, say row 10, you can just subtract that number - 1 from the ROW(), so for starting on row 10 from 1, subtract 9:
=CEILING.MATH((ROW()-9)/3)
And if you wanted the sequence to start from a different number at a different row, you can just add that number -1 to this whole thing, this example will start at 11 on row 10:
=CEILING.MATH((ROW()-9)/3)+10
EDIT: Much better solution proposed by P.b, you don't need the IFs at all:
=INDIRECT(B11 & "!G" & (CEILING.MATH(ROW()/3)+10) & ":Z" & (CEILING.MATH(ROW()/3)+10))
So, an example which you can expand:
VLOOKUP(A1,INDIRECT("'RTR'!"&"G11:Z11",1),1,0)
Not sure where you increment of 3 occurs as B11 goes to B12 and even the last two B16 goes to B17 and the target range matches the row numbers.
As I have shown you can build the target range so adding the row numbers is trivial now. They can be taken from cells, C1 could be 3, C2 6 etc.
The following could be used (to avoid using (volatile) INDIRECT):
=INDEX(
CHOOSE( MATCH(B11, {"RTR","DHG2","JQV"}, 0),
'RTR'!G:Z, 'DHG2'!G:Z, 'JQV'!G:Z),
INT((ROW()-11)/3)+11,
)
It selects the correct tab by matching the value in B11 to an array mentioning the names of the tabs. It than indexes range G:Z from that tab.
The row number shifts 1 number every 3 rows because of INT((ROW()-11)/3)+11.

Excel Vlookup calculating marks with age range and pushup result

I am testing my clients for pushups and other exercises.
I want to make excel table where I can put client name, age, number of reps
and to make some formula that can put the new column with given mark. According to
table of ranges.
Table of problem
Use INDEX/MATCH:
As stated, change your Age and number of pushups to just the minimums; 20,30,40,50. And change the order from lowest mark to highest.
And do not skip any lines.
=INDEX($A:$A,MATCH($D11,INDEX($A:$F,0,MATCH($C11,$1:$1))))
Reformat your values, just write your minimum values in the cells (e.g. 20 instead of 20-29) and turn the table around so that 1 is on top and 5 is at the bottom. Then you can use the following formula:
=Indirect(Address(Match(val, Indirect(Address(4, Match(age, A2:F2, 1)) & ":"
& Address(8, Match(age, A2:F2, 1))), 1) + 3, 1))
Quite some formula actually ;) What it does:
Match(age, A2:F2, 1)
returns the column in which the user is to be sorted.
The inner Indirect creates a matrix with that column (e.g. if age is 25, this returns B4:B8).
The outter Match searches the value within this matrix and returns the corresponding row.
With that row and the fixed first column you can get your desired mark.
I wrote this one
=INDEX($A:$A,MATCH($D$11:$D$17,INDEX($A:$F,0,MATCH($C​$11:$C$17,1:1))))
table2
Just one more thing,
if I want to be able to keep formula open for more people...formula remain the same,just to change D number and C number?
table3

Find a range of value in excel

I have two different sheets with 300,000 data in Excel.
First sheet contains:
S2_Symbol Start_Pos End Position
STE 254857 267891
PRI 748578 758962
ILA 852741 963369
VIS 789456 796325
Second:
S1_Location
789460
852898
748678
My output should be like this:
S1_Location Symbol
789460 VIS
852898 ILA
748678 PRI
I have to find that S1_location falls in which S2_location and its corresponding Symbol. I have used INDEX formula in Excel but for each cell, I have to change the reference cell manually. I couldn't do it 300,000 data.
How can I do in an in Excel or should I use a script?
This solution assumes the following:
Start and End Positions for each S2 Symbol are unique (i.e. there is no intersection between the ranges allocated to each symbol)
Data in first sheet is located at A1:D17 (adjust ranges in formulas as needed)
Data in second sheet is locate at A1:B300010 (adjust ranges in formulas as needed)
The solution requires:
To add a working column in worksheet one. Enter this formula in D2 and copy till last record.
=ROWS($A$1:$A2)
Fig. 1
Then in second worksheet enter this formula at B2 and copy till last record.
=INDEX( Sheet1!$A$1:$A$17,
SUMIFS( Sheet1!$D$1:$D$17,
Sheet1!$B$1:$B$17, "<=" & $A2, Sheet1!$C$1:$C$17, ">=" & $A2 ) )
Fig. 2
It took aprox. less than 14 seconds to copy downwards and calculate the formulas in sheet 2.
As it can be seen in figures 1 and 2 none of the tables need to be sorted.
Assuming both sheets start in A1, and First sheet ColumnB is sorted ascending, in Second sheet B2 please try:
=INDEX(First!A:A,MATCH(A2,First!B:B))
copied down to suit. It relies on inexact matching.
Assuming we have a Sheet1 like this:
note, the Sheet1is sorted by Start_Pos, End_Pos in ascending order.
and a Sheet2 like this:
Then the formula in Sheet2!B2 downwards could be:
=INDEX(Sheet1!A:A,IF(MATCH(A2,Sheet1!B:B)>IFERROR(MATCH(A2-(10^-10),Sheet1!C:C),0),MATCH(A2,Sheet1!B:B),NA()))
See MATCH: https://support.office.com/en-us/article/MATCH-function-e8dffd45-c762-47d6-bf89-533f4a37673a
The idea is: MATCH without exact matching (without parameter match_type) gets the row of the largest value which is smaller or equal the search value. So in the Start_Pos column it will get the row from which we can get the S2_Symbol. But from the End_Pos column it should get one row beforehand if the value is not outside the given ranges.
There is only one exception. If the value is exact the value in the End_Pos column, then it will return the same row as in the Start_Pos column. Considering this exception, we can search in the End_Pos column with a little bit smaller value. Thanks to Tom Sharpe for his comment.
The formula in Sheet2!D2 downwards is:
{=INDEX(Sheet1!A:A,MIN(IF($A2>=Sheet1!$B$2:$B$300000,IF($A2<=Sheet1!$C$2:$C$300000,ROW(Sheet1!$A$2:$A$300000),2^20+1))))}
this is an array formula which is exactly formulated respecting the requirements. But this is very bad in performance for using in much many cells. But using this, the Sheet1 is not required to be sorted.
Benchmark test:
Have the following Sheet1:
Formulas:
A2:A300002: ="S"&(ROW(A1)-1)*10&"-"&(ROW(A1)-1)*10+7
B2:B300002: =(ROW(A1)-1)*10
C2:C300002: =B2+7
and the following Sheet2:
Formulas:
A2:A300002: =RANDBETWEEN(0,3000007)
B2:B300002: =INDEX(Sheet1!A:A,IF(MATCH(A2,Sheet1!B:B)>IFERROR(MATCH(A2-10^-9,Sheet1!C:C),0),MATCH(A2,Sheet1!B:B),NA()))
Note the -10^-9 instead of -10^-10 in previous version. This is because we have only 16 digits precision. In previous version this was maximum 6 digits integer part and then 10 digits decimal part. Now it is maximum 7 digits integer part and then 9 digits decimal part.
Calculation after pressing F9 in Sheet2 takes ca. 2 s. (Excel 2007, Windows 7, 4 core processor).
I would have gone for something like this which gives you the first match if there is one:-
=INDEX(First!A:A,MATCH(1,(First!B:B<=A2)*(First!C:C>=A2),0))
assuming keys and start and end values are in a sheet called First and lookup values start in A2.
Array formula which must be entered with CtrlShiftEnter
In response to the question from #pnuts about how long it will take, I have set up a similar benchmark with 300,000 rows in each sheet and it has reached 1% after 90 minutes, so it should take about 150 hours to reach 100% or roughly one week. This is to be expected as the number of computations required is (rows in sheet 1) X (rows in sheet 2)
300,000 X 300,000
but in fact because the multiplication applies to complete columns, I believe it is more correctly
300,000 X 1,048,576
i.e. > 300 billion.
A practical version which gives good response for smaller ranges is as follows:-
I define three named ranges Range1, Range2 and Range3
=First!$A$1:INDEX(First!$A:$A,MATCH("ZZZ",First!$A:$A))
=First!$B$1:INDEX(First!$B:$B,MATCH(9.9E+307,First!$B:$B))
=First!$C$1:INDEX(First!$C:$C,MATCH(9.9E+307,First!$C:$C))
and the modified formula is
=INDEX(Range1,MATCH(1,(Range2<=A2)*(Range3>=A2),0))
I was thinking of deleting this answer, but would rather it stood as a counter-example.

Looking for formula to extract specific values from a row containing numbers and blanks

I have a sheet with rows of data, with many columns. I am looking for help on a formula that will extract the sum of the smallest 3 numbers in a row based on the last 5 values entered. Note that not all the rows will have values for each column, so the first value found on each row will may be found in a different column.
To determine the sum of the smallest 3 I am using the formula =SUM(SMALL(B3:R3,{1,2,3})), Unfortunately, that formula is looking at the entire range. Again, I am looking for help that with a formula that will select only the last 5 values posted.
Here is simple example. The results for each line show the totals that should be determined. Again, it needs to look for the sum of the smallest 3 based on the last 5 posted (in the example below the range would be col. 1 thru 10, with col 10 having the latest postings).
Ex.
1.....2.....3......4......5.....6.....7.....8......9.....10...... Result
31.........44....51....36..........44...34....36....38.......106 (34+36+34)
35..31...44...40.....38...52..........42....37...............115 (37+38+40)
Hope this is understandable. I am looking for a formula solution vs a VBA macro solution because of my users. Thanks for any help!!
Now that you clarified the question, I have an answer for you. This is fairly ugly but it gets the job done. You might want to hide the columns with the intermediate results - or you could get adventurous and "nest" the expressions. This makes it really hard to understand / debug though. If there's a smarter way to do this I am always open to learning.
Assuming you have the data in columns A through J, starting in row 2, put the following in cell L2:P2:
=MATCH(9999, A2:J2,1)
=MATCH(9999,OFFSET($A2,0,0, 1, L2-1)) ... copy this by dragging right to the next 2 columns
=MATCH(9999,OFFSET($A2,0,0, 1, M2-1))
=MATCH(9999,OFFSET($A2,0,0, 1, N2-1))
=MATCH(9999,OFFSET($A2,0,0, 1, O2-1))
The first line finds the last cell with data in it; the next ones find the last cell "not including the last cell", and so they work backwards. The result is a number corresponding to the columns with data. For your example, this gives
10 9 8 7 5
9 8 6 5 4
Now we want to find the sum of the smallest 3 of these: put the following equation in cell Q2:
=SUM(SMALL(INDIRECT("RC["&P2-17&"]:RC["&L2-17&"]",FALSE),{1,2,3}))
Working from the inside out:
RC["&P2-17"] results in RC[-12], which is "the cell 12 to the left of this one".
That is the first of the "last five cells with data", cell E2
RC["&L2-17"] results in RC[-7], the last cell with data in this row
FALSE use "RC" rather than "A1" indexing
INDIRECT turn string into an address (in this case a range)
SMALL find the 3 smallest values in this range
SUM and add them together.
This formula did indeed give me 106, 115 for the example you provided.
I would hide columns L through P so you only see the result (and not the intermediate stuff).

Copy every nth line from one sheet to another

I have an Excel spreadsheet with 1 column, 700 rows. I care about every seventh line. I don't want to have to go in and delete the 6 rows between each row I care about. So my solution was to create another sheet and specify a reference to each cell I want.
=sheet1!a1
=sheet1!a8
=sheet1!a15
But I don't want to type in each of these formulas ... `100 times.I thought if I selected the three and dragged the box around, it would understand what I was trying to do, but no luck.
Any ideas on how to do this elegantly/efficiently?
In A1 of your new sheet, put this:
=OFFSET(Sheet1!$A$1,(ROW()-1)*7,0)
... and copy down. If you start somewhere other than row 1, change ROW() to ROW(A1) or some other cell on row 1, then copy down again.
If you want to copy the nth line but multiple columns, use the formula:
=OFFSET(Sheet1!A$1,(ROW()-1)*7,0)
This can be copied right too.
In my opinion the answers given to this question are too specific. Here's an attempt at a more general answer with two different approaches and a complete example.
The OFFSET approach
OFFSET takes 3 mandatory arguments. The first is a given cell that we want to offset from. The next two are the number of rows and columns we want to offset (downwards and rightwards). OFFNET returns the content of the cell this results in. For instance, OFFSET(A1, 1, 2) returns the contents of cell C2 because A1 is cell (1,1) and if we add (1,2) to that we get (2,3) which corresponds to cell C2.
To get this to return every nth row from another column, we can make use of the ROW function. When this function is given no argument, it returns the row number of the current cell. We can thus combine OFFSET and ROW to make a function that returns every nth cell by adding a multiplier to the value returned by ROW. For instance OFFSET(A$1,ROW()*3,0). Note the use of $1 in the target cell. If this is not used, the offsetting will offset from different cells, thus in effect adding 1 to the multiplier.
The ADDRESS + INDIRECT approach
ADDRESS takes two integer inputs and returns the address/name of the cell as a string. For instance, ADDRESS(1,1) return "$A$1". INDIRECT takes the address of a cell and returns the contents. For instance, INDIRECT("A1") returns the contents of cell A1 (it also accepts input with $'s in it). If we use ROW inside ADDRESS with a multiplier, we can get the address of every nth cell. For instance, ADDRESS(ROW(), 1) in row 1 will return "$A$1", in row 2 will return "$A$2" and so on. So, if we put this inside INDIRECT, we can get the content of every nth cells. For instance, INDIRECT(ADDRESS(1*ROW()*3,1)) returns the contents of every 3rd cell in the first column when dragged downwards.
Example
Consider the following screenshot of a spreadsheet. The headers (first row) contains the call used in the rows below.
Column A contains our example data. In this case, it's just the positive integers (the counting continues outside the shown area). These are the values that we want to get every 3rd of, that is, we want to get 1, 4, 7, 10, and so on.
Column B contains an incorrect attempt at using the OFFSET approach but where we forgot to use $. As can be seen, while we multiply by 3, we actually get every 4th row.
Column C contains an incorrect attempt at using the OFFSET approach where we remembered to use $, but forgot to subtract. So while we do get every 3rd value, we skipped some values (1 and 4).
Column D contains a correct function using the OFFSET approach.
Column E contains an incorrect attempt at using the ADDRESS + INDRECT approach, but where we forgot to subtract. Thus we skipped some rows initially. The same problem as with column C.
Column F contains a correct function using the ADDRESS + INDRECT approach.
If I were confronted with extracting every 7th row I would “insert” a column before Column “A” . I would then (assuming that there is a header row in row 1) type in the numbers 1,2,3,4,5,6,7 in rows 2,3,4,5,6,7,8, I would highlight the 1,2,3,4,5,6,7 and paste that block to the end of the sheet (700 rows worth). The result will be 1,23,4,5,6,7,1,2,3,4,5,6,7,1,2,3,4,5,6,7……. Now do a data sort ascending on column “A”. After the sort all of the 1’s will be the first in the series, all of the 7’s will be the seventh item.
insert a new column and put a series in 1,2,3,4, etc. Then create another new column and use the command =if(int(a1/7)=(a1/7),1,0) you should get a 1 in every 7th row, filter the column on the 1
Highlight the 7th line. Paintbrush the format for the first 7 lines a few times. Then do a bigger chunk of paintbrush copying the format until you are done. Every 7th line should be highlighted. Filter by color and then copy and paste (paste the values) from the highlighted cells into a new sheet.
Create a macro and use the following code to grab the data and put it in a new sheet (Sheet2):
Dim strValue As String
Dim strCellNum As String
Dim x As String
x = 1
For i = 1 To 700 Step 7
strCellNum = "A" & i
strValue = Worksheets("Sheet1").Range(strCellNum).Value
Debug.Print strValue
Worksheets("Sheet2").Range("A" & x).Value = strValue
x = x + 1
Next
Let me know if this helps!
JFV
If your original data is in column form with multiple columns and the first entry of your original data in C42, and you want your new (down-sampled) data to be in column form as well, but only every seventh row, then you will also need to subtract out the row number of the first entry, like so:
=OFFSET(C$42,(ROW(C42)-ROW(C$42))*7,0)
Add new column and fill it with ascending numbers. Then filter by ([column] mod 7 = 0) or something like that (don't have Excel in front of me to actually try this);
If you can't filter by formula, add one more column and use the formula =MOD([column; 7]) in it then filter zeros and you'll get all seventh rows.

Resources