I have created a text file with dates and products bought on that date. I want to read the file when a button is clicked and the return the products bought on the current date only (todays date) into a listbox in VB.net . Any help appreciated.
This is an example of my textfile.
06:35 Sunday, 15 March 2015
Corona Bottle
Miller Bottle
Bulmers Bottle
Beamish Pint
Bacon Fries
Orange Juice
06:41 Sunday, 15 March 2015
Murphy's Pint
Bulmers Pint
Tayto
Purple Snack
This is the code that i have so far:
Private Sub btnTodaysTrans_Click(sender As Object, e As EventArgs) Handles btnTodaysTrans.Click
Dim sr As IO.StreamReader = IO.File.OpenText("ProductsSold.txt")
lstTodaysTrans.Items.Clear()
Do While sr.Peek <> -1
lstTodaysTrans.Items.Add(sr.ReadLine)
Loop
sr.Close()
End Sub
try using the textparser for your operation.it will be like
dim field as string
dim date as datetime
If File.Exists(yourfilename) Then
Using parser As New TextFieldParser(yourfilename)
parser.SetDelimiters(vbTab)
While Not parser.EndOfData
fields = parser.ReadFields()
if IsDate(fields) Then
date= DateTime.ParseExact(fields, "yyyy-MM-dd HH:mm tt", System.Globalization.CultureInfo.InvariantCulture)
if date.value<> your condition Then
'' what you want
else
''what you want
end if
end if
end while
end if
NOTE
Or else You can use the error encountered while converting the text files to datetime as condition for checking if it is a valid date.
First, that is a bad way to store your data. The best way is a database. But even if you use a text-file you could use a better approach. Because the file contains empty line and also different lines belong logically together. So you need to find the date of every product in the previous lines. You could add it to every line, then it's easier.
However, you can use following code which uses LINQ and a loop:
Dim format = "dd MMMM yyyy"
Dim dateProducts As New List(Of Tuple(Of Date, String))
Dim lines = From line In File.ReadLines("ProductsSold.txt")
Where Not String.IsNullOrWhiteSpace(line)
Select line.Trim()
For Each line As String In lines
Dim currentDate As Date
Dim isDateline As Boolean = False
If line.Length >= format.Length AndAlso line.Contains(","c) Then
' try to extract the date...
Dim tokens = line.Split({","c}, StringSplitOptions.RemoveEmptyEntries)
isDateline = Date.TryParseExact(tokens.Last().Trim(), format, CultureInfo.InvariantCulture, DateTimeStyles.None, currentDate)
End If
If isDateline Then
dateProducts.Add(New Tuple(Of Date, String)(currentDate, Nothing))
ElseIf dateProducts.Count > 0 Then
' select date from last item and add this product
dateProducts.Add(New Tuple(Of Date, String)(dateProducts.Last().Item1, line))
Else
' otherwise invalid data, product without date, skip
End If
Next
Now you could use ToLookup to create something similar to a dictionary, the key is the date(without time) and the value is the list of products for that date. One difference to a dictionary is that you get an empty sequence if there is no product for a given date.
Dim dateLookup = dateProducts.
Where(Function(ds) ds.Item2 IsNot Nothing).
ToLookup(Function(ds) ds.Item1.Date)
Dim allProductsOfToday = dateLookup(Date.Today)
For Each dateProductInfo In allProductsOfToday
lstTodaysTrans.Items.Add(dateProductInfo.Item2) ' Item2 is the product
Next
I have tested it with your sample file which doesn't contain products for today, so it's not the best example. If you change one of both date from 15 March 2015 to 16 March 2015 you see the appropriate products in the ListBox.
Related
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.
This is my first time asking in Stack Overflow :)
I have a program that lets the user pick a date in a combobox and display it on the label. The other parts of the code for that is fine but I cant make exception for months with special days (like february which only has 29 days in leap years).
I tried using the If/Else statement so that when the users click the years 2016,2012,2008 and 2004 and february it will display on the combobox named "day" 1 to 29 and if the users click february but not the specified dates it will display 1 to 28:
If month.SelectedItem = "Feb" And year.SelectedItem = "2016" Or "2012" Or "2008" Or "2004" Then
Dim jkl As Integer
For jkl = 1 To 29
day.Items.Add(jkl)
Next
ElseIf month.SelectedItem = "Feb" Then
Dim poi As Integer
For poi = 1 To 28
day.Items.Add("poi")
Next
End If
But unfortunately when i debug it, when i select dates other than the specified in the first If statement the combo box named day only displays 29 instead of 28. I tried changing the order of the conditions, changing the separator of the numbers to "&" but it is still the same.
I hope someone gets to the bottom of this. I feel like its in my structure that is wrong but even if I change the order everytime and it is still displaying the same bug.
I tried searching here but I cant find one like my condition even remotely similar.
Turn Option Strict On, it will help you detect these errors right away. VB does not handle If statement like this, what you wrote doesn't do what you think it does. You need to specify both side every time.
If month.SelectedItem = "Feb" And (year.SelectedItem = "2016" Or year.SelectedItem = "2012" Or year.SelectedItem = "2008" Or year.SelectedItem = "2004") Then
As for your logic, there are formula to detect leap day. It might be better to use it instead.
Lastly, near the end, you add the string and not the variable value.
day.Items.Add(poi)
I think you should use here the DateTime functions:
DateTime.DaysInMonth(year, month)
Docs
Dim dateString As String = String.Format("{0} 1 2001", month.SelectedItem)
Dim dDate As Date = DateTime.Parse(dateString)
Dim numberOfMonth As Integer = DateAndTime.Month(dDate)
For jkl = 1 To DateTime.DaysInMonth(numberOfMonth, year.SelectedItem)
day.Items.Add(jkl)
Next
Personally, i would have made a nested If
if month.SelectedItem = "Feb" then
if year.SelectedItem = "2016" Or "2012" Or "2008" Or "2004" Then
Dim jkl As Integer
For jkl = 1 To 29
day.Items.Add(jkl)
Next
else
Dim poi As Integer
For poi = 1 To 28
day.Items.Add("poi")
Next
end if
I am trying to pull all data entries that are within a userform selected month and year. I can get the code to run fine when I hard code the year but I want the year to come off of a text box. I converted the Textbox value to an integer using Cint() and dim'd it to "Year" in my if statement. I can get it to work if I write Cdate("3/1/2016"), but I want see if there is a way to run it like: Cdate("3/1/Year"). I tried it this way and get a typematch error on the Cdate Im pretty new to VBA so excuse my stupidity.
Ignore the "Month" variable I was just using that to put a stop on the code and step it through to see if it would enter my if statement.
Thanks in advance.
My Code
Private Sub OKBtn_Click()
Dim Sales As Range
Dim Year As Integer
Dim Month As Integer
Dim i As Integer
Year = CInt(YearText.Value)
Set Sales = Worksheets("Sales").Range("A4")
i = 0
If Sales.Offset(i, 1).Value >= CDate("3/1/2016") And Sales.Offset(i, 1).Value <= CDate(" 3/31/2016 ") Then
Month = 1
End If
In order for the CDate to work, you need to seperate the stings inside the brackets to 2 parts
1.The constant, in your case "3/1/".
2.And the variable, CInt(YearText.Value).
Option Explicit
Private Sub OKBtn_Click()
Dim DDate As Date
DDate = CDate("3/1/" & CInt(YearText.Value))
' for debug only
MsgBox "Date entered is :" & DDate
End Sub
I have a .text file of strings delimited by spaces. That would be the obvious parsing solution when I bring it into Excel or Access, but since the strings are not the same size, the fields will be incorrect. I'm hoping to find some help here as I'm not really experienced with this.
This is an example section of the string:
259998887575 15 00:14:38 C33 0:14:42 T33 00:14:52 00:14:58
202224446898 33 00:16:24 B23 00:17:00 C31 00:17:15 T31 00:19:30 C04 00:17:15 T28 00:19:30 00:19:32
The numbers with colons are time stamps and the letter codes (T/C/B) all represent a different field type. My problem is that there can be any number of C and T time stamps listed in the string and there may or may not be a B time stamp.
I'd like the result to show 4 fields... the first, the first c time stamp, the last t time stamp and the last time stamp (the bolded time stamps). All other information can be disregarded. I'd like to use VB to cycle through due to the number of records.
Any help is appreciated!
Edit: It seems like you want to split the dates into types, determined by the bit before each letter.
You can use the Strings.Split method to divide the lines at the spaces. Then use the Date.TryParse method to check which parts are Dates (or times, it's the same). Then you select the first letter of the previous part and sort the dates into their respective lists.
Dim s As String = "202224446898 33 00:16:24 B23 00:17:00 C31 00:17:15 T31 00:19:30 C04 00:17:15 T28 00:19:30 00:19:32"
Dim parts() As String = Strings.Split(s, " ") 'Split the string at all spaces
'Create lists of Date, one list for all dates, one list for each Letter
Dim Tdates As New List(Of Date) 'This stores converted dates
Dim Cdates As New List(Of Date) 'This stores converted dates
Dim Bdates As New List(Of Date) 'This stores converted dates
Dim Alldates As New List(Of Date) 'This stores converted dates
For i = 0 To parts.Count - 1 'Iterate through all parts
Dim ThisDate As Date
If Date.TryParse(parts(i), ThisDate) = True Then 'This tries to parse the current part as a date, returns True if the part is a date
Alldates.Add(ThisDate) 'You want to store all dates in this list
If i > 0 AndAlso parts(i - 1).Length > 0 Then
Dim PrevPartsFirstLetter As String = parts(i - 1)(0) 'Crop the first letter of the previous part
Select Case PrevPartsFirstLetter
Case "T" : Tdates.Add(ThisDate)
Case "C" : Cdates.Add(ThisDate)
Case "B" : Bdates.Add(ThisDate)
End Select
End If
End If
Next
'You can now select the parts you want from the lists
The Tdates-List contains all dates which have a T thing before them and so on. The AllDates-List contains all dates in the line.
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)