Outlook Instant Search - hit and miss results - vb.net

I have the below code to run an instant search from a tool I've developed that iterates through all Outlook folders and then uses the restrict method to get two counts, first the total and the second, a count of those items that are two years or older.
Once done, this is displayed to the user in a listview and the code below is supposed to do an instant search query on the selected result using the 'received' date to limit the results.
What I've found is that sometimes the instant result filters the results and in other cases it purely displays all items from within the selected folder. For example, a folder has 90 items but 5 are over 2 years old, sometimes it will show 5 (generally after the selection has been made from the listview twice) and the rest of the time the full 90 are shown.
Has anyone else come across this is and managed to resolve it?
Private Sub OpenOlFolder(sender As Object, e As EventArgs) Handles lvwProgress.DoubleClick
With olApp.ActiveExplorer
'// CLEAR SEARCH
.ClearSearch()
'// SWITCH TO SELECTED FOLDER
.CurrentFolder = GetOlFolderFromPath(Me.lvwProgress.Items(Me.lvwProgress.FocusedItem.Index).SubItems(0).Text)
'// DO SEARCH
.Search(String.Concat("received:<", RetentionDate.ToString("MM/dd/yyyy")), Outlook.OlSearchScope.olSearchScopeCurrentFolder)
End With
End Sub

In your code I have noticed multiple dots in the single line of code. It is hard to understand where your code fails if something unexpected happens. So, breaking the chain of property and method calls is essential in troubleshooting such cases.
In the code you change the current folder by setting the CurrentFolder property of the Explorer class. It is a time-consuming operation, so it make sense to wait until it is done. For example, you may try to run the Search method in the Explorer.FolderSwitch event which is fired when when the explorer goes to a new folder, either as a result of user action or through program code.
Also it make sense to do the same operation manually to make sure the filter is correct.

Related

How can I make a form instance open a specific record on creation?

I'm trying to optimize the performance of my access frontend. One of the problems I'm stumbling on is how to set a multi-window form to open immediately to a specific record, because at the moment it queries everything twice.
Essentially, I allow my users to open multiple instances of a form. That way, a user can compare multiple records by placing the windows of those forms side by side.
At the moment, my code looks like this:
Set frm = New Form_Name
frm.RecordSource = "select * from Table where id = " & ID 'ID is a variable passed to the method
I'm pretty sure back then this question was one of the building blocks I relied on.
The problem is that on the first line, access already entirely opens the form and does everything the form does when opening, such as Form_Open, Form_Current, and loading subforms. Then, when I set the recordsource, it does all (or most) of that again, which significantly slows down the process of opening the form.
Here are some of the things I've tried:
Changing the Form_Current to recognize that it's being "used" twice and only actually run the code once. The problem is that the code is already very optimized and doesn't seem to be the bottleneck, so this doesn't seem to do much. Actually opening the form seems to be the bottleneck.
Trying to change the properties of the original form so that it opens the specific record I need, but I can't seem to change the properties without it opening the form.
Looking for a way to supply arguments to the form. That doesn't seem to be supported in VBA.
One other idea that popped into my mind was creating a variable in vba with the ID of the record, setting recordsource in the form properties to fetch that variable, but then, when I would open another form and change that ID, the form
I realize that I can do this with DoCmd.OpenForm, but that doesn't give me the option to open multiple instances of the same form.
How can I achieve this? This would mean a significant performance improvement.
OK, so I actually wanted to ask this question. But just before I hit the submit button, I had an idea...
Here's the idea: you set a global variable in VBA, which you then access in the form filter command. In my case I just added Public OpeningID As Long at the top of my VBA module. Then I create a function to get that value:
Public Function getFormID() As Long
getFormID = OpeningID
End Function
Then, in the form, you can set the filter criteria as ID = getFormID(). And then when you open the form instance, you do it like this:
OpeningID = ID
Set frm = New Form_Name
OpenindID = 0 'reset this to make sure that if it's being accessed when it shouldn't, it generates a clear error
The only problem is what happens when you refresh the form, as that will call the method again. When you refresh the form via VBA, you can set the OpeningID beforehand, and to avoid users refreshing the form, you can add this to your form (don't forget to turn on Key Previews in the form settings):
Private Sub Form_KeyDown(KeyCode As Integer, Shift As Integer)
If KeyCode = vbKeyF5 Then KeyCode = 0
End Sub
Bang. Forms open almost twice as fast. Awesome.

How to change the image displayed on a button at runtime in Visual Basic?

I am trying to change the Image attribute associated with a button when the button is clicked.
I have added the image I want to display (called "Black Pawn.png") as a resource within the solution and (from searching around and looking at similar questions) am trying to set the image attribute to it as shown below:
Private Sub boardButtonA2_Click(sender As Object, e As EventArgs) Handles boardButtonA2.Click
Dim sprites As Object = My.Resources.ResourceManager
boardButtonA2.Image = sprites.GetObject("Black Pawn.png")
End Sub
But when I click the button, the default image on it just disappears and is replaced with nothing instead of Black Pawn.png.
I am pretty new to using Visual Basic and Visual Studio so I may have failed to have added the image as a resource properly but I can see the image in the Solution Explorer above the form the button is in.
Any help or advice would be a great help.
Thanks.
EDIT:
Having thought more about the potential scenario, I'm wondering whether this answer is actually relevant. Your example code uses a hard-coded String but I'm wondering whether the actual String really would be a user selection. I'll leave it here anyway.
ORIGINAL:
There's no reason to use a hard-coded String to get a resource. If the String was from user entry then maybe, depending on the circumstances. As it is though, you should be using the dedicated property for that resource. That means using this:
boardButtonA2.Image = My.Resources.Black_Pawn
Just be aware that a new object is created every time you get a resource from My.Resources. For that reason, don't keep getting the same property over and over. If you need to use a resource multiple times, get it once and assign it to a field, then use that field multiple times, e.g.
Private blackPawnImage As Image
Private Function GetBlackPawnImage() As Image
If blackPawnImage Is Nothing Then
blackPawnImage = My.Resources.Black_Pawn
End If
Return blackPawnImage
End Function
and then:
boardButtonA2.Image = GetBlackPawnImage()
Also, I suggest that you change the name of the property to BlackPawn rather than Black_Pawn. You can change it to whatever you want on the Resources page of the project properties.
EDIT:
If this application is a chess game then you definitely will need every resource image for the playing pieces so you probably ought to get all of them at load and assign them to variables, then use them from those variables over the course of the game.
(I am assuming the question is for WinForms, if it isn't I will remove this answer)
When adding images as resources to a project, you have to pay attention to the name given to the resource after it is imported - the name can be changed if you want.
The image below is from one of my projects:
The name of the files on disk are:
CSV - Excel.png
GreenDot.png
RedDot.png
To fix your problem change the line:
boardButtonA2.Image = sprites.GetObject("Black Pawn.png")
to be:
boardButtonA2.Image = sprites.GetObject("Black_Pawn")
I don't think adding the image by going into Project > Add Existing Item properly added the image as a resource.
I instead went into *Project > (Solution Name) Properties > Resources > Images > Add Existing Item * and added it that way and was then able to get it working using jmcilhinney's method (I think my original method/a variation of it would work too but theirs is better).

Search text file and put matching results in listbox

I have a VB.NET project in which there is a form where there is a TextBox control, a ListBox control and an external text file that contains a list of outlook folder paths for client emails.
Essentially, the user enters into the text box the name of a client and/or their unique reference number, presses the search button (yes - I know I could make the results appear as they type, I want a button!) and it comes up with the matching results for the company name or serial number that are in the text file and puts them in the list box, with the full path of the outlook email folder.
For example:
If I put into the textbox: "06967759-274D-40B2-A3EB-D7F9E73727D7"
It would put the following result into the listbox:
"EIS Admin\Contacts{06967759-274D-40B2-A3EB-D7F9E73727D7}"
And the user can then go to that folder and find the email(s).
I have gone through several revisions both of my own code and code pasted from online with people having the same issue, only to have Visual Studio throw no errors, run the code and have no luck, with it doing nothing but clearing the list box, and not showing matching results of any kind.
I understand this may be a repeat question but I am extremely confused, can't get anything to work and need some help regarding my issue.
Here is the current code (from online - not mine):
lbx_OFL_Results.Items.Clear()
Dim i As Integer
For i = 0 To lbx_OFL_Results.Items.Count - 1
If i > lbx_OFL_Results.Items.Count - 1 Then Exit For
If Not lbx_OFL_Results.Items(i).Contains(tbx_FindText.Text) Then
lbx_OFL_Results.Items.Remove(lbx_OFL_Results.Items(i))
i -= 1
End If
Next
The list box is called "lbx_OFL_Results"
The textbox is called "tbx_FindText"
I start by clearing the list box of all items (when the form loads, it fills the list box will all lines of the text file, so I need to clear it).
Form Load Event Code:
Dim lines1() As String = IO.File.ReadAllLines("C:\ProgramData\WPSECHELPER\.data\Outlook Folder Wizard\outlookfolders.txt")
lbx_OFL_Results.Items.AddRange(lines1)
For the rest of the code it seems to be doing some form of a 'sort search' then removing any excess results.
If anyone can suggest edits to my code, or new code then that would be sublime.
Thanks.
Thanks to #Jimi for the answer.
Code:
listbox.Items.Clear()
listbox.BeginUpdate()
For i as Integer = 0 To lines1().Length - 1
If lines1(i).Contains(searchbox.Text) Then
listbox.Items.Add(lines1(i))
End If
Next
listbox.EndUpdate()
I have another question which solves how to make this search non case-sensitive. It can be found here.

How can I redirect to the same page multiple times with a different query string?

I have a page that contains a table with a list of data and an icon (on each row) which redirects the user to a new aspx page with a queryString and does some custom logic to then download the file. The user has asked that we make a "download all" button so they don't have to go through and manually click every icon in every row.
My code is close, I feel, but it will hang after the first file is downloaded and will never progress further.
Here is the code I have so far
Protected Sub ibDownloadAll_Click(sender As Object, e As ImageClickEventArgs)
'Get Parameters
'Run stored procedure to get the query string we're going to use
'Fill DataSet
For Each myItem As DataRow In ds.Tables(0).Rows
Response.Redirect("redirectPage?ID=" &myItem.Item("ID")) 'Gets stuck after here
Next
End Sub
I realized if I added the second parameter (Indicates whether execution of the
current page should terminate)
Response.Redirect("redirectPage?ID=" &myItem.Item("ID"), False)
Then it would make it to the end of the function, running through the loop as expected, but then only outputting/downloading the last file.
Is there something I'm missing or an alternative that can be used to effectively redirect multiple times? Unfortunately with the framework I'm using I'm not able to use Response.Write and put custom scripts in that way, nor can I really change the page that we are redirecting to.
You can't redirect to multiple pages (a redirect close the request) and you also can't send multiple files. Your only option would be to have a request that zip all the files together. You can do this with System.IO.Compression.ZipArchive. You don't need to save the zip on disk, you could just send the memory stream.

Gridview not updating within update panel

Using Visual Studio 2015 (VB) with SQL Server 2012. This is going to be complicated please bear with me.
My questions is why wont my gridview update?
I have a web page that creates txt files in a remote server location. These files are then picked up by a separate (third party tool) which sends them to a government body. The government body then sends a receipt file for each txt file which my web app then picks up and records the result. The result is either an acceptance or a rejection.
On the web page I provide a gridview showing the last ten results and if I send 1 file at a time (with every click of the button) my gridview will refresh without issue showing the results of the receipts. There can be up to minute gap between the creation of the file, the file sending and the receipt being received.
The image below shows an example of my gridview after successful submission and receipt.
As the button is clicked the sent and accepted column display as red with 'No' within them.
When the button is clicked to send the file a sub is processed that creates the file. A timer is then enabled (fires every ten seconds) that runs another sub to check for sent and receipts. I have no issue with this as it works as expected and each cell within the gridview changes to reflect the sent and receipt status.
This is done using a call to build the gridview.
The call
displayLastSentGridView()
displayHistoryGridView()
historyUpdatePanel.Update()
One of the subs to build the gridview
Public Sub displayLastSentGridView()
Dim mlastSent As New lastSent
Dim mLastSents As New List(Of lastSent)
mLastSents = mlastSent.lastSentGridView
gridLastSent.DataSource = mLastSents
gridLastSent.DataBind()
End Sub
Ok so a request came in that when a particular file is created a further 4 are generated (with a different layout) and auto sent. I have implemented this and it works as expected. I then use a new sub to check on the status of these files (as their classification is different). When the file is sent the web page updates the database flagging the entry as sent, when the receipt is accepted it flags it as accepted. My problem occurs here. I use the same code as above to call the gridview updates when the sent even occurs and when the acceptance comes in but the gridviedw does not update.
If I place the code at the end of the sub routine all the cells update i.e. it will update the gridview in one go and all the cells turn green with Yes inside them, but i want it to update each cell as the database notifications are changed.
Below is an excert from my code that checks the folder location strSentFileLocation if it exists the database is updated and then the call to update the gridviews is made. The database update works but the gridview doesnt change.
If File.Exists(strSentFileLocation) Then
db.ngc_updateActivityLogSent(True, seq)
db.ngc_updateActivityLogRejected(False, "N/A", seq)
db.ngc_updateActivityLogAccepted(False, seq)
'update gridviews
displayLastSentGridView()
displayHistoryGridView()
historyUpdatePanel.Update()
End If
My update panel is set to conditional.
Any help greatly appreciated. Thanks
UPDATE
For info the IF statement is nested within a FOR loop.
The from was the for loops, as the sub never actually finished the update panel never got chance to update till right at the end. I have removed the for loop and added in a hidden field that I increment and call the sub until the hidden field reaches a specific value.