I have an app that uses the following procedure to change some of the Current DB properties.
Public Sub SetStartupOptions(propname As String, propdb As Variant, prop As Variant)
On Error GoTo Err_SetStartupOptions
'Set passed startup property.
'some of the startup properties you can use...
' "StartupShowDBWindow", DB_BOOLEAN, False
' "StartupShowStatusBar", DB_BOOLEAN, False
' "AllowBuiltinToolbars", DB_BOOLEAN, False
' "AllowFullMenus", DB_BOOLEAN, False
' "AllowBreakIntoCode", DB_BOOLEAN, False
' "AllowSpecialKeys", DB_BOOLEAN, False
' "AllowBypassKey", DB_BOOLEAN, False
Dim dbs As Object
Dim prp As Object
Set dbs = CurrentDb
If propname = "DBOpen" Then
dbs.Properties("AllowBreakIntoCode") = prop
dbs.Properties("AllowSpecialKeys") = prop
dbs.Properties("AllowBypassKey") = prop
dbs.Properties("AllowFullMenus") = prop
dbs.Properties("StartUpShowDBWindow") = prop
Else
dbs.Properties(propname) = prop
End If
Set dbs = Nothing
Set prp = Nothing
Exit_SetStartupOptions:
Exit Sub
Err_SetStartupOptions:
Select Case Err.Number
Case 3270
Set prp = dbs.CreateProperty(propname, propdb, prop)
Resume Next
Case Else
Dim ErrAns As Integer, ErrMsg As String
If ErrChoice = vbYesNoCancel Then
ErrMsg = Err.Description & ": " & Str(Err.Number) & vbNewLine & "Press 'Yes' to resume next;" & vbCrLf & _
"'No' to Exit Procedure." & vbCrLf & "or 'Cancel' to break into code"
Else
ErrMsg = Err.Description & ": " & Str(Err.Number) & vbNewLine & "Press 'Yes' to resume next;" & vbCrLf & _
"'No' to Exit Procedure."
End If
ErrAns = MsgBox(ErrMsg, _
vbCritical + vbQuestion + ErrChoice, "SetStartupOptions")
If ErrAns = vbYes Then
Resume Next
ElseIf ErrAns = vbCancel Then
On Error GoTo 0
Resume
Else
Resume Exit_SetStartupOptions
End If
End Select
End Sub
procedure can be used to add and set values for DB.properties, These are the properties that are set in the Access options screen. I have a limited list of property names but, does anyone know where I can find the full list of properties that are recognized? ( i.e. the startup form name, start up ribbon name,... )
You can list all of the properties for the database that exist at the time you run the code using a very simple procedure as seen here.
Public Sub ListDBProps()
Dim db As Database
Dim prp As Property
Set db = CurrentDb
For Each prp In db.Properties
Debug.Print prp.Name
Next prp
End Sub
There are a couple of gotcha's in this. Notice I said "that exist at the time you run the code". That is, Access creates properties for the database (and presumably other objects as well) on an "as needed" basis. For instance, when you compile the database into, what used to be called an MDE, now an ACCDE, Access will add a new property of Type "Text" [10] named "MDE" with a value of "T". There are a couple of properties in the list you provided that fall into this category as well, such as "AllowBypassKey" and "AllowBreakIntoCode".
Here is the list that I got when I ran this code on a simple database I opened up:
Name
Connect
Transactions
Updatable
CollatingOrder
QueryTimeout
Version
RecordsAffected
ReplicaID
DesignMasterID
Connection
ANSI Query Mode
Themed Form Controls
AccessVersion
NavPane Category
UseMDIMode
ShowDocumentTabs
Build
CheckTruncatedNumFields
ProjVer
StartUpShowDBWindow
StartUpShowStatusBar
AllowShortcutMenus
AllowFullMenus
AllowBuiltInToolbars
AllowToolbarChanges
AllowSpecialKeys
UseAppIconForFrmRpt
AllowDatasheetSchema
Show Values Limit
Show Values in Indexed
Show Values in Non-Indexed
Show Values in Remote
Auto Compact
DesignWithData
Picture Property Storage Format
NavPane Closed
NavPane Width
NavPane View By
NavPane Sort By
Track Name AutoCorrect Info
Perform Name AutoCorrect
HasOfflineLists
You can add the Type property to your output easily enough. It is an integer value corresponding to the DataTypeEnum enumeration. The Value property of the Property can be a little more tricky. Usually it's a value that can be easily converted to a string value but there are a couple that cause a runtime error when you try to print them out or store them in a String variable. A little error handling in a small function can handle that with no trouble.
My example was run on an ACCDB in Microsoft Access 2007.
Enjoy . . . Doug
Related
I am working in MS Access. All the tables and views are linked to a SQL Server database. I want to write a procedure that will retrieve and store all of the formatting information about these objects. A lot of this information is available from the property sheet (I open a table in Design View, and hit F4 for the property sheet). Eg:
Filter
Order By
Filter On Load
Order by On Load
Order by On
How do I retrieve these properties programmatically? I only see them listed for Reports.
Note that I need to retrieve the values, not just set them. I know about the SetFilter method, and that's not what I need.
The linked table exists as a DAO.TableDef in your database's TableDefs collection. So you can check the TableDef.Properties collection for those 5 properties.
However beware that both Filter and OrderBy are user-created instead of default properties, which means they are not included in the Properties collection unless you've assigned them values. Attempting to retrieve one which doesn't exist triggers error 3270, "Property not found". You can trap that error, respond to it as you wish, and continue on for the other properties you're interested in. Or you could first determine whether the property exists and only attempt to retrieve its value when it does exist.
This code sample uses the first approach (trap the error):
Const cstrTable As String = "YourLinkedTableNameHere"
Dim db As DAO.Database
Dim tdf As DAO.TableDef
Dim strMsg As String
Dim varProp As Variant
Dim varProperties As Variant
On Error GoTo ErrorHandler
varProperties = Array("Filter", "FilterOnLoad", "OrderBy", _
"OrderByOn", "OrderByOnLoad")
Set db = CurrentDb
Set tdf = db.TableDefs(cstrTable)
For Each varProp In varProperties
Debug.Print varProp, tdf.Properties(varProp).Value
Next
ExitHere:
Exit Sub
ErrorHandler:
Select Case Err.Number
Case 3270 ' Property not found.
strMsg = "Property '" & varProp & "' not found."
'MsgBox strMsg
Debug.Print strMsg
Resume Next
Case Else
strMsg = "Error " & Err.Number & " (" & Err.Description & ")"
MsgBox strMsg
Resume ExitHere
End Select
How about something like this? (I've defined "table2" to have two fields, "PropertyName" and "PropertyValue"..."table1" is a placeholder for any of your existing tables)
Dim i As Integer
Dim j As Integer
Dim RS As DAO.Recordset
On Error Resume Next
Set RS = CurrentDb.OpenRecordset("select * from table2")
j = CurrentDb.TableDefs("table1").Properties.Count
For i = 0 To j - 1
RS.AddNew
RS!PropertyName = CurrentDb.TableDefs("table1").Properties(i).Name
RS!PropertyValue = Nz(CurrentDb.TableDefs("table1").Properties(i).Value, "-")
RS.Update
Next i
I have an access db that pulls volumes from a table of exceptions. Each volume has an ID. I've created queries to pull details, for all possible volumes, and saved each one with the same name as each volume ID. Each time the volume exceptions are pulled into this db, the volume IDs can change. So, there is a query that runs that updates the volume table with the new IDs.
Unless you know a way to do this with a query, I need to write Access VBA code that will loop through the volume table, identify the name of each query and then run those queries until it reaches the end of the table. For example, the code needs to look at the first record in the volume table, say it is 1040. This is the name of the query that needs to run. The code then needs to find the query named 1040 and run it. It is a make table query.
The table name is FacilityVolume and it has one field named Volume. The value in the field is shorttext format even though it is numeric.
I've tried a couple of different things. Here is my latest try.
Dim db as Database
Dim vol as Recordset
Dim code as QueryDef
Set db = CurrentDb()
Set vol = db.OpenRecordset("FacilityVolume")
Set Volume = vol.Fields("Volume")
Vol.MoveFirst
Do Until vol.EOF = True
If QueryDef.Name = Volume Then
DoCmd.OpenQuery
Else MsgBox("The query does not exist")
vol.MoveNext
Loop
End Sub
I've searched the internet for a few days and can't find any reference to this particular code. I'm sure other users would like to know how to do this. I'm a novice and still learning VBA so any help you can provide is greatly appreciated.
Your code will loop through, even if you found your query and you do not pass the Query-Name to the OpenQuery command... This won't work...
The collection CurrentDb.QueryDefs knows all existing queries, but there is no "Exists" or "Contains" method.
So: The approach would be a loop (as you tried it) or an Error handling.
It's quite a time ago since I've coded with VBA, but I think you could try:
On Error Resume Next
DoCmd.OpenQuery "YourQueryName"
If Err Then
MsgBox("The query does not exist!")
Err.Clear
End If
On Error Goto 0
I recommend using full DAO in VBA to accomplish your goal. DoCmd.OpenQuery is really a VBA function that mimics the Macro RunQuery action. You don't get much control or true error handling capability.
Here is a complete code function that
Gives you an example of how to select all or some records from your table that lists the queries, including the ability to only select "Active" records, and even sort them in a particular execution sequence
Handles the instances where the query name in your table does not exist
Allows you to display a message about any errors that occur
Allows you to return an exit code to the calling procedure so that you can possibly act on the results of running these queries (such as choosing not to do the next step in your code if this function encounters an error of any kind (returns a non-zero value)
Here is the code. You will need to modify the SQL statement for your correct table name and field names, but this should be a good example to get you on your way.
Public Function lsProcessQuerySet() As Long
On Error GoTo Err_PROC
Dim ErrMsg As String
Dim db As DAO.Database
Dim rstEdits As DAO.Recordset
Dim qdf As DAO.QueryDef
Dim mssql As String
Dim ReturnCode As Long
Set db = CurrentDb()
'============================
'Select the list of Queries you want to process
'============================
mssql = "SELECT tblQueryList.ID, tblQueryList.QueryName, "
mssql = mssql & "tblQueryList.QueryShortDesc "
mssql = mssql & "FROM tblQueryList "
mssql = mssql & "WHERE tblQueryList.QueryActive = True "
mssql = mssql & "ORDER BY tblQueryList.SortOrder;"
Set rstEdits = db.OpenRecordset(mssql, dbOpenDynaset)
DoCmd.Hourglass True
'============================
'Execute each query, allowing processing to continue
'if the query does not exist (an error occurs)
'============================
Do While Not rstEdits.EOF
Set qdf = db.QueryDefs(rstEdits("QueryName"))
qdf.Execute dbSeeChanges
ResumeNextEdit:
rstEdits.MoveNext
Loop
rstEdits.Close
Exit_PROC:
lsProcessQuerySet = ReturnCode
Set qdf = Nothing
Set rstEdits = Nothing
db.Close
Set db = Nothing
DoCmd.Hourglass False
Exit Function
Err_PROC:
Select Case Err.Number
Case 3265 'Item Not Found in this Collection
ReturnCode = Err.Number
ErrMsg = "Query Not Found:" & vbCrLf & vbCrLf
ErrMsg = ErrMsg & rstEdits("QueryName")
DoCmd.Hourglass False
MsgBox ErrMsg, vbOKOnly + vbCritical, "Function lsProcessQuerySet"
Resume ResumeNextEdit
Case Else
ReturnCode = Err.Number
ErrMsg = "Error: " & Err.Number & vbCrLf
ErrMsg = ErrMsg & Err.Description
DoCmd.Hourglass False
MsgBox ErrMsg, vbOKOnly + vbCritical, "Function lsProcessQuerySet"
Resume Exit_PROC
End Select
End Function
The answer of #Shnugo is already good. Just to give you a complete VBA function, this should be working for you.
Public Sub MySub()
On Error GoTo err_mySub
Dim db as Database
Dim vol as Recordset
Set db = CurrentDb()
Set vol = db.OpenRecordset("FacilityVolume", dbOpenDynaset) ' I don't know if you want to run all queries of the table "FacilityVolume".
'So maybe you could also use something like "SELECT Volume FROM FacilityVolume WHERE Volume LIKE ""*10*"""
Vol.MoveFirst
Do Until vol.EOF = True
DoCmd.OpenQuery vol!Volume
vol.MoveNext
Loop
exit_MySub:
Exit Sub
err_MySub:
If Err.Number = 7874 Then
MsgBox "The Query """ & Vol!Volume & """ wasn't found."
Resume Next
Else
MsgBox Err.Description
Resume exit_MySub
End If
End Sub
Using Access 2010, I have a form for Purchase_Orders where the status changes depending on the whether the Items in the sub form have been delivered or not, and, it is influenced by the date as well.
Private Sub Form_AfterUpdate()
Dim rs As Recordset
Dim db As Database
Dim var_Delivered As String
var_Delivered = "SELECT Count(*) AS d_Count" & _
" FROM Items" & _
" WHERE PO_ID =" & Me.PO_ID.Value & _
" AND Supplier_Dnote_ID IS Null" & _
" AND Delivered_Without_Dnote =0;"
Set db = CurrentDb
Set rs = db.OpenRecordset(var_Delivered, dbOpenDynaset)
'MsgBox rs!d_Count
If rs!d_Count > 0 Then
If Me.Supply_date < Date Then
Me.Status = "Overdue"
Else
Me.Status = "Submitted"
End If
Else
Me.Status = "Delivered"
End If
db.Close
Set db = Nothing
Set rs = Nothing
End Sub
This runs after_update of the Purchase_Orders. I have a save_close button that uses the following code and doesn't return an error:
If Me.Dirty = True Then
DoCmd.Close acForm, "Purchase_Orders", acSaveYes
Else
DoCmd.Close acForm, "Purchase_Orders", acSaveNo
End If
However, I also have a Save button that doesn't close the form. This is where I get run-time error 2759 : The method you tried to invoke on an object failed. Debug Highlights the saverecord line.
Private Sub SaveOnlyBtn_Click()
If Me.Dirty = True Then
docmd.RunCommand acCmdSaveRecord
End If
End Sub
If I comment the status code out and use the save button, the record saves fine without any errors. Why do I get this error? I'm completely stumped and searching the error online hasn't helped me either.
So I found that the error did not occur when I put the code in the "on dirty" event, which then made me realise that I don't need necessarily have to run the code after the form updates, only when specific fields change. So I changed my code to a public code and called it when supply date, delivered_without_dnote, or supplier_Invoice_ID changed.
the public code is :
Public Sub delivered_status()
On Error GoTo errTrap1
If Forms!Purchase_Orders_Ex.Form!Status = "Cancelled" Then
Exit Sub
Else
DoCmd.RunCommand acCmdSaveRecord
Dim rs As Recordset
Dim db As Database
Dim var_Delivered As String
var_Delivered = "SELECT Count(*) AS d_Count" & _
" FROM Items" & _
" WHERE PO_ID =" & Forms!Purchase_Orders_Ex.Form!PO_ID.Value & _
" AND Supplier_Dnote_ID IS Null" & _
" AND Delivered_Without_Dnote =0;"
Set db = CurrentDb
Set rs = db.OpenRecordset(var_Delivered, dbOpenDynaset)
'MsgBox "Outstanding Items: " & rs!d_Count
If rs!d_Count > 0 Then
If Forms!Purchase_Orders_Ex.Form!Supply_date < Date Then
Forms!Purchase_Orders_Ex.Form!Status = "Overdue"
Else
Forms!Purchase_Orders_Ex.Form!Status = "Submitted"
End If
Else
Forms!Purchase_Orders_Ex.Form!Status = "Delivered"
End If
rs.Close
Set db = Nothing
Set rs = Nothing
End If
errTrap1:
Select Case Err.Number
Case 3314 'form not complete and other required fields are empty
Exit Sub
Case Else
If Err.Number > 0 Then
MsgBox Err.Number & ": " & Err.Description
End If
End Select
End Sub
Now, when I use either the save_close or Save_Only I do not get error 2759. I do not completely understand which part of my original method caused the error but it no longer occurs with this approach.
I've just encountered this issue and moving code out of Form_AfterUpdate fixed it for me too.
What's (vaguely) interesting is that the code in question worked fine locally, but did not work when deployed to the client. I tried importing just the amended form instead of replacing the whole access app, but I still got the same issue. I also copied the back-end database back from the server to my development machine, but still didn't get the issue locally. On top of that I did endless compact/repair and decompile/compile.
My conclusion at the end of all of that was that this was yet another weird issue emanating from the Access black-box, rather than an issue with the particular code.
I'm using a code i found online to fill in form fields in a Word document. When i use it on an empty document and add to it a form field, it works. However, when i use it on the form i'm trying to fill nothing happens when i execute the code. I checked the name of the fields in Word and they match the code, i don't know what's wrong.
I also checked the data type in Access and it's not the problem, i don't have access to the code right now but does anyone have any idea of what's causing this?
Edit: Here is a similar code, i don't have access to the exact same one:
Dim appWord As Word.Application
Dim doc As Word.Document
'Avoid error 429, when Word isn't open.
Err.Clear
'Set appWord object variable to running instance of Word.
Set appWord = GetObject(, "Word.Application")
If Err.Number <> 0 Then
'If Word isn't open, create a new instance of Word.
Set appWord = New Word.Application
End If
Set doc = appWord.Documents.Open("C:\Users\" & Environ$("Username") & "\Desktop\Form.doc", , True)
With doc
.FormFields("TextEn").Result = DLookup("[End date]", "[Table1]", "[Table1]![ID Number] =" & [ID2])
.FormFields("TextSt").Result = DLookup("[Starting date]", "[Table1]", "[Table1]![ID Number] =" & [ID2])
.Visible = True
.Activate
End With
Set doc = Nothing
Set appWord = Nothing
Exit Sub
errHandler:
MsgBox Err.Number & ": " & Err.Description
You could try to validate that your dlookup is returning a value with the following:
If DCount("[End date]", "[Table1]", "[Table1]![ID Number] =" & [ID2]) > 0 then
.FormFields("TextEn").Result = DLookup("[End date]", "[Table1]", "[Table1]![ID Number] =" & [ID2])
End If
You would have to do this for each lookup before trying to set your fields.
Variety of ways to get a list of report names:
Query
SELECT [Name] FROM MsysObjects
WHERE ([Type] = -32764)
Or VBA
Dim rpt As AccessObject
Dim dB As Object
On Error GoTo Error_Handler
Set dB = Application.CurrentProject
For Each rpt In dB.AllReports
Debug.Print rpt.Name
Next rpt
A report can have a Description under the Properties (Right-Click on report object), but I cannot access with code.
I'd like to have a listbox display a user-friendly report name associated with the actual report name. I'm trying to avoid creating a separate table to manage this at this point.
CurrentProject is an ADO object, and I don't know how to do what you want from ADO. You can use DAO to retrieve the Description property.
? CurrentDb.Containers("Reports").Documents("rptFoo").Properties("Description")
Foo Report
Since Description is a user-defined property, it doesn't exist until you assign a value for it. Therefore the next line triggers error 3270 (Property not found) for rptLinks, since it doesn't have a Description assigned.
? CurrentDb.Containers("Reports").Documents("rptLinks").Properties("Description")
You could trap that error. Or see if you can make use of Allen Browne's HasProperty function
A totally different approach would be to create tblReports with report_name and friendly_name fields. You would have to maintain that table, but the workload should be roughly equivalent to maintaining the Description properties on the report objects. Then you could use a simple SELECT on the table as the RowSource for your list box.
Update: You could also SELECT from MSysObjects with a custom function to return the Description for each report.
Public Function ReportDescription(ByVal pName As String) As String
Dim strReturn As String
Dim strMsg As String
On Error GoTo ErrorHandler
strReturn = _
CurrentDb.Containers("Reports").Documents(pName).Properties("Description")
ExitHere:
On Error GoTo 0
ReportDescription = strReturn
Exit Function
ErrorHandler:
Select Case Err.Number
Case 3270 'Property not found.'
'strReturn = "(no Description)"'
'* no Description -> just echo report name *'
strReturn = pName
Case Else
strMsg = "Error " & Err.Number & " (" & Err.description _
& ") in procedure ReportDescription"
MsgBox strMsg
strReturn = vbNullString
End Select
GoTo ExitHere
End Function
Revise your original query to use the function.
SELECT
[Name] AS report_name,
ReportDescription([Name]) AS friendly_name
FROM MsysObjects
WHERE ([Type] = -32764);