UPDATE - this was resolved with:
=OR(ISNUMBER(SEARCH("225522",A2)),ISNUMBER(SEARCH("225522",A3)))
As an advanced filter criteria.
The goal was to find 225522 on the second row, and pull the row above it which was accomplished with the above along with the row containing 225522.
Original question
I have several thousand lines on an excel sheet and each second line has a header line labelled USD. I need to filter to find all of the 225522 rows but I need to include the row above it with the USD.
Example:
USD
11111.222222.333
USD
11111.225522.333
USD
11111.222222.333
USD
11111.222222.333
USD
11111.225522.333
I can filter 225522 and usd, but that would just unfilter all of the rows with 222222 leaving me to manually delete thousands of USD rows. It looks like the below...
USD
USD
11111.225522.333
USD
USD
USD
11111.225522.333
But I need it to look like
USD
11111.225522.333
USD
11111.225522.333
Is there a way to filter 225522 and keep the row above it to achieve my example above?
Use an advanced filter with formula criteria like:
=OR(ISNUMBER(SEARCH("225522",A2)),ISNUMBER(SEARCH("225522",A3)))
where A2 is the first row of data in the relevant column and A3 is the second row.
This is may or may not fit your definition of filter.
In an unused portion of your sheet or in a new sheet use the forllowing formula assuming that your data is in the range A3:A2003
=AGGREGATE(15,6,ROW($A$3:$A$2003)/ISNUMBER(SEARCH("22522",$A$3:$A$2003)),ROW(A1))
That will generate a list of row numbers that match your criteria. What you want to do now is have ROW(A1), increase by 1 every two rows it gets copied down. Then you will want to put an if statement in that so that if ROW(A1) is odd, your use the row number -1 to get your USD. and if even that you leave the row number alone. Now tie that in with INDEX and you will generate the list you are looking for.
so to get it to count every second row increasing by 1 we could use something like:
=INT((ROW(A1)+1)/2)
This would turn our formula into:
=AGGREGATE(15,6,ROW($A$3:$A$2003)/ISNUMBER(SEARCH("22522",$A$3:$A$2003)),INT((ROW(A1)+1)/2))
in order to get our -1 to the row number we could incorporate something like:
=-ISODD(ROW(A1))
incorporating that into the previous formula would result in:
=AGGREGATE(15,6,ROW($A$3:$A$2003)/ISNUMBER(SEARCH("22522",$A$3:$A$2003)),INT((ROW(A1)+1)/2))-ISODD(ROW(A1))
The above could also have been achieved with an if statement but I decided to take a short cut.
The last step will be to incorporate it into an INDEX formula. which will wind up looking like:
=INDEX($A:$A,AGGREGATE(15,6,ROW($A$3:$A$2003)/ISNUMBER(SEARCH("22522",$A$3:$A$2003)),INT((ROW(A1)+1)/2))-ISODD(ROW(A1)))
Now you have the formula, you just need to copy it down as far as you need to go. It will start spewing errors when you run out of acceptable rows.
Alternatively you can set it up to display "" when there is an error/it runs out of rows by using the following:
=IFERROR(INDEX($A:$A,AGGREGATE(15,6,ROW($A$3:$A$2003)/ISNUMBER(SEARCH("22522",$A$3:$A$2003)),INT((ROW(A1)+1)/2))-ISODD(ROW(A1))),"")
The draw back to this method is that it performs array like calculations. As such you should limit its use to a defined range and not full column references within the AGGREGATE function. Having said that the Advanced filter option listed in your comments seems much simpler and probably a hell of a lot faster.
UPDATE
Since you need to pull multiple columns, I would adjust your INDEX portion of the formula. Now assuming your criteria column (column where the 225522 is located) is column F I would modify your formula as follows:
=IFERROR(INDEX($F:$F,AGGREGATE(15,6,ROW($F$2:$F$4401)/ISNUMBER(SEARCH("225222",$F$2:$F$4401)),INT((ROW(A1)+1)/2))-ISODD(ROW(A1))),"")
Now in order to return the same row but different columns there are two ways to approach this. Either change the $F:$F to the appropriate column for each column you want to return or change the range from F:F to F:P and add a column reference to the index. This following method works if the 11 columns are side by side. Other wise you will either have to assign a manual column reference that covers your range or use a match function to match column headers over the same range.
=IFERROR(INDEX($F:$P,AGGREGATE(15,6,ROW($F$2:$F$4401)/ISNUMBER(SEARCH("225222",$F$2:$F$4401)),INT((ROW(A1)+1)/2))-ISODD(ROW(A1)),COLUMN(A1)),"")
The reason you see me using A1 with ROW() or COLUMN() is that I am using it as a counter that starts at 1. So no real harm leaving it at F1 for row references as it is really only important that the row start at 1. conversely COLUMN(A1) can really be any row from column A as I am only interested in starting at 1. If you have to manually index because your columns are not side by side, replace COLUMN(A1) with an integer that represents the column number you want starting from the first column reference in the index range. So in the case of the formula above F:P, start counting from F.
Related
i have an excel sheet in which the first few columns contain titles and information and the rest are repetitive 3 columns sets (i'll refer to as col1,col2,col3), containing dates.
i added an other 3 columns set in which i want to show the last date set in that row(i'll refer to as last1,last2,last3).
currently i set "last3" to look for the last non blank cell in row, last2 to look for the one before and last1 2 before.
problem is, not every time i fill the information i fill the whole set, meaning i could have a situation where the set contains col1 col2 values but not col3, then last3 actually takes a col2 value and messes up everything.
is there a way (please please no VBA programming) to write an array function of some sort that looks for the last 3 col set containing any value, and copying it to the last col set?
thanks!!
I have cooked up this formula for you. It isn't pretty and it's volatile (meaning, it will slow down your worksheet if you have a large quantity of these formula in it) but it does the job. It's the same formula for all columns and all rows.
=INDEX(INDIRECT(ADDRESS(ROW(),1)&":"&ADDRESS(ROW(),COLUMN()-1)),,COUNTA(INDIRECT(ADDRESS(ROW(),4)&":"&ADDRESS(ROW(),COLUMN()-1)))-MOD(COUNTA(INDIRECT(ADDRESS(ROW(),4)&":"&ADDRESS(ROW(),COLUMN()-1))),3)-(2-MOD(COLUMN()-4,3))+(4-1))
In this formula the number 4 stands for the first column of the first set of 3. If you have more columns to the left or fewer, change this number wherever you find it.
The number 3 stands for sets of 3 columns. the "2" in 2-MOD(COLUMN()-4,3)) is also related to this number being used here to reverse the result of Mod(,3) which will be 1, 2 or 0.
-1 generally stands for an adjustment, for example COLUMN()-1 is the number of the column to the left of where the formula resides. But in ADDRESS(ROW(),1) the "1" specifies column A.
The formula specifies a range starting from column 4 to the last column to the left of the formula and counts the number of entries in it, excluding cells of its own group. The 3 entries to be retrieved are in the range extending from itself 2 cells to the left.
If you deploy this formula, replace it with hard values when you add the same formula to the right of columns where it is already deployed. Use Copy/Paste Values (after copying the formulas to the right. This is to reduce the load on your worksheet.
BTW, I took a hard look at this thread, where they deal with columns. Some of the solutions there can be reformulated to work on rows but I failed to make them work on sets of 3.
I am currently automating a dashboard creation and I've hit a bit of a roadblock. I need some code that will go through about 7000 rows of data and return the highest value in a certain column for each specific item. The data is copied from a pivot table and so is broken down into row sections, I have attached a mock of what it looks like.
I need the highest value in Column G for each portfolio, and will need to use the portfolio code (e.g. XY12345 - They are always 7 characters) to map that value to the dashboard.
My issue is, each portfolio has a different number of rows for the values, and some have blank cells between them, and therefore I am stumped. I was hoping to use Column J to count the number of rows for each portfolio (as there are no breaks for the portfolios in this column) and then use a loop to loop through each portfolios rows of values, based off the Column J count, and then return the highest row value for each portfolio. Problem is I'm new to VBA and have been teaching myself as I go, and I've yet to use a loop.
Many thanks,
Harry
If I understand correctly, you're looking for the largest value in Column G.
I'm not sure why you think you would need VBA for this.
Get the maximum value of a column
You mentioned that you're concerned about each column not having the same number of cells but that's irrelevant. as SUM ignores blank cells, so just "go long", or - find the maximum of the entire column.
To return the largest number in Column G you could use worksheet formula :
=MAX(G:G)
The only catch is that you can't place that formula anywhere column G or else it would create a circular cell reference (trying to infinitely add a number to itself). let's pit that formula in cell F1 for now (but anywhere besides column G would do fine).
Find the location of a value
Now that you know the largest value, you can determine where it is using a lookup function such as MATCH or VLOOKUP. Like with so many things in Excel, there are several ways to accomplish the same thing. I'll go with MATCH.
Replace the formula from above (in F1) with:
=MATCH(MAX(G:G),G:G,0)
This will return the row number of the first exact match of the maximum value of Column G.
As for the third part of question: returning the code like X12345 where the value exists, will be a little tricky since your data is not organized in a logical tabular style (tabular meaning, "like a table").
Your data is organized for humans to look at, not for machines to easily read and manipulate it. (See: Office Support: Guidelines for organizing and formatting data on a worksheet)
Basically, when organizing data in rows, all relevant information should be on the same row (not a subjective number of rows behind). Also, you have the number combined with other information.
My suggestion for a quick fix:
Right-click the heading of Column C and choose Insert to insert a blank column.
In C2 enter formula: =IF(B2="",C1,LEFT(B2,7))
Copy cell C2
Select cells in column C all the way to the "end" of your data, where ever that is (not the end of the worksheet). For example maybe you would select cells B2:B1000)
Paste the copied cell into all those cells.
Now, you can again modify the formula in F1:
=INDEX(C:C,MATCH(MAX(G:G),G:G,0))
This will return the value from Column C in the same row that the maximum value of Column G is located.
This is known as an INDEX/MATCH formula.
Hopefully this works for you in the interim until you can organize your data more logically. There's lots of related information and tutorials online.
I want to find the value of corresponding clients PO # Invoice # Quote # etc.. & client list is mentioned in different multiple columns.
Formula used : =INDEX(D16,D17,2,MATCH('Client PO & Invoice Details'!A1:ACZ25,'Client PO & Invoice Details'!A1:ACZ1,0))
LOOKING FOR REQUIRED LOOKUP FUNCTIONS WITH MATCH OFFSET INDEX
The staging of your data is really inefficient. If you made a client number column and expanded the data vertically rather than horizontally, you could really save yourself a lot of headaches. For example, if your data was organized that way you could use a pivot tabel to massively simplify this problem.
Barring changes to your data structure, you can do a vlookup for the date against an offset range:
=VLOOKUP($D$17,OFFSET('Client PO & Invoice Details'!$A$1,0,MATCH($D$16,'Client PO & Invoice Details'!$1:$1,0)-1,1048575,6),2,FALSE)
This formula should be placed in D18:D22 below the id and date filters. you will need to increment the vlookup index toward the end of the formula ( ...,2,FALSE) to grab the specific column you are looking for. The 2 will need to be updated to 3,4,5, and 6 in the subsequent formulas to get each of the values.
First The formula finds your client number in row 1, next the offset defines a range 6 columns wide starting at the column that the client number was found in, lastly the vlookup works as usual by finding the date in the first column of the offset range and returning the value of the indexed column.
INDEX(range you want to look in, how many rows down from the top of your range, how many columns to the right)
That is the basic usage for index. If the range is a single row or single column, then only the second entry is required and its how far down the range do you want to go. Another small caveat is if you 0 for # of rows or columns. 0 will make index return the entire corresponding row or column.
lets start by looking at what set of columns you want to be looking at. you need to match D16 (client#) with the appropriate entry in your header row. To do this, MATCH is a great choice.
=MATCH(value you are looking for, range you want to look in, and what type of match)
In your case
=MATCH($D$16,'Client PO & Invoice Details'!$1:$1,0)
$1:$1 is the entire 1st row of the spread sheet. The $ will keep the row number from changing if the formula was copied up/down to another cell. The 0 at the end tells the function you want an exact match, and not an approximate type match. After performing this function you will know what column to start looking in.
So now you need to figure out what row you want to work with and then start pulling the data. This could be down with a VLOOKUP. You could define your range using an OFFSET function. I am however going to take a different route. I am going to use MATCH again to determine the row we want to look at based on the column we determined
=INDEX('Client PO & Invoice Details'$A:$ACZ,0,MATCH($D$16,'Client PO & Invoice Details'!$1:$1,0))
This index is going to all rows in the column found with the match. So now we need to do a match in those results to figure out what row you are working with. In doing so we get a formula that looks like:
=MATCH($D$17,INDEX('Client PO & Invoice Details'$A:$ACZ,0,MATCH($D$16,'Client PO & Invoice Details'!$1:$1,0)),0)
Now that you know the row you are working with and the column(S) you are working with you can now extract the data you need using INDEX.
In D18 place the following formula
=INDEX('Client PO & Invoice Details'$A:$ACZ,MATCH($D$17,INDEX('Client PO & Invoice Details'$A:$ACZ,0,MATCH($D$16,'Clent PO & Invoice Details'!$1:$1,0)),0),MATCH($D$16,'Client PO & Invoice Details'!$1:$1,0)+1)
In D19 use the same formula but change the +1 to +2. keep doing that as you go down increasing the +# by one each time.
Based on the comment you will add columns as clients are added, you will need to adjust the formula each time a client is added. There are ways to automated this, but you are probably better off going the offset route in this case.
Be aware that you do have a limited number of column to group clients by.
tl;dr Is it possible to label cells as 'ignore' (or equivalent) so that if they are included in the range of a SUM function, they are not included in the calculation and therefore outputted value?
I have created a complex table that depicts revenue over the next few years. The table rows run continuously through the months with no break between December of one year and January of the next. I have realised I need to put in a Total column at the end of each year. If I select each Jan column and click insert, I get a vacant column at the end of each year that can be used for my total column (to the left of each Jan). However, I use SUM extensively in each row and I do not want any of the cells in the Total columns to be included in any of the calculations of the cells for the months. Is it possible for me to write my formulae in each Total column cell and then somehow specify that I do not want this value to be included in any calculations at all i.e. is there some sort of 'ignore' label i can apply to these cells? I know the alternative is to manually change each formula, but I have 5 years worth of predictions each with 50 rows and each cell has multiple SUM functions in it...
Say we have values in column A from A1 through A400, but some of the items are intermediate subtotals, etc. We want to sum column A, but omit the subtotals.
In column B place a 1 in rows that you want to process and a 0 in rows you want to skip
Then use:
=SUMPRODUCT((A1:A400)*(B1:B400))
Two options:
Use the SUBTOTAL function to calculate those subtotals, and the AGGREGATE function to do the sum at the end, as it has an option that lets you ignore SUBTOTAL results.
Use a PivotTable. You can then easily subtotal by year or whatever else you want.
I would personally go for option 2
I have a spreadsheet and I need to match the two columns together. However "Dove code" is 3600 rows and "code 2" is 1100. They all have the same codes as you can see in the image but you can also see where it starts changing and I need to have the codes all line up so I can see the gaps. I have already arranged them all alphabetically and its the "code 2" that would need to match up to "Dove code
If the above solution would result in too much shunting and vba is not an option, there's another way. Copy the first column and use 'remove duplicates' on it. Now you have an index list, put numbers from 1 to x in the column on the right of it.
Insert a column between the two lists and right of the second one.
Assuming that the index list is in F and the numbers in G, put this formula in the cell right of the first cell in the larger list:
=VLOOKUP(A2,$F$2:$G$500,2,FALSE)
Adjust the range accordingly. Put the same formula in the cell right of the first cell in the shorter list, with of course C2 instead of A2. Copy both formules to the end of the list.
Now both columns have an index on every row. You can match them using data sort, but for that you need to add dummies in the index columns.
Put this formula in the cell right of your basic index list: =countif(B:B,G2)
And this one in the cell right of that: =countif(D:D,G2)
Now you know how many times each record arises in both lists. Just add extra numbers manually so that both formulas turn up the same result. You should be able to do that really fast. If you have 200 records that are used 2 times in the first column and not in the second one, just copy the index of those 200 records and paste them twice. The countif's will automatically update.
You can use an extra column to calculate the difference between the two counts and use data sort on your basic index list to sort on the diferences.
After that just use data sort.
IF my directions are clear enough, this shouldn't cost you more than 10 minutes.
Edit:
Here's an example: http://img14.imageshack.us/img14/6366/k8pg.jpg
Without VBA I do this (for columns with a limited number of mismatches!) by adding a formula such as =INDIRECT("A"&ROW())<>INDIRECT("B"&ROW()) in a helper column. Working downwards, every time you see a TRUE shunt the appropriate column down to suit. But it may be only just about viable for 1100 rows!