Is there any way to save the checkbox's state of a program made in visual basic 6.0 - visual-studio

I have made(designed) a program in Visual Basic 6.0,it consists of around 100 checkboxes ,the program does not require any code just a yes/no checkbox type program , but I want to save the checkbox state ,so that if a check box is in yes state then after restarting the program it's state remains conserved .
I have read about
My.Settings.Save but I dont know how to use it , I am using Visual Basic 6.0.

Create keys in Registry, save each checkbox value on their checkbox Change event and load the status of each of them in the form Initialize event code.
Option Explicit
Private Const MyApp As String = "My Own App" 'put here your application name
Private Const Sett As String = "Settings"
Private Sub CheckBox1_Change()
Dim chkBoxStatus As String
chkBoxStatus = "CheckBox1"
If Me.CheckBox1.value = True Then
SaveSetting MyApp, Sett, chkBoxStatus, CStr(True)
Else
SaveSetting MyApp, Sett, chkBoxStatus, CStr(False)
End If
End Sub
Do the same for all your check boxes.
And then:
Private Sub UserForm_Initialize() 'I do not remember well if VB6 uses Form_Initialize... You must adapt it accordingly.
Dim regValue As String
regValue = GetSetting(MyApp, Sett, "CheckBox1", "No value")
If regValue <> "No value" Then Me.CheckBox1.value = CBool(regValue)
'do the same for all checkboxes in discussion
'.
'.
End Sub
"No value" is returned if no value has been set in Registry (yet)...

Well, I would have made all checkboxes a control array and would save their sate in a text file in some hidden place, like C:\Users\UserName\AppData\Local. It would be a pretty small code.

Related

Expected Function or variable vb6.0

Hello i am coding in Visual Basic 6.0 and i have this error, i am trying to make a button inserting data in database.
Expected Function or variable
This is my code
Private Sub Command1_Click()
With ConString.Recordset.AddNew
!ID = txtID
!Emri = txtEmri
!Mbiemri = txtMbiemri
!Datelindja = txtData
!Telefon = !txtTelefon
!Gjinia = gender
!Punesuar = job
!Martese = cmbMartese
!Vendlindja = txtVendlindje
End With
End Sub
txtID is textbox
txtEmri is textbox
txtMbiemri is textbox
txtData is date picker
txtTelefon is textbox
gender is a string that takes value if a radio button is clicked
job is an integer if a checkbox is clicked
cmbMartese is combo box
txtVendlindje is textbox
Thank you in advance.
#JohnEason gave you the right answer. But there's another error in the line !Telefon = !txtTelefon, if I'm not mistaken. It should read !Telefon = txtTelefon, i.e. without the exclamation mark in front of txtTelefon.
I'm also not a big fan of that coding style. I prefer to not rely on default properties, but instead "spell out" the whole term, e.g.
With ConString.Recordset
.AddNew
!ID = txtID.Text
!Emri = txtEmri.Text
!Mbiemri = txtMbiemri.Text
!Datelindja = txtData.Text
!Telefon = txtTelefon.Text
' Since VB6 doesn't provide Intellisense for variables, I prefer to use some
' kind of hungarian notation for variable names, in this case sGender or strGender for a string variable
!Gjinia = gender
' Same here: iJob or intJob for an integer variable
!Punesuar = job
' You need to specify that you want the selected item of a combobox
!Martese = cmbMartese.List(cmbMartese.ListIndex)
!Vendlindja = txtVendlindje.Text
' If you're done setting column values and don't do so somewhere else,
' you also need to add a .Update statement here in order to finish the
' .AddNew action and actually persist the data to the database.
' .Update
End With
End Sub
As pointed out below by #JohnEason, there's also potentially an .Update statement missing within the With/End With block

Is there a built in MS Access VBA Event to simplify Data Verification and SetFocus

Bit of a rookie issue here. How do you deal with data verification using Access Events? The problem is that when I use SetFocus to return the Cursor to the field with the errant data, Access goes through the _Exit and/or _LostFocus Events of the next Control in the Tab Order. If those include data validation procedures, the desired SetFocus is circumvented.
Using techturtles answer, I came up with this "solution" (read "hack").
Private Sub ServicingEmployee_LostFocus() 'Check data validity
If dataEntryCancelled Then Exit Sub
Dim cntrl As Control
Set cntrl = Me.ServicingEmployee
Dim myResponse As Integer
If IsNull(cntrl.Value) Then
myResponse = MsgBox("This field cannot be left blank.", vbOKOnly, "Enter Date Collected")
dataErrorInPreviousField = True
**'Next line sets a Public Control**
Set controlWithDataEntryError = Me.ServicingEmployee
End If
End Sub
Private Sub Client_GotFocus() '**Check for data Error in previous Control according to Tab Order**
If dataErrorInPreviousField Then Call dataErrorProc
End Sub
Public Sub dataErrorProc()
With controlWithDataEntryError
.SetFocus
.SelStart = 0
.SelLength = Len(.Text)
End With
dataErrorInPreviousField = False
End Sub
Private Sub Client_Exit(Cancel As Integer) '**Example of Bypassing _Exit Event**
If dataEntryCancelled Or dataErrorInPreviousField Then Exit Sub
.
...
End Sub
My question is this: Is there a simpler way to accomplish this?
First, I would strongly encourage you to add table constraints in addition to your form validation, if you haven't already done so. Assuming this form is tied to a table in Access, just make sure the ServicingEmployee field (in the table) is set to required. That way, you have another level of validation making sure the field has a value.
For form validation, you can use either the form's or control's BeforeUpdate event. If you use the form's event, you only have to run the check once.
I would also suggest having a separate function (within the form) to check validity. Something like this (here, I'm using a form tied to an Employees table, with a first name and last field which should both be non-null):
Private Function isFormValid() As Boolean
' we start off assuming form is valid
isFormValid = True
If IsNull(Me.txtFirstName) Then
MsgBox "First name cannot be blank", vbOKOnly
Me.txtFirstName.SetFocus
isFormValid = False
ElseIf IsNull(Me.txtLastName) Then
MsgBox "Last name cannot be blank", vbOKOnly
Me.txtLastName.SetFocus
isFormValid = False
End If
End Function
Private Sub Form_BeforeUpdate(Cancel As Integer)
If Not isFormValid Then
Cancel = 1
End If
End Sub

how to send contents of a textbox in vb6 to a notepad document

I am trying to send the data inserted into a textbox into a notepad document so that the data can be held for future reference, as i am trying to create an assessment date reminder as i am a student.
But whenever i try to send the data with this code by writing data = "txtAssign_Name, txtAssign_Due" when i check the notepad after running the program, all that is in the document is txtAssign_Name, txtAssign_Due.
Private Sub Form_Load()
Dim Data As String
txtAssign_Name.Text = ""
txtAssign_Due.Text = ""
Data = ""
Open "F:\Personal\date calender test - Copy\test.txt" For Output As #1
Print #1, Data
Close #1
End Sub
Try this:
Data = txtAssign_Name.Text & ", " & txtAssign_Due.Text
(In the lines above, you will want to NOT set those values to "")
Note - using the built in VB6 writing to text files will result in your output being formated in a way so that VB6 can read it back in again. So all strings will have quotes aroud them, other values are displayed in a variety of odd ways, commas seperate all values.
If the output text file is desired to be primarily for human use, then I find using the richtextbox control a better way of creating the file. Add it from Project -> Components -> Controls -> Microsoft Rich Textbox Control 6.0
Add the Rich text box to your form (you can set visible = false if you don't want users to see it). Add your data to it something like this:
RichTextBox1.text = txtAssingn_Name.text & ", " & txt_Assing_Due.text
' If you need to add more things, add them on to the end like this
RichTextBox1.text = richtextbox1.text & vbcrlf & "More text on the next line"
Then, when all the data is added, you just do this
RichTextBox1.SaveFile "C:\Test.txt", rtfText
rtfText is a visual basic constant, that tells the RTB to save as plain text. The alterntaive is rtfRTF. You can learn more about the RTB on MSDN
OK, so a comment above states that you want to be able to read the data back into VB.
The code as it shown in the question will just output a blank text file, as the variable Data is set to "", so that is all that will be output.
What you need is something like this
private Sub SaveData()
dim SaveFile as integer
SaveFile = Freefile ' This gets a file number not currently in use
Open "F:\Personal\date calender test - Copy\test.txt" For Output As #Savefile
write #SaveFile, txtAssign_Name.Text, txtAssign_Due.Text
close #savefile
end sub
And call SaveData in the appropriate place. NOT form load, as the user won't have entered anything at this point. Either after the user has pressed a button, or on Form_Unload if you want it to autosave on form close.
To populate your form again, something like this
private sub LoadData()
dim LoadFile as integer
dim StringData as string
loadfile = freefile
Open "F:\Personal\date calender test - Copy\test.txt" For Input As #loadfile
input #loadfile, StringData
txtAssign_Name.Text = StringData
input #loadfile, StringData
txtAssign_Name.Text = stringdata
close #loadfile
end sub
You should also add error handing whenever working with files. VB6 is quite particular and its very easy to throw an exception when dealing with files.

Change word when entered in MS Access?

From my understanding, validation rules can't CHANGE things- I tried the replace fn in the validation rule and it did nothing but wouldn't let me enter the word I wanted to change.
I want 'asst' to change to 'assistant' and 'prof' to change to 'professor' when entered in Access. Any ideas on how to do this?
Been looking for an hour and haven't found anything- any input appreciated!
I would implement an AfterUpdate event on the textbox you are validating. You can click the Event tab of the TextBox properties window to create the event.
Private Sub txtMyTextBox_AfterUpdate()
If Me!txtMyTextBox = "prof" Then Me!txtMyTextBox = "Professor"
End Sub
Or something like
Private Sub txtMyTextBox_AfterUpdate()
If InStr(1, Me!txtMyTextBox, "prof ") <> 0 Then Me!txtMyTextBox = Replace(Me!txtMyTextBox, "prof ", "Professor ")
End Sub

How to gracefully exit from the middle of a nested subroutine when user cancels?

(I'm using VB6 but I imagine this comes up in most other languages.)
I've got a GUI button that calls a routine that takes a minute or two to complete. I want impatient users to be able to click on the button a second time to have it gracefully exit out of the routine at any point.
I used a static variable to make this work pretty well (see code below), but I'm cleaning up the project and I want to put the For/Next loop into its own function, since it's required in several different places in the project.
But doing that would break my static flag embedded in the for/next, so I need to make some changes. Before I do something hare-brained with public (global) variables, I thought I'd ask what other (smarter, perhaps actually CS educated) people have done when faced with this problem.
So basically my question is how do I replicate this:
Private Sub DoSomething_Click()
Static ExitThisSub As Boolean ' Needed for graceful exit
If DoSomething.Caption = "Click To Stop Doing Something" Then
ExitThisSub = False ' this is the first time we've entered this sub
Else ' We've re-entered this routine (user clicked on button to stop it)
ExitThisSub = True ' Set this so we'll see it when we exit this re-entry
Exit Sub '
End If
DoSomething.Caption = "Click To Stop Doing Something"
For i = 0 To ReallyBigNumber
Call DoingSomethingSomewhatTimeConsuming
If ExitThisSub = True Then GoTo ExitThisSubNow
DoEvents
Next
' The next line was missing from my original example,
' prompting appropriate comments
DoSomething.Caption = "Click To Do Something"
Exit Sub
ExitThisSubNow:
ExitThisSub = False ' clear this so we can reenter later
DoSomething.Caption = "Click To Do Something"
End Sub
When I move the for/next loop to its own function?
I'm thinking I'll change ExitThisSub to a public variable QuitDoingSoManyLongCalculations that will exit the new for/next sub and then the DoSomething_Click in the same way.
But I always feel like an amateur (which I am) when I use global variables - is there a more elegant solution?
Well you could declare the variable at module level in the forms as private.
That is not a global but a module level variable.
Then you could pass it to the function you create and check it in the function.
But be careful with the DoEvents. It basically means allow the windows message loop to process messages. This means that not only can the user click your button again, they can close the form and do other things. So when you are in this loop you'll need to set a module level variable anyway as you'll need to check for it in a QueryUnload of the form and in any event handlers.
You can also use the Tag property of the control itself to store a flag of sorts. But I don't consider that more elegant.
I also prefer to use two different buttons. Just hide one and show the other. That way your cancel code and run code are separated in different event handlers.
To expand on my answer here is some sample code that handles the unloading aspect.
Here if you stop via the x it prompts you. If you kill via task manager, it dies gracefully.
Option Explicit
Private Enum StopFlag
NotSet = 0
StopNow = 1
StopExit = 2
End Enum
Private m_lngStopFlag As StopFlag
Private m_blnProcessing As Boolean
Private Sub cmdGo_Click()
Dim lngIndex As Long
Dim strTemp As String
m_lngStopFlag = StopFlag.NotSet
m_blnProcessing = True
cmdStop.Visible = True
cmdGo.Visible = False
For lngIndex = 1 To 99999999
' check stop flag
Select Case m_lngStopFlag
Case StopFlag.StopNow
MsgBox "Stopping - Last Number Was " & strTemp
Exit For
Case StopFlag.StopExit
m_blnProcessing = False
End
End Select
' do your processing
strTemp = CStr(lngIndex)
' let message loop process messages
DoEvents
Next lngIndex
m_lngStopFlag = StopFlag.NotSet
m_blnProcessing = False
cmdGo.Visible = True
cmdStop.Visible = False
End Sub
Private Sub cmdStop_Click()
m_lngStopFlag = StopFlag.StopNow
End Sub
Private Sub Form_Load()
m_blnProcessing = False
End Sub
Private Sub Form_QueryUnload(Cancel As Integer, UnloadMode As Integer)
Select Case UnloadMode
Case vbFormControlMenu, vbFormCode
If m_blnProcessing Then
Cancel = True
If MsgBox("Unload Attempted - Cancel Running Process?", vbOKCancel + vbDefaultButton1 + vbQuestion, "Test") = vbOK Then
m_lngStopFlag = StopFlag.StopExit
End If
End If
Case Else
m_lngStopFlag = StopFlag.StopExit
Cancel = True
End Select
End Sub
You need some kind of shared variable so that your for loop and your button can communicate. I'd put the for loop (and its associated code) in a command object. My VB is rusty but I think you can declare Modules with their own 'global' variables and functions. You can move all the code into a module and just check the global variable as you do now.
My main concern with the code sample you've posted has nothing to do with user-cancelling but rather everything else: you check your running state by reading the button text instead of doing that the other way around (set the button text because of the running state, which should be stored in a variable); you use a GOTO to exit your for loop instead of a break (does VB have breaks?) and you put your cleanup code outside the normal flow, when it seems to me that it could be run regardless of whether the user cancelled or not.
One possible alternative is to offload your heavy-work function to a new Thread. Then you can either directly kill that thread if the user wants to cancel, or you can send a message to the thread.
Toggling via button name, as you are doing above, is a pretty commonly seen trick though, and pretty safe if you only have a couple of button states.
I've always used a global boolean variable like bUserPressedCancel, along with DoEvents within a loop. Elegant, smelegant, it works.
I agree with Mr Shiny that testing against the value of a caption is not a great idea. If you change the text on the button in the designer, you'll break the code. Better not to rely on the wording of the text for your code to work.
Works until you need to do localization or any other thing else that require the UI to be changed independently of the logic. I would use the Tag property or a private module level variable . Then you can vary the caption independently from the logic.
If it was me I'd use 2 buttons - one to GO and one to STOP. The STOP button is made visible when you click GO. The Click event for STOP simply hides itself - that's it.
Your loop can then simply check to see if the STOP button is still visible. If it's not, that means it was clicked and you should break out.
Your controls are static objects with form scope...

Resources