How to encrypt Access with password using code? - ms-access

I created a Deploy Access file which I use to deploy my production Access file. This re-links tables to production SQL server, incorporates disabling use of Shift, add new version number.... I need also encrypt the production Access file with a password. This should be done using code in my Deploy Access file but I cannot find a way to do it. Any ideas? Thanks.

Try this function:
Public Function SetDatabasePassword(strDatabasePath As String, Optional pNewPassword As Variant, Optional pOldPassword As Variant) As String
On Error GoTo SetDatabasePassword_Error
DoCmd.Hourglass True
Const cProvider = "Microsoft.ACE.OLEDB.12.0"
Dim cnn As ADODB.Connection
Dim strNewPassword As String
Dim strOldPassword As String
Dim strCommand As String
Dim strResult As String
' If a password is not specified (IsMissing), ' the string is "NULL" WITHOUT the brackets
If IsMissing(pNewPassword) Then
strNewPassword = "NULL"
Else
strNewPassword = "[" & pNewPassword & "]"
End If
If IsMissing(pOldPassword) Then
strOldPassword = "NULL"
Else
strOldPassword = "[" & pOldPassword & "]"
End If
strCommand = "ALTER DATABASE PASSWORD " & strNewPassword & " " & strOldPassword & ";"
Set cnn = New ADODB.Connection
With cnn
.Mode = adModeShareExclusive
.Provider = cProvider
If Not IsMissing(pOldPassword) Then
.Properties("Jet OLEDB:Database Password") = pOldPassword
End If
.Open "Data Source=" & strDatabasePath & ";"
.Execute strCommand
End With
strResult = "Password Set"
ExitProc_:
On Error Resume Next
cnn.Close
Set cnn = Nothing
SetDatabasePassword = strResult
DoCmd.Hourglass False
Exit Function
SetDatabasePassword_Error:
DoCmd.Hourglass False
If Err.Number = -2147467259 Then
strResult = "An error occured"
ElseIf Err.Number = -2147217843 Then
strResult = "Invalid password"
Else
strResult = Err.Number & " " & Err.Description
End If
Resume ExitProc_
Resume ' use for debugging
End Function

Related

Why does connection string work on development machine only?

I have written 2 programs, one in VB6 and one in VBA for Excel. Calling the mySQL connection works perfectly in both on the development machine only. Trying to run either program on any other machine fails. Code is as follows:
Private Sub cmdErrors_Click()
On Error GoTo remote_err
Set myCon = New ADODB.Connection
strConnect = "Driver={MySQL ODBC 5.3 ANSI
Driver};Server=xxx.xxx.xxx.xxx;Port=3306;Database=cl22-budget;User=username;
Password=password;Option=3;"
myCon.ConnectionString = strConnect
myCon.Open
MsgBox "Connected"
myCon.Close
Set myCon = Nothing
Exit Sub
remote_err:
Dim ErrorCollection As Variant
Dim ErrLoop As Error
Dim strError As String
Dim iCounter As Integer
On Error Resume Next
iCounter = 1
strError = ""
Set ErrorCollection = myCon.Errors
For Each ErrLoop In ErrorCollection
With ErrLoop
strError = "error # " & iCounter & vbCrLf
strError = strError & "ADO Error # " & .Number & vbCrLf
strError = strError & " Description " & .Description & vbCrLf
strError = strError & " Source " & .Source & vbCrLf
MsgBox strError
iCounter = iCounter + 1
End With
Next
End Sub
Install ODBC Driver and create a DSN for your DB and there it will ask for server address there you mention your server ip then it will work.

Linking tables in Access

I have an access database that links to 6 tables. These tables are updated weekly and kept in a folder with the date. I would like for my access program to ask the user to select the location of the tables with out specifically using the Linked Table Manager.
The following code will prompt a user for the full path and file name of the database to be linked to. I decided to do this rather than just prompt for a folder. I strongly suggest you look at the connect string for one of your linked tables and make sure no other parameters are specified other than something like ';DATABASE=C:\Foldera\YYMMDD\MyAccessDB.mdb"
Private Function ReLinkTables()
Dim dbs As DAO.Database
Dim tdf As DAO.TableDef
Dim tdf2 As DAO.TableDef
Dim strConn As String
Dim strNewPath As String
Dim strTableName As String
On Error GoTo ERROR_HANDLER
' Prompt user for new path...
strNewPath = GetFolder
' Exit if none
If strNewPath = "" Then
Exit Function
End If
Set dbs = CurrentDb
dbs.TableDefs.Refresh
' Find all the linked tables...
For Each tdf In dbs.TableDefs
'Debug.Print tdf.Name & vbTab & tdf.Connect
If Len(tdf.Connect) > 0 Then
strTableName = tdf.Name
Debug.Print "Linked Table: " & tdf.Name & vbTab & tdf.Connect
dbs.TableDefs.Delete strTableName ' Delete the linked table
strConn = ";DATABASE=" & strNewPath
Set tdf2 = CurrentDb.CreateTableDef(strTableName, dbAttachSavePWD, strTableName, strConn)
CurrentDb.TableDefs.Append tdf2
Else ' Not a linked table
'Debug.Print "Keep: " & tdf.Name & vbTab & tdf.Connect
End If
Next tdf
Set tdf = Nothing
Set tdf2 = Nothing
dbs.TableDefs.Refresh
dbs.Close
Set dbs = Nothing
MsgBox "Finished Relinking Tables"
Proc_Exit:
Exit Function
ERROR_HANDLER:
Debug.Print Err.Number & vbTab & Err.Description
Err.Source = "Module_Load_SQLSERVER_DATABASE: ReLinkTables at Line: " & Erl
If Err.Number = 9999 Then
Resume Next
End If
MsgBox Err.Number & vbCrLf & Err.Description
Resume Proc_Exit
Resume Next
End Function
Function GetFolder() As String
Dim fldr As FileDialog
Dim sItem As String
Set fldr = Application.FileDialog(msoFileDialogFilePicker)
With fldr
.Title = "Select a Folder"
.AllowMultiSelect = False
'.InitialFileName = "Z:\xxxxxxxx" ' You can change to valid start path
If .Show <> -1 Then GoTo NextCode
sItem = .SelectedItems(1)
End With
NextCode:
Debug.Print "User selected path: >" & sItem & "<"
If sItem = "" Then MsgBox "User did not select a path.", vbOKOnly, "No Path"
GetFolder = sItem
Set fldr = Nothing
End Function

Can't save to local table when network access is interrupted.

I have a split database where the backend is located remotely; when I get the error "Network access has been interrupted" I want to log something on a local table for future access. After creating a system for this I found out that when the connection is lost to the remote backend the local tables also become inaccessible.
While I don't think there is necessarily a solution to this I want to find out why the local tables aren’t accessible when clearly they shouldn't require a network connection to be used. The following is the code for my function that I use to try and log locally.
Public Function LogTempError(ByVal lngErrNumber As Long, _
ByVal strErrDescription As String, _
strCallingProc As String, _
Optional varParameters As Variant, _
Optional blnSHOW_USER As Boolean = True) As Boolean
On Error GoTo Err_Handler
'Set warnings to True just in case the error happened while they were set to false.
DoCmd.SetWarnings True
Dim rs As DAO.Recordset
Set rs = DBEngine(0)(0).OpenRecordset("TempErrorTable", dbOpenDynaset, dbAppendOnly)
With rs
.AddNew
!ERROR_LOG_NUMBER = lngErrNumber
!ERROR_LOG_USERID = NetworkUserName()
!ERROR_LOG_DESCRIPTION = strErrDescription & " logged from Temp Table"
!ERROR_LOG_TIMESTAMP = Now()
!ERROR_LOG_FORM = strCallingProc
.Update
End With
Exit_Handler:
On Error Resume Next
rs.Close
Set rs = Nothing
Exit Function
Err_Handler:
If DateDiff("s", dteLAST_ERROR_TIME, Now()) > 20 Or lngLAST_ERROR_NUMBER <> lngErrNumber Then
' If there are more errors that can't be logged, simply email the errors.
SendEmail "First Unloggable error", "Error Num: " & Err.Number & " Error Description: " & strErrDescription & " From: " & strCallingProc
SendEmail "Second Unloggable error", "Error Num: " & Err.Number & " Error Description: " & Err.Description & " From: " & strCallingProc
MsgBox "An error occured that wasn't able to be logged, a message was sent to Database Administrator on your behalf.", vbInformation, "Notification Sent"
End If
Resume Exit_Handler
End Function
Try this slightly stripped-down version, which opens the connection to TempErrorTable on first use, and keeps the connection open. Let it stop on errors within LogTempError so you can see where the TempErrorTable update is failing.
Public Function LogTempError(ByVal lngErrNumber As Long, _
ByVal strErrDescription As String, _
strCallingProc As String, _
Optional varParameters As Variant, _
Optional blnSHOW_USER As Boolean = True) As Boolean
Static rs As Recordset
On Error GoTo 0
DoCmd.SetWarnings True
If rs Is Nothing Then ' open recordset on first use
Set rs = CurrentDb.OpenRecordset("TempErrorTable", dbOpenDynaset, dbAppendOnly)
End If
With rs
.AddNew
!ERROR_LOG_NUMBER = lngErrNumber
!ERROR_LOG_USERID = NetworkUserName()
!ERROR_LOG_DESCRIPTION = strErrDescription & " logged from Temp Table"
!ERROR_LOG_TIMESTAMP = Now()
!ERROR_LOG_FORM = strCallingProc
.Update
End With
Exit Function

Change Access server connection from command line

I have inherited an Access 2007 ADP application that uses a SQL Server 2008 backend. Is it possible to change the server connection used by the application from the command line or by some VBScript? At the moment, when I am releasing the application to a test/UAT/production environment, I have to open the project, change the server connection, and save it again.
I am trying to automate the build process as much as possible, and currently this is one of the last remaining manual tasks.
Hmm, my Google-fu is weak. I just found an article on MSDN which gives the VBA script to achieve this. I modified it to run as a VBScript below:
Dim fso
Set fso = CreateObject("Scripting.FileSystemObject")
If (WScript.Arguments.Count = 0) Then
WScript.Echo "ERROR - the Access project name must be specified"
WScript.Quit()
End If
Dim sAccessProject
sAccessProject = fso.GetAbsolutePathName(WScript.Arguments(0))
If (fso.FileExists(sAccessProject) = False) Then
WScript.Echo "ERROR - the Access project could not be located : " & sAccessProject
WScript.Quit()
End If
If (WScript.Arguments.Count = 1) Then
WScript.Echo "ERROR - the SQL Server hostname must be specified"
WScript.Quit()
End If
Dim sServer
sServer = WScript.Arguments(1)
If (WScript.Arguments.Count = 2) Then
WScript.Echo "ERROR - the SQL Server database name must be specified"
WScript.Quit()
End If
Dim sDatabase
sDatabase = WScript.Arguments(2)
Dim sUsername
If (WScript.Arguments.Count = 3) Then
sUsername = ""
Else
sUsername = WScript.Arguments(3)
End If
Dim sPassword
If (WScript.Arguments.Count >= 3) Then
sPassword = ""
Else
sPassword = WScript.Arguments(4)
End If
ChangeADPConnection sAccessProject, sServer, sDatabase, sUsername, sPassword
Function ChangeADPConnection(strProjectName, strServerName, strDBName, strUN , strPW)
Dim strConnect
Dim oApplication
Set oApplication = CreateObject("Access.Application")
WScript.Echo "Starting MS Access"
WScript.Echo "Opening " & strProjectName & " ..."
oApplication.OpenAccessProject strProjectName
oApplication.Visible = false
oApplication.CurrentProject.CloseConnection
'The Provider, Data Source, and Initial Catalog arguments are required.
strConnect = "Provider=SQLOLEDB.1" & _
";Data Source=" & strServerName & _
";Initial Catalog=" & strDBName
If strUN <> "" Then
strConnect = strConnect & ";User ID=" & strUN
If strPW <> "" Then
strConnect = strConnect & ";Password=" & strPW
End If
Else 'Try to use integrated security if no username is supplied.
strConnect = strConnect & ";Integrated Security=SSPI"
End If
WScript.Echo "Setting connection string to " & strConnect
oApplication.CurrentProject.OpenConnection strConnect
oApplication.Quit()
Set oApplication = Nothing
End Function
To run it, just use the following from the commandline:
cscript connect.vbs Project.adp, "ServerName", "DatabaseName", "Username", "Password"

exporting code from Microsoft Access

Is there any way to bulk-export Microsoft Access code to files? I see I can export one file at a time, but there are hundreds and I'll be here all day. It there no "Export All" or multi-select export anywhere?
You can do this without having to write any code at all. From the menu, choose tools->analyze->database documenter.
This will give you a bunch of options to print out the code. You can then while viewing the report ether send it out to your PDF printer (if you have one). Or, simply print out to a text file printer. Or you can even then click on the word option in the report menu bar and the results will be sent out to word
The database documenter has provisions to print out all code, including code in forms.
So, in place of some of the suggested code examples you can do this without having to write any code at all. Do play with the additional options in the documenter. The documenter will produce HUGE volumes print out information for every single property and object in the database. So, if you don't un-check some of the options then you will easily empty a full size printer tray of paper. This documenter thus results in huge printouts.
To output all code to desktop, including code from forms and reports, you can paste this into a standard module and run it by pressing F5 or step through with F8. You may wish to fill in the name of the desktop folder first.
Sub AllCodeToDesktop()
''The reference for the FileSystemObject Object is Windows Script Host Object Model
''but it not necessary to add the reference for this procedure.
Dim fs As Object
Dim f As Object
Dim strMod As String
Dim mdl As Object
Dim i As Integer
Set fs = CreateObject("Scripting.FileSystemObject")
''Set up the file.
''SpFolder is a small function, but it would be better to fill in a
''path name instead of SpFolder(Desktop), eg "c:\users\somename\desktop"
Set f = fs.CreateTextFile(SpFolder(Desktop) & "\" _
& Replace(CurrentProject.Name, ".", "") & ".txt")
''For each component in the project ...
For Each mdl In VBE.ActiveVBProject.VBComponents
''using the count of lines ...
i = VBE.ActiveVBProject.VBComponents(mdl.Name).CodeModule.CountOfLines
''put the code in a string ...
If i > 0 Then
strMod = VBE.ActiveVBProject.VBComponents(mdl.Name).codemodule.Lines(1, i)
End If
''and then write it to a file, first marking the start with
''some equal signs and the component name.
f.writeline String(15, "=") & vbCrLf & mdl.Name _
& vbCrLf & String(15, "=") & vbCrLf & strMod
Next
''Close eveything
f.Close
Set fs = Nothing
End Sub
To get special folders, you can use the list supplied by Microsoft.
Enumerating Special Folders: http://www.microsoft.com/technet/scriptcenter/guide/sas_fil_higv.mspx?mfr=true
From: http://wiki.lessthandot.com/index.php/Code_and_Code_Windows
There is nothing in the interface to export more than one module at a time.
You can code your own "export all" equivalent easily:
Public Sub ExportModules()
Const cstrExtension As String = ".bas"
Dim objModule As Object
Dim strFolder As String
Dim strDestination As String
strFolder = CurrentProject.Path
For Each objModule In CurrentProject.AllModules
strDestination = strFolder & Chr(92) & objModule.Name & cstrExtension
Application.SaveAsText acModule, objModule.Name, strDestination
Next objModule
End Sub
Here's my version:
'============================================================'
' OutputCodeModules for Access
' Don Jewett, verion 2014.11.10
' Exports the following items from an Access database
' Modules
' Form Modules
' Report Modules
'
' Must be imported into Access database and run from there
'============================================================'
Option Explicit
Option Compare Database
Private Const KEY_MODULES As String = "Modules"
Private Const KEY_FORMS As String = "Forms"
Private Const KEY_REPORTS As String = "Reports"
Private m_bCancel As Boolean
Private m_sLogPath As String
'------------------------------------------------------------'
' >>>>>> Run this using F5 or F8 <<<<<<<<
'------------------------------------------------------------'
Public Sub OutputModuleHelper()
OutputModules
End Sub
Public Sub OutputModules(Optional ByVal sFolder As String)
Dim nCount As Long
Dim nSuccessful As Long
Dim sLine As String
Dim sMessage As String
Dim sFile As String
If sFolder = "" Then
sFolder = Left$(CurrentDb.Name, InStrRev(CurrentDb.Name, "\") - 1)
sFolder = InputBox("Enter folder for files", "Output Code", sFolder)
If sFolder = "" Then
Exit Sub
End If
End If
'normalize root path by removing trailing back-slash
If Right(sFolder, 1) = "\" Then
sFolder = Left(sFolder, Len(sFolder) - 1)
End If
'make sure this folder exists
If Not isDir(sFolder) Then
MsgBox "Folder does not exist", vbExclamation Or vbOKOnly
Exit Sub
End If
'get a new log filename
m_sLogPath = sFolder & "\_log-" & Format(Date, "yyyy-MM-dd-nn-mm-ss") & ".txt"
sLine = CurrentDb.Name
writeLog sLine
sMessage = sLine & vbCrLf
sLine = Format(Now, "yyyy-MM-dd nn:mm:ss") & vbCrLf
writeLog sLine
sMessage = sMessage & sLine & vbCrLf
'output modules
nCount = CurrentDb.Containers(KEY_MODULES).Documents.Count
nSuccessful = outputContainerModules(sFolder, KEY_MODULES)
'write to the log file and final message
sLine = nSuccessful & vbTab & "of" & vbTab & nCount & vbTab & KEY_MODULES & " exported"
writeFile m_sLogPath, sLine, True
sMessage = sMessage & vbTab & sLine & vbCrLf
'output form modules
If Not m_bCancel Then
nCount = CurrentDb.Containers(KEY_FORMS).Documents.Count
nSuccessful = outputContainerModules(sFolder, KEY_FORMS)
'write to the log file and final message
sLine = nSuccessful & vbTab & "of" & vbTab & nCount & vbTab & "Form Modules exported"
writeFile m_sLogPath, sLine, True
sMessage = sMessage & vbTab & sLine & vbCrLf
End If
'output report modules
If Not m_bCancel Then
nCount = CurrentDb.Containers(KEY_REPORTS).Documents.Count
nSuccessful = outputContainerModules(sFolder, KEY_REPORTS)
'write to the log file and final message
sLine = nSuccessful & vbTab & "of" & vbTab & nCount & vbTab & "Report Modules exported"
writeFile m_sLogPath, sLine, True
sMessage = sMessage & vbTab & sLine & vbCrLf
End If
If Len(sMessage) Then
MsgBox sMessage, vbInformation Or vbOKOnly, "OutputModules"
End If
End Sub
Private Function outputContainerModules( _
ByVal sFolder As String, _
ByVal sKey As String) As Long
Dim n As Long
Dim nCount As Long
Dim sName As String
Dim sPath As String
On Error GoTo EH
'refactored this to use reference to Documents,
'but the object reference doesn't stick around
'and I had to roll back to this which isn't as pretty.
'but this works (and if it ain't broke...)
For n = 0 To CurrentDb.Containers(sKey).Documents.Count - 1
nCount = nCount + 1
sName = CurrentDb.Containers(sKey).Documents(n).Name
Select Case sKey
Case KEY_FORMS
sName = "Form_" & sName
Case KEY_REPORTS
sName = "Report_" & sName
End Select
sPath = sFolder & "\" & sName & ".txt"
DoCmd.OutputTo acOutputModule, sName, acFormatTXT, sPath, False
Next 'n
outputContainerModules = nCount
Exit Function
EH:
nCount = nCount - 1
Select Case Err.Number
Case 2289 'can't output the module in the requested format.
'TODO: research - I think this happens when a Form/Report doesn't have a module
Resume Next
Case Else
Dim sMessage As String
writeError Err, sKey, sName, nCount
sMessage = "An Error ocurred outputting " & sKey & ": " & sName & vbCrLf & vbCrLf _
& "Number " & Err.Number & vbCrLf _
& "Description:" & Err.Description & vbCrLf & vbCrLf _
& "Click [Yes] to continue with export or [No] to stop."
If vbYes = MsgBox(sMessage, vbQuestion Or vbYesNo Or vbDefaultButton2, "Error") Then
Resume Next
Else
m_bCancel = True
outputContainerModules = nCount
End If
End Select
End Function
Private Function writeFile( _
ByVal sPath As String, _
ByRef sMessage As String, _
Optional ByVal bAppend As Boolean) As Boolean
'Dim oFSO as Object
'Dim oStream as Object
'Const ForWriting As Long = 2
'Const ForAppending As Long = 8
'Dim eFlags As Long
Dim oFSO As FileSystemObject
Dim oStream As TextStream
Dim eFlags As IOMode
On Error GoTo EH
'Set oFSO = Server.CreateObject("Scripting.FileSystemObject")
Set oFSO = New FileSystemObject
If bAppend Then
eFlags = ForAppending
Else
eFlags = ForWriting
End If
Set oStream = oFSO.OpenTextFile(sPath, eFlags, True)
oStream.WriteLine sMessage
writeFile = True
GoTo CLEAN
EH:
writeFile = False
CLEAN:
If Not oFSO Is Nothing Then
Set oFSO = Nothing
End If
If Not oStream Is Nothing Then
Set oStream = Nothing
End If
End Function
Private Sub writeError( _
ByRef oErr As ErrObject, _
ByVal sType As String, _
ByVal sName As String, _
ByVal nCount As Long)
Dim sMessage As String
sMessage = "An Error ocurred outputting " & sType & ": " & sName & " (" & nCount & ")" & vbCrLf _
& "Number " & oErr.Number & vbCrLf _
& "Description:" & oErr.Description & vbCrLf & vbCrLf
writeLog sMessage
End Sub
Private Sub writeLog( _
ByRef sMessage As String)
On Error GoTo EH
writeFile m_sLogPath, sMessage & vbCrLf, True
Exit Sub
EH:
'swallow errors?
End Sub
Private Function isDir(ByVal sPath As String) As Boolean
On Error GoTo EH
If Right$(sPath, 1) <> "\" Then
sPath = sPath & "\"
End If
If Dir$(sPath & ".", vbDirectory) = "." Then
isDir = True
ElseIf Len(sPath) = 3 Then
If Dir$(sPath, vbVolume) = Left(sPath, 1) Then
isDir = True
End If
End If
Exit Function
EH:
isDir = False
End Function