Showing posts with label VBA. Show all posts
Showing posts with label VBA. Show all posts

Friday, 15 June 2012

Model View Controller (MVC) implementation in Excel VBA

With this post I would like to illustrate the concept of Model View Controller (MVC) design pattern implemented in excel VBA with a simple and easy to understand example.

The model view controller design pattern has a benefit which provides separation of concern objectively while designing the solution. With this technique in hand, the data is modelled as an object and the form in which is represented is also modelled as object with relevant functions provided for the operations required, which is orchestrated by a controller class.


 

The attached example is a crude implementation of MVC a quick attempt of mine to achieve the same, though I do accept that this piece of code is far from perfection and has still room to improve upon.

Explanation:

The workbook has simple worksheet which on one side has form to display the data (left) and on (right) a table storing multiple values for the same. The workbook has two functionalities provided to get the relevant data based on the serial number provided and update functionality to update the corresponding the record.


 

Please check the workbook VBA code for MVC implementation details.

Download:

Download Solution
Download solution



Refrences:
Link: http://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller

Unlimited Function Arguments – ParamArray in VBA

Recently I stumbled upon an interesting functionality provided by VBA, termed by ‘ParamArray’ keyword.

This key word is used in to send unknown number of arguments in the form of variant array to the function/sub-procedure in VBA.

This can be illustrated via following code:

Option Explicit

'The following VBA illustrates the use of ParamArray functionality illustrated by a
'functiuon returning the count of arguments passed to the function.

Function param_array_function(ParamArray Args() As Variant) As Integer

    Dim iCount As Integer
    iCount = UBound(Args)
    param_array_function = IIf(iCount < 0, 0, iCount + 1)

End Function


Sub Test_Proc()

Debug.Print "Args :" & param_array_function(1, 2, 3, 4, 5)
Debug.Print "Args :" & param_array_function("amol", "pandey", "excel", "vba")
Debug.Print "Args :" & param_array_function(1, 2, 3)
Debug.Print "Args :" & param_array_function(1, 2)

End Sub


This functionality can be very handy to design function/sub-procedures which are generic enough to take in multiple arguments previously unknown and provides an alternative to send in arguments previously being packed in array/collection for the same purposes.

Refrences:
Link: http://www.cpearson.com/excel/optionalargumentstoprocedures.aspx

Sunday, 20 May 2012

Key Word Web Parser Tool (Selenium Vs WinHttp)

With this post I wanted to highlight two interesting techniques for web text parsing via VBA using Selenium framework and WinHttp.

Task:

Given the set of key words (comma separated list) we want to count the occurrence of the key word in the html body of the web page (giving us the popularity of the key word within the set of web pages).

Solution One:

Selenium” as popularly known in the market, is a very robust web testing framework and used in writing automated testing for Web UI. So recently I stumbled upon a very interesting project which is a wrapper written for using selenium via VBA exposing very strong integration of selenium functionalities with VBA. The project home page is very good in describing upon the features of the same.

 

Solution Two:

Using the native WinHttp solution in VBA, we are downloading the HTML text of the web page via “GET” command and thus counting the key word occurrence in the same.

 

Comparison:

For the task in hand I found that using the WinHttp solution wins over the Selenium based methodology purely by the performance and over head the Selenium incurs for the same.

The Selenium framework has its own very important place to automate the Web UI task in hand when JavaScript is also in play with modern day web pages. Selenium plays a very important role where one can script all the user actions that have to be performed on the web, like filling forms, clicking buttons, checking options and more with the power of VBA.

Note: There is a large difference in count values between the Selenium and WinHttp based tools, for the reason that for former I am using Instr function to get the key word count, where as for the later I a using custom written function for the key word count.

Download Solution
Download solution


References:
Link1: http://code.google.com/p/selenium-vba/

Friday, 4 May 2012

Excel VBA Data Warehouse Generator Tool

Recently I was observing our database development team, and I observed that much of my colleagues were struggling with lots of boiler plate code. In the process of generating Dimension and Fact tables (in snow flaked schema), I thought it would be nice to create an easy to use tool to generate database schema with the following rules in place:

1. Each dimension table would have a primary key, combined with identity auto generation.
2. A dimension table may have referential constraint upon another dimension table
3. A fact table will have multiple referential constraints from multiple dimension tables but not from any other factual table.
4. A fact table will not have a primary key nor an identity column.

This tool is primarily an assisting tool for repetitive process occurred in the data warehouse table structure generation, though for any other design requirements developer intervention is very much required to meet the special conditions.



To use the tool, there is a main page where all the relevant information needs to be set like connection string, script folder path and updated database on which the operation needs to be performed once the list is refreshed.

Control Page:


Dimension Page:


Fact Page:


Then there is a SQL Server Management Studio style dimension and fact table generation worksheets where user can set the desired columns required according to the business needs along with integrated drop down list on the Table Link column where the refrence dimension tables can be selected(The table name for dimension and fact wil be appended by keywords "Dim" and "Fact" respectivly. And also for the dimension tables the key columns as they will be auto generated via VBA and appended terms like "Id").

Download Solution
Download solution

File - Directory (Tree Map) in Excel

Being a software developer and in my quest of achieving an organised methodology for saving my personal files, I many times end up saving same file in multiple locations. Ahh…

So many times we can’t keep track of how our file structure if expanding underlying the cover of multiple nested folders. So, I thought to develop a tool in Excel/VBA which could visually represent me the file directory structure in the form of tree and also could provide me an easy to navigate mechanism for the nodes I wish to explore.

Some thing like this …



This tool request for the root node location to start its parsing and with the condition provided by the user to layout the sub folder (recursively) by a check box you will achieve the above result.

Public Sub FileLister(rootPath As String, exploreSubFolder As Boolean)

    Dim file As Scripting.file, folder As Scripting.folder, subfolder As Scripting.folder

    If fso Is Nothing Then
        Set fso = New FileSystemObject
    End If

    Set folder = fso.GetFolder(rootPath)

    If (folder.SubFolders.Count > 0) And exploreSubFolder Then
    
        For Each subfolder In folder.SubFolders
            
            nestLevel = nestLevel + 1
            ReDim Preserve navigated(nestLevel)
            
            If navigated(nestLevel) = 0 Then
                For Each file In folder.Files
                    'Record files in folder
                    anchorRange.Offset(printRow, nestLevel + 1).Value = file.Name
                    anchorRange.Offset(printRow, 0).Hyperlinks.Add Control.Range("A12").Offset(printRow, 0), file.path, , , "Link"
                    printRow = printRow + 1
                Next file
            End If
            
            anchorRange.Offset(printRow, nestLevel + 1).Value = subfolder.Name
            anchorRange.Offset(printRow, nestLevel + 1).Interior.Color = 10092543  'Light Yellow
            anchorRange.Offset(printRow, 0).Hyperlinks.Add Control.Range("A12").Offset(printRow, 0), subfolder.path, , , "Link"
            printRow = printRow + 1

            navigated(nestLevel) = 1
            FileLister subfolder.path, exploreSubFolder
            nestLevel = nestLevel - 1
            
        Next subfolder
        
    Else
    
        nestLevel = nestLevel + 1
        For Each file In folder.Files
            'Record files in folder
            anchorRange.Offset(printRow, nestLevel + 1).Value = file.Name
            anchorRange.Offset(printRow, 0).Hyperlinks.Add Control.Range("A12").Offset(printRow, 0), file.path, , , "Link"
            printRow = printRow + 1
        Next file
        For Each subfolder In folder.SubFolders
            anchorRange.Offset(printRow, nestLevel + 1).Value = subfolder.Name
            anchorRange.Offset(printRow, nestLevel + 1).Interior.Color = 10092543  'Light Yellow
            anchorRange.Offset(printRow, 0).Hyperlinks.Add Control.Range("A12").Offset(printRow, 0), subfolder.path, , , "Link"
            printRow = printRow + 1
        Next subfolder
        nestLevel = nestLevel - 1
        
        If exploreSubFolder Then
            navigated(nestLevel) = 0
        End If
        
    End If
End Sub


Download:

Download Solution
Download solution


Friday, 20 April 2012

Analytics on Analytics Hmm..?? (Google Analytics to Excel)

Recently I came across a project requirement which interested me quite a lot; the project actually did analytics on top of Google analytics data (though Google Analytics does indeed provide a lot of interesting analytics, via its feature rich platform). Interestingly I don’t understand where the human quest for analytics will end, but it keeps me on my toes to build some exciting tools.

So the challenge presented to me was to download the Google analytics data to excel on demand by the user. This presented me with the following technical challenges:

1. User Authentication for access to Google API
2. Google analytics API mechanism for data download



Thus the major key to the excel model is in the authentication subroutine which retrieves the authentication key for the future request authentication based on user credentials as follows:

Private Function getGAauthenticationToken(ByVal email As String, ByVal password As String)
    Dim authResponse As String
    Dim authTokenStart As Integer
    Dim URL As String
    Dim authtoken As String

    If email = "" Then
        getGAauthenticationToken = ""
        Exit Function
    End If

    If password = "" Then
        getGAauthenticationToken = "Input password"
        Exit Function
    End If
    password = modCommonFunctions.uriEncode(password)

    On Error GoTo errhandler
    Dim objhttp As Object
    Set objhttp = CreateObject("MSXML2.ServerXMLHTTP.6.0")
    URL = "https://www.google.com/accounts/ClientLogin"
    objhttp.Open "POST", URL, False
    objhttp.setRequestHeader "Content-type", "application/x-www-form-urlencoded"
    objhttp.setTimeouts 1000000, 1000000, 1000000, 1000000
    objhttp.send ("accountType=GOOGLE&Email=" & email & "&Passwd=" & password & "&service=analytics&Source=Excel based analytics. (c) Amol Pandey 2012")
    authResponse = objhttp.responseText
    If InStr(1, authResponse, "BadAuthentication") = 0 Then
        authTokenStart = InStr(1, authResponse, "Auth=") + 4
        authtoken = Right(authResponse, Len(authResponse) - authTokenStart)
        getGAauthenticationToken = authtoken
    Else
        getGAauthenticationToken = "Authentication failed"
    End If
    Exit Function
errhandler:
    getGAauthenticationToken = "Authentication failed"
End Function

Rest of the request are appended by the authentication id obtained from the previous module for request authentication for the data download from API, leaving us with the XML formatted data to lay out as desired on to excel worksheet.
Private Sub getDetailedGoogleAnalyticsData(authtoken As String, profileNumber As Long, startDate As Date, endDate As Date, metrics() As String, Optional dimensions As Variant)

    Dim httpUrl As String
    Dim request As MSXML2.ServerXMLHTTP60
    Dim requstTimeOut As Long
    Dim requestReponseText As String
    Dim startDateString As String, endDateString As String
    Dim item As Variant, subItem As Variant, responseXml As MSXML2.DOMDocument
    Dim rowCount As Integer
    'clear Range
    RawData.Range("F5:F6").ClearContents
    RawData.Range("H2").Resize(MAX_ROWS, 4).ClearContents
    rowCount = 0

    startDateString = Year(startDate) & "-" & Right("0" & Month(startDate), 2) & "-" & Right("0" & Day(startDate), 2)
    endDateString = Year(endDate) & "-" & Right("0" & Month(endDate), 2) & "-" & Right("0" & Day(endDate), 2)

    httpUrl = "https://www.google.com/analytics/feeds/data?ids=ga:" & profileNumber & "&start-date=" & startDateString & "&end-date=" & endDateString & "&max-results=10000&metrics="

    For Each item In metrics
        httpUrl = httpUrl & "ga:" & item & ","
    Next item
    httpUrl = Left(httpUrl, Len(httpUrl) - 1)


    'Aggreagted values
    Set request = New MSXML2.ServerXMLHTTP60
    requstTimeOut = 1000000
    request.Open "GET", httpUrl, False
    request.setRequestHeader "Content-type", "application/x-www-form-urlencoded"
    request.setRequestHeader "Authorization", "GoogleLogin Auth=" & authtoken
    request.setRequestHeader "GData-Version", "2"
    request.setTimeouts requstTimeOut, requstTimeOut, requstTimeOut, requstTimeOut
    request.send ("")
    Set responseXml = request.responseXml
    For Each item In responseXml.ChildNodes(1).ChildNodes
        If item.nodeName = "dxp:aggregates" Then
            For Each subItem In item.ChildNodes
                If subItem.Attributes.Length > 0 Then
                    RawData.Range("F5").Offset(rowCount, 0).Value = subItem.Attributes(3).Value
                    rowCount = rowCount + 1
                End If
            Next subItem
        End If
    Next item
    If Not (IsError(dimensions)) Then
        httpUrl = httpUrl + "&dimensions="
        For Each item In dimensions
            httpUrl = httpUrl & "ga:" & item & ","
        Next item
        httpUrl = Left(httpUrl, Len(httpUrl) - 1)
        Set request = New MSXML2.ServerXMLHTTP60
        requstTimeOut = 1000000
        request.Open "GET", httpUrl, False
        request.setRequestHeader "Content-type", "application/x-www-form-urlencoded"
        request.setRequestHeader "Authorization", "GoogleLogin Auth=" & authtoken
        request.setRequestHeader "GData-Version", "2"
        request.setTimeouts requstTimeOut, requstTimeOut, requstTimeOut, requstTimeOut
        request.send ("")
        Set responseXml = request.responseXml
        rowCount = 0
        For Each item In responseXml.ChildNodes(1).ChildNodes
            If item.nodeName = "entry" Then
                RawData.Range("H2").Offset(rowCount, 0).Value = item.ChildNodes(4).Attributes(1).Value    'Country
                RawData.Range("H2").Offset(rowCount, 1).Value = item.ChildNodes(5).Attributes(1).Value    'region
                RawData.Range("H2").Offset(rowCount, 2).Value = item.ChildNodes(6).Attributes(3).Value    'visits
                RawData.Range("H2").Offset(rowCount, 3).Value = item.ChildNodes(7).Attributes(3).Value    'pageviews
                rowCount = rowCount + 1
            End If
        Next item
    End If
End Sub

The attached excel model takes in the user details, then fetches the list of web sites monitored by the user account, and then on second step downloads the country wise detailed data of page visit and views for the selected site via drop down.

Happy analytics…

Download:

Download Solution
Download solution


Refrences:
Link1: http://www.automateanalytics.com/2009/08/excel-functions-for-fetching-data.html
Link2: https://developers.google.com/analytics/
Link3: https://developers.google.com/analytics/devguides/reporting/core/dimsmets

Tuesday, 17 April 2012

Indian Market Data Download (NSE & BSE)

Recently while browsing the Indian stock market web sites (NSE and BSE), a thought came by to build a automated data downloader for the historical equity prices to be analyzed in excel.

Henceforth the following tool was built to do the same. This tool extracts the data from the exchanges (NSE and BSE) website (Historical Data Section) for the equity and the time period requested (Currently the tool downloads the daily data only but easily configurable via code to monthly/yearly).

The data downloaded via tool is placed on separate sheets for both NSE and BSE, upon which any post download analysis can be conducted..

Hope this tool helps you in outperform the markets better. Happy trading..

 


modNse.bas
Option Explicit

Private Const NSE_URL As String = "http://www.nseindia.com/products/dynaContent/common/productsSymbolMapping.jsp?symbol={0}&segmentLink=3&symbolCount=1&series=EQ&dateRange=+&fromDate={1}&toDate={2}&dataType=PRICEVOLUME"

Public Sub GetNseData()

    Dim request As WinHttp.WinHttpRequest
    Dim htmlDocument As MSHTML.htmlDocument
    Dim rowCollection As Variant
    Dim htmlRow As Variant
    Dim rowSubContent As Variant
    Dim rowSubData As Variant
    Dim rowCount As Integer, colCount As Integer
    Dim anchorRange As Range
    Dim prepUrl As String
    Dim timeOut As Long

    On Error GoTo errHandler
    
    timeOut = 10000
    DataDumpNse.Cells.Clear
    Set anchorRange = DataDumpNse.Range("A1")

    Set htmlDocument = New MSHTML.htmlDocument

    Set request = New WinHttp.WinHttpRequest

    prepUrl = Replace(NSE_URL, "{0}", modCommonFunctions.URLEncode(ThisWorkbook.Names("NSE_TICKER").RefersToRange.Value))
    prepUrl = Replace(prepUrl, "{1}", Format(ThisWorkbook.Names("NSE_FROM_DATE").RefersToRange.Value, "dd-mm-yyyy"))
    prepUrl = Replace(prepUrl, "{2}", Format(ThisWorkbook.Names("NSE_TO_DATE").RefersToRange.Value, "dd-mm-yyyy"))
    request.Open "GET", prepUrl
    request.SetTimeouts timeOut, timeOut, timeOut, timeOut
    request.Send
    htmlDocument.body.innerHTML = request.ResponseText

    rowCount = 0
    colCount = 0

    Set rowCollection = htmlDocument.getElementsByTagName("tr")
    For Each htmlRow In rowCollection
        Set rowSubContent = htmlRow.getElementsByTagName("th")
        If rowSubContent.Length <> 0 Then
            For Each rowSubData In rowSubContent
                anchorRange.Offset(rowCount, colCount).Value = rowSubData.innerText
                colCount = colCount + 1
            Next rowSubData
        Else
            Set rowSubContent = htmlRow.getElementsByTagName("td")
            For Each rowSubData In rowSubContent
                anchorRange.Offset(rowCount, colCount).Value = rowSubData.innerText
                colCount = colCount + 1
            Next rowSubData
        End If

        colCount = 0
        rowCount = rowCount + 1
    Next htmlRow
    
    Exit Sub
    
errHandler:
    MsgBox Err.Description, vbExclamation, "Download Error"
    On Error GoTo 0
    Err.Clear
End Sub



modBse.bas
Option Explicit

Private Const BSE_URL As String = "http://www.bseindia.com/stockinfo/stockprc2_excel.aspx?scripcd={0}&FromDate={1}&ToDate={2}&OldDMY=D"

Public Sub GetBseData()

    Dim request As WinHttp.WinHttpRequest
    Dim lineSplit As Variant
    Dim rowCount As Long
    Dim line As Variant
    Dim anchorRange As Range
    Dim url As String
    
    DataDumpBse.Cells.Clear
    Set anchorRange = DataDumpBse.Range("A1")
    
    Set request = New WinHttp.WinHttpRequest
    
    url = Replace(BSE_URL, "{0}", ThisWorkbook.Names("BSE_TICKER").RefersToRange.Value)
    url = Replace(url, "{1}", Format(ThisWorkbook.Names("BSE_FROM_DATE").RefersToRange.Value, "mm/dd/yyyy"))
    url = Replace(url, "{2}", Format(ThisWorkbook.Names("BSE_TO_DATE").RefersToRange.Value, "mm/dd/yyyy"))
    
    request.Open "GET", url
    request.Send
    lineSplit = Split(request.ResponseText, vbCrLf)
    
    rowCount = 0
    For Each line In lineSplit
        anchorRange.Offset(rowCount, 0).Value = line
        rowCount = rowCount + 1
    Next line
    
    DataDumpBse.Range("A:A").TextToColumns DataDumpBse.Range("A1"), xlDelimited, Comma:=True
    
End Sub



Download Solution
Download solution


References:
Link1: http://www.nseindia.com/
Link2: http://www.bseindia.com/

Tuesday, 3 April 2012

JIRA Excel Tool (Data Import via VBA)

JIRA is one the majorly used tools for managing large software development projects in many of the big organizations these days. It’s one the products which is quite multi-faceted, providing functionality for varied users ranging from project managers, business users, developers and more. So for the non familiar ones the better option is to explore the tool themselves.
(Link provided in the reference) 

From couple of past days I was indulge developing the tool to do a seemingly simple operation for many of the business users i.e. bring the JIRA data to excel via VBA. In spite the JIRA providing many of the functionalities required of dashboard and reporting aggregated numbers, still business people ask for data analysis where excel sneak’s in with developers like me (pat on the back).

So I was working with JIRA version 4.4 and exploring the available options provided via JIRA API ranging from SOAP (not recommended any more via JIRA) to REST (recommended). Painfully I discovered that either of the options wasn’t the best, as the requirement consisted of fields which weren’t available by either of the methods to be imported to excel via VBA (like computed or custom).

Then I tried navigating to the search area (via JQL) of the JIRA portal where I fire-bugged the request of XML option gaining the link being fired and using the knowledge gained for authentication via REST. Then I tried combining the knowledge of both in the tool I created recently, using the basic authentication mechanism for the REST API and firing the URL for the XML data containing the JQL query which is used to filter the cases in JIRA. And surprisingly it worked in my favor giving me the ability to build the following tool.


 

modJira.bas
Public Sub extractJiraQuery(userName As String, password As String)

    Dim MyRequest As New WinHttpRequest
    Dim resultXml As MSXML2.DOMDocument, resultNode As IXMLDOMElement
    Dim nodeContainer As IXMLDOMElement
    Dim rowCount As Integer, colCount As Integer
    Dim fixVersionString As String
    Dim dumpRange As Range, tempValue As Variant

    Set dumpRange = Sheet2.Range("A2")
    Sheet2.Range("A2:AZ65536").Clear
    
    Application.ScreenUpdating = False
    
    Application.StatusBar = "JIRA: Preparing header..."
    MyRequest.Open "GET", _
                   "https://JIRA_HOST_NAME/sr/jira.issueviews:searchrequest-xml/temp/SearchRequest.xml?jqlQuery=" & modCommonFunction.URLEncode(ThisWorkbook.Names("jqlQuery").RefersToRange.value) & "&tempMax=1000"

    MyRequest.setRequestHeader "Authorization", "Basic " & modCommonFunction.EncodeBase64(userName & ":" & password)

    MyRequest.setRequestHeader "Content-Type", "application/xml"

    'Send Request.
    Application.StatusBar = "JIRA: Querying request to  JIRA..."
    MyRequest.Send

    Set resultXml = New MSXML2.DOMDocument
    resultXml.LoadXML MyRequest.ResponseText

    Application.StatusBar = "JIRA: Processing Response..."
    For Each nodeContainer In resultXml.ChildNodes(2).ChildNodes(0).ChildNodes
        fixVersionString = ""
        If nodeContainer.BaseName = "issue" Then
            Application.StatusBar = "JIRA: The total issues found: " & nodeContainer.Attributes(2).text
        End If
        If nodeContainer.BaseName = "item" Then
            For Each resultNode In nodeContainer.ChildNodes
                'Debug.Print resultNode.nodeName & " :: " & resultNode.text

                If resultNode.nodeName = "fixVersion" Then
                    fixVersionString = fixVersionString & resultNode.text & " | "
                    GoTo nextNode
                End If

                If resultNode.nodeName = "aggregatetimeoriginalestimate" Then
                    tempValue = GetOriginalEstimate(resultNode)
                    dumpRange.Offset(rowCount, 23).value = tempValue
                    If tempValue <> "" Then
                        dumpRange.Offset(rowCount, 25).value = CLng(tempValue) / (60 * 60)
                    End If
                End If

                If resultNode.nodeName = "customfields" Then
                    dumpRange.Offset(rowCount, 22).value = GetStoryPoint(resultNode)
                    GoTo nextNode
                End If

                If resultNode.nodeName = "timespent" Then
                    tempValue = GetTimeSpent(resultNode)
                    dumpRange.Offset(rowCount, 24).value = tempValue
                    If tempValue <> "" Then
                        dumpRange.Offset(rowCount, 26).value = CLng(tempValue) / (60 * 60)
                    End If
                End If

                dumpRange.Offset(rowCount, GetColumnValueByName(resultNode.nodeName)).value = resultNode.text

nextNode:
            Next resultNode

            dumpRange.Offset(rowCount, 14).value = fixVersionString    ' Fix Version
            rowCount = rowCount + 1
        End If

    Next nodeContainer

    Application.ScreenUpdating = True
    
    MsgBox "The data extractions is now complete.", vbInformation, "Process Status"
End Sub

modCommonFunction.bas
Option Explicit

Public Function EncodeBase64(text As String) As String
    Dim arrData() As Byte
    arrData = StrConv(text, vbFromUnicode)

    Dim objXML As MSXML2.DOMDocument
    Dim objNode As MSXML2.IXMLDOMElement

    Set objXML = New MSXML2.DOMDocument
    Set objNode = objXML.createElement("b64")

    objNode.DataType = "bin.base64"
    objNode.nodeTypedValue = arrData
    EncodeBase64 = objNode.text

    Set objNode = Nothing
    Set objXML = Nothing
End Function

Public Function URLEncode( _
       StringVal As String, _
       Optional SpaceAsPlus As Boolean = False _
     ) As String

    Dim StringLen As Long: StringLen = Len(StringVal)

    If StringLen > 0 Then
        ReDim result(StringLen) As String
        Dim i As Long, CharCode As Integer
        Dim Char As String, Space As String

        If SpaceAsPlus Then Space = "+" Else Space = "%20"

        For i = 1 To StringLen
            Char = Mid$(StringVal, i, 1)
            CharCode = Asc(Char)
            Select Case CharCode
            Case 97 To 122, 65 To 90, 48 To 57, 45, 46, 95, 126
                result(i) = Char
            Case 32
                result(i) = Space
            Case 0 To 15
                result(i) = "%0" & Hex(CharCode)
            Case Else
                result(i) = "%" & Hex(CharCode)
            End Select
        Next i
        URLEncode = Join(result, "")
    End If
End Function

Function GetColumnValueByName(columnName As String) As Integer
    Dim iCount As Integer
    GetColumnValueByName = 100    'Default if not found
    For iCount = 0 To Sheet2.Range("A1").End(xlToRight).Column
        If Sheet2.Range("A1").Offset(0, iCount).value = columnName Then
            GetColumnValueByName = iCount
            Exit Function
        End If
    Next iCount

End Function

Function GetTimeSpent(node As IXMLDOMElement) As String

    GetTimeSpent = node.Attributes(0).text

End Function

Function GetOriginalEstimate(node As IXMLDOMElement) As String

    GetOriginalEstimate = node.Attributes(0).text

End Function

Function GetStoryPoint(node As IXMLDOMElement) As String

    Dim itm As IXMLDOMElement

    For Each itm In node.ChildNodes
        If (itm.ChildNodes(0).text = "Story Points") Then
            GetStoryPoint = itm.ChildNodes(1).text
            Exit Function
        End If
    Next itm

End Function

* The code is in two module with couple of functions specific to the XML parsing. But the main core of the tool is in modJira where the request is being fired to JIRA portal and response being recived in as XML.

Though the tool doesn’t offer the auto-complete feature as JIRA itself, I would suggest forming the JQL’s in JIRA and transferring them on to excel for import would be a good idea.

Download Solution
Download solution


References:
Link1: http://www.atlassian.com/software/jira/overview
Link1: https://developer.atlassian.com/display/JIRADEV/JIRA+REST+API+Example+-+Basic+Authentication
Link3: http://docs.atlassian.com/rpc-jira-plugin/4.4/com/atlassian/jira/rpc/soap/JiraSoapService.html
Link4: http://getfirebug.com/

Thursday, 22 December 2011

Recursion vs. Loops in VBA and SQL

Recursion, when I was first taught about it in our class rooms our professor mentioned, this is one topic which every student ask to repeat once again.

Though after a while in the business I am learning actually it’s not that bad too. But it’s just a concept which has to be used wisely. In the past the context I have used recursion is for file/directory searches and listing. But I was also taught to us in the context of factorial and mathematical concepts which could be achieved via loops.

Thus I am embarking in this post to figure out which is a better one to choose:

With recursion, though our mathematical models can be represented well in comparison to loops programmatically. The concept of recursion has some underlying concerns which also need to be taken into account while designing the programs.

The following concerns are sourced from MSDN (for further details please refer to the detailed MSDN documentation):

1. Limiting condition: This is the most important part of recursion and upon which many times my programs have crashed up. Design the recursion ending condition well for all scenarios of the input, if not you might end up into stack overflow error.

2. Memory Usage/Performance: This is one of the most important considerations to take into account while writing code for recursion. As the function/procedure calls upon itself each time the copy of local variable for each instance of execution is created on stack and the overhead of argument passing has to be taken.

3. Debug: Painful to debug in recursive codes.

So rather stick with Looping?? Well it’s an answer you as developer have to decide which route to take; personally I have used recursion for scenarios of file/directory listing arenas and mostly stick to the simple forms of looping for any other tasks of computations. But your comments are valuable for me in this space .. !!!

Below are the codes to illustrate the use of recursion in VBA and in SQL (too but only limited to 32 levels)

VBA:
Option Explicit

Public Function recursive_fact(n As Integer) As Integer
    If n < 1 Then
        recursive_fact = 1
        Exit Function
    End If
    recursive_fact = n * recursive_fact(n - 1)
End Function

Public Function looping_fact(n As Integer) As Integer
    Dim jCount As Integer
    looping_fact = 1
    For jCount = n To 1 Step -1
        looping_fact = looping_fact * jCount
    Next jCount
End Function

Sub test_functions()
    Dim iCount As Integer
    Dim jCount As Integer
    iCount = 5
    jCount = 5
    iCount = recursive_fact(iCount)
    jCount = looping_fact(jCount)
    Debug.Print "Factorial of iCount: " & iCount
    Debug.Print "Factorial of jCount: " & jCount
End Sub
'--Output--
'Factorial of iCount: 120
'Factorial of jCount: 120
SQL:
--Create a sample table
CREATE TABLE employee(
    id          INTEGER NOT NULL PRIMARY KEY,
    first_name  VARCHAR(10),
    last_name   VARCHAR(10),
    salary      DECIMAL(10,2),
    start_Date  DATETIME,
    region      VARCHAR(10),
    city        VARCHAR(20),
    managerid   INTEGER
 );
--Insert some records into it
INSERT INTO employee VALUES (1, 'Jason' ,  'Martin', 5890,'2005-03-22','North','Vancouver',3);
GO
INSERT INTO employee VALUES (2, 'Alison',  'Mathews',4789,'2003-07-21','South','Utown',4);
GO
INSERT INTO employee VALUES (3, 'James' ,  'Smith',  6678,'2001-12-01','North','Paris',5);
GO
INSERT INTO employee VALUES (4, 'Celia' ,  'Rice',   5567,'2006-03-03','South','London',6);
GO
INSERT INTO employee VALUES (5, 'Robert',  'Black',  4467,'2004-07-02','East','Newton',7);
GO
INSERT INTO employee VALUES (6, 'Linda' ,  'Green' , 6456,'2002-05-19','East','Calgary',8);
GO
INSERT INTO employee VALUES (7, 'David' ,  'Larry',  5345,'2008-03-18','West','New York',9);
GO
INSERT INTO employee VALUES (8, 'James' ,  'Cat',    4234,'2007-07-17','West','Regina',9);
GO
INSERT INTO employee VALUES (9, 'Joan'  ,  'Act',    6123,'2001-04-16','North','Toronto',10);
GO
--Verify the data
SELECT * FROM employee;
GO  
 
--Create the procedure
CREATE PROC usp_FindBoss(
   @EmployeeID int
 )
 AS
 DECLARE @ReportsTo int
 SELECT
   @ReportsTo = managerid
 FROM
     Employee
 WHERE
     Id = @EmployeeID
 IF @ReportsTo IS NOT NULL AND @@NESTLEVEL <= 32
 BEGIN
   SELECT
     @EmployeeID AS Employee,
     @ReportsTo  AS Manager
   EXEC usp_FindBoss
     @ReportsTo
 END
 GO
 
--Execute the procedure
SELECT * FROM employee
EXEC usp_FindBoss 2


Note: For SQL Stored Procedures CAN call Stored Procedures & Functions(Both), but Functions CAN call Functions (Only).

Refrences:
Link1 (MSDN Recursion): http://msdn.microsoft.com/en-us/library/81tad23s%28v=vs.80%29.aspx
Link2: http://stackoverflow.com/questions/660337/recursion-vs-loops

Wednesday, 21 December 2011

Variable Declaration – Sounds Easy in VBA..

Well its easy up to the point you like to keep it easy by single individual variable declaration, but when the smart ways kicks in even simple things don’t remain easy in VBA.

Well some time I myself got confused about some codes of what’s happening and what these symbols interpret. So I wanted to clarify some bits of variable declaration styles in this post of mine.

Combined Declaration:

When multiple variables are declared in one Dim statement, the types have to be individually defined for each of them using the “as” operator.

Data Type Symbol declaration:

This is another way of declaring variables whereby you are escaped from writing a whole big line specifying the data type a variable is declared of.In this you just use the specified symbols and works done!!
The following, lists the symbols used for the same:

! = Single Precision
% = Integer
& = Long Integer
@ = Currency
# = Double Precision
$ = String

Also along with this post I am providing some quick referencing links for the data types and their capacity with byte consumption to efficiently design your code.

1. Quick ref 1: http://office.blogs.webucator.com/2010/11/30/data-types-in-vba/
2. Quick ref 2: http://www.ozgrid.com/VBA/variables.htm

The following VBA code illustrates the declaration styles.

Public Sub dataTypes_Declarations()

    '--Old ways of declaration

    Dim r As Integer
    Dim s As Double

    Debug.Print "--Old ways of Declaration--"
    Debug.Print "r is of type: " & TypeName(r)
    Debug.Print "s is of type: " & TypeName(s)

    '--Combined declaration BEWARE

    Dim i, j, k As Integer

    Debug.Print "--Combined Declaration --"
    Debug.Print "i is of type: " & TypeName(i)
    Debug.Print "j is of type: " & TypeName(j)
    Debug.Print "k is of type: " & TypeName(k)
            
    '--Declaration Shortcuts
    '! = Single Precision
    '% = Integer
    '& = Long Integer
    '@ = Currency
    '# = Double Precision
    '$ = String

    Dim a!, b%, c&, d@, e#, f$

    Debug.Print "--Declaration Shortcuts --"
    Debug.Print "a (!) is of type: " & TypeName(a)
    Debug.Print "b (%) is of type: " & TypeName(b)
    Debug.Print "c (&) is of type: " & TypeName(c)
    Debug.Print "d (@) is of type: " & TypeName(d)
    Debug.Print "e (#) is of type: " & TypeName(e)
    Debug.Print "f ($) is of type: " & TypeName(f)
       
End Sub

Refrences:
Link: http://www.daniweb.com/software-development/pascal-and-delphi/threads/17511

Performance & Memory – Large Collection vs. UDT Array in VBA

This article is focused on the use of “UDT” user defined types in VBA. I came across this while looking upon performance and memory consumption issues in VBA while dealing with large datasets.

As classes in object oriented concept provide a wrapper and functionality for one or more related elements. So UDT in VBA is also a wrapper mechanism where it can encapsulate the properties of an object, subtracting the custom functionality as provided by the classes.

The primary utility of an UDT is that, it’s a very light weight composition of object (similar in lines to struct in C#). Its more performance oriented and can be used for representing data series for stocks (encapsulating ISIN, Price, volume and more).

This UDT mechanism is commonly used in counter part of collection object because of the following 2 reasons:

1. VBA Collection contains nothing but variant data types, which, as you know, have one of the highest costs with regard to system resources.

2. Collection object uses a linked list storage structure that also adds to its overhead.

As illustrated in the code below a similar structure of data when implemented using user defined type (UDT) against classes, the performance was considerably higher with the UDT mechanism.

Main Module (Module.bas) :

Option Explicit
'--Declaration for getting millisecond count since system startup --
Public Declare Function GetTickCount Lib "kernel32.dll" () As Long

'--Define the Max Loop count for the interation to measure performance --
Private Const MAXCOUNT As Integer = 30000

'--User Type Defination--
Public Type StockPrice
    Price As Integer
    volume As Long
End Type

'--Routine creating and adding elements to array/collections
Sub compare_UDT()

    Dim stock_array(MAXCOUNT) As StockPrice
    Dim iCount As Integer
    Dim stock_collection As Collection
    Dim stock As clsStock
    Dim stTime As Long

    Set stock_collection = New Collection

    'User Defined Type
    stTime = GetTickCount
    For iCount = 0 To MAXCOUNT
        With stock_array(iCount)
            .Price = Rnd
            .volume = Rnd
        End With
    Next iCount
    Debug.Print GetTickCount - stTime & " Milliseconds for UDT"

    'Class Objects
    stTime = GetTickCount
    For iCount = 0 To MAXCOUNT
        Set stock = New clsStock
        With stock
            .Price = Rnd
            .volume = Rnd
        End With
        stock_collection.Add stock
    Next iCount
    Debug.Print GetTickCount - stTime & " Milliseconds for Collection"

End Sub
'--Results --
'31 Milliseconds for UDT
'171 Milliseconds for Collection



Class Object (clsStock.bas):

Option Explicit

Private m_iPrice As Integer
Private m_lvolume As Long

Public Property Get volume() As Long

    volume = m_lvolume

End Property

Public Property Let volume(ByVal lvolume As Long)

    m_lvolume = lvolume

End Property

Public Property Get Price() As Integer

    Price = m_iPrice

End Property

Public Property Let Price(ByVal iPrice As Integer)

    m_iPrice = iPrice

End Property 
Refrences: 
Link1: http://msdn.microsoft.com/en-us/library/aa260421%28v=vs.60%29.aspx
Link2: http://msdn.microsoft.com/en-us/library/030kb3e9%28v=vs.90%29.aspx

Filter Unique items list in VBA

Many times I have been presented with this challenge to extract a unique item list from a pre-defined array containing non unique items.
For the purposes I tend to use a collection object in VBA and use its “key” element to uniquely identify my items being added to the collection and extracting it back to another unique array.

This functionality should be implemented as function, its a subroutine only for illustration purposes.
Sub uniqueItems()

    Dim repArray(10) As Integer
    Dim unqColl As Collection
    Dim unqArray() As Integer
    Dim iCount As Integer

    '--Allocate repArray
    repArray(0) = 2
    repArray(1) = 2
    repArray(2) = 2
    repArray(3) = 2
    repArray(4) = 2
    repArray(5) = 2
    repArray(6) = 2
    repArray(7) = 2
    repArray(8) = 2
    repArray(9) = 2
    repArray(10) = 20

    '--Filtering via Collection
    Set unqColl = New Collection

    On Error Resume Next
    For iCount = 0 To UBound(repArray)
        '--The identifying key has to be string
        unqColl.Add repArray(iCount), CStr(repArray(iCount))
        '--In case of refrential object variables can also use VarPtr for idnetifying unique address
    Next iCount
    Err.Clear
    On Error GoTo 0

    '--Resize the unique array based upon the unique items in the collection
    ReDim unqArray(unqColl.Count - 1) As Integer
    
    '--Populate the unique array
    For iCount = 0 To (unqColl.Count - 1)
        unqArray(iCount) = unqColl(iCount + 1)
    Next iCount

    '--unqArray Content
    'unqArray(0) = 2
    'unqArray(1) = 20

    '--Free up the space
    Set unqColl = Nothing
    Erase repArray
    Erase unqArray

End Sub

Tuesday, 20 December 2011

Pointers in VBA.. Huhh !!! (delegates in VBA)

“Pointers“ – aaah the word which is not pleasing to most of the programmers is a very powerful functionality in programmers world. (Rightly said power and pain goes along)

I thought working in VBA arena one would be safe from the world of pointers and I wouldn’t have to deal with it. But embarking on voyage to explore the object oriented nature of VBA and its support to OOP’s (Object oriented programming) I stumbled upon an article and resources in line of using pointers in VBA.

So keywords associated with pointers in VBA are as follows:

Note: All the Address values of pointers are stored in the “Long” data type

1. AddressOf: This functionality in VBA provides the addresses of objects (i.e. module, projects, but Not Classes), functions & procedures address.
2. VarPtr: Returns the address of a variable.
3. VarPtrArray: Returns the address of an array.
4. StrPtr: Returns the address of the UNICODE string buffer.
5. VarPtrStringArray: Returns the address of an array of strings.
6. ObjPtr: Returns the pointer to the interface referenced by an object variable.

Using the concept of pointers I have designed a VBA code to illustrate the implementation of “delegate” (function pointers) in VBA and also illustrated the use of the above mentioned keywords.

Also to mention this concept of pointers is also associated with the Callback functionality of VBA with external DLL’s.

Delegate Sample Code:
Option Explicit

'-----External Library Declaration which helps call the Proc by Address -----
Private Declare Function CallWindowProc _
                          Lib "user32.dll" Alias "CallWindowProcA" ( _
                              ByVal lpPrevWndFunc As Long, _
                              ByVal hwnd As Long, _
                              ByVal msg As Long, _
                              ByVal wParam As Long, _
                              ByVal lParam As Long) As Long


'-----This is the main function calling upon the proc via pointer -----
Public Sub test_delegate()
    Dim sMessage As String
    Dim nSubAddress    'As Long

    'This message will be passed to our Sub as an argument
    sMessage = InputBox("Please input a short message")
    'Get the address to the sub we are going to call
    nSubAddress = ProcPtr(AddressOf ShowMessage)
    'Do the magic! Function Called via Pointer...
    CallWindowProc nSubAddress, VarPtr(sMessage), 0&, 0&, 0&
End Sub

'-----This is the subroutine we want to call by address-----
Private Sub ShowMessage( _
        msg As String, _
        ByVal nUnused1 As Long, _
        ByVal nUnused2 As Long, _
        ByVal nUnused3 As Long)
'This is the Sub we will call by address
'it only use one argument but we need to pull the others
'from the stack, so they are just declared as Long values
    MsgBox msg
End Sub

'-----This function is used to extract the address of value to long -----
Private Function ProcPtr(ByVal nAddress As Long) As Long
'Just return the address we just got
    ProcPtr = nAddress
End Function



Pointer Sample Code:
Option Explicit

Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" _
                               (ByVal dst As Long, _
                                ByVal src As Long, _
                                ByVal nBytes As Long)

Sub pointerDemo()

    Dim iCount As Double
    Dim jCount As Double
    Dim ptr_iCount As Long
    Dim ptr_jCount As Long

    iCount = 100.23
    jCount = 200.45

    ptr_iCount = VarPtr(iCount)
    ptr_jCount = VarPtr(jCount)

    '--Common mistake: This will only overwrite the pointer variables
    '--The underlying values refrneced by the pointers will remina the same.
    'ptr_jCount = ptr_iCount

    '--The below mentioned method is the correct version to change the
    '--value of the underlying variables refrenced by the pointers.(2 version)
    'CopyMemory VarPtr(jCount), VarPtr(iCount), Len(iCount)
    CopyMemory ptr_jCount, ptr_iCount, Len(iCount)

    Debug.Print iCount
    Debug.Print jCount

End Sub


Download:

Download Solution
Download solution


Refrences:
Link1: http://msdn.microsoft.com/en-us/library/y72ewk2b%28v=vs.80%29.aspx
Link2: http://support.microsoft.com/kb/199824 
Link3: http://www.vbforums.com/showpost.php?p=2046053&postcount=5


Function Overloading – VBA

Function overloading, another wonders of the object oriented world where by the same name functions with different signatures provide the respective functionality based on the invoking arguments passed and their types.

Picking upon this and some google’ing I attempted to implement a function overloading mechanism via the help of “Variant” within VBA, as sadly function overloading is not inherently supported by VBA and it screams error of “Ambiguous names detected …”

Thus in order to implement the function overloading, we would have first construct a wrapper function which evaluates the signature of arguments sent and match to the respective function call and based upon which it executes and return the respective function.

Not very optimistic and delightful way of doing things but it’s something good to have in the repository for just one day when everything else fails.

'This enforces all the variables used within this module mush have their declartions explicitly
Option Explicit

'This enforces all the arrays implemented within this module starts from 0 'Zero'
Option Base 0

'This prevents the avilabiltiy of the function within this module to external refrencing projects
'and UDF's
Option Private Module

'Constant declaration
Private Const ConstIntVal As Integer = 10
Private Const ConstStrVal As String = "Hello"

'----- Overloading Implementation ------
Public Function addValue(Optional args As Variant) As Variant
    'Function signature identification and call relevant function component
    If IsMissing(args) Then
        
        addValue = addValue_Null
        Exit Function
        
    End If
    
    If Not IsArray(args) Then
        If TypeName(args) = "Integer" Then
        
            addValue = addValue_Int_Const(CInt(args))
            Exit Function
            
        ElseIf TypeName(args) = "String" Then
        
            addValue = addValue_Str_Const(CStr(args))
            Exit Function
            
        End If
    Else
        If TypeName(args(0)) = "Integer" Then
        
            addValue = addValue_Int(CInt(args(0)), CInt(args(1)))
            Exit Function
            
        ElseIf TypeName(args(0)) = "String" Then
        
            addValue = addValue_Str(CStr(args(0)), CStr(args(1)))
            Exit Function
            
        End If
    End If
End Function

'------ OverLoad Components ------

'Return 0 'Zero' for no arguments
Private Function addValue_Null() As Integer
    addValue_Null = 0
End Function

'Returns the constant added value to the argument (Integer)
Private Function addValue_Int_Const(val As Integer) As Integer
    addValue_Int_Const = val + ConstIntVal
End Function

'Returns the constant added value to the argument (String)
Private Function addValue_Str_Const(val As String) As String
    addValue_Str_Const = ConstStrVal & val
End Function

'Returns addtion of two integers
Private Function addValue_Int(val1 As Integer, val2 As Integer) As Integer
    addValue_Int = val1 + val2
End Function

'Returns concatenation of two strings
Private Function addValue_Str(val1 As String, val2 As String) As String
    addValue_Str = val1 + val2
End Function



Attached file illustrates the function overload mechanism.
Download:

Download Solution
Download solution


Refrences:
Link: http://stackoverflow.com/questions/64436/function-overloading-in-excel-vba

“Implements” Keyword, Interface – Class in VBA

Recently I was puzzled with a question about the levels of Object oriented structure can VBA support?
Suddenly my thoughts shifted to the key word I was always suspicious about but didn’t found time to explore. This post is all about key word “Implements” in VBA.

Learning about “Implements” in the context of VBA I am quite amazed about its potential. This keyword is used in conjunction to provide the interface-class implementation structure to VBA.
The code in the attached file is separated into 3 class objects (out of which 2 are implementation of the 1 interface) and 1 module object to illustrate the usage.

Code Explanation:
The attached file along with this post creates the following VBA structure:
1. IHuman (Interface)
2. clsMan (Class implementing IHuman)
3. clsWomen (Class implementing IHuman)
4. modTest (Module illustrating the usage of the class/interface)

The code also illustrates the additional method defined in the implementing classes and their usage patterns. Please explore the attached file VBA for the entire code.

Download:

Download Solution
Download solution


Refrences:
Link: http://www.vbi.org/Items/article.asp?id=78

Late & Early Binding VBA

Recently I came across this term of bindings (Late/Early). Being a VBA developer for past few years and having worked with the concept numerous times, I realized lately it as Late/Early Binding. (I am bad with names and terms, I must confess)
So the concept goes as follows according to MSDN:

Early binding (MSDN):
An object is early bound when it is assigned to a variable declared to be of a specific object type

Example:
Sub test_LateEarlyBindings()

     'Early Binding
     Dim fs As Scripting.FileSystemObject

     Set fs = New Scripting.FileSystemObject

End Sub



Late Binding (MSDN):
An object is late bound when it is assigned to a variable declared to be of type Object.

Example:
Sub test_LateEarlyBindings()

    'Late Binding
    Dim fs As Object
    
    Set fs = CreateObject("Scripting.FileSystemObject")


End Sub

The advantage of early binding over late binding is they allow compiler to allocate memory and perform optimization before an application executes. In addition to this when objects are declared explicitly as their types the VBA editor provide a helpful intellisense to assist the developer with object associated methods and properties, which becomes quite difficult in terms of late bound objects.

 

Then why use late binding ???

I came to know the utility of the late binding when I had to develop VBA based solutions which addressed users with varying office application versions (2003/2007).
Sub test_LateEarlyBindings()

    'Early Binding
    Dim outlookApp As Outlook.Application
    
    Set outlookApp = New Outlook.Application


End Sub

In the above code the instantiation of the Outlook object within VBA if flexible to work with different version of outlook installed on user PC (2003/2007) as this is instantiated as late bound object to the variable. This code relives the developer to explicitly add the outlook reference to the solution as it is picked up at run time and provides higher flexibility to the solution. This case was also sometimes used by myself when referencing the PDFCreator library for generating PDF reports.

Coding Tip (Late bound object):

As we discussed earlier since the late bound object doesn’t offer intellisense help while coding, I becomes tedious to develop the functionality and call upon the right name of methods and properties associated with the object.
A simple tip to overcome this problem is, initially develop the code as an early bound object and once the required functionality works well replace the object instantiation part by “CreateObject” method and uncheck the external references relating to the object from the reference library of the VBA project.

Refrences: 
Link: http://msdn.microsoft.com/en-us/library/0tcf61s1.aspx

Monday, 17 October 2011

Excel – iTunes: Let’s account for our music

Recently I was bit lost managing my iTunes songs and its playlist. So I thought excel would lend me a hand to get hold of my music analytics. So here I have created an excel VBA based solution to get out my list of all the songs present in my iPod.

Additionally I have also created a utility to create playlist via VBA for my iPod. Hope this tool helps many others to enjoy their music excelly.  

Songs list from iPod to Excel Sheet
 

Creating Playlist in iPod from Excel
 

Result in iTunes
 


Download:

Download Solution
Download solution



References:
Link1: http://developer.apple.com/sdk/itunescomsdk.html

Thursday, 6 October 2011

Dynamic VBA ... Why.... ???

Recently i came up with a thought in my free mind, if we can use dynamic SQL for many kinds of SQL servers, there must be a way to execute the dynamic VBA. But then lately i am very confused as how can and it would be useful in any scenario. As we can have multiple alternatives than to dynamically plug the VBA code in and execute it.

But any ways here the solution.. if some one please find a sensible usage of this method please leave a comment for me to know its utility. 




Download:
Download Solution
Download solution



References:
Link: http://www.cpearson.com/excel/vbe.aspx


Tuesday, 4 October 2011

VBA tooo WCF tooo C#

Recently I came across an issue where a VBA application model had to trigger a job in remotely running C# application. Suddenly polling via DB and creating a queue based mechanism was on cards, but this process involves so many elements and is resource intensive. So I thought there should be a better mechanism for the same.

And WCF was to answer my problem. I have seen some solutions online but was based on the WCF as a service but in my context I had to have a win form/console application and VBA had to trigger a job in those applications based remotely.

So I ported the service based solution to my needs and below the code illustrated and sample files for the C# and VBA solution.

(Note: Sometimes if the VBA call fails please instead of localhost use the ip-address of the PC on which the C# application is running.)

Sub testWcf()

Dim addr As String
Dim i As Long
addr = "service:mexAddress=""net.tcp://localhost:9001/hello/mex"","
addr = addr + "address=""net.tcp://localhost:9001/hello"","
addr = addr + "contract=""IHelloWorldService"", contractNamespace=""http://tempuri.org/"","
addr = addr + "binding=""NetTcpBinding_IHelloWorldService"", bindingNamespace=""http://tempuri.org/"""


Dim service1 As Object
Set service1 = GetObject(addr)

For i = 0 To 10

Debug.Print service1.SayHello("Test Message: " & i)

Next i


End Sub

And the associated C# model is as follows:

using System;
using System.Collections.Generic;
using System.Linq;
using System.ServiceModel.Channels;
using System.Text;
using System.ServiceModel;
using System.ServiceModel.Description;

namespace ConsoleApplication1
{

    [ServiceContract]
    public interface IHelloWorldService
    {
        [OperationContract]
        string SayHello(string name);
    }

    public class HelloWorldService : IHelloWorldService
    {
        public string SayHello(string name)
        {
            Console.WriteLine("The param passed is :" + name);
            return string.Format("Hello {0}", name);
        }
    }

    class Program
    {


        static void Main(string[] args)
        {
            BindingElement bindingElement =
                new TcpTransportBindingElement();
            CustomBinding binding =
               new CustomBinding(bindingElement);
            Uri tcpBaseAddress =
               new Uri("net.tcp://localhost:9001/hello");
            ServiceHost host =
               new ServiceHost(typeof(HelloWorldService), tcpBaseAddress);
            ServiceMetadataBehavior metadataBehavior;
            metadataBehavior =
               host.Description.Behaviors.
               Find();
            if (metadataBehavior == null)
            {
                metadataBehavior = new ServiceMetadataBehavior();
                host.Description.Behaviors.Add(metadataBehavior);
            }
            host.AddServiceEndpoint(typeof (IHelloWorldService), new NetTcpBinding(), tcpBaseAddress);
            host.AddServiceEndpoint(
               typeof(IMetadataExchange), binding, "MEX");
            host.Open();
            Console.WriteLine("Server started @." + tcpBaseAddress);
            Console.ReadLine();
        }
    }
}

Download Solution
Download solution 


Refrences:
Link: http://damianblog.com/2009/07/05/excel-wcf/

Wednesday, 29 June 2011

Meeting Roomss... Lets book them - Outlook Meeting Room Finder

Hi today i would like to introduce to a very handy tool which me and my office personnel's are quite linking.
Recently i joined my new office and its quite beautiful, but i soon found big beautiful things have some problems which VBA can solve in many times. 

The issue is we have 20-30 meeting rooms in the office and they all can be booked via sending the appointment item to a certain patterned email address each unique for individual meeting room's.

To cut short the story this tool analyses all the meeting room's shared calender selected on the basis of the patterned email address assigned to each one of them. And it collate a list scanning those shared calenders illustrating the time periods between which the required time slot (duration input by user in mins) can be booked and in which meeting room the appointment can be booked.

This entire code is written in VBA within outlook. Give this handy tool a check and alter it to your requirements and make it work for you so that you are never late in you next appointment.

Also the code includes a feature for minimizing the user form in VBA.




Download:
Download Solution
Download solution


References:
Outlook Calender Scan: http://www.vbaexpress.com/kb/getarticle.php?kb_id=671
UserForm Minimize: http://www.vbaexpress.com/kb/getarticle.php?kb_id=165