Force return values to be saved in VB.net - vb.net

Is there a way in VB.net to force someone to save a value returned from a function?
Here's the reason:
I work with databases, and we have created a function to credit a person's account. However, we want to see the results before we commit them to the database:
Dim trans as List(Of Transaction) = Transaction.createCredit(agreement_id, amount)
However, we don't want anyone at our company to think that the createCredit function will also commit the transactions to the database. Is there a way to ensure that they save the return value?
Thanks in advance!

There is no way to force function return value to be collected by the caller.
This is not VB.NET specific behavior, it works in C# the same way. So this is perfectly valid syntax in VB.NET, with no warnings or errors:
Sub Main()
X()
End Sub
Function X()
Return 0
End Function
What you need is coding standards, unfortunately, you cannot force coding standards, you can only agree on them. There has to be mutual understanding and agreement in this, before you see any benefit from it.

you could rise an event at the end of the Transaction.createCredit function and use this to set a variable isSavedToDb = False
and at some state (probably the closing event) check that variable and call the Save function if needed.

Related

System.StackOverflowException intersection error

I want my program to take a variable, and find letters A-Z. I have made this section of my program in a module to be shared between 2 different forms.
variables are passed from form1 and are processed by the module and then sent back again to form1. the problem is I think some sort of bug in the code but I cant identify it.
Public Function UPCASES(ByRef password1, points) As Boolean
Dim intersection As IEnumerable(Of Char)
intersection = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".Intersect(password1)
'System.StackOverflowException error ^^^^^^^^^^^^^^^^^^^^^^^^^
If intersection.Count() = 1 Then
points = 5
Else
points = 0
End If
Return UPCASES(password1, points)
End Function
You are calling the method itself at the method end, that causes the StackOverflowException:
Return UPCASES(password1, points)
I guess this method should check if the password contains uppercase letters, then use:
Dim containsUpperCase = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".Intersect(password1).Any()
So no need to create a method just for this one-liner, if you need a method:
Public Function ContainsUpperCaseLetter(password1 As String) As Boolean
Return "ABCDEFGHIJKLMNOPQRSTUVWXYZ".Intersect(password1).Any()
End Function
Side-note: you should change your default project settings to use Option Strict ON(Off is default unfortunately). Then you will be able to write much more safe, robust and performant code after you have learned a lot about .NET types because you have to fix the compiler errors.

Prevent Recalculating of Functions when applying autofilter in Excel

I am using excel 2013. I have a large sheet which consist of a list of Customers and their information. When I add new customers to this spreadsheet it fills most information by posting the CustomerID to our server, the server returns the customer information in a Json string which is then parsed. A specific function returns the information required i.e. "=Json_get_email(Userid)" will return the email address. All this work very well and is relatively user friendly for the staff in my company to use.
The problem arises when an autofilter is applied. Even if no function is volatile in this, applying an autofilter causes the spreadsheet to recalculate all the functions and what was efficient and quick for a customer or a few customers is now slowing down the spreadsheet like crazy.
I am turning to you to know if there is any way of preventing my functions to be calculated every time a filter is applied.
my best,
Fabien
Something like this will make your sheet much faster:
Function Json_get_email(arg)
Static dict As Object '<< persists between calls
If dict is nothing then set dict = Createobject("scripting.dictionary")
If not dict.exists(arg) Then
'have not seen this value of arg before
'...get the return "email" value for 'arg' here
dict.add arg, email
End If
Json_get_email = dict(arg) 'return the cached value
End Function
Should be no problem caching the return email values between calls which use the same argument value.
Here is the solution I implemented. I want to share it as I have seen that many people had the same issue with UDFs.
It is not perfect but makes it a lot faster as it avoids connecting to the server and parsing the string each time.
I created a public array of booleans indexed by User_ID,
Public Names_in_List(100000000 To 104000000) As Boolean
Function JSon_CustomerName2(UserID As String) As String
If Names_in_List(UserID) = False Then
'The Function Has not yet been run for this ID
'... Do whatever
Names_in_List(UserID) = True 'Update the status
Else
JSon_CustomerName2 = Application.Caller.value 'Reuse the value that was in the cell.
End If
End Function
As always, I had to trade memory for speed but with booleans its only one bit per user.
Many thanks #Tim for your helpful insight.

Passing VBA variable to Access Query Criteria

I have a simple task giving me a lot of trouble.
What I need is to simply move a variable from my VBA macro to a function, to be able to use it in an Access Query.
ADDED: I have created a small and simple access document with a simple VBA. Download it at:
http://sharesend.com/olpy1o7d
If someone could be kind to download and see what I am doing wrong, I would really prefer it.
In the form f_main I need to be able to change counter to whatever number and hence get an updated query when the button is pressed in the main form.
It is described below, but downloading it may explain my situation easier.
EDITED:
Public counter as Integer
Private Sub Command_Click()
counter = 1
End Sub
And in a module:
Public Function n()
n = counter
End Function
In access, I have a SQL Query as:
SELECT t_Data.ID, n() AS Expr1 FROM t_Data;
Access says it can not find the function n()
If i use the function builder, i can see n(), so i guess it is because the function n() is empty - It can not find "counter" declared in my form.
What can i do?
To help future bummers like mine, I found the error.
I named the module the same as the function, which caused the problem.
By changing the name of the module from n to m_n, and keeping the function name n() it worked perfectly fine.
Stupid mistake is stupid. But thank you guys who looked into my issue.
Declaring a variable as public in a form seems to not actually make it globally public. This has annoyed me many times in Access. Move your declaration of counter to your Module code and you should see a change in operation.
There is a good discussion of this behavior in the following SO post (Public variables are not REALLY public in VBA in Forms).

Delegate function to return value

I am trying to get value from the delegate function. Basically I am trying to get the richboxtext line length from delegate function.
Here is my function
Private Delegate Function getrichlengthmain(ByVal TB As RichTextBox) As String
Private Function getrichlenghtdele(ByVal TB As RichTextBox) As string
Return TB.Lines.Length
End Function
And I am calling it by
Dim d As getrichlengthmain
d = AddressOf getrichlenghtdele
dim returnvalue as string
returnvalue = d.BeginInvoke(FstList,nothing,nothing)
2 problems in this code
1st problem
when I change the code from "returnvalue = d.BeginInvoke(FstList,nothing,nothing)" to "d.BeginInvoke(FstList,nothing,nothing)"
The cross-thread error popout while debuiging
2nd problem
How do I get the value from the function without getting any cross thread error.
Very thanks for your time and thanks in advance for solving it.
You are experiencing an error because the control you are trying to access was created on a different thread from the one you are accessing it on. This is a common mistake when developing threaded UI applications in .Net.
There are (at least) two ways to tackle the problem you have, the lazy way and the correct way. To solve this the lazy way, you simply stop the check for illegal cross-threading calls to controls from taking place by including this line of code somewhere in your UI component:
Control.CheckForIllegalCrossThreadCalls = False
A better way to deal with the problem is to ensure you code executes on the correct thread (therefore maintaining thread safety). One method of accomplishing this is described here.

is there a better way of retrieving my settings?

I'm not an IT professional so apologies if I've missed something obvious.
When writing a program I add a class SettingsIni that reads a text file of keys and values. I find this method really flexible as settings can be added or changed without altering any code, regardless of what application I have attached it to.
Here's the main code.
Public Shared Sub Load()
Using settingsReader As StreamReader = New StreamReader(System.AppDomain.CurrentDomain.BaseDirectory & "settings.ini")
Do While settingsReader.Peek > -1
Dim line As String = settingsReader.ReadLine
Dim keysAndValues() As String = line.Split("="c)
settingsTable.Add(keysAndValues(0).Trim, keysAndValues(1).Trim)
Loop
End Using
End Sub
Public Shared Function GetValue(ByVal key As String)
Dim value As String = settingsTable(key)
Return value
End Function
This allows you to use a setting within your code by calling the SettingsIni.GetValue method.
For example:
watcher = New FileSystemWatcher(SettingsIni.GetValue("inputDir"), "*" & SettingsIni.GetValue("extn")).
I find this makes my code esay to read.
My problem is the values in this case, inputDir and extn, are typed freehand and not checked by intellisense. I'm always worried that I may make a typo in an infrequently used branch of an application and miss it during testing.
Is there a best practice method for retrieving settings? or a way around these unchecked freehand typed values?
A best practice for your code example would be to use Constants for the possible settings.
Class Settings
Const inputDir as String = "inputDir"
Const extn as String = "extn"
End Class
watcher = New FileSystemWatcher(SettingsIni.GetValue(Settings.inputDir), "*" & SettingsIni.GetValue(Settings.extn))
I assume you are using VB.NET?
If so, there is the handy "Settings"-menu under "my project". It offers a way to store the settings for your program and retrieve them via "my.settings.YOURKEY". The advantage is, that type securtiy is enforced on this level.
Additionally, you can also store "resources" almost the same way - but resources are better suited for strings / pictures etc. But they are expecially good if you want to translate your program.
As for your current problem:
Store the path in the settings, this way you do not need to change alll your code immidiately but you can use your system and never misspell anything.
If it's a number you could do these 3 things:
Check if is numeric - using IsNumeric function
Check if it is whole number - using Int function, like: if Int(number)=number
Check for the valid range, like: if number>=lowerbound and number<=upperbound
It totally depends on you. You are the one to check almost all the things inside quotes, not the intellisense.
But you still use Try-Catch block:
Try
Dim value As String = settingsTable(key)
Return value
Catch ex As Exception
MsgBox(ex.ToString)
Return ""
End Try
So you will get an message box if you are trying to access a non-existing setting that you may have mistyped.