I've inherited a Access database that is used to import some data in SQL. The MDB opens with a form, in a modal mode: no Access menubar or buttons are visible. I can view the tables with content by using the Visual Studio 'Data Connection' tool, but I cannot see the module's code.
I've looked at this question here, but the answers there aren't really what I need. Is there a way to either force the form to close (and access the modules) or to extract the VBA code ?
[EDIT] I am using Access 2007, not sure what the original developer used.
Hold down the shift key when you open the database. This will prevent it from loading the automatic script it's running and allow you to gain access to the tables, queries, and VBA scripts.
This is a rather long addendum to, or comment on, Michael Todd's reply in response to edosoft's comment.
Rather than choosing to enable the content, check the start-up options (either (file->options->current database->display form) or (tools->start up->display form)) and remove the name of the form, having taken a note, and ensure that Allow Full Menus (same page) is ticked. You may also like to press Alt+F11 to display code, and check that for start-up code, finally, see if there is an AutoRun macro and rename it.
EDIT re Comments
You do not have to open an mdb to change the start-up form, for example, code such as this could be run from another mdb using the full name and path of the mdb you wish to change.
Sub SetStartForm(DBFile As String)
Dim prp As Object
Dim db As Database
Const PROPERTY_NOT_FOUND As Integer = 3270
Set db = OpenDatabase(DBFile)
db.Properties("StartupForm") = "(none)"
If Err.Number > 0 Then
If Err.Number = PROPERTY_NOT_FOUND Then
'' Create the new property, but this is not relevant in this case
End If
End If
db.Close
Set db = Nothing
Set prp = Nothing
End Sub
Button close with function:
Private sub cmdClose_Click()
CloseForm(YourFormName)
End sub
Public Sub CloseForm(ByVal strFormName As String)
Dim iCounter As Integer
For Each frm In Forms
With frm
If (.Name = strFormName) Then
iCounter = iCounter + 1
End If
End With
Next
If (iCounter > 0) Then
For i = 1 To iCounter
DoCmd.Close acForm, strFormName, acSaveNo
Next
End If
End Sub
Related
I'm having issues with trying to display the file picker using the FileDialog property in MS Access 2016. I've tried both early and late binding but the file picker never displays. No errors are detected nor messages displayed. When I try to debug it line by line, the .show doesn't trigger the form. I've also tried If .show=-1 in lieu of .show but that does not work either. I've tried removing the library reference to Microsoft Office 16.0 Object Library, and even using late binding the window still does not display. Any ideas as to what is going wrong, and how to remedy it? I'm adding both early and late binding examples below.
Public Sub FP_EarlyBinding()
Dim fd As Office.FileDialog
Set fd = Application.FileDialog(msoFileDialogFilePicker)
With fd
.AllowMultiSelect = True
.Show
For Each vrtSelectedItem In .SelectedItems
Debug.Print vrtSelectedItem
Next vrtSelectedItem
End With
End Sub
Public Sub FP_LateBinding()
Const msoFileDialogFilePicker As Long = 3
Dim fd As Object
Set fd = Application.FileDialog(msoFileDialogFilePicker)
With fd
.AllowMultiSelect = True
.Show
For Each vrtSelectedItem In .SelectedItems
Debug.Print vrtSelectedItem
Next vrtSelectedItem
End With
End Sub
--------------EDIT-------------------------
Per comments, I was instructed to not to do this in a class module. I've since edited the code, as below. This still does not allow for the form to appear.
This is in a standard module:
Public Function filePicker() As Variant
Dim fd As FileDialog
Dim sFiles$
Dim vrtSelectedItem As Variant
Set fd = Application.FileDialog(msoFileDialogFilePicker)
With fd
.AllowMultiSelect = True
.Show
For Each vrtSelectedItem In .SelectedItems
sFiles = sFiles & vrtSelectedItem & ","
Next vrtSelectedItem '-----------loops again to attach other files
End With
filePicker = sFiles
End Function
I call this procedure from a class module:
Public Sub Test()
Dim vFileList As Variant, vFile As Variant
vFileList = Split(filePicker(), ",")
For Each vFile In vFileList
Attachments.Add vFile
Next vFile
End Sub
-------------FINAL EDIT---------------------
Turns out the problem here was the Access install...I went to the installation directory and found MSACCESS.EXE, right-clicked, and repaired.
What you have looks almost good.
I recommend you ALWAYS, but ALWAYS ALWAYS ALWAYS put option explicit t the start of your code modules.
eg this:
Option Compare Database
Option Explicit
With above, your code does not compile. I mean, after you type in your code, I assume you do from the code menu a debug->compile. I will do that 100's of time in a typical day (after editing code). so, make that a habit.
Also, to set the default for NEW code modules (setting does not effect existing), set this option in the VBA code editor: tools->Options
So, your code snip looks ok, but, with above option explicit, then you have to declare all variables (and bonus is compile will cast incorrect spellings or miss typed variable names).
So, your code like this should work fine:
Public Sub FP_LateBinding()
Const msoFileDialogFilePicker As Long = 3
Dim fd As Object
Set fd = Application.FileDialog(msoFileDialogFilePicker)
With fd
.AllowMultiSelect = True
.Show
Dim vrtSelectedItem As Variant
For Each vrtSelectedItem In .SelectedItems
Debug.Print vrtSelectedItem
Next vrtSelectedItem
End With
End Sub
Now, it also not clear how you are test/running the above. But, we assume you create a new code module (NOT class module)
You will then type/paste in above. Save it
do a debug->compile from the VBA editor menu - does it compile ok?
(and if other errors in other places - fix those first).
Now, to run it, place cursor anywhere inside of that code stub, hit f5.
Or you can type in the name of the above sub in the debug window like this:
FP_LateBinding
So your posted code - looks really nice! - all good. Try the above option explcit. And of course now in your example, add the declare for vrtSelectedItem
Edit: ============================================================
Now, of course if this is a class module, then just like code in a form/report, you can't just hit f5 in the code module, nor can you JUST type in the name of the sub.
In fact, if you place your cursor in the code and hit F5, then you get this:
So, it not that the code or file does not appear, you get the above - a big WHOPPER of a difference issue.
And if it is a class module as opposed to a regular code module?
Then to test or use the code, you have to write in test code into a REGULAR code module. You can't use the debug/VBA editor to JUST run a class.
This not different then creating any other object.
So, if we create a new class module, paste in above code, say we save the class code module as MyClassTest ?
Then you have to write code in another standard code module like this:
Sub Test1()
Dim clsTest As New MyClassTest
clsTest.FP_LateBinding
End Sub
So, you can't run class code (even code in a forms code behind module), or any custom class module, you have to FIRST create a instance.
Now it is "possbile" that you used VBA, VB5, VB6. And in fact used "early" versions of Access (before access 2000 - 21 years ago).
you will find by default, it is possbile to use + call class module code without first creating a instance of the class module. This ability was and is for keeping compatibility for pre access 2000 VBA, in which class code modules did not require to be delcared as a new instance. This so called "base" class instance thus was possbile.
it turns out, that if you been importing code for the last 20 years from previous verisons of Access? This flag setting - and option STILL exists in Access 2019 - over 20 years later!!!!
I doubt that you are/did import code from such older versions of Access, but it is in fact still possible to set a class module to NOT require a instance of the class to be created in code. However, I don't recommend doing this, despite the fact that this is still possible.
There are three separate shared Access databases (tampa1, tampa2, tampa3), multiple users access them. Each user needs to be able to switch databases (using a dropdown list/combo) at any given time, when the user does so. Goal: the program should be able to open the new database in the same instance and close the exiting database (in either order) if it was opened by the same user. I don't want the database to close another instance of any of the three databases opened by different user.
I was able to create the first part of the code, opening the database (although I am not sure if it has been opened in same or different instance). I created a code to close the exiting db (Applicaton.quit), however when I run the code, both databases are closed.
Public Sub Opendb21()
Static acc As Access.Application
Dim db As DAO.Database
Dim strDbName As String
Set acc = New Access.Application
strDbName = "C:\Users\YOURNAME\Documents\Opening multiple db Test\tampa2.accdb"
Set db = acc.DBEngine.OpenDatabase(strDbName, False, False)
acc.OpenCurrentDatabase strDbName
acc.Visible = True
'db.Close
'Set dbRemote = acc.CurrentDb
Set db = Nothing
'Closing the current db tampa1
Forms!Form1.cmd_CloseAccess_Click
End Sub
'Second sub
'Closing cmd -macro converted to VBA code
'This is on Form1, tampa1 database
Public Sub cmd_CloseAccess_Click()
DoCmd.Quit acQuitSaveAll
End Sub
I am expecting the program to close the current db (tampa1); open the second db (tampa2), but the program closes both instead. I need a way to make sure the code doesn't close an instance currently open by different user.
thank you for your hints! I found the solution to the issue by reading another Stack overflow posting, here is the link to that posting:
Access: Shell cmd Open MDB
I was missing the command "Application.UserControl=True" , which makes the application persistent and visible. I created a form which has a combo box that lists the databases I want to switch to. The variable ("OpenWhat")captures the name of the specific database and passes the parameter to a Module Sub, where it then completes the string by adding the rest of the information. After the new database is open, the Form in the first database closes the calling database.
Here is my particular piece of code:
Private Sub cbb_open_otherdb_AfterUpdate()
Dim OpenWhat As String
OpenWhat = Forms!Form1.cbb_open_otherdb.Value
Call Opendb(OpenWhat)
Forms!Form1.cmd_CloseAccess_Click
End Sub
Public Sub cmd_CloseAccess_Click()
On Error GoTo cmd_CloseAccess_Click_Err
DoCmd.Quit acQuitSaveAll
cmd_CloseAccess_Click_Exit:
Exit Sub
cmd_CloseAccess_Click_Err:
MsgBox Error$
Resume cmd_CloseAccess_Click_Exit
End Sub
Option Compare Database
Option Explicit
Public Sub Opendb(ByVal OpenWhat)
Dim objApp As Access.Application
Set objApp = New Access.Application
objApp.UserControl = True
objApp.OpenCurrentDatabase "C:\Users\YOURNAME\Documents\Opening multiple db Test\" + OpenWhat & ".accdb"
MsgBox ("Opening ") & OpenWhat
Debug.Print OpenWhat
Set objApp = Nothing
End Sub
I copied similar code to the other two databases to create a navigation ring.
Thank you for your help!
I am periodically getting Word documents from various clients and sometimes they send them to me in 'Read-Only' mode. While it isn't a big deal to go to 'View > Edit Document' manually, I cannot seem to find how to do this within my VBA code.
Either opening a document as editable or toggling it as editable once it is open would be sufficient for my needs.
Note that I cannot open the document with 'readOnly = false' as it looks like it is set to 'readOnly recommended' (based on my reading of the MS man page on Document.Open).
IN CONTEXT:
I was also hitting a problem with turning off 'read-mode' which the documents were opening as by default. I have posted this question and answer here.
The code below will change the ReadOnly attribute of a closed file, setting its ReadOnly attribute to either True or False depending on the argument supplied to the procedure.
Private Sub SetReadOnlyProperty(Fn As String, _
ByVal ReadOnly As Boolean)
' 21 Nov 2017
Dim Fso As Object
Dim Doc As Object
Set Fso = CreateObject("Scripting.FileSystemObject")
Set Doc = Fso.GetFile(Fn)
If (Doc.Attributes And vbReadOnly) <> Abs(Int(ReadOnly)) Then
Doc.Attributes = Doc.Attributes Xor vbReadOnly
End If
End Sub
This procedure requires access to the MS Scripting Runtime DLL. Enable this access by checking the box against Miscrosoft Scripting Runtime from Tools >References in the VBE window. Below is an example of how to call the function. Note that an error will result if the supplied file doesn't exist.
Private Sub TestReadOnly()
SetReadOnlyProperty "H:\Test Folder\Test File.docx", False
End Sub
I am building an Access report (2010 version), and would like to be able to customize it based on the user's selections on a form. When I run it, I get error 2771: The bound or unbound object frame you tried to edit does not contain an OLE object.
This is the code to pass the parameter:
Private Sub Command120_Click()
DoCmd.OpenReport ReportName:="rpt_EODGraph", View:=acViewPreview, _
OpenArgs:=Me!Text0.Value
End Sub
This is the code to open the report.
Private Sub Report_Open(Cancel As Integer)
Dim ch As Chart
Set ch = Me.Graph3.Object.Application.Chart 'This line generates the error
ch.ChartTitle.text = OpenArgs
End Sub
I've found at least one person saying that this is not actually possible to do on a report. (http://www.access-programmers.co.uk/forums/showthread.php?t=177778&page=2 Note that this is page 2 of a 2 page forum discussion...) Can anyone corroborate or refute?
Apparently the Report has to have some kind of focus before OLE objects are accessible.
It is enough if you click on it or set the focus to something:
Private Sub Report_Open(Cancel As Integer)
Dim ch As Object
Me.RandomButton.SetFocus
Set ch = Me.Diagramm11.Object
ch.ChartTitle.Text = "Hello"
End Sub
This works. I just set a button on the report that gets the focus. Perhaps you find something more elegant ;)
We have numerous MS Access files with the "Auto Compact" option set.
I would like to open a file using VBA and close it (or quit) without going through the long compacting process. However, I don't want to touch the "Auto Compact" option, because it needs to stay True for the normal users.
Is it possible to close the file with VBA and skip the compacting?
You can always disable the Auto Compact on Close and use a Flagging system. Create a Universal flag, allowCompact As Boolean, and based on the user permission set the Flag to True, and on a Form (probably a hidden form) or the form that is always kept open's Close method you can check if the Compact Flag is set, if yes use the Code (http://access.mvps.org/access/general/gen0041.htm) to Perform Compact else just quit the DB.
'In a Standard Module
Public allowCompact
'Code to perform AutoComapct
Public Sub CompactDB()
CommandBars("Menu Bar"). _
Controls("Tools"). _
Controls("Database utilities"). _
Controls("Compact and repair database..."). _
accDoDefaultAction
End Sub
Then in the Form that is opened first (probably a login Form)
Private Sub buttonName_Click()
'Check the users permission
If Me.permissionLevel <> "Manager" Then
allowCompact = True
Else
allowCompact = False
End If
End Sub
Then finally on the Final form's close event you can use.
Private Sub Form_Close(Cancel As Integer)
If allowCompact Then _
CompactDB
Application.Quit
End Sub
Hope this helps !