Thursday, November 8, 2012

GetKeyState

You can use the GetKeyState API to find out if the user is holding down a particular key. http://msdn.microsoft.com/en-us/library/windows/desktop/ms646301(v=vs.85).aspx I've used this function to take me directly into the VBA code behind a command button while a form is in form view. This is very hand for debugging, but takes some setup. I check for the Ctl-Alt key combination in the OnMouseUp event property of the command button. My OnMouseUp event property looks like this:
=xg_CtrlAltMouseUp()
In the declarations section of a standard module I put:
Const VK_LSHIFT = &HA0
Const VK_RSHIFT = &HA1
Const VK_LCONTROL = &HA2
Const VK_RCONTROL = &HA3
Const VK_LMENU = &HA4
Const VK_RMENU = &HA5
 
#If vba7 Then
    Declare PtrSafe Function GetKeyState Lib "user32" Alias "GetKeyState" (ByVal nVirtKey As Long) As Integer
#Else
    Declare Function GetKeyState Lib "user32" (ByVal nVirtKey As Long) As Integer
#End If
And the function looks like this:
Function xg_CtrlAltMouseUp() As Integer
'******************************************************************************
'* Peter De Baets, author
'* 11/2/2012
'*
'******************************************************************************
Dim Marker As Integer
Dim Rtn As Integer

On Error GoTo Err_Section
Marker = 1

'Return values
'0 if the key is neither down nor toggled,
'-127 if the key is down but not toggled,
'1 if the key is toggled but up, and
'-128 if the key is both toggled and down.
If GetKeyState(VK_LCONTROL) < 0 And GetKeyState(VK_LMENU) < 0 Then
    DoCmd.OpenModule "Form_" & Screen.ActiveForm.Name, _
        Screen.ActiveControl.Name & "_Click"

Else
End If

Exit_Section:
    On Error Resume Next
    On Error GoTo 0
    Exit Function
Err_Section:
    Select Case Err
    Case Else
        Beep
        MsgBox "Error in xg_CtrlAltMouseUp (" & Marker & "), _
        object " & Err.Source & ": " & Err.Number & _
        " - " & Err.Description
    End Select
    Err.Clear
    Resume Exit_Section
End Function

Access 2010: Replacing 32-bit API declarations with 64-bit

Here's a site which lists all the 64-bit API declarations for use in your Access 2010 64-bit application: http://www.excelfin.ru/attachments/article/163/ptrsafe_declarations.txt

Friday, January 6, 2012

Introduction to Access Programming

I get a lot of questions from people who are new to Access development and have never programmed before. Here's an introduction to the subject:

Introduction to Access Programming

(Disclaimer: Please realize that getting involved in programming can be life-changing - not necessarily for the better!)

Thursday, December 29, 2011

Map Network Drives with VBScript

When setting up that Access database on a local area network, you'll likely need to map network drives on each end user's PC. This means you'll be creating a psuedo-drive "Z:" or whatnot, which opens a folder on the server where your Access application back-end resides.

As new computers are added to the network, you'll need to map the network drives on the new computers. This process can be eased by running a VBScript to automatically do the drive mapping. Below is an example script that I use to do this. You can modify the "Actions" to add or remove mapped network drives, in case you have multiple drives mapped, or need to do some mapping clean up.

Just save this code in a file with a .vbs extension, modify it for your needs, then double-click it from Windows Explorer to run it.

' Map network drives 

' Usage
'    Set the size of the ADrive, ARemoteShare, and AAction arrays to
'    be the number of drive mapping actions you want to take. Modify
'    the "Actions" in the "Fill Actions Array" section below, save, 
'    then double-click on this file from Windows Explorer to run it.
'
' "Actions" can be "Remove" (removes/disconnects a mapped network 
' drive), or "Add" (adds a mapped network drive, replacing whatever 
' mapping exists for the same drive letter).
'
' For multiple "Actions", modify the array sizes below, then fill
' the array entries as shown in the "Fill Actions Array" section below.
'
' This script will remove any existing drive map to the same drive letter
' including persistent or remembered connections (Q303209)
'
' from: http://ss64.com/vb/syntax-drivemap.html
' modified by Peter De Baets 12/28/2011

Option Explicit
Dim objNetwork, objDrives, objReg, i, objDrive, fileSys
Dim strReplaceDrive, strLocalDrive, strRemoteShare, strShareConnected, strMessage
Dim bolFoundExisting, bolFoundRemembered
Const HKCU = &H80000001
Dim J
'******************************************
'* Set the size of these arrays to the number
'* of drive mapping actions you want to take.
'*
Dim ADrive(2)
Dim ARemoteShare(2) 
Dim AAction(2)
'*
'****************************************** 


'******************************************
'* Fill Actions Array 
'* (make your changes here)
'*
' Example
'ADrive(1) = "X:"
'ARemoteShare(1) = "\\Servername\Share"
'AAction(1) = "Add"

' Action #1
ADrive(1) = "X:"
ARemoteShare(1) = "\\MyServer\MyShare"
AAction(1) = "Remove"

' Action #2
ADrive(2) = "Z:"
ARemoteShare(2) = "\\MyServer\MyShare"
AAction(2) = "Add"
'*
'******************************************


Set filesys = CreateObject("Scripting.FileSystemObject") 
for j = 1 to ubound(AAction)
  ' Check parameters passed make sense
  If Right(ADrive(j), 1) <> ":" OR Left(ARemoteShare(j), 2) <> "\\" Then
    wscript.echo "INvalid Action #" & j & " //NoLogo"
    WScript.Quit(1)
  End If
  if AAction(j) = "Add" then
    wscript.echo " - Mapping: " + ADrive(j) + " to " + ARemoteShare(j)
  Else
    wscript.echo " - Disconnecting: " + ADrive(j) + " from " + ARemoteShare(j)
  End If
  Set objNetwork = WScript.CreateObject("WScript.Network")
  ' Loop through the network drive connections and disconnect any that match strLocalDrive
  bolFoundExisting = False
  Set objDrives = objNetwork.EnumNetworkDrives
  If objDrives.Count > 0 Then
    For i = 0 To objDrives.Count-1 Step 2
      If objDrives.Item(i) = ADrive(j) Then
     if AAction(j) = "Remove" Then
    set objDrive = fileSys.GetDrive(objDrives.Item(i))
       if objDrive.ShareName = ARemoteShare(j) then
            strShareConnected = objDrives.Item(i+1)
            objNetwork.RemoveNetworkDrive ADrive(j), True, True
            i=objDrives.Count-1
            bolFoundExisting = True
    Else
      wscript.echo " - Drive " + ADrive(j) + " connected to " + ARemoteShare(j) + " not found. Continuing..."
    End if
  Else
       'wscript.echo "  sharename=" + objDrive.ShareName
          strShareConnected = objDrives.Item(i+1)
          objNetwork.RemoveNetworkDrive ADrive(j), True, True
          i=objDrives.Count-1
          bolFoundExisting = True
  End if
      End If
    Next
  End If

  ' If there's a remembered location (persistent mapping) delete the associated HKCU registry key
  If bolFoundExisting <> True Then
    Set objReg = GetObject("winmgmts:{impersonationLevel=impersonate}!\\.\root\default:StdRegProv")
    objReg.GetStringValue HKCU, "Network\" & Left(ADrive(j), 1), "RemotePath", strShareConnected
    If strShareConnected <> "" Then
      objReg.DeleteKey HKCU, "Network\" & Left(ADrive(j), 1)
      Set objReg = Nothing
      bolFoundRemembered = True
    End If
  End If

  if AAction(j) = "Add" then
    'Now actually do the drive map (persistent)
    Err.Clear
    On Error Resume Next
    objNetwork.MapNetworkDrive ADrive(j), ARemoteShare(j), True
  End If
Next 

'Error traps
If Err <> 0 Then
  Select Case Err.Number
    Case -2147023694
      'Persistent connection so try a second time
      On Error Goto 0
      objNetwork.RemoveNetworkDrive ADrive(j), True, True
      objNetwork.MapNetworkDrive ADrive(j), ARemoteShare(j), True
      WScript.Echo "Second attempt to " & AAction(j) & " map drive " & ADrive(j) & " to/from " & ARemoteShare(j)
    Case Else
      On Error GoTo 0
      WScript.Echo " - ERROR: Failed to " & AAction(j) & " map drive " & ADrive(j) & " to/from " & ARemoteShare(j)
  End Select
  Err.Clear
End If

Set objNetwork = Nothing
wscript.echo "Done. "

Saturday, October 1, 2011

How to Set Trusted Locations for a Runtime Application

A user at AccessForums.net asked how to set up trusted locations when the end user doesn't have Access installed. You need to have a bit of a comfort level with regedit, then it is easy:

http://www.accessforums.net/security/how-set-macro-security-distributed-app-17714.html#post81250

Wednesday, September 28, 2011

Copy & Design Action in Navigation Pane Relief v2.0


I use form and report templates when putting together Access applications. This new feature of Navigation Pane Relief v2.0 takes 4 steps out of the process of turning a template into an application object.

For me, a template is simply a form or report that I copy and use as a starting point when designing a new form or report.

I used to right click on the template, select copy, specify a new name, then find the copy in the Navigation Pane, then right click on it and select "Design", then make my changes to it. With the new "Copy & Design" feature in Navigation Pane Relief, I double click "Copy & Design", I specify a new name, and then the copy is automatically opened in design mode. A great time-saver (2 steps instead of 6) if you work from templates.

More information about the new version of Navigation Pane Relief can be found at the Navigation Pane Relief Homepage.

Tuesday, September 20, 2011

Help Tab

In my latest application, I've included an extra tab on each form with help information. I thought this would be easier than writing an entire help add-on. We'll see how my customer likes it.




Other Microsoft Access Blogs

Here are some other Access blogs I check out every now and then:

http://blogs.office.com/b/microsoft-access/

http://msmvps.com/blogs/access/default.aspx

http://blog.nkadesign.com/

http://accessblog.net/

http://rogersaccessblog.blogspot.com/

Connecting to Other Applications Using Late Binding

Here are some great examples of how to use late binding to connect to other Office applications like Excel, PowerPoint, and Word.

http://www.excelguru.ca/node/10

I especially like the way the code checks first for an existing instance of the application, and if not found, gets a new one.

Documenting Using Dia

Visio is nice if you want to create a diagram to document some process or flow in your Access application, but if you don't have Visio, there is a nice (and free) alternative called Dia. You can download it here:

http://live.gnome.org/Dia

I use a flowchart diagram to help me track where different queries are used and what they are used for.

Print Barcodes from Access

You'll need a barcode font, if you don't already have it. Once you install the barcode font on your computer, you can print using that font and your text or ID number will appear as a barcode that can be scanned. Here's the site to download the barcode font:

http://www.idautomation.com/fonts/free/

Longevity

A customer from 10 years ago just contacted me to upgrade ShrinkerStretcher to the latest version. So I would have to assume that he was using the 10 year old version all of this time. That's longevity!

We're now on ShrinkerStretcher version 11.7. You can find out more at http://www.peterssoftware.com/ss.htm