Automatic backup on Opening database - ms-access

Can anyone give me the code to create a backup/copy of the Database when opening? it I know how to use autoexec macro i just need the code. The database name is Datenbank and the back to have the time of back in its name

That command could be:
FileCopy CurrentDb.Name, Replace(CurrentDb.Name, ".accdb", Format(Now(), " yyyymmdd hhnnss") & ".accdb")
but you can't do that for the database file itself from inside the application.
Your best option would be to create a shortcut that runs a script that copies the file first, then opens it.
Addendum
I located a function that will create a zipped backup of the current project:
Option Compare Database
Option Explicit
' API call for sleep function.
Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
Public Function ZipCurrentProject() As Long
Dim ShellApplication As Object
Dim CurrentProjectFile As String
Dim ZipPath As String
Dim ZipName As String
Dim ZipFile As String
Dim FileNumber As Integer
' File and folder names.
CurrentProjectFile = CurrentProject.Path & "\" & CurrentProject.Name
' The path must exist.
ZipPath = CurrentProject.Path & "\#dbase_bk" & Format(Now, " yyyy-mm-dd hh.nn.ss") & "\"
ZipName = "CCOLearningHub.zip"
ZipFile = ZipPath & ZipName
' Create sub folder if missing.
If Dir(ZipPath, vbDirectory) = "" Then
MkDir ZipPath
End If
' Create empty zip folder.
FileNumber = FreeFile
Open ZipFile For Output As #FileNumber
Print #FileNumber, Chr(80) & Chr(75) & Chr(5) & Chr(6) & String(18, vbNullChar)
Close #FileNumber
Set ShellApplication = CreateObject("Shell.Application")
' Copy the project file into the zip file.
With ShellApplication
Debug.Print Timer, "zipping started ..."
.Namespace(CVar(ZipFile)).CopyHere CVar(CurrentProjectFile)
' Ignore error while looking up the zipped file before is has been added.
On Error Resume Next
' Wait for the file to created.
Do Until .Namespace(CVar(ZipFile)).Items.Count = 1
' Wait a little ...
'DoEvents
Sleep 100
Debug.Print " .";
Loop
Debug.Print
' Resume normal error handling.
On Error GoTo 0
Debug.Print Timer, "zipping finished."
End With
Set ShellApplication = Nothing
ZipCurrentProject = Err.Number
End Function

Related

copyhere doesn't respect overwrite parameter in VBA

I'm writing a VBA code to add files, which are into several folders, into a ZIP file.
This procedure should run automatically, by a scheduled job, and I try to add a parameter to force "yes to all".
In Microsoft support there are some constants but if I add to my code, I don't have the aspected result.
the code is the following
Public Sub ZipFolder(ZipFileName As Variant, _
FolderPath As Variant, _
Optional ByVal FileFilter As String, _
Optional ByVal Overwrite As Boolean = False)
Dim fso As Object, tf As Object
Dim strZIPHeader As String, sFile As String
On Error GoTo done
' create zip file header
strZIPHeader = Chr(80) & Chr(75) & Chr(5) & Chr(6) & String(18, Chr(0))
With CreateObject("Shell.Application")
sFile = Dir(FolderPath, vbNormal)
Do Until sFile = vbNullString
.Namespace(ZipFileName).CopyHere FolderPath & sFile, **"&H10&"**
sFile = Dir
Loop
End With
Set fso = Nothing
Set tf = Nothing
done:
If Err.Number <> 0 Then MsgBox Err.Description, vbApplicationModal + vbInformation
End Sub
The parameter &H10& doesn't work. I have tried with "&0X14&" as well but same result.
Any idea?
Thank you
You can study the article and full code here on exactly this subject:
Zip and unzip files and folders with VBA the Windows Explorer way
You'll see, that shall the file be overwritten, it is simply deleted before proceeding:
If FileSystemObject.FileExists(ZipFile) Then
If Overwrite = True Then
' Delete an existing file.
FileSystemObject.DeleteFile ZipFile, True
' At this point either the file is deleted or an error is raised.
Else
ZipBase = FileSystemObject.GetBaseName(ZipFile)
' Modify name of the zip file to be created to preserve an existing file:
' "Example.zip" -> "Example (2).zip", etc.
Version = Version + 1
Do
Version = Version + 1
ZipFile = FileSystemObject.BuildPath(ZipPath, ZipBase & Format(Version, " \(0\)") & ZipExtension)
Loop Until FileSystemObject.FileExists(ZipFile) = False Or Version > MaxZipVersion
If Version > MaxZipVersion Then
' Give up.
Err.Raise ErrorPathFile, "Zip Create", "File could not be created."
End If
End If
End If

MS Access Linked Table Manager doesn't update new data source

I have an MS Access 2010 Database that has a table that is linked to a CSV file. Upating the CSV files location using the inbuilt Access "Linked Table Manager" doesn't work.
I check the file i want to update, choose "always prompt for new location" and select the new file. I get a message telling me that the update was successful, but when I go to check, the table is still linked to the old file.
Is this a MS Access bug and if so what is the most efficient workaround?
I ended up deleting the old table and manually recreating a new table with the same specifications.
*Updated: -- I forgot to include the referenced Function Relink_CSV :(
Yes, I would call it a bug. Microsoft probably calls it a 'design characteristic'.
As you have discovered, you can manually fix the issue. If you are interested in a code solution, then I may have something that will work for you -- if your CSV file is delimited by comma's.
The following code (which you need to modify!) will delete the existing linked csv file, then add a link to the same file. For debugging, my code then deletes that link and adds a link to a different file name, but in the same folder.
There are other solutions that make use of a saved Import Specification, that you can reuse, if your csv format is not simple.
Option Explicit
Option Compare Database
Sub Call_Relink()
Dim dbs As DAO.Database
Dim tdf As DAO.TableDef
Dim strTableName As String
Dim strPath As String
Dim strFile As String
Dim iReply As Integer
iReply = MsgBox("WARNING!!!! This code will remove the linked tables 'FileA' and 'FileB'" & vbCrLf & vbCrLf & _
"Click 'Yes' to Continue" & vbCrLf & "Click 'No' to Stop", vbYesNo, "CAUTION!! Will remove linked table(s)")
If iReply <> vbYes Then
Exit Sub
End If
On Error GoTo Error_Trap
Set dbs = CurrentDb
dbs.TableDefs.Delete "FileA" ' For testing; delete table if it already exists
strPath = "C:\Temp\"
strFile = "FileA.csv"
strTableName = "FileA" ' Table name in Access
Relink_CSV strTableName, strPath, strFile ' Call function to link the CSV file
dbs.TableDefs.Refresh ' Refresh TDF's
Debug.Print "Pause here and check file link" ' Put a breakpoint here; pause and look at the table in Access
dbs.TableDefs.Delete "FileA" ' For testing; delete table if it already exists
strPath = "C:\Temp\" ' Path to next csv
strFile = "FileB.csv" ' Name of next csv file
strTableName = "FileA" ' Table name in Access
Relink_CSV strTableName, strPath, strFile ' Call function to link to a different CSV file
dbs.TableDefs.Refresh
Debug.Print "Pause here and check file link" ' Put a breakpoint here; pause and look at the table in Access
My_Exit:
Set dbs = Nothing
Exit Sub
Error_Trap:
Debug.Print Err.Number & vbTab & Err.Description
If Err.Number = 3265 Then ' Item not found in this collection.
' Ignore this error
Resume Next
End If
MsgBox Err.Number & vbTab & Err.Description
Resume My_Exit
Resume
End Sub
Function Relink_CSV(strTableName As String, strPath As String, strFile As String)
' (1) Name of the table in Access
' (2) Path to the file
' (3) File name
On Error GoTo Relink_Err
DoCmd.TransferText acLinkDelim, , strTableName, strPath & strFile, False, ""
Relink_Exit:
Exit Function
Relink_Err:
Debug.Print Err.Number & vbTab & Err.Description
MsgBox Err.Number & vbTab & Err.Description
Resume Relink_Exit
Resume
End Function

DoCmd.TransferText error 3051

I am attempting to import data into my MS Access project via TransferText, but am receiving error #3051: "The Microsoft Access database engine cannot open or write to the file ''. It is already opened exclusively by another user, or you need permissions to view and write its data."
It is odd to me that the filename given in the error message is blank. I have checked and rechecked the file name, even to perform a check "If Not fso.FileExists(file_name) Then ... End If" prior to the TransferText call.
I have also checked and rechecked the table name and the file permissions. The table is successfully emptied before the TransferText call, so I know that works. The file is in a subfolder relative to the Access database file in a folder on my desktop. I have not set or unset any permissions for any of the folders or files.
Until now I had been using DoCmd.TransferSpreadsheet to import the data that is downloaded from a web based tool, but I found Excel was misinterpreting some alphanumeric codes as numbers in scientific format, such as 1E100 would become 1E+100 in the Excel file, so the data was corrupted before getting to the Access database. These codes are getting corrupted in uncorrectable ways, so I can't modify the data after import. I found I could save the data from the web tool as a CSV file rather than an Excel file; this led me to try to use DoCmd.TransferText.
Below is the code I am using:
Private Function ImportExcel( _
ByVal file_name As String, _
ByVal table_name As String _
) As Integer
On Error GoTo Error
Dim fso As FileSystemObject, folder_name As String
Dim xl_book As Excel.Workbook
Dim xl_sheet As Excel.Worksheet
Dim i As Integer
' suppress excel's file-not-found popup
Set fso = New FileSystemObject
If Not fso.FileExists(file_name) Then
ImportExcel = -1
GoTo Finish
End If
' gets a workbook from a global application object
Set xl_book = Util.GetExcelWorkbook( _
file_name:=file_name, _
visible:=False, _
use_cache:=True _
)
If xl_book Is Nothing Then
ImportExcel = -1
GoTo Finish
End If
' always use the first worksheet
Set xl_sheet = xl_book.Sheets(1)
' fake the first record to force columns types
xl_sheet.range("A2").EntireRow.Insert
For i = 1 To xl_sheet.UsedRange.columns.count
xl_sheet.Cells(2, i) = "test"
Next i
' make sure the table is closed
DoCmd.Close _
ObjectType:=acTable, _
ObjectName:=table_name, _
Save:=acSaveNo
' link to file
DoCmd.SetWarnings False
If ".csv" = Right(file_name, 4) Then
' empty table
DoCmd.RunSQL "DELETE * FROM " & table_name, True
' import data
Debug.Print table_name
Debug.Print file_name
DoCmd.TransferText _
TransferType:=acImportDelim, _
SpecificationName:=table_name & " Import Spec", _
TableName:=table_name, _
FileName:=file_name, _
HasFieldNames:=True
Else
' delete table
On Error Resume Next
DoCmd.DeleteObject _
ObjectType:=acTable, _
ObjectName:=table_name
If 0 <> Err.Number Then
Resume Next
End If
On Error GoTo Error
' import data
DoCmd.TransferSpreadsheet _
TransferType:=acImport, _
TableName:=table_name, _
FileName:=file_name, _
HasFieldNames:=True, _
range:=xl_sheet.NAME() & "!" & _
xl_sheet.range( _
xl_sheet.Cells(1, 1), _
xl_sheet.Cells( _
xl_sheet.UsedRange.rows.count, _
xl_sheet.UsedRange.columns.count _
) _
).Address(RowAbsolute:=False, ColumnAbsolute:=False), _
SpreadsheetType:=acSpreadsheetTypeExcel9
End If
DoCmd.SetWarnings True
Finish:
Set xl_sheet = Nothing
If Not xl_book Is Nothing Then
xl_book.Close SaveChanges:=False
End If
Set xl_book = Nothing
Set fso = Nothing
Exit Function
Error:
Resume Finish
End Function
The two Debug.Print calls just prior to the DoCmd.TransferText call print exactly what is expected.

How do I prevent this Error Message

I have created a VBA access application to find a PDF file in a folder by doing one sweep to get all the sub-folders in the root folder. Then another sweep to collect and compare all the file names to the one that is selected. We are then using the following code to open the file when it is found:
Private Sub Command132_Click()
On Error GoTo Err_Command132_Click
Dim rootFolder As String
Dim subFolder As String
Dim fileSpec As String
Dim filename As String
Dim foundfile As String
Dim filepath As String
Dim subfolders() As String
Dim co As String
Dim intSubFolderCount As Integer
rootFolder = "T:\Scanned Work Orders (Archives)\"
subFolder = Dir(rootFolder & "*.*", vbDirectory)
'*** Get subfolders in array ***
While subFolder <> ""
If subFolder <> "." And subFolder <> ".." Then
ReDim Preserve subfolders(intSubFolderCount)
subfolders(intSubFolderCount) = subFolder
intSubFolderCount = intSubFolderCount + 1
Debug.Print subFolder
End If
subFolder = Dir()
Wend
'*** Loop over array and find files ***
For intSubFolderCount = 0 To UBound(subfolders)
fileSpec = Trim(Me.Combo_History) & "*.pdf"
co = subfolders(intSubFolderCount)
filename = Dir(rootFolder & subfolders(intSubFolderCount) & "\" & fileSpec)
Do While filename <> ""
filepath = rootFolder & subfolders(intSubFolderCount)
foundfile = filepath & "\" & filename
Application.FollowHyperlink foundfile
GoTo Exit_Command132_Click
Exit Do
Loop
Next intSubFolderCount
MsgBox "No Scanned work order found for " & Me.Combo_History & "!"
Exit_Command132_Click:
Exit Sub
Err_Command132_Click:
Select Case Err.Number
Case 52
MsgBox "No Scanned work order found for " & Me.Combo_History & "!"
Case Else
MsgBox Err.Number & "-" & Err.Description
End Select
End Sub
But on some of the computers in my office they get this error message:
"Some Files can contain viruses or otherwise be harmful to your computer.
It is important to be certain that this file is from a trustworthy source.
Would you like to open this file?"
Is it possible to suppress this? We are running windows 7 professional.
This is a windows feature. Microsoft have KB on removing it here.
https://support.microsoft.com/en-us/kb/925757
It is possible to use VBA to change the registry settings, but follow the KB instructions first to ensure it solves your issue.

why can't i programmatically copy a locked .mdb but i can copy it through explorer?

I intended to write a VBA function which would copy a .mdb file if a certain criterion is met.
I hit a roadblock when I realized the FileCopy method throws an error if the .mdb it is trying to copy/paste has an associated .ldb file.
However, I am able to manually copy/paste the .mdb through windows explorer.
The .mdb i am trying to copy will always be locked, since I have added a reference to it in the DB that is running the filecopy procedure.
Can someone show me how to force a copy programatically with VBA? I tried searching but all I found was advice against doing this because of DB corruption etc. BUT this won't be an issue, because none of the DB objects will be manipulated while this procedure is executing.
If anyone is curious, here is my procedure:
Function fn_ArchiveMonthEndDB()
'load INI data
fn_ReadINI
Dim asOfDate As Date
asOfDate = getAsOfDate()
Dim monthEndDate As Date
monthEndDate = fn_GetMonthEndDate()
sSQL = "SELECT CDate(Nz(LastRunDate,'1/1/1990')) as BackupDate FROM tbl_UseStats WHERE ProcessName = 'Archive Backend DB'"
Dim rs As Recordset
Set rs = CurrentDb.OpenRecordset(sSQL)
Dim dLastBackup As Date
dLastBackup = rs!BackupDate
rs.Close
Set rs = Nothing
If (dLastBackup <> monthEndDate) Then
'determine if it actually is month-end. if yes, then archive the DB.
If (asOfDate = monthEndDate) Then
'archive backend DB
sDir = iBackendArchive & "\" & CStr(Year(monthEndDate)) & CStr(Month(monthEndDate))
'create dir if it does not exist
If (Dir(sDir, vbDirectory)) = "" Then
MkDir sDir
End If
FileCopy iBackendPath & "\ETL_be.mdb", sDir & "\ETL_be.mdb"
Else
'if no, do nothing
End If
ElseIf (dLastBackup = monthEndDate) Then
'do nothing, because we already took a backup of the backend DB.
End If
End Function
Microsoft explains it pretty simply in their KB article.
- Create a module and type the following lines in the Declarations section:
Option Explicit
Declare Function apiCopyFile Lib "kernel32" Alias "CopyFileA" _
(ByVal lpExistingFileName As String, _
ByVal lpNewFileName As String, _
ByVal bFailIfExists As Long) As Long
- Type the following procedure:
Sub CopyFile(SourceFile As String, DestFile As String)
'---------------------------------------------------------------
' PURPOSE: Copy a file on disk from one location to another.
' ACCEPTS: The name of the source file and destination file.
' RETURNS: Nothing
'---------------------------------------------------------------
Dim Result As Long
If Dir(SourceFile) = "" Then
MsgBox Chr(34) & SourceFile & Chr(34) & _
" is not valid file name."
Else
Result = apiCopyFile(SourceFile, DestFile, False)
End If
End Sub
- To test this procedure, type the following line in the Immediate window, and then press ENTER:
CopyFile "<path to Northwind.mdb>", "C:\Northwind.mdb"