Hello I'm trying to figure out the time difference between data in Column K and J. I need to know how long it took for data to be updated by the amount of days it took, hours, or minutes and am using those columns. I also want to get the average amount of time only if the names in Column A match and enter that information in Column N. This is what I have so far for the first part.
ActiveSheet.Name = "Raw Data"
Range("M2:M").Value = ("K2:K-J2:J" > 1) + ("d:hh:mm")
Thanks for the help.
This should get the results you want. The With ... End With block is used to save having to write Worksheets("Raw Data") all the time. Anything within the block which starts with a . refers to Worksheets("Raw Data")
The formula was adapted from this answer but modified to allow for more than 31 days. We then use the FillDown method to copy the formula in cell M2 down to the same row as the last used cell in column K. The references in the formula adjust automatically to point to the correct row
edit: updated to calculate average elapsed time for each name listed in column A. This is more complicated because we can't directly average the values we put in column M because we have converted them into a text format. I've chosen to use column Z to hold the numeric time values which we need. You could choose any other unused column and you could hide the column so it doesn't display.
The last used row is stored in a variable because we need to use it in a couple of different places. The numeric difference between columns K and J is stored in column Z. The text value in column M is then calculated from the value in column Z.
Finally, the average in column N is calculated using the AVERAGEIF function. This looks through all the used rows in column A, finds those with the same name as the current row and then averages all the values from column Z for any matching rows.
One important point to note: all of the formulas in column N will need to be rewritten if any rows are added or deleted. This is because the last row value stored in those formulas will become incorrect if rows are added or deleted
With Worksheets("Raw Data")
Dim lngLastUsedRow As Long
lngLastUsedRow = .Cells(.Rows.Count, "K").End(xlUp).Row
.Range("Z2").Formula = "=K2-J2"
.Range("Z2:Z" & lngLastUsedRow).FillDown
.Range("M2").Formula = "=FLOOR(Z2,1)&"":""&TEXT(Z2,""hh:mm"")"
.Range("M2:M" & lngLastUsedRow).FillDown
.Range("N2").Formula = "=AVERAGEIF(A$2:A$" & lngLastUsedRow & ",A2,Z$2:Z$" & lngLastUsedRow &")"
.Range("N2:N" & lngLastUsedRow).FillDown
End With
Related
I've been trying soo hard much to clean up this csv data for a coworker.
I’m going to walk through what the data usually looks like and then walk through the steps I’ve done and then bring up what I’m currently struggling with… Bear with me as this is my first post (and I have no background in vba and everything is self-taught by Google).
So the data export is a csv which can be opened in excel broken out by several columns. The column in question is column G, which essentially has multiple data sets (1 – 219) for the same menu item (row).
For example:
A B C D E F G
Chicken Soup {1;$6.00;59;$9.00;88;$6.00}
Beef Soup {1;$8.00;59;$12.00;88;$8.00}
Duck Soup {1;$6.00;59;$6.00;88;$6.00}
Egg Soup {1;$8.00;59;$9.00;88;$8.00}
Water {1;$0.00}
French Onion Soup {1;$16.00;59;$15.00;88;$12.00}
Chili Soup {1;$17.00;84;$17.00}
So in column G, you can tell, there is multiple prices the format is:
{Column Number ; $ Price ; Column number $ Price etc & }
Regex: .[0-9]{1,2},[$][0-9]{1,3}[.][0-9][0-9].|[0-9]{1,2},[$][0-9]{1,3}[.][0-9][0-9]
The first goal was to parse out the data in the column into the row, in a format that is true to the csv (so it can be combined and resubmitted).
For example: (imagine there is a semi colon between each data set, as there should be in the final result)
{1;$21.00}
{1;$16.00}
{1;$12.00 5;$12.00 8;$12.00}
{1;$18.00 6;$18.00 8;$18.00}
{1;$10.00 6;$7.00 9;$12.00 11;$10.00}
{1;$20.00 6;$20.00 8;$20.00}
{1;$5.49 3;$3.99 10;$4.99 12;$4.99}
{1;$18.99}
{1;$21.00}
{1;$21.00}
To accomplish this goal, I wrote a macro that:
Copies column G from “Sheet1” and inputs to new sheet “Sheet2” in A1
Replace all “;$” with “,$” to help separate each data set by itself instead of having it broken out column name then dollar sign in two different columns
Text to columns macro splitting on “;” (and inputs results starting B1 so I can keep A1 with all the data sets in one column in case I need it) – also if you know how to keep the semi colon here, that would be helpful so I don’t have to re-add it in the future
Replace All from b1 to end of data set "," to ";" <-- to bring it back to original formatting
Copies the Data from B1 to last cell with data (data is not in order, the 50th row could have 219 columns and then the last row could only have 150) and pastes this data into column G of “rp items” (therefore overriding the existing data and shifting the columns as far right as the last column used.
However, when I showed my coworker what I’ve done, he wanted the leading number (column number) to correspond to the Columns (since data starts in column G, this will be column 1, H will be 2 etc). Therefore looking something like this so he can filter the column by the all the items that have that column number:
For example, this photo is how the outcome should look
So, now the goal is to create a macro that…
Loops through B1:B in sheet “STEP ONE” (column B starting at B1 then C1 then when blank in that row go to next row)
While (B1 (or next row) is blank, do nothing, end macro)
If B1 (or active cell) is not blank, read the cell value to extract column; copy the cell’s contents, paste in “STEP TWO” sheet in the same row as the active cell, but offset by the column number from cell value.
Toggle back to main sheet, goes to next cell within that row – if blank, go to next row and repeat until all data is done.
To give you some background, I have more than 25,000 lines of data (menu items) and the longest column (I believe is 219). So far, I’ve mostly been trying pieces of scripts I’ve found online but none of them are doing similar to what I need and I don’t know how to write enough code to just write the script out myself. I believe I’ll need to have to establish a variable: the column name (not sure if I can extract this using the regex code I found out) and then use that in the offset...
But my range needs to be dynamic and loop…
Please let me know if you can assist – I’ve been stuck on this for like a week!
Thank you all so much for reading – if I can provide extra detail please let me know.
For example you could do it this way:
Sub Tester()
Dim arr, i As Long, c As Range, v, col, price
For Each c In Range("G2:G4").Cells
v = Replace(Replace(c.Value, "{", ""), "}", "") 'remove braces
If Len(c.Value) > 0 Then 'anything to process?
arr = Split(v, ";") 'split on ;
For i = 0 To UBound(arr) - 1 Step 2 'loop 2 at a time
col = CLng(Trim(arr(i))) 'column number
price = Trim(arr(i + 1)) 'price
c.Offset(0, col).Value = col & ";" & price
Next i
End If
Next c
End Sub
I've got a few large (500-1000) datasets in the following format using only the first two rows.
id
value
a-b
number
a-c
number
a-d
number
...
number
b-c
number
b-d
number
and so on
They compare two values and save their difference while skipping previously done comparisons. I want to put them in a table like this:
id
a
b
c
d
e
a
/
number
number
number
number
b
number
/
number
number
number
c
number
number
/
number
number
d
number
number
number
/
number
e
number
number
number
number
/
The lower left half of this table is easily prepared with offset, but how do I feed the values into the upper right half?
Is there a way to mostly automate doing this?
If i understand what you are trying to do, I would suggest to do this in 2 steps:
Set up formulas in the results table to "read" data
Have a macro to "save" data
First fill your results table with this formula (example for cell B2) - keep your offset formula in bottm left half
=IF(B$2=$A3, "\", VLOOKUP(IF(B$2>$A3,$A3&"-"&B$2, B$2&"-"&$A3), $H$3:$I$35, 2, FALSE))
This will give you \ if the row and column id or the same or vlookup on row_id-column_id/column_id-row_id if they are different ensuring they are ordered "low-high" always to give you your mirror across the diagonal. Some might argue the duplication of vlookup is inefficient but more inefficient than an offset and figuring our how to paste one formula into one diagonal and a different one in the other? Who really knows and it is simple and it works IMHO
Next put the data for the current "pass" into the observations table and your values will appear in the table via the VLOOKUP
Finally you need a little macro to replace the formula with the value and run it after every set of results is acquired, so that you don't lose this data when you put a subsequent set of new values in your results table
Option Explicit
Sub replace_formula_with_value()
Dim ws As Worksheet
Set ws = ThisWorkbook.Sheets("Sheet1")
Dim r_in As Range
' this is where my input data start
Set r_in = Range(ws.Range("B3"), ws.Range("B3").End(xlDown).End(xlToRight))
Dim r As Range
For Each r In r_in
If Not IsError(r.Value) Then
If r.Value <> "\" Then
'overwrite formula with value by setting value to the evaluation of the formula in the cell
r.Value = r.Value
End If
End If
Next r
End Sub
If you dont want to have a macro then you need to keep ALL data in your observations table and just build it up over time.
I am relatively new to Excel VBA that's why I have some problems.
I have constructed a (Poisson-) matrix with range "EB5:EV25" where each cell contains a formula that basically (not only) multiplies two input values, e.g. they look like
=POISSON(0;$H$2;FALSE)*POISSON(0;$H$2;FALSE)
where "$H$2" and "$H$2" are my first two input values.
The results are presented in "EB33:ED33" where in each of the three cells the sum of a certain part of the matrix above is summed up.
Lets say the column with one of the input values is H and the column with the other input values is K (the values are in every 82th row). Thus for every 82th row of column H and K my matrix in "EB5:EV25" calculates results and presents them in "EB33:ED33". This solution so far only allows for presenting the results of one pair of input variables at a time - I need to change the row of input variables in my matrix manually.
However I don't finally want to present my results in "EB33:ED33" but in a different column, say "BA:BC", 2 rows after the row that contains the input values (separately for each row of input values).
I have already tried out some code but I am not even able to work with input variables that are in different columns, neither does my code change the input values - for each row of input values the results are always the same (i does not change).
Dim i As Integer
Dim rng As Range
Set rng = Range("EB5:EV25")
For i = 3 To Cells(Rows.Count, 8).End(xlUp).Row Step 82
rng.Replace "$" & i - 1, "$" & i
Application.Calculate
Range("EB33:ED33").Copy
Cells(i + 1, 63).PasteSpecial xlValues
Next i
Set rng = Nothing
End Sub
Would be great if anybody is able to help!
I have a list of names in Sheet1 which gets updated manually, and I'm trying to program a macro (I want to attach it to a button) that will count the rows with values - COUNTA() - and drop the value in a column (let's say A) with the date it was counted next to it (column B). Here are the problems I'm having:
1 - I can't use "Today()" because it changes every day. I could just type in the date, but it would be much easier if there was a way to do it automatically and have it lock at that date.
2 - I don't know how to tell the macro that every time it executes, it should put the info in the next row down, in order to create (and grow) a list.
Thanks!
To find the last row you can do this:
FinalRow = Cells(Rows.Count, 1).End(xlUp).Row
This will put the number of rows in column 1 (A) in the FinalRow variable.
To add the current date into a cell:
cells(1,1) = Date
You can use this e.g. to go through all lines:
For i=1 to FinalRow
cells(i,2) = Date
next i
Hope I could help.
It is a requirement that I use Excel to solve this issue.
In col A I have 0s and 1s with various quantities of 0s between the 1s. Every time a 1 appears I want the difference between two numbers given in two columns next to my binary column. However I wish to get the results from this calculation stated next to the previous 1.
I'd cope with different software, but how do I achieve this with Excel?
=IF(A4=1,OFFSET(B4,MATCH(1,A5:A$1000,0),0)-OFFSET(C4,MATCH(1,A5:A$1000,0),),"")
in D4 and copied down to suit seems to work.
Edit:
=(IF(A$=1, ,"") is as in: IF(logical_test,value_if_true,value_if_false) where value if false is (blank), expressed as "".
The value_if_true is the difference between ColumnB and ColumnC values, each ‘located’ from an OFFSET function as in =OFFSET(reference,rows,cols,height,width).
references are to the appropriate column for the row into which the formula is inserted (ie B4 and C4) from which the values required are ‘south’ by a variable amount.
MATCH, as in =MATCH(lookup_value, lookup_array, [match_type]) is to determine the extent of the offset on a case-by-case basis. In reverse order, the parameters here are match_type = 0 (to require an exact match) and lookup_array is as much of ColumnA as required. Initially chosen as up to Row1000 (by A$1000) but can be extended as far as necessary, subject to row limit for the relevant Excel version.
The first parameter lookup_value) is of course 1 since that is the flag for the rows that contain the values to be subtracted.
Without a $ between A and 5 in the MATCH functions the size of the array automatically decreases (top cell row reference increases) as the formula is copied down, hence finds the next instance (rather than the same one over and over again).
With VBA, I'd first set the formulas to show results in same line as the "ones". (Suppose I used the D column for that.)
= if(A1 = 1; B1 - C1; "")
Then, in VBA window, do the following:
Dim i as integer
Dim Filled as Collection
Set Filled = new Colleciton 'this collection will stored filled lines
'store filled lines
for i = 2 to 1000 'use your table limit
if Sheet1.Cells(i, 4).Value <> "" then 'the 4 is for D column, i for the line
Filled.Add i
end if
next
'now fill the E column with displaced values
for i = 1 to Filled.Count - 1
Sheet1.Cells(Filled(i), 5).Value = Sheet1.Cells(Filled(i+1), 5).Value
next
'please note there's a missing line (the last), it's up to you to decide how to fill it
'sorry I cannot debug this code
I'd associate that to some sheet event or to a button.