Access form edit doesn't save when closing with acSaveYes - ms-access

I can't get Access to save a form I have edited using VBA to hide (or unhide) a column. The basic code is below. I open the form (in Datasheet mode because I am changing the ColumnHidden property), make the change, and close and save, but it doesn't save the change. Experimenting, I changed acSaveYes to acSavePrompt, and it doesn't even prompt me to save. Does this have anything to do with being in datasheet mode? Never had this problem making similar edits in design mode. If so, how do I make and save such a change. Thanks for any ideas!
DoCmd.OpenForm "Form1", acFormDS
Forms![Form1].MyColumn.ColumnHidden = True
DoCmd.Close acForm, "Form1", acSaveYes

Changes you make using VBA are seen as temporary by Access, and not saved, even if you explicitly save your object. This behavior is intended (and very useful, as it allows you to hide things on the fly based on whatever you want without you having to worry about reverting changes after the user is done with the form). An exception to this is when the user first lets VBA make changes, then switches to layout view and makes additional changes, and then saves the object. In that case the changes made by VBA are saved.
As far as I know, you cannot change this. Obviously, you can make the change manually and then save it, or check if the column should be visible or not once you open the form based on something you set somewhere.

Related

Prevent 'save design changes' for an open form when closing Access

I have a split form as my main interface in an Access 2010 application. As normal, users are able to resize the datasheet portion, reorder columns, etc.
However, I don't want them to save such changes when leaving the form. Each time the form is opened the default format should be loaded.
I've taken care of all but one closing method. To avoid them closing using the default close button I've set Border Style = None. Instead I have a Close Form button that uses DoCmd.CLOSE acForm, "Main_form", acSaveNo
But if the user clicks the close button for the Access application, it pops the 'Do you want to save changes to the design of form` dialog like always.
I looked into disabling the application's Close button, but messing with Windows API is beyond my skill (and there should be a way to accomplish this without going to extreme measures).
I found a way to do this. A combination of database options, form format options, and vba can do it.
Go to the 'Current Database' options screen in the main Access
options and uncheck 'Enable design changes in Datasheet view'. This will prevent all datasheet view design changes in the database, so you will have to go into design mode for any table changes. Users can still reorder and resize columns within a form, but Access no longer considers that a valid design change and will not prompt to save it no matter how you close the form
Set the form format property 'Save Splitter Bar Position' = No. The form will now clear any change to the bar location when the form is closed. Access got really weird on me about this setting, however. Once I had ever set the option to no, I could no longer use design view or layout view to set a new default bar position; it always reverted to the location where it was when I first tried this setting. Even resetting the option to Yes, saving the design change, and fully exiting the database did not fix this.
So I added an On Load event to reset the split form size when the form opens: Me.SplitFormSize = 9000. The numbers involved are surprisingly high; in the form properties list this is set in inches. Mine was 6.5", which apparently translates to 9000.
With these three changes (along with the steps I detailed in the question) Access no longer prompts to save design changes when the form is closed, even if the user is closing the Access application entirely. The form also snaps the split form bar back to where it should be on load.
Since the API is beyond my skill too, here is a left-field workaround.
Duplicate Main_Form and rename it "Main_Form_Template". Create an Autoexec module or edit an existing one and add:
DoCmd.DeleteObject acForm, "Main_Form"
DoCmd.CopyObject , "Main_Form", acForm, "Main_Form_Template"
That should reinstate the standard template for the user each time they open the database even if they were to save the form when closing Access.
Turn your close button off on the form.
On the form's property sheet, format tab, about 2/3 of way down. Set Close Button = No
This forces the user to close it via the button you created.

Avoid prompt to save form upon form close in MS Access

I have a form with save and cancel button.
When save is pressed and some required data was not provided, it prompts a message that data cannot be saved and I do some vba cosmetics to change the border of the controls that needed to be filled up. I change border colors in red and make it thicker.
My problem is when this changes was triggered and the user decided not to submit the form data, upon click on cancel button, message pops asking the user if he wants to save changes made on the form which obviously I do not want that.
I saw some suggestion in this post
MS Access - Prevent prompt to save form
but reading on the documentation of the suggested answer, to me is not ideal to tun off all errors.
I also found another possible solution using
DoCmd.Close acForm, "myform", acSaveNo
But it seems acSaveNo only applies to data changes not on the controls property changes.
Is there any better way to avoid prompting form save and automatically discard any changes and close the form?
Thanks
EDIT: My code on changing form control appearance
Public Function InvalidBox(ByRef theBox As Control)
theBox.BorderStyle = 1
theBox.BorderColor = RGB(255, 0, 0)
theBox.BorderWidth = 2
End Function
On my cancel button I have this code
DoCmd.Close acForm, "myform", acSaveNo
Solution was: normally Access doesn't ask "Do you want to save the changes" for changes made in Form view. Only in Design view.
So it is perfectly normal to change layout properties in a form at runtime, without any problems when closing the form.
Why the "save changes" prompt appeared here is unknown, but a reboot solved it.
There aren't really except for those methods you've already seen.
The best thing is to avoid "physical" design changes. Instead of changing the border thickness, only change the colour, or overlay the textbox with a red rectangle normally hidden. Then, for a warning, unhide the rectangle.

Error upon opening form

I am going crazy with the easiest piece of code that just won't work. I can't fugure out why. I have a button on a form that opens another form but when i click it I get the following error and don't really know what to change:
my code click code is:
Private Sub HSbrowse_Click()
DoCmd.OpenForm "frmSearchPCR"
End Sub
Any Ideas?
I've had this issue several times. I believe that it is caused by the module of your form becoming corrupt. To fix it, set the "Has Module" property of your form to "No" and save and close your form. This will delete the module and any code it contains, so you will need to copy your code first. Open the VBA window to verify that the module was deleted, then reopen your form and set its "Has Module" property back to "Yes" and paste your code back in. This method has solved this problem for me on more than one occasion.
Does the current form has any ActiveX Control in it?
If not then your form may be corrupt,
rebuild your database using e.g. TM-RebuildDatabase
Start by removing individual controls one-at-a-time. When your error goes away you will know the offending control, if that is indeed the problem.
Does the form have underlying data? Did you remove that to see if the problem changes?

Obtaining textbox value in change event handler

I've written a form that performs queries asynchronously as text is typed into a textbox, however I somewhat arbitrarily seem to get the following error thrown: "You can't reference a property or method for a control unless the control has focus."
The immediately relevant code is:
Dim UpdateRequested As Boolean
Dim qryText As String
.
.
.
Private Sub txtBox_Change()
qryText = txtBox.Text
UpdateRequested = true
End Sub
Some place in the ellipses is the code that handles dynamically loading an ADODB record set, populating a local table, and refreshing a sub form. However, even when I disable this code, the problem persists: Sometimes I get the error. Sometimes I do not.
This seems to be persistent through closing the database and reopening it. Every time it starts working again, it's because I've been fooling around with code in the debugger, but I'm not sure what exactly is causing it to magically "just work" or what is causing it to not work at all.
Update
Just to make things more puzzling, I added a couple of simple event handlers:
Private Sub txtBox_GotFocus()
MsgBox "Got focus"
End Sub
Private Sub txtBox_LostFocus()
MsgBox "Lost focus"
End Sub
I run the form. I click in the test box. I receive the "Got focus" message. As soon as I type I see the error as described above. If I re-open the form, I can click between the text box in question (which itself is unbound) and a bound text box in the sub form and see both "Got focus" and "lost focus" messages as one would expect. Furthermore, showing a message box with the current value of "Screen.ActiveControl.Name" shows the expected name just before the Text property is accessed.
I know this is an old thread but it's the first I found when I had the same problem. None of the answers helped except Kaganar's own solution, which pointed me in the right direction. I'm guessing the reason people had trouble reproducing the error is there are some important details missing from Kaganar's description:
The Textbox was in the form header (or footer).
The form did not allow additions.
Because I believe the full answer is...
The Text property of any control is inaccessible when the form has a record source with no records to edit
I think there is part of Access that does not realise the textbox exists :) To understand how that might come about...
Put the unbound TextBox in the detail of the form
Do not allow additions
Set the recordsource to return no records
Open the form.
Hey presto! No Textbox.
Return a record, or allow additions, or delete the recordsource, et Voila! There is your Textbox with it's Text.
I added a text box named txtFoo to my form. Here is the procedure for its change event.
Private Sub txtFoo_Change()
Debug.Print "Value: " & Nz(Me.txtFoo.value, "*Null*") & _
"; Text: " & Nz(Me.txtFoo.Text, "*Null*")
End Sub
Then, with nothing in txtFoo (IOW its value is Null) when I type "abc" into txtFoo, here is what I see in the Immediate window.
Value: *Null*; Text: a
Value: *Null*; Text: ab
Value: *Null*; Text: abc
Basically, each character I add to the text box triggers its change event and prints the text box's current contents to the Immediate window.
As far as I understand, you want to do something similar ... except you want a different action in place of Debug.Print. Take another look at your change event procedure and compare it to mine.
Private Sub txtBox_Change()
qryText = txtVendorName.Text
UpdateRequested = true
End Sub
That is the change event for a control named txtBox. Within that procedure you reference the .Text property of a control named txtVendorName. However txtBox is the active control at the time its change event code runs ... so you can not access the .Text property of txtVendorName because it is not the active control.
Given that this problem surfaces for only the one form, but not on other new forms, I would suspect the problem form has become corrupted. Read the 2 answers to this SO question and try decompile to cure the corruption: HOW TO decompile and recompile. Decompile is often recommended as a routine practice during development.
You could also use the undocumented Application.SaveAsText method to save your form as a text file. Delete the bad form, and use Application.LoadFromText to import the saved text copy.
Make sure you have a backup copy of your db file in case anything goes wrong.
To set or return a control's Text property, the control must have the focus, or an error occurs.
To move the focus to a control, you can use txtBox.SetFocus or DoCmd.GoToControl "txtBox".
Also, the Text property is not always available:
While the control has the focus, the Text property contains the text data currently in the control; the Value property contains the last saved data for the control. When you move the focus to another control, the control's data is updated, and the Value property is set to this new value. The Text property setting is then unavailable until the control gets the focus again.
The form had a lingering data source. I'm not sure why this would cause to the behavior described above, especially considering the text box controls are unbound, however since removing the data source the text boxes are behaving as expected.
You said "somewhat arbitrarily" I think if everything is fine you must get the error when your form's recordset is empty.
In fact it's a know bug in Access and this error can occur if these conditions are met:
a) The control is in the Form Header or Form footer section
b) The form is filtered such that no records match (or there are no records)
c) No new record can be added.
In this case, the Detail section of the form goes blank. The controlis still
visible, but Access gets really confused and can throw the error you
describe.
More info:
http://allenbrowne.com/bug-06.html
I know my answer is out of date. Yet you just can set focus three times. On TextBox in header, on any texbox in detail space and On TextBox in header again. I use access 2003.

DoCmd.OutputTo On Report Doesn't Unload

In Access 2007, I have a form set up to allow previewing and exporting options for the project's reports.
DoCmd.OutputTo seems to behave strangely when dealing with reports that have the Modal property set to true. Modal is currently set to True in the Open event for all of the reports that I'm working with.
If I do
DoCmd.OpenReport szReportName, acViewPreview
DoCmd.Close acReport, szReportName
Then, focus and control is returned to the executing form normally.
If I export directly instead and use
DoCmd.OutputTo acOutputReport, szReportName
Then, the report is exported correctly, but control never returns to the executing form. It's completely disabled. The same code works just fine, if I use Modal = False when opening the report instead. I experimented a little with the report's event hooks to try and figure out what the difference is and OnUnload is never hit after OutputTo is called.
I know I could work around this by only making the report modal when I need it to be modal, but it's definitely easiest to do from inside the report's code instead of the module opening it and I really don't think I should be having this problem. I also have no problem exporting the report from preview mode instead of directly from VBA, but apparently the customer does...
So, actual questions:
Is there any good reason for OutputTo to not trigger the Unload event? If this is normal behavior, then fine, but I would at least like to understand the reason for it.
Is there any way to export a modal report and still regain control of the other windows? Or at least, a non-hacky way to re-enable and give focus to the calling form?
Your first code:
DoCmd.OpenReport szReportName, acViewPreview
DoCmd.Close acReport, szReportName
...is going to error out if the report is modal. The reason why is the second line can't be executed until the report opened on the first line is closed. So, as soon as you get to the second line, you get an error, because the report isn't open any longer by that point.
What you need to do is not set the modality in the report's properties sheet, but in the DoCmd.OpenReport command:
DoCmd.OpenReport szReportName, acViewPreview, , , acDialog
The acDialog switch opens it modally, and code will pause until the report is closed, and then continue.
But when you use DoCmd.OutputTo, it will behave normally, because the report is not modal.
In general in Access forms and reports, you don't really need to set the Modal property at all, since you can always open it modally at runtime.
I don't know why you believe you need to set the modal property in the report's OnOpen event at all. There is no code needed there, and I don't think it's a good place to be changing that (and would have expected it to not work in the first place, as you can't really change window mode after the window is already created; maybe the OnOpen executes before the visible window is created?).
But you're doing things backwards from the standpoint of standard Access practices. I don't know why you resist setting the window mode in the calling code, as it means you can use the report in any context without having to have code that worries about the issue inside the report itself. I always think that reports and forms should be as dumb as possible, knowing only about themselves, and let the calling contexts have all the intelligence in them (though with as little poking into the internal contents of the called form/report as necessary).