Multi Select List Boxes with Multiple Columns in Access 2013 - ms-access

I have a listbox set to Multiselect property of Simple.
The listbox is populated by using a table.
There are 4 columns in the listbox
1 3/23/2014 4/5/2014 2014
2 4/6/2014 4/19/2014 2014
3 4/20/2014 5/3/2014 2014
The columns are PayPeriod, StartDate, EndDate, FiscalYear
What I want to be able to do is highlight a chunk of dates and have the first selected StartDate and the last selected EndDate populate two hidden text boxes so I can use them for my queries/reports.
I've tried a couple different ways. Each time what happens is it only uses the last item I have selected in it's calculations.
Dim ItemIndex As Variant
For Each ItemIndex In Me.lstPayPeriods.ItemsSelected
If Me.lstPayPeriods.Selected(ItemIndex) And Me.lstPayPeriods.Selected(ItemIndex - 1) = False Then
Date1.SetFocus
Date1.Text = Me.lstPayPeriods.Column(2, Me.lstPayPeriods.ListIndex)
End If
Next
In this example I tried to have it go through each Item of the listbox. I wanted to check to see if the current row was selected and the row before it wasn't. That way I could determine it was the first item selected in the group of selected items. It would always only use the last item I had selected.
Dim CurrentRow As Integer
Dim FirstDate As Date
For CurrentRow = 0 To Me.lstPayPeriods.ListCount - 1
If Me.lstPayPeriods.Selected(CurrentRow) Then
Date2.SetFocus
Date2.Text = Me.lstPayPeriods.Column(3, Me.lstPayPeriods.ListIndex)
End If
Next CurrentRow
For CurrentRow = 0 To Me.lstPayPeriods.ListCount - 1
If Me.lstPayPeriods.Selected(CurrentRow) And Me.lstPayPeriods.Selected(CurrentRow - 1) = False Then
Date1.SetFocus
Date1.Text = Me.lstPayPeriods.Column(2, Me.lstPayPeriods.ListIndex)
End If
Next CurrentRow
I tried to do something similar with this code. Again, it only uses the last item I have selected.
I am running into a wall figuring out how to accomplish my goal.

I think the issue is in your approach. I'm personally not keen on the approach you're using to determine the earliest start and latest end, though the issue might just be your column numbers: the first column in a listbox is column 0, and the last column (of 4 columns) is column 3. Accordingly in your code above, you're setting Date2 = fiscal year, not enddate.
I would however recommend a different approach to determining (a) the earliest selected StartDate, and (b) the latest selected enddate. You could have a loop for each operation, or your can encapsulate both in a function:
private function GetPayPeriodDate(baseValue as Date, findLater as boolean, colNo as long) as Date
'baseValue is the default date to test against
'findLater tells the function whether to look for < or > the baseValue
'colNo tells the function which column of data to test
Dim vv as variant
For each vv in lstPayPeriods.ItemsSelected
if lstPayPeriods.Selected(vv) then
if findLater then
if lstPayPeriods.Column(colNo, vv) > baseValue then
baseValue = lstPayPeriods.Column(colNo, vv)
end if
else
if lstPayPeriods.Column(colNo, vv) < baseValue then
baseValue = lstPayPeriods.Column(colNo, vv)
end if
end if
end if
next vv
GetPayPeriodDate = baseValue
end function
Then you can set your start and end date textboxes by calling this function:
me.StartDate = GetPayPeriodDate(CDate("31/12/2099"), false, 1)
'since startdate looks for the earliest date, the base date must be in the future
me.EndDate = GetPayPeriodDate(CDate("01/01/1900"), true, 2)
'similarly, looking for the latest date, base date must be in the past

Related

MS Access: Calculate First Day of Next Quarter based on Date field

On a MS Access Table, I would like to have a column that has the first day of the following quarter based on a date in another column.
For example, I have a Start_Date column with a value of 2018-02-04, I would like the record on that column to show that the following quarter would start on 2018-04-01.
I have this working fine in Excel using the following formula:
=DATE(YEAR(M2),((INT((MONTH(M2)-1)/3)+1)*3)+1,1)
In Access, I added the column choosing Calculated Field > Date/Time, but could not figure out a way to get it to work like an Excel.
Has anyone tried this before or know of a possible solution? Thanks
You can use this function:
Public Function DateNextQuarterFirst( _
Optional ByVal datDateThisQuarter As Date) As Date
Const cintQuarterMonthCount As Integer = 3
Dim intThisMonth As Integer
If datDateThisQuarter = 0 Then
datDateThisQuarter = Date
End If
intThisMonth = DatePart("q", datDateThisQuarter) * cintQuarterMonthCount
DateNextQuarterFirst = DateSerial(Year(datDateThisQuarter), intThisMonth + 1, 1)
End Function
To use it in a query with SQL similar to this:
Select *, DateNextQuarterFirst([Start_Date]) As NextQuarterFirst
From YourTable

excel vba - add table column with date based on adjacent cell that includes date and time

I have an excel table ("Table1") with 4 total columns. The 3rd and 4th column contain 'clock in' and 'clock out' information formatted to show date and time. For example :
6/3/2016 10:54:52 AM
I would like to do two things here...first, I want to create a new, 3rd column that just reads the date, formatted "d-mmm". This should match the date found in what would now be column 4.
The second thing I would like to do is take the date portion of text out of what would now be columns 4 and 5. So at the end, an example row of data might read as follows (columns 3:5):
C, D, E
7-Jun, 10:54:52 AM, 4:59:44 AM
Here is what I have so far for code:
Sub test()
Dim currentSht As Worksheet
Dim lst As ListObject
Set curretnSht = ActiveWorkbook.Sheets(1)
Set lst = currentSht.ListObjects("Table1")
lst.ListColumns.Add Position:=3
'Not really sure how to do the rest
End Sub
That's not the Excel way. Dates are numbers 0 represents 1/1/1900. Add 1 to it and you get the next day the value of an hour is 1/24 .
The biggest problem of your approach is Excel you stop editing the cell Excel evaluate the cells value. It'll still look like 7 - Jun but Excel changes the cells format and the cells value to be 7 - Jun of this your 6/7/216. It's best to have all the cells equal the same date. Just change the cells formatting to display the results that you want. If you need to calculate the Month use the a WorkSheet Function to do so. =Month(A1)
Try this:
Sub Demo()
Range("C1").EntireColumn.Insert '-->insert column
Range("D:D").Copy Destination:=Range("C1") '-->copy column 4 to column 3
Range("C:C").NumberFormat = "d-mmm" '-->format column 3
Range("D:E").NumberFormat = "h:mm:ss AM/PM" '-->format column 4 and 5
End Sub
Even this will work:
Sub Demo()
Dim currentSht As Worksheet
Dim lastRow As Long
Set currentSht = ActiveWorkbook.Sheets("Sheet1")
lastRow = currentSht.Cells(Rows.Count, "C").End(xlUp).Row '-->get last row with data
currentSht.Range("C1").EntireColumn.Insert '-->insert column
currentSht.Range("C1:C" & lastRow) = currentSht.Range("D1:D" & lastRow).Value '-->copy column 4 to column 3
currentSht.Range("C1:C" & lastRow).NumberFormat = "d-mmm" '-->format column 3
currentSht.Range("D1:E" & lastRow).NumberFormat = "h:mm:ss AM/PM" '-->format column 4 and 5
End Sub
This meets your specs:
Sub InsertColumnAndFormatDates()
Columns("C:C").Copy
Selection.Insert Shift:=xlToRight
Application.CutCopyMode = False
Columns("C").NumberFormat = "d-mmm"
Columns("D:E").NumberFormat = "h:mm:ss AM/PM"
End Sub

Access Query. If records Due Date = Last Week Insert Yes in Cell

Good morning All,
I am working on the following however, I can't figure it out for the life of me. I have table that contains a bunch of due dates. What I am trying to do is add a query that adds another field and inserts a yes if the date equals a day in last week. Honestly I need it to insert yes as long as it does not = this week.
I've tried using:
Urgent: IIf([Due Date]=[Due Date]
Between
DateAdd("d",1-Weekday(Date()) 7, Date()) And
DateAdd("d",1-Weekday(Date())-1, Date()),"Yes","")
with no luck. What am I missing here?!
Thanks all. Cheers.
Here's how to return Urgent if 'not this week' means previous Saturday and before. Not sure how you would do it without code.
Helper Function to get the first day of this week based on current date. Paste it into a new or existing global module.
Function FirstDateOfTheWeek() As Date
Dim dt As Date
If Weekday(Date) = vbSaturday Then
FirstDateOfTheWeek = DateAdd("y", -6, Date) 'today is Saturday? then return previous Sunday
ElseIf Weekday(Date) = vbSunday Then
FirstDateOfTheWeek = Date 'today is Sunday? then return Sunday because its the first day of the week
Else 'weekday, so just go backwards until we hit previous sunday's date
dt = Date
While Weekday(dt) <> vbSunday
dt = DateAdd("y", -1, dt)
Wend
FirstDateOfTheWeek = dt
End If
End Function
An IsUrgent function to be called from query. Paste it into a new or existing global module.
Function IsUrgent(dt As Variant) As String
If IsNull(dt) Then 'if null date is passed then return blank string; Variant chosen instead of date for this case; change it to N/A if you want?
IsUrgent = ""
Exit Function
End If
If dt < FirstDateOfTheWeek Then
IsUrgent = "Yes"
Else
IsUrgent = ""
End If
End Function
The Query Column calling IsUrgent() function:
IsUrgent: IsUrgent([Due Date])

How to display the maximum value from one column in a listbox, in a textbox on the same form

How can I select the maximum value from a column in a listbox, and display that value in a textbox on the same form? The listbox itself is populated by a query that depends on user inputs, so its values are unknown in advance.
I could sort the listbox by value and select the first value, but it is already sorted by date on another column, for a different purpose. What I want to know is the Date on which that maximimum value occurred in column 2.
The next step is to display or all the values in column 4 which occure before that date as blank or N/A.
You may find the following VBA code helpful. It scans values inside the .Column data for a list box named List0, for example...
2013-04-18 | 123
2013-04-17 | 77
2013-04-16 | 345
2013-04-15 | 34
...finds the date (first column) corresponding to the maximum value in the second column of the list box, and puts that date into a text box named Text3. Note that the CompareNumeric flag controls whether the comparison is string-based ("77" would win), or number-based (345 would win).
Private Sub Command2_Click()
Const DateCol = 0 '' column numbers start with 0
Const MaxCol = 1 '' second column has column index of 1
Const CompareNumeric = True '' convert strings to numbers for finding maximum
Dim RowIdx As Long, MaxItem As Variant, MaxIdx As Long, CurrItem As Variant, NewMaxFound As Boolean
MaxIdx = -1
MaxItem = Null
For RowIdx = 0 To Me.List0.ListCount - 1
CurrItem = Me.List0.Column(MaxCol, RowIdx)
If CompareNumeric Then
CurrItem = Val(CurrItem)
End If
If IsNull(MaxItem) Then
NewMaxFound = True '' first one
Else
NewMaxFound = (CurrItem > MaxItem)
End If
If NewMaxFound Then
MaxItem = CurrItem
MaxIdx = RowIdx
End If
Next
If MaxIdx >= 0 Then
Me.Text3.Value = Me.List0.Column(DateCol, MaxIdx)
End If
End Sub

Check Microsoft Access Form Values before Save

I have an Access Form - lets call it "Add Labor" (Access 2007) that saves data into a table.
The table has two columns in particular called "Start Date" and "End Date" (This table stores tasks)
There is also another table called FiscalYears which includes Start and End Dates for Fiscal Years, which is structured as follows
FyID
FYear
StartDate
EndDate
Example Data:
FYId FYear StartDate EndDate
-----------------------------
1 2010 10/1/2009 9/30/2010
2 2011 10/1/2010 9/30/2011
So in My Add Labor Form if someone enters labor that span across two fiscal years I need to enter two labor entries. Here is an example
If a user selects Labor Start Date = 6/30/2009
And End Date 10/2/2010 , it spans two fiscal years
So in my Labor Table I should enter two things
LaborID StartDate EndDate
-----------------------------
1 6/30/2009 9/30/2010
2 10/1/2010 10/2/2010
Basically I need to do a check before I save the record and add two records if they span Fiscal years, right now I'm just blindly doing Save Record on the form (inbuilt), but I guess I need to add some VBA. I've hardly ever used Access so this may be simple(hopefully). I am thinking instead of the event which just calls Save Record, I need it to add custom VBA.
Say you have an unbound form for adding the dates, you can say:
Dim rsFY As DAO.Recordset
Dim rsAL As DAO.Recordset
Dim db As Database
Dim sSQL As String
Set db = CurrentDb
''Select all years from the fiscal years table
sSQL = "SELECT FYear, StartDate, EndDate " _
& "FROM FiscalYears WHERE StartDate>=#" & Format(Me.StartDate, "yyyy/mm/dd") _
& "# Or EndDate <=#" & Format(Me.Enddate, "yyyy/mm/dd") _
& "# ORDER BY FYear"
Set rsFY = db.OpenRecordset(sSQL)
Set rsAL = db.OpenRecordset("AddLabor") ''table
''Populate recordset
rsFY.MoveLast
rsFY.MoveFirst
Do While Not rsFY.EOF
''Add records for each year selected
rsAL.AddNew
If rsFY.AbsolutePosition = 0 Then
rsAL!StartDate = Format(Me.StartDate, "yyyy/mm/dd")
Else
rsAL!StartDate = rsFY!StartDate
End If
If rsFY.AbsolutePosition + 1 = rsFY.RecordCount Then
rsAL!Enddate = Format(Me.Enddate, "yyyy/mm/dd")
Else
rsAL!Enddate = rsFY!Enddate
End If
rsAL.Update
rsFY.MoveNext
Loop
If the code was running in a main form with a subform showing the Addlabor table, you could update the subform to show the new records like so:
Me.Addlabor_subform.Requery
Why do you need a FiscalYears table? If your organization's fiscal years always start on Oct. 1 and end on Sept. 30, you can use a function to determine the fiscal year for a given date.
Public Function Fy(ByVal pDate As Date) As Integer
Dim intYear As Integer
Dim intReturn As Integer
intYear = Year(pDate)
If pDate > DateSerial(intYear, 9, 30) Then
intReturn = intYear + 1
Else
intReturn = intYear
End If
Fy = intReturn
End Function
And simple functions to return the Start and End dates for a given year.
Public Function FyStart(ByVal pYear As Integer) As Date
FyStart = DateSerial(pYear - 1, 10, 1)
End Function
Public Function FyEnd(ByVal pYear As Integer) As Date
FyEnd = DateSerial(pYear, 9, 30)
End Function
You can then determine how many fiscal years are included in a given date range by:
Fy(EndDate) - Fy(StartDate)
But I may be totally off base because you said "Start Date = 6/30/2009 And End Date 10/2/2010" spans two years. However, this expression returns 2 (3 years):
Fy(#10/2/2010#) - Fy(#6/30/2009#)