How can I get the resulting generated list of links sorted out alphabetically according to "sTitle"? My sort function on line 272 is not giving me the results I need. Please help.
<script language="VB" runat="server">
Function sectionTitle(ByRef f As String)
'Open a file for reading
'Dim FILENAME As String = Server.MapPath("index.asp")
Dim FILENAME As String = f
'Get a StreamReader class that can be used to read the file
Dim objStreamReader As StreamReader
objStreamReader = File.OpenText(FILENAME)
'Now, read the entire file into a string
Dim contents As String = objStreamReader.ReadToEnd()
'search string for <title>some words</title>
Dim resultText As Match = Regex.Match(contents, "(<title>(?<t>.*?)</title>)")
'put result into new string
Dim HtmlTitle As String = resultText.Groups("t").Value
Return HtmlTitle
' If HtmlTitle <> "" Then
'Response.Write(HtmlTitle)
' Else
'Response.Write("<ul><li>b: " & contents & "</a></li></ul>")
' End If
End Function
Public Class linkItem
Public myName As String
Public myValue As String
Public Sub New(ByVal myName As String, ByVal myValue As String)
Me.myName = myName
Me.myValue = myValue
End Sub 'New
End Class 'linkItem
Sub DirSearch(ByVal sDir As String)
Dim d As String
Dim f As String
Dim mylist As New List(Of linkItem)
Try
For Each d In Directory.GetDirectories(sDir)
'Response.Write("test c")
For Each f In Directory.GetFiles("" & d & "", "index.asp")
'Response.Write("test a")
Dim sTitle As String = sectionTitle(f)
'remove wilbur wright college - from sTitle string
sTitle = Regex.Replace(sTitle, "My College - ", "")
'print section title - must come before search n replace string
f = Regex.Replace(f, "C:\\inetpub\\wwwroot\\mypath\\", "")
'add to list
mylist.Add(New linkItem(f, sTitle))
'print links as list
'Response.Write("<ul><li><a href='" & f & "'>" & sTitle & "</a></li></ul>")
Next
DirSearch(d)
Next
Catch excpt As System.Exception
'Response.Write("test b")
Response.Write(excpt.Message)
End Try
mylist.Sort(Function(p1, p2) p1.myValue.CompareTo(p2.myValue))
mylist.ForEach(AddressOf ProcessLink)
End Sub
Sub ProcessLink(ByVal P As linkItem)
If (True) Then
Response.Write("<ul><li><a href='" & P.myName & "'>" & P.myValue & "</a></li></ul>")
End If
End Sub
</script>
<%
'Dim sDir As New DirectoryInfo(Server.MapPath(""))
Call DirSearch((Server.MapPath("")))
%>
Check out the IComparable interface to help with this.
Basically, you need to teach your program what to use as a comparison point of reference for your class.
IComparable will allow you to make use of the CompareTo() method.
Here's the sample code if you're interested:
Public Class Temperature
Implements IComparable
Public Overloads Function CompareTo(ByVal obj As Object) As Integer _
Implements IComparable.CompareTo
If TypeOf obj Is Temperature Then
Dim temp As Temperature = CType(obj, Temperature)
Return m_value.CompareTo(temp.m_value)
End If
Throw New ArgumentException("object is not a Temperature")
End Function
' The value holder
Protected m_value As Integer
Public Property Value() As Integer
Get
Return m_value
End Get
Set(ByVal Value As Integer)
m_value = Value
End Set
End Property
Public Property Celsius() As Integer
Get
Return (m_value - 32) / 2
End Get
Set(ByVal Value As Integer)
m_value = Value * 2 + 32
End Set
End Property
End Class
Related
When I try to get the phone number of a person from Active Directory, all the properties are loaded but except mail nothing is returned. Can someone please help out in how to retrieve the phone number with some changes in the below code? In myrelustpropcollection.propertynames only 2 is the count ADSPATH and mail. No other property is loaded.
Public Function GetPhoneByName(ByVal Name As String) As String
Dim srch As DirectorySearcher
Dim results As SearchResultCollection = Nothing
Dim phone As Integer
srch = New DirectorySearcher(New DirectoryEntry())
srch.Filter = "(mailnickname=" + Name + ")"
srch.PropertiesToLoad.Add("homephone")
srch.PropertiesToLoad.Add("mail")
srch.PropertiesToLoad.Add("mobile")
srch.PropertiesToLoad.Add("telephoneNumber")
Try
results = srch.FindAll()
Catch ex As Exception
End Try
For Each result In results
Dim myKey As String
Dim myResultPropCollection As ResultPropertyCollection
myResultPropCollection = result.Properties
For Each myKey In myResultPropCollection.PropertyNames
Dim tab1 As String = " "
Dim myCollection As Object
Select Case myKey
Case "mobile" ' Telephone Number
For Each myCollection In myResultPropCollection(myKey)
phone = myCollection.toint
Next myCollection
End Select
Next myKey
Next
Return phone
End Function
This works fine for me and the code is more concise:
Imports System.DirectoryServices.AccountManagement
Imports System.DirectoryServices
Imports System.Collections
Public Function GetPhoneByName(Name As String) As String
Dim ctx As New PrincipalContext(ContextType.Domain, "DomainName")
Dim q As New UserPrincipal(ctx)
q.DisplayName = Name
Dim s As PrincipalSearcher = New PrincipalSearcher(q)
Dim ds As DirectorySearcher = s.GetUnderlyingSearcher
ds.PropertiesToLoad.Clear()
ds.PropertiesToLoad.Add("homephone")
ds.PropertiesToLoad.Add("mail")
ds.PropertiesToLoad.Add("mobile")
ds.PropertiesToLoad.Add("telephoneNumber")
For Each dsResult As SearchResult In ds.FindAll()
For Each itm As DictionaryEntry In dsResult.Properties
Select Case itm.Key
Case "mobile"
Return itm.Value(0)
End Select
Next
Next
Return "Not found"
End Function
The following code will return all values available for the user from the active directory:
Imports System.DirectoryServices
Module AdTest
Sub Main()
GetPhoneByName("Persons Display Name")
Console.ReadLine()
End Sub
Public Sub GetPhoneByName(ByVal Name As String)
Dim srch As New DirectorySearcher(New DirectoryEntry())
srch.Filter = "(displayname=" + Name + ")"
For Each result As SearchResult In srch.FindAll()
For Each key As DictionaryEntry In result.Properties
For Each keyVal In result.Properties(key.Key)
Try
Console.WriteLine(key.Key + ": " + keyVal)
Catch ex As Exception
'value of keyVal could not convert to string (probably byte array)
End Try
Next
Next
Next
End Sub
End Module
I'm practicing VB.NET and I've got a problem with Reading and writing to a .dat file. I have made a structure to store data temporarily (below).
Structure CustomerType
Dim AccountNum As String
Dim Surname As String
Dim Forename As String
Dim Balance As Decimal
End Structure
I then Dim everything.
Dim Customers(9) As CustomerType
Dim Filename As String = "Accounts.dat"
Dim NumberOfRecords As Short = 0
Dim myFormat As String = "{0,-15}|{1,-15}|{2,-10}|{3,-10}"
I have a button that creates a new account and this is where I get the problem.
FileOpen(1, Filename, OpenMode.Random, , , )
For i = 1 To Customers.Length() - 1
With Customers(i)
.Forename = InputBox("First name", "Forename")
Do Until .Forename <> "" And TypeOf .Forename Is String
.Forename = InputBox("First name", "Forename")
Loop
.Surname = InputBox("Surname", "Surname")
Do Until .Surname <> "" And TypeOf .Surname Is String
.Surname = InputBox("Surname", "Surname")
Loop
.AccountNum = InputBox("Account Number of " & Customers(i).Forename & " " & Customers(i).Surname & ".", "Account Number")
Do Until .AccountNum.Length = 8 And TypeOf .AccountNum Is String
.AccountNum = InputBox("Account Number of " & Customers(i).Forename & " " & Customers(i).Surname & ".", "Account Number")
Loop
.Balance = InputBox("Balance of " & Customers(i).Forename & " " & Customers(i).Surname & ".", "Balance")
Do Until .Balance > -1
.Balance = InputBox("Balance of " & Customers(i).Forename & " " & Customers(i).Surname & ".", "Balance")
Loop
FilePut(1, Customers, NumberOfRecords + 1)
NumberOfRecords += 1
lblNumberOfRecords.Text = NumberOfRecords
End With
Next
FileClose(1)
I have another button that displays the data in a listbox. I can only get one item to display before I get a bad length error.
Dim Index As Integer
ListBox1.Items.Clear()
ListBox1.Items.Add(String.Format(myFormat, "Forename", "Surname", "Acc. Num.", "Balance"))
ListBox1.Items.Add("_____________________________________________________")
FileOpen(1, Filename, OpenMode.Random, , , )
For Index = 1 To NumberOfRecords
FileGet(1, Customers)
ListBox1.Items.Add(String.Format(myFormat, Customers(Index).Forename, Customers(Index).Surname, Customers(Index).AccountNum, Format(Customers(Index).Balance, "currency")))
Next Index
FileClose(1)
The main question that I have is What am I doing wrong, and how can I fix it?
Many Thanks in advance,
Jordan
First you'll need to import these namespaces:
Imports System.Runtime.Serialization
Imports System.Runtime.Serialization.Formatters.Binary
Imports System.IO
Model
Change your customertype model to this:
<Serializable()> _
Public Class CustomerType
Implements ISerializable
Public Sub New()
End Sub
Protected Sub New(info As SerializationInfo, context As StreamingContext)
Me.AccountNum = info.GetString("AccountNum")
Me.Surname = info.GetString("Surname")
Me.Forename = info.GetString("Forename")
Me.Balance = info.GetDecimal("Balance")
End Sub
Public AccountNum As String
Public Surname As String
Public Forename As String
Public Balance As Decimal
Public Sub GetObjectData(info As System.Runtime.Serialization.SerializationInfo, context As System.Runtime.Serialization.StreamingContext) Implements System.Runtime.Serialization.ISerializable.GetObjectData
info.AddValue("AccountNum", Me.AccountNum)
info.AddValue("Surname", Me.Surname)
info.AddValue("Forename", Me.Forename)
info.AddValue("Balance", Me.Balance)
End Sub
End Class
Your model do now support serialization. Next step is to create functions to read/write a model collection to/from a file.
Write
Friend Shared Sub Write(filePathAndName As String, list As List(Of CustomerType))
Dim formatter As IFormatter = New BinaryFormatter()
Using stream As New FileStream(filePathAndName, FileMode.Create, FileAccess.Write, FileShare.None)
formatter.Serialize(stream, list)
End Using
End Sub
Read
Friend Shared Function Read(filePathAndName As String) As List(Of CustomerType)
Dim formatter As IFormatter = New BinaryFormatter()
Dim list As List(Of CustomerType) = Nothing
Using stream As New FileStream(filePathAndName, FileMode.Open, FileAccess.Read, FileShare.None)
list = DirectCast(formatter.Deserialize(stream), List(Of CustomerType))
End Using
Return list
End Function
Usage
Drop a button named Button1 onto a form named Form1 and add this code:
Public Class Form1
Public Sub New()
Me.InitializeComponent()
End Sub
Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
Dim path As String = "C:\test.dat" '<- Change to desired path
Dim list As New List(Of CustomerType)
'Create test item1 and add to list.
Dim item1 As New CustomerType()
With item1
.AccountNum = "1"
.Balance = 1000D
.Forename = "Forename 1"
.Surname = "Surname 1"
End With
list.Add(item1)
'Create test item2 and add to list.
Dim item2 As New CustomerType()
With item2
.AccountNum = "2"
.Balance = 2000D
.Forename = "Forename 2"
.Surname = "Surname 2"
End With
list.Add(item2)
'Write to file:
Write(path, list)
'Read from file into new list:
Dim list2 As List(Of CustomerType) = Read(path)
MsgBox(String.Format("Count={0}", list2.Count))
End Sub
Friend Shared Sub Write(filePathAndName As String, list As List(Of CustomerType))
Dim formatter As IFormatter = New BinaryFormatter()
Using stream As New FileStream(filePathAndName, FileMode.Create, FileAccess.Write, FileShare.None)
formatter.Serialize(stream, list)
End Using
End Sub
Friend Shared Function Read(filePathAndName As String) As List(Of CustomerType)
Dim formatter As IFormatter = New BinaryFormatter()
Dim list As List(Of CustomerType) = Nothing
Using stream As New FileStream(filePathAndName, FileMode.Open, FileAccess.Read, FileShare.None)
list = DirectCast(formatter.Deserialize(stream), List(Of CustomerType))
End Using
Return list
End Function
End Class
I am working on my first website and need help with a loop. I have a database table containing food items named Menu with 8 categories (such as Burgers, Appetizers). I also have a menu page on website with 8 different pics to display items from each category. I need to loop through rows of database. What is happening is it's only looping through columns and repeating first line over and over. I'm aware I need a loop but for some reason cannot get that right.
This is code behind:
Partial Class Burger
Inherits System.Web.UI.Page
'String Used to build the necessary markup and product information
Dim str As String = ""
'Var used to interact with SQL database
Dim db As New Interaction
'Adds the necessary markup for each menu item, using its productName
Protected Sub printMenuBlock(ByVal productName As String)
'Set up variable storing the product
Dim product As Product
'Pull the product in from our database using the productName
product = db.ReadProduct(productName)
'Add necessary markup to str variable, with products information within
str += "<div class='storeItem'>"
' str += " <img alt='Item Picture' class='itemPicture' src='" + product.ImagePath.Substring(3).Replace("\", "/") + "' />"
' str += " <div class='itemInfo'>"
str += " <h1 class='itemName'>"
str += " " + product.Name + "</h1>"
str += " <h3 class='itemDescription'>"
str += " " + product.Description + "</h3>"
str += " <p class='itemPrice'>"
str += " " + product.Price.ToString("c") + "</p>"
str += " "
str += " </div>"
str += " </div>"
End Sub
'Uses
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Dim productNames As New List(Of String)
'Pull the product names using the database
productNames = db.getProductNames
'Loop through all product names
For Each name As String In productNames
'Add necessary markup and product info to str variable
printMenuBlock(name)
Next
'Print the str variable in our menuPlace div
menuPlace.InnerHtml = str
End Sub
End Class
This is functions from interaction class:
Private Sub GetProduct(ByVal CatIn As String)
' SQL String
Dim strSelect As String
strSelect = "SELECT * "
strSelect &= " FROM Menu "
' strSelect &= " WHERE (ProductCat = 'Burgers')"
' Set up the connection to the datebase
cmdSelect.Connection = conIn.Connect
' Add the SQL string to the connection
cmdSelect.CommandText = strSelect
' Add the parameters to the connection
cmdSelect.Parameters.Add("#CatIn", SqlDbType.NVarChar).Value = CatIn
End Sub
'Executes the SQL statement to find a Product by ProductId
Public Function ReadProduct(ByVal CatIn As String) As Product
' Product object initalized to nothing
Dim prod As Product = Nothing
Try
Call GetProduct(CatIn)
Dim dbr As SqlDataReader
Dim strCat As String
Dim strName As String
Dim strDesc As String
Dim decPrice As Decimal
Dim strPath As String
' Execute the created SQL command from GetProduct and set to the SqlDataReader object
dbr = cmdSelect.ExecuteReader
dbr.Read()
' Check if there are any returned values
If dbr.HasRows Then
' Assign the value in column two to strName
strCat = dbr.GetString(1)
' Assign the value in column two to strName
strName = dbr.GetString(2)
' Assign the value in column three to strDesc
strDesc = dbr.GetString(3)
' Assing the value in column four to intPrice
decPrice = ToDecimal(dbr.GetValue(4))
'Assign the value in column five to strPath
'strPath = dbr.GetString(3)
' Create the new Product object from the returned values
prod = New Product(strName, strDesc, decPrice, strCat, strPath)
End If
' Clear the SQL parameters and close the connection
cmdSelect.Parameters.Clear()
dbr.Close()
Catch ex As SqlException
Dim strOut As String
strOut = ex.Message
Console.WriteLine(strOut)
End Try
' Return the Product object
Return prod
End Function
'Returns a list of Product Names
Public Function getProductNames() As List(Of String)
Dim list As New List(Of String)
Dim sql As String = "SELECT ProductName FROM Menu " +
"WHERE (ProductCat) = 'Burgers'"
'"DISTINCT 'ProductName'"
cmdSelect.CommandText = sql
cmdSelect.Connection = conIn.Connect
Dim dbr As SqlDataReader
dbr = cmdSelect.ExecuteReader
If dbr.HasRows Then
Do While dbr.Read()
list.Add(dbr.GetString(0))
Loop
End If
dbr.Close()
Return list
End Function
There is obviously a Product Class but don't think that is necessary to show on here.
Also, ignore the string path, that will be for images later. Thanks for any help. I'm pretty sure instead of do while I need a for each somewhere but just can't get her done. Thanks in advance.
Products Class:
Public Class Product
Private pName As String
Private pDescription As String
Private pPrice As Integer
Private pPath As String
Private pCat As String
'Constructor, uses database to populate properties based on productName
Public Sub New(ByVal productName As String)
Dim data As New Interaction
Dim work As Product
work = data.ReadProduct(productName)
pCat = work.Cat
pName = work.Name
pDescription = work.Description
pPrice = work.Price
End Sub
'Constructor, populates properties from passed in values
Public Sub New(ByVal NameIn As String,
ByVal DescriptionIn As String, ByVal PriceIn As Integer, ByVal CatIn As String, ByVal ImagePathIn As String)
pName = NameIn
pDescription = DescriptionIn
pPrice = PriceIn
pPath = ImagePathIn
pCat = CatIn
End Sub
'Stores name of product
Public ReadOnly Property Name() As String
Get
Return pName
End Get
End Property
'Stores a description of the product
Public ReadOnly Property Description() As String
Get
Return pDescription
End Get
End Property
'Stores the price of the product
Public ReadOnly Property Price() As Integer
Get
Return pPrice
End Get
End Property
'Stores the path to the image associated with this product
Public ReadOnly Property ImagePath() As String
Get
Return pPath
End Get
End Property
'Stores name of product
Public ReadOnly Property Cat() As String
Get
Return pCat
End Get
End Property
End Class
Use this instead
Public Function ReadProduct(ByVal CatIn As String) As List(Of Dictionary(String, Of String))
Dim ReturnProducts As New List(Of Dictionary(String, Of String))
Try
Call GetProduct(CatIn)
Dim dbr As SqlDataReader
' Execute the created SQL command from GetProduct and set to the SqlDataReader object
dbr = cmdSelect.ExecuteReader
Dim FieldCount = dbr.FieldCount()
Dim ColumnList as New List(Of String)
For i as Integer = 0 to FieldCount - 1
ColumnList.Add(dbr.GetName(i))
Next
While dbr.Read()
Dim ReturnProduct As New Dictionary(String, Of String)
For i as Integer = 0 to FieldCount - 1
ReturnProduct.Add(ColumnList(i), dbr.GetValue(i).toString())
Next
ReturnProducts.Add(ReturnProduct)
End While
cmdSelect.Parameters.Clear()
dbr.Close()
Catch ex As SqlException
Dim strOut As String
strOut = ex.Message
Console.WriteLine(strOut)
End Try
' Return the Product object
Return ReturnProducts
End Function
then, inside printMenuBlock, you declare product with
Dim product = db.ReadProduct(productName)
and later, you access it like so
For i as Integer = 0 to product.Count - 1
'do everything normally for building str except, for example, if you want
'to acccess product.Name as before, access it with product(i).Item("Name"),
'assuming that your column name/alias for "Name" is in fact "Name"
'i personally like to align column names to variable names for laziness's sake
'bad obfuscation practice tho if you don't use aliases
Next
First off thanks for reading this, I've spent the last four hours trying to work this out.
Essentially I'm building a application in where the user inputs: date, Name, Phone number and instructor name to a simple csv .txt database file. I've got all that working.
Now all I need to do is somehow group the details together, and separate from other entries.
I now want to sort these grouped details by date through a bubble sort and then save it to another file. WHen I say sort, I want the other details to go along with the date.
The date when inputted to the application has to be: (yyMMddhhmm)
Eg: 1308290930 = 9:30 on 29/08/13
I can post what I've done thus far.
Public Class Form2
Dim currentRow As String()
Dim count As Integer
Dim one As Integer
Dim two As Integer
Dim three As Integer
Dim four As Integer
Dim catchit(100) As String
Dim count2 As Integer
Dim arrayone(50) As Integer
Dim arraytwo(50) As String
Dim arraythree(50) As Integer
Dim arrayfour(50) As String
Dim bigstring As String
Dim builder As Integer
Dim twodata As Integer
Private Sub Form2_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
'Me.RichTextBox1.LoadFile("D:\completerecord.txt", RichTextBoxStreamType.PlainText)
Using MyReader As New Microsoft.VisualBasic.FileIO.TextFieldParser("D:\completerecord.txt")
MyReader.TextFieldType = FileIO.FieldType.Delimited
MyReader.SetDelimiters(",")
Dim currentRow As String()
Dim count As Integer
count = 0
While Not MyReader.EndOfData
Try
currentRow = MyReader.ReadFields()
Dim currentField As String
For Each currentField In currentRow
' makes one array to contain a record for each peice of text in the file
'MsgBox(currentField) '- test of Field Data
' builds a big string with new line-breaks for each line in the file
bigstring = bigstring & currentField + Environment.NewLine
'build two arrays for the two columns of data
If (count Mod 2 = 1) Then
arraytwo(two) = currentField
two = two + 1
'MsgBox(currentField)
ElseIf (count Mod 2 = 0) Then
arrayone(one) = currentField
one = one + 1
End If
count = count + 1
'MsgBox(count)
Next
Catch ex As Microsoft.VisualBasic.FileIO.MalformedLineException
MsgBox("Error Occured, Please contact Admin.")
End Try
End While
End Using
RichTextBox1.Text = bigstring
' MsgBox("test")
End Sub
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim NoMoreSwaps As Boolean
Dim counter As Integer
Dim Temp As Integer
Dim Temp2 As String
Dim listcount As Integer
Dim builder As Integer
Dim bigString2 As String = ""
listcount = UBound(arraytwo)
'MsgBox(listcount)
builder = 0
'bigString2 = ""
counter = 0
Try
'this should sort the arrays using a Bubble Sort
Do Until NoMoreSwaps = True
NoMoreSwaps = True
For counter = 0 To (listcount - 1)
If arraytwo(counter) > arraytwo(counter + 1) Then
NoMoreSwaps = False
If arraytwo(counter + 1) > 0 Then
Temp = arraytwo(counter)
Temp2 = arrayone(counter)
arraytwo(counter) = arraytwo(counter + 1)
arrayone(counter) = arrayone(counter + 1)
arraytwo(counter + 1) = Temp
arrayone(counter + 1) = Temp2
End If
End If
Next
If listcount > -1 Then
listcount = listcount - 1
End If
Loop
'now we need to output arrays to the richtextbox first we will build a new string
'and we can save it to a new sorted file
Dim FILE_NAME As String = "D:\sorted.txt"
If System.IO.File.Exists(FILE_NAME) = True Then
Dim objWriter As New System.IO.StreamWriter(FILE_NAME, True)
While builder < listcount
bigString2 = bigString2 & arraytwo(builder) & "," & arrayone(builder) + Environment.NewLine
objWriter.Write(arraytwo(builder) & "," & arrayone(builder) + Environment.NewLine)
builder = builder + 1
End While
RichTextBox2.Text = bigString2
objWriter.Close()
MsgBox("Text written to log file")
Else
MsgBox("File Does Not Exist")
End If
Catch ex As Exception
MsgBox(ex.Message)
End Try
End Sub
End Class
Create a class to hold the information for each entry, like this:
Public Class MyEntry
Public Property TheDate() As DateTime
Get
Return m_Date
End Get
Set
m_Date = Value
End Set
End Property
Private m_Date As DateTime
Public Property Name() As String
Get
Return m_Name
End Get
Set
m_Name = Value
End Set
End Property
Private m_Name As String
Public Property PhoneNumber() As String
Get
Return m_PhoneNumber
End Get
Set
m_PhoneNumber = Value
End Set
End Property
Private m_PhoneNumber As String
Public Property Instructor() As String
Get
Return m_Instructor
End Get
Set
m_Instructor = Value
End Set
End Property
Private m_Instructor As String
Public Sub New(date As DateTime, name As String, phoneNumber As String, instructor As String)
TheDate = date
Name = name
PhoneNumber = phoneNumber
Instructor = instructor
End Sub
End Class
Now you can create a list of the above class, like this:
Private entries As var = New List(Of MyEntry) From { _
New MyEntry(DateTime.Now.AddDays(-1), "Dummy 1", "555-123-4567", "Instructor A"), _
New MyEntry(DateTime.Now.AddDays(-1), "Dummy 2", "555-124-4567", "Instructor B"), _
New MyEntry(DateTime.Now.AddDays(-1), "Dummy 3", "555-125-4567", "Instructor C"), _
New MyEntry(DateTime.Now.AddDays(-2), "Dummy 4", "555-126-4567", "Instructor A"), _
New MyEntry(DateTime.Now.AddDays(-2), "Dummy 5", "555-127-4567", "Instructor B") _
}
Note: You will need to substitute your real values here and would use some type of looping structure to do that.
Now you can apply the LINQ GroupBy function to the list of entries, like this:
Private entriesByDate As var = entries.GroupBy(Function(x) x.TheDate).ToList()
This results in a list of two entries for the dummy data I created above, your amount of groupings will vary based upon your actual data.
Now you could loop through the list of groups, like this:
For Each entry In entriesByDate
' Put logic here to save each group to file
Next
My suggestion is to add a marker at the end of reach recoord (date, time, etc.). I use "|". Then, when you read the data back, split the records into an array, and read them out using that.
So it would be:
130829|0930|<name>|<phone number>|etc
Do you understand?
POP Servers allow for the LIST command that returns a list of all of the emails in the mail box. Unfortunately it does not return ALL of the emails, it only returns the emails from the Inbox. So if an email lands in a junk folder it cannot find it.
Is it possible to download emails from the junk folder using POP?
This is the current class(s) that I am using:
Option Strict On
Option Explicit On
Imports System.Net, System.Text
Public Class POP3
Inherits Sockets.TcpClient
Dim Stream As Sockets.NetworkStream
Dim UsesSSL As Boolean = False
Dim SslStream As Security.SslStream
Dim SslStreamDisposed As Boolean = False
Public LastLineRead As String = vbNullString
Public Overloads Sub Connect(ByVal Server As String, ByVal Username As String, ByVal Password As String, Optional ByVal InPort As Integer = 110,Optional ByVal UseSSL As Boolean = False)
If Connected Then Disconnect()
UsesSSL = UseSSL
MyBase.Connect(Server, InPort)
Stream = MyBase.GetStream
If UsesSSL Then
SslStream = New Security.SslStream(Stream)
SslStream.AuthenticateAsClient(Server)
End If
If Not CheckResponse() Then Exit Sub
If CBool(Len(Username)) Then
Me.Submit("USER " & Username & vbCrLf)
If Not CheckResponse() Then Exit Sub
End If
If CBool(Len(Password)) Then
Me.Submit("PASS " & Password & vbCrLf)
If Not CheckResponse() Then Exit Sub
End If
End Sub
Public Function CheckResponse() As Boolean
If Not IsConnected() Then Return False
LastLineRead = Me.Response
If (Left(LastLineRead, 3) <> "+OK") Then
Throw New POP3Exception(LastLineRead)
Return False
End If
Return True
End Function
Public Function IsConnected() As Boolean
If Not Connected Then
Throw New POP3Exception("Not Connected to an POP3 Server.")
Return False
End If
Return True
End Function
Public Function Response(Optional ByVal dataSize As Integer = 1) As String
Dim enc As New ASCIIEncoding
Dim ServerBufr() As Byte
Dim Index As Integer = 0
If dataSize > 1 Then
ReDim ServerBufr(dataSize - 1)
Dim dtsz As Integer = dataSize
Dim sz As Integer
Do While Index < dataSize
If UsesSSL Then
sz = SslStream.Read(ServerBufr, Index, dtsz)
Else
sz = Stream.Read(ServerBufr, Index, dtsz)
End If
If sz = 0 Then Return vbNullString
Index += sz
dtsz -= sz
Loop
Else
ReDim ServerBufr(255)
Do
If UsesSSL Then
ServerBufr(Index) = CByte(SslStream.ReadByte)
Else
ServerBufr(Index) = CByte(Stream.ReadByte)
End If
If ServerBufr(Index) = -1 Then Exit Do
Index += 1
If ServerBufr(Index - 1) = 10 Then Exit Do
If Index > UBound(ServerBufr) Then
ReDim Preserve ServerBufr(Index + 255)
End If
Loop
End If
Return enc.GetString(ServerBufr, 0, Index)
End Function
Public Sub Submit(ByVal message As String)
Dim enc As New ASCIIEncoding
Dim WriteBuffer() As Byte = enc.GetBytes(message)
If UsesSSL Then
SslStream.Write(WriteBuffer, 0, WriteBuffer.Length)
Else
Stream.Write(WriteBuffer, 0, WriteBuffer.Length)
End If
End Sub
Public Sub Disconnect()
Me.Submit("QUIT" & vbCrLf)
CheckResponse()
If UsesSSL Then
SslStream.Dispose()
SslStreamDisposed = True
End If
End Sub
'*******************************************************************************
' Function Name : List
' Purpose : Get the drop listing from the maildrop
' :
' Returns : Any Arraylist of POP3Message objects
' :
' Typical telNet I/O:
'LIST (submit)
'+OK Mailbox scan listing follows
'1 2532 (record index and size in bytes)
'2 1610
'3 12345
'. (end of records terminator)
'*******************************************************************************
Public Function List() As ArrayList
If Not IsConnected() Then Return Nothing 'exit if not in TRANSACTION mode
Me.Submit("LIST" & vbCrLf) 'submit List request
If Not CheckResponse() Then Return Nothing 'check for a response, but if an error, return nothing
'
'get a list of emails waiting on the server for the authenticated user
'
Dim retval As New ArrayList 'set aside message list storage
Do
Dim response As String = Me.Response 'check response
If (response = "." & vbCrLf) Then 'done with list?
Exit Do 'yes
End If
Dim msg As New POP3Message 'establish a new message
Dim msgInfo() As String = Split(response, " "c) 'separate by spaces, which divide its fields
msg.MailID = Integer.Parse(msgInfo(0)) 'get the list item number
msg.ByteCount = Integer.Parse(msgInfo(1)) 'get the size of the email message
msg.Retrieved = False 'indicate its message body is not yet retreived
retval.Add(msg) 'add a new entry into the retrieval list
Loop
Return retval 'return the list
End Function
Public Function GetHeader(ByRef msg As POP3Message, Optional ByVal BodyLines As Integer = 0) As POP3Message
If Not IsConnected() Then Return Nothing
Me.Submit("TOP " & msg.MailID.ToString & " " & BodyLines.ToString & vbCrLf)
If Not CheckResponse() Then Return Nothing
msg.Message = vbNullString
Do
Dim response As String = Me.Response
If response = "." & vbCrLf Then
Exit Do
End If
msg.Message &= response
Loop
Return msg
End Function
Public Function Retrieve(ByRef msg As POP3Message) As POP3Message
If Not IsConnected() Then Return Nothing
Me.Submit("RETR " & msg.MailID.ToString & vbCrLf)
If Not CheckResponse() Then Return Nothing
msg.Message = Me.Response(msg.ByteCount)
Do
Dim S As String = Response()
If S = "." & vbCrLf Then
Exit Do
End If
msg.Message &= S
Loop
msg.ByteCount = Len(msg.Message)
Return msg
End Function
Public Sub Delete(ByVal msgHdr As POP3Message)
If Not IsConnected() Then Exit Sub
Me.Submit("DELE " & msgHdr.MailID.ToString & vbCrLf)
CheckResponse()
End Sub
Public Sub Reset()
If Not IsConnected() Then Exit Sub
Me.Submit("RSET" & vbCrLf)
CheckResponse()
End Sub
Public Function NOOP() As Boolean
If Not IsConnected() Then Return False
Me.Submit("NOOP")
Return CheckResponse()
End Function
Protected Overrides Sub Finalize()
If Not SslStreamDisposed Then
SslStream.Dispose()
End If
MyBase.Finalize()
End Sub
End Class
Public Class POP3Message
Public MailID As Integer = 0
Public ByteCount As Integer = 0
Public Retrieved As Boolean = False
Public Message As String = vbNullString
Public Overrides Function ToString() As String
Return Message
End Function
End Class
Public Class POP3Exception
Inherits ApplicationException
Public Sub New(ByVal str As String)
MyBase.New(str)
End Sub
End Class
As per the comments, the POP3 standard only allows for downloading from the "Inbox". It's not designed for anything more advanced.
The ideal solution would be to use IMAP4, if the mail server supports it.
IMAP4 allows you to save, flag, copy and delete messages, as well as allowing folders and subfolders and it does not require exclusive access.