Monday, August 1, 2011

Excel User Defined Function - nslookup

Recently I have found myself in a position where I needed to run basic networking commands on numerous remote devices. At the end of the day I often found myself with several command prompts or cygwin bash shells open where I had to run umpteen nslookup commands. 

It didn't take long for me to find this whole process entirely unsatisfactory. I wanted to a way to run these commands very quickly and have the results returned in a place that I could refer to afterwards. I turned to the internet and ultimately did not find a simple, free, trustworthy utility that I could use to serve this purpose.

I turned to Excel and decided to write a user defined function that completes an nslookup command. The function has two parameters as described below:

nslookup( lookupVal, [addressOpt] )

lookupVal: represents the hostname or ip address that you wish to lookup

addressOpt: An integer that can have one of the values below

<blank> Auto Detect
0 Auto Detect
1 Forced Address Lookup
2 Forced Name Lookup

Here's some examples of how to run the code
=nslookup("hostname")           
=nslookup("148.175.254.250")
=nslookup("www.google.com",1)

=nslookup("149.175.254.240",2)
=nslookup(B1)
The full Excel UDF is shown below. In order to get this function working properly you should save copy this code into a module, save the Excel File as an .xlam file, and add the file as an Add-in to Excel. A subsequent blog post will detail this process. Alternatively you can just add it as a function within an Excel file if you only need to use it in that file.

Public Function NSLookup(lookupVal As String, Optional addressOpt As Integer) As String
   Const ADDRESS_LOOKUP = 1
   Const NAME_LOOKUP = 2
   Const AUTO_DETECT = 0
   
   'Skip everything if the field is blank
   If lookupVal <> "" Then
        Dim oFSO As Object, oShell As Object, oTempFile As Object
        Dim sLine As String, sFilename As String
        Dim intFound As Integer
        Set oFSO = CreateObject("Scripting.FileSystemObject")
        Set oShell = CreateObject("Wscript.Shell")
        
        'Handle the addresOpt operand
        'Regular Expressions are used to complete a substring match for an IP Address
        'If an IP Address is found, a DNS Name Lookup will be forced
        If addressOpt = AUTO_DETECT Then
            ipLookup = FindIP(lookupVal)
            If ipLookup = "" Then
                addressOpt = ADDRESS_LOOKUP
            Else
                addressOpt = NAME_LOOKUP
                lookupVal = ipLookup
            End If
        'Do a regular expression substring match for an IP Address
        ElseIf addressOpt = NAME_LOOKUP Then
            lookupVal = FindIP(lookupVal)
        End If
        
        'Run the nslookup command
        sFilename = oFSO.GetTempName
        oShell.Run "cmd /c nslookup " & lookupVal & " > " & sFilename, 0, True
        Set oTempFile = oFSO.OpenTextFile(sFilename, 1)
        Do While oTempFile.AtEndOfStream <> True
            sLine = oTempFile.Readline
            cmdStr = cmdStr & Trim(sLine) & vbCrLf
        Loop
        oTempFile.Close
        oFSO.DeleteFile (sFilename)
        
        'Process the result
        intFound = InStr(1, cmdStr, "Name:", vbTextCompare)
        If intFound = 0 Then
            NSLookup = "NotFound"
            Exit Function
        ElseIf intFound > 0 Then
            'TODO: Cleanup with RegEx
            If addressOpt = ADDRESS_LOOKUP Then
                loc1 = InStr(intFound, cmdStr, "Address:", vbTextCompare) + InStr(intFound, cmdStr, "Addresses:", vbTextCompare)
                loc2 = InStr(loc1, cmdStr, vbCrLf, vbTextCompare)
                nameStr = Trim(Mid(cmdStr, loc1 + 8, loc2 - loc1 - 8))
            ElseIf addressOpt = NAME_LOOKUP Then
                loc1 = InStr(intFound, cmdStr, "Name:", vbTextCompare)
                loc2 = InStr(loc1, cmdStr, vbCrLf, vbTextCompare)
                nameStr = Trim(Mid(cmdStr, loc1 + 5, loc2 - loc1 - 5))
            End If
        End If
        NSLookup = nameStr
    Else
        NSLookup = "N/A"
    End If
End Function

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

35 comments:

  1. has anyone ported this to Excel 2011 for OS X?

    ReplyDelete
  2. Just had to say thanks - very nice and useful code. I was able to save this as an add-in for later use, as well.

    ReplyDelete
  3. Dude, this script rocks. thanks!

    ReplyDelete
  4. This is awesome code, but it only works intermittently for me (sometimes I just get the #VALUE! error). I've toggled macro security features, but still have intermittent luck. Any tips?

    ReplyDelete
    Replies
    1. Send an example spreadsheet that you are having issues with and I can take a look.

      Delete
    2. I think the problem may be that my account on this PC doesn't have permission to write to the folder where the output the nslookup command written > to a file named for the sFilename variable. I'm trying to see if the code can be changed to run nslookup from a folder my account has permission to write to, such as c:\Users\[myusername].

      As an example, I tried to write the output of a command > testfile.txt in the windows\system32 directory, and got an 'access denied' error.

      Delete
    3. Yes, so I made a very small change to the code, so it will use a proper temporary folder for the nslookup output, which fixed it for me:

      'Run the nslookup command
      tFolder = oFSO.GetSpecialFolder(2)
      sFilename = tFolder & "\" & oFSO.GetTempName

      Delete
    4. Was the "#VALUE! error" ever resolved? I can not get this to work at all.
      1. I have an IP in F1. That column is formatted as General.
      2. I am attempting to get the host name in A1 which is also formated as General.
      3. I have added the function.
      4. In A1 I put the following function: =nslookup(f1)
      5. I get the #VALUE! and when I hoover over it I get "A value used in the formula is of the wrong data type"

      I have several hundered that I need to resolve IP to Hostname.

      Delete
    5. Well, this is a very delayed reply, but Mark's temp folder code change worked for me!

      Delete
  5. Thanks for this...I'm trying to get it to work and I can call the function but keep getting #NAME? errors. I get the same with your ping function. Any ideas?

    ReplyDelete
  6. Thanks for sharing! Works like a charm, real time safer

    ReplyDelete
  7. Great program !!! Thanks sharing !!!

    ReplyDelete
  8. Great piece of code, found a bug as nslookup does ipv6 first, so does not show the ipv4 addresses on the other lines.
    Good news is I found a workaround....
    nslookup -type=A address.com will resolve and show ipv4 only.
    nslookup -type=AAAA address.com will resolve and show only ipv6

    ReplyDelete
    Replies
    1. how do we get only IPV4 address on cell values?

      Delete
  9. hi guys am optional user of excel but this will be very useful for my real time job. any one plz send that addin or macro to me please
    kkbmani6@gmail.com

    ReplyDelete
  10. This is fantastic! Thanks for taking the time to post it.

    ReplyDelete
  11. I am trying to rewrite the script so that I would get the MX records of the hostname/IP, but I am failing so far. I would be glad for any help!

    ReplyDelete
  12. I can not make it work, can someone send me additional instruction or even to make the code with team viewer.
    Thx

    ReplyDelete
  13. Hi,

    Can someone help in configuring the above code in excel. I'm unable to do that and its not working for me.

    ReplyDelete
  14. Getting Compile Error: Ambiguous name detected: NSlookup.

    ReplyDelete
  15. This code is great! Thanks for sharing.

    ReplyDelete
    Replies
    1. Hello, I need some assistance, can someone assist. If followed the above directions. I got NotFound for all my IPs

      Delete
  16. Function partially works.
    =NSLookup(A1,2) - A1 contains 10.10.10.1
    When nothing is added to adjoining field, I get "N/A". When I add data to the adjoining field, I get "#VALUE!"

    ReplyDelete
  17. This comment has been removed by the author.

    ReplyDelete
  18. Any chance to port this for Excel in Mac, please?

    ReplyDelete
  19. Great code! Anyone know why when replacing nslookup command with NBTSTAT no data is populated in the .txt ?

    ReplyDelete
  20. Great script - just saved me hours! Thanks

    ReplyDelete
  21. Hi, I would find this useful but there's no way I could set it up. Could anyone email me the .xls with it in or the addon please? (kevroden@gmail.com) Most appreciated.

    ReplyDelete
  22. Hi Jay,

    I cant seem to get this function to work in Excel 2010, even with a simple google IP, perhaps i'm doing something horribly wrong or I did something to the script itself (simply copied it), I keep getting #VALUE! returns on an IP when I use =NSLookup(*1) with the * being the column or cell that contains the IP address.

    ReplyDelete
  23. Does this work for Excel 2016? When I put =NSLookup(A1) in a cell, I get a #Name? error as if it doesn't know what it is. I pasted the code into the VBA editor and saved the file as an XLSM but can't get anything to happen.

    ReplyDelete
    Replies
    1. I've tried this in Excel 2016 and it works great. I just followed the instructions above. The only thing is that is not working well in combination with IPv6. The answer on www.goolge.nl for example is: s: 2a00:1450:400e:80b::2003

      Delete