MS Access, Linking backend tables using VB code over network - sql

I have made a Tracking Database for work that has a front end interface and backend tables. Right now I have a section of code which upon start up will link the front end with the back end tables so people can copy and paste the front end from "G:\Sections\MEO\DDPO\Active Issues\Tracking Database" to their desktop and it will still be able to access the backend file.
The Issue I want to avoid is if someone changes the file path of where the back end is located the front end will not be able to find the backend.
example:
Original Path G:\Sections\MEO\DDPO\Active Issues\Tracking Database\Database Backend\tracking Database_be.accdb
If someone Modified the Path
G:\New Sections\MEO\DDPO\Active Issues\Tracking Database\Database Backend\tracking Database_be.accdb
This is the current code I use for the front end to ensure it links to the backend upon start up.
Private Function ReconnectTables() As Boolean
On Error Resume Next
Dim tdf As DAO.TableDef
Dim dbs As DAO.Database
Dim strPath As String
Dim strConnect As String
Set dbs = CurrentDb
strPath = dbs.Name
strPath = "G:\Sections\MEO\DDPO\Active Issues\Tracking Database\Database Backend\tracking Database_be.accdb"
strConnect = strPath
For Each tdf In dbs.TableDefs
If tdf.Connect <> "" Then
tdf.Connect = ";DATABASE=" & strConnect
tdf.RefreshLink
End If
Next
Set dbs = Nothing
If Err.Number = 0 Then ReconnectTables = True
End Function

I ended up removing the hard written path from the code and added a line where it checks a value in a table. That value stored in the table is the path which the user can select in a separate form which now gets called if it detects the tables are not linked.
My new code looks like this:
Private Function ReconnectTables() As Boolean
On Error Resume Next
Dim tdf As DAO.TableDef
Dim dbs As DAO.Database
Dim strPath As String
Dim strConnect As String
Set dbs = CurrentDb
strPath = dbs.Name
strPath = me.BackEndPath.Value
strConnect = strPath
For Each tdf In dbs.TableDefs
If tdf.Connect <> "" Then
tdf.Connect = ";DATABASE=" & strConnect
tdf.RefreshLink
End If
Next
Set dbs = Nothing
If Err.Number = 0 Then ReconnectTables = True
End Function
I used to just have a message box that would pop up if the tables were not linked but now I added 2 lines of code to open a form (frmBEpath) if the tables are not linked.
Private Sub Form_Load()
On Error Resume Next
'DoCmd.ShowToolbar "Ribbon", acToolbarNo
If ReconnectTables() = True Then
strVerClient = Nz(DLookup("[VersionNumber]", "[tblVersionClient]"), "")
strVerServer = Nz(DLookup("[VersionNumber]", "[tblVersionServer]"), "")
Me.Repaint
Else
'MsgBox "Couldn't Find Data Tables. Exiting.", vbCritical, "Error"
DoCmd.Close
DoCmd.OpenForm "frmBEpath"
End If
End Sub
This new form tells the user the tables are not linked and it gives them a button to browse for the backend files. When they select the backend file and click the yes button it stores the path name in a table.
Option Compare Database
Public Function FolderSelection() As String
Dim objFD As Object
Dim strOut As String
strOut = vbNullString
Set objFD = Application.FileDialog(3)
If objFD.Show = -1 Then
strOut = objFD.SelectedItems(1)
End If
Set objFD = Nothing
FolderSelection = strOut
End Function
Private Sub btnBrowse_Click()
Dim strChoice As String
strChoice = FolderSelection
If Len(strChoice) > 0 Then
Me.txtPath = strChoice
End If
End Sub
Private Sub btnConfirmYes_Click()
Me.BackEndPath.Value = Me.txtPath.Value
DoCmd.Close
DoCmd.OpenForm "frmsplash"
End Sub

Related

MS ACCESS VBA Move/Copy Files

I am using the below code to reference a table that has full path information to move (or copy) files from 1 location to another. However, it's not moving anything, but is completing per my Debug.Print message (Move Complete 2/22/2021 1:22:41 PM). Any thoughts on what I'm missing?
Additionally, I'd like to build the folder/subfolder structure where the file was located in the source...but don't know how to achieve that...and pointers on how to do this?
Sub copy_files_from_table()
Dim FSO As Object
Dim source As String
Dim destination As String
Dim SQL As String
Dim RS As DAO.Recordset
Dim db As DAO.Database
SQL = "select * from file_test"
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set db = CurrentDb
Set RS = db.OpenRecordset(SQL)
source = RS!LocalFile
destination = "C:\Temp\Test"
While Not RS.EOF
If Dir(source, vbDirectory) <> "" Then
objFSO.CopyFolder source, destination:=destination '
Debug.Print "Move Folder Command Complete From: " & destination
Else
End If
RS.MoveNext
Wend
Debug.Print "Move Complete " & Now()
End Sub
Appreciate any help provided.
So far, I have gotten the following code to work on file paths <259; however, anything longer is causing the code to error. Since I'm pretty green on coding:) any suggestions how I can get around the long file path names?
Sub CopyFilesFromTable2()
On Error GoTo ErrorHandler
Dim source As String
Dim destination As String
Dim FSO As New FileSystemObject
Dim SQL As String
Dim RS As DAO.Recordset
Dim db As DAO.Database
'Test Table
SQL = "select * from file_test"
'Prod Table
'SQL = "select * from file"
Set FSO = CreateObject("Scripting.FileSystemObject")
Set db = CurrentDb
Set RS = db.OpenRecordset(SQL)
source = RS!LocalFile
File = VBA.FileSystem.Dir(source)
destination = "D:\Temp\Test\"
With RS
If Not .BOF And Not .EOF Then
.MoveLast
.MoveFirst
While (Not .EOF)
FSO.CopyFile RS!LocalFile, destination
.MoveNext
Wend
End If
.Close
End With
ExitSub:
Set RS = Nothing
'set to nothing
MsgBox "Done!"
Exit Sub
ErrorHandler:
MsgBox Err, vbCritical
Resume ExitSub
End Sub

How to store record information from a ListBox to a Table?

I am using the following code that is linked to a button cmdAdd. Using the 'On Click' event, the ListBox selection information is copied to a table KitBuild.
Private Sub cmdAdd_Click()
Dim strSQL As String
Dim db As DAO.Database
Dim rs As DAO.Recordset
Dim ctl As Control
Dim varItem As Variant
On Error GoTo ErrorHandler
Set db = CurrentDb()
Set rs = db.OpenRecordset("KitBuild", dbOpenDynaset, dbAppendOnly)
'make sure a selection has been made
If Me.lstResults.ItemsSelected.Count = 0 Then
MsgBox "At least 1 part must be selected."
Exit Sub
End If
'add selected value(s) to table
Set ctl = Me.lstResults
For Each varItem In ctl.ItemsSelected
rs.AddNew
rs!ItemNo = ctl.ItemData(varItem)
rs.Update
Next varItem
ExitHandler:
Set rs = Nothing
Set db = Nothing
Exit Sub
ErrorHandler:
Select Case Err
Case Else
MsgBox Err.Description
DoCmd.Hourglass False
Resume ExitHandler
End Select
End Sub
Shown below is the table KitBuild where selections are saved. Currently, it only transfers over 1 piece of information from the selection which is No from qryParts into the column called ItemNo (ID #8). This works fine but I also need to transfer over the Description and Unit Cost of records from qryParts to KitBuild.
I tried changing the following to rs!Description and rs!UnitCost but the No value just shifts over to those columns (ID #9, 10) rather than providing the Description and Cost.
'add selected value(s) to table
Set ctl = Me.lstResults
For Each varItem In ctl.ItemsSelected
rs.AddNew
rs!ItemNo = ctl.ItemData(varItem)
rs.Update
Next varItem
This is an example of the information I would like copied from qryParts to KitBuild.
How can I modify the code to include No, Description and Cost?
I assume that your ListBox has data in the order as on your last picture. Use this:
'add selected value(s) to table
Set ctl = Me.lstResults
For Each varItem In ctl.ItemsSelected
rs.AddNew
rs!ItemNo = ctl.Column(0)
rs!Description = ctl.Column(1)
rs!UnitCost = ctl.Column(2)
rs.Update
Next varItem

How to auto-backup Access Database

I want to autoback up my access database with the below code and it didn't work for me. I got an error "cannot find the input table or query "WinAutoBackup" Please view the picture. Also, did I use CurrentProject correctly?
[Function fMakeBackup() As Boolean
Dim Source As String
Dim Target As String
Dim retval As Integer
On Error GoTo sysBackup_Err
Source = CurrentDb.name
Target = "CurrentProject.path\backups\"
Target = Target & Format(Now, "yyyymmdd-hhnn") & ".accdb"
If DateDiff("d", DLookup("\[BackupDate\]", "WinAutoBackup", "\[BckID\]
=1"), Date) = 3 Then
retval = 0
Dim objFSO As Object
Set objFSO = CreateObject("Scripting.FileSystemObject")
retval = objFSO.CopyFile(Source, Target, True)
Set objFSO = Nothing
DoCmd.SetWarnings False
DoCmd.RunSQL "UPDATE WinAutoBackup SET WinAutoBackup.BackupDate =
Date();"
DoCmd.SetWarnings True
MsgBox "Backup successfull. Next auto backup in 3 days"
Else
Exit Function
End If
sysBackup_Exit:
Exit Function
sysBackup_Err:
MsgBox Err.Description, , "sysBackup()"
Resume sysBackup_Exit
End Function][1]
Start with including:
Option Explicit
at the top of the module.
Then try with:
Function fMakeBackup() As Boolean
Dim objFSO As Object
Dim Source As String
Dim Target As String
Dim retval As Integer
' Disable error handling during development.
' On Error GoTo sysBackup_Err
Source = CurrentDb.Name
' Adjust if if backup folder is not \backups\.
Target = CurrentProject.Path & "\backups\"
Target = Target & Format(Now, "yyyymmdd-hhnn") & ".accdb"
' To run every time, use this line in plade of If DateDiff ...:
' If True Then
If DateDiff("d", DLookup("[BackupDate]", "[WinAutoBackup]", "[BckID] = 1"), Date) >= 3 Then
Set objFSO = CreateObject("Scripting.FileSystemObject")
retval = objFSO.CopyFile(Source, Target, True)
Set objFSO = Nothing
DoCmd.SetWarnings False
DoCmd.RunSQL "UPDATE WinAutoBackup SET WinAutoBackup.BackupDate = Date() WHERE [BckID] = 1;"
DoCmd.SetWarnings True
MsgBox "Backup successful. Next auto backup in 3 days."
End If
sysBackup_Exit:
Exit Function
sysBackup_Err:
MsgBox Err.Description, , "sysBackup()"
Resume sysBackup_Exit
End Function

Getting the user input of a variable as a string to use in vba access

I'm sure there is a really easy way around this. Say I have a query called query_1 and upon running this query the user has to input the two values which are labelled as q_month, q_year.
I am running a bit of code that exports this query, but I want to take the user input values as strings which I can then use further down the line in my code. How would one do this?
(Apologies I am new to syntax in Access)
See below my attempt (I open the query first as it then will prompt user to input value). I know the lines v_Month and v_year are incorrect but hopefully it shows what I want to do clearer.
Thanks!
Function ExportExcel()
Dim myQueryName As String, sFolderPath As String, v_Month As String, v_Year As String
myQueryName = "query_1"
sFolderPath = "C:\Folder1"
DoCmd.OpenQuery myQueryName
v_Month = [query_1].[q_month]
v_Year = [query_1].[q_year]
myExportFileNameExcel = sFolderPath & "\" & v_Month & "\Test.xlsx"
DoCmd.OutputTo acOutputQuery, myQueryName, "ExcelWorkbook(*.xlsx)", myExportFileNameExcel, False, "", , acExportQualityPrint
End Function
You can use InputBox:
SomeStringVariable = InputBox("Please enter value:")
To set the parameters before running the query, use DoCmd.SetParameter:
DoCmd.SetParameter method (Access)
You haven't given the SQL for the query so I wrote a basic query showing how to use parameters:
PARAMETERS q_month Long, q_year Long;
SELECT *
FROM Table1
WHERE YEAR(DateField) = q_year AND MONTH(DateField) = q_month
You can then use this code to export the query data to Excel:
Sub Test()
Dim MonthNumber As Long, YearNumber As Long
'Get the details from the user.
MonthNumber = InputBox("Enter month number:")
YearNumber = InputBox("Enter full year:")
'Pass the details to the Export procedure.
ExportToExcel MonthNumber, YearNumber
End Sub
Public Function ExportToExcel(lMonth As Long, lYear As Long)
Dim qdf As DAO.QueryDef
Dim rst As DAO.Recordset
Dim fld As DAO.Field
Dim oXL As Object, oWB As Object, oWS As Object
'Open the query as a recordset.
Set qdf = CurrentDb.QueryDefs("Query1")
With qdf
.Parameters("q_Month") = lMonth
.Parameters("q_Year") = lYear
Set rst = .OpenRecordset
End With
Set oXL = CreateXL 'Create an instance of Excel.
Set oWB = oXL.WorkBooks.Add 'Create workbook.
Set oWS = oWB.Worksheets(1) 'Reference to first sheet.
'Copy the data over to row 2.
oWS.Range("A2").CopyFromRecordset rst
'Add the field headings to row 1
For Each fld In rst.Fields
oWS.cells(1, fld.OrdinalPosition + 1) = fld.Name
Next fld
'Using the passed values again.
MsgBox "Data exported for " & Format(DateSerial(lYear, lMonth, 1), "mmmm 'yy")
'Assumes the month folder already exists.
'Names folders as "01_January_18" to "12_December_18"
oWB.SaveAs "C:\Folder1\" & Format(DateSerial(lYear, lMonth, 1), "mm_mmmm_yy") & "\Test.xlsx", 51
rst.Close
qdf.Close
Set rst = Nothing
Set qdf = Nothing
End Function
Public Function CreateXL(Optional bVisible As Boolean = True) As Object
Dim oTmpXL As Object
'''''''''''''''''''''''''''''''''''''''''''''''''''''
'Defer error trapping in case Excel is not running. '
'''''''''''''''''''''''''''''''''''''''''''''''''''''
On Error Resume Next
Set oTmpXL = GetObject(, "Excel.Application")
'''''''''''''''''''''''''''''''''''''''''''''''''''''''
'If an error occurs then create an instance of Excel. '
'Reinstate error handling. '
'''''''''''''''''''''''''''''''''''''''''''''''''''''''
If Err.Number <> 0 Then
Err.Clear
Set oTmpXL = CreateObject("Excel.Application")
End If
oTmpXL.Visible = bVisible
Set CreateXL = oTmpXL
End Function

Export Each Access Table To Individual Workbook

I have been using this syntax which will export every table in a database to ONE excel workbook, but now my needs are to export every table to it's own workbook. How could this be tweaked to export each table to it's own workbook?
Sub ExportToExcel()
Dim td As DAO.TableDef, db As DAO.Database
Dim out_file As String
out_file = "C:\fromaccess.xlsx"
Set db = CurrentDb()
For Each td in db.TableDefs
If Left(td.Name, 4) = "MSys" Then
'Do Nothing
Else
DoCmd.TransferSpreadsheet acExport, acSpreadsheetTypeExcel9, td.Name, out_file, True, Replace(td.Name, "dbo_","")
End If
Next
End Sub
EDIT
I tried the suggestion by #HA560 but get an error of
Run-time error '91':
Object variable or With block variable not set
This is updated code:
Sub ExportToExcel()
Dim td As DAO.TableDef, db As DAO.Database
Dim out_file As String
Dim xl As Excel.Application
out_file = "C:\fromaccess.xlsx"
Set db = CurrentDb()
For Each td in db.TableDefs
xl.Workbooks.Add
If Left(td.Name, 4) = "MSys" Then
'Do Nothing
Else
DoCmd.TransferSpreadsheet acExport, acSpreadsheetTypeExcel9, td.Name, out_file, True, Replace(td.Name, "dbo_","")
End If
Next
End Sub
Bit of a long one which includes a three procedures. After running you should have a list of table names and TRUE/FALSE in the immediate window saying whether the export was successful.
ExportAll - The main procedure.
CreateXL - this creates an instance of Excel. It uses late binding, so no need to set references.
QueryExportToXL - this is the code to export the table. I haven't used TransferSpreadsheet as I like more control.
You need to pass a worksheet reference to the function.
You can pass either a query name or a recordset to the function.
You can pass an alternative sheet name.
The default cell to paste into is A1, but you can change this.
By default it adjusts the column widths to fit.
You can pass a collection of heading names to use instead of the field names.
There's not much error handling in there - such as passing a different number of heading names than there are fields, giving illegal sheet names.
It needs work :)
Public Sub ExportAll()
Dim db As DAO.Database
Dim tdf As DAO.TableDef
Dim rst As DAO.Recordset
Dim oXL As Object
Dim oWrkBk As Object
Set db = CurrentDb
'Create instance of Excel.
Set oXL = CreateXL
For Each tdf In db.TableDefs
If Left(tdf.Name, 4) <> "MSys" Then
'Create workbook with single sheet.
Set oWrkBk = oXL.WorkBooks.Add(-4167) 'xlWBATWorksheet
'Open the table recordset.
Set rst = tdf.OpenRecordset
'In the immediate window display table name and TRUE/FALSE if exported successfully.
Debug.Print tdf.Name & " - " & QueryExportToXL(oWrkBk.worksheets(1), , rst, tdf.Name)
'Save and close the workbook.
oWrkBk.SaveAs "<path to folder>" & tdf.Name
oWrkBk.Close
End If
Next tdf
End Sub
'----------------------------------------------------------------------------------
' Procedure : CreateXL
' Author : Darren Bartrup-Cook
' Date : 02/10/2014
' Purpose : Creates an instance of Excel and passes the reference back.
'-----------------------------------------------------------------------------------
Public Function CreateXL(Optional bVisible As Boolean = True) As Object
Dim oTmpXL As Object
'''''''''''''''''''''''''''''''''''''''''''''''''''''
'Defer error trapping in case Excel is not running. '
'''''''''''''''''''''''''''''''''''''''''''''''''''''
On Error Resume Next
Set oTmpXL = GetObject(, "Excel.Application")
'''''''''''''''''''''''''''''''''''''''''''''''''''''''
'If an error occurs then create an instance of Excel. '
'Reinstate error handling. '
'''''''''''''''''''''''''''''''''''''''''''''''''''''''
If Err.Number <> 0 Then
Err.Clear
On Error GoTo ERROR_HANDLER
Set oTmpXL = CreateObject("Excel.Application")
End If
oTmpXL.Visible = bVisible
Set CreateXL = oTmpXL
On Error GoTo 0
Exit Function
ERROR_HANDLER:
Select Case Err.Number
Case Else
MsgBox "Error " & Err.Number & vbCr & _
" (" & Err.Description & ") in procedure CreateXL."
Err.Clear
End Select
End Function
'----------------------------------------------------------------------------------
' Procedure : QueryExportToXL
' Author : Darren Bartrup-Cook
' Date : 26/08/2014
' Purpose : Exports a named query or recordset to Excel.
'-----------------------------------------------------------------------------------
Public Function QueryExportToXL(wrkSht As Object, Optional sQueryName As String, _
Optional rst As DAO.Recordset, _
Optional SheetName As String, _
Optional rStartCell As Object, _
Optional AutoFitCols As Boolean = True, _
Optional colHeadings As Collection) As Boolean
Dim db As DAO.Database
Dim prm As DAO.Parameter
Dim qdf As DAO.QueryDef
Dim fld As DAO.Field
Dim oXLCell As Object
Dim vHeading As Variant
On Error GoTo ERROR_HANDLER
If sQueryName <> "" And rst Is Nothing Then
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'Open the query recordset. '
'Any parameters in the query need to be evaluated first. '
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Set db = CurrentDb
Set qdf = db.QueryDefs(sQueryName)
For Each prm In qdf.Parameters
prm.Value = Eval(prm.Name)
Next prm
Set rst = qdf.OpenRecordset
End If
If rStartCell Is Nothing Then
Set rStartCell = wrkSht.cells(1, 1)
Else
If rStartCell.Parent.Name <> wrkSht.Name Then
Err.Raise 4000, , "Incorrect Start Cell parent."
End If
End If
If Not rst.BOF And Not rst.EOF Then
With wrkSht
Set oXLCell = rStartCell
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'Paste the field names from the query into row 1 of the sheet. '
'Or the alternative field names provided in a collection. '
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
If colHeadings Is Nothing Then
For Each fld In rst.Fields
oXLCell.Value = fld.Name
Set oXLCell = oXLCell.Offset(, 1)
Next fld
Else
For Each vHeading In colHeadings
oXLCell.Value = vHeading
Set oXLCell = oXLCell.Offset(, 1)
Next vHeading
End If
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'Paste the records from the query into row 2 of the sheet. '
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Set oXLCell = rStartCell.Offset(1, 0)
oXLCell.copyfromrecordset rst
If AutoFitCols Then
.Columns.Autofit
End If
If SheetName <> "" Then
.Name = SheetName
End If
'''''''''''''''''''''''''''''''''''''''''''
'TO DO: Has recordset imported correctly? '
'''''''''''''''''''''''''''''''''''''''''''
QueryExportToXL = True
End With
Else
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'There are no records to export, so the export has failed. '
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
QueryExportToXL = False
End If
Set db = Nothing
On Error GoTo 0
Exit Function
ERROR_HANDLER:
Select Case Err.Number
Case Else
MsgBox "Error " & Err.Number & vbCr & _
" (" & Err.Description & ") in procedure QueryExportToXL."
Err.Clear
Resume
End Select
End Function
After for each use workbooks.add()method...out_file=activeworkbook.path