Thursday, September 22, 2011

Query Access Database (MDB) from Python

Ever wish that you could quickly run a query against an Access database (MDB) from a command line? If you're already working within a command line this can be very efficient to do a quick lookup. Here's how this can be accomplished.

  1. Install pyodbc
  2. Copy the lookup.py code into a file and edit the MDB and SQL variables to suit your needs
  3. Copy the lookup.bat file into a file (you may need to edit the path to point to lookup.py)
  4. You should save lookup.bat to a folder that is within your Windows Path

lookup.py

import sys, csv
import pyodbc

# Handle command line arguments
if len(sys.argv) == 1:
    print "Enter usage notes here"
    print "(use % for wildcard)"
    sys.exit()
print "Searching for '%s'" % sys.argv[1]
print ""

# Query the CLLI MDB
MDB  = "PATH TO MDB"
DRV  = "{Microsoft Access Driver (*.mdb)}"
conn = pyodbc.connect("DRIVER=%s;DBQ=%s" % (DRV,MDB))
curs = conn.cursor()
SQL  = "SELECT * FROM table WHERE col='%s'" % sys.argv[1]
curs.execute(SQL)
rows = curs.fetchall()
curs.close()
conn.close()

# Print out results
i = 1
for row in rows:
    print "Result #%s" % i
    print "--------------------------"
    for col in row:
        print col
    print ""
    i = i + 1

lookup.bat

@call python.exe lookup.py %1


Tuesday, September 20, 2011

Excel User Defined Function for Ping

Here's another Excel UDF that I'm sharing with everyone. This User Defined Function allows a user to execute a Windows ping command from an Excel cell. Currently this code is written to parse a string for an IP Address and ping that address (that's the desired effect I was looking for). If you wish to ping hostnames as well, you can make the following subsitution

Old: retVal = sPing(FindIP(sHost), 1, 200)
New: retVal = sPing(sHost, 1, 200)

Here are some examples of how to use the UDF and the code itself.

Ex. =ping("192.168.1.0")        'returns average ms response time
Ex. =ping("192.168.1.0")        'returns received ICMP packets


'--------------------------------------------
'Ping UDF
'--------------------------------------------
'A ping function formatted for use as an Excel cell formula
'sHost - the host to be pinged
'selectVal - optional parameter that defines what should be returned
'          - refer to sPing return type for clarification of what 
'            value to be used
'          - the default return is the millisecond average ping time
Function Ping(sHost As String, Optional selectVal As Integer) As String
Dim retVal As Variant
retVal = sPing(FindIP(sHost), 1, 200)
If retVal(1) <> 0 Then
    If selectVal = 0 Then
        Ping = retVal(4)
    Else
        Ping = retVal(selectVal)
    End If
Else
    Ping = "#N/A"
End If

End Function
 
'--------------------------------------------
'Find IP Address
'--------------------------------------------
'A support function that parses input strTest through a regular
'expression to find an IP Address
'A blank value is returned if no IP address can be found
Function FindIP(strTest As String) As String
    Dim RegEx As Object
    Dim valid As Boolean
    Dim Matches As Object
    Dim i As Integer
    Set RegEx = CreateObject("VBScript.RegExp")
   
    RegEx.Pattern = "\b(?:\d{1,3}\.){3}\d{1,3}\b"
    valid = RegEx.test(strTest)
    If valid Then
        Set Matches = RegEx.Execute(strTest)
        FindIP = Matches(0)
    Else
        FindIP = ""
    End If
End Function

'--------------------------------------------
'Ping Support Function
'--------------------------------------------
'This function runs a cmd ping request 
'sHost    - the host to be pinged
'numPings - the number of ICMP ping packets to send
'msDelay  - the ping timeout delay
'
'The return value from this function is an array with the following 
'values defined
'sPing(0) - Transmitted ICMP Packets
'sPing(1) - Received ICMP Packets
'sPing(2) - Lost ICMP Packets
'sPing(3) - Maximum Round Trip Time
'sPing(4) - Average Round Trip Time
'sPing(5) - Comments
Function sPing(sHost As String, numPings As Integer, msDelay As Integer) As Variant
    Dim oFSO As Object, oShell As Object, oTempFile As Object
    Dim sLine As String, sFilename As String
    Dim retVal(5) As String
    
    Set oFSO = CreateObject("Scripting.FileSystemObject")
    Set oShell = CreateObject("Wscript.Shell")
   
   
    sFilename = oFSO.GetTempName
    oShell.Run "cmd /c ping -n " & numPings & " -w " & msDelay & " " & sHost & " > " & sFilename, 0, True
    Set oTempFile = oFSO.OpenTextFile(sFilename, 1)
    Do While oTempFile.AtEndOfStream <> True
    sLine = oTempFile.Readline
    cmdStr = cmdStr & Trim(sLine)
    Loop
    oTempFile.Close
    oFSO.DeleteFile (sFilename)

    If cmdStr = "IP address must be specified." Then
        retVal(5) = "IP address must be specified"
        sPing = retVal
        Exit Function
    End If
   
    If InStr(1, cmdStr, "Ping request could not find host", vbTextCompare) > 0 Then
        retVal(6) = "Could not find host"
        sPing = retVal
        Exit Function
    End If
   
    txLoc = InStr(1, cmdStr, "Sent = ", vbTextCompare)
    If txLoc > 0 Then
        txLoc = txLoc + 7
        txLoc2 = InStr(txLoc, cmdStr, ",", vbTextCompare)
        retVal(0) = Trim(Mid(cmdStr, txLoc, txLoc2 - txLoc))
    End If
   
    rxLoc = InStr(1, cmdStr, "Received = ", vbTextCompare)
    If rxLoc > 0 Then
        rxLoc = rxLoc + 11
        rxLoc2 = InStr(rxLoc, cmdStr, ",", vbTextCompare)
        retVal(1) = Trim(Mid(cmdStr, rxLoc, rxLoc2 - rxLoc))
    End If
   
    ltLoc = InStr(1, cmdStr, "Lost = ", vbTextCompare)
    If ltLoc > 0 Then
        ltLoc = ltLoc + 7
        ltLoc2 = InStr(ltLoc, cmdStr, "(", vbTextCompare)
        retVal(2) = Trim(Mid(cmdStr, ltLoc, ltLoc2 - ltLoc))
    End If
   
    maxLoc = InStr(1, cmdStr, "Maximum = ", vbTextCompare)
    If maxLoc > 0 Then
        maxLoc = maxLoc + 10
        maxLoc2 = InStr(maxLoc, cmdStr, "ms", vbTextCompare)
        retVal(3) = Trim(Mid(cmdStr, maxLoc, maxLoc2 - maxLoc))
    End If
   
    aveLoc = InStr(1, cmdStr, "Average = ", vbTextCompare)
    If aveLoc > 0 Then
        aveLoc = aveLoc + 10
        aveLoc2 = InStr(aveLoc, cmdStr, "ms", vbTextCompare)
        retVal(4) = Trim(Mid(cmdStr, aveLoc, aveLoc2 - aveLoc))
    End If
    sPing = retVal
End Function

Monday, September 19, 2011

Excel User Defined Function for CIDR Subnet Mask Notation

Here's another one of the Excel UDF's I have prepared for performing network operations in Excel. I find it specifically useful when dealing with large data sets. This function converts a subnet mask to CIDR notation. It is implemented with statically defining a dictionary object. It may not be an elegant solution, but it is works.

Ex. CIDR("255.128.0.0")=9

'--------------------------------------------
'CIDR (Classless Inter-Domain Routing)
'--------------------------------------------
'Given an inputStr value containing a subnet mask in an IP 
'format this functio returns the corresponding subnet mask 
'in CIDR Notation
Function cidr(inputStr As String)
    Dim maskDict As Dictionary
    Set maskDict = New Dictionary
    maskDict.Add "128.0.0.0", 1
    maskDict.Add "192.0.0.0", 2
    maskDict.Add "224.0.0.0", 3
    maskDict.Add "240.0.0.0", 4
    maskDict.Add "248.0.0.0", 5
    maskDict.Add "252.0.0.0", 6
    maskDict.Add "254.0.0.0", 7
    maskDict.Add "255.0.0.0", 8
    maskDict.Add "255.128.0.0", 9
    maskDict.Add "255.192.0.0", 10
    maskDict.Add "255.224.0.0", 11
    maskDict.Add "255.240.0.0", 12
    maskDict.Add "255.248.0.0", 13
    maskDict.Add "255.252.0.0", 14
    maskDict.Add "255.254.0.0", 15
    maskDict.Add "255.255.0.0", 16
    maskDict.Add "255.255.128.0", 17
    maskDict.Add "255.255.192.0", 18
    maskDict.Add "255.255.224.0", 19
    maskDict.Add "255.255.240.0", 20
    maskDict.Add "255.255.248.0", 21
    maskDict.Add "255.255.252.0", 22
    maskDict.Add "255.255.254.0", 23
    maskDict.Add "255.255.255.0", 24
    maskDict.Add "255.255.255.128", 25
    maskDict.Add "255.255.255.192", 26
    maskDict.Add "255.255.255.224", 27
    maskDict.Add "255.255.255.240", 28
    maskDict.Add "255.255.255.248", 29
    maskDict.Add "255.255.255.252", 30
    maskDict.Add "255.255.255.254", 31
    maskDict.Add "255.255.255.255", 32
    cidr = maskDict.Item(FindIP(inputStr))
End Function

'--------------------------------------------
'Find IP Address
'--------------------------------------------
'A support function that parses input strTest through a regular 
'expression to find an IP Address
'A blank value is returned if no IP address can be found
Function FindIP(strTest As String) As String
    Dim RegEx As Object
    Dim valid As Boolean
    Dim Matches As Object
    Dim i As Integer
    Set RegEx = CreateObject("VBScript.RegExp")
   
    RegEx.Pattern = "\b(?:\d{1,3}\.){3}\d{1,3}\b"
    valid = RegEx.test(strTest)
    If valid Then
        Set Matches = RegEx.Execute(strTest)
        FindIP = Matches(0)
    Else
        FindIP = ""
    End If
End Function