int array to returning to previous record - vba

I have a standard form which displays information based on a partID. The form has a subform showing ancillaries of the part where on double click will take you to that part number (code snippet below). var_lastPartID is a global long variable which records the current ID so upon pressing a return button will take you back to the previous record. However, as this can only store 1 value at a time I imagine the best way would to be to store an array of long/int whereby upon the double click the current ID is stored. When you click return it will take the last value added and take you to that record then delete that record, so that the next time you click return it will take you to the next record. However, my experience with VBA is very limited and I have not used them before. Please could someone explain the syntax of how I could achieve this?
Private Sub childPart_DblClick(Cancel As Integer)
var_lastPartID = Forms![Part]![part_ID].Value
Forms("Part").Recordset.FindFirst ("part_ID = " & childPart)
End Sub

Ok, so you have a parent form, and then a sub form.
You click on a row in the sub form. You want the parent form to JUMP to this record. But as you may well do this several times, then you want on the main form some kind of “back” or “previous” button. When you click on this back button, then you want the previous ID that you jumped to occur.
Ok, the way to drive this and have a next/previous set of buttons that traverse the records that you looked at, worked on, and clicked on?
Ok, in the main form, at the code module level, create a pointer, and a collection, and a routine like this:
Option Compare Database
Option Explicit
Dim intListPosition As Integer
Dim colRecords As New Collection
Public Sub AddAndJump(MyID As Long)
' add this new ID to the list
intListPosition = intListPosition + 1
colRecords.Add MyID, CStr(intListPosition)
' now jump (move) to this record
Me.Recordset.FindFirst "ID = " & MyID
End Sub
Public Sub BackOne()
' call this code from your back buttion
' go to previous record
If intListPosition > 1 Then
intListPosition = intListPosition - 1
Me.Recordset.FindFirst "ID = " & colRecords.Item(CStr(intListPosition))
End If
End Sub
Public Sub ForwardOne()
'call this code from your forward buttion
If intListPosition < colRecords.Count Then
intListPosition = intListPosition + 1
Me.Recordset.FindFirst "ID = " & colRecords.Item(CStr(intListPosition))
End If
End Sub
Private Sub cmdBack_Click()
BackOne
End Sub
Private Sub cmdNext_Click()
ForwardOne
End Sub
So the above goes in the main form.
In my "sample" code, I used ID, you have to change that to part_id
Now, you button code in the sub form is going to be "similar" to what you have, but you can now use this:
Call Me.Parent.AddAndJump(Me.ID)
So, the above will now allow a next/back button on the top form, as you click away and select the items from the lower form (the sub form), then the list of "id" will be built up, and the buttons for next/prev will work.

Related

Access 2013 - Save Value from Textbox and display again when form is opened after close

I want to save a value from textbox in a string for example and display it again when the form get's openend.
I have two textboxes PriceRangeOne and PriceRangeTwo .. The user enter here for example 20 and 40
The problem i have is that when the user switches between Form and Report the values in this textboxes are beeing deleted. How can i save them?
I tried adding a sourcecontrol to the fields but had name errors eventhough i used different names.
I tried adding this to on change and retrieve it in an onload
Dim eingabe As String = textBox1.Text or .Value
Still didn't worked. Does anyone know a way to do this?
Typically, the most efficient and reliable way to do this is to have some form auto-open when the database is opened. It could be a dashboard, or just some form with nothing else on it. Whatever you use, launch it when the database opens and then minimize it. Now you have a form that's always open, as long as the application is open. Add a couple of textboxes to this form/dashboard.
When you close your form referenced in this question, write the values of PriceRangeOne and PriceRangeTwo to the textboxes on the form I described above. Then, when you open a new form or report, you can reference the values in those textboxes. Since the form is always open, you can reference these values at any time from any form or report until you close your database.
Solved it with variables.
I declared global variables in my standart module
For example
Public PriceOne As Double
Public PriceTwo As Double
Than i did this in my form in Close() and Open():
Private Sub Form_Close()
PriceOne = Me.Field
PriceTwo = Me.FieldTwo
End Sub
Private Sub Form_Open(Cancel As Integer)
Me.Field = PriceOne
Me.FieldTwo = PriceTwo
End Sub
Works perfect!
Courtesy of How to save the last value of a textbox. | Access World Forums:
Private Sub Form_Close()
'Set the default value for textbox
DoCmd.SetWarnings False
DoCmd.RunSQL "UPDATE table SET table.field = [Forms]![FormName]![Textbox] " & vbCrLf & _
"WHERE (((table.ID)=1));"
DoCmd.SetWarnings True
End Sub
Private Sub Form_Load()
'Load the default value for textbox
Me.Textbox.Value = DLookup("[field]", "[table]", "[ID]=1")
End Sub

Microsoft Access applying 1 function to all fields automatically

I have a form that keeps track of assigned patient equipment. I have it set so that any changes made to text fields on the form automatically move down to the "comments" section of the form (this is done so that any changes made are documented in case the user forgets to manually document changes). I have a sub that I wrote that accomplishes this that I am currently calling for every single text field. This works but is messy.
Is there a way to apply the sub to all the fields in one procedure without calling it for every individual field? Code is below, please let me know if I can clarify anything.
Private Sub pPEMoveValue(sField)
'Moves the old field value down to the comments section automatically
Dim sOrigValue As String
Dim sCommentValue As String
sOrigValue = sField
sCommentValue = Nz(mPEComments, "")
Me.mPEComments = sCommentValue & vbNewLine & sOrigValue
End Sub
Private Sub sPEBatCharger_Dirty(Cancel As Integer)
pPEMoveValue (Nz(Me.sPEBatCharger.OldValue, ""))
End Sub
This is the solution I came up with to do what you are looking to do. I took advantage of the MS Access Tag system. You can add tags to your controls so you can sort of "Group" them.
First put the form in design view and adjust the tag for all of the fields you want to record to say "Notes".
Then in the Form's BeforeUpdate even you would add this:
Private Sub Form_BeforeUpdate(Cancel As Integer)
Call FindControlsForComments(Me.Form)
End Sub
Then you would use this function to find any fields that have the "Notes" tag and run it through the function you created:
Public Function FindControlsForComments(frm As Form)
Dim ctrl As Access.Control
For Each ctrl In frm
'If the control is tagged for notes
If ctrl.Tag = "Notes" Then
'If the old value is different than the current value
If Nz(ctrl.OldValue, "") <> Nz(ctrl.Value, "") Then
'Add to comment
Call pPEMoveValue(Nz(ctrl.Value, ""))
End If
End If
Next ctrl
End Function
You may have to adjusted this slightly to work with your system but this has worked well for me.

Opening new form after right click on selected record in continuous form

In my access database before I was using a list box in the form for having list of items and I had below code for opening new form after right click on each selected item in list box.
Private Sub ItemList_MouseUp(Button As Integer, Shift As Integer, X As Single, Y As Single)
Const RIGHTBUTTON = 2
If Button = RIGHTBUTTON Then
DoCmd.OpenForm "frmShortcut_GenerateTask"
DoCmd.MoveSize udtPos.X * mp.TwipsPerPixelX, udtPos.Y * mp.TwipsPerPixelY
End If
End Sub
Now I am using a continuous form instead of list box and I have defined a [isselected) field for selecting each record in continuous form after clicking on that. Now my problem is how I have to write code for right clicking and opening new form.
I used the same code I had used for list box, but it does not work and nothing happened.
Private Sub Form_MouseUp(Button As Integer, Shift As Integer, X As Single, Y As Single)
Const RIGHTBUTTON = 2
If Button = RIGHTBUTTON Then
DoCmd.OpenForm "frmShortcut_GenerateTask"
DoCmd.MoveSize udtPos.X * mp.TwipsPerPixelX, udtPos.Y * mp.TwipsPerPixelY
End If
End Sub
Private Sub P_Click()
On Error Resume Next
Me.IsSelected = Not Me.IsSelected
' Save the status
Me.Dirty = False
' Force conditional highlighting
P_ForceHighLight
' Update display in SF_Selected
Me.Parent("SF_Selected").Requery
ActiveControl.SelLength = 0
On Error GoTo 0
End Sub
I recommend either using a DoubleClick event in all of your textboxes and combos, or else putting a small button at one edge of your continuous form that allows the user to open records. Right-click is going to give you problems (so will labels and image controls) because this event doesn't cause (or ensure) that the Form's internal Recordset Bookmark property is actually moved to the record they right-clicked on. In my experience, only buttons, textboxes, and comboboxes will move the Bookmark to the record the user is trying to select.
To Test this, try putting code at the top of your different routines that shows you what record is selected:
MsgBox "RecordID = " & Me!RecordIDField
If you are consistently getting the correct ID, then your problem has to do with how your opening your new form, passing parameters or arguments, etc.

SetFocus inside a GotFocus procedure initiated by another SetFocus

Objective: Redirect focus from one command button to another using the first's GotFocus procedure.
Context: I have a form-independent procedure in a generic module that, on most forms, sets focus to the NewRecord button after saving the previous record. But on one form, I would like to redirect (based on certain conditions) focus back to the SignRecord button so the user can "sign" a second part of the same record (I may need this for other uses in the future). The target control is enabled and visible and can otherwise be focused and the original control can be focused when the redirect doesn't occur. Reference [2] below implies that this should be possible, though I'm not changing visibility of my controls.
Issue: When the conditions are met to redirect focus in the GotFocus procedure, it redirects as desired but the original (test) SetFocus call throws a "Run-time error '2110', Can't move focus to the control CommandNew".
What I've tried:
Exit Sub after my downstream SetFocus calls.
Call CommandSign.SetFocus in the hopes that it would make it happen outside the previous SetFocus process.
In a module,
Public Sub test()
Forms("TargetForm").CommandNew.SetFocus 'This gets the error '2110'
End Sub
In the 'TargetForm',
Private Sub CommandNew_GotFocus()
If IsNull(textDateTime) Then Exit Sub 'Works as expected
'I can see these two parts work. The framSign value changes
'and CommandSign gets focus
If checPPC And IsNull(textSigID_PPC) And framSign = 2 Then
framSign = 1
CommandSign.SetFocus
ElseIf checDAS And IsNull(textSigID_DAS) And framSign = 1 Then
framSign = 2
CommandSign.SetFocus
End If
End Sub
References:
[1]: SelectNextControl() a bad idea in a GotFocus event?
[2]: http://www.access-programmers.co.uk/forums/showthread.php?t=100071
I think your problem is that the call to Forms("TargetForm").CommandNew.SetFocus doesn't quite seem to, in fact, finish setting the focus to CommandNew until after Private Sub CommandNew_GotFocus() has finished executing. Because you've called another SetFocus before the first SetFocus could finish, there is a conflict that Access seems to be unable to cope with.
Whether or not that is the case, one thing is clear: the way you have your execution plan set up right now is unfortunately not going to work. You might try adding either a global variable or a public variable to each form that determines whether or not you should set your focus to CommandSign after you set the focus to CommandNew.
Ex. TargetForm:
Public boolSetCommandSignFocusInstead As Boolean
Private Sub CommandNew_GotFocus()
If IsNull(textDateTime) Then Exit Sub 'Works as expected
'I can see these two parts work. The framSign value changes
'and CommandSign gets focus
If checPPC And IsNull(textSigID_PPC) And framSign = 2 Then
framSign = 1
boolSetCommandSignFocusInstead = True
ElseIf checDAS And IsNull(textSigID_DAS) And framSign = 1 Then
framSign = 2
boolSetCommandSignFocusInstead = True
Else
boolSetCommandSignFocusInstead = False
End If
End Sub
Module:
Public Sub test()
Forms("TargetForm").CommandNew.SetFocus
If Forms("TargetForm").boolSetCommandSignFocusInstead Then
Forms("TargetForm").CommandSign.SetFocus
End If
End Sub

How to wait for a Visual Basic 2010 form's button-click event to end

In my vb program, I have two forms that work together to allow you to define an almost arbitrary amount of designs. In the first form, there is a two-dimensional array, storing an integer (not important) and an ID class that I defined as a public inner class in another form. Clicking on the "Define ID" button in this form will take you to the next form, where you will define a new ID or edit an old one based off of an index in the array you selected or entered in the first form's combo box, using multiple fields in the second form to define its different aspects. What I want to happen is the first form's code to be suspended as the user defines the ID in the second form, then they click on the Continue button on the second form. After a bit of error-checking, the form either is momentarily hidden (which is how I originally implemented it) or returns the edited ID object, but only if the error-checking does not indicate any input is incorrect. Originally, I simply grabbed the ID by using newForm.curID and set that to its spot in the array, waiting for the user to finish by using newForm.showDialog(), but sometimes the program would return a null exception because I don't think I copy the IDs correctly. Also, though the errors show up for a small amount of time, the Continue button saves the ID regardless of its correctness. Is there a way to manipulate the showDialog to get a result response out of it?
Short version: I need to either return an object of an inner class in one form to an array in a calling form or wait for a form to finish and use the calling form to copy its object, then close the callee form.
First Form's "Define" button method
Private Sub DesignButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles DesignButton.Click
Me.totalCoilBox.Focus() 'calls validating method, makes textbox yellow if invalid'
If totalCoilBox.BackColor = Color.White Then
Dim newForm As New IVD_DesignData 'creates an object of ID called curID as well'
Try
If DesignIDBox.Items.Contains(DesignIDBox.Text) Then 'design exists
set the curID to the one already in the array'
newForm.curID = CGID(Integer.Parse(DesignIDBox.Text), 1)
'set number of coils to new number, if applicable'
CGID(Integer.Parse(DesignIDBox.Text), 0) = Integer.Parse(DesignIDBox.Text)
'show dialog for editing'
newForm.ShowDialog()
'put the (edited) curID back into the array'
CGID(Integer.Parse(DesignIDBox.Text), 1) = newForm.curID
Else 'design does not exist, make a new one
put number of coils into new array spot'
CGID(Integer.Parse(DesignIDBox.Text), 0) = Integer.Parse(totalCoilBox.Text)
'set the design ID to the number of defined IDs plus one'
newForm.curID.designID = Integer.Parse(DesignIDBox.Text)
'show dialog for editing'
newForm.ShowDialog()
'add curID into the array'
CGID(Integer.Parse(DesignIDBox.Text), 1) = newForm.curID
'add that design number to the dropdown box'
DesignIDBox.Items.Add(newForm.curID.ToString())
'increment number of defined designs'
Current_IDBox.Text = Integer.Parse(Current_IDBox.Text) + 1
End If
Catch ex As ArgumentOutOfRangeException 'dropdown box has no elements in it;
do the same as adding a new ID:
put number of coils into new array spot'
CGID(Integer.Parse(DesignIDBox.Text), 0) = Integer.Parse(totalCoilBox.Text)
'set the design ID to the number of defined IDs plus one'
newForm.curID.designID = Integer.Parse(DesignIDBox.Text)
'show dialog for editing'
newForm.showDialog()
'add curID into the array'
CGID(Integer.Parse(DesignIDBox.Text), 1) = newForm.curID
'add that design number to the dropdown box'
DesignIDBox.Items.Add(newForm.curID.ToString())
'increment number of defined designs'
Current_IDBox.Text = Integer.Parse(Current_IDBox.Text) + 1
End Try
DesignIDBox.Text = newForm.curID.ToString()
newForm.Close()
End If
Second Form's "Continue" button method
Private Sub ContinueButton_Click(ByVal sender As System.Object, ByVal e As ByVal e As System.EventArgs) Handles ContinueButton.Click
Me.NTBox.Focus()
Me.IDBox.Focus()
Me.ODBox.Focus()
Me.TBox.Focus()
Me.WBox.Focus()
If HSCBox.Checked Then
Me.HSC_MultBox.Focus()
Else
curID.HSC = "n"
curID.HSC_Mult = 1
End If
If NTBox.BackColor = Color.White And IDBox.BackColor = Color.White And ODBox.BackColor = Color.White And TBox.BackColor = Color.White And WBox.BackColor = Color.White And ((HSCBox.Checked And HSC_MultBox.BackColor = Color.White) Or Not (HSCBox.Checked)) Then
'success! window falls back?'
End If
End Sub
Thanks for any and all help! I'm much more proficient in Java, so this VB project is a bit frustrating sometimes.
On your second form, make a method like this:
public function ReturnSomething(curId as whateverType) as whateverReturnType
me.curId = curId
me.showDialog
return someValue
end function
then call that from your first form.
EDIT: also, have your second form's Continue method call Me.Close. This will close the second form. The ShowDialog call will block until the form is closed.
The first form should not be calling the second form's close method.