I have three sets of data and each has two columns.
The first column is Date and second column is Price. The dates are formatted different with each data set eg. Gold's date(1951), Money Supply M2's date (1951-01), and Money Sup. M3 Date (9/01/1951)
What i need:
I want to chart these with dates on x-axis and price on y-axis
Questions:
do i need to make Gold's Date(YYYY) and Money Supply M2's Date(YYYY-MM) a date object?
if so how?
do i need to place all dates in one column and create a sub to help sort the Price with appropriate Date?
Does this make sense?
I have very little experience programming in VBA and was having a hard time finding info on using dates. I came across an Answer, given by the person who edited this (brettdj), that listed a few extremely helpful sights on VBA programming for excel. One of those had info on the DateSerial() function. I was then able to throw together some code to quickly fix my problem.
Sub CreateDates()
Dim dt As Date
Dim s As String
For Each c In Worksheets("Sheet1").Range("A7:A27080").Cells
s = Len(c.Value)
If s = 4 Then '(YYYY)
dt = DateSerial(s, 7, 1)
c.Value = dt
End If
If s = 7 Then '(YYYY-MM)
y = Left(s, 4)
m = Right(s, 2)
dt = DateSerial(y, m, 1)
c.Value = dt
End If
Next c
End Sub
I could probably spend some time and add some regular expressions and make a one-size fits most, but this will work as i want have to use it very often.
Related
I have a question regarding the Calculation of something:
I used to use this function below to calculate the available hours of working colleagues like this:
Function BerekenUrenPercentage(OptelGebied As Range, TriggerWoord As String, PercentageGebied As Range) As Double
Dim Cel As Range, Uren As Double, Waarde As String, Teller As Double, Factor As Integer
For Each Cel In OptelGebied.Cells
Teller = Teller + 1
If InStr(Cel.Formula, TriggerWoord) > 0 Then
Waarde = Cel.Formula
Waarde = Replace(Waarde, TriggerWoord, "")
Factor = PercentageGebied.Formula(Teller, 1)
Uren = Uren + ((Int(Waarde) * Factor) / 100)
End If
Next Cel
BerekenUrenPercentage = Uren
End Function
But I need some more flexibility and efficiency in my calculations so I reworked the whole thing, but can't figure out the formula I need to use.
It searches in a whole week of attendance (7 columns) for the desired Code (see below), if found it subtracts that code from the cell and only the hours remain.
It duplicates that with the percentage of Employability (searches in the correct week and person (on Pers ID)) and searches on.
I Would also like (later on) to enter multiple codes in 1 cell like: DAV4/VK4 or DAV4/DEV4 in the future and still find the two correct codes
We have an attendance schedule on my work:
Attendance Table where we note if someone is working, in which discipline and for how long.
Like: DAA8 -> DAA is a code and 8 is 8 hours
Examples of codes: DVP8, DVA,DVV,DPP,DPA,DPV,DAP,DAA,DAV,DEV,DLOG, VK8,ZK8,BK8,BL6 etc
VK = Vacation, ZK = Sick
There is also an Table for Employability in Percentage Where all the workers are displayed with the percentage of employability. We use this to calculate how many hours a person is helping towards our goal.
And the calculation of Hours available table: Here is where I will use the function I am searching for.
Can anyone help me?
Example: In the first cell of the attendance table is one of the cells i want to count.
I want the lookup function
cell (in the picture has the value 120) in the row with the code DVP
(left of that cell) to search for the code, Distill the numeric value
multiply that by the corresponding week in the Employability table.
And do that for every occurence of the code in the week the cell
stands (top of the tables).
I'm trying to create a Macro that will, among other things, set the .CurrentPage to a specific value. My question is can you use an index value instead of the name of one of the values?
ActiveSheet.PivotTables("PivotTable1").PivotFields("starttime").CurrentPage = "11/19/2018"
Here is an example line that I'm using. The problem is the dates will change every week to represent the new data. However there will always be five options, Monday to Friday. So instead of having to use the date, which I'll have to change every week, can I use an index value instead?
I.e. [0] for Monday and [4] for Friday etc. If this is possible then what is the correct syntax for this? I've looked all over the web and found nothing even remotely related to using index numbers instead of values.
If you know that your field will only contain the relevant items and nothing else, then:
With ActiveSheet.PivotTables("PivotTable1").PivotFields("starttime")
.CurrentPage = .PivotItems(3).Value
End With
However pivot tables may retain items deleted from the data source. If that is how it is set up for you, then you will either need to remove cached items before using this code, or calculate that page value instead of looking it up in the list of available values, which should be not difficult given that it is based on the current week.
Something like this
Public arrDate(4) As Date
Sub CreateDateArray()
Dim i As Integer
For i = 0 To 4
arrDate(i) = DateAdd("d", -Weekday(Date, vbMonday) + (i + 1), Date)
Next i
End Sub
or something like this
Function DateFromIndex(intDay As Integer) As Date
DateFromIndex = DateAdd("d", -Weekday(Date, vbMonday) + (intDay+1), Date)
End Function
I'm working on Social Survey project.Due to discrepancies in data I'm stuck at a certain place. The survey conducting volunteers were given tablets with unique IDs. On different dates, the tablets were used in different cities
Sheet 1 one contains a list of around thousands of responses for which city names are missing and Sheet 2 contains a list of tablets in use in different cities on different dates.
Sheet 1
City DeviceID StartDate EndDate
Delhi 25 21-08-2014 26-08-2014
Mumbai 39 14-05-2014 21-05-2014
Chennai 91 17-11-2014 21-11-2014
Bangalore 91 11-10-2014 21-10-2014
Delhi 91 26-05-2015 29-05-2015
Hyderabad 25 23-05-2015 28-05-2015
Sheet 2
S.Id DeviceId SurveyDate City
203 91 15-10-2014 ?
204 25 24-08-2014 ?
I need to somehow fill up the values for the city column in Sheet 2.
I tried using Vlookup but being a beginner to excel, was unable to get things working. I managed to format the string in date columns as date.
But am unsure about how to pursue this further.
From my understanding, Vlookup requires that the date ranges to be continuous, with no missing values in between. It is not so in this case. This is real world data and hence imperfect.
What would be the right approach to this problem ? Can this be done with excel macros ?
I also read up a bit about nested if statements but am confused being a beginner to excel formulas and data manipulation.
There is two ways to do what you want.
The first one is using vba and create a macro to do the job BUT you will have to iterate through all your data multiple time (n1*n2 loops in the worst case scenario where n1 and n2 is the number of rows in it's table respectively) which is really slow if you have a lot of data.
The other way is a little more complicated and includes array formulas but is really faster than vba because it uses the build in functions of excel (which are optimized already).
So I will use a much simpler example and you can use that as you wish on your data.
I have the following tables:
Table1
city ID start end
A 1 3 5
B 3 4 6
C 3 5 8
Table 2
ID point city
3 5 ?
So we want a formula that completes the second table. where ID match exactly and point is between start-end. We are going to use MATCH and INDEX to get it.
Here it is:
=INDEX(A$2:A$4;MATCH(1;(B$2:B$4=G2)*(C$2:C$4<=H2)*(D$2:D$4>=H2);0))
First of all to run this after you write it you should not press enter but instead ctrl+shift+enter to tell excel to run it as an array formula otherwise it will not run at all.
Now we got that out of the way let me explain what is going on here:
The MATCH does the following:
match the value 1 (TRUE) in the range I created and that should be an exact match. But how the range is created? Lets take that part for example:
This B$2:B$4=G2 -gives-> {1;3;3}=3 --> {FALSE;TRUE;TRUE}
Similarly the second thing in the MATCH gives: {TRUE;TRUE;FALSE}
So now we have (keep in mind that the * is similar to logical AND):
{FALSE;TRUE;TRUE}*{TRUE;TRUE;FALSE} --> {FALSE;TRUE;FALSE}
and this combined with the third gives {FALSE;TRUE;FALSE}
So now we have MATCH(1;{FALSE;TRUE;FALSE};0) --> 2 because in the range only the second row matches the 1 (first row that it matches).
So now we just use index to get from another range whatever is on row 2.
You can use the above on your own data to get the expected results.
Good luck!
If the deviceId values should match and the survey date should be between the start date and end date, VLookup won't suffice. The following pointers, however, should get you started:
1) Define the date ranges from which the date comparisons should be made.
2) Use an overlap date checking function to determine if the date in question overlaps the start and end dates.
3) Loop through the date ranges and insert in Sheet2 when a match is found, i.e. when the deviceId values match and the date overlaps.
The following function takes as parameters the date to be checked, the start and end date and returns True, if dateVal overlaps the start and end date:
Function dateOverlap(dateVal As String, startDate As String, endDate As String) As Boolean
If DateDiff("d", startDate, dateVal) >= 0 And DateDiff("d", endDate, dateVal) <= 0 Then _
dateOverlap = True
End Function
Example usage
Debug.Print dateOverlap("05-10-2016", "01-10-2016", "10-10-2016") (returns true).
Here we use MEDIAN() as an easy way to test for "in-between".
Sub FillInTheBlanks()
Dim s1 As Worksheet, s2 As Worksheet
Dim N1 As Long, N2 As Long, i As Long, j As Long
Dim rc As Long, DeId As Long, sDate As Date
Dim wf As WorksheetFunction
Set s1 = Sheets("Sheet1")
Set s2 = Sheets("Sheet2")
Set wf = Application.WorksheetFunction
rc = Rows.Count
N1 = s1.Cells(rc, "A").End(xlUp).Row
N2 = s2.Cells(rc, "A").End(xlUp).Row
For i = 2 To N2
DeId = s2.Cells(i, "B").Value
sDate = s2.Cells(i, "C").Value
For j = 2 To N1
If DeId = s1.Cells(j, 2).Value Then
If sDate = wf.Median(sDate, s1.Cells(j, "C").Value, s1.Cells(j, "D").Value) Then
s2.Cells(i, "D").Value = s1.Cells(j, "A").Value
End If
End If
Next j
Next i
End Sub
Sheet2:
starting from Sheet1:
I have a VBA script at the moment that reads in 6 values as integers. 3 values for date, month, and year and 3 of the same type from a different location. I'd like to take the values and check if there has been more than a year to pass between them. DateDiff seems like the easiest way to handle this, however that function reads in the values as one DateValue (ie March 20, 2015) and my values are returned individually (08,08,2015).
I wrote a function that stores each value into a var and then using those individually I concat them into a format that DateValue can use.
This works, however I am curious if there is another(better) way to handle this problem?
Thanks in advance.
The function DateSerial(2015,3,4) will return the date for 3/4/2015, and with both of your dates in that format, you can subtract the one date from the other, and if the (absolute value of the) difference is > 365 then you know that they are over a year apart.
Dim A As Date
A = DateSerial(2015, 3, 4)
Dim B As Date
B = DateSerial(2014, 3, 2)
Dim C As Integer
C = Abs(A - B)
MsgBox C & " days between"
I'm a bit new to trying to program and originally was just trying to improve a spreadsheet but it's gone beyond using a basic function in excel. I have a table that I am having a function look at to find a building number in the first column and then look at start and finish dates in two other respective columns to find out if it should populate specific blocks on a calendar worksheet. The problem occurs because the same building number may appear multiple times with different dates and I need to to find an entry that matches the correct dates.
I was able to create a working though complicated formula to find the first instance and learned I can add a nested if of that formula again in the false statement with a slight change. I can continue doing that but it becomes very large and cumbersome. I'm trying to find a way to make a function for the formula with a variable in it that would look at how many times the it has already been used so it keeps searching down the table for an answer that fits the parameters.
This is currently my formula:
=IFERROR(IF(AND(DATE('IF SHEET (2)'!$F$7,MATCH('IF SHEET (2)'!$C$2,'IF SHEET (2)'!$C$2:'IF SHEET (2)'!$N$2,0),'IF SHEET (2)'!C$4)>=VLOOKUP("2D11"&1,A2:F6,4,0),DATE('IF SHEET (2)'!$F$7,MATCH('IF SHEET (2)'!$C$2,'IF SHEET (2)'!$C$2:'IF SHEET (2)'!$N$2,0),'IF SHEET (2)'!C$4)<=VLOOKUP("2D11"&1,A2:F6,4,0)),IF(VLOOKUP("2D11"&1,A2:F6,3,0)="2D11",VLOOKUP("2D11"&1,A2:F6,6,FALSE)),"NO ANSWER"),"ERROR")
Where you see 2D11&1 is where I need the variable for 1 so it would be "number of times it's been used in the function +1" then I could just loop it so it would keep checking till it ran out of 2D11's or found one that matched. I haven't posted before and I'm doing this through a lot of trial and error so if you need more info please post and say so and I'll try to provide it.
So rather than have someone try to make sense of the rediculous formula I posted I though I would try to make it simpler by just stating what I need to accomplish and trying to see how to turn that into a VBA function. So I'm kinda looking at a few steps:
Matches first instance of building name in column A with
building name for the row of the output cell.
Is date connected with the output cell >= start date of first entry(which is user entered in column D).
Is date connected with the output cell <= end date of first entry(which is user entered in column E).
Enters Unit name(located in column F) for first instance of the building if Parts 1, 2, and 3 are all True.
If parts 1, 2, or 3 are False then loops to look at next instance of the building name down column 1.
Hopefully this makes things clearer than the formula so I'm able to get help as I'm still pretty stuck due to low knowledge of VBA.
Here is a simple solution...
Building_name = ???
Date = ???
Last_Row = Range("A65536").End(xlUp).Row
For i = 1 To Last_Row
if cells(i,1).value = Building_Name Then
if date >= cells(i,4).value Then
if date <= cells(i,5).value Then
first instance = cells(i,6).value
end if
end if
end if
next
you should add a test at the end to avoid the case where there is no first instance in the table
If I understand correctly, you have a Table T1 made of 3 columns: T1.building, T1.start date, T1.end date.
Then you have 3 parameters: P1=building, P2=start date, P3=end date.
You need to find the first entry in table T1 that "fits" within the input parameters dates, that is:
P1=T1.building
P2<=T1.start date
P3>=T1.end date
If so, you can define a custom function like this
Public Function MyLookup(Key As Variant, DateMin As Variant, DateMax As Variant, LookUpTable As Range, ResultColumn As Integer) As Range
Dim iIndx As Integer
Dim KeyValue As Variant
Dim Found As Boolean
On Error GoTo ErrHandler
Found = False
iIndx = 1
Do While (Not Found) And (iIndx <= LookUpTable.Rows.Count)
KeyValue = LookUpTable.Cells(iIndx, 1)
If (KeyValue = Key) And _
(DateMin <= LookUpTable.Cells(iIndx, 2)) And _
(DateMax >= LookUpTable.Cells(iIndx, 3)) Then
Set MyLookup = LookUpTable.Cells(iIndx, ResultColumn)
Found = True
End If
iIndx = iIndx + 1
Loop
Exit Function
ErrHandler:
MsgBox "Error in MyLookup: " & Err.Description
End Function
That may not be the most performant piece of code in the world, but I think it's explanatory.
You can download this working example