How to keep a button in access form disabled after one click using VBA - forms

I am trying to code a button that allows user to only click once. I have managed to disable the button after one click but when I reopen the form the button is still enabled.
How can I keep the button disabled after one click. Ultimately I want to make ACCDE containing a form that has a button which is only enabled once. the ACCDE file will be used to for different projects and every time when starting a new project a copy of the generic ACCDE file will be used. The button needs to be internally enabled for every time you start a new project (i.e open a generic copy of the ACCDE) and becomes disabled after the user has clicked on it and remain disable forever for that particular project.
I managed to do the following coding for that button.
Private Sub Command21_Click()
DoCmd.OpenQuery "Reset AutoCounter"
Command21.Enabled = False
Command25.SetFocus
End Sub
The code above disables the button after one click, but when you close the form and reopen it the button comes as enabled.
Is there a code that I can use to keep the button disabled.

You can use TempVars for this:
Private Sub Form_Open()
If IsNull(TempVars("ProjectEnabled").Value) Then
' Initialise.
TempVars.Add "ProjectEnabled", True
End If
Me!Command21.Enabled = TempVars("ProjectEnabled").Value
End Sub
Private Sub Command21_Click()
Command25.SetFocus
DoCmd.OpenQuery "Reset AutoCounter"
Command21.Enabled = False
TempVars "ProjectEnabled", False
End Sub
Edit
Testing shows, that the above doesn't work as TempVars are not persistent.
So the simple workaround is to create a small local table with a Boolean field with DefaultValue of True, and then update this to False when clicking the button.

you either do it at design time:
in VBA IDE select the wanted UserForm from Project View and have it appear in the main code pane
select its Command21 control
in Properties View (F4 to pop it out) set its Enabled property to False
or, do it at runtime
insert this in your UserForm code pane :
Private Sub UserForm_Initialize()
Command21.Enabled = False
End Sub

Create a local table and make it hidden.
Use a value from that table to determine whether to hide enable it or not on either form load or application load (using a global variable).

Related

How to know closing event of sub form in parent form

I have a main form with :
a table of data (list of pay)
a button calling a subform (assistant form to create easily a bound of pay for a complete year)
After closing the subform, I have to update the main form data (table view) only if the user click Generate (to avoid data update), ie only if the user generate new payroll.
Is there a way to know if the user cancel or not action in the subform?
Ok, so you NOT really talking about a form + sub form.
There are two ways to do this:
First, you can open the 2nd child form as acDialog (not modal - very big difference).
So, your main form code can do this:
Dim strF As String
strF = "frmChildForm"
DoCmd.OpenForm strF, , , , , acDialog
' CODE WILL HALT and wait for above form to be closed
' code here continues
' can even update data on this main form from that child form.
If CurrentProject.AllForms(strF).IsLoaded Then
' user hit ok - or your save button
Me.LastChildUpdate = Forms(strF)!LastUpdate
DoCmd.Close acForm, strF
Else
' code goes here - user hit cancel button, or X to close - we assume cancel
End If
Now in that other child form, you DO NOT CLOSE when your "done/save/ok" button runs. It simply sets the form's visible property to false
eg:
Me.Visible = False
So, now our calling code will WAIT until the user is done. If the form is closed, then we assume a user "canceled" that child form.
so, the user can hit X to close, OR the user might hit your close/cancel button. Your close/cancel button thus can close the form. eg this code:
docmd.Close acForm,me.name
So, now you know if the user canceled (closed) the form. Your "ok/save" button in that form ONLY sets the forms visible=False. That makes the calling code continue, and then you check if the form is open or not - and thus your code can take appropriate action.
However, you don't even have to use the "halt" code trick above.
What you can do in that child form you launch?
You can in the on-open event, or even on-load? You pick up the name of the calling form.
So, you define this in your code:
Option Compare Database
Option Explicit
Dim frmPrevious As Form
Private Sub Form_Load()
Set frmPrevious = Screen.ActiveForm
End Sub
So, now your save button on this form?
It can call/use/update ANYTHING from the main previous form caller.
So, your save button can now;
frmPrevious.Refresh
Or
frmPrevous!LastName = me.LastName
So, you can do "anything" by replacing "me" with frmPrevous, and any operation (such as your custom save button on that 2nd form) can update, call code, refresh, or do anything it wants to operation on the first main calling form.
And you can even call subs/functions in that main form.
So, you could have a public sub in the main form, and in the 2nd form, on the close event do this:
Call frmPrevous.MySubName ' tell + call code in main form.
docmd.close acForm,me.name
So the above outlines two approaches:
First idea:
You open 2nd form as "acdialog" and the code waits. You either then close the 2nd form (considered a cancel), or you save visible=false and the calling code CONTINUES.
Second idea:
You pick up the previous form in the on-load event. Now your save button can directly update values, controls etc. in "frmPrevious", and then once done, you close the 2nd form in that "ok button" routine.
So, quite much is that in that 2nd form, you can directly update controls and do things to the first calling form with the above 2nd idea.
Or, as noted, you can HALT the calling code that opens the form, wait for user response, and then use the visible=false trick to allow the calling code to continue. Once again, since the 2nd form is still open, you are free to get/grab/take values from that STILL open form, and then when done you thus as a last stop close that 2nd form. So in effect, your 2nd form does NOT close when the user is done - but only visible = false. As noted, this trick only works if you open/call the 2nd form as "acDialog". This is a great idea for say yes/no dialog prompts etc., since then you can upon user selection have the calling code continue, and examine the values in that 2nd form before closing it.
And the last but not least method:
In that 2nd form the code behind your "ok" button can simple update the first form
forms!MyFirstForm!LastName = me.LastName
docmd.close acForm,me.name
However, above has the form(s) name hard coded, and frmPrevious trick is thus somewhat better since then you don't hard code the calling forms name, and thus many forms can call + use that same 2nd form.

tabcontrol page not updated

In my winfom program I have a function that change the tabpage when I hit a key.
On tabcontrol indexchanged I check for some parametre and if they are not correct I change the tabpage to the first tab.
If I click on the page with the mouse the tabpage changed to the first tab with the correct content.
If I click a key and run this code "tcOrdre.SelectedTab = tpOrdre;" it changes the tab back to the first but still showing the content of the selected one.
In SelectedIndexChanged is use this code:
MessageBox.Show("Der skal vælges en ordre først"); // Show a messagebox
tcOrdre.SelectedTab = tpOrdreListe; // change tap to first
If I use the mouse then SelectIndexChanged get called when I run:
tcOrdre.SelectedTab = tpOrdreListe; // change tap to first
the SelectedIndexChanged function is called again and the content is okay.
But if I use the key to change index the SelectedIndexChanged does not get called Again and the content never change. Only the tab in the top change to the first one.
I hope someone can help me.
I found the solution.
All I have to do is call this line.
this.BeginInvoke(new Action(() => tcOrdre.SelectTab(0)));
and not tcOrdre.SelectedTab = tpOrdreListe;
And everything Works fine.

How do I set size of colums in a table subform datasheet view in MS Access

I have a subform bugging me. The mainform contains buttons etc. Everytime the user close/open the form, the columns width is reset to whatever the table likes. If i open the table directly, the size is as i want. If i change it in the subform, it is not saved. (See screendump)
I would like "Phase" to stay about 2 cm width. I can enter the subform and edit the "Width" but that is only applied to the other views.
I hope you can help, Emil.
I realize this post is almost 2 years old, but I ran into the same problem and came across this post.
I am running MS Access 2013 on Windows 7 Ultimate. I did not find the solutions offered here to work for me, so, I set out to find something that would work for me before I went to VBA code. (Incidentally, I appreciate the link offered by #Patrick_Honorez in his comment on the original post because that was going to be my fall-back solution.)
Anyway, here is what worked for me and I hope perhaps it will work for others as well:
Open the parent form.
In the subform, right-click the column header
for the column for which you wish to adjust the width.
Select the “Field Width” item from the context menu.
In the “Column Width” dialog that appears in step 3, enter the desired column width in points, or, use the [Best Fit] button. Then click the [OK] button to close the dialog and return to the form.
Right-click the parent form’s border to bring up the parent form’s context menu. Click the “Save” item in the context menu.
Now close the parent form.
The next time the form is loaded, the column widths should be as set it step 4 above--at least they are for my setup.
I see this post is quite old and OP must have figured someway to tackle the issue. I came across same issue today and found solution on this link.
For anybody else having same issue, use following code (I modified the code a little because original code from the above mentioned post saves column width of only text boxes but my form has combo boxes too, column width of which was not getting saved) in close and open events of your subform and then open main form in Form View and then manually select desired widths either by mouse, by entering column width value or using best fit. Save the form and reopen to check results. That's it.
Private Sub Form_Close()
Dim ctrl As Control
For Each ctrl In Me.Controls
If (ctrl.ControlType = acTextBox Or ctrl.ControlType = acComboBox) Then
SaveSetting "propertiesDBS", Me.Name, ctrl.Name, ctrl.ColumnWidth
End If
Next
End Sub
Private Sub Form_Open(Cancel As Integer)
Dim ctrl As Control
Dim frm As Form
Dim w As Long
For Each ctrl In Me.Controls
If (ctrl.ControlType = acTextBox Or ctrl.ControlType = acComboBox) Then
w = GetSetting("propertiesDBS", Me.Name, ctrl.Name, 0)
If w <> 0 Then ctrl.ColumnWidth = w
End If
Next
End Sub
I know this is late to the party and most likely going to be the last comment anyone reads, but this can be done quite simply in MS Access 2016 - by someone like myself who has no more than 4 days experience in databasing overall and no experience with writing custom Macro's or VB Script (using only what is native to MS Access).
Here's how I did it.
Scenario - Split Form (Form + Datasheet).
Extra Recommendations:
It pays to be across all properties of every object type in your database, as a change in a field property can cause unpredictable erratic effects, which take ages to figure out why it happened and how to stop it from happening again, whilst delivering your desired outcome.
Me.Requery in your VBA script after every necessary event and also in your main form (generally the 'After Update' event is used most), and be wary that too many Me.Requery's (in unnecessary events) can also be detrimental - so too much of a good thing can be a bad thing.
Bottom Line Up Front - Modify the format of your query that is to be exported/printed.
In 'Design View' of the query you are concerned with, ensure that the fields are in the order you need them outputted in first as this is exactly how the macro will present them for export/print (example could be "Australia" then "Northern Territory" then "Town's In The Northern Half Of The State" then "Darwin" then "Suburbs In The Northern Half Of City").
Switch to 'DataSheet View' in the same query and use the top left folded over triangle looking thingy to highlight the entire data set then right click that same triangle to present an options menu. Select 'Row Height' and type in "15" (default row height in Excel).
Deselect the entire spreadsheet and this time select every column (left click the left most column, hold shift button, scroll over to the right to the far end of the data set and click the last column) and then right click one of the highlighted columns to present another menu. Select 'Field Width' and within that new pop-up menu select 'Best Fit' and then 'OK'.
(Optional - not sure if this helps or hinders but I did it for my purpose) With the columns still selected right click one of the highlighted columns again and select 'Freeze Fields'.
My scenario had buttons with macros configured to run filtered reports so I was able to check this by simply clicking any of those buttons and seeing the report formatting, which it held true to the work I had just done. I exported using another button with a macro that exports to Excel with 'Print Formatting' selected (my main form also had the datasheet view as the only thing that could be printed and was also set in 'Print' formatting.
The Excel spreadsheet opened with all row heights and column widths in a way that I could read every field/record with perfect ease and without extra modification.
This also worked for cascaded combo boxes, with the export only outputting the 'drilled down/filtered' datasheet records, in a format that required no further modifications.
Hope this helps someone, as its saved my hide! :)
Open the Main form in Design. Go to the SubForm. Click on the square at the top left of the SubForm and select 'Properties'. Right-Click the control 'Phase' and click 'Properties'.Click the 'Format' tab and select 'Width'. What do you see there? That should control the widht of control 'Phase' unless you have some overriding coding elsewhere. Input the size you want and see what happens.
Use continuous forms instead. It gives you complete control over how your subform displays.
If you open your subform directly, your property sheet menu should display automatically if the default view is "Datasheet." Click on "All" and change the "Auto Resize" property to "No." This should solve the issue and avoid the need for VBA.
This only works when you open the subform separately. So if you want the changes to be reflected within your main form, you'll have to close it and switch back and forth.
Super annoying by default.
It seems to work as one would expect of you set the view mode to layout view. Drag column widths as needed and save. Go back to form view and it works. It's really dumb it doesn't work the same way in form view our design view.
In Access 365, open main form, right-click sub-form datasheet columns that need width adjustment, use the Field Width to adjust, click on border of main form to select Layout view, and save changes.
Open subform in datasheet view (by double click on subform in the left pannel)
Resize columns as you want by dragging or by right-click the column header for the column for which you wish to adjust the width and select the “Field Width” item from the context menu.
Right-click the subform border to bring up the context menu. Click the “Save” item in the context menu.
Either open the Main Form in Layout View or directly open your Subform in Datasheet View. Right Click on the Field Header, select Field Width, and enter the desired width. Save. Bewm.
My solution (Access 2016) was to create the main & subform, recreate the subform on its own using form wizard and set it up the way I want it, rename the original subform to something else, and finally rename the recreated subform to the original form name. Open the main form and the subform should be laid out the way you want it. You can then delete the original subform you renamed.

Access Form with checkbox toggled textboxes to make visible

Im trying to cut down on the clutter of my form since the data im getting can fill in more or less fields from my table.
as of right now im trying to build an event but I do not know the right syntax to use to create my event.
right now i have:
= if toggle.onclick ="yes" then
data.visible=true
else
data.visible=false
end if
in the After Update tab of the Event tab.
I hope that gives you an idea of what im trying to do.
I have this on a test form so the only objects are:
checkbox name "toggle"
textbox name "data"
the text box is default to not visible at the moment.
my goal is to have a list of check boxes and once they are checked their corresponding text box would appear on a refresh. this way the workers wont be intimidated by the amount of textboxes are on my current form. also will reduce the vast clutter on the current form.
By default, the 'Toggle' value will be True or False - not 'yes' or 'no'. Thus the following is what you need to toggle fields:
Private Sub Toggle_AfterUpdate()
If Me.Toggle = True Then
Me.Data.Visible = True
Else
Me.Data.Visible = False
End If
End Sub

Choosing a button from a view

I'm stuck with some syntax on figuring out which of 2 buttons in a view was clicked. I have multiple views - so what happens first is text is assigned to the 2 buttons based on the current view - then what I want to have happen is an action based on which button was clicked. My views work ok - it's the button code that I'm trying to figure out. I'm also trying to avoid writing a sub for each individual button click - and want generic code that I can reuse for any of the views that will always have 2 buttons.
Sub catchtheClick
Dim button1,button2,clickButton As Button
clickButton = Sender
If (we figure out which view - view1 for example) Then
button1.Text = "view1-button1"
button2.Text = "view1.button2"
button1.Tag = "btn1"
button2.Tag = "btn2"
Select clickButton.Tag
Case "btn1"
(we go to another view etc.)
Case "btn2" Then
(we go to some other view etc.)
End Select
End If
End Sub
Did you see the Arrays of views tutorial?
Your code is wrong. You are declaring button1 and button2 which are never initialized or assigned.
The simplest solution is to use the Tag property to mark each button and then check clickButton.Tag and find which button was pressed.
Avoid the confusion - simply use the Designer to add the views and then use "Tools .... Generate Members" to add all your Dim statements and Event statments.
I made a few changes - including the location of the button init and event names - all works fine now.