Copy matching cells based on one column - vba

Please see here for snippet from my spreadsheet, what I am trying to do is fairly simple, however I am unable to find a way to do this after searching through online forums extensively.
Column A contains my order numbers and column B the line items that correspond to each order number.
Column D contains the delivery date as it appears on my printed order sheet, you will see this only pulls through for the first line item on each order - the raw data displays this way and so there is way to change the raw data
Column E simply extrapolates just the date rather than the format Delivery Date: dd/mm/yyyy.
What I would like then, is for column E to have the delivery date copied down to all corresponding cells for each order number - so as per the attached sheet, 30 Jul 2015 would appear for all line items that correspond to order no #1192.
I feel v look up etc will only work to manipulate data once I have these dates copied down. I have tried index match but it doesn't seem to do what I want it to do.
Is there a way to copy down the dates for all line items relative to their order number? I understand that it will probably require copying full lines down column D first and keeping the formula in column E to extrapolate just the date.
Any help is much appreciated

You don't need a macro for this. There are many ways to go about this, I'll show you two, you can figure out the one you like from there.
Select coloumn E, go to Home, Editing, Find & Select, Go To Special. Hit Formulas (if the values are not formulas, go for Constants), and check only Errors. Now type =E2 (or whatever is above your active cell), and hit Ctrl+Enter. It is a wise idea to copy-paste values the whole coloumn E after this.
Another way would be entering this formula in coloumn F (cell F2, then pull it down):
=IFERROR(E2;F1)
Or you could combine this with your original formula, or use a macro to insert the formula in the empty/#error cells etc...

Assuming you are using =RIGHT(D2,LEN(D2)-FIND(":",D2)-1) in E2, then you are well on the way to a solution.
You also mentioned INDEX/MATCH which, if used in column F will pull the Delivery Date in Column E for each Order No:
=INDEX($E$2:$E$31,MATCH(A2,$A$2:$A$31,0))
This finds the position of the first match for your Order No and returns the Delivery Date from column E.

Related

Complex IF. formula in Excel

I checked various posts on IF formulas but I cannot find a way to receive the correct result in my report. I manage deliveries and I would like to calculate the delay days basing on the data from delivery report. The trick is that the delay will depend on the status of delivery, as in each case I have to consider a different date and column in Excel. These are the data:
Status of delivery:
Confirmed
Unloaded
Unloading
Not confirmed
Started
In route
Pick-up pending
Prepared
This delivery status is updated in C column in my Raw Data report. For each, I will have to calculate the delay in a different way therefore I figured that IF formula could be of use.
Below you can see the columns that contain the relevant dates for the calculations:
Status of delivery and reference date:
Confirmed - D
Unloaded - D
Unloading - D
Not confirmed - S
Started - D
In route - S
Pick-up pending - E
Prepared - S
I made this formula as below, sadly, only the first record is calculated correctly, the rest of the delays is "null".
=IF(C2="Confirmed";(TODAY()-D2);IF(C2="Unloaded";(TODAY()-D2);IF(C2="Unloading";(TODAY()-D2);IF(C2="Not confirmed";(TODAY()-S2);IF(C2="Started";(TODAY()-D2);IF(C2="In route";(TODAY()-S2);IF(C2="Pick-up pending";(TODAY()-E2);IF(C2="Prepared";(TODAY()-S2);"null"))))))))
Do you happen to have any idea where am I making the error which I don´t see? I will be grateful for any help. If it´s also relevant, I am using Excel 2016.
Breaking it down so the long line becomes readable.
=IF(C2="Confirmed";
(TODAY()-D2);
IF(C2="Unloaded";
(TODAY()-D2);
IF(C2="Unloading";
(TODAY()-D2);
IF(C2="Not confirmed";
(TODAY()-S2);
IF(C2="Started";
(TODAY()-D2);
IF(C2="In route";
(TODAY()-S2);
IF(C2="Pick-up pending";
(TODAY()-E2);
IF(C2="Prepared";
(TODAY()-S2);
"null"
)
)
)
)
)
)
)
)
At first glance, what I'm looking at is basically a vertical lookup schedule here.
So, I created these two colums. One is the text status we're looking for.
The other is the calculated date.
Single date VLOOKUp
Assuming D2, S2 and E2 are fixed fields I made the formula =TODAY() - $D$2
Then it's a simple matter of doing the VLOOKUP in the correct field.
Because we're working with a date type field we need to convert the number to text to get a meaning full date. (I used JJ in the screenshot for years because I have a dutch locale)
Then we also need to handle when VLOOKUP can't find anything, for that we use IFERROR.
=IFERROR(TEXT(VLOOKUP(F6;$A$2:$B$9;2);"MM-DD-YY");"NULL")
And now you have an easy to expand lookup table you can put anywhere, hide on a worker tab, etc.. where you can calculate your values, where you can add and remove values.
Many rows, many dates
But, say you have many rows with different statusses and dates, and you wish to know the number of days it'll take. Then this vertical lookup doesn't look so useful because it can only be used for one row.
We can still leverage VLOOKUP to make our life a bit easier
Assuming there are dates in colums D, E and S
=IFERROR(DATEDIF(TODAY();INDIRECT(ADDRESS(ROW();VLOOKUP(F2;$A$2:$B$9;2;FALSE)));"d");"NULL")
We use VLOOKUP to see which column we need to look in. We use a number here for column, not a letter.
We then use ADDRESS to get an excel address reference for the current ROW(), and the column we found via vlookup
We funnel that through INDIRECT so we can get the value from that targeted cell.
Then we get a DATEDIFference in days from offset today.
We wrap it all in an IFERROR to keep things clean.
You could use an INDEX($D2:$S2;0;VLOOKUP($F2;$A$2:$B$9;2;FALSE)) to get the same effect, as pointed out by Dirk Reichel but you have to mindful then that the index used is from the start of the matrix range. So here the matrix starts on row D. So D2 is index 1 instead of 4 it is with my original method, so you'd need to adjust the lookup table accordingly.

Match, pull and add numbers from different cells on a different sheet

I have data on 'JobSheet1' in Column D, I have Invoice Numbers in ascending order (some are repeated for different products on same order), in Column E, I have amounts i.e £50.00.
On a second sheet 'InvoicesSheet1' in Column B, I have the invoice numbers and Column C is where I would like the total for each invoice number to appear.
Can anyone help with very simple VBA or a formula that will search for the Invoice Number its sitting by in 'JobSheet1' Column D and add all the matching invoice number totals from Column E.
Scott Craner is right, with the schema you described, you will get the result you want entering into cells Ci:Cj (where "i" and "j" are
the start and end of your table, respectively):
=SUMIFS('JobSheet1'!E:E,'JobSheet1'D:D,B{i...j})
If this doesn't work, likely issues you need to watch out for would be:
Sheets are not named exactly as you typed here. Maybe they have a leading or trailing space.
Your copy of Excel/Windows may be set with a different regional setting, which requires that formula parameters be separated by semicolons (;) instead of comas.
Your invoice numbers may not be typed precisely the same in the two different formulas.
Your amounts in column E may not be stored as numeric values. You can test for this by selecting a few values from column E - if excel doesn't show their sum and average in the bottom right corner, they are stored as text and you can't perform math operations on them.
I'd need to see your data to see what could be the issue, but that's not what this forum is for - Try constructing a new table with dummy data set up exactly as you described it here and try using this formula, to verify if it works. Then, adjust accordingly as needed.
Assuming you're first invoice number in InvoiceSheet1 is in cell b3, you can use:
=SUMIF(JobSheet1!D:D,InvoiceSheet1!B3,JobSheet1!E:E).
If it's in another row, replace InvoiceSheet!B3, with the relevant cell where your data starts. Copy down the formula for the other invoices
SUMIFS is not necessary with just one lookup condition.
I solved this by amending the SUMIFS suggestion from ScottCraner and this is what I ended up with
=SUMIFS(Jobs!K:K,Jobs!A:A,D3)+SUMIFS(Jobs!L:L,Jobs!A:A,D3)
Does the job!

How to reference a specific cell location within a changing table

I am not sure how, if at all, this can be done. Basically I have a report that is generated from SalesForce for some co-workers. It exports to Excel in this nice little table. Depending on their team, they filter the results and then filter the month (fiscal year in this case).
What I want to do is have text populate at the top which is based on the text that is in the first cell in the column C (not including header row of course) when they filter. How do I go about referencing the spot where C4 is currently when they select Team "White-1" and Fiscal Year "Aug"? That cell will become hidden and I will need to pull the data from C6 which HAPPENS to be in the location that C4 was just in before being hidden.
Here is an image of the report in Excel as well as the "location" that I want to reference no matter the filtering that the employee does:
Report
I assume VBA will be needed. Preferably I want to generate the text in A1
If you are ok with adding a "Helper Column" you can do the following to get the results you are wanting:
Add a column between B and C Give it a header of some kind I used "Helper". Then in this new Column use use the formula =Row() to generate a number for each row.
You can hide this column now if you want.
Then in whichever cell you want the answer you seek enter the following formula:
=Vlookup(Aggregate(5,5,C:C),C:D,2,false)
Now you can filter all you want and you should get the result you wanted.

Searching column for consecutive values and returning three different values to other cells

I have a series of columns. One contains a time stamp for a data point, the next is the data point, the one following that is a conversion from decimal to binary for that data point, and the remaining columns are that binary string split into each bit. Each column has a title: "No Engine Speed", "Engine Derate", and so on.
Here's what I'd like to do, but don't have the skill with VBA/Excel to do. I'm trying to take all that information and put it into something that's more friendly to a reader.
So, for example this:
would get me this:
The description comes from the column titles, and the time range start/end would come from the first column. The error codes I'll get with an Excel IF function or some kind of VLOOKUP function based on the contents of the description column. What I need is a VBA code or set of Excel functions that will populate those description and time stamp columns for me based on the contents of those bit columns.
How I envisioning it working is as follows: each bit column is searched through, if a 1 is found and the four cells more more below it are also found to be 1s the date stamp of the first 1 and final 1 populate the Start/End times in the more readable report I'm creating. In addition to this, the column header is copied to the description field.
The reason I want to only get the time stamps if there are five or more 1s consecutively is that I want some time to pass before the state is considered to be an 'event'. A second condition I'd like to meet would be that the time stamps are reasonably close together (say, within 2 minutes of each other). This is why even though there is a '1' event in the picture I linked for "16-May-15 21:52:47" I excluded it from the second image I linked.
The numbers next to the time stamps (and the timestamps themselves) will change depending on when the user opens the workbook. Those columns are the result of a query to a database and change based on what the previous shift's start and end time were. As a side note, when copying the time stamps I know that you need to paste the cell value and not just a regular paste, otherwise you wind up copying a query array to the database. I don't know if that has any bearing on a coding solution but I thought it was worth mentioning.
I considered trying to use some type of VLOOKUP function, but what I found doesn't quite do what I want because it doesn't check if there's five events or more in succession. Any guidance or direction you all can provide would be greatly appreciated. I feel like I have an idea of how to do this but I'm new to VBA and my Excel abilities are not up to the task just yet, and my Googling isn't turning up what I need.
I hope I was clear in my explanation of what I'm trying to do, feel free to ask questions if I wasn't.
Thanks,
Dan
EDIT 1:
As Grade 'Eh' Bacon suggested, I asked an additional question related to this one that resulted in a solution better suited to my needs. It can be found here.
Since you don't seem to have a problem using helper columns, this can be done in a fairly straightforward way, given that your data is already sorted by date.
RAW DATA TAB
Add a new column (we'll call it column X) which checks to see if your cell is the first cell which starts a string of 5 date stamps, all of which being, as you say, 2 minutes apart [starting in X2, ending at an assumed X100 assuming the datestamp is column A, and the reference code in decimal is column B]:
=COUNTIFS(A2:A$100,">=" & A2 - TIMEVALUE("00:02:00"),B2:B$100,B2)
This counts how many cells below the current cell are no more than 2 minutes later, including itself, and also have the same code in column B. We will use this to check whether that cell starts a new string of 5 + identical, near-in-time, codes.
In Column Y, starting at Y2, put:
=IF(AND(OR(B2<>B1,A2 - TIMEVALUE("00:02:00")>A1),X2 >= 5), TRUE)
This will first check if either (1) the code in the current cell doesn't match the code in the previous cell; OR (2) the time of the current row is at least 2 minutes later than the last line (either way, this is a new cycle). Then we check for the AND condition of whether the current row in column X shows a match of at least 5 cells below with the same code in the same time cycle. If TRUE, then it will return TRUE. Otherwise, it will return FALSE.
Then the code in column Z returns the number of the nth "hit code" we're on for that row. ie: whether this is the 1st, 2nd, nth time that a string of 5 codes has been hit [starting in Z2; hardcode Z1 as "0", or do some other special case so the first one won't add the title of the cell above, resulting in a #VALUE! error]:
=IF(Y2,Z1+1,Z1)
This will turn Z into an ascending list of positions, repeating values whenever a NEW code has failed to be created. Now we need to grab the description of the code that this row represents.
Assume you have an ordered list of all your codes, where column 1 would be equivilent to "1000000...", column 2 would be equivilent to "01000000.." etc. Name that single-row column (or, single column row) as a Range, which I will call Code_Index.
In column AA, starting at AA2, put the following:
=INDEX(Code_Index,SEARCH("1",C2))
This checks at which character "1" appears in column C at that row, and that becomes the position we want to pull the description from (which we have placed in the named range Code_Index).
Finally, we need to add a row which checks to see when a specific block of 5+ codes ends. Say, AB:AB (I forgot about this initially, hence its a little out of order initially). In AB2 and copied down, you will check to see whether there are at least 5 rows in a row of the same thing, within the 2 minute block, and also whether the next row is the same thing, within a new 2 minute block.
=IF(AND(COUNTIFS(B$1:B2,B2,A$1:A2,">"A2 - TIMEVALUE("00:02:00")>=5,OR(B3<>B2, A3 + TIMEVALUE("00:02:00")>= A2)),MAX(Z$1:Z1),"")
RESULTS PAGE
Now assume that's all on Sheet1, and you want your 'clean' results on Sheet2.
In sheet 2, have column A be an index, which simply starts at 1 on A2 & adds 1 each row afterwards. Column B will be another 'helper' column, column C will pull the description, column D will pull the start time, and column E will pull the end time.
In column B, put the following formula, which will check which 'new' index we're on (from column Z on the last tab). Starting at B2,
=MATCH(A2,Sheet1!Z:Z,0)
This will find the first row from the raw data tab which matches the current index number on A1. Then simply use this in an index formula in each of the next 3 columns, to pull the description, start time, and end time.
In C2 (pulling the description from AA on the last tab):
=INDEX(Sheet1!AA:AA,B2)
In D2 (pulling the start time from A on the last tab)
=INDEX(Sheet1!A:A,B2)
In E2 (pulling the end time from A on the last tab, *based on the row number from the column AB index)
=INDEX(Sheet1!A:A,MATCH(A2,Sheet1!AB:AB,0))
Let me know if I've misconstrued how you want your "2 minute time blocks" set up; do some rigorous testing to make sure it acts the way you expect.

How do I look backwards for the most recent match of a text string in a column?

I have an Excel sheet with various data entries that are in date order going down the page, with the dates in column A. I need a formula that will take a text string from an adjacent cell, then look back up a neighbouring column for the most recent match then return the date from column A.
Currently I have this formula in cell H100: =LOOKUP(G100,E100:E$5,A100:A$5).
I want it to look for the text in G100 in column E, going backwards to find the most recent example and then return the corresponding date from column A but despite the LOOKUP command being in reverse it always returns the first example in date order, not the most recent.
I would really appreciate some help from an expert, which I am not!
I am not certain to understand the question, but try
=OFFSET($A$1, 1+MATCH(G100, E$5:E100, 0)0,1,1)
this should catch the first (higher in the sheet) instance of the lookup match.
I would bring it into an Access database where that kind of data manipulation is easy.
But then, I know how to use Access to do those kinds of things and I think it's much harder to do in Excel.