Saving Database issue - vb.net

So basically, I believe I am using the correct code yet the database will still not update. It will work for the current session, however, when I stop and restart the program, it appears that the data has not been updated in the database.
The really interesting part is that I am using the same method to update the database elsewhere, which when used and session restarted, the database has been updated.
p.s. I also have the same adapters and binding sources set up etc on both forms
I am so confused, help pls
Code that I believe is correct but is not working: (updating on another form so I have one place where all forms update hence FRMMain. etc)
Private Sub btnConfirm_Click(sender As Object, e As EventArgs) Handles btnConfirm.Click
Dim CurrentPoints As Integer
Dim UpdatedPoints As Integer
CurrentPoints = FRMMain.MyDBDataSet.Tables("TBLPupil").Rows(looopcount)(15)
UpdatedPoints = CurrentPoints + stfPoints
FRMMain.MyDBDataSet.Tables("TBLPupil").Rows(looopcount)(15) = UpdatedPoints
FRMMain.TBLPupilTableAdapter.Update(MyDBDataSet.TBLPupil)
FRMMain.TBLPupilTableAdapter.Fill(MyDBDataSet.TBLPupil)
End Sub
Code that I am using in another form that that DOES work:
Private Sub BtnYes_Click(sender As Object, e As EventArgs) Handles BtnYes.Click
Dim Points As Integer = FRMPupil.Pointss
Dim Cost As Integer = FRMPupil.RewardCost
Points = Points - Cost
FRMPupil.LePoints = Points
MyDBDataSet.Tables("TBLPupil").Rows(FRMLogin.DBLocation)(15) = Points
FRMMain.TBLPupilTableAdapter.Update(MyDBDataSet.TBLPupil)
FRMMain.TBLPupilTableAdapter.Fill(MyDBDataSet.TBLPupil)
Me.Hide()
End Sub

My code is correct but is not working.
No, if it is not working, then it is not correct!
There are different things you can do: DRY, Dont Repeat Yourself. You are repeating the code for updating points at several places in your code. This is error prone. Write it once and re-use it, e.g. by applying the the Repository Pattern. It makes it easier to detect errors and correct them. It allows you to re-use code that has already been tested in other scenarios (on another form).
Debug, debug, debug. Place breakpoints in the not working methods and see what happens. Do all the variables have the expected values? E.g., does looopcount have the same value as FRMLogin.DBLocation? There must be a difference somewhere. See: Navigating through Code with the Debugger or the more recent article Debug your Hello World application with Visual Studio 2017.

Related

Microsoft Project VBA to update Custom field on task change

I have been wracking my brain trying to work out how to write a small piece of code that will activate only when particular fields at a task level have been modified.
I tried to make this code work at the project change level with a for each loop and select cases but that lags the whole program and still doesn't give me the result I need. I also tried to make it work when run manually with a for each loop and select cases or a bunch of If statements, but again, it can't tell me which field changed, but it can highlight a discrepancy between two fields.
The goal is to have a change log field (Text10) that auto updates based on the field that is modified and the date of the change. I only care about 4 fields changing (Date1, Date2, Date3, Date4).
e.g. If [Date1] is modified, Text10 = "Date1 modified 10/11/21"
Note: If 2 fields are modified, I would be happy enough with just listing the last one.
I was hoping there was some sort of "On Change, If Target = xxx" but I have not been able to find anything like that.
I also tried implementing the code as defined here >> Microsoft Documents: Project.Change Event but I am unclear what this is supposed to do and couldn't actually see it doing anything / I never got the message box I believe was supposed to appear.
I am using Microsoft Project Standard 2019.
After much research and trial and error, I ended up solving this.
To get it working, I added a Class Module and ran a piece of code on open to initialize it. This essentially tells Project to start watching for events. I then use the "Field" variant to fill the field name amongst the text string and "NewVal" variant to fill the result. This was an easy solution in the end. The code I found that worked is below:
In Class Module "cm_Events"
Public WithEvents MyMSPApp As MSProject.Application
Private Sub Class_Initialize()
Set MyMSPApp = Application
End Sub
Private Sub MyMSPApp_ProjectBeforeTaskChange(ByVal tsk As Task, ByVal Field As PjField, ByVal NewVal As Variant, Cancel As Boolean)
'What you want the code to do
End Sub
In Module "m_Events"
Public oMSPEvents As New cm_Events
Sub StartEvents()
Set oMSPEvents.MyMSPApp = MSProject.Application
End Sub
In ThisProject code
Private Sub Project_Open(ByVal pj As Project)
Call m_Events.StartEvents
End Sub

How to update a group of combo boxes using Loops

I have a form with combo boxes (cmbPort#) to select up to 8 serial ports. I want to first clear the item list for each, populate them with currently available system ports, and then add the option "Off" to each list. Finally, to set each combo box according to defaults saved in string spName(). I created a GroupBox (gBox1) and dragged each cmbPort onto it but I'm not sure how to reference the controls on it. I'm using VB 2015.
Can you help with VB.NET code to use loops ("For Each" or similar) to do this more efficiently?
Private Sub frmProp_Load(sender As Object, e As EventArgs) Handles MyBase.Load
cmbPort1.Items.Clear()
...
cmbPort8.Items.Clear()
For Each sp As String In My.Computer.Ports.SerialPortNames
cmbPort1.Items.Add(sp)
...
cmbPort8.Items.Add(sp)
Next
cmbPort1.Items.Add("Off")
...
cmbPort8.Items.Add("Off")
cmbPort1.Text = spName(1)
...
cmbPort8.Text = spName(8)
End Sub
Loops are an incredibly useful tool to master. I pitched here some code so you can get the idea, but I was working out of IDE so you might have to apply some fixes to this code to make it work as you want it to.
The main idea is that you shouldn't have to write a line more than once. If you multiply the same operation on several lines of code, you create potential problems for the future. Loops and subs are really helpful to prevent this kind of issues.
Private Sub frmProp_Load(sender As Object, e As EventArgs) Handles MyBase.Load
'This is for later
Dim cmbIndex As Integer = 1
'You basically do the same operations for every Combobox in your list, son only one loop needed
For Each cmbPort As ComboBox In {cmbPort1, cmbPort2, cmbPort3 [...] cmbPort8} 'this is a way to declare an array
'Clear
cmbPort.Items.Clear()
'Add SerialPortNames
For Each sp As String In My.Computer.Ports.SerialPortNames
cmbPort.Items.Add(sp)
Next
'Add "Off"
cmbPort.Items.Add("Off")
'This last one is a little bit trickier because you want to match numbers
'This is the place where you get errors when something doesn't go as planned
'If you need to keep it inside the loop here's a way to achieve that, but honestly I would't do that
'Instead I would suggest that you take this part out of the loop and do it manually
If spName(cmbIndex) IsNot Nothing Then cmbPort.Text = spName(cmbIndex)
cmbIndex += 1
Next
End Sub
You shouldn't consider efficiency into this equation, as this operation will not be called all the time, only on load. I mean: you should always do things in the best way you can, but optimization is sometimes the enemy of good, readable code.

Setting the value of a variable in Visual BASIC

Hi i'm new in programming world and I've started my programming by Visual BASIC. I'm trying to set a value of a variable through the program closing event and load the same value in program load event. As example:
At first I tried:
Dim Age as Integer
Private Sub Form1_FormClosing(sender As Object, e As FormClosingEventArgs) Handles Me.FormClosing
Age = 50
End Sub
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Textbox1.text = Age
End Sub
But when I close the program and restart it, it resets to zero.
Next I tried "Settings" from properties but if I move my program from one location to another then it also resets everything.
Finally I tried Stream readers and writers to catch the final value but for this I had to attach some text files to the programs which I don't want. Can anyone help me how to solve the following problem with custom class libraries or by something else?
All the variables that you have are run time variables. What that means is it will only have value till your program is running.
If you want to store the data taken from user, you store it in database. You can use any kind of database and connect it to your program, store everything in there. You can also retrieve the values from database to use in system when you restart your program.
If you are new to programming and trying to learn visual basic, start with basic concepts or pick up a book that start with basics. Once you know the basics of programming, you can read about connecting program to database.
The value of age is never going to remain static when the application is shut down unless you keep it in the application settings or some sort of flat file, database etc. The initial value could be set in the application when the form opens or from at static value in application settings, but unless you store the value somewhere other than memory, it will not persist.
What you can do is create a form called module1.vb . in this form declare and set your variables . . .
Example
Public Age As Integer = 50

NullReferenceException and/or variable usage before it has been assigned

I am new to .net and am doing my best to understand the Nuances (or Nuisance). I am trying to print text on a form. I did find many examples of the Graphics class, DrawString() etc. Unfortunately, I cannot get any of them to work. The stumbling block for me seems to be the error “NullReferenceException” and/or the warning “variable usage before it has been assigned”. One example found at "http://msdn.microsoft.com/en-US/library/76c5db29(v=vs.80).aspx?cs-save-lang=1&cs-lang=vb#code-snippet-1". vs2005 displays the warning "Variable 'myE' is used before it has been assigned a value. A null referene excpetion could result at runtime and sure enough when I run a NullReferenceException is thrown at "e.Graphics.DrawString(drawString, drawFont, drawBrush, drawPoint)" How do I fix this?
Public Class Form1
Public Sub DrawStringPointF(ByVal e As PaintEventArgs)
Dim drawString As [String] = "Sample Text"
Dim drawFont As New Font("Arial", 16)
Dim drawBrush As New SolidBrush(Color.Black)
Dim drawPoint As New PointF(150.0F, 150.0F)
e.Graphics.DrawString(drawString, drawFont,drawBrush, drawPoint)
End Sub
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim myE As PaintEventArgs
DrawStringPointF(myE)
End Sub
End Class
You can't do that.
Instead, handle the Paint event and draw everything you need to.
To trigger a redraw, call Invalidate().
Your question is broader than your problem.
You're asking what a null reference exception is; this question has been answered many times elsewhere. A NRE (NullReferenceException) is referring to a variable that isn't defined at all
We can think about memory as being a vast, open parking lot. When you define a variable, using a statement like this,
Dim myObject as Integer
... you're claiming one or more of the parking spaces in the parking lot. However, all you've done is declare that this spot is yours, but not what goes in it. To give it a value, simply use the equals operator.
myObject = 100
Simple objects, known as primitives, like strings, numbers and characters, have an implied value when they're not defined. For example, integers are assumed to be zero if they have no value.
In your program, when you get a NRE, mouse over each argument in the function and the object that the function is being called from. If any of them claim to have a value of Nothing, there's your problem. You've reserved space for your object, but not yet given it a value.
As SLaks said, your specific problem is related to how you're calling the method, but without a strong understanding of what Nothing means, it may not correctly address the underlying question>
Finally, let's look at code that's specifically yours. You call
Dim myE as PaintEventArgs.
In this statement, you have reserved space in the memory- that is to say, claimed a parking space we talked about earlier. However, it does NOT have a value! It's empty. The program cannot function properly because you're telling it to perform an action on something that doesn't exist. To fix it, use the New operator. When making new objects, first reserve them in memory (Dim actually stands for "define in memory") and then give them a value with the New operator. You'd see something like this:
Dim myObj As Object
myObj = New Object()
You can also do it inline:
Dim myObj As Object = New Object()
When you try to do that with your PaintEventArgs, you'll see that that's quite impossible. PaintEventArgs requires information that's taken from a Windows Form control. That method you've written needs to handle an event. This post is too long as it is, so hopefully someone else can explain events and how they're related to methods. Basically, each control (textbox, image, or even the picture itself) raises an event every time it "paints" to the screen. You can "handle" that event; or do actions when it occurs, by doing this:
Public Sub OnPaint(sender as Object, e as PaintEventArgs) Handles myControl.OnPaint
You are declaring that whenever myControl raises an event for OnPaint, it will call this method, with arguments provided from the control.
You cannot simply substitute the required arguments from elsewhere. In order for it to work properly, the event arguments must be passed from the control that you wish to paint to.
I hope this helps. Please let me know if I've been unclear.

vb.net - redirect output to form textbox

I am trying to read/use the output from a python program in my vb.net project so far I'm not getting any results. What I'd like to see is the python program run (just by itself first) and all of the output get redirected into a textbox.
I've looked at some other posts about this, but I'm either missing something or not understanding something, as all I'm getting is blank output.
Public Class Form1
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Dim PythonPath = "C:\Python27\"
Dim strPath As String = Application.StartupPath
MessageBox.Show(PythonPath & "python.exe """ & strPath & "\Resources\import_logs.py"" ")
Dim start_info As New ProcessStartInfo(TextBox1.Text)
' Make the process and set its start information.
Dim process As New Process()
process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden
process.StartInfo.FileName = PythonPath & "\python.exe"
process.StartInfo.Arguments = """" & strPath & "\resources\import_logs.py"""""
process.StartInfo.UseShellExecute = False
process.StartInfo.CreateNoWindow = True
process.StartInfo.RedirectStandardOutput = True
'process.StartInfo.RedirectStandardError = True
AddHandler process.OutputDataReceived, AddressOf proccess_OutputDataReceived
process.Start()
process.BeginOutputReadLine()
End Sub
Public Sub proccess_OutputDataReceived(ByVal sender As Object, ByVal e As DataReceivedEventArgs)
On Error Resume Next
' output will be in string e.Data
' modify TextBox.Text here
'Server_Logs.Text = e.Data ` Does not display anything in textbox
MsgBox(e.Data) 'It works but I want output in text box field
End Sub
End Class
Eventually I'm going to pass arguments to the python script and I'd like to get feedback that I can then use (insert error into a database, email when it's done, etc), so I'd like it to capture the process while running and not just a data dump at the end.
Any help would be much appreciated.
First things first—it's no wonder you aren't sure what's wrong with your code, you're silencing all errors that could possibly help you to diagnose it. That's the only purpose of On Error Resume Next in VB.NET. That unstructured error handling was included only for backwards compatibility with the pre-.NET versions of VB and it's time to forget that it ever existed. You certainly don't want to use it in code. (I would say "in code that you're debugging", but all code is a potential candidate for debugging and ignoring errors is just dumb.)
Anyway, on to the specific problem. We know that the call to MsgBox works, but it doesn't work right when you start interacting with controls on your form. So something is falling apart there.
It turns out that the OutputDataReceived event is raised on an entirely different thread, a different one than was used to create the process and a different one than is running your application's UI. It actually just retrieves a thread from the system thread pool.
And that's where the problem lies: you cannot manipulate UI objects on a thread other than the one that created those objects (at least not without jumping through some hoops), which is precisely what your code tries to do here. In fact, you're probably swallowing an exception that would have rather obtusely informed you of this situation.
The simple fix is to set the SynchronizingObject property of the Process class to one of your UI components (like the form, or the specific control you want to output to). This forces all event handlers to execute on the same thread that created that component. At that point, your code should work fine, because you're not trying to do any cross-thread UI access. (Message boxes are not vulnerable to this because any thread can display a message box. You're not trying to access an existing UI object that is bound to another thread.)
Alternatively, you could handle the marshalling yourself in the event handler method through the use of delegates and the BeginInvoke method, but this seems like unnecessary work to me.