MS Access – VBA – Copy a File

Have you ever needed to make a copy of a file? Well, there are a number of ways that you can do it.

Built-in VBA FileCopy

I find that using the built-in FileCopy function to be the simplest and cleaness method. Below is a simple procedure around it that trap certain common errors.

'---------------------------------------------------------------------------------------
' Procedure : CopyFile
' Author    : Daniel Pineault, CARDA Consultants Inc.
' Website   : http://www.cardaconsultants.com
' Purpose   : Copy a file
'             Overwrites existing copy without prompting
'             Cannot copy locked files (currently in use)
' Copyright : The following is release as Attribution-ShareAlike 4.0 International
'             (CC BY-SA 4.0) - https://creativecommons.org/licenses/by-sa/4.0/
' Req'd Refs: None required
'
' Input Variables:
' ~~~~~~~~~~~~~~~~
' sSource - Path/Name of the file to be copied
' sDest - Path/Name for copying the file to
'
' Revision History:
' Rev       Date(yyyy/mm/dd)        Description
' ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
' 1         2007-Apr-01             Initial Release
'---------------------------------------------------------------------------------------
Public Function CopyFile(sSource As String, sDest As String) As Boolean
On Error GoTo CopyFile_Error

    FileCopy sSource, sDest
    CopyFile = True
    Exit Function

CopyFile_Error:
    If Err.Number = 0 Then
    ElseIf Err.Number = 70 Then
        MsgBox "The file is currently in use and therfore is locked and cannot be copied at this" & _
               " time.  Please ensure that no one is using the file and try again.", vbOKOnly, _
               "File Currently in Use"
    ElseIf Err.Number = 53 Then
        MsgBox "The Source File '" & sSource & "' could not be found.  Please validate the" & _
               " location and name of the specifed Source File and try again", vbOKOnly, _
               "File Currently in Use"
    Else
        MsgBox "MS Access has generated the following error" & vbCrLf & vbCrLf & "Error Number: " & _
               Err.Number & vbCrLf & "Error Source: CopyFile" & vbCrLf & _
               "Error Description: " & Err.Description, vbCritical, "An Error has Occurred!"
    End If
    Exit Function
End Function

All you have to do is copy it into a module and then call it as required. Enjoy!

Copying a File Using FSO

As an alternative, here is an example to copy a file using FSO.

'---------------------------------------------------------------------------------------
' Procedure : FSO_FileCopy
' Author    : Daniel Pineault, CARDA Consultants Inc.
' Website   : http://www.cardaconsultants.com
' Purpose   : Copy a file
'               Overwrites existing copy without prompting (you can change the varible
'               in the CopyFile method call)
' Copyright : The following is release as Attribution-ShareAlike 4.0 International
'             (CC BY-SA 4.0) - https://creativecommons.org/licenses/by-sa/4.0/
' Req'd Refs: Uses Late Binding, so none required
' Ref       : FSO - https://msdn.microsoft.com/en-us/library/ms127964(v=vs.110).aspx
'
' Input Variables:
' ~~~~~~~~~~~~~~~~
' sSource - Path/Name of the file to be copied
' sDest - Path/Name for copying the file to
'
' Usage:
' ~~~~~~
' FSO_FileCopy("C:\TE.MP\Tab.le1.txt", "C:\TE.MP\Tab.le3.txt")
'
' Revision History:
' Rev       Date(yyyy/mm/dd)        Description
' **************************************************************************************
' 1         2018-06-16              Initial Release - Blog Help
'---------------------------------------------------------------------------------------
Public Function FSO_FileCopy(ByVal sSource As String, _
                             ByVal sDest As String) As Boolean
    On Error GoTo Error_Handler
    Dim oFSO                  As Object

    Set oFSO = CreateObject("Scripting.FileSystemObject")
    Call oFSO.CopyFile(sSource, sDest, True)
    FSO_FileCopy = True

Error_Handler_Exit:
    On Error Resume Next
    If Not oFSO Is Nothing Then Set oFSO = Nothing
    Exit Function

Error_Handler:
    MsgBox "The following error has occurred" & vbCrLf & vbCrLf & _
           "Error Number: " & Err.Number & vbCrLf & _
           "Error Source: FSO_FileCopy" & vbCrLf & _
           "Error Description: " & Err.Description & _
           Switch(Erl = 0, "", Erl <> 0, vbCrLf & "Line No: " & Erl) _
           , vbOKOnly + vbCritical, "An Error has Occurred!"
    Resume Error_Handler_Exit
End Function

MS Access – VBA – Rename a File

Ever simply needed to rename a file? Well, once again there are a multitude of ways to accomplish this within MS Access. I have seen numerous postings suggest using a scripting object and then copy the file while renaming the copied version. To me, if all you need is to rename the file, this is a uselessly complicated method. Instead, why not simply use the Name Statement? It can all be accomplished in one clean line of code!!!

Name "C:\OldFileName" AS "C:\NewFileName"

Actually, you can even use the Name command to move and rename a file simultaneously.

Name "C:\OldDir\OldFileName" AS "C:\NewDir\NewFileName"

As you can see this is another versatile command to be aware of.

VBA – Run/Execute A File

Ever needed to run, execute a file? It could be a *.bat, *.vbs, *.exe, … One common method is to use the shell function. However, we see quite often in the forums and newsgroups regarding issues with it not working and users not getting the synthax right because of spaces in the file paths, etc.

Below is, yet again, a very simple procedure which encapsulates the file to be run/executed with the necessary quotations so that you no longer have any headaches trying to get your Shell function operational. Simply copy the function to a module and call it as indicated below.

'---------------------------------------------------------------------------------------
' Procedure : RunFile
' Author    : CARDA Consultants Inc.
' Website   : http://www.cardaconsultants.com
' Purpose   : Run/Execute files from vba (bat, vbs,…)
' Copyright : The following may be altered and reused as you wish so long as the
'             copyright notice is left unchanged (including Author, Website and
'             Copyright).  It may not be sold/resold or reposted on other sites (links
'             back to this site are allowed).
'
' Input Variables:
' ~~~~~~~~~~~~~~~~
' strFile - full path including filename and extension
' strWndStyle - style of the window in which the program is to be run
'               value can be vbHide,vbNormalFocus,vbMinimizedFocus
'               vbMaximizedFocus,vbNormalNoFocus or vbMinimizedNoFocus
'
' Usage Example:
' ~~~~~~~~~~~~~~~~
' RunFile("c:\test.bat", vbNormalFocus)
'
' Revision History:
' Rev       Date(yyyy/mm/dd)        Description
' **************************************************************************************
' 1         2010-Feb-05             Initial Release
'---------------------------------------------------------------------------------------
Function RunFile(strFile As String, strWndStyle As String)
On Error GoTo Error_Handler

   Shell "cmd /k """ & strFile & """", strWndStyle

Error_Handler_Exit:
   On Error Resume Next
   Exit Function

Error_Handler:
   MsgBox "MS Access has generated the following error" & vbCrLf & vbCrLf & "Error Number: " & _
   Err.Number & vbCrLf & "Error Source: RunFile" & vbCrLf & "Error Description: " & _
   Err.Description, vbCritical, "An Error has Occurred!"
   Resume Error_Handler_Exit
End Function

If however you are interested in opening a file, any type of file, then please refer to my MS Access VBA – Open a File post.

MS Access – VBA – Automatically Adjust User Input to Percentage Values

Have you ever created a control on a form to enter percentage values and had your users complain because they enter whole numbers which get automatically multiplied by 100. So if the user enters 3, it will actually give 300%.

No worries anymore! I created a very simple procedure which will automatically readjust values entered by your users. 3 will automatically be updated to 0.03, which give 3%.

'---------------------------------------------------------------------------------------
' Procedure : ajustPercentage
' Author    : CARDA Consultants Inc.
' Website   : http://www.cardaconsultants.com
' Purpose   : Automatically adjust whole number to percentage values
' Copyright : The following may be altered and reused as you wish so long as the
'             copyright notice is left unchanged (including Author, Website and
'             Copyright).  It may not be sold/resold or reposted on other sites (links
'             back to this site are allowed).
'
' Revision History:
' Rev       Date(yyyy/mm/dd)        Description
' **************************************************************************************
' 1         2010-Sep-21                 Initial Release
'---------------------------------------------------------------------------------------
Function ajustPercentage(sValue As Variant) As Double
On Error GoTo Error_Handler

    If IsNumeric(sValue) = True Then            'Only treat numeric values
        If Right(sValue, 1) = "%" Then
            sValue = Left(sValue, Len(sValue) - 1)
            ajustPercentage = CDbl(sValue)
        End If
        
        If sValue > 1 Then
            sValue = sValue / 100
            ajustPercentage = sValue
        Else
            ajustPercentage = sValue
        End If
    Else                                        'Data passed is not of numeric type
        ajustPercentage = 0
    End If

Error_Handler_Exit:
    On Error Resume Next
    Exit Function

Error_Handler:
    MsgBox "The following error has occurred" & vbCrLf & vbCrLf & _
           "Error Number: " & Err.Number & vbCrLf & _
           "Error Source: ajustPercentage" & vbCrLf & _
           "Error Description: " & Err.Description, vbCritical, _
           "An Error has Occurred!"
    Resume Error_Handler_Exit
End Function

The one thing to note regarding this procedure is that it is meant for controls/fields that you always expect a percentage value between 0% and 100%. If you expect percentage above 100% this procedure will not help you in that case and you will need to build a custom procedure for that situation.

MS Access – VBA – Import Directory Listing Into A Table

I was asked in a forum how one could automate importing the links (path & Filename) of all the files contained within a specified directory. It is relatively easy to accomplish and the procedure below is one possible method.

The procedure has 2 input variables:

  • strPath which is the full path of the directory whose files you wish to import all the file paths from
  • strFilter which is an optional input variable should you wish to refine what type of document is imported (for instance is you only want to import PDFs then you’d enter “pdf”, Word documents “doc”, and so on)

Do not forget to select the sSQL statement that suits your needs (simply comment out the other 2) and replace the YourTableName, YourTableFieldName, YourTablePathFieldName and/or YourTableFileFieldName to match your table and field(s) names.

Continue reading

VBA – Word – Update/Fill-in Document Form Fields

Have you ever needed to fill-in or update the form fields of a Word Document from say Access, Excel, … Below is a simple example of how you can do this. In it I demonstrate how to populate a textbox, as well as show you how you can check/uncheck a checkbox.

'---------------------------------------------------------------------------------------
' Procedure : UpdateDoc
' Author    : CARDA Consultants Inc.
' Website   : http://www.cardaconsultants.com
' Purpose   : Update/Fill-in a Word document's form fields
' Copyright : The following may be altered and reused as you wish so long as the
'             copyright notice is left unchanged (including Author, Website and
'             Copyright).  It may not be sold/resold or reposted on other sites (links
'             back to this site are allowed).
'
' Revision History:
' Rev       Date(yyyy/mm/dd)        Description
' **************************************************************************************
' 1         2010-Sep-17                 Initial Release
'---------------------------------------------------------------------------------------
Sub UpdateDoc()
'Requires a reference to the Word object library
Dim oApp        As Object 'Word.Application
Dim oDoc        As Object 'Word.Document
Dim sDocName    As String

On Error Resume Next
    Set oApp = GetObject(, "Word.Application") 'See if word is already running
    If Err.Number <> 0 Then     'Word isn't running so start it
        Set oApp = CreateObject("Word.Application")
    End If

On Error GoTo Error_Handler_Exit
    sDocName = "YourWordDocToOpenFullPathAndExtension"
    Set oDoc = oApp.Documents.Open(sDocName)
    oApp.Visible = True
    
    oDoc.FormFields("TextboxName").Result = "NewValue"      'Textbox
    oDoc.FormFields("CheckboxName").CheckBox.Value = True   'Checkbox

Error_Handler_Exit:
    On Error Resume Next
    oDoc.Close True
    oApp.Quit
    Set oDoc = Nothing
    Set oApp = Nothing
    Exit Sub

Error_Handler:
    If Err.Number = 5174 Then
        MsgBox "The specified file '" & sDocName & "' could not be found.", _
               vbCritical
    Else
        MsgBox "The following error has occurred." & vbCrLf & vbCrLf & _
               "Error Number: " & Err.Number & vbCrLf & _
               "Error Source: UpdateDoc" & vbCrLf & _
               "Error Description: " & Err.Description, _
               vbCritical, "An Error has Occurred!"
    End If
    Resume Error_Handler_Exit
End Sub

MS Access – Report – Sequential Numbering of Records

Have you ever needed to add a sequential number to a report’s rows. Well, it is surprising easy to do!

All you need to do is add a textbox into the detail section of your report and set the control’s Control Source property to ‘=1’ and then set the Running Sum property to either ‘Over Group’ or ‘Over All’ depending on what you are trying to achieve. The properties should be as shown below.

Textbox properties to setup sequential numbering in an MS Access Report
Textbox properties to setup sequential numbering in an MS Access Report

Close and save your changes and run your report. That’s it! It is that simple.

Launch/Open an MS Access Database Using a VBScript – Part 2

In my previous post launch-open-an-ms-access-database-using-a-vbscript I went over the basic concept of using a VBScript to launch a database.

In this post I would like to demonstrate the true power of VBScript for this type of application.

Say, you are a developer within a structured company network environment and you want to standardize the front-end setup on your users computers without having to sit down at each of their computers, one by one. Well, VBScript to the rescue!

The script below may seem scary, but really isn’t. It start by determining the user’s My Documents location. This is where I have chosen to place the Front-End application of the database. You could always alter this aspect, but it has served me very well in numerous routines. Once it has determine the location it determines the location of the VBScript itself (which will be installed with the Master copy of the Front-end). As such, it copies the Master copy to the user’s My Documents. Then it determines the location of the msaccess.exe required to launch the database and then finally launches it!

Once again, I do hope this helps someone out there as I found it hard to come across this information several years ago when I needed it.

'*******************************************************************************
'Date:		2008-05-27
'Author:	Daniel Pineault / CARDA Consultants Inc.
'Purpose:	This script should be located on a network share in the same
'		directory as the Front-End which it will automatically copy
'		to each user's MyDoc\Subfolder\ and then launch
'		Give your users a link to this script and it will do the rest
'Copyright:	You are free to use the following code as you please so long as
'		this header remains unaltered.
'Revision:	2008-05-27   Initial Release
'*******************************************************************************

	Const MY_DOCUMENTS = &H5&
	Const PROGRAM_FILES = &H26&

	Dim objShell
	Dim objFolder
	Dim objFolderItem
	Dim objNetwork
	Dim objFSO
	Dim objShellDb
	Dim DelFoldr
	Dim sMyDocPath
	Dim sProgPath
	Dim sVBSPath
	Dim sAccPath
	Dim sFrontEnd
	Dim sFolder
	Dim sSec
	Dim sUser
	Dim sPath
	Dim sComTxt


	'Specify the Fullpath and filename of the database to launch
	sFrontEnd = "test.mdb"	'Database name to open
	sFolder = "Databases"		'MyDoc subfolder where the
						'front-end will be copied to
	'If your database is secured by an mdw file specify it below, otherwise
	'leave its value blank
	sSec = "Security.mdw"


'Determine the location/path of the user's MyDocuments folder
'*******************************************************************************
	Set objShell = CreateObject("Shell.Application")
	Set objFolder = objShell.Namespace(MY_DOCUMENTS)
	Set objFolderItem = objFolder.Self
	sMyDocPath = objFolderItem.Path		'My Documents path
	sPath = sMyDocPath & "\" & sFolder & "\"'Path to front-end
	Set objFolder = objShell.Namespace(PROGRAM_FILES)
	Set objFolderItem = objFolder.Self
	sProgPath = objFolderItem.Path		'Program Files Path

'Determine path of this VBScript
'*******************************************************************************
	sVBSPath = Left(WScript.ScriptFullName,(Len(WScript.ScriptFullName) _
		     - (Len(WScript.ScriptName) + 1)))

	'Ensure lastest version of front-end is installed
	Set objNetwork = CreateObject("Wscript.Network")
	sUser = objNetwork.UserName			'User's network username
	Set objFSO = CreateObject("Scripting.FileSystemObject")

'Copy a network version of the Front-end to the MyDocs/SubFolder
'*******************************************************************************
	'Create application folder if it does not already exist
	If objFSO.FolderExists(sPath) = False then
		Set objFolderCreate = objFSO.CreateFolder(sPath)
	End If
	'Delete the existing copy to ensure we have a fresh copy
	If objFSO.FileExists(sPath & sFrontEnd) then
    		'Delete the file to copy a new fresh copy
    		Set DelFile = objFSO.GetFile(sPath & sFrontEnd)
    		DelFile.Delete
		Do While objFSO.FileExists(sPath & sFrontEnd) = True
			WScript.Sleep 100
		Loop
  	End if
	'Copy a fresh copy of the FE
	objFSO.CopyFile sVBSPath & "\" & sFrontEnd, sPath & _
                  	sFrontEnd, OverWriteExisting
	Do While objFSO.FileExists(sPath & sFrontEnd) = False
		WScript.Sleep 100
	Loop

'Determine the location of the MS Access executable
'*******************************************************************************
'	Set objShellDb = CreateObject("WScript.Shell")
'	'Determine in which folder the Access executable is located
'	If objFSO.FileExists(sProgPath &_
'                     	     "\Microsoft Office\OFFICE11\msaccess.exe") Then
'		sAccPath = sProgPath & "\Microsoft Office\OFFICE11"
'	Elseif objFSO.FileExists(sProgPath &_
'                                 "\Microsoft Office\OFFICE10\msaccess.exe") Then
'  		sAccPath = sProgPath & "\Microsoft Office\OFFICE10"
'	Elseif objFSO.FileExists(sProgPath &_
'                                 "\Microsoft Office\OFFICE\msaccess.exe") Then
'  		sAccPath = sProgPath & "\Microsoft Office\OFFICE"
'	End if
	sAppEXE = "MSACCESS.EXE"
	sRegKey = "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\" & sAppEXE & "\Path"
	sAccPath = objShellDb .RegRead(sRegKey)


'Launch database
'*******************************************************************************
	'Build the command to launch the database
	sComTxt = chr(34) & sAccPath & "msaccess.exe" & chr(34) &_
		  " " & chr(34) & sPath & sFrontEnd & chr(34)
	if isNull(sSec)=False AND sSec<>"" Then
		sComTxt = sComTxt & " /wrkgrp " & chr(34) & sVBSPath &_
			  "\" & sSec & chr(34)
		if isNull(sUser)=False AND sUser<>"" Then
			sComTxt = sComTxt & " /user " & sUser
		End if
	End if

	objShellDb.Run sComTxt 'Launch the database

Launch/Open an MS Access Database Using a VBScript

Have you ever tried to make a shortcut to launch/open an MS Access database and had an error returned because the Target string was too long? Or do you simply need more control/flexibility from your launching routine. In that case, a VBScript is the ideal way to go. Below is the most basic format that the VBScript can take. Simply alter the Script Variables, Save and execute!

I have made the following as flexible as possible so it can open simple database files, as well as security enabled database. It is simply a question of assigning values to the Script Variables or not.

I truly hope this helps you out!

'*******************************************************************************
'Date:		2008-05-27
'Author:	Daniel Pineault / CARDA Consultants Inc.
'		http://www.cardaconsultants.com
'Copyright:	You are free to use the following code as you please so long as
'		this header remains unaltered.
'Purpose:	Launch the specified access database
'Revision:	2008-05-27   Initial Release
'*******************************************************************************

	Dim sAcc
	Dim sFrontEnd
	Dim sSec
	Dim sUser
	Dim objShellDb
	Dim sComTxt

'Script Configuration Variable
'*******************************************************************************
	'Specify the Fullpath and filename of the msaccess executable
	sAcc = "C:\Program Files\Microsoft Office\OFFICE11\msaccess.exe"
	'Specify the Fullpath and filename of the database to launch
	sFrontEnd = "D:\Main\My Documents\TestDb.mdb"
	'If your database is secured by an mdw file specify it below, otherwise
	'leave its value blank
	sSec = "C:\Databases\Security.mdw"
	'If your database is secured by an mdw file and you want to specify the
	'username to use specify it below, otherwise leave its value blank
	sUser = ""


'*******************************************************************************
'*******************************************************************************
'You should not need to edit anything below this point
'*******************************************************************************
'*******************************************************************************


'Launch database
'*******************************************************************************
	Set objShellDb = CreateObject("WScript.Shell")
	'Build the command to launch the database
	sComTxt = chr(34) & sAcc & chr(34) &_
		  " " & chr(34) & sFrontEnd & chr(34) 
	if isNull(sSec)=False AND sSec<>"" Then
		sComTxt = sComTxt & " /wrkgrp " & chr(34) & sSec & chr(34)
	End if
	if isNull(sUser)=False AND sUser<>"" Then
		sComTxt = sComTxt & " /user " & sUser
	End if
	objShellDb.Run sComTxt 'Launch the database

Web Devlopment Learning Resource – Where to Start

I short while I was asked to sit down with a graphic artist who also was a web developer because they wanted me to teach them what I knew because I had commented on their work to their client (who happened to also be one of my database clients).

I was more than happy to oblige, as I have no problem trying to help someone else out when I can.

They basically knew how-to use Dreamweaver, but that was about it. So I went over a number of things that I have learnt in the past few years and thought I should post them here should they be useful to someone else. So here goes…

The first aspect I wanted to emphasize was the importance of clean code! What does this entail, a couple of simple things really:

  • CSS driven design
  • Separate files for CSS, JS
  • Clean directory structure. Don’t dump everything into the root folder, but rather make a simple directory structure (images, js, css, …)
  • When appropriate add comments within your code so you can find yourself at a later date.
  • Ensure that your design is cross-browser compliant. Long gone are the days that Internet Explorer is the only web browser, so make sure your website works in the other browsers (Firefox, Opera, Safari, and many more…)
  • Ensure your code is W3C compliant by simply testing each of your pages with their Free Validation tools (links provided below). Take some time to get to know the standards and utilize all the free information this organisation provides.

 

W3C Links

 

Other Useful Links

 

Javascript and JQuery

At some point or another you will be faced with the need to add some form of automation to your webpage. At that point you will need to look into javascripting,… I would urge you to simply go straight to learning JQuery instead. It actually use javascript, but is simpler and comes with many already existing functions and samples. Believe me, this will save you time and frustrations in the long run and will give you tremendous capabilities right from the start. Another beauty is that unlike custom javascript functions, jQuery is crossbrowser compatible! This will save you countless hours of testing, troubleshooting and finding browser hacks!!! Check it out for yourself at: http://jquery.com/

I truly hope this brief article gives you a jump start into web development and various online resources at your disposal. Have fun!