vb.net - How to get the day number from a weekday name - vb.net

Long story short:
I need the inverted function of WeekdayName(), in the following terms:
You provide a week day name (e.g. Sunday)
You get the correspondent week day number (that depends which is the first week day as returned in WeekdayName, e.g., you get 1 for Sunday if Sunday is the first day of the week)
Background:
I'm using date functions in vb.net. So far so good. I'm using the function WeekdayName() in order to set the titles for tab pages in a TabControl. My custom control (kind of calendar control) holds the mentioned TabControl and it has the option of choosing which day of the week you want to diplay.
If you want to display ALL days, the TabControl will have TabPages filled by iterating upon the WeekdayName() function mentioned above (localized and managed by the system calendar and capitalized by me).
If you set only Tuesday and Friday, you will have two tab pages with those titles and sorted as [Tuesday | Friday]. If you decide to add Wednesday, now you should have 3 tab pages: [Tuesday | Wednesday | Friday], and so on...
In order to keep tabs sorted, when I need to insert a tab to be shown I want to provide the tab's title to check against the new-to-insert weekday name and in that way have the order resolved.
I believe one workaround is to create a fake date object with the tab's title string in it in order to have a, for instance, "Sunday" date and then use: Weekday() but I was hoping an API solution.
NOTE: This is not: how to get the day number from a date.
EDIT:
As we disscused with #jmshapland, a custom code approach using the default localization and system settings could be:
Function WeekdayNumber(day as String)
' The following initialization does not necessary go in this function.
' The idea is to have a mapping between key day name and index in the
' same order as the WeekdayName() method with the default system settings
Dim weekdayNamesCollection as Collection = New Collection()
For i = 1 to WEEKDAYS
Dim wDay as String = WeekdayName(i)
' add the day with a key with the same name
weekdayNamesCollection.add(wDay, wDay)
Next i
If weekdayNamesCollection.ContainsKey(day) Then
Return weekdayNamesCollection.IndexOfKey(day) + 1
End If
' Raise an error as the string 'day' is not in the collection
End Sub
I didn't test this out as I am in a computer without any framework and/or IDE. But basically, the idea is to return the index where the weekday name is stored in the collection (previously, it was stored in the system settings order as WeekdayName().

I don't think there's a built-in function for it. But if you are using WeekdayName then you should use it for your purpose.
Public Function WeekDayNumber(ByVal weekName As String) As Integer
Dim weekNames As New Dictionary(Of String, Integer)
For i As Integer = 1 To 7
weekNames.Add(WeekdayName(i), i)
Next
Return weekNames(weekName)
End Function

Sorry if this is formatted poorly, I never work with VB usually just C#. However, this should do what you are looking for... If you want the first day of the week to return as 0 instead of 1 just remove the + 1 from the return statement.
Private Function FindDayOfWeek(day As String) As Integer
Dim daysOfWeek = CultureInfo.CurrentCulture.DateTimeFormat.DayNames
Dim counter As Integer = Array.IndexOf(daysOfWeek, WeekdayName(1))
Dim numericDay As Integer
For i As Integer = 0 To 6
If counter > 6 Then
counter = 0
End If
If daysOfWeek(counter) = day Then
numericDay = i
Exit For
End If
counter += 1
Next
Return numericDay + 1
End Function

By using val() function, will give Day of Week number from 0 to 6 :
intDayofWeek = val(System.DateTime.Now.DayOfWeek)

Related

Create Sequence Number by year and number that will increase +1

I would like to edit/modify my field based on year and then the sequence number.
Field: Year - 00#
For example, a file is created this year, 2020.
So, I would like a filed that is computed by number and will increase +1.
The filed will be : 2020-001 , then 2020 - 002 and so on.
Before, I got some code from somebody to generate a sequence number.
Sub Querysave(Source As Notesuidocument, Continue As Variant)
'get total no of documents from the view
'if no documents then seq start with 1
Dim docCount
Dim viewCollection As NotesViewEntryCollection
Dim viewEntry As NotesViewEntry
Dim vNum As Long
If source.IsNewDoc Then
Set viewCollection = view.AllEntries
docCount = viewCollection.count
If doccount = 0 Then
doccount=1
Call source.FieldSetText("ReqNo","REQ" & Cstr(Format(docCount,"00000#")))
Else
Set viewEntry = viewCollection.GetLastEntry
Call source.FieldSetText("ReqNo","REQ" &Cstr(Format(doccount+1,"00000#")))
End If
End If
End Sub
Based on that code, how can I edit the "REQ" as per above to be the created year?
Thank you very much for your help.
You get the current year as string with
CStr(Year(Now))
Replace "REQ" with it.

How to get the second to the last item in combobox

So I have a combobox which gets its value in a database, at first I only need the last value inside the combobx in which i used
Dim lastitem As Integer = 0
lastitem = ClassInfo.ComboBox1.Items.Count
ClassInfo.ComboBox1.SelectedIndex = lastitem - 1
Btw I'm creating an enrollment system in which the system will automatically detects the previous year for the new enrollees to be added in the the current year, since every year is changing i need to know how to do this. Thanks for the help.

VBA-Excel return the latest date

I am a newbie to using VBA to program functions in Excel (just started this morning actually). Here is my problem including my almost but non-working solution.
Problem outline:
I have 2 columns of data, a userID and a Date column. I want to create a function that returns the maximum date (latest) for a userID. A userID may appear once, or many times (number varies from user to user, but doesn't exceed 20).
Now to make this problem a easier for my little brain, I pre-sort the userIDs to appear one after another, and then created a third column to mark the first instance of a userID (not necessarily the one with the earliest/latest date) using a simple excel If statement: If its the first instance it is the userID, else it is empty.
Then I created a function that takes in a range of cells (userIDs), and a single other value (the third column cell containing a single value of userID)
A typical excel worksheet will look like this:
userID Date First Instance
1 3/3/12 1
1 3/2/11
1 2/3/14
2 2
2 3/4/15
2
2 5/6/15
3 5/5/16 3
4 4/4/14 4
4
4 6/7/08
...
I wrote the function below, which takes in userID as the iRange (I select more than 20 so that for other users which may have 20 instances of userID are also included), and idCell as the single identifier of the first instance of userId.
The logic behind the code is:
Loop through iRange and compare it to idCell
If it's equal, check that the next cell (next to the element from iRange is a date) and if it is
Check whether it is larger than the maxDate, store it if true
At the end I return maxDate
The result:
I get a number back, but it isn't a date and I don't think it has any bearing on a date.
Function returnDate2(iRange As Range, idCell As Range) As Date
Dim elem As Variant
Dim i As Long
Dim maxDate As Date
For Each elem In iRange
If elem = idCell Then
If IsDate(elem.Offset(0, 1)) Then
If elem.Offset(0, 1) > maxDate Then
maxDate = DateValue(elem.Offset(0, 1))
End If
returnDate2 = maxDate
End If
End If
Next elem
End Function
Thanks in advance!

Check row for multiple values from Excel

I am making a data entry form through VBA excel. I am very new at this and was unable to get any meaningful search results as I was unsure of the name of what I was trying to do.
Anyway, the form I am making is for users to enter data collected from running audits and when "Save" button is clicked, the data from the text boxes and combo boxes is written to a new row in an excel workbook.
In my form there are four fields that identify each data entry (Year, Quarter, Day, Ward) followed by the rest of the data. I am trying to get some code to first check if there is a row with the same values already in the workbook to prevent duplicate entries.
e.g. The spreadsheet contains the following data -
YEAR -- QUARTER---- DAY--- WARD
2013----------1--------- Monday -- ICU
2013----------2--------- Monday -- ICU
2013----------3--------- Monday -- ICU
2013----------4--------- Monday -- ICU
2014----------1--------- Monday -- ICU
And a user enters a new entry with the following values
Year - 2014
Quarter - 1
Day - Monday
Ward - ICU
I need some code that would give a result (Msgbox saying duplicate entry etc)
but if they entered one that was
Year - 2014
Quarter - 2
Day - Monday
Ward - ICU
All is ok and they are able to click "save"
I appreciate your help (sorry for the dumb question!)
Here's a code fragment (Function IsDuplicate()) which loops through a range until the first blank row (to be precise to the first row where the fist column is empty) and compares 4 key fields with 4 parameters you are providing.
You can call this from your Save button and, depending on the outcome, proceed with writing and closing the form or refuse the writing and display a MsgBox.
Sub Test()
Dim DTab As Range
Set DTab = ActiveSheet.[B3] ' define start of data table
If IsDuplicate(DTab, 1, 1, 1, 1) Then ' your form input here instead of 1,1,1,1
MsgBox ("duplicate")
' stay in form
Else
MsgBox ("unique")
' write record and close form
End If
End Sub
Private Function IsDuplicate(DRange As Range, P1 As Variant, P2 As Variant, P3 As Variant, P4 As Variant) As Boolean
Dim Idx As Long
IsDuplicate = False
Idx = 2 ' 1st row is header
Do While DRange(Idx, 1) <> "" ' break at 1st blank row
If DRange(Idx, 1) = P1 And _
DRange(Idx, 2) = P2 And _
DRange(Idx, 3) = P3 And _
DRange(Idx, 4) = P4 Then
IsDuplicate = True
Exit Do
End If
Idx = Idx + 1
Loop
End Function
You will need this function quite often .... sometimes you want to return Idx instead of just a True/False to return the number of the record - if you must decide whether to Insert/Append or Update a record.

Get a list of the last 10 Mondays

I wanna have a drop down that lets me select "Week Commencing Monday the 20th" going back 10 Mondays but I'm not sure how to go about doing this.
I've used date.now(), etc. before but not sure how to do this one.
Thanks,
Billy
UPDATED CODE
Public Sub GetMondays()
Dim dtMondays As New DataTable()
dtMondays.Columns.Add("Date")
Dim i As Integer = 1
While (dtMondays.Rows.Count < 11)
Dim Day As DateTime = Today.AddDays(-i)
If Day.DayOfWeek = 1 Then
dtMondays.Rows.Add(Day)
End If
i += 1
End While
drpDate.DataSource = dtMondays
drpDate.DataBind()
End Sub
You could come up with a formula for calculating the dates of the previous Mondays, but why not do something simple:
Begin loop.
Subtract one day.
Check if it is Monday.
If so, add to a list.
If the list contains 10 elements, exit loop.
Go back to start of loop.
I'm sure you can implement that. It's not that fastest way, but it's simple and probably fast enough for most purposes. If you want to optimize it, you can do so, but it's probably not worth your time unless this is being executed many times per second.
Let's work through it. I'll do this in C# but hopefully some enterprising young polyglot can do the translation for me and score the accepted answer.
DateTime.Today gets you today's date. DateTime.Today.DayOfWeek gets you today's "day of the week" as an enum, where Sunday is 0 and Saturday is 6.
So we can get the latest Monday using:
var lastMonday = DateTime.Today.AddDays(1 - (int)DateTime.Today.DayOfWeek);
edit There's one little glitch here, in that if today is Sunday you'll be getting tomorrow's date, not last Monday's. There's probably some really tricky mathematical way to get around that, but it's just as easy to throw in an extra check:
if (lastMonday > DateTime.Today) lastMonday = lastMonday.AddDays(-7);
Then we just need to get ten of them:
var lastTenMondays = from i in Enumerable.Range(0, 10)
select lastMonday.AddDays(i * -7);
I was searching for something similar, only that I wanted to display the upcoming Mondays. This thread helped in some way. Thanks!
Even though this thread is old, for any one coming across, this may be helpful:
Public Sub Form5_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Dim nextMondays = DateTime.Today.AddDays(1 - CInt(DateTime.Today.DayOfWeek))
Dim i As Integer = 1
If nextMondays < DateTime.Today Then
nextMondays = nextMondays.AddDays(+7)
End If
For i = 0 To 14
ComboBox1.Items.Add("Mon. " + nextMondays.AddDays(i * +7))
Next i
End Sub
It's probably late but might be helpful for others.
You can do what Mark said but instead of continuing the loop once you find a Monday you can then subtract 7 (or add if you want to find the next 10 mondays) days and get the other monday and you can do this 10 times
* Begin loop.
* Subtract one day.
* Check if it is Monday.
o If so, add to a list.
o (in a for i = 1 to 10 loop) add 7 days and add to list (end for loop)
* Go back to start of loop.
this might save up some time.