Set Startup Display Form using VBA - vba

Is it possible to change the Startup Display Form using VBA? It is very easy to do using the Access Options page, but I am trying to do this from within VBA and nothing seems to work. I've searched all over looking for Database properties or settings that would allow for this.
Does anyone have any insight into this issue?

I don't know about directly changing the startup form property but what you could try is creating a form that can load your desired startup form. This way you can for instance store the form to be loaded in a config table and change it via VBA.
Downside is that effectively two forms are started and not one.

Have a look at the autoexec macro. It'll run code for you when your database is launched. Use this to load a form.

You can set a form to automatically open up in access VBA by setting the built-in database property StartUpForm to the name of the form.
To remove this form from startup you can simply delete that property.
Private Sub debug_properties()
ListProperties
SetProperty "StartupForm", 10, "Form_Name" 'UPDATE TO YOUR FORM NAME
' DeleteProperty "StartupForm"
' ListProperties
End Sub
Public Function SetProperty(ByVal propName As String, ByVal propType As Long, propValue As Variant)
''SetProperty will create a property if it doesn't exist
On Error GoTo SetProperty_Err
Dim dbs As DAO.Database ''Reference: Microsoft Office 16.0 Access database engine Object Library 'ACEDAO.DLL 'Access.References.AddFromGuid "{4AC9E1DA-5BAD-4AC7-86E3-24F4CDCECA28}", 0, 0
Set dbs = CurrentDb
Dim prps As DAO.Properties ''Reference: Microsoft Office 16.0 Access database engine Object Library 'ACEDAO.DLL 'Access.References.AddFromGuid "{4AC9E1DA-5BAD-4AC7-86E3-24F4CDCECA28}", 0, 0
Set prps = dbs.Properties
''attempt to set property
prps(propName) = propValue
SetProperty_Exit:
On Error Resume Next
On Error GoTo 0
Exit Function
SetProperty_Err:
Select Case Err.Number
Case 3270 ''The property was not found
''create property
Dim prp As DAO.Property
Set prp = dbs.CreateProperty(Name:=propName, _
Type:=propType, _
Value:=propValue)
''add new property to collection
dbs.Properties.Append prp
Case Else
MsgBox "SetProperty, Error " & Err.Number & ": " & Err.Description
End Select
Resume SetProperty_Exit
End Function
Private Function DeleteProperty(ByVal propName As String)
On Error GoTo DeleteProperty_Err
Dim dbs As DAO.Database ''Reference: Microsoft Office 16.0 Access database engine Object Library 'ACEDAO.DLL 'Access.References.AddFromGuid "{4AC9E1DA-5BAD-4AC7-86E3-24F4CDCECA28}", 0, 0
Set dbs = CurrentDb
dbs.Properties.Delete propName
DeleteProperty_Exit:
On Error Resume Next
On Error GoTo 0
Exit Function
DeleteProperty_Err:
Select Case Err.Number
Case 3265 ''The property was not found
MsgBox "Property '" & propName & "' does not exist."
Case Else
MsgBox "DeleteProperty, Error " & Err.Number & ": " & Err.Description
End Select
Resume DeleteProperty_Exit
End Function
Private Sub ListProperties()
''Lists DB properties created in code (as well as built-in properties)
Dim dbs As DAO.Database ''Reference: Microsoft Office 16.0 Access database engine Object Library 'ACEDAO.DLL 'Access.References.AddFromGuid "{4AC9E1DA-5BAD-4AC7-86E3-24F4CDCECA28}", 0, 0
Set dbs = Application.CurrentDb
Debug.Print vbCrLf & Format(Now, "hh:mm:ss") & " ======="
Debug.Print """" & Mid(CurrentDb.Name, _
InStrRev(CurrentDb.Name, "\") + 1, _
InStr(CurrentDb.Name, ".accdb") - InStrRev(CurrentDb.Name, "\") - 1) & _
""" Properties: "
On Error Resume Next 'skips the 'connection' property which has no 'value' for some reason
Dim prp As DAO.Property
For Each prp In dbs.Properties
Debug.Print prp.Name & ": " & prp.Value
Next prp
On Error GoTo 0
End Sub

Related

Trying to get to the code lines of a form's module in a remote project

I am trying to list code lines of all procedures in a remote MS Access project. There is no problem with the standard or class modules but when I get to the forms, I cannot access their modules properties.
Public Sub TestFrms(MyDataBaseFullName)
'MyDataBaseFullName should be a valid full name (Path & Name)
'of an MS Access DataBase mdb or accdb local file
Dim appAccess As Access.Application
Dim xObj As AccessObject
Dim xFrm As Form
Dim xMdl As Module
Dim i As Long
On Error GoTo Error
Set appAccess = New Access.Application
Call appAccess.OpenCurrentDatabase(MyDataBaseFullName)
For Each xObj In appAccess.CurrentProject.AllForms
For i = 0 To appAccess.CurrentProject.AllForms.Count - 1
'Here I am trying to get to the forms module
'because I want to lit all its code lines
'I think understand that the AllForms property does not contain
'a list of all the Forms objects but only a collection of AccessObject
'but is there a way to get to the Form's module?
'Assuming AllForms contains a collection of forms
'this next line should work and I could get to the
'Code Lines of each procedure in that module
'' Set xMdl = appAccess.CurrentProject.AllForms(i).Module
Next i
Next
NormalEnding:
'Fermer la base de données
appAccess.CloseCurrentDatabase
Set appAccess = Nothing
Set xObj = Nothing
Exit Sub
Error:
'Aviser l'utilisateur
Call MsgBox("Error " & Err.Number & " (" & Err.Description & ")", vbCritical)
GoTo NormalEnding
End Sub
To get a form's module, you need to open the form in design view.
For Each xObj In appAccess.CurrentProject.AllForms
appAccess.DoCmd.OpenForm xObj.Name, 1 '1 = acDesign
Debug.Print appAccess.Forms(xObj.Name).Module.Lines(1, 10000) 'Print the first 10K lines
'If you want to print all lines with no maximum, use `Module.CountOfLines` to get the count
appAccess.DoCmd.Close 2, xObj.Name '2 = acForm
Next

VBA - Unable to map drive to sharepoint on another computer

I'm mapping to the company's sharepoint drive using VBA. The intention is to save local file to sharepoint, and delete local file and unmapped the drive after success.
On my machine(Windows 10 64bits), the code works perfectly fine, successfully mapped the drive, created folder and file, successfully uploaded to sharepoint and unmap the drive.
However, when I run the same excel workbook that contains the same code on my colleague's computer(Window 7), it failed. There's no error being shown, except that it keeps on loading and loading until Excel Not Responsive. I tried manually mapping the drive, it success.
I tried to debug and found out that the code stops (keeps on loading) at MsgBox "Hello" but could not figure out what's missing.
Both are using Excel 2016
Any help and suggestions are appreciated. let me know if more info is needed. Thanks in advance.
This is my vba code
Sub imgClicked()
Dim fileName As String
Dim SharePointLib As String
Dim MyPath As String
Dim folderPath As String
Dim objNet As Object
Dim copyPath As String
Dim copyFilePath As String
folderPath = Application.ThisWorkbook.path
MyPath = Application.ThisWorkbook.FullName
Dim objFSO As Object
Dim strMappedDriveLetter As String
Dim strPath As String
Dim spPath As String
strPath = "https://company.com/sites/test/test 123/" 'example path
spPath = AvailableDriveLetter + ":\test.xlsm" 'example path
copyPath = folderPath + "\copyPath\"
'Add reference if missing
Call AddReference
Set objFSO = CreateObject("Scripting.FileSystemObject")
With objFSO
strMappedDriveLetter = IsAlreadyMapped(.GetParentFolderName(strPath))
If Not Len(strMappedDriveLetter) > 0 Then
strMappedDriveLetter = AvailableDriveLetter
If Not MapDrive(strMappedDriveLetter, .GetParentFolderName(strPath)) Then
MsgBox "Failed to map SharePoint directory", vbInformation, "Drive Mapping Failure"
Exit Sub
End If
End If
' Check file/folder path If statement here
End With
Set objFSO = Nothing
End Sub
Code for getting available drive
' Returns the available drive letter starting from Z
Public Function AvailableDriveLetter() As String
' Returns the last available (unmapped) drive letter, working backwards from Z:
Dim objFSO As Object
Dim i As Long
Set objFSO = CreateObject("Scripting.FileSystemObject")
For i = Asc("Z") To Asc("A") Step -1
Select Case objFSO.DriveExists(Chr(i))
Case True
Case False
Select Case Chr(i)
Case "C", "D" ' Not actually necessary - .DriveExists should return True anyway...
Case Else
AvailableDriveLetter = Chr(i)
Exit For
End Select
End Select
Next i
Set objFSO = Nothing
MsgBox "This is the next available drive: " + AvailableDriveLetter ' returns Z drive
MsgBox "Hello" ' After this msgBox, starts loading until Not Responsive
End Function
Function to Map drive
Public Function MapDrive(strDriveLetter As String, strDrivePath As String) As Boolean
Dim objNetwork As Object
If Len(IsAlreadyMapped(strDrivePath)) > 0 Then Exit Function
Set objNetwork = CreateObject("WScript.Network")
objNetwork.MapNetworkDrive strDriveLetter & ":", strDrivePath, False
MapDrive = True
MsgBox "Successfully Created the Drive!"
Set objNetwork = Nothing
End Function
Code for MappedDrive
Public Function GetMappedDrives() As Variant
' Returns a 2-D array of (1) drive letters and (2) network paths of all mapped drives on the users machine
Dim objFSO As Object
Dim objDrive As Object
Dim arrMappedDrives() As Variant
Dim i As Long
Set objFSO = CreateObject("Scripting.FileSystemObject")
ReDim arrMappedDrives(1 To 2, 1 To 1)
For i = Asc("A") To Asc("Z")
If objFSO.DriveExists(Chr(i)) Then
Set objDrive = objFSO.GetDrive(Chr(i))
If Not IsEmpty(arrMappedDrives(1, UBound(arrMappedDrives, 2))) Then
ReDim Preserve arrMappedDrives(1 To 2, 1 To UBound(arrMappedDrives, 2) + 1)
End If
arrMappedDrives(1, UBound(arrMappedDrives, 2)) = Chr(i) ' Could also use objDrive.DriveLetter...
arrMappedDrives(2, UBound(arrMappedDrives, 2)) = objDrive.ShareName
End If
Next i
GetMappedDrives = arrMappedDrives
Set objDrive = Nothing
Set objFSO = Nothing
End Function
Public Function IsAlreadyMapped(strPath As String) As String
' Tests if a given network path is already mapped on the users machine
' (Returns corresponding drive letter or ZLS if not found)
Dim strMappedDrives() As Variant
Dim i As Long
strMappedDrives = GetMappedDrives
For i = LBound(strMappedDrives, 2) To UBound(strMappedDrives, 2)
If LCase(strMappedDrives(2, i)) Like LCase(strPath) Then
IsAlreadyMapped = strMappedDrives(1, i)
Exit For
End If
Next i
Set objNetwork = Nothing
End Function
Add Reference
Sub AddReference()
'Macro purpose: To add a reference to the project using the GUID for the
'reference library
Dim strGUID As String, theRef As Variant, i As Long
'Update the GUID you need below.
strGUID = "{420B2830-E718-11CF-893D-00A0C9054228}"
'Set to continue in case of error
On Error Resume Next
'Remove any missing references
For i = ThisWorkbook.VBProject.References.Count To 1 Step -1
Set theRef = ThisWorkbook.VBProject.References.Item(i)
If theRef.isbroken = True Then
ThisWorkbook.VBProject.References.Remove theRef
End If
Next i
'Clear any errors so that error trapping for GUID additions can be evaluated
Err.Clear
'Add the reference
ThisWorkbook.VBProject.References.AddFromGuid _
GUID:=strGUID, Major:=1, Minor:=0
'If an error was encountered, inform the user
Select Case Err.Number
Case Is = 32813
'Reference already in use. No action necessary
Case Is = vbNullString
'Reference added without issue
Case Else
'An unknown error was encountered, so alert the user
MsgBox "A problem was encountered trying to" & vbNewLine _
& "add or remove a reference in this file" & vbNewLine & "Please check the " _
& "references in your VBA project!", vbCritical + vbOKOnly, "Error!"
End Select
On Error GoTo 0
End Sub
Procedure imgClicked is calling function AvailableDriveLetter multiple times. Remember that the function has to execute each time you refer to it.
I ran imgClicked (assuming that's the procedure you start with) and I was told, twice, "Next available letter = Z" and "Hello" and then it crashed Excel (perhaps getting stuck in a loop of creating FileSystem objects to look for an available drive letter?)
Try assigning AvailableDriveLetter to a variable (string) at the beginning of the procedure and referring to the variable each time you need the value, and see if you still have the issue.
(Remember to save before execution -- I get frustrated when troubleshooting "application hanging" issues because I keep forgetting to save my changes and then lose them on the crash!)
If this doesn't work, add a breakpoint (F9) on the End Function line after your "Hello" box and see if the code stops there. (I have trouble believing the MsgBox or End Function are the culprit.) If not, which procedure runs after that?
One more thing whether the issue is resolved or not:
Add Option Explicit at the very beginning of your module and then Compile the project and fix your missing variable declaration(s).
This is recommended whenever troubleshooting an issue as a means to eliminate variable declaration issues as a possible cause.

using IMAPI in excel vba to burn dvd(s)

I am encountering a run-time error while using IMAPI. The error:
Adding a file or folder would result in a result image having a size larger than the current configured limit.
It works great for anything that doesn't exceed the type of media in the optical drive, else I get the above.
I saw a post from A_J here that leans toward a possible solution in C#:
fileSystemImage.FreeMediaBlocks = int.MaxValue;
I am looking for help in writing the above, but in 2013 Excel VBA.
Below is a copy of what I'm using:
Option Explicit
Sub TestCDWrite()
Application.DisplayAlerts = False
Dim objDiscMaster As IMAPI2.MsftDiscMaster2
Dim objRecorder As IMAPI2.MsftDiscRecorder2
Dim DataWriter As IMAPI2.MsftDiscFormat2Data
Dim intDrvIndex As Integer
'The Object browser, but not intellisense, presents types for these, but they cannot be used in VBA
Dim stream As Variant
Dim FS As Variant
Dim Result As Variant
Dim FSI As Object
Dim strBurnPath As String
Dim strUniqueID As String
' *** CD/DVD disc file system types
Const FsiFileSystemISO9660 = 1
Const FsiFileSystemJoliet = 2
Const FsiFileSystemUDF102 = 4
'On Error GoTo TestCDWrite_Error
intDrvIndex = 0
strBurnPath = Worksheets("mphoi").Range("AF2")
' Create a DiscMaster2 object to connect to optical drives.
Set objDiscMaster = New IMAPI2.MsftDiscMaster2
' Create a DiscRecorder2 object for the specified burning device.
Set objRecorder = New IMAPI2.MsftDiscRecorder2
strUniqueID = objDiscMaster.Item(intDrvIndex)
objRecorder.InitializeDiscRecorder (strUniqueID)
' Create a DiscFormat2Data object and set the recorder
Set DataWriter = New IMAPI2.MsftDiscFormat2Data
DataWriter.Recorder = objRecorder
DataWriter.ClientName = "IMAPIv2 TEST"
' Create a new file system image object
Set FSI = New IMAPI2FS.MsftFileSystemImage
fsi.freemediablocks=int.maxvalue
' Import the last session, if the disc is not empty, or initialize
' the file system, if the disc is empty
If Not DataWriter.MediaHeuristicallyBlank Then
On Error Resume Next
FSI.MultisessionInterfaces = DataWriter.MultisessionInterfaces
If Err.Number <> 0 Then
MsgBox "Multisession is not supported on this disc", vbExclamation, "Data Archiving"
GoTo ExitHere
End If
On Error GoTo 0
MsgBox "Importing data from previous session ...", vbInformation, "Data Archiving"
FS = FSI.ImportFileSystem()
Else
FS = FSI.ChooseImageDefaults(objRecorder)
End If
' Add the directory and its contents to the file system
MsgBox "Adding " & strBurnPath & " folder to the disc...", vbInformation, "Data Archiving"
FSI.Root.AddTree strBurnPath, False
' Create an image from the file system image object
Set Result = FSI.CreateResultImage()
Set stream = Result.ImageStream
' Write stream to disc using the specified recorder
MsgBox "Writing content to the disc...", vbInformation, "Data Archiving"
DataWriter.Write (stream)
MsgBox "Completed writing Archive data to disk ", vbInformation, "Data Archiving"
ExitHere:
Exit Sub
'Error handling block
TestCDWrite_Error:
Select Case Err.Number
Case Else
MsgBox "Error " & Err.Number & ": " & Err.Description, vbCritical, "TestCode.TestCDWrite"
End Select
Resume ExitHere
Application.DisplayAlerts = True
'End Error handling block
End Sub

Access 2007 to 2010 Conversion Compile Error: User-defined type not defined

I recently converted (exported/imported) a 2007 Access file to 2010. Everything works fine except one form. I keep getting the error:
Compile error: User-defined type not defined
I tried adding "Microsoft ActiveX Data Objects 2.8" to my References, but the problem still exists. Sub ClearTreeView(tvwTree As TreeView) is what Access highlighted as the issue.
Option Compare Database
Option Explicit
' Clears all nodes on a treeview control
Sub ClearTreeView(tvwTree As TreeView) 'what Access highlighted as the issue
On Error GoTo EH
tvwTree.Nodes.Clear
Exit Sub
EH:
MsgBox "Error " & Err.Number & ": " & Err.Description
End Sub
' Calls functions to clear and populate a treeview control
' Parameters:
' strForm Name of the form
' strTV TreeView control name
' strSourceName Name of the table or query containing the data used to populate the treeview
' strChildField ID field for the child records
' strParentField Parent ID Field
' strTextField Field containing text that will be used as node labels
'
Sub FillTreeView(tvwTree As Object, strSourceName As String, strChildField As String, strParentField As String, strTextField As String)
Dim strSQL As String
Dim rs As DAO.Recordset
On Error GoTo EH
' Open the recordset using table and fields specified in Sub parameters
strSQL = "SELECT " & strChildField & ", " & strParentField & ", " & strTextField & " FROM " & strSourceName
Set rs = CurrentDb.OpenRecordset(strSQL, dbOpenDynaset)
' Clear any existing data out of the treeview
ClearTreeView tvwTree
' Call recursive function to fill in treeview
AddTreeData tvwTree, rs, strChildField, strParentField, strTextField
' Close the recordset
rs.Close
Set rs = Nothing
Exit Sub
EH:
MsgBox "Error " & Err.Number & ": " & Err.Description
End Sub
' Recursive function to populate a treeview control
' Parameters:
' strFormName Name of the form
' strTreeViewName TreeView control name
' rs Recordset containing the data used to populate the treeview
' strChildField ID field for the child records
' strParentField Parent ID Field
' strTextField Field containing text that will be used as node labels
' varParentID Optional parameter that only gets passed for recursive calls to this function. Specifies the ID of the current record to be used as a
' ParentID when searching the recordset for "grand-children", etc.
Sub AddTreeData(objTV As TreeView, rs As DAO.Recordset, strChildField As String, strParentField As String, strTextField As String, Optional varParentID As Variant)
Dim nodChild As Node
Dim nodParent As Node
Dim strLabel As String
Dim strNodeID As String
Dim strCriteria As String
Dim strBookmark As String
On Error GoTo EH
' Test for a circular reference
If rs(strChildField) = rs(strParentField) Then GoTo EH_CircularReference
' If the optional parameter is missing, then this is the first(non-recursive) call to this function.
' Set the critieria to look for a parent id of 0.
If IsMissing(varParentID) Then
strCriteria = strParentField & " = 0 "
Else
' Otherwise, extract the childID portion of the node ID, which was passed as an optional parameter.
strCriteria = strParentField & " = " & Mid(varParentID, InStr(1, varParentID, "C") + 1)
' Define the parent node
Set nodParent = objTV.Nodes("node" & varParentID)
End If
' Look for records having the specified "parent"
rs.FindFirst strCriteria
Do Until rs.NoMatch
' Read node caption from the text field
strLabel = rs(strTextField)
' Create a new node ID in the format ParentID &"C" & ChildID (eg: 4C12)
strNodeID = "node" & rs(strParentField) & "C" & rs(strChildField)
' If optional parameter is missing (first call to this function)...
If Not IsMissing(varParentID) Then
'add new node to the next higher node for this record
Set nodChild = objTV.Nodes.Add(nodParent, tvwChild, strNodeID, strLabel)
Else
' Otherwise, add new node to the top level of the tree
Set nodChild = objTV.Nodes.Add(, , strNodeID, strLabel)
End If
' Bookmark our place in the recordset so that we can resume the search from the same point after the recursive call to this function.
strBookmark = rs.Bookmark
' call this function recursively for "children"
AddTreeData objTV, rs, strChildField, strParentField, strTextField, rs(strParentField) & "C" & rs(strChildField)
' Return to bookmared place in the recordset
rs.Bookmark = strBookmark
' Find the next record having the same parentID
rs.FindNext strCriteria
Loop
Exit Sub
EH_CircularReference:
MsgBox "Exiting because of a circular reference in which a child record was determined to be it's own parent."
Exit Sub
EH:
MsgBox "Error " & Err.Number & ": " & Err.Description
End Sub
I received the same error on one of my User Forms in Excel!
If your new 2010 Office package is 64Bit, then the previous 32-Bit ActiveX Controls used in the 2007 version will not be compatible.
Refer to this link: http://msdn.microsoft.com/en-us/library/ee691831(office.14).aspx#odc_office2010_Compatibility32bit64bit_ActiveXControlCOMAddinCompatibility
If you try opening the form in design view and the TreeView control doesn't exist on the form, then this is likely to be the issue.
To find if you installed the 64-bit version:
Open Access -> File -> Help -> and look under "About Microsoft Access" on the right - it should say 32-Bit or 64-Bit in brackets
As the link explains, you will have to replace the incompatible functionality - so you will have to use a new control.
Possible Solution:
If you open the form in design view, and select the down arrow on the Controls Group in the Ribbon Tab - there should be an option named "ActiveX Controls" (You have to be in design view to select it)
Search here for the "CTreeView" Control and try working with that instead of the traditional Microsoft TreeView Control (which shouldn't be listed on 64-Bit Access).
If you have 32-Bit office installed, then I can't figure out the problem with what you have posted - but I suspect it's the case.
Best Regards,

How to list DataMacro objects in an Access database?

Is it possible to programmatically enumerate the Data Macros in an Access 2010+ database? If so, how?
Note: Data Macros are trigger-like procedures that are created in the context of the table designer UI. They were new in Acces 2010. They are NOT the same thing as normal macros, which are easy to enumerate.
They have their own new AcObjectType enumeration value : acTableDataMacro, but I can find no other aspect of the Access or DAO object model that refers to them. They do not even appear in the MSysObjects table.
This code will export DataMacro metadata to an XML Document (Source):
Sub DocumentDataMacros()
'loop through all tables with data macros
'write data macros to external files
'open folder with files when done
' click HERE
' press F5 to Run!
' Crystal
' April 2010
On Error GoTo Proc_Err
' declare variables
Dim db As DAO.Database _
, r As DAO.Recordset
Dim sPath As String _
, sPathFile As String _
, s As String
' assign variables
Set db = CurrentDb
sPath = CurrentProject.Path & "\"
s = "SELECT [Name] FROM MSysObjects WHERE Not IsNull(LvExtra) and Type =1"
Set r = db.OpenRecordset(s, dbOpenSnapshot)
' loop through all records until the end
Do While Not r.EOF
sPathFile = sPath & r!Name & "_DataMacros.xml"
'Big thanks to Wayne Phillips for figuring out how to do this!
SaveAsText acTableDataMacro, r!Name, sPathFile
'have not tested SaveAsAXL -- please share information if you do
r.MoveNext
Loop
' give user a message
MsgBox "Done documenting data macros for " & r.RecordCount & " tables ", , "Done"
Application.FollowHyperlink CurrentProject.Path
Proc_Exit:
' close and release object variables
If Not r Is Nothing Then
r.Close
Set r = Nothing
End If
Set db = Nothing
Exit Sub
Proc_Err:
MsgBox Err.Description, , _
"ERROR " & Err.Number _
& " DocumentDataMacros"
Resume Proc_Exit
Resume
End Sub
EDIT: Gord pointed out that you wanted the DataMacros opposed to standard macros. I found some code and tested it (it works) here
I tested the top function when you follow that link and it saves information regarding your table macros for each table in an XML document. It works nicely, props to whoever wrote it.