Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations gkittelson on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Backup of Back End files 1

Status
Not open for further replies.

THWatson

Technical User
Apr 25, 2000
2,601
CA
Using Access 2003 (2000 format)

I have a module that creates a Backup of Back End tables upon close of the database. TheAceMan1 provided me with a link to this solution. Following is the code...

Code:
' Copyright 2005 Alexey Dybenko. All Rights Reserved.
' E-mail: alexdyb@PointLtd.com
Option Compare Database
Option Explicit
'Temporary database name during backup
Private Const cTempDatabase = "~DataFile~.MDT"
'Database password if required
Private Const cstrPassword = ""
Private Function GetAppOption(strOption As String) As Variant
    'this function returns appliction options,
    'you can replace it with your function or
    'just read from hidden form with option values
    Select Case strOption
        Case "BackUpInterval"
            GetAppOption = 1 'Every day
        Case "BackupPath"
            GetAppOption = "" 'if empty - then using application path
        Case "LeaveCopies"
            GetAppOption = 3 ' we leave 3 last backups
        Case "CompactAfterBackUp"
            GetAppOption = True 'we will compact BE
    End Select
End Function

Public Function ToBackup() As Boolean
On Local Error GoTo ToBackup_Err
    Dim dbData As Database
    
    Dim datLastBackupDate As Date, intBackupInterval As Integer
    
    If Len(cstrPassword) > 0 Then
        Set dbData = DBEngine.OpenDatabase(WhereAttached(), False, False, ";pwd=" & cstrPassword)
    Else
        Set dbData = DBEngine.OpenDatabase(WhereAttached())
    End If
    
    datLastBackupDate = CDate(PrpGet(dbData, "LastBackUp"))
    dbData.Close

    intBackupInterval = GetAppOption("BackUpInterval")
    If intBackupInterval = 0 Then GoTo ToBackup_End
    
    If ((VBA.Date - datLastBackupDate) >= intBackupInterval) Then
        ToBackup = True
    End If

ToBackup_End:
    Exit Function
ToBackup_Err:
    Select Case Err.Number
        Case Else
            MsgBox "Error " & Err.Number & " (" & Err.Description & ")"
            Resume ToBackup_End
    End Select
End Function
Public Function BackUpNow(Optional strFilename As String)
On Local Error GoTo BackUpNow_Err
    Dim strMDTSourcePath As String, strBackupPath As String, intLeaveCopies As Integer
    Dim strBackupFile As String, i As Integer, strTemp As String
    Dim BackupArray() As String
    Dim dbData As Database
    DoCmd.Hourglass True
    Call MsgBox("Creating a backup of the Back End tables." _
                & vbCrLf & "It will be the 3rd entry in the Backup folder." _
                , vbExclamation, "Backup process")
        
        If Len(strFilename) = 0 Then
        strMDTSourcePath = WhereAttached()
    Else
        strMDTSourcePath = strFilename
    End If
    strBackupPath = GetAppOption("BackupPath")
    intLeaveCopies = GetAppOption("LeaveCopies")
    
    If Len(strBackupPath) < 3 Then
        strBackupPath = CurrentProject.Path & "\BackUp"
    End If
    If Len(Dir(strBackupPath & "\", vbDirectory)) = 0 Then
        MkDir strBackupPath
    End If
    strBackupFile = strBackupPath & "\Backup_" & Format(Now, "yymmdd_hhmmss") & "_Of_" & Mid$(strMDTSourcePath, InStrRev(strMDTSourcePath, "\") + 1)
    If Len(Dir(strBackupFile)) > 0 Then
        Kill strBackupFile
    End If
    FileCopy strMDTSourcePath, strBackupFile
    strTemp = Dir(strBackupPath & "\Backup_" & "??????_??????" & "_Of_" & Mid$(strMDTSourcePath, InStrRev(strMDTSourcePath, "\") + 1))
    Do While Len(strTemp) > 0
        ReDim Preserve BackupArray(1 To i + 1)
        BackupArray(i + 1) = strTemp
        strTemp = Dir
        i = i + 1
    Loop
    BubbleSort BackupArray()
    For i = 1 To UBound(BackupArray) - intLeaveCopies
        Kill strBackupPath & "\" & BackupArray(i)
    Next i
    If Len(cstrPassword) > 0 Then
        Set dbData = DBEngine.OpenDatabase(strMDTSourcePath, False, False, ";pwd=" & cstrPassword)
    Else
        Set dbData = DBEngine.OpenDatabase(strMDTSourcePath)
    End If

    PrpSet dbData, "LastBackUp", dbDate, Date
    dbData.Close
    
    If GetAppOption("CompactAfterBackUp") Then
        Application.Echo True, "Compacting database..."
        strTemp = Left$(strMDTSourcePath, InStrRev(strMDTSourcePath, "\")) & cTempDatabase
        If Len(Dir(strTemp)) > 0 Then Kill strTemp
        
        If Len(cstrPassword) > 0 Then
            CompactDatabase strMDTSourcePath, strTemp, ";pwd=" & cstrPassword, , ";pwd=" & cstrPassword
        Else
            CompactDatabase strMDTSourcePath, strTemp
        End If
        Kill strMDTSourcePath
        Name strTemp As strMDTSourcePath
    End If
    
BackUpNow_End:
    DoCmd.Hourglass False
    Application.Echo True
    
    Exit Function
BackUpNow_Err:
    Select Case Err.Number
        Case 70, 3356
            
            MsgBox "Cannot backup just now - the database is already open:" & vbCrLf & "" _
                    & strMDTSourcePath _
                    & vbCrLf & "Backing up is to be perfomed on the first user logging in." _
                    & " Since you watch this message," _
                    & vbCrLf & "- either some workstation has not been configured to backup automatically," _
                    & vbCrLf & "- or some workstation has an invalid system date/time setting.", vbInformation
            Resume BackUpNow_End
        Case 68, 71, 76
            MsgBox "Backup failed!" _
                    & "@Backup folder is not available or cannot be created or device is not ready." _
                    & "@Open Program Options Dialog and choose an existing Backup Folder.", vbInformation '
            Resume BackUpNow_End
        Case Else
            MsgBox "Error " & Err.Number & " (" & Err.Description & ")"
            Resume BackUpNow_End
    End Select
End Function
Sub BubbleSort(pstrItem() As String)

    Dim intDone As Integer, intRow As Integer, intLastItem As Integer
    intLastItem = UBound(pstrItem)
    Do
        intDone = True
        For intRow = 1 To intLastItem - 1
            If pstrItem(intRow) > pstrItem(intRow + 1) Then
                SwapStr pstrItem(), intRow, intRow + 1
                intDone = False
            End If
        Next
    Loop Until intDone
End Sub
Sub SwapStr(pstrItem() As String, ByVal pintRow1 As Integer, ByVal pintRow2 As Integer)

    ' Swaps two elements of pstrItem()
    '
    ' Called from all sort routines except strInsertSort
    '
    Dim strTemp As String
    '
    strTemp = pstrItem(pintRow1)
    pstrItem(pintRow1) = pstrItem(pintRow2)
    pstrItem(pintRow2) = strTemp

End Sub
Public Function WhereAttached() As String
    
    Dim MyTable As TableDef
    Dim MyDB As Database
    Dim i As Integer
    Dim intPos1 As Integer, intPos2 As Integer
On Error GoTo Err_WhereAttached
    WhereAttached = ""
    Set MyDB = CurrentDb
        
    For i = 0 To MyDB.TableDefs.Count - 1
        Set MyTable = MyDB.TableDefs(i)
        If MyTable.Connect <> "" Then
            intPos1 = InStr(1, MyTable.Connect, "DATABASE=")
            If intPos1 > 0 Then
                intPos2 = InStr(intPos1, MyTable.Connect, ";")
                If intPos2 > 0 Then
                    WhereAttached = VBA.Mid$(MyTable.Connect, intPos1 + 9, intPos2 - intPos1 - 9)
                Else
                    WhereAttached = VBA.Mid$(MyTable.Connect, intPos1 + 9)
                End If
            End If
            Exit For
        End If
    Next i

Exit_WhereAttached:
    Exit Function

Err_WhereAttached:
    MsgBox "Error " & Err.Number & " (" & Err.Description & ")"
    Resume Exit_WhereAttached

End Function
Private Function PrpGet(dbs As Database, strPrpName As String) As Variant
On Local Error Resume Next
    PrpGet = dbs.Containers!Databases.Documents("UserDefined").Properties(strPrpName).Value
End Function
Public Function PrpSet(dbs As Database, strPropName As String, intPropType _
    As Integer, varGen As Variant) As Boolean
    
    Dim doc As Document, prp As Property, cnt As Container

    Const conPropertyNotFound = 3270    ' Property not found error.
    Set cnt = dbs.Containers!Databases  ' Define Container object.

On Local Error GoTo PrpSet_Err
    
    Set doc = cnt.Documents!UserDefined
    doc.Properties.Refresh
    ' Set custom property name. If error occurs here it means
    ' property doesn't exist and needs to be created and appended
    ' to Properties collection of Document object.
    Set prp = doc.Properties(strPropName)
    prp = varGen
    PrpSet = True
PrpSet_Bye:
    Exit Function

PrpSet_Err:
    If Err = conPropertyNotFound Then
        Set prp = doc.CreateProperty(strPropName, intPropType, varGen)
        doc.Properties.Append prp       ' Append to collection.
        Resume Next
    ElseIf Err.Number = 3265 Then
        Resume PrpSet_Bye
    Else ' Unknown error.
        PrpSet = False
        Resume PrpSet_Bye
    End If
End Function

This works fine for the tables that are linked to the Back End that was created as a result of splitting the database (in this case that Back End is called "Trinity Data_be.mdb"

However, there are other tables that are otherwise linked. tblNewGivingsArchive is linked to "Trinity Archive.mdb"
and
tblGiftInKindDonations, tblMiscellaneousDonations, tblMiscellaneousFunds, tblUCWDonations, tblUCWExtraAddress, tblUCWMembers are linked to "Trinity Miscellaneous.mdb"

These tables are not picked up in the Backup process. Is there a way to change the code to make that happen.

Tom
 
TH,

Please provide the code that currently calls the above code to back-up the current tables.

ATB

Darrylle

Never argue with an idiot, he'll bring you down to his level - then beat you with experience.
 
Hi Tom,

Why are these 'other' tables not defined in your 'back-end' database?

If they were, they would be backed-up.

ATB

Darrylle

Never argue with an idiot, he'll bring you down to his level - then beat you with experience.
 
Darrylle
Excellent question. I'll try to explain it this way...

This database is for our church. I, with the help of experts such as people on this site, built it from scratch, starting about 12 or more years ago. Over the course of that, I have undertaken some, I think, 4 major revisions.

The database keeps track of all members, their weekly donations, issues receipts, statements, prints any number of reports including a full Directory of people.

We keep in an Active file all donations within the current and immediately preceding year. Each March, anything earlier gets archived. (e.g. in March of 2009, donations for the year 2007 get archived.) For whatever quirky reason, I called the original donations table tblNewGivings, so the archive table is tblNewGivingsArchive. I remember when I built the Archive process, a few years back, I pulled suggestions from the Internet, and the process pointed to having a second .mdb where the archived donations were stored. So this explains the Trinity Archive.mdb

As for the Trinity Miscellaneous Donations.mdb that keeps track of donations in memory of someone at a funeral, and stuff like that...essentially donations from people who have no connection to the church. The donations are entered in the main database, as the tables are linked, but are stored off in the other .mdb

It might be possible to bring those tables into the Back End (the Trinity Data_be.mdb file). Honestly, I never thought of doing that until you raised the question. Rather, I was quite content with things the way they were, as everything works without a hitch, and it keeps Members' data and Non-members' data quite nicely distinct from each other. And it's only a month ago I decided to go searching for a Backup process that would run when the database closes, so to then it was a moot point.

Having said that, I don't know whether or not I have the time right now to get into another rebuild. And it strikes me that, given the number of database objects (queries in particular), it might well be a major rebuild.

I am, however, open to further thinking on this, and would appreciate any wisdom you have to offer.

Thanks, Darrylle!

Tom
 
Darrylle
Well, I tried it...and it's doable. At first blush, it looks as if I wouldn't have to change any queries at all.

Prior to doing that merge of tables from Trinity Archive.mdb and Trinity Miscellaneous.mdb into Trinity Data_be.mdb, here are the .mdb sizes
Trinity Data.mdb 6.64 mb
Trinity Data_be.mdb 2.75 mb
Trinity Archive.mdb 2.04 mb
Trinity Miscellaneous.mdb 540 kb

After the merge there are only 2 files...
Trinity Data.mdb (unchanged)
Trinity Data_be.mdb increases to 5.14 mb

I get pulling in the Miscellaneous tables into the Back End, and that will work.

The question remains about the Archive. Since it only changes once a year, and therefore doesn't require regular back-up, would it be better to keep it separate from the existing Back End?

This is a single user database. Only the church secretary gets into it.

Tom
 
Darrylle
Thanks for pointing me in a new direction on this!

Tom
 
TH,

Your question regarding the 'archive' pretty well relies on your interpretation of it's importance.

If this is a back-up strategy 'archive', then is it important after every record change, or is it important after every day of record changes or month of changes or year of changes?

Remember that last years backup store - records data from last year - as a snapshot - on that day only.
If you backup this year's data - it records just that - the data for this year, at this month, at this day - it will not record CHANGES.

If you want to see data from 3 months ago - this last backup will not be able to show you this, 'cos now data has overwritten such changes.

Imagine this scenario: I change a comment in record 1, and it is stored in the Year 1 archive. (Comment1)
The next year I edit the comment in record 1 to say something else.(Comment2)
Before the archive for the end of year - I edit this comment yet again.(Comment3)
The database is then archived.

Comment2 is lost forever - I didn't back a snapshot of the database up at that time.

I think that this should give you my angle, and it really depends on your requirement when 'backing' data up.

(Companies back data up daily - taking 'snapshots' of whole hard-drives every day), thus they can retrieve any data over certain periods.

It depends on what you would want to retrieve from history.

If it's simply a case of ensuring that the current database structure and data is current (no requirement to look back) - then daily backups to another hard-drive (internal or external) is your answer.

If daily historical data is not required:
1) Back up to ANOTHER physical hard-drive (not just another folder on your current hard-drive).
2) Set MS Scheduler to copy your database app to another hard-drive and shut the PC down after it's done it - very easy. Your database is always backed up - every day.

ATB

Darrylle
Darrylle





Never argue with an idiot, he'll bring you down to his level - then beat you with experience.
 
Darrylle
The "archive" is not a back-up strategy archive. The principal function of the archive piece is to avoid keeping so many records on hand for editing purposes. ONLY the weekly donations to the church go into tblNewGivings and this amounts to roughly 5000 entries per year. Each March, those older than the first of January of the year prior are archived off (thus, in March of 2009 records older than January 1, 2008 are archived).

It's not quite as complicated a database as you are suggesting, so a snapshot of a particular date or month is not required. And we can easily find what we need for any period of time in the database.

I agree completely that making daily backups does not eliminate the necessity of making regular backups to other media. The church secretary makes those backups to CD on a regular basis.

Thanks, Darrylle, for your continued interest. I appreciate it.

Tom
 
Th,

OK - complexity gone.

Only rule is: simply copy the database to another physical location.

Think about Microsoft Scheduler and copy the db to another hard-drive (not the same hard-drive, 'cos this is what will fail).

See ya later.

Darrylle





Never argue with an idiot, he'll bring you down to his level - then beat you with experience.
 
Darrylle
Thanks for the tip. I haven't been familiar with Microsoft Scheduler, so will look it up.

The church computer has only 1 hard drive...that's why backups are made to CDs. I agree that it's not IF hard drives will fail, it's WHEN. I've experienced it.

However, the Backup process I am using could make the backup to a USB drive, and that could be a good route to go.

Tom
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top